1 //===- DenseAnalysis.cpp - Dense data-flow 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/DenseAnalysis.h"
10 #include "mlir/Analysis/DataFlow/DeadCodeAnalysis.h"
11 #include "mlir/Interfaces/CallInterfaces.h"
12 #include "mlir/Interfaces/ControlFlowInterfaces.h"
13
14 using namespace mlir;
15 using namespace mlir::dataflow;
16
17 //===----------------------------------------------------------------------===//
18 // AbstractDenseDataFlowAnalysis
19 //===----------------------------------------------------------------------===//
20
initialize(Operation * top)21 LogicalResult AbstractDenseDataFlowAnalysis::initialize(Operation *top) {
22 // Visit every operation and block.
23 visitOperation(top);
24 for (Region ®ion : top->getRegions()) {
25 for (Block &block : region) {
26 visitBlock(&block);
27 for (Operation &op : block)
28 if (failed(initialize(&op)))
29 return failure();
30 }
31 }
32 return success();
33 }
34
visit(ProgramPoint point)35 LogicalResult AbstractDenseDataFlowAnalysis::visit(ProgramPoint point) {
36 if (auto *op = point.dyn_cast<Operation *>())
37 visitOperation(op);
38 else if (auto *block = point.dyn_cast<Block *>())
39 visitBlock(block);
40 else
41 return failure();
42 return success();
43 }
44
visitOperation(Operation * op)45 void AbstractDenseDataFlowAnalysis::visitOperation(Operation *op) {
46 // If the containing block is not executable, bail out.
47 if (!getOrCreateFor<Executable>(op, op->getBlock())->isLive())
48 return;
49
50 // Get the dense lattice to update.
51 AbstractDenseLattice *after = getLattice(op);
52 if (after->isAtFixpoint())
53 return;
54
55 // If this op implements region control-flow, then control-flow dictates its
56 // transfer function.
57 if (auto branch = dyn_cast<RegionBranchOpInterface>(op))
58 return visitRegionBranchOperation(op, branch, after);
59
60 // If this is a call operation, then join its lattices across known return
61 // sites.
62 if (auto call = dyn_cast<CallOpInterface>(op)) {
63 const auto *predecessors = getOrCreateFor<PredecessorState>(op, call);
64 // If not all return sites are known, then conservatively assume we can't
65 // reason about the data-flow.
66 if (!predecessors->allPredecessorsKnown())
67 return reset(after);
68 for (Operation *predecessor : predecessors->getKnownPredecessors())
69 join(after, *getLatticeFor(op, predecessor));
70 return;
71 }
72
73 // Get the dense state before the execution of the op.
74 const AbstractDenseLattice *before;
75 if (Operation *prev = op->getPrevNode())
76 before = getLatticeFor(op, prev);
77 else
78 before = getLatticeFor(op, op->getBlock());
79 // If the incoming lattice is uninitialized, bail out.
80 if (before->isUninitialized())
81 return;
82
83 // Invoke the operation transfer function.
84 visitOperationImpl(op, *before, after);
85 }
86
visitBlock(Block * block)87 void AbstractDenseDataFlowAnalysis::visitBlock(Block *block) {
88 // If the block is not executable, bail out.
89 if (!getOrCreateFor<Executable>(block, block)->isLive())
90 return;
91
92 // Get the dense lattice to update.
93 AbstractDenseLattice *after = getLattice(block);
94 if (after->isAtFixpoint())
95 return;
96
97 // The dense lattices of entry blocks are set by region control-flow or the
98 // callgraph.
99 if (block->isEntryBlock()) {
100 // Check if this block is the entry block of a callable region.
101 auto callable = dyn_cast<CallableOpInterface>(block->getParentOp());
102 if (callable && callable.getCallableRegion() == block->getParent()) {
103 const auto *callsites = getOrCreateFor<PredecessorState>(block, callable);
104 // If not all callsites are known, conservatively mark all lattices as
105 // having reached their pessimistic fixpoints.
106 if (!callsites->allPredecessorsKnown())
107 return reset(after);
108 for (Operation *callsite : callsites->getKnownPredecessors()) {
109 // Get the dense lattice before the callsite.
110 if (Operation *prev = callsite->getPrevNode())
111 join(after, *getLatticeFor(block, prev));
112 else
113 join(after, *getLatticeFor(block, callsite->getBlock()));
114 }
115 return;
116 }
117
118 // Check if we can reason about the control-flow.
119 if (auto branch = dyn_cast<RegionBranchOpInterface>(block->getParentOp()))
120 return visitRegionBranchOperation(block, branch, after);
121
122 // Otherwise, we can't reason about the data-flow.
123 return reset(after);
124 }
125
126 // Join the state with the state after the block's predecessors.
127 for (Block::pred_iterator it = block->pred_begin(), e = block->pred_end();
128 it != e; ++it) {
129 // Skip control edges that aren't executable.
130 Block *predecessor = *it;
131 if (!getOrCreateFor<Executable>(
132 block, getProgramPoint<CFGEdge>(predecessor, block))
133 ->isLive())
134 continue;
135
136 // Merge in the state from the predecessor's terminator.
137 join(after, *getLatticeFor(block, predecessor->getTerminator()));
138 }
139 }
140
visitRegionBranchOperation(ProgramPoint point,RegionBranchOpInterface branch,AbstractDenseLattice * after)141 void AbstractDenseDataFlowAnalysis::visitRegionBranchOperation(
142 ProgramPoint point, RegionBranchOpInterface branch,
143 AbstractDenseLattice *after) {
144 // Get the terminator predecessors.
145 const auto *predecessors = getOrCreateFor<PredecessorState>(point, point);
146 assert(predecessors->allPredecessorsKnown() &&
147 "unexpected unresolved region successors");
148
149 for (Operation *op : predecessors->getKnownPredecessors()) {
150 const AbstractDenseLattice *before;
151 // If the predecessor is the parent, get the state before the parent.
152 if (op == branch) {
153 if (Operation *prev = op->getPrevNode())
154 before = getLatticeFor(point, prev);
155 else
156 before = getLatticeFor(point, op->getBlock());
157
158 // Otherwise, get the state after the terminator.
159 } else {
160 before = getLatticeFor(point, op);
161 }
162 join(after, *before);
163 }
164 }
165
166 const AbstractDenseLattice *
getLatticeFor(ProgramPoint dependent,ProgramPoint point)167 AbstractDenseDataFlowAnalysis::getLatticeFor(ProgramPoint dependent,
168 ProgramPoint point) {
169 AbstractDenseLattice *state = getLattice(point);
170 addDependency(state, dependent);
171 return state;
172 }
173