diff --git a/mlir/include/mlir/Interfaces/SideEffectInterfaces.h b/mlir/include/mlir/Interfaces/SideEffectInterfaces.h index a2e55f36671c..f9cd96e9762e 100644 --- a/mlir/include/mlir/Interfaces/SideEffectInterfaces.h +++ b/mlir/include/mlir/Interfaces/SideEffectInterfaces.h @@ -251,9 +251,10 @@ struct Write : public Effect::Base {}; //===----------------------------------------------------------------------===// /// Returns true if `op` has only an effect of type `EffectTy` (and of no other -/// type) on `value`. +/// type) on `value`. If no value is provided, simply check if effects of that +/// type and only of that type are present. template -bool hasSingleEffect(Operation *op, Value value); +bool hasSingleEffect(Operation *op, Value value = nullptr); /// Return true if the given operation is unused, and has no side effects on /// memory that prevent erasing. diff --git a/mlir/lib/Dialect/Affine/Analysis/AffineAnalysis.cpp b/mlir/lib/Dialect/Affine/Analysis/AffineAnalysis.cpp index 4e8952da9de6..3a0a11535605 100644 --- a/mlir/lib/Dialect/Affine/Analysis/AffineAnalysis.cpp +++ b/mlir/lib/Dialect/Affine/Analysis/AffineAnalysis.cpp @@ -21,6 +21,7 @@ #include "mlir/IR/AffineExprVisitor.h" #include "mlir/IR/BuiltinOps.h" #include "mlir/IR/IntegerSet.h" +#include "mlir/Interfaces/SideEffectInterfaces.h" #include "mlir/Interfaces/ViewLikeInterface.h" #include "llvm/ADT/TypeSwitch.h" #include "llvm/Support/Debug.h" @@ -114,12 +115,6 @@ bool mlir::isLoopParallel(AffineForOp forOp, return isLoopMemoryParallel(forOp); } -/// Returns true if `op` is an alloc-like op, i.e., one allocating memrefs. -static bool isAllocLikeOp(Operation *op) { - auto memEffects = dyn_cast(op); - return memEffects && memEffects.hasEffect(); -} - /// Returns true if `v` is allocated locally to `enclosingOp` -- i.e., it is /// allocated by an operation nested within `enclosingOp`. static bool isLocallyDefined(Value v, Operation *enclosingOp) { @@ -127,7 +122,8 @@ static bool isLocallyDefined(Value v, Operation *enclosingOp) { if (!defOp) return false; - if (isAllocLikeOp(defOp) && enclosingOp->isProperAncestor(defOp)) + if (hasSingleEffect(defOp, v) && + enclosingOp->isProperAncestor(defOp)) return true; // Aliasing ops. @@ -153,7 +149,7 @@ bool mlir::isLoopMemoryParallel(AffineForOp forOp) { if (!isLocallyDefined(writeOp.getMemRef(), forOp)) loadAndStoreOps.push_back(op); } else if (!isa(op) && - !isAllocLikeOp(op) && + !hasSingleEffect(op) && !MemoryEffectOpInterface::hasNoEffect(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). diff --git a/mlir/lib/Interfaces/SideEffectInterfaces.cpp b/mlir/lib/Interfaces/SideEffectInterfaces.cpp index 563d86432f7b..1a1970db3522 100644 --- a/mlir/lib/Interfaces/SideEffectInterfaces.cpp +++ b/mlir/lib/Interfaces/SideEffectInterfaces.cpp @@ -99,9 +99,10 @@ bool mlir::hasSingleEffect(Operation *op, Value value) { memOp.getEffects(effects); bool hasSingleEffectOnVal = false; // Iterate through `effects` and check if an effect of type `EffectTy` and - // only of that type is present. + // only of that type is present. A `value` to check the effect on may or may + // not have been provided. for (auto &effect : effects) { - if (effect.getValue() != value) + if (value && effect.getValue() != value) continue; hasSingleEffectOnVal = isa(effect.getEffect()); if (!hasSingleEffectOnVal)