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 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 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 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 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 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 * 167 AbstractDenseDataFlowAnalysis::getLatticeFor(ProgramPoint dependent, 168 ProgramPoint point) { 169 AbstractDenseLattice *state = getLattice(point); 170 addDependency(state, dependent); 171 return state; 172 } 173