diff --git a/mlir/include/mlir/Interfaces/SideEffectInterfaceBase.td b/mlir/include/mlir/Interfaces/SideEffectInterfaceBase.td --- a/mlir/include/mlir/Interfaces/SideEffectInterfaceBase.td +++ b/mlir/include/mlir/Interfaces/SideEffectInterfaceBase.td @@ -94,13 +94,6 @@ return effects.empty(); } - /// Returns true if the given operation has no effects for this interface. - static bool hasNoEffect(Operation *op) { - if (auto interface = dyn_cast<}] # name # [{>(op)) - return interface.hasNoEffect(); - return op->hasTrait<::mlir::OpTrait::HasRecursiveMemoryEffects>(); - } - /// Collect all of the effect instances that operate on the provided value /// and place them in 'effects'. void getEffectsOnValue(::mlir::Value value, diff --git a/mlir/include/mlir/Interfaces/SideEffectInterfaces.h b/mlir/include/mlir/Interfaces/SideEffectInterfaces.h --- a/mlir/include/mlir/Interfaces/SideEffectInterfaces.h +++ b/mlir/include/mlir/Interfaces/SideEffectInterfaces.h @@ -318,6 +318,25 @@ /// `isOpTriviallyDead` if `op` was unused. bool wouldOpBeTriviallyDead(Operation *op); +/// Returns true if the given operation is free of memory effects. +/// +/// An operation is free of memory effects if its implementation of +/// `MemoryEffectOpInterface` indicates that it has no memory effects. For +/// example, it may implement `NoMemoryEffect` in ODS. Alternatively, if the +/// operation has the `HasRecursiveMemoryEffects` trait, then it is free of +/// memory effects if all of its nested operations are free of memory effects. +/// +/// If the operation has both, then it is free of memory effects if both +/// conditions are satisfied. +bool isMemoryEffectFree(Operation *op); + +/// Returns true if the given operation is speculatable, i.e. has no undefined +/// behavior or other side effects. +/// +/// An operation can indicate that it is speculatable by implementing the +/// getSpeculatability hook in the ConditionallySpeculatable op interface. +bool isSpeculatable(Operation *op); + } // namespace mlir //===----------------------------------------------------------------------===// diff --git a/mlir/include/mlir/Transforms/SideEffectUtils.h b/mlir/include/mlir/Transforms/SideEffectUtils.h deleted file mode 100644 --- a/mlir/include/mlir/Transforms/SideEffectUtils.h +++ /dev/null @@ -1,37 +0,0 @@ -//===- SideEffectUtils.h - Side Effect Utils --------------------*- C++ -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// - -#ifndef MLIR_TRANSFORMS_SIDEFFECTUTILS_H -#define MLIR_TRANSFORMS_SIDEFFECTUTILS_H - -namespace mlir { - -class Operation; - -/// Returns true if the given operation is free of memory effects. -/// -/// An operation is free of memory effects if its implementation of -/// `MemoryEffectOpInterface` indicates that it has no memory effects. For -/// example, it may implement `NoMemoryEffect` in ODS. Alternatively, if the -/// operation has the `HasRecursiveMemoryEffects` trait, then it is free of -/// memory effects if all of its nested operations are free of memory effects. -/// -/// If the operation has both, then it is free of memory effects if both -/// conditions are satisfied. -bool isMemoryEffectFree(Operation *op); - -/// Returns true if the given operation is speculatable, i.e. has no undefined -/// behavior or other side effects. -/// -/// An operation can indicate that it is speculatable by implementing the -/// getSpeculatability hook in the ConditionallySpeculatable op interface. -bool isSpeculatable(Operation *op); - -} // end namespace mlir - -#endif // MLIR_TRANSFORMS_SIDEFFECTUTILS_H diff --git a/mlir/lib/Analysis/SliceAnalysis.cpp b/mlir/lib/Analysis/SliceAnalysis.cpp --- a/mlir/lib/Analysis/SliceAnalysis.cpp +++ b/mlir/lib/Analysis/SliceAnalysis.cpp @@ -13,6 +13,7 @@ #include "mlir/Analysis/SliceAnalysis.h" #include "mlir/IR/BuiltinOps.h" #include "mlir/IR/Operation.h" +#include "mlir/Interfaces/SideEffectInterfaces.h" #include "mlir/Support/LLVM.h" #include "llvm/ADT/SetVector.h" #include "llvm/ADT/SmallPtrSet.h" @@ -293,9 +294,8 @@ // terminator is found. Gather all the combiner ops along the way in // topological order. while (!combinerOp->mightHaveTrait()) { - if (!MemoryEffectOpInterface::hasNoEffect(combinerOp) || - combinerOp->getNumResults() != 1 || !combinerOp->hasOneUse() || - combinerOp->getParentOp() != redRegionOp) + if (!isMemoryEffectFree(combinerOp) || combinerOp->getNumResults() != 1 || + !combinerOp->hasOneUse() || combinerOp->getParentOp() != redRegionOp) return nullptr; combinerOps.push_back(combinerOp); diff --git a/mlir/lib/Conversion/SCFToGPU/CMakeLists.txt b/mlir/lib/Conversion/SCFToGPU/CMakeLists.txt --- a/mlir/lib/Conversion/SCFToGPU/CMakeLists.txt +++ b/mlir/lib/Conversion/SCFToGPU/CMakeLists.txt @@ -19,5 +19,6 @@ MLIRMemRefDialect MLIRPass MLIRSupport + MLIRSideEffectInterfaces MLIRTransforms ) diff --git a/mlir/lib/Conversion/SCFToGPU/SCFToGPU.cpp b/mlir/lib/Conversion/SCFToGPU/SCFToGPU.cpp --- a/mlir/lib/Conversion/SCFToGPU/SCFToGPU.cpp +++ b/mlir/lib/Conversion/SCFToGPU/SCFToGPU.cpp @@ -24,6 +24,7 @@ #include "mlir/IR/AffineExpr.h" #include "mlir/IR/BlockAndValueMapping.h" #include "mlir/IR/Builders.h" +#include "mlir/Interfaces/SideEffectInterfaces.h" #include "mlir/Pass/Pass.h" #include "mlir/Transforms/DialectConversion.h" #include "mlir/Transforms/Passes.h" @@ -656,8 +657,8 @@ cloningMap.map(op->getResults(), clone->getResults()); // Check for side effects. // TODO: Handle region side effects properly. - seenSideeffects |= !MemoryEffectOpInterface::hasNoEffect(clone) || - clone->getNumRegions() != 0; + seenSideeffects |= + !isMemoryEffectFree(clone) || clone->getNumRegions() != 0; // If we are no longer in the innermost scope, sideeffects are disallowed. if (seenSideeffects && leftNestingScope) return failure(); diff --git a/mlir/lib/Dialect/Affine/Analysis/AffineAnalysis.cpp b/mlir/lib/Dialect/Affine/Analysis/AffineAnalysis.cpp --- a/mlir/lib/Dialect/Affine/Analysis/AffineAnalysis.cpp +++ b/mlir/lib/Dialect/Affine/Analysis/AffineAnalysis.cpp @@ -150,7 +150,7 @@ loadAndStoreOps.push_back(op); } else if (!isa(op) && !hasSingleEffect(op) && - !MemoryEffectOpInterface::hasNoEffect(op)) { + !isMemoryEffectFree(op)) { // Alloc-like ops inside `forOp` are fine (they don't impact parallelism) // as long as they don't escape the loop (which has been checked above). return WalkResult::interrupt(); diff --git a/mlir/lib/Dialect/Affine/Analysis/CMakeLists.txt b/mlir/lib/Dialect/Affine/Analysis/CMakeLists.txt --- a/mlir/lib/Dialect/Affine/Analysis/CMakeLists.txt +++ b/mlir/lib/Dialect/Affine/Analysis/CMakeLists.txt @@ -14,6 +14,7 @@ MLIRCallInterfaces MLIRControlFlowInterfaces MLIRInferTypeOpInterface + MLIRSideEffectInterfaces MLIRPresburger MLIRSCFDialect ) diff --git a/mlir/lib/Dialect/Bufferization/Transforms/Bufferize.cpp b/mlir/lib/Dialect/Bufferization/Transforms/Bufferize.cpp --- a/mlir/lib/Dialect/Bufferization/Transforms/Bufferize.cpp +++ b/mlir/lib/Dialect/Bufferization/Transforms/Bufferize.cpp @@ -17,6 +17,7 @@ #include "mlir/Dialect/Func/IR/FuncOps.h" #include "mlir/Dialect/MemRef/IR/MemRef.h" #include "mlir/IR/Operation.h" +#include "mlir/Interfaces/SideEffectInterfaces.h" #include "mlir/Pass/PassManager.h" #include "mlir/Transforms/GreedyPatternRewriteDriver.h" #include "mlir/Transforms/Passes.h" @@ -493,7 +494,7 @@ if (opFilter && !opFilter->isOpAllowed(op)) continue; // Ops without any uses and no side effects will fold away. - if (op->getUses().empty() && MemoryEffectOpInterface::hasNoEffect(op)) + if (op->getUses().empty() && isMemoryEffectFree(op)) continue; // ToTensorOps/ToMemrefOps are allowed in the output. if (isa(op)) diff --git a/mlir/lib/Dialect/Bufferization/Transforms/CMakeLists.txt b/mlir/lib/Dialect/Bufferization/Transforms/CMakeLists.txt --- a/mlir/lib/Dialect/Bufferization/Transforms/CMakeLists.txt +++ b/mlir/lib/Dialect/Bufferization/Transforms/CMakeLists.txt @@ -28,6 +28,7 @@ MLIRMemRefDialect MLIRPass MLIRTensorDialect + MLIRSideEffectInterfaces MLIRTransforms MLIRViewLikeInterface ) diff --git a/mlir/lib/Dialect/GPU/CMakeLists.txt b/mlir/lib/Dialect/GPU/CMakeLists.txt --- a/mlir/lib/Dialect/GPU/CMakeLists.txt +++ b/mlir/lib/Dialect/GPU/CMakeLists.txt @@ -78,6 +78,7 @@ MLIRMemRefDialect MLIRPass MLIRSCFDialect + MLIRSideEffectInterfaces MLIRSupport MLIRTransformUtils ) diff --git a/mlir/lib/Dialect/GPU/Transforms/AsyncRegionRewriter.cpp b/mlir/lib/Dialect/GPU/Transforms/AsyncRegionRewriter.cpp --- a/mlir/lib/Dialect/GPU/Transforms/AsyncRegionRewriter.cpp +++ b/mlir/lib/Dialect/GPU/Transforms/AsyncRegionRewriter.cpp @@ -21,6 +21,7 @@ #include "mlir/IR/Builders.h" #include "mlir/IR/PatternMatch.h" #include "mlir/IR/SymbolTable.h" +#include "mlir/Interfaces/SideEffectInterfaces.h" #include "mlir/Support/LLVM.h" #include "mlir/Transforms/RegionUtils.h" #include "llvm/ADT/TypeSwitch.h" @@ -45,9 +46,7 @@ static bool isTerminator(Operation *op) { return op->mightHaveTrait(); } -static bool hasSideEffects(Operation *op) { - return !MemoryEffectOpInterface::hasNoEffect(op); -} +static bool hasSideEffects(Operation *op) { return !isMemoryEffectFree(op); } // Region walk callback which makes GPU ops implementing the AsyncOpInterface // execute asynchronously. diff --git a/mlir/lib/Dialect/MemRef/IR/MemRefOps.cpp b/mlir/lib/Dialect/MemRef/IR/MemRefOps.cpp --- a/mlir/lib/Dialect/MemRef/IR/MemRefOps.cpp +++ b/mlir/lib/Dialect/MemRef/IR/MemRefOps.cpp @@ -1368,7 +1368,7 @@ bool hasSideEffects = body.walk([&](Operation *nestedOp) { - if (MemoryEffectOpInterface::hasNoEffect(nestedOp)) + if (isMemoryEffectFree(nestedOp)) return WalkResult::advance(); nestedOp->emitError( "body of 'memref.generic_atomic_rmw' should contain " diff --git a/mlir/lib/Dialect/SCF/Transforms/CMakeLists.txt b/mlir/lib/Dialect/SCF/Transforms/CMakeLists.txt --- a/mlir/lib/Dialect/SCF/Transforms/CMakeLists.txt +++ b/mlir/lib/Dialect/SCF/Transforms/CMakeLists.txt @@ -31,6 +31,7 @@ MLIRPass MLIRSCFDialect MLIRSCFUtils + MLIRSideEffectInterfaces MLIRSupport MLIRTensorDialect MLIRTensorTransforms diff --git a/mlir/lib/Dialect/SCF/Transforms/ParallelLoopFusion.cpp b/mlir/lib/Dialect/SCF/Transforms/ParallelLoopFusion.cpp --- a/mlir/lib/Dialect/SCF/Transforms/ParallelLoopFusion.cpp +++ b/mlir/lib/Dialect/SCF/Transforms/ParallelLoopFusion.cpp @@ -18,6 +18,7 @@ #include "mlir/IR/BlockAndValueMapping.h" #include "mlir/IR/Builders.h" #include "mlir/IR/OpDefinition.h" +#include "mlir/Interfaces/SideEffectInterfaces.h" namespace mlir { #define GEN_PASS_DEF_SCFPARALLELLOOPFUSION @@ -155,8 +156,7 @@ continue; } // TODO: Handle region side effects properly. - noSideEffects &= - MemoryEffectOpInterface::hasNoEffect(&op) && op.getNumRegions() == 0; + noSideEffects &= isMemoryEffectFree(&op) && op.getNumRegions() == 0; } for (ArrayRef ploops : ploopChains) { for (int i = 0, e = ploops.size(); i + 1 < e; ++i) diff --git a/mlir/lib/Dialect/SCF/Utils/CMakeLists.txt b/mlir/lib/Dialect/SCF/Utils/CMakeLists.txt --- a/mlir/lib/Dialect/SCF/Utils/CMakeLists.txt +++ b/mlir/lib/Dialect/SCF/Utils/CMakeLists.txt @@ -14,6 +14,7 @@ MLIRFuncDialect MLIRIR MLIRSCFDialect + MLIRSideEffectInterfaces MLIRSupport MLIRTransforms ) diff --git a/mlir/lib/Dialect/SCF/Utils/Utils.cpp b/mlir/lib/Dialect/SCF/Utils/Utils.cpp --- a/mlir/lib/Dialect/SCF/Utils/Utils.cpp +++ b/mlir/lib/Dialect/SCF/Utils/Utils.cpp @@ -18,6 +18,7 @@ #include "mlir/IR/BlockAndValueMapping.h" #include "mlir/IR/BuiltinOps.h" #include "mlir/IR/PatternMatch.h" +#include "mlir/Interfaces/SideEffectInterfaces.h" #include "mlir/Support/MathExtras.h" #include "mlir/Transforms/RegionUtils.h" #include "llvm/ADT/STLExtras.h" @@ -825,7 +826,7 @@ } // Skip if op has side effects. // TODO: loads to immutable memory regions are ok. - if (!MemoryEffectOpInterface::hasNoEffect(&op)) { + if (!isMemoryEffectFree(&op)) { status = failure(); continue; } diff --git a/mlir/lib/Dialect/Vector/Transforms/CMakeLists.txt b/mlir/lib/Dialect/Vector/Transforms/CMakeLists.txt --- a/mlir/lib/Dialect/Vector/Transforms/CMakeLists.txt +++ b/mlir/lib/Dialect/Vector/Transforms/CMakeLists.txt @@ -31,6 +31,7 @@ MLIRLinalgDialect MLIRMemRefDialect MLIRSCFDialect + MLIRSideEffectInterfaces MLIRTransforms MLIRVectorDialect MLIRVectorInterfaces diff --git a/mlir/lib/Dialect/Vector/Transforms/VectorDistribute.cpp b/mlir/lib/Dialect/Vector/Transforms/VectorDistribute.cpp --- a/mlir/lib/Dialect/Vector/Transforms/VectorDistribute.cpp +++ b/mlir/lib/Dialect/Vector/Transforms/VectorDistribute.cpp @@ -13,8 +13,8 @@ #include "mlir/Dialect/Vector/IR/VectorOps.h" #include "mlir/Dialect/Vector/Transforms/VectorDistribution.h" #include "mlir/IR/AffineExpr.h" +#include "mlir/Interfaces/SideEffectInterfaces.h" #include "mlir/Transforms/RegionUtils.h" -#include "mlir/Transforms/SideEffectUtils.h" #include "llvm/ADT/SetVector.h" #include diff --git a/mlir/lib/Dialect/Vector/Transforms/VectorTransferOpTransforms.cpp b/mlir/lib/Dialect/Vector/Transforms/VectorTransferOpTransforms.cpp --- a/mlir/lib/Dialect/Vector/Transforms/VectorTransferOpTransforms.cpp +++ b/mlir/lib/Dialect/Vector/Transforms/VectorTransferOpTransforms.cpp @@ -18,7 +18,7 @@ #include "mlir/Dialect/Vector/Utils/VectorUtils.h" #include "mlir/IR/BuiltinOps.h" #include "mlir/IR/Dominance.h" -#include "mlir/Transforms/SideEffectUtils.h" +#include "mlir/Interfaces/SideEffectInterfaces.h" #include "llvm/ADT/STLExtras.h" #include "llvm/ADT/StringRef.h" #include "llvm/Support/Debug.h" diff --git a/mlir/lib/Interfaces/SideEffectInterfaces.cpp b/mlir/lib/Interfaces/SideEffectInterfaces.cpp --- a/mlir/lib/Interfaces/SideEffectInterfaces.cpp +++ b/mlir/lib/Interfaces/SideEffectInterfaces.cpp @@ -154,3 +154,50 @@ return false; return wouldOpBeTriviallyDeadImpl(op); } + +bool mlir::isMemoryEffectFree(Operation *op) { + if (auto memInterface = dyn_cast(op)) { + // If the op has side-effects, it cannot be moved. + if (!memInterface.hasNoEffect()) + return false; + // If the op does not have recursive side effects, then it can be moved. + if (!op->hasTrait()) + return true; + } else if (!op->hasTrait()) { + // Otherwise, if the op does not implement the memory effect interface and + // it does not have recursive side effects, then it cannot be known that the + // op is moveable. + return false; + } + + // Recurse into the regions and ensure that all nested ops can also be moved. + for (Region ®ion : op->getRegions()) + for (Operation &op : region.getOps()) + if (!isMemoryEffectFree(&op)) + return false; + return true; +} + +bool mlir::isSpeculatable(Operation *op) { + auto conditionallySpeculatable = dyn_cast(op); + if (!conditionallySpeculatable) + return false; + + switch (conditionallySpeculatable.getSpeculatability()) { + case Speculation::RecursivelySpeculatable: + for (Region ®ion : op->getRegions()) { + for (Operation &op : region.getOps()) + if (!isSpeculatable(&op)) + return false; + } + return true; + + case Speculation::Speculatable: + return true; + + case Speculation::NotSpeculatable: + return false; + } + + llvm_unreachable("Unhandled enum in mlir::isSpeculatable!"); +} diff --git a/mlir/lib/Transforms/CMakeLists.txt b/mlir/lib/Transforms/CMakeLists.txt --- a/mlir/lib/Transforms/CMakeLists.txt +++ b/mlir/lib/Transforms/CMakeLists.txt @@ -26,6 +26,7 @@ MLIRCopyOpInterface MLIRLoopLikeInterface MLIRPass + MLIRSideEffectInterfaces MLIRSupport MLIRTransformUtils ) diff --git a/mlir/lib/Transforms/CSE.cpp b/mlir/lib/Transforms/CSE.cpp --- a/mlir/lib/Transforms/CSE.cpp +++ b/mlir/lib/Transforms/CSE.cpp @@ -209,7 +209,7 @@ // Some simple use case of operation with memory side-effect are dealt with // here. Operations with no side-effect are done after. - if (!MemoryEffectOpInterface::hasNoEffect(op)) { + if (!isMemoryEffectFree(op)) { auto memEffects = dyn_cast(op); // TODO: Only basic use case for operations with MemoryEffects::Read can be // eleminated now. More work needs to be done for more complicated patterns diff --git a/mlir/lib/Transforms/ControlFlowSink.cpp b/mlir/lib/Transforms/ControlFlowSink.cpp --- a/mlir/lib/Transforms/ControlFlowSink.cpp +++ b/mlir/lib/Transforms/ControlFlowSink.cpp @@ -19,7 +19,6 @@ #include "mlir/Interfaces/ControlFlowInterfaces.h" #include "mlir/Interfaces/SideEffectInterfaces.h" #include "mlir/Transforms/ControlFlowSinkUtils.h" -#include "mlir/Transforms/SideEffectUtils.h" namespace mlir { #define GEN_PASS_DEF_CONTROLFLOWSINK diff --git a/mlir/lib/Transforms/Inliner.cpp b/mlir/lib/Transforms/Inliner.cpp --- a/mlir/lib/Transforms/Inliner.cpp +++ b/mlir/lib/Transforms/Inliner.cpp @@ -201,7 +201,7 @@ // If the parent operation isn't a symbol, simply check normal SSA deadness. Operation *nodeOp = node->getCallableRegion()->getParentOp(); if (!isa(nodeOp)) - return MemoryEffectOpInterface::hasNoEffect(nodeOp) && nodeOp->use_empty(); + return isMemoryEffectFree(nodeOp) && nodeOp->use_empty(); // Otherwise, check the number of symbol uses. auto symbolIt = discardableSymNodeUses.find(node); @@ -212,7 +212,7 @@ // If this isn't a symbol node, check for side-effects and SSA use count. Operation *nodeOp = node->getCallableRegion()->getParentOp(); if (!isa(nodeOp)) - return MemoryEffectOpInterface::hasNoEffect(nodeOp) && nodeOp->hasOneUse(); + return isMemoryEffectFree(nodeOp) && nodeOp->hasOneUse(); // Otherwise, check the number of symbol uses. auto symbolIt = discardableSymNodeUses.find(node); diff --git a/mlir/lib/Transforms/LoopInvariantCodeMotion.cpp b/mlir/lib/Transforms/LoopInvariantCodeMotion.cpp --- a/mlir/lib/Transforms/LoopInvariantCodeMotion.cpp +++ b/mlir/lib/Transforms/LoopInvariantCodeMotion.cpp @@ -13,8 +13,8 @@ #include "mlir/Transforms/Passes.h" #include "mlir/Interfaces/LoopLikeInterface.h" +#include "mlir/Interfaces/SideEffectInterfaces.h" #include "mlir/Transforms/LoopInvariantCodeMotionUtils.h" -#include "mlir/Transforms/SideEffectUtils.h" namespace mlir { #define GEN_PASS_DEF_LOOPINVARIANTCODEMOTION diff --git a/mlir/lib/Transforms/Utils/CMakeLists.txt b/mlir/lib/Transforms/Utils/CMakeLists.txt --- a/mlir/lib/Transforms/Utils/CMakeLists.txt +++ b/mlir/lib/Transforms/Utils/CMakeLists.txt @@ -7,7 +7,6 @@ InliningUtils.cpp LoopInvariantCodeMotionUtils.cpp RegionUtils.cpp - SideEffectUtils.cpp TopologicalSortUtils.cpp ADDITIONAL_HEADER_DIRS @@ -16,5 +15,6 @@ LINK_LIBS PUBLIC MLIRAnalysis MLIRLoopLikeInterface + MLIRSideEffectInterfaces MLIRRewrite ) diff --git a/mlir/lib/Transforms/Utils/LoopInvariantCodeMotionUtils.cpp b/mlir/lib/Transforms/Utils/LoopInvariantCodeMotionUtils.cpp --- a/mlir/lib/Transforms/Utils/LoopInvariantCodeMotionUtils.cpp +++ b/mlir/lib/Transforms/Utils/LoopInvariantCodeMotionUtils.cpp @@ -13,7 +13,7 @@ #include "mlir/Transforms/LoopInvariantCodeMotionUtils.h" #include "mlir/IR/Operation.h" #include "mlir/Interfaces/LoopLikeInterface.h" -#include "mlir/Transforms/SideEffectUtils.h" +#include "mlir/Interfaces/SideEffectInterfaces.h" #include "llvm/Support/Debug.h" #include diff --git a/mlir/lib/Transforms/Utils/SideEffectUtils.cpp b/mlir/lib/Transforms/Utils/SideEffectUtils.cpp deleted file mode 100644 --- a/mlir/lib/Transforms/Utils/SideEffectUtils.cpp +++ /dev/null @@ -1,60 +0,0 @@ -//===- SideEffectUtils.cpp - Side Effect Utils ------------------*- C++ -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// - -#include "mlir/Transforms/SideEffectUtils.h" -#include "mlir/IR/Operation.h" -#include "mlir/Interfaces/SideEffectInterfaces.h" - -using namespace mlir; - -bool mlir::isMemoryEffectFree(Operation *op) { - if (auto memInterface = dyn_cast(op)) { - // If the op has side-effects, it cannot be moved. - if (!memInterface.hasNoEffect()) - return false; - // If the op does not have recursive side effects, then it can be moved. - if (!op->hasTrait()) - return true; - } else if (!op->hasTrait()) { - // Otherwise, if the op does not implement the memory effect interface and - // it does not have recursive side effects, then it cannot be known that the - // op is moveable. - return false; - } - - // Recurse into the regions and ensure that all nested ops can also be moved. - for (Region ®ion : op->getRegions()) - for (Operation &op : region.getOps()) - if (!isMemoryEffectFree(&op)) - return false; - return true; -} - -bool mlir::isSpeculatable(Operation *op) { - auto conditionallySpeculatable = dyn_cast(op); - if (!conditionallySpeculatable) - return false; - - switch (conditionallySpeculatable.getSpeculatability()) { - case Speculation::RecursivelySpeculatable: - for (Region ®ion : op->getRegions()) { - for (Operation &op : region.getOps()) - if (!isSpeculatable(&op)) - return false; - } - return true; - - case Speculation::Speculatable: - return true; - - case Speculation::NotSpeculatable: - return false; - } - - llvm_unreachable("Unhandled enum in mlir::isSpeculatable!"); -} diff --git a/utils/bazel/llvm-project-overlay/mlir/BUILD.bazel b/utils/bazel/llvm-project-overlay/mlir/BUILD.bazel --- a/utils/bazel/llvm-project-overlay/mlir/BUILD.bazel +++ b/utils/bazel/llvm-project-overlay/mlir/BUILD.bazel @@ -1942,6 +1942,7 @@ ":SCFDialect", ":SCFPassIncGen", ":SCFUtils", + ":SideEffectInterfaces", ":Support", ":TensorDialect", ":TensorTransforms", @@ -2553,6 +2554,7 @@ ":ArithDialect", ":FuncDialect", ":IR", + ":SideEffectInterfaces", ":Support", ":ViewLikeInterface", "//llvm:Support", @@ -2855,6 +2857,7 @@ ":FuncDialect", ":IR", ":SCFDialect", + ":SideEffectInterfaces", ":Support", ":Transforms", "//llvm:Support", @@ -3337,6 +3340,7 @@ ":MemRefDialect", ":Pass", ":SCFDialect", + ":SideEffectInterfaces", ":Support", ":TensorDialect", ":Transforms", @@ -3841,6 +3845,7 @@ ":ROCDLToLLVMIRTranslation", ":SCFDialect", ":FuncDialect", + ":SideEffectInterfaces", ":Support", ":Transforms", ":ToLLVMIRTranslation", @@ -5694,6 +5699,7 @@ ":LoopLikeInterface", ":Pass", ":Rewrite", + ":SideEffectInterfaces", ":Support", ":TransformUtils", ":TransformsPassIncGen", @@ -5731,6 +5737,7 @@ ":MemRefDialect", ":Pass", ":SCFDialect", + ":SideEffectInterfaces", ":Support", ":TransformUtils", ":Transforms", @@ -9999,6 +10006,7 @@ ":LoopLikeInterface", ":MemRefDialect", ":Pass", + ":SideEffectInterfaces", ":TensorDialect", ":Transforms", ":ViewLikeInterface",