27#ifndef ENZYME_MLIR_ANALYSIS_DATAFLOW_ACTIVITYANALYSIS_H
28#define ENZYME_MLIR_ANALYSIS_DATAFLOW_ACTIVITYANALYSIS_H
30#include "mlir/Analysis/DataFlow/DenseAnalysis.h"
31#include "mlir/Analysis/DataFlow/SparseAnalysis.h"
32#include "mlir/Analysis/DataFlowFramework.h"
33#include "mlir/IR/Block.h"
34#include "mlir/Interfaces/FunctionInterfaces.h"
35#include "mlir/Interfaces/SideEffectInterfaces.h"
36#include "mlir/Support/LLVM.h"
43using namespace mlir::dataflow;
45class FunctionOpInterface;
103 void print(raw_ostream &os)
const;
104 raw_ostream &
operator<<(raw_ostream &os)
const;
116 using Lattice::Lattice;
124 using AbstractSparseLattice::AbstractSparseLattice;
128 void print(raw_ostream &os)
const override;
143 using SparseForwardDataFlowAnalysis::SparseForwardDataFlowAnalysis;
149 ArrayRef<const enzyme::ForwardValueActivity *> operands,
150 ArrayRef<enzyme::ForwardValueActivity *> results)
override;
154 ArrayRef<const enzyme::ForwardValueActivity *> operands,
155 ArrayRef<enzyme::ForwardValueActivity *> results)
override;
158 ArrayRef<const enzyme::ForwardValueActivity *> operands,
159 ArrayRef<enzyme::ForwardValueActivity *> results);
165 using SparseBackwardDataFlowAnalysis::SparseBackwardDataFlowAnalysis;
177 ArrayRef<BlockArgument> arguments)
override {}
180 ArrayRef<enzyme::BackwardValueActivity *> operands,
181 ArrayRef<const enzyme::BackwardValueActivity *> results);
184 Operation *op, ArrayRef<enzyme::BackwardValueActivity *> operands,
185 ArrayRef<const enzyme::BackwardValueActivity *> results)
override;
188 CallOpInterface call, ArrayRef<enzyme::BackwardValueActivity *> operands,
189 ArrayRef<const enzyme::BackwardValueActivity *> results)
override;
212 return !(*
this == other);
215 ChangeResult
reset();
221 using AbstractDenseLattice::AbstractDenseLattice;
224 ChangeResult
reset();
236 void print(raw_ostream &os)
const override;
237 raw_ostream &
operator<<(raw_ostream &os)
const;
243 DenseMap<DistinctAttr, MemoryActivityState> activityStates;
249 using MemoryActivity::MemoryActivity;
253 return merge(lattice);
259 using MemoryActivity::MemoryActivity;
262 return merge(lattice);
270 ArrayRef<enzyme::Activity> argumentActivity)
272 argumentActivity(argumentActivity) {}
279 CallControlFlowAction action,
293 SmallVector<enzyme::Activity> argumentActivity;
300 SymbolTableCollection &symbolTable,
301 FunctionOpInterface parentOp,
302 ArrayRef<enzyme::Activity> argumentActivity,
303 ArrayRef<enzyme::Activity> returnActivity)
305 argumentActivity(argumentActivity), returnActivity(returnActivity) {}
312 CallControlFlowAction action,
321 FunctionOpInterface parentOp;
322 SmallVector<enzyme::Activity> argumentActivity;
323 SmallVector<enzyme::Activity> returnActivity;
327 ArrayRef<enzyme::Activity> argumentActivity,
328 ArrayRef<enzyme::Activity> returnActivity,
329 bool print =
false,
bool verbose =
false,
330 bool annotate =
false);
ChangeResult meet(const AbstractDenseLattice &lattice) override
ChangeResult meet(const AbstractSparseLattice &other) override
enzyme::ValueActivity getValue() const
void print(raw_ostream &os) const override
void visitCallControlFlowTransfer(CallOpInterface call, CallControlFlowAction action, const BackwardMemoryActivity &after, BackwardMemoryActivity *before) override
DenseBackwardActivityAnalysis(DataFlowSolver &solver, SymbolTableCollection &symbolTable, FunctionOpInterface parentOp, ArrayRef< enzyme::Activity > argumentActivity, ArrayRef< enzyme::Activity > returnActivity)
LogicalResult visitOperation(Operation *op, const BackwardMemoryActivity &after, BackwardMemoryActivity *before) override
void setToExitState(BackwardMemoryActivity *lattice) override
LogicalResult visitOperation(Operation *op, const ForwardMemoryActivity &before, ForwardMemoryActivity *after) override
DenseForwardActivityAnalysis(DataFlowSolver &solver, Block *entryBlock, ArrayRef< enzyme::Activity > argumentActivity)
void setToEntryState(ForwardMemoryActivity *lattice) override
Initialize the entry block with the supplied argument activities.
void visitCallControlFlowTransfer(CallOpInterface call, CallControlFlowAction action, const ForwardMemoryActivity &before, ForwardMemoryActivity *after) override
ChangeResult join(const AbstractDenseLattice &lattice)
Join the activity states.
void print(raw_ostream &os) const override
ChangeResult setActiveIn()
ChangeResult setActiveOut()
bool activeDataFlowsOut(DistinctAttr aliasClass) const
ChangeResult reset()
Clear all modifications.
ChangeResult merge(const AbstractDenseLattice &lattice)
raw_ostream & operator<<(raw_ostream &os) const
bool hasActiveData(DistinctAttr aliasClass) const
void visitExternalCall(CallOpInterface call, ArrayRef< enzyme::BackwardValueActivity * > operands, ArrayRef< const enzyme::BackwardValueActivity * > results) override
void setToExitState(enzyme::BackwardValueActivity *lattice) override
void transfer(Operation *op, ArrayRef< enzyme::BackwardValueActivity * > operands, ArrayRef< const enzyme::BackwardValueActivity * > results)
void visitCallOperand(OpOperand &operand) override
void visitBranchOperand(OpOperand &operand) override
LogicalResult visitOperation(Operation *op, ArrayRef< enzyme::BackwardValueActivity * > operands, ArrayRef< const enzyme::BackwardValueActivity * > results) override
void visitNonControlFlowArguments(RegionSuccessor &successor, ArrayRef< BlockArgument > arguments) override
Sparse activity analysis reasons about activity by traversing forward down the def-use chains startin...
void transfer(Operation *op, ArrayRef< const enzyme::ForwardValueActivity * > operands, ArrayRef< enzyme::ForwardValueActivity * > results)
void setToEntryState(enzyme::ForwardValueActivity *lattice) override
In general, we don't know anything about entry operands.
void visitExternalCall(CallOpInterface call, ArrayRef< const enzyme::ForwardValueActivity * > operands, ArrayRef< enzyme::ForwardValueActivity * > results) override
LogicalResult visitOperation(Operation *op, ArrayRef< const enzyme::ForwardValueActivity * > operands, ArrayRef< enzyme::ForwardValueActivity * > results) override
static ValueActivity join(const ValueActivity &lhs, const ValueActivity &rhs)
ValueActivity(ActivityKind value)
void print(raw_ostream &os) const
static ValueActivity merge(const ValueActivity &lhs, const ValueActivity &rhs)
const ActivityKind & getValue() const
Get the known activity state.
bool operator==(const ValueActivity &rhs) const
static ValueActivity getUnknown()
raw_ostream & operator<<(raw_ostream &os) const
static ValueActivity getConstant()
static ValueActivity getActiveVal()
@ Activity
Names the activity of the argument that follows it.
ActivityKind
From LLVM Enzyme's activity analysis, there are four activity states.
void runDataFlowActivityAnalysis(FunctionOpInterface callee, ArrayRef< enzyme::Activity > argumentActivity, ArrayRef< enzyme::Activity > returnActivity, bool print=false, bool verbose=false, bool annotate=false)
This needs to keep track of three things:
bool activeIn
Whether active data has stored into this memory location.
ChangeResult merge(const MemoryActivityState &other)
bool operator==(const MemoryActivityState &other)
bool operator!=(const MemoryActivityState &other)
bool activeOut
Whether active data was loaded out of this memory location.