From 0ddba0bd59c337f16b51a00cb205ecfda46f97fa Mon Sep 17 00:00:00 2001 From: River Riddle Date: Thu, 12 Mar 2020 14:06:41 -0700 Subject: [mlir][SideEffects] Replace HasNoSideEffect with the memory effect interfaces. HasNoSideEffect can now be implemented using the MemoryEffectInterface, removing the need to check multiple things for the same information. This also removes an easy foot-gun for users as 'Operation::hasNoSideEffect' would ignore operations that dynamically, or recursively, have no side effects. This also leads to an immediate improvement in some of the existing users, such as DCE, now that they have access to more information. Differential Revision: https://reviews.llvm.org/D76036 --- mlir/lib/Interfaces/SideEffects.cpp | 67 +++++++++++++++++++++++++++++++++++++ 1 file changed, 67 insertions(+) (limited to 'mlir/lib/Interfaces/SideEffects.cpp') diff --git a/mlir/lib/Interfaces/SideEffects.cpp b/mlir/lib/Interfaces/SideEffects.cpp index da43239..53406c6 100644 --- a/mlir/lib/Interfaces/SideEffects.cpp +++ b/mlir/lib/Interfaces/SideEffects.cpp @@ -25,3 +25,70 @@ bool MemoryEffects::Effect::classof(const SideEffects::Effect *effect) { return isa(effect) || isa(effect) || isa(effect) || isa(effect); } + +//===----------------------------------------------------------------------===// +// SideEffect Utilities +//===----------------------------------------------------------------------===// + +bool mlir::isOpTriviallyDead(Operation *op) { + return op->use_empty() && wouldOpBeTriviallyDead(op); +} + +/// Internal implementation of `mlir::wouldOpBeTriviallyDead` that also +/// considers terminator operations as dead if they have no side effects. This +/// allows for marking region operations as trivially dead without always being +/// conservative of terminators. +static bool wouldOpBeTriviallyDeadImpl(Operation *rootOp) { + // The set of operations to consider when checking for side effects. + SmallVector effectingOps(1, rootOp); + while (!effectingOps.empty()) { + Operation *op = effectingOps.pop_back_val(); + + // If the operation has recursive effects, push all of the nested operations + // on to the stack to consider. + bool hasRecursiveEffects = op->hasTrait(); + if (hasRecursiveEffects) { + for (Region ®ion : op->getRegions()) { + for (auto &block : region) { + for (auto &nestedOp : block) + effectingOps.push_back(&nestedOp); + } + } + } + + // If the op has memory effects, try to characterize them to see if the op + // is trivially dead here. + if (auto effectInterface = dyn_cast(op)) { + // Check to see if this op either has no effects, or only allocates/reads + // memory. + SmallVector effects; + effectInterface.getEffects(effects); + if (!llvm::all_of(effects, [](const auto &it) { + return isa(it.getEffect()) || + isa(it.getEffect()); + })) { + return false; + } + continue; + + // Otherwise, if the op has recursive side effects we can treat the + // operation itself as having no effects. + } else if (hasRecursiveEffects) { + continue; + } + + // If there were no effect interfaces, we treat this op as conservatively + // having effects. + return false; + } + + // If we get here, none of the operations had effects that prevented marking + // 'op' as dead. + return true; +} + +bool mlir::wouldOpBeTriviallyDead(Operation *op) { + if (!op->isKnownNonTerminator()) + return false; + return wouldOpBeTriviallyDeadImpl(op); +} -- cgit v1.1