xref: /llvm-project/mlir/lib/Analysis/DataFlowFramework.cpp (revision 3a439e2caf0bb545ee451df1de5b02ea068140f7)
1ead75d94SMogball //===- DataFlowFramework.cpp - A generic framework for data-flow analysis -===//
2ead75d94SMogball //
3ead75d94SMogball // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4ead75d94SMogball // See https://llvm.org/LICENSE.txt for license information.
5ead75d94SMogball // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6ead75d94SMogball //
7ead75d94SMogball //===----------------------------------------------------------------------===//
8ead75d94SMogball 
9ead75d94SMogball #include "mlir/Analysis/DataFlowFramework.h"
10a5a90865SMehdi Amini #include "mlir/IR/Location.h"
11a5a90865SMehdi Amini #include "mlir/IR/Operation.h"
12a5a90865SMehdi Amini #include "mlir/IR/Value.h"
13*3a439e2cSHongren Zheng #include "llvm/ADT/ScopeExit.h"
14a5a90865SMehdi Amini #include "llvm/ADT/iterator.h"
15a5a90865SMehdi Amini #include "llvm/Config/abi-breaking.h"
16a5a90865SMehdi Amini #include "llvm/Support/Casting.h"
17ead75d94SMogball #include "llvm/Support/Debug.h"
18a5a90865SMehdi Amini #include "llvm/Support/raw_ostream.h"
19ead75d94SMogball 
20ead75d94SMogball #define DEBUG_TYPE "dataflow"
21ead75d94SMogball #if LLVM_ENABLE_ABI_BREAKING_CHECKS
22ead75d94SMogball #define DATAFLOW_DEBUG(X) LLVM_DEBUG(X)
23ead75d94SMogball #else
24ead75d94SMogball #define DATAFLOW_DEBUG(X)
25ead75d94SMogball #endif // LLVM_ENABLE_ABI_BREAKING_CHECKS
26ead75d94SMogball 
27ead75d94SMogball using namespace mlir;
28ead75d94SMogball 
29ead75d94SMogball //===----------------------------------------------------------------------===//
30b6603e1bSdonald chen // GenericLatticeAnchor
31ead75d94SMogball //===----------------------------------------------------------------------===//
32ead75d94SMogball 
33b6603e1bSdonald chen GenericLatticeAnchor::~GenericLatticeAnchor() = default;
34ead75d94SMogball 
35ead75d94SMogball //===----------------------------------------------------------------------===//
36ead75d94SMogball // AnalysisState
37ead75d94SMogball //===----------------------------------------------------------------------===//
38ead75d94SMogball 
39ead75d94SMogball AnalysisState::~AnalysisState() = default;
40ead75d94SMogball 
414b3f251bSdonald chen void AnalysisState::addDependency(ProgramPoint *dependent,
426a666737SZhixun Tan                                   DataFlowAnalysis *analysis) {
436a666737SZhixun Tan   auto inserted = dependents.insert({dependent, analysis});
446a666737SZhixun Tan   (void)inserted;
456a666737SZhixun Tan   DATAFLOW_DEBUG({
466a666737SZhixun Tan     if (inserted) {
476a666737SZhixun Tan       llvm::dbgs() << "Creating dependency between " << debugName << " of "
48b6603e1bSdonald chen                    << anchor << "\nand " << debugName << " on " << dependent
496a666737SZhixun Tan                    << "\n";
506a666737SZhixun Tan     }
516a666737SZhixun Tan   });
526a666737SZhixun Tan }
536a666737SZhixun Tan 
548a918c54SAlex Zinenko void AnalysisState::dump() const { print(llvm::errs()); }
558a918c54SAlex Zinenko 
56ead75d94SMogball //===----------------------------------------------------------------------===//
574b3f251bSdonald chen // ProgramPoint
58ead75d94SMogball //===----------------------------------------------------------------------===//
59ead75d94SMogball 
60ead75d94SMogball void ProgramPoint::print(raw_ostream &os) const {
61ead75d94SMogball   if (isNull()) {
62ead75d94SMogball     os << "<NULL POINT>";
63ead75d94SMogball     return;
64ead75d94SMogball   }
654b3f251bSdonald chen   if (!isBlockStart()) {
664b3f251bSdonald chen     os << "<after operation>:";
674b3f251bSdonald chen     return getPrevOp()->print(os, OpPrintingFlags().skipRegions());
68b6603e1bSdonald chen   }
694b3f251bSdonald chen   os << "<before operation>:";
704b3f251bSdonald chen   return getNextOp()->print(os, OpPrintingFlags().skipRegions());
71ead75d94SMogball }
72ead75d94SMogball 
734b3f251bSdonald chen //===----------------------------------------------------------------------===//
744b3f251bSdonald chen // LatticeAnchor
754b3f251bSdonald chen //===----------------------------------------------------------------------===//
764b3f251bSdonald chen 
77b6603e1bSdonald chen void LatticeAnchor::print(raw_ostream &os) const {
78b6603e1bSdonald chen   if (isNull()) {
79b6603e1bSdonald chen     os << "<NULL POINT>";
80b6603e1bSdonald chen     return;
81b6603e1bSdonald chen   }
82b6603e1bSdonald chen   if (auto *LatticeAnchor = llvm::dyn_cast<GenericLatticeAnchor *>(*this))
83b6603e1bSdonald chen     return LatticeAnchor->print(os);
84b6603e1bSdonald chen   if (auto value = llvm::dyn_cast<Value>(*this)) {
85b6603e1bSdonald chen     return value.print(os, OpPrintingFlags().skipRegions());
86b6603e1bSdonald chen   }
87b6603e1bSdonald chen 
884f4e2abbSKazu Hirata   return llvm::cast<ProgramPoint *>(*this)->print(os);
89b6603e1bSdonald chen }
90b6603e1bSdonald chen 
91b6603e1bSdonald chen Location LatticeAnchor::getLoc() const {
92b6603e1bSdonald chen   if (auto *LatticeAnchor = llvm::dyn_cast<GenericLatticeAnchor *>(*this))
93b6603e1bSdonald chen     return LatticeAnchor->getLoc();
9468f58812STres Popp   if (auto value = llvm::dyn_cast<Value>(*this))
95ead75d94SMogball     return value.getLoc();
96b6603e1bSdonald chen 
974f4e2abbSKazu Hirata   ProgramPoint *pp = llvm::cast<ProgramPoint *>(*this);
984b3f251bSdonald chen   if (!pp->isBlockStart())
994b3f251bSdonald chen     return pp->getPrevOp()->getLoc();
1004b3f251bSdonald chen   return pp->getBlock()->getParent()->getLoc();
101ead75d94SMogball }
102ead75d94SMogball 
103ead75d94SMogball //===----------------------------------------------------------------------===//
104ead75d94SMogball // DataFlowSolver
105ead75d94SMogball //===----------------------------------------------------------------------===//
106ead75d94SMogball 
107ead75d94SMogball LogicalResult DataFlowSolver::initializeAndRun(Operation *top) {
108*3a439e2cSHongren Zheng   // Enable enqueue to the worklist.
109*3a439e2cSHongren Zheng   isRunning = true;
110*3a439e2cSHongren Zheng   auto guard = llvm::make_scope_exit([&]() { isRunning = false; });
111*3a439e2cSHongren Zheng 
112ead75d94SMogball   // Initialize the analyses.
113ead75d94SMogball   for (DataFlowAnalysis &analysis : llvm::make_pointee_range(childAnalyses)) {
114ead75d94SMogball     DATAFLOW_DEBUG(llvm::dbgs()
115ead75d94SMogball                    << "Priming analysis: " << analysis.debugName << "\n");
116ead75d94SMogball     if (failed(analysis.initialize(top)))
117ead75d94SMogball       return failure();
118ead75d94SMogball   }
119ead75d94SMogball 
120ead75d94SMogball   // Run the analysis until fixpoint.
121ead75d94SMogball   do {
122ead75d94SMogball     // Exhaust the worklist.
123ead75d94SMogball     while (!worklist.empty()) {
1249fa59e76SBenjamin Kramer       auto [point, analysis] = worklist.front();
125ead75d94SMogball       worklist.pop();
126ead75d94SMogball 
127ead75d94SMogball       DATAFLOW_DEBUG(llvm::dbgs() << "Invoking '" << analysis->debugName
128ead75d94SMogball                                   << "' on: " << point << "\n");
129ead75d94SMogball       if (failed(analysis->visit(point)))
130ead75d94SMogball         return failure();
131ead75d94SMogball     }
132ead75d94SMogball 
133ead75d94SMogball     // Iterate until all states are in some initialized state and the worklist
134ead75d94SMogball     // is exhausted.
135ead75d94SMogball   } while (!worklist.empty());
136ead75d94SMogball 
137ead75d94SMogball   return success();
138ead75d94SMogball }
139ead75d94SMogball 
140ead75d94SMogball void DataFlowSolver::propagateIfChanged(AnalysisState *state,
141ead75d94SMogball                                         ChangeResult changed) {
142*3a439e2cSHongren Zheng   assert(isRunning &&
143*3a439e2cSHongren Zheng          "DataFlowSolver is not running, should not use propagateIfChanged");
144ead75d94SMogball   if (changed == ChangeResult::Change) {
145ead75d94SMogball     DATAFLOW_DEBUG(llvm::dbgs() << "Propagating update to " << state->debugName
146b6603e1bSdonald chen                                 << " of " << state->anchor << "\n"
147ead75d94SMogball                                 << "Value: " << *state << "\n");
148ead75d94SMogball     state->onUpdate(this);
149ead75d94SMogball   }
150ead75d94SMogball }
151ead75d94SMogball 
152ead75d94SMogball //===----------------------------------------------------------------------===//
153ead75d94SMogball // DataFlowAnalysis
154ead75d94SMogball //===----------------------------------------------------------------------===//
155ead75d94SMogball 
156ead75d94SMogball DataFlowAnalysis::~DataFlowAnalysis() = default;
157ead75d94SMogball 
158ead75d94SMogball DataFlowAnalysis::DataFlowAnalysis(DataFlowSolver &solver) : solver(solver) {}
159ead75d94SMogball 
1604b3f251bSdonald chen void DataFlowAnalysis::addDependency(AnalysisState *state,
1614b3f251bSdonald chen                                      ProgramPoint *point) {
1626a666737SZhixun Tan   state->addDependency(point, this);
163ead75d94SMogball }
164ead75d94SMogball 
165ead75d94SMogball void DataFlowAnalysis::propagateIfChanged(AnalysisState *state,
166ead75d94SMogball                                           ChangeResult changed) {
167ead75d94SMogball   solver.propagateIfChanged(state, changed);
168ead75d94SMogball }
169