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