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>
34#define GEN_PASS_DECL_PREDECESSORPRINTERPASS
35#define GEN_PASS_DEF_PREDECESSORPRINTERPASS
39raw_ostream &
printRegionless(raw_ostream &os, Operation *op,
bool withParent =
false) {
41 llvm::raw_string_ostream ss(s);
43 if (
auto fnOp = op->getParentOfType<
FuncDefOp>()) {
44 os <<
'<' << fnOp.getFullyQualifiedName() <<
">:";
46 os <<
"<(no parent function op)>:";
49 op->print(ss, mlir::OpPrintingFlags().skipRegions());
59 llvm::MapVector<Operation *, llvm::SmallSetVector<Operation *, 4>> predecessors;
62 using AbstractDenseLattice::AbstractDenseLattice;
64 ChangeResult
visit(Operation *op, Operation *pred) {
65 bool newlyInserted = predecessors[op].insert(pred);
66 return newlyInserted ? ChangeResult::Change : ChangeResult::NoChange;
69 ChangeResult
join(
const AbstractDenseLattice &rhs)
override {
72 llvm::report_fatal_error(
"wrong lattice type provided for join");
74 ChangeResult r = ChangeResult::NoChange;
75 for (
const auto &[op, preds] : other->predecessors) {
76 for (
auto *pred : preds) {
83 ChangeResult
meet(
const AbstractDenseLattice & )
override {
84 llvm::report_fatal_error(
"meet operation is not supported for PredecessorLattice");
85 return ChangeResult::NoChange;
88 void print(raw_ostream &os)
const override {
89 if (predecessors.empty()) {
93 for (
const auto &[k, v] : predecessors) {
96 llvm::interleave(v, [&os](Operation *p) {
106 :
public mlir::dataflow::DenseForwardDataFlowAnalysis<PredecessorLattice> {
113 return dyn_cast<ProgramPoint *>(l.getAnchor());
118 ChangeResult result = after->
join(before);
119 ProgramPoint *pointBefore = getProgramPointBefore(op);
120 auto *predState = getOrCreate<mlir::dataflow::PredecessorState>(pointBefore);
121 if (!predState->getKnownPredecessors().empty()) {
122 for (Operation *pred : predState->getKnownPredecessors()) {
123 result |= after->
visit(op, pred);
127 Operation *pred = pointBefore->isBlockStart() ? op->getParentOp() : pointBefore->getPrevOp();
128 result |= after->
visit(op, pred);
134 using Base = DenseForwardDataFlowAnalysis<PredecessorLattice>;
141 ChangeResult result = updateLattice(op, before, after);
142 propagateIfChanged(after, result);
147 CallOpInterface call, mlir::dataflow::CallControlFlowAction action,
153 if (action == mlir::dataflow::CallControlFlowAction::EnterCallee) {
162 else if (action == mlir::dataflow::CallControlFlowAction::ExitCallee) {
166 ensure(beforeCall,
"could not get prior lattice");
167 ChangeResult r = after->
join(before);
169 r |= updateLattice(call, *beforeCall, after);
170 propagateIfChanged(after, r);
176 else if (action == mlir::dataflow::CallControlFlowAction::ExternalCallee) {
187 RegionBranchOpInterface branch, std::optional<unsigned> ,
207 markAllAnalysesPreserved();
212 DataFlowSolver solver;
222 LogicalResult res = solver.initializeAndRun(getOperation());
225 llvm::report_fatal_error(
"PredecessorAnalysis failed.");
228 getOperation()->walk<WalkOrder::PreOrder>([&](
FuncDefOp fnOp) {
229 Region &fnBody = fnOp.getFunctionBody();
230 if (fnBody.empty()) {
231 return WalkResult::skip();
234 ProgramPoint *point = solver.getProgramPointAfter(fnBody.back().getTerminator());
237 printRegionless(os, fnOp.getOperation()) <<
":\n" << *finalLattice <<
'\n';
239 return WalkResult::skip();
245 return std::make_unique<PredecessorPrinterPass>();
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 runOnOperation() override
PredecessorPrinterPassBase()
::mlir::Pass::Option<::llzk::OutputStream > outputStream
::mlir::Pass::Option< bool > preRunRequiredAnalyses
void loadRequiredAnalyses(DataFlowSolver &solver)
LogicalResult loadAndRunRequiredAnalyses(DataFlowSolver &solver, Operation *op)
std::unique_ptr< mlir::Pass > createPredecessorPrinterPass()
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.