diff --git a/mlir/lib/Dialect/Bufferization/Transforms/OneShotAnalysis.cpp b/mlir/lib/Dialect/Bufferization/Transforms/OneShotAnalysis.cpp --- a/mlir/lib/Dialect/Bufferization/Transforms/OneShotAnalysis.cpp +++ b/mlir/lib/Dialect/Bufferization/Transforms/OneShotAnalysis.cpp @@ -750,18 +750,9 @@ /// * However, adding an alias {%0, %t} would mean that the second /// TransferWriteOp overwrites the first one. Therefore, the TransferReadOp /// would no longer be reading the result of %1. -/// -/// If `checkConsistencyOnly` is true, this function checks if there is a -/// read-after-write conflict without bufferizing `operand` inplace. This would -/// indicate a problem with the current inplace bufferization decisions. -/// -/// Note: If `checkConsistencyOnly`, this function may be called with a null -/// OpResult. In that case, only the consistency of bufferization decisions -/// involving aliases of the given OpOperand are checked. static bool wouldCreateReadAfterWriteInterference( OpOperand &operand, const DominanceInfo &domInfo, AnalysisState &state, - const BufferizationAliasInfo &aliasInfo, - bool checkConsistencyOnly = false) { + const BufferizationAliasInfo &aliasInfo) { // Collect reads and writes of all aliases of OpOperand and OpResult. DenseSet usesRead, usesWrite; getAliasingReads(usesRead, operand.get(), aliasInfo, state); @@ -770,7 +761,7 @@ getAliasingReads(usesRead, result, aliasInfo, state); getAliasingInplaceWrites(usesWrite, result, aliasInfo, state); } - if (!checkConsistencyOnly && state.bufferizesToMemoryWrite(operand)) + if (state.bufferizesToMemoryWrite(operand)) usesWrite.insert(&operand); return hasReadAfterWriteInterference(usesRead, usesWrite, domInfo, state, @@ -810,16 +801,17 @@ /// Return true if bufferizing `operand` inplace would create a write to a /// non-writable buffer. -static bool wouldCreateWriteToNonWritableBuffer( - OpOperand &operand, const BufferizationAliasInfo &aliasInfo, - OneShotAnalysisState &state, bool checkConsistencyOnly = false) { +static bool +wouldCreateWriteToNonWritableBuffer(OpOperand &operand, + const BufferizationAliasInfo &aliasInfo, + OneShotAnalysisState &state) { // Collect writes of all aliases of OpOperand and OpResult. DenseSet usesWrite; getAliasingInplaceWrites(usesWrite, operand.get(), aliasInfo, state); for (OpResult result : state.getAliasingOpResult(operand)) { getAliasingInplaceWrites(usesWrite, result, aliasInfo, state); } - if (!checkConsistencyOnly && state.bufferizesToMemoryWrite(operand)) + if (state.bufferizesToMemoryWrite(operand)) usesWrite.insert(&operand); // Assuming that `operand` bufferizes in-place: For each write (to each @@ -911,13 +903,25 @@ unsigned analysisFuzzerSeed = 0) { // Collect ops so we can build our own reverse traversal. SmallVector ops; - op->walk([&](Operation *op) { + WalkResult status = op->walk([&](Operation *op) { // No tensors => no buffers. if (!hasTensorSemantics(op)) - return; + return WalkResult::skip(); + + // Input IR may not contain any ToMemrefOps. These are not supported because + // the analysis cannot follow the data flow through memrefs. + if (isa(op)) { + op->emitError("to_memref ops not supported during One-Shot Analysis"); + return WalkResult::interrupt(); + } + ops.push_back(op); + return WalkResult::advance(); }); + if (status.wasInterrupted()) + return failure(); + return inPlaceAnalysis(ops, aliasInfo, state, domInfo, analysisFuzzerSeed); } @@ -954,45 +958,6 @@ equivalenceAnalysis(ops, aliasInfo, state); } -/// Assert that the current bufferization decisions are consistent. -static LogicalResult -checkAliasInfoConsistency(Operation *op, const DominanceInfo &domInfo, - AnalysisState &state, - const BufferizationAliasInfo &aliasInfo) { - const BufferizationOptions &options = state.getOptions(); - - WalkResult walkResult = op->walk([&](BufferizableOpInterface op) { - // Skip ops that are not in the filter. - if (!options.isOpAllowed(op.getOperation())) - return WalkResult::advance(); - - // Input IR may not contain any ToMemrefOps. These are not supported because - // the analysis cannot follow the data flow through memrefs. - if (isa(op.getOperation())) { - op->emitError("to_memref ops not supported during One-Shot Analysis"); - return WalkResult::interrupt(); - } - - for (OpOperand &opOperand : op->getOpOperands()) { - if (opOperand.get().getType().isa()) { - if (wouldCreateReadAfterWriteInterference( - opOperand, domInfo, state, aliasInfo, - /*checkConsistencyOnly=*/true)) { - // This error can happen if certain "mustBufferizeInPlace" interface - // methods are implemented incorrectly, such that the IR already has - // a RaW conflict before making any bufferization decisions. - op->emitError("input IR has RaW conflict"); - return WalkResult::interrupt(); - } - } - } - - return WalkResult::advance(); - }); - - return success(!walkResult.wasInterrupted()); -} - /// Annotate the IR with the result of the analysis. For testing/debugging only. static void annotateOpsWithBufferizationMarkers(Operation *op, @@ -1083,9 +1048,6 @@ const auto &options = static_cast(state.getOptions()); - if (failed(checkAliasInfoConsistency(op, domInfo, state, aliasInfo))) - return failure(); - // If the analysis fails, just return. if (failed(inPlaceAnalysis(op, aliasInfo, state, domInfo, options.analysisFuzzerSeed)))