Issue 154948
Summary [MLIR] Race condition on DeadCodeAnalysis
Labels mlir
Assignees
Reporter amd-eochoalo
    The title specifically mentions DeadCodeAnalysis, but I believe this may affect all DataFlowAnalysis when analyses are issued at the FuncOp level as opposed to the ModuleOp level.

The concrete issue raised by TSan started with [this patch](https://github.com/llvm/llvm-project/pull/150775). TSan found a race condition when `UnsignedWhenEquivalent` and `LowerAffine` are scheduled at the FuncOp level. 

I am attaching the read and write traces from TSan.

```
WARNING: ThreadSanitizer: data race (pid=1005165)
  Read of size 8 at 0x722800004028 by thread T4:  
  #0 mlir::iree_compiler::IREE::Util::FuncOp::getInherentAttr(mlir::MLIRContext*, mlir::iree_compiler::IREE::Util::detail::FuncOpGenericAdaptorBase::Properties const&, llvm::StringRef) /home/eochoalo/code/iree-build/compiler/src/iree/compiler/Dialect/Util/IR/UtilOps.cpp.inc (libIREECompiler.so+0xfc20346) (BuildId: 761b80a368cfa643)
    #1 mlir::RegisteredOperationName::Model<mlir::iree_compiler::IREE::Util::FuncOp>::getInherentAttr(mlir::Operation*, llvm::StringRef) /home/eochoalo/code/iree/third_party/llvm-project/mlir/include/mlir/IR/OperationSupport.h:570:16 (libIREECompiler.so+0xfb8f4cd) (BuildId: 761b80a368cfa643)
    #2 mlir::OperationName::getInherentAttr(mlir::Operation*, llvm::StringRef) const /home/eochoalo/code/iree/third_party/llvm-project/mlir/include/mlir/IR/OperationSupport.h:393:23 (libIREECompiler.so+0x7dd33c4) (BuildId: 761b80a368cfa643) 
    #3 mlir::Operation::getInherentAttr(llvm::StringRef) /home/eochoalo/code/iree/third_party/llvm-project/mlir/lib/IR/Operation.cpp:341:20 (libIREECompiler.so+0x7dd33c4)
    #4 mlir::Operation::getAttr(mlir::StringAttr) /home/eochoalo/code/iree/third_party/llvm-project/mlir/include/mlir/IR/Operation.h:536:51 (libIREECompiler.so+0x7df9408) (BuildId: 761b80a368cfa643)
    #5 mlir::StringAttr mlir::Operation::getAttrOfType<mlir::StringAttr>(mlir::StringAttr) /home/eochoalo/code/iree/third_party/llvm-project/mlir/include/mlir/IR/Operation.h:551:46 (libIREECompiler.so+0x7df9408)
    #6 getNameIfSymbol(mlir::Operation*, mlir::StringAttr) /home/eochoalo/code/iree/third_party/llvm-project/mlir/lib/IR/SymbolTable.cpp:31:14 (libIREECompiler.so+0x7df9408) 
    #7 mlir::SymbolTable::SymbolTable(mlir::Operation*) /home/eochoalo/code/iree/third_party/llvm-project/mlir/lib/IR/SymbolTable.cpp:129:23 (libIREECompiler.so+0x7df9408)
    #8 std::__detail::_MakeUniq<mlir::SymbolTable>::__single_object std::make_unique<mlir::SymbolTable, mlir::Operation*&>(mlir::Operation*&) /usr/bin/../lib/gcc/x86_64-linux-gnu/13/../../../../include/c++/13/bits/unique_ptr.h:1070:34 (libIREECompiler.so+0x7e0124d) (BuildId: 761b80a368cfa643)
    #9 mlir::SymbolTableCollection::getSymbolTable(mlir::Operation*) /home/eochoalo/code/iree/third_party/llvm-project/mlir/lib/IR/SymbolTable.cpp:996:24 (libIREECompiler.so+0x7e0124d) 
    #10 mlir::SymbolTableCollection::lookupSymbolIn(mlir::Operation*, mlir::StringAttr) /home/eochoalo/code/iree/third_party/llvm-project/mlir/lib/IR/SymbolTable.cpp:954:10 (libIREECompiler.so+0x7e00ee6) (BuildId: 761b80a368cfa643)
    #11 mlir::SymbolTableCollection::lookupSymbolIn(mlir::Operation*, mlir::SymbolRefAttr, llvm::SmallVectorImpl<mlir::Operation*>&)::$_0::operator()(mlir::Operation*, mlir::StringAttr) const /home/eochoalo/code/iree/third_party/llvm-project/mlir/lib/IR/SymbolTable.cpp:971:12 (libIREECompiler.so+0x7e087ad) (BuildId: 761b80a368cfa643)
    #12 mlir::Operation* llvm::function_ref<mlir::Operation* (mlir::Operation*, mlir::StringAttr)>::callback_fn<mlir::SymbolTableCollection::lookupSymbolIn(mlir::Operation*, mlir::SymbolRefAttr, llvm::SmallVectorImpl<mlir::Operation*>&)::$_0>(long, mlir::Operation*, mlir::StringAttr) /home/eochoalo/code/iree/third_party/llvm-project/llvm/include/llvm/ADT/STLFunctionalExtras.h:46:12 (libIREECompiler.so+0x7e087ad)
    #13 llvm::function_ref<mlir::Operation* (mlir::Operation*, mlir::StringAttr)>::operator()(mlir::Operation*, mlir::StringAttr) const /home/eochoalo/code/iree/third_party/llvm-project/llvm/include/llvm/ADT/STLFunctionalExtras.h:69:12 (libIREECompiler.so+0x7dfca9a) (BuildId: 761b80a368cfa643)
    #14 lookupSymbolInImpl(mlir::Operation*, mlir::SymbolRefAttr, llvm::SmallVectorImpl<mlir::Operation*>&, llvm::function_ref<mlir::Operation* (mlir::Operation*, mlir::StringAttr)>) /home/eochoalo/code/iree/third_party/llvm-project/mlir/lib/IR/SymbolTable.cpp:416:19 (libIREECompiler.so+0x7dfca9a) 
   #15 mlir::SymbolTableCollection::lookupSymbolIn(mlir::Operation*, mlir::SymbolRefAttr, llvm::SmallVectorImpl<mlir::Operation*>&) /home/eochoalo/code/iree/third_party/llvm-project/mlir/lib/IR/SymbolTable.cpp:973:10 (libIREECompiler.so+0x7e010ea) (BuildId: 761b80a368cfa643) 
   #16 mlir::SymbolTableCollection::lookupSymbolIn(mlir::Operation*, mlir::SymbolRefAttr) /home/eochoalo/code/iree/third_party/llvm-project/mlir/lib/IR/SymbolTable.cpp:959:14 (libIREECompiler.so+0x7e0100e) (BuildId: 761b80a368cfa643)
   #17 mlir::SymbolTableCollection::lookupNearestSymbolFrom(mlir::Operation*, mlir::SymbolRefAttr) /home/eochoalo/code/iree/third_party/llvm-project/mlir/lib/IR/SymbolTable.cpp:989:26 (libIREECompiler.so+0x7e011b2) (BuildId: 761b80a368cfa643)
    #18 mlir::call_interface_impl::resolveCallable(mlir::CallOpInterface, mlir::SymbolTableCollection*) /home/eochoalo/code/iree/third_party/llvm-project/mlir/lib/Interfaces/CallInterfaces.cpp:196:25 (libIREECompiler.so+0x10530569) (BuildId: 761b80a368cfa643)
    #19 mlir::detail::CallOpInterfaceTrait<mlir::iree_compiler::IREE::Util::CallOp>::resolveCallableInTable(mlir::SymbolTableCollection*) /home/eochoalo/code/iree-build/llvm-project/tools/mlir/include/mlir/Interfaces/CallInterfaces.h.inc:156:14 (libIREECompiler.so+0xfb885e2) (BuildId: 761b80a368cfa643) #20 mlir::detail::CallOpInterfaceInterfaceTraits::Model<mlir::iree_compiler::IREE::Util::CallOp>::resolveCallableInTable(mlir::detail::CallOpInterfaceInterfaceTraits::Concept const*, mlir::Operation*, mlir::SymbolTableCollection*) /home/eochoalo/code/iree-build/llvm-project/tools/mlir/include/mlir/Interfaces/CallInterfaces.h.inc:303:56 (libIREECompiler.so+0xfb885e2)
    #21 mlir::CallOpInterface::resolveCallableInTable(mlir::SymbolTableCollection*) /home/eochoalo/code/iree-build/llvm-project/tools/mlir/include/mlir/Interfaces/CallInterfaces.cpp.inc:44:14 (libIREECompiler.so+0x10530797) (BuildId: 761b80a368cfa643)
    #22 mlir::dataflow::DeadCodeAnalysis::visitCallOperation(mlir::CallOpInterface) /home/eochoalo/code/iree/third_party/llvm-project/mlir/lib/Analysis/DataFlow/DeadCodeAnalysis.cpp:362:32 (libIREECompiler.so+0x104ec31f) (BuildId: 761b80a368cfa643)
    #23 mlir::dataflow::DeadCodeAnalysis::visit(mlir::ProgramPoint*) /home/eochoalo/code/iree/third_party/llvm-project/mlir/lib/Analysis/DataFlow/DeadCodeAnalysis.cpp:301:5 (libIREECompiler.so+0x104eb40a) (BuildId: 761b80a368cfa643)            #24 mlir::DataFlowSolver::initializeAndRun(mlir::Operation*) /home/eochoalo/code/iree/third_party/llvm-project/mlir/lib/Analysis/DataFlowFramework.cpp:134:26 (libIREECompiler.so+0x104c4eb9) (BuildId: 761b80a368cfa643)
    #25 (anonymous namespace)::ArithUnsignedWhenEquivalentPass::runOnOperation() /home/eochoalo/code/iree/third_party/llvm-project/mlir/lib/Dialect/Arith/Transforms/UnsignedWhenEquivalent.cpp:130:23 (libIREECompiler.so+0xe4e7503) (BuildId: 761b80a368cfa643)
```

```
 Previous write of size 8 at 0x722800004028 by thread T2:
    #0 __tsan_memcpy <null> (iree-compile+0x99d7f) (BuildId: 302c91be97368fb1)
 #1 mlir::RegisteredOperationName::Model<mlir::iree_compiler::IREE::Util::FuncOp>::copyProperties(mlir::OpaqueProperties, mlir::OpaqueProperties) /home/eochoalo/code/iree/third_party/llvm-project/mlir/include/mlir/IR/OperationSupport.h:661:31 (libIREECompiler.so+0xfb8f7f5) (BuildId: 761b80a368cfa643)
    #2 mlir::OperationName::copyOpProperties(mlir::OpaqueProperties, mlir::OpaqueProperties) const /home/eochoalo/code/iree/third_party/llvm-project/mlir/include/mlir/IR/OperationSupport.h:445:23 (libIREECompiler.so+0x7dd3829) (BuildId: 761b80a368cfa643)
    #3 mlir::Operation::copyProperties(mlir::OpaqueProperties) /home/eochoalo/code/iree/third_party/llvm-project/mlir/lib/IR/Operation.cpp:366:8 (libIREECompiler.so+0x7dd3829)
    #4 (anonymous namespace)::ModifyOperationRewrite::rollback() /home/eochoalo/code/iree/third_party/llvm-project/mlir/lib/Transforms/Utils/DialectConversion.cpp:712:11 (libIREECompiler.so+0xfd8eb00) (BuildId: 761b80a368cfa643)
    #5 mlir::ConversionPatternRewriter::cancelOpModification(mlir::Operation*) /home/eochoalo/code/iree/third_party/llvm-project/mlir/lib/Transforms/Utils/DialectConversion.cpp:1954:10 (libIREECompiler.so+0xfd707ce)

...

    #14 applyConversion(llvm::ArrayRef<mlir::Operation*>, mlir::ConversionTarget const&, mlir::FrozenRewritePatternSet const&, mlir::ConversionConfig, (anonymous namespace)::OpConversionMode) /home/eochoalo/code/iree/third_party/llvm-project/mlir/lib/Transforms/Utils/DialectConversion.cpp:3573:8 (libIREECompiler.so+0xfd7a13a)
    #15 mlir::applyPartialConversion(llvm::ArrayRef<mlir::Operation*>, mlir::ConversionTarget const&, mlir::FrozenRewritePatternSet const&, mlir::ConversionConfig) /home/eochoalo/code/iree/third_party/llvm-project/mlir/lib/Transforms/Utils/DialectConversion.cpp:3589:10 (libIREECompiler.so+0xfd7a210) (BuildId: 761b80a368cfa643)
    #16 mlir::applyPartialConversion(mlir::Operation*, mlir::ConversionTarget const&, mlir::FrozenRewritePatternSet const&, mlir::ConversionConfig) /home/eochoalo/code/iree/third_party/llvm-project/mlir/lib/Transforms/Utils/DialectConversion.cpp:3596:10 (libIREECompiler.so+0xfd7a210)
    #17 (anonymous namespace)::LowerAffine::runOnOperation() /home/eochoalo/code/iree/third_party/llvm-project/mlir/lib/Conversion/AffineToStandard/AffineToStandard.cpp:564:16 
```

I tried applying the following patch to avoid resolving the call, but the error moves to AbstractSparseForwardDataFlowAnalysis.


```diff
diff --git a/mlir/lib/Analysis/DataFlow/DeadCodeAnalysis.cpp b/mlir/lib/Analysis/DataFlow/DeadCodeAnalysis.cpp
index 10874fd0feb5..a04dd30482b7 100644
--- a/mlir/lib/Analysis/DataFlow/DeadCodeAnalysis.cpp
+++ b/mlir/lib/Analysis/DataFlow/DeadCodeAnalysis.cpp
@@ -20,6 +20,7 @@
 #include "mlir/IR/ValueRange.h"
 #include "mlir/Interfaces/CallInterfaces.h"
 #include "mlir/Interfaces/ControlFlowInterfaces.h"
+#include "mlir/Interfaces/FunctionInterfaces.h"
 #include "mlir/Support/LLVM.h"
 #include "llvm/Support/Casting.h"
 #include "llvm/Support/Debug.h"
@@ -359,15 +360,28 @@ LogicalResult DeadCodeAnalysis::visit(ProgramPoint *point) {

 void DeadCodeAnalysis::visitCallOperation(CallOpInterface call) {
 LDBG() << "visitCallOperation: " << call.getOperation()->getName();
- Operation *callableOp = call.resolveCallableInTable(&symbolTable);
+ Operation *parent = call->getParentOfType<FunctionOpInterface>();
+  if (analysisScope == parent) {
+    return;
+  }

   // A call to a externally-defined callable has unknown predecessors.
-  const auto isExternalCallable = [this](Operation *op) {
+  const auto isExternalCallable = [this](CallOpInterface call) {
+    Operation *parent = call->getParentOfType<FunctionOpInterface>();
+    if (analysisScope == parent) {
+      return true;
+    }
+
+    Operation *callableOp = call.resolveCallableInTable(&symbolTable);
+
+    if (isa_and_nonnull<SymbolOpInterface>(callableOp)) {
+      return true;
+ }
     // A callable outside the analysis scope is an external callable.
- if (!analysisScope->isAncestor(op))
+    if (!analysisScope->isAncestor(callableOp))
       return true;
     // Otherwise, check if the callable region is defined.
-    if (auto callable = dyn_cast<CallableOpInterface>(op))
+    if (auto callable = dyn_cast<CallableOpInterface>(callableOp))
       return !callable.getCallableRegion();
     return false;
   };
@@ -375,8 +389,8 @@ void DeadCodeAnalysis::visitCallOperation(CallOpInterface call) {
   // TODO: Add support for non-symbol callables when necessary. If the
   // callable has non-call uses we would mark as having reached pessimistic
   // fixpoint, otherwise allow for propagating the return values out.
-  if (isa_and_nonnull<SymbolOpInterface>(callableOp) &&
- !isExternalCallable(callableOp)) {
+  if (!isExternalCallable(call)) {
+ Operation *callableOp = call.resolveCallableInTable(&symbolTable);
     // Add the live callsite.
     auto *callsites =
 getOrCreate<PredecessorState>(getProgramPointAfter(callableOp));
```
_______________________________________________
llvm-bugs mailing list
llvm-bugs@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-bugs

Reply via email to