Skip to content

Commit d3cb6bf

Browse files
[mlir][linalg][bufferize] Rewrite conflict detection
For each memory read, follow SSA use-def chains to find the op that produces the data being read (i.e., the most recent write). A memory write to an alias is a conflict if it takes places after the "most recent write" but before the read. This CL introduces two main changes: * There is a concise definition of a conflict. Given a piece of IR with InPlaceSpec annotations and a computes alias set, it is easy to compute whether this program has a conflict. No need to consider multiple cases such as "read of operand after in-place write" etc. * No need to check for clobbering. Differential Revision: https://reviews.llvm.org/D111287
1 parent 3f96f7b commit d3cb6bf

File tree

3 files changed

+334
-323
lines changed

3 files changed

+334
-323
lines changed

mlir/include/mlir/Dialect/Linalg/Transforms/ComprehensiveBufferize.h

Lines changed: 11 additions & 77 deletions
Original file line numberDiff line numberDiff line change
@@ -71,44 +71,19 @@ class BufferizationAliasInfo {
7171
/// Set the inPlace bufferization spec to false.
7272
void bufferizeOutOfPlace(OpResult result);
7373

74-
/// Return true if it is possible to find an inplace write W among `usesWrite`
75-
/// and a read R among `usesRead`, such that W and R interfere.
76-
/// Such a (W, R) pair is an interference to the inplace bufferization of
77-
/// opResult when:
78-
/// 1. R is not known properly dominate W (i.e. the effects of the write may
79-
/// be visible from R).
80-
/// 2. one cannot find an intermediate clobbering write `C` to W, such that
81-
/// C interleaved between W and R (i.e. W -> C -> R where -> denotes
82-
/// dominance).
83-
bool wouldCreateReadAfterWriteInterference(
84-
Operation *opToBufferize, DenseSet<OpOperand *> &usesRead,
85-
DenseSet<OpOperand *> &usesWrite, const DominanceInfo &domInfo) const;
74+
/// Return true if `value` has an ExtractSliceOp matching the given
75+
/// InsertSliceOp in its reverse SSA use-def chain.
76+
bool hasMatchingExtractSliceOp(Value value,
77+
tensor::InsertSliceOp insertOp) const;
8678

8779
/// Return true if bufferizing `opOperand` inplace with `opResult` would
8880
/// create a write to a non-writable buffer.
8981
bool wouldCreateWriteToNonWritableBuffer(OpOperand &opOperand,
9082
OpResult opResult) const;
9183

9284
/// Assume that result bufferizes in-place with one of the operation's
93-
/// operands. Return true if it is possible to find an inplace write W (resp.
94-
/// a read R) among the uses of `aliasInfo[result]`, and a read R (resp. an
95-
/// inplace write W) among the uses of
96-
/// `aliasInfo[getAliasingOpOperand(result)]`, such that W and R interfere.
97-
/// Interference detection is needed to determine which cases may bufferize
98-
/// inplace without interferences. Such cases comprise:
99-
///
100-
/// ```
101-
/// %0 = op_to_bufferize(%1)
102-
/// read(%1)
103-
///
104-
/// %0 = op_to_bufferize(%1)
105-
/// write(%0)
106-
/// read(%1)
107-
///
108-
/// %0 = op_to_bufferize(%1)
109-
/// write(%1)
110-
/// read(%0)
111-
/// ```
85+
/// operands. Return true if it is possible to find an inplace write W that
86+
/// creates a conflict.
11287
bool
11388
wouldCreateReadAfterWriteInterference(OpOperand &operand, OpResult result,
11489
const DominanceInfo &domInfo) const;
@@ -171,54 +146,13 @@ class BufferizationAliasInfo {
171146
bool areEquivalentExtractSliceOps(tensor::ExtractSliceOp st,
172147
tensor::InsertSliceOp sti) const;
173148

174-
/// Return true if there is a `candidateOp` that would write to memory after
175-
/// bufferization and such that:
176-
/// 1. The written buffer is equivalent to either `aliasingRead` or
177-
/// `aliasingWrite` under the inPlace bufferization decisions taken
178-
/// so far.
179-
/// 2. `aliasingWrite` properly dominates `candidateOp`.
180-
/// 3. `candidateOp` properly dominates `aliasingReadOp`.
181-
// TODO: richer clobbering analysis with container-containee relationship
182-
// instead of equivalence.
183-
bool existsInterleavedValueClobber(OpOperand &aliasingRead,
184-
OpOperand &aliasingWrite,
149+
/// Given sets of uses and writes, return true if there is a RaW conflict
150+
/// under the assumption that all given reads/writes alias the same buffer and
151+
/// that all given writes bufferize inplace.
152+
bool hasReadAfterWriteInterference(const DenseSet<OpOperand *> &usesRead,
153+
const DenseSet<OpOperand *> &usesWrite,
185154
const DominanceInfo &domInfo) const;
186155

187-
/// Return true if there is a write that:
188-
/// 1. Properly dominates aliasingReadOp.
189-
/// 2. Is properly dominated by aliasingWriteOp.
190-
/// 3. Clobbers the write that would be interfering with the read.
191-
///
192-
/// Case discussion:
193-
/// ================
194-
/// Case 1: opOperand is produced by opToBufferize,
195-
/// Case 2: opResult is produced by opToBufferize,
196-
/// Common case:
197-
/// - aliasingReadOp is a read to an alias of opOperand.
198-
/// - aliasingWriteOp is an inplace write to an alias of opResult.
199-
/// - aliasingWriteOp dominates aliasingReadOp.
200-
///
201-
/// ```
202-
/// // Either case 1:
203-
/// %opOperand = opToBufferize(%opResult)
204-
/// aliasingWriteOp(%aliasingWrite = alias(%opResult)) // inplace
205-
/// aliasingReadOp( %aliasingRead = alias(%opOperand))
206-
/// ```
207-
///
208-
/// ```
209-
/// // Or case 2:
210-
/// %opResult = opToBufferize(%opOperand)
211-
/// aliasingWriteOp(%aliasingWrite = alias(%opResult)) // inplace
212-
/// aliasingReadOp( %aliasingRead = alias(%opOperand))
213-
/// ```
214-
///
215-
/// Capture possible cases where `aliasingWriteOp(alias(%opResult))` has no
216-
/// visible effect on `aliasingReadOp(alias(%opOperand))`.
217-
bool isClobberedWriteBeforeRead(Operation *opToBufferize,
218-
OpOperand &aliasingRead,
219-
OpOperand &aliasingWrite,
220-
const DominanceInfo &domInfo) const;
221-
222156
/// Set of tensors that are known to bufferize to writable memory.
223157
llvm::DenseSet<Value> bufferizeToWritableMemory;
224158

0 commit comments

Comments
 (0)