19#include <mlir/Analysis/DataFlow/ConstantPropagationAnalysis.h>
20#include <mlir/Analysis/DataFlow/DeadCodeAnalysis.h>
21#include <mlir/Analysis/DataFlow/DenseAnalysis.h>
22#include <mlir/Analysis/DataFlowFramework.h>
24#include <llvm/ADT/MapVector.h>
25#include <llvm/ADT/SetVector.h>
26#include <llvm/Support/ErrorHandling.h>
32#define GEN_PASS_DEF_PREDECESSORPRINTERPASS
36raw_ostream &
printRegionless(raw_ostream &os, Operation *op,
bool withParent =
false) {
38 llvm::raw_string_ostream ss(s);
41 os <<
'<' << fnOp.getFullyQualifiedName() <<
">:";
43 os <<
"<(no parent function op)>:";
46 op->print(ss, OpPrintingFlags().skipRegions());
56 llvm::MapVector<Operation *, llvm::SmallSetVector<Operation *, 4>> predecessors;
59 using AbstractDenseLattice::AbstractDenseLattice;
61 ChangeResult
visit(Operation *op, Operation *pred) {
62 bool newlyInserted = predecessors[op].insert(pred);
63 return newlyInserted ? ChangeResult::Change : ChangeResult::NoChange;
66 ChangeResult
join(
const AbstractDenseLattice &rhs)
override {
69 llvm::report_fatal_error(
"wrong lattice type provided for join");
71 ChangeResult r = ChangeResult::NoChange;
72 for (
const auto &[op, preds] : other->predecessors) {
73 for (
auto *pred : preds) {
80 ChangeResult
meet(
const AbstractDenseLattice & )
override {
81 llvm::report_fatal_error(
"meet operation is not supported for PredecessorLattice");
82 return ChangeResult::NoChange;
85 void print(raw_ostream &os)
const override {
86 if (predecessors.empty()) {
90 for (
const auto &[k, v] : predecessors) {
93 llvm::interleave(v, [&os](Operation *p) {
103 :
public mlir::dataflow::DenseForwardDataFlowAnalysis<PredecessorLattice> {
110 return dyn_cast<ProgramPoint *>(l.getAnchor());
115 ChangeResult result = after->
join(before);
116 ProgramPoint *pointBefore = getProgramPointBefore(op);
117 auto *predState = getOrCreate<mlir::dataflow::PredecessorState>(pointBefore);
118 if (!predState->getKnownPredecessors().empty()) {
119 for (Operation *pred : predState->getKnownPredecessors()) {
120 result |= after->
visit(op, pred);
124 Operation *pred = pointBefore->isBlockStart() ? op->getParentOp() : pointBefore->getPrevOp();
125 result |= after->
visit(op, pred);
131 using Base = DenseForwardDataFlowAnalysis<PredecessorLattice>;
138 ChangeResult result = updateLattice(op, before, after);
139 propagateIfChanged(after, result);
144 CallOpInterface call, mlir::dataflow::CallControlFlowAction action,
150 if (action == mlir::dataflow::CallControlFlowAction::EnterCallee) {
159 else if (action == mlir::dataflow::CallControlFlowAction::ExitCallee) {
163 ensure(beforeCall,
"could not get prior lattice");
164 ChangeResult r = after->
join(before);
166 r |= updateLattice(call, *beforeCall, after);
167 propagateIfChanged(after, r);
173 else if (action == mlir::dataflow::CallControlFlowAction::ExternalCallee) {
184 RegionBranchOpInterface branch, std::optional<unsigned> ,
204 using Base = PredecessorPrinterPassBase<PassImpl>;
207 void runOnOperation()
override {
208 markAllAnalysesPreserved();
211 raw_ostream &os =
toStream(outputStream);
213 DataFlowSolver solver;
214 if (preRunRequiredAnalyses) {
222 solver.load<PredecessorAnalysis>(os);
223 LogicalResult res = solver.initializeAndRun(getOperation());
226 llvm::report_fatal_error(
"PredecessorAnalysis failed.");
229 getOperation()->walk<WalkOrder::PreOrder>([&](function::FuncDefOp fnOp) {
230 Region &fnBody = fnOp.getFunctionBody();
231 if (fnBody.empty()) {
232 return WalkResult::skip();
235 ProgramPoint *point = solver.getProgramPointAfter(fnBody.back().getTerminator());
236 PredecessorLattice *finalLattice = solver.getOrCreateState<PredecessorLattice>(point);
238 printRegionless(os, fnOp.getOperation()) <<
":\n" << *finalLattice <<
'\n';
240 return WalkResult::skip();
void setToEntryState(PredecessorLattice *lattice) override
void visitCallControlFlowTransfer(CallOpInterface call, mlir::dataflow::CallControlFlowAction action, const PredecessorLattice &before, PredecessorLattice *after) override
DenseForwardDataFlowAnalysis< PredecessorLattice > Base
LogicalResult visitOperation(Operation *op, const PredecessorLattice &before, PredecessorLattice *after) override
PredecessorAnalysis(DataFlowSolver &s, raw_ostream &ro)
void visitRegionBranchControlFlowTransfer(RegionBranchOpInterface branch, std::optional< unsigned >, std::optional< unsigned >, const PredecessorLattice &before, PredecessorLattice *after) override
ChangeResult visit(Operation *op, Operation *pred)
ChangeResult join(const AbstractDenseLattice &rhs) override
ChangeResult meet(const AbstractDenseLattice &) override
void print(raw_ostream &os) const override
void loadRequiredAnalyses(DataFlowSolver &solver)
LogicalResult loadAndRunRequiredAnalyses(DataFlowSolver &solver, Operation *op)
llvm::raw_ostream & toStream(OutputStream val)
void ensure(bool condition, const llvm::Twine &errMsg)
raw_ostream & printRegionless(raw_ostream &os, Operation *op, bool withParent=false)
Prints op without region.