Skip to content

Commit d4f8086

Browse files
[mlir][bufferization] Use a cache when checking whether ops are in mutually exclusive regions
When profiling one-shot-bufferization over large programs, I found that the analysis would spend a large amount of time checking whether two operations are "inside mutually exclusive regions". This change adds a cache for that information, which can result in a noticeable speedup depending on program structure.
1 parent ddfd89a commit d4f8086

File tree

3 files changed

+26
-2
lines changed

3 files changed

+26
-2
lines changed

mlir/include/mlir/Dialect/Bufferization/IR/BufferizableOpInterface.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -563,6 +563,8 @@ class AnalysisState {
563563

564564
virtual void resetCache();
565565

566+
bool checkInMutuallyExclusiveRegions(Operation *op0, Operation *op1);
567+
566568
protected:
567569
AnalysisState(const BufferizationOptions &options, TypeID type);
568570

@@ -576,6 +578,11 @@ class AnalysisState {
576578
/// Cache containing closest ancestor repetitive Region.
577579
DenseMap<std::variant<Operation *, Block *, Region *, Value>, Region *>
578580
enclosingRepetitiveRegionCache;
581+
582+
/// Cache that specifies whether the two operations are in mutually exclusive
583+
/// regions.
584+
DenseMap<std::pair<Operation *, Operation *>, bool>
585+
insideMutuallyExclusiveRegionsCache;
579586
};
580587

581588
/// Create an AllocTensorOp for the given shaped value (memref or tensor).

mlir/lib/Dialect/Bufferization/IR/BufferizableOpInterface.cpp

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -107,7 +107,23 @@ Region *AnalysisState::getEnclosingRepetitiveRegion(
107107
return region;
108108
}
109109

110-
void AnalysisState::resetCache() { enclosingRepetitiveRegionCache.clear(); }
110+
bool AnalysisState::checkInMutuallyExclusiveRegions(Operation *op0,
111+
Operation *op1) {
112+
auto key = std::make_pair(op0, op1);
113+
if (auto iter = insideMutuallyExclusiveRegionsCache.find(key);
114+
iter != insideMutuallyExclusiveRegionsCache.end())
115+
return iter->second;
116+
bool result = insideMutuallyExclusiveRegions(op0, op1);
117+
// Populate results for both orderings of the ops.
118+
insideMutuallyExclusiveRegionsCache[key] = result;
119+
insideMutuallyExclusiveRegionsCache[std::make_pair(op1, op0)] = result;
120+
return result;
121+
}
122+
123+
void AnalysisState::resetCache() {
124+
enclosingRepetitiveRegionCache.clear();
125+
insideMutuallyExclusiveRegionsCache.clear();
126+
}
111127

112128
Region *bufferization::getNextEnclosingRepetitiveRegion(
113129
Region *region, const BufferizationOptions &options) {

mlir/lib/Dialect/Bufferization/Transforms/OneShotAnalysis.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -705,7 +705,8 @@ hasReadAfterWriteInterference(const DenseSet<OpOperand *> &usesRead,
705705
// Note: If ops are executed multiple times (e.g., because they are
706706
// inside a loop), mutually exclusive regions may be executed
707707
// multiple times.
708-
if (insideMutuallyExclusiveRegions(readingOp, conflictingWritingOp)) {
708+
if (state.checkInMutuallyExclusiveRegions(readingOp,
709+
conflictingWritingOp)) {
709710
LLVM_DEBUG(llvm::dbgs() << " no conflict: read and write are in "
710711
"mutually exclusive regions\n");
711712
continue;

0 commit comments

Comments
 (0)