1 //===- TestDeadCodeAnalysis.cpp - Test dead code analysis -----------------===// 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/Analysis/DataFlow/ConstantPropagationAnalysis.h" 10 #include "mlir/Analysis/DataFlow/DeadCodeAnalysis.h" 11 #include "mlir/IR/Matchers.h" 12 #include "mlir/Pass/Pass.h" 13 14 using namespace mlir; 15 using namespace mlir::dataflow; 16 17 /// Print the liveness of every block, control-flow edge, and the predecessors 18 /// of all regions, callables, and calls. 19 static void printAnalysisResults(DataFlowSolver &solver, Operation *op, 20 raw_ostream &os) { 21 op->walk([&](Operation *op) { 22 auto tag = op->getAttrOfType<StringAttr>("tag"); 23 if (!tag) 24 return; 25 os << tag.getValue() << ":\n"; 26 for (Region ®ion : op->getRegions()) { 27 os << " region #" << region.getRegionNumber() << "\n"; 28 for (Block &block : region) { 29 os << " "; 30 block.printAsOperand(os); 31 os << " = "; 32 auto *live = solver.lookupState<Executable>(&block); 33 if (live) 34 os << *live; 35 else 36 os << "dead"; 37 os << "\n"; 38 for (Block *pred : block.getPredecessors()) { 39 os << " from "; 40 pred->printAsOperand(os); 41 os << " = "; 42 auto *live = solver.lookupState<Executable>( 43 solver.getProgramPoint<CFGEdge>(pred, &block)); 44 if (live) 45 os << *live; 46 else 47 os << "dead"; 48 os << "\n"; 49 } 50 } 51 if (!region.empty()) { 52 auto *preds = solver.lookupState<PredecessorState>(®ion.front()); 53 if (preds) 54 os << "region_preds: " << *preds << "\n"; 55 } 56 } 57 auto *preds = solver.lookupState<PredecessorState>(op); 58 if (preds) 59 os << "op_preds: " << *preds << "\n"; 60 }); 61 } 62 63 namespace { 64 /// This is a simple analysis that implements a transfer function for constant 65 /// operations. 66 struct ConstantAnalysis : public DataFlowAnalysis { 67 using DataFlowAnalysis::DataFlowAnalysis; 68 69 LogicalResult initialize(Operation *top) override { 70 WalkResult result = top->walk([&](Operation *op) { 71 if (op->hasTrait<OpTrait::ConstantLike>()) 72 if (failed(visit(op))) 73 return WalkResult::interrupt(); 74 return WalkResult::advance(); 75 }); 76 return success(!result.wasInterrupted()); 77 } 78 79 LogicalResult visit(ProgramPoint point) override { 80 Operation *op = point.get<Operation *>(); 81 Attribute value; 82 if (matchPattern(op, m_Constant(&value))) { 83 auto *constant = getOrCreate<Lattice<ConstantValue>>(op->getResult(0)); 84 propagateIfChanged( 85 constant, constant->join(ConstantValue(value, op->getDialect()))); 86 } 87 return success(); 88 } 89 }; 90 91 /// This is a simple pass that runs dead code analysis with no constant value 92 /// provider. It marks everything as live. 93 struct TestDeadCodeAnalysisPass 94 : public PassWrapper<TestDeadCodeAnalysisPass, OperationPass<>> { 95 MLIR_DEFINE_EXPLICIT_INTERNAL_INLINE_TYPE_ID(TestDeadCodeAnalysisPass) 96 97 StringRef getArgument() const override { return "test-dead-code-analysis"; } 98 99 void runOnOperation() override { 100 Operation *op = getOperation(); 101 102 DataFlowSolver solver; 103 solver.load<DeadCodeAnalysis>(); 104 solver.load<ConstantAnalysis>(); 105 if (failed(solver.initializeAndRun(op))) 106 return signalPassFailure(); 107 printAnalysisResults(solver, op, llvm::errs()); 108 } 109 }; 110 } // end anonymous namespace 111 112 namespace mlir { 113 namespace test { 114 void registerTestDeadCodeAnalysisPass() { 115 PassRegistration<TestDeadCodeAnalysisPass>(); 116 } 117 } // end namespace test 118 } // end namespace mlir 119