49 for (mlir::Region ®ion : top->getRegions()) {
50 for (mlir::Block &block : region) {
51 (void)solver.getOrCreateState<mlir::dataflow::Executable>(&block)->setToLive();
52 for (mlir::Operation &oper : block) {
66 for (Region ®ion : top->getRegions()) {
67 for (Block &block : region) {
69 for (Operation &op : block) {
80 if (
auto *op = llvm::dyn_cast_if_present<Operation *>(point)) {
82 }
else if (
auto *block = llvm::dyn_cast_if_present<Block *>(point)) {
92void AbstractDenseForwardDataFlowAnalysis::visitCallOperation(
98 if (!getSolverConfig().isInterprocedural() ||
99 (mlir::succeeded(callable) && !callable->get().getCallableRegion())) {
105 SmallVector<Operation *> predecessors;
106 auto fnOp = callable.value().get();
107 fnOp.walk([&predecessors](
ReturnOp ret)
mutable { predecessors.push_back(ret); });
111 if (predecessors.empty()) {
115 for (Operation *predecessor : predecessors) {
133 call, CallControlFlowAction::ExitCallee, *latticeAtCalleeReturn, latticeAfterCall
140 if (!getOrCreateFor<Executable>(op, op->getBlock())->isLive()) {
149 if (Operation *prev = op->getPrevNode()) {
157 if (
auto branch = dyn_cast<RegionBranchOpInterface>(op)) {
163 if (
auto call = dyn_cast<CallOpInterface>(op)) {
164 return visitCallOperation(call, *before, after);
173void AbstractDenseForwardDataFlowAnalysis::visitBlock(Block *block) {
175 if (!getOrCreateFor<Executable>(block, block)->isLive()) {
184 if (block->isEntryBlock()) {
186 auto callable = dyn_cast<CallableOpInterface>(block->getParentOp());
187 if (callable && callable.getCallableRegion() == block->getParent()) {
188 if (!getSolverConfig().isInterprocedural()) {
193 ensure(mlir::succeeded(moduleOpRes),
"could not get root module from callable");
195 SmallVector<Operation *> callsites;
196 moduleOpRes->walk([
this, &callable, &callsites](CallOp call)
mutable {
198 if (mlir::succeeded(calledFnRes) &&
199 calledFnRes->get().getCallableRegion() == callable.getCallableRegion()) {
200 callsites.push_back(call);
204 for (Operation *callsite : callsites) {
207 if (Operation *prev = callsite->getPrevNode()) {
214 llvm::cast<CallOpInterface>(callsite), CallControlFlowAction::EnterCallee, *before,
222 if (
auto branch = dyn_cast<RegionBranchOpInterface>(block->getParentOp())) {
231 for (Block::pred_iterator it = block->pred_begin(), e = block->pred_end(); it != e; ++it) {
233 Block *predecessor = *it;
234 if (!getOrCreateFor<Executable>(block, getProgramPoint<CFGEdge>(predecessor, block))
249 Operation *op =
nullptr;
250 if (point.is<Block *>()) {
251 op = point.get<Block *>()->getParentOp();
252 }
else if (point.is<Operation *>()) {
253 op = point.get<Operation *>();
259 if (Operation *prev = op->getPrevNode()) {
283 std::optional<unsigned> regionFrom =
284 op == branch ? std::optional<unsigned>() : op->getBlock()->getParent()->getRegionNumber();
285 if (
auto *toBlock = point.dyn_cast<Block *>()) {
286 unsigned regionTo = toBlock->getParent()->getRegionNumber();
289 assert(point.get<Operation *>() == branch &&
"expected to be visiting the branch itself");
292 if (op->getParentOp() == branch || op == branch) {
294 branch, regionFrom, std::nullopt, *before, after
297 join(after, *before);
306 addDependency(state, dependent);
virtual void visitCallControlFlowTransfer(mlir::CallOpInterface call, CallControlFlowAction action, const AbstractDenseLattice &before, AbstractDenseLattice *after)
Propagate the dense lattice forward along the call control flow edge, which can be either entering or...
virtual void visitRegionBranchControlFlowTransfer(mlir::RegionBranchOpInterface branch, std::optional< unsigned > regionFrom, std::optional< unsigned > regionTo, const AbstractDenseLattice &before, AbstractDenseLattice *after)
Propagate the dense lattice forward along the control flow edge from regionFrom to regionTo regions o...
mlir::FailureOr< SymbolLookupResult< T > > resolveCallable(mlir::SymbolTableCollection &symbolTable, mlir::CallOpInterface call)
Based on mlir::CallOpInterface::resolveCallable, but using LLZK lookup helpers.