[Mlir-commits] [mlir] d6048f5 - [mlir][bufferization] Skip parallel analysis without parallel regions (#227202)

llvmlistbot at llvm.org llvmlistbot at llvm.org
Wed Sep 30 02:12:41 PDT 2026


Author: Ziliang Zhang
Date: 2026-09-30T09:12:34Z
New Revision: d6048f5ff3bdd934508a585a92ba010834981b7c

URL: https://github.com/llvm/llvm-project/commit/d6048f5ff3bdd934508a585a92ba010834981b7c
DIFF: https://github.com/llvm/llvm-project/commit/d6048f5ff3bdd934508a585a92ba010834981b7c.diff

LOG: [mlir][bufferization] Skip parallel analysis without parallel regions (#227202)

One-Shot Bufferize currently runs parallel-region conflict analysis even
when the analyzed IR has no parallel regions. This can repeatedly walk
long reverse use-def chains without being able to find a parallel-region
conflict.

Added: 
    

Modified: 
    mlir/include/mlir/Dialect/Bufferization/IR/BufferizableOpInterface.h
    mlir/include/mlir/Dialect/Bufferization/Transforms/OneShotAnalysis.h
    mlir/include/mlir/Dialect/Bufferization/Transforms/Passes.td
    mlir/lib/Dialect/Bufferization/Transforms/Bufferize.cpp
    mlir/lib/Dialect/Bufferization/Transforms/OneShotAnalysis.cpp
    mlir/test/Dialect/SCF/one-shot-bufferize-analysis.mlir

Removed: 
    


################################################################################
diff  --git a/mlir/include/mlir/Dialect/Bufferization/IR/BufferizableOpInterface.h b/mlir/include/mlir/Dialect/Bufferization/IR/BufferizableOpInterface.h
index 203680796a289..bec14fffec96c 100644
--- a/mlir/include/mlir/Dialect/Bufferization/IR/BufferizableOpInterface.h
+++ b/mlir/include/mlir/Dialect/Bufferization/IR/BufferizableOpInterface.h
@@ -312,10 +312,11 @@ struct BufferizationOptions {
   /// bufferized or not.
   bool bufferizeFunctionBoundaries = false;
 
-  // Specifies whether to account for parallel regions in RaW analysis. If true,
-  // then writes inside of parallel regions that write to buffers defined
-  // outside of the parallel region will be given a new buffer.
-  bool checkParallelRegions = true;
+  /// Whether the IR may contain a parallel region. When unset, the analysis
+  /// walks the IR to compute it.
+  /// Note: If the IR contains a parallel region, but this flag is set to
+  /// "false", the bufferization may produce incorrect IR.
+  std::optional<bool> mayHaveParallelRegions = std::nullopt;
 
   /// This function controls buffer types on function signatures. Sets
   /// `functionArgTypeConverterFn` and `inferFunctionResultLayout` accordingly.

diff  --git a/mlir/include/mlir/Dialect/Bufferization/Transforms/OneShotAnalysis.h b/mlir/include/mlir/Dialect/Bufferization/Transforms/OneShotAnalysis.h
index af5d2bd9a2db4..8b647790d6703 100644
--- a/mlir/include/mlir/Dialect/Bufferization/Transforms/OneShotAnalysis.h
+++ b/mlir/include/mlir/Dialect/Bufferization/Transforms/OneShotAnalysis.h
@@ -91,6 +91,10 @@ class OneShotAnalysisState : public AnalysisState {
   /// the options when set; otherwise computed by walking the IR.
   bool mayHaveUnstructuredControlFlow() const { return mayHaveUnstructuredCF; }
 
+  /// True if the analyzed IR may contain a parallel region. Taken from the
+  /// options when set; otherwise computed by walking the IR.
+  bool mayHaveParallelRegions() const { return mayHaveParallelRegionsFlag; }
+
   /// Analyze the given op and its nested ops.
   LogicalResult analyzeOp(Operation *op, const DominanceInfo &domInfo);
 
@@ -267,6 +271,9 @@ class OneShotAnalysisState : public AnalysisState {
   /// True if any region has more than one block.
   bool mayHaveUnstructuredCF = false;
 
+  /// True if the analyzed IR may contain a parallel region.
+  bool mayHaveParallelRegionsFlag = false;
+
   /// Cached CFG reachability. Defined out-of-line to keep BitVector out of
   /// this header.
   class CFGReachabilityCache;

diff  --git a/mlir/include/mlir/Dialect/Bufferization/Transforms/Passes.td b/mlir/include/mlir/Dialect/Bufferization/Transforms/Passes.td
index b2608fc5b574c..0638b339cf9dc 100644
--- a/mlir/include/mlir/Dialect/Bufferization/Transforms/Passes.td
+++ b/mlir/include/mlir/Dialect/Bufferization/Transforms/Passes.td
@@ -516,9 +516,9 @@ def OneShotBufferizePass : Pass<"one-shot-bufferize", "ModuleOp"> {
        Option<"bufferizeFunctionBoundaries", "bufferize-function-boundaries",
               "bool", /*default=*/"0",
               "Bufferize function boundaries (experimental).">,
-       Option<"checkParallelRegions", "check-parallel-regions", "bool",
+       Option<"mayHaveParallelRegions", "may-have-parallel-regions", "bool",
               /*default=*/"true",
-              "Account for parallel regions in RaW analysis.">,
+              "Whether the IR may contain parallel regions.">,
        Option<"copyBeforeWrite", "copy-before-write", "bool",
               /*default=*/"false",
               "Skip the analysis. Make a buffer copy on every write.">,

diff  --git a/mlir/lib/Dialect/Bufferization/Transforms/Bufferize.cpp b/mlir/lib/Dialect/Bufferization/Transforms/Bufferize.cpp
index 099f2a9372215..18ae650526d53 100644
--- a/mlir/lib/Dialect/Bufferization/Transforms/Bufferize.cpp
+++ b/mlir/lib/Dialect/Bufferization/Transforms/Bufferize.cpp
@@ -97,7 +97,8 @@ struct OneShotBufferizePass
       opt.bufferAlignment = bufferAlignment;
       opt.testAnalysisOnly = testAnalysisOnly;
       opt.bufferizeFunctionBoundaries = bufferizeFunctionBoundaries;
-      opt.checkParallelRegions = checkParallelRegions;
+      if (!mayHaveParallelRegions)
+        opt.mayHaveParallelRegions = false;
       opt.noAnalysisFuncFilter = noAnalysisFuncFilter;
 
       // Configure type converter.

diff  --git a/mlir/lib/Dialect/Bufferization/Transforms/OneShotAnalysis.cpp b/mlir/lib/Dialect/Bufferization/Transforms/OneShotAnalysis.cpp
index 1649a84c41674..e8b3404843217 100644
--- a/mlir/lib/Dialect/Bufferization/Transforms/OneShotAnalysis.cpp
+++ b/mlir/lib/Dialect/Bufferization/Transforms/OneShotAnalysis.cpp
@@ -131,11 +131,32 @@ static bool detectUnstructuredControlFlow(Operation *op) {
   return walkRes.wasInterrupted();
 }
 
+/// Return "true" if any allowed op has a parallel region.
+static bool detectParallelRegions(Operation *op,
+                                  const BufferizationOptions &options) {
+  WalkResult walkRes =
+      op->walk([&](BufferizableOpInterface bufferizableOp) -> WalkResult {
+        if (!options.isOpAllowed(bufferizableOp))
+          return WalkResult::skip();
+        for (Region &region : bufferizableOp->getRegions()) {
+          if (bufferizableOp.isParallelRegion(region.getRegionNumber()))
+            return WalkResult::interrupt();
+        }
+        return WalkResult::advance();
+      });
+  return walkRes.wasInterrupted();
+}
+
 OneShotAnalysisState::OneShotAnalysisState(
     Operation *op, const OneShotBufferizationOptions &options)
     : AnalysisState(options, TypeID::get<OneShotAnalysisState>()) {
   mayHaveUnstructuredCF = options.mayHaveUnstructuredControlFlow.value_or(
       detectUnstructuredControlFlow(op));
+  if (!options.mayHaveParallelRegions.has_value()) {
+    mayHaveParallelRegionsFlag = detectParallelRegions(op, options);
+  } else {
+    mayHaveParallelRegionsFlag = *options.mayHaveParallelRegions;
+  }
 
   // Set up alias sets.
   op->walk([&](Operation *op) {
@@ -153,6 +174,7 @@ OneShotAnalysisState::OneShotAnalysisState(
   op->walk([&](BufferizableOpInterface bufferizableOp) {
     if (!options.isOpAllowed(bufferizableOp))
       return WalkResult::skip();
+
     for (OpOperand &opOperand : bufferizableOp->getOpOperands())
       if (isa<TensorLikeType>(opOperand.get().getType()))
         if (bufferizableOp.mustBufferizeInPlace(opOperand, *this))
@@ -841,7 +863,7 @@ hasReadAfterWriteInterference(const DenseSet<OpOperand *> &usesRead,
   // Before going through the main RaW analysis, find cases where a buffer must
   // be privatized due to parallelism. If the result of a write is never read,
   // privatization is not necessary (and large parts of the IR are likely dead).
-  if (options.checkParallelRegions && !usesRead.empty()) {
+  if (state.mayHaveParallelRegions() && !usesRead.empty()) {
     for (OpOperand *uConflictingWrite : usesWrite) {
       // Find the allocation point or last write (definition) of the buffer.
       // Note: In contrast to `findDefinitions`, this also returns results of
@@ -858,10 +880,11 @@ hasReadAfterWriteInterference(const DenseSet<OpOperand *> &usesRead,
 
       // The writing op must bufferize out-of-place if the definition is in a
       // 
diff erent parallel region than this write.
+      Region *writeParallelRegion = getParallelRegion(
+          uConflictingWrite->getOwner()->getParentRegion(), options);
       for (Value def : definitionsOrLeaves) {
         if (getParallelRegion(def.getParentRegion(), options) !=
-            getParallelRegion(uConflictingWrite->getOwner()->getParentRegion(),
-                              options)) {
+            writeParallelRegion) {
           LDBG() << "\n- bufferizes out-of-place due to parallel region:\n"
                  << "  unConflictingWrite = operand "
                  << uConflictingWrite->getOperandNumber() << " of "

diff  --git a/mlir/test/Dialect/SCF/one-shot-bufferize-analysis.mlir b/mlir/test/Dialect/SCF/one-shot-bufferize-analysis.mlir
index ed3685514dd0d..3d02f022a3864 100644
--- a/mlir/test/Dialect/SCF/one-shot-bufferize-analysis.mlir
+++ b/mlir/test/Dialect/SCF/one-shot-bufferize-analysis.mlir
@@ -1,5 +1,5 @@
 // RUN: mlir-opt %s -one-shot-bufferize="allow-return-allocs-from-loops bufferize-function-boundaries test-analysis-only" -split-input-file | FileCheck %s --check-prefixes=CHECK,PARALLEL-CHECK
-// RUN: mlir-opt %s -one-shot-bufferize="allow-return-allocs-from-loops bufferize-function-boundaries test-analysis-only check-parallel-regions=false" -split-input-file | FileCheck %s --check-prefixes=CHECK,NO-PARALLEL-CHECK
+// RUN: mlir-opt %s -one-shot-bufferize="allow-return-allocs-from-loops bufferize-function-boundaries test-analysis-only may-have-parallel-regions=false" -split-input-file | FileCheck %s --check-prefixes=CHECK,NO-PARALLEL-CHECK
 
 // Run fuzzer with 
diff erent seeds.
 // RUN: mlir-opt %s -one-shot-bufferize="allow-return-allocs-from-loops bufferize-function-boundaries test-analysis-only analysis-heuristic=fuzzer analysis-fuzzer-seed=23" -split-input-file -o /dev/null


        


More information about the Mlir-commits mailing list