Skip to content

Commit dbbdc7e

Browse files
[mlir][bufferization] Use a cache when checking whether ops are in mutually exclusive regions (#123516)
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 41f96f9 commit dbbdc7e

File tree

3 files changed

+29
-2
lines changed

3 files changed

+29
-2
lines changed

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

+10
Original file line numberDiff line numberDiff line change
@@ -563,6 +563,11 @@ class AnalysisState {
563563

564564
virtual void resetCache();
565565

566+
/// Checks whether `op0` and `op1` are inside mutually exclusive regions.
567+
/// The logic defers to `mlir::insideMutuallyExclusiveRegions`, but the
568+
/// result is cached.
569+
bool insideMutuallyExclusiveRegions(Operation *op0, Operation *op1);
570+
566571
protected:
567572
AnalysisState(const BufferizationOptions &options, TypeID type);
568573

@@ -576,6 +581,11 @@ class AnalysisState {
576581
/// Cache containing closest ancestor repetitive Region.
577582
DenseMap<std::variant<Operation *, Block *, Region *, Value>, Region *>
578583
enclosingRepetitiveRegionCache;
584+
585+
/// Cache that specifies whether the two operations are in mutually exclusive
586+
/// regions.
587+
DenseMap<std::pair<Operation *, Operation *>, bool>
588+
insideMutuallyExclusiveRegionsCache;
579589
};
580590

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

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

+17-1
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::insideMutuallyExclusiveRegions(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 = ::mlir::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

+2-1
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.insideMutuallyExclusiveRegions(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)