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