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,
/// `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
//===----------------------------------------------------------------------===//
+++ /dev/null
-//===- 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
#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"
// terminator is found. Gather all the combiner ops along the way in
// topological order.
while (!combinerOp->mightHaveTrait<OpTrait::IsTerminator>()) {
- 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);
MLIRMemRefDialect
MLIRPass
MLIRSupport
+ MLIRSideEffectInterfaces
MLIRTransforms
)
#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"
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();
loadAndStoreOps.push_back(op);
} else if (!isa<AffineForOp, AffineYieldOp, AffineIfOp>(op) &&
!hasSingleEffect<MemoryEffects::Allocate>(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();
MLIRCallInterfaces
MLIRControlFlowInterfaces
MLIRInferTypeOpInterface
+ MLIRSideEffectInterfaces
MLIRPresburger
MLIRSCFDialect
)
#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"
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<ToTensorOp, ToMemrefOp>(op))
MLIRMemRefDialect
MLIRPass
MLIRTensorDialect
+ MLIRSideEffectInterfaces
MLIRTransforms
MLIRViewLikeInterface
)
MLIRMemRefDialect
MLIRPass
MLIRSCFDialect
+ MLIRSideEffectInterfaces
MLIRSupport
MLIRTransformUtils
)
#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"
static bool isTerminator(Operation *op) {
return op->mightHaveTrait<OpTrait::IsTerminator>();
}
-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.
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 "
MLIRPass
MLIRSCFDialect
MLIRSCFUtils
+ MLIRSideEffectInterfaces
MLIRSupport
MLIRTensorDialect
MLIRTensorTransforms
#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
continue;
}
// TODO: Handle region side effects properly.
- noSideEffects &=
- MemoryEffectOpInterface::hasNoEffect(&op) && op.getNumRegions() == 0;
+ noSideEffects &= isMemoryEffectFree(&op) && op.getNumRegions() == 0;
}
for (ArrayRef<ParallelOp> ploops : ploopChains) {
for (int i = 0, e = ploops.size(); i + 1 < e; ++i)
MLIRFuncDialect
MLIRIR
MLIRSCFDialect
+ MLIRSideEffectInterfaces
MLIRSupport
MLIRTransforms
)
#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"
}
// Skip if op has side effects.
// TODO: loads to immutable memory regions are ok.
- if (!MemoryEffectOpInterface::hasNoEffect(&op)) {
+ if (!isMemoryEffectFree(&op)) {
status = failure();
continue;
}
MLIRLinalgDialect
MLIRMemRefDialect
MLIRSCFDialect
+ MLIRSideEffectInterfaces
MLIRTransforms
MLIRVectorDialect
MLIRVectorInterfaces
#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 <utility>
#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"
return false;
return wouldOpBeTriviallyDeadImpl(op);
}
+
+bool mlir::isMemoryEffectFree(Operation *op) {
+ if (auto memInterface = dyn_cast<MemoryEffectOpInterface>(op)) {
+ if (!memInterface.hasNoEffect())
+ return false;
+ // If the op does not have recursive side effects, then it is memory effect
+ // free.
+ if (!op->hasTrait<OpTrait::HasRecursiveMemoryEffects>())
+ return true;
+ } else if (!op->hasTrait<OpTrait::HasRecursiveMemoryEffects>()) {
+ // 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 are memory effect
+ // free.
+ 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<ConditionallySpeculatable>(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!");
+}
MLIRCopyOpInterface
MLIRLoopLikeInterface
MLIRPass
+ MLIRSideEffectInterfaces
MLIRSupport
MLIRTransformUtils
)
// 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<MemoryEffectOpInterface>(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
#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
// If the parent operation isn't a symbol, simply check normal SSA deadness.
Operation *nodeOp = node->getCallableRegion()->getParentOp();
if (!isa<SymbolOpInterface>(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);
// If this isn't a symbol node, check for side-effects and SSA use count.
Operation *nodeOp = node->getCallableRegion()->getParentOp();
if (!isa<SymbolOpInterface>(nodeOp))
- return MemoryEffectOpInterface::hasNoEffect(nodeOp) && nodeOp->hasOneUse();
+ return isMemoryEffectFree(nodeOp) && nodeOp->hasOneUse();
// Otherwise, check the number of symbol uses.
auto symbolIt = discardableSymNodeUses.find(node);
#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
InliningUtils.cpp
LoopInvariantCodeMotionUtils.cpp
RegionUtils.cpp
- SideEffectUtils.cpp
TopologicalSortUtils.cpp
ADDITIONAL_HEADER_DIRS
LINK_LIBS PUBLIC
MLIRAnalysis
MLIRLoopLikeInterface
+ MLIRSideEffectInterfaces
MLIRRewrite
)
#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 <queue>
+++ /dev/null
-//===- 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<MemoryEffectOpInterface>(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<OpTrait::HasRecursiveMemoryEffects>())
- return true;
- } else if (!op->hasTrait<OpTrait::HasRecursiveMemoryEffects>()) {
- // 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<ConditionallySpeculatable>(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!");
-}
// CHECK-SAME: memref<1xindex>, memref<3xindex>, memref<?xindex>, memref<?xindex>, memref<?xf64>
// CHECK-DAG: %[[C0:.*]] = arith.constant 0 : index
// CHECK-DAG: %[[C1:.*]] = arith.constant 1 : index
-// CHECK-DAG: %[[F0:.*]] = arith.constant 0.{{0*}}e+00 : f64
// CHECK: %[[T0:.*]] = memref.alloc() : memref<1xindex>
// CHECK: %[[T1:.*]] = memref.alloc() : memref<3xindex>
// CHECK: %[[T2:.*]] = memref.alloc() : memref<16xindex>
// CHECK: linalg.fill ins(%[[C0]] : index) outs(%[[T4]] : memref<16xindex>)
// CHECK: %[[T6:.*]] = memref.alloc() : memref<16xf64>
// CHECK: %[[T7:.*]] = memref.cast %[[T6]] : memref<16xf64> to memref<?xf64>
-// CHECK: linalg.fill ins(%[[F0]] : f64) outs(%[[T6]] : memref<16xf64>)
+// CHECK: linalg.fill ins(%{{.*}} : f64) outs(%[[T6]] : memref<16xf64>)
// CHECK: linalg.fill ins(%[[C0]] : index) outs(%[[T1]] : memref<3xindex>)
// CHECK: memref.store %[[A]], %[[T0]][%[[C0]]] : memref<1xindex>
// CHECK: %[[P0:.*]] = sparse_tensor.push_back %[[T1]], %[[T3]]
":SCFDialect",
":SCFPassIncGen",
":SCFUtils",
+ ":SideEffectInterfaces",
":Support",
":TensorDialect",
":TensorTransforms",
":ArithDialect",
":FuncDialect",
":IR",
+ ":SideEffectInterfaces",
":Support",
":ViewLikeInterface",
"//llvm:Support",
":FuncDialect",
":IR",
":SCFDialect",
+ ":SideEffectInterfaces",
":Support",
":Transforms",
"//llvm:Support",
":MemRefDialect",
":Pass",
":SCFDialect",
+ ":SideEffectInterfaces",
":Support",
":TensorDialect",
":Transforms",
":ROCDLToLLVMIRTranslation",
":SCFDialect",
":FuncDialect",
+ ":SideEffectInterfaces",
":Support",
":Transforms",
":ToLLVMIRTranslation",
":LoopLikeInterface",
":Pass",
":Rewrite",
+ ":SideEffectInterfaces",
":Support",
":TransformUtils",
":TransformsPassIncGen",
":MemRefDialect",
":Pass",
":SCFDialect",
+ ":SideEffectInterfaces",
":Support",
":TransformUtils",
":Transforms",
":LoopLikeInterface",
":MemRefDialect",
":Pass",
+ ":SideEffectInterfaces",
":TensorDialect",
":Transforms",
":ViewLikeInterface",