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 &region : 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