/home/arjun/llvm-project/mlir/lib/Interfaces/SideEffectInterfaces.cpp
| Line | Count | Source (jump to first uncovered line) | 
| 1 |  | //===- SideEffectInterfaces.cpp - SideEffects in MLIR ---------------------===// | 
| 2 |  | // | 
| 3 |  | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | 
| 4 |  | // See https://llvm.org/LICENSE.txt for license information. | 
| 5 |  | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | 
| 6 |  | // | 
| 7 |  | //===----------------------------------------------------------------------===// | 
| 8 |  |  | 
| 9 |  | #include "mlir/Interfaces/SideEffectInterfaces.h" | 
| 10 |  |  | 
| 11 |  | using namespace mlir; | 
| 12 |  |  | 
| 13 |  | //===----------------------------------------------------------------------===// | 
| 14 |  | // SideEffect Interfaces | 
| 15 |  | //===----------------------------------------------------------------------===// | 
| 16 |  |  | 
| 17 |  | /// Include the definitions of the side effect interfaces. | 
| 18 |  | #include "mlir/Interfaces/SideEffectInterfaces.cpp.inc" | 
| 19 |  |  | 
| 20 |  | //===----------------------------------------------------------------------===// | 
| 21 |  | // MemoryEffects | 
| 22 |  | //===----------------------------------------------------------------------===// | 
| 23 |  |  | 
| 24 | 0 | bool MemoryEffects::Effect::classof(const SideEffects::Effect *effect) { | 
| 25 | 0 |   return isa<Allocate>(effect) || isa<Free>(effect) || isa<Read>(effect) || | 
| 26 | 0 |          isa<Write>(effect); | 
| 27 | 0 | } | 
| 28 |  |  | 
| 29 |  | //===----------------------------------------------------------------------===// | 
| 30 |  | // SideEffect Utilities | 
| 31 |  | //===----------------------------------------------------------------------===// | 
| 32 |  |  | 
| 33 | 0 | bool mlir::isOpTriviallyDead(Operation *op) { | 
| 34 | 0 |   return op->use_empty() && wouldOpBeTriviallyDead(op); | 
| 35 | 0 | } | 
| 36 |  |  | 
| 37 |  | /// Internal implementation of `mlir::wouldOpBeTriviallyDead` that also | 
| 38 |  | /// considers terminator operations as dead if they have no side effects. This | 
| 39 |  | /// allows for marking region operations as trivially dead without always being | 
| 40 |  | /// conservative of terminators. | 
| 41 | 0 | static bool wouldOpBeTriviallyDeadImpl(Operation *rootOp) { | 
| 42 | 0 |   // The set of operations to consider when checking for side effects. | 
| 43 | 0 |   SmallVector<Operation *, 1> effectingOps(1, rootOp); | 
| 44 | 0 |   while (!effectingOps.empty()) { | 
| 45 | 0 |     Operation *op = effectingOps.pop_back_val(); | 
| 46 | 0 | 
 | 
| 47 | 0 |     // If the operation has recursive effects, push all of the nested operations | 
| 48 | 0 |     // on to the stack to consider. | 
| 49 | 0 |     bool hasRecursiveEffects = op->hasTrait<OpTrait::HasRecursiveSideEffects>(); | 
| 50 | 0 |     if (hasRecursiveEffects) { | 
| 51 | 0 |       for (Region ®ion : op->getRegions()) { | 
| 52 | 0 |         for (auto &block : region) { | 
| 53 | 0 |           for (auto &nestedOp : block) | 
| 54 | 0 |             effectingOps.push_back(&nestedOp); | 
| 55 | 0 |         } | 
| 56 | 0 |       } | 
| 57 | 0 |     } | 
| 58 | 0 | 
 | 
| 59 | 0 |     // If the op has memory effects, try to characterize them to see if the op | 
| 60 | 0 |     // is trivially dead here. | 
| 61 | 0 |     if (auto effectInterface = dyn_cast<MemoryEffectOpInterface>(op)) { | 
| 62 | 0 |       // Check to see if this op either has no effects, or only allocates/reads | 
| 63 | 0 |       // memory. | 
| 64 | 0 |       SmallVector<MemoryEffects::EffectInstance, 1> effects; | 
| 65 | 0 |       effectInterface.getEffects(effects); | 
| 66 | 0 |       if (!llvm::all_of(effects, [op](const MemoryEffects::EffectInstance &it) { | 
| 67 | 0 |             // We can drop allocations if the value is a result of the | 
| 68 | 0 |             // operation. | 
| 69 | 0 |             if (isa<MemoryEffects::Allocate>(it.getEffect())) | 
| 70 | 0 |               return it.getValue() && it.getValue().getDefiningOp() == op; | 
| 71 | 0 |             // Otherwise, the effect must be a read. | 
| 72 | 0 |             return isa<MemoryEffects::Read>(it.getEffect()); | 
| 73 | 0 |           })) { | 
| 74 | 0 |         return false; | 
| 75 | 0 |       } | 
| 76 | 0 |       continue; | 
| 77 | 0 | 
 | 
| 78 | 0 |       // Otherwise, if the op has recursive side effects we can treat the | 
| 79 | 0 |       // operation itself as having no effects. | 
| 80 | 0 |     } else if (hasRecursiveEffects) { | 
| 81 | 0 |       continue; | 
| 82 | 0 |     } | 
| 83 | 0 |  | 
| 84 | 0 |     // If there were no effect interfaces, we treat this op as conservatively | 
| 85 | 0 |     // having effects. | 
| 86 | 0 |     return false; | 
| 87 | 0 |   } | 
| 88 | 0 | 
 | 
| 89 | 0 |   // If we get here, none of the operations had effects that prevented marking | 
| 90 | 0 |   // 'op' as dead. | 
| 91 | 0 |   return true; | 
| 92 | 0 | } | 
| 93 |  |  | 
| 94 | 0 | bool mlir::wouldOpBeTriviallyDead(Operation *op) { | 
| 95 | 0 |   if (!op->isKnownNonTerminator()) | 
| 96 | 0 |     return false; | 
| 97 | 0 |   return wouldOpBeTriviallyDeadImpl(op); | 
| 98 | 0 | } |