1*ead75d94SMogball //===- DataFlowFramework.cpp - A generic framework for data-flow analysis -===//
2*ead75d94SMogball //
3*ead75d94SMogball // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4*ead75d94SMogball // See https://llvm.org/LICENSE.txt for license information.
5*ead75d94SMogball // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6*ead75d94SMogball //
7*ead75d94SMogball //===----------------------------------------------------------------------===//
8*ead75d94SMogball
9*ead75d94SMogball #include "mlir/Analysis/DataFlowFramework.h"
10*ead75d94SMogball #include "llvm/Support/Debug.h"
11*ead75d94SMogball
12*ead75d94SMogball #define DEBUG_TYPE "dataflow"
13*ead75d94SMogball #if LLVM_ENABLE_ABI_BREAKING_CHECKS
14*ead75d94SMogball #define DATAFLOW_DEBUG(X) LLVM_DEBUG(X)
15*ead75d94SMogball #else
16*ead75d94SMogball #define DATAFLOW_DEBUG(X)
17*ead75d94SMogball #endif // LLVM_ENABLE_ABI_BREAKING_CHECKS
18*ead75d94SMogball
19*ead75d94SMogball using namespace mlir;
20*ead75d94SMogball
21*ead75d94SMogball //===----------------------------------------------------------------------===//
22*ead75d94SMogball // GenericProgramPoint
23*ead75d94SMogball //===----------------------------------------------------------------------===//
24*ead75d94SMogball
25*ead75d94SMogball GenericProgramPoint::~GenericProgramPoint() = default;
26*ead75d94SMogball
27*ead75d94SMogball //===----------------------------------------------------------------------===//
28*ead75d94SMogball // AnalysisState
29*ead75d94SMogball //===----------------------------------------------------------------------===//
30*ead75d94SMogball
31*ead75d94SMogball AnalysisState::~AnalysisState() = default;
32*ead75d94SMogball
33*ead75d94SMogball //===----------------------------------------------------------------------===//
34*ead75d94SMogball // ProgramPoint
35*ead75d94SMogball //===----------------------------------------------------------------------===//
36*ead75d94SMogball
print(raw_ostream & os) const37*ead75d94SMogball void ProgramPoint::print(raw_ostream &os) const {
38*ead75d94SMogball if (isNull()) {
39*ead75d94SMogball os << "<NULL POINT>";
40*ead75d94SMogball return;
41*ead75d94SMogball }
42*ead75d94SMogball if (auto *programPoint = dyn_cast<GenericProgramPoint *>())
43*ead75d94SMogball return programPoint->print(os);
44*ead75d94SMogball if (auto *op = dyn_cast<Operation *>())
45*ead75d94SMogball return op->print(os);
46*ead75d94SMogball if (auto value = dyn_cast<Value>())
47*ead75d94SMogball return value.print(os);
48*ead75d94SMogball return get<Block *>()->print(os);
49*ead75d94SMogball }
50*ead75d94SMogball
getLoc() const51*ead75d94SMogball Location ProgramPoint::getLoc() const {
52*ead75d94SMogball if (auto *programPoint = dyn_cast<GenericProgramPoint *>())
53*ead75d94SMogball return programPoint->getLoc();
54*ead75d94SMogball if (auto *op = dyn_cast<Operation *>())
55*ead75d94SMogball return op->getLoc();
56*ead75d94SMogball if (auto value = dyn_cast<Value>())
57*ead75d94SMogball return value.getLoc();
58*ead75d94SMogball return get<Block *>()->getParent()->getLoc();
59*ead75d94SMogball }
60*ead75d94SMogball
61*ead75d94SMogball //===----------------------------------------------------------------------===//
62*ead75d94SMogball // DataFlowSolver
63*ead75d94SMogball //===----------------------------------------------------------------------===//
64*ead75d94SMogball
initializeAndRun(Operation * top)65*ead75d94SMogball LogicalResult DataFlowSolver::initializeAndRun(Operation *top) {
66*ead75d94SMogball // Initialize the analyses.
67*ead75d94SMogball for (DataFlowAnalysis &analysis : llvm::make_pointee_range(childAnalyses)) {
68*ead75d94SMogball DATAFLOW_DEBUG(llvm::dbgs()
69*ead75d94SMogball << "Priming analysis: " << analysis.debugName << "\n");
70*ead75d94SMogball if (failed(analysis.initialize(top)))
71*ead75d94SMogball return failure();
72*ead75d94SMogball }
73*ead75d94SMogball
74*ead75d94SMogball // Run the analysis until fixpoint.
75*ead75d94SMogball ProgramPoint point;
76*ead75d94SMogball DataFlowAnalysis *analysis;
77*ead75d94SMogball
78*ead75d94SMogball do {
79*ead75d94SMogball // Exhaust the worklist.
80*ead75d94SMogball while (!worklist.empty()) {
81*ead75d94SMogball std::tie(point, analysis) = worklist.front();
82*ead75d94SMogball worklist.pop();
83*ead75d94SMogball
84*ead75d94SMogball DATAFLOW_DEBUG(llvm::dbgs() << "Invoking '" << analysis->debugName
85*ead75d94SMogball << "' on: " << point << "\n");
86*ead75d94SMogball if (failed(analysis->visit(point)))
87*ead75d94SMogball return failure();
88*ead75d94SMogball }
89*ead75d94SMogball
90*ead75d94SMogball // Iterate until all states are in some initialized state and the worklist
91*ead75d94SMogball // is exhausted.
92*ead75d94SMogball } while (!worklist.empty());
93*ead75d94SMogball
94*ead75d94SMogball return success();
95*ead75d94SMogball }
96*ead75d94SMogball
propagateIfChanged(AnalysisState * state,ChangeResult changed)97*ead75d94SMogball void DataFlowSolver::propagateIfChanged(AnalysisState *state,
98*ead75d94SMogball ChangeResult changed) {
99*ead75d94SMogball if (changed == ChangeResult::Change) {
100*ead75d94SMogball DATAFLOW_DEBUG(llvm::dbgs() << "Propagating update to " << state->debugName
101*ead75d94SMogball << " of " << state->point << "\n"
102*ead75d94SMogball << "Value: " << *state << "\n");
103*ead75d94SMogball for (const WorkItem &item : state->dependents)
104*ead75d94SMogball enqueue(item);
105*ead75d94SMogball state->onUpdate(this);
106*ead75d94SMogball }
107*ead75d94SMogball }
108*ead75d94SMogball
addDependency(AnalysisState * state,DataFlowAnalysis * analysis,ProgramPoint point)109*ead75d94SMogball void DataFlowSolver::addDependency(AnalysisState *state,
110*ead75d94SMogball DataFlowAnalysis *analysis,
111*ead75d94SMogball ProgramPoint point) {
112*ead75d94SMogball auto inserted = state->dependents.insert({point, analysis});
113*ead75d94SMogball (void)inserted;
114*ead75d94SMogball DATAFLOW_DEBUG({
115*ead75d94SMogball if (inserted) {
116*ead75d94SMogball llvm::dbgs() << "Creating dependency between " << state->debugName
117*ead75d94SMogball << " of " << state->point << "\nand " << analysis->debugName
118*ead75d94SMogball << " on " << point << "\n";
119*ead75d94SMogball }
120*ead75d94SMogball });
121*ead75d94SMogball }
122*ead75d94SMogball
123*ead75d94SMogball //===----------------------------------------------------------------------===//
124*ead75d94SMogball // DataFlowAnalysis
125*ead75d94SMogball //===----------------------------------------------------------------------===//
126*ead75d94SMogball
127*ead75d94SMogball DataFlowAnalysis::~DataFlowAnalysis() = default;
128*ead75d94SMogball
DataFlowAnalysis(DataFlowSolver & solver)129*ead75d94SMogball DataFlowAnalysis::DataFlowAnalysis(DataFlowSolver &solver) : solver(solver) {}
130*ead75d94SMogball
addDependency(AnalysisState * state,ProgramPoint point)131*ead75d94SMogball void DataFlowAnalysis::addDependency(AnalysisState *state, ProgramPoint point) {
132*ead75d94SMogball solver.addDependency(state, this, point);
133*ead75d94SMogball }
134*ead75d94SMogball
propagateIfChanged(AnalysisState * state,ChangeResult changed)135*ead75d94SMogball void DataFlowAnalysis::propagateIfChanged(AnalysisState *state,
136*ead75d94SMogball ChangeResult changed) {
137*ead75d94SMogball solver.propagateIfChanged(state, changed);
138*ead75d94SMogball }
139