//===- SideEffectInterfaces.cpp - SideEffects in MLIR ---------------------===// // // 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/Interfaces/SideEffectInterfaces.h" using namespace mlir; //===----------------------------------------------------------------------===// // SideEffect Interfaces //===----------------------------------------------------------------------===// /// Include the definitions of the side effect interfaces. #include "mlir/Interfaces/SideEffectInterfaces.cpp.inc" //===----------------------------------------------------------------------===// // MemoryEffects //===----------------------------------------------------------------------===// bool MemoryEffects::Effect::classof(const SideEffects::Effect *effect) { return 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, [op](const MemoryEffects::EffectInstance &it) { // We can drop allocations if the value is a result of the // operation. if (isa(it.getEffect())) return it.getValue() && it.getValue().getDefiningOp() == op; // Otherwise, the effect must be a read. return 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); }