13#include <llvm/Support/DebugLog.h>
23#define DEBUG_TYPE "liveness-analysis"
33 os << (
isLive ?
"live" :
"not live");
43 const auto *otherLiveness =
reinterpret_cast<const Liveness *
>(&other);
82 LDBG() <<
"[visitOperation] Enter: "
86 LDBG() <<
"[visitOperation] Operation has memory effects or is "
87 "return-like, marking operands live";
88 for (
auto *operand : operands) {
89 LDBG() <<
" [visitOperation] Marking operand live: " << operand <<
" ("
90 << operand->isLive <<
")";
96 bool foundLiveResult =
false;
98 if (r->isLive && !foundLiveResult) {
99 LDBG() <<
"[visitOperation] Found live result, "
100 "meeting all operands with result: "
104 for (
Liveness *operand : operands) {
105 LDBG() <<
" [visitOperation] Meeting operand: " << operand
106 <<
" with result: " << r;
109 foundLiveResult =
true;
111 LDBG() <<
"[visitOperation] Adding dependency for result: " << r
120 LDBG() <<
"Visiting branch operand: " << operand.
get()
125 assert((isa<RegionBranchOpInterface>(op) || isa<BranchOpInterface>(op) ||
126 isa<RegionBranchTerminatorOpInterface>(op)) &&
127 "expected the op to be `RegionBranchOpInterface`, "
128 "`BranchOpInterface` or `RegionBranchTerminatorOpInterface`");
145 isa<RegionBranchTerminatorOpInterface>(op) ? op->
getParentOp() : op;
150 LDBG() <<
"Visiting operation for non-forwarded branch operand: "
156 LDBG() <<
"Visiting call operand: " << operand.
get()
157 <<
" in op: " << *operand.
getOwner();
160 assert(isa<CallOpInterface>(operand.
getOwner()) &&
161 "expected the op to implement `CallOpInterface`");
170 LDBG() <<
"Marking call operand live: " << operand.
get();
177 LDBG() <<
"visitNonControlFlowArguments visit the region: #"
182 llvm::map_to_vector(arguments, valuesToLattices);
184 llvm::map_to_vector(parentOp->
getResults(), valuesToLattices);
186 for (
Liveness *resultLattice : parentResultLattices) {
187 if (resultLattice->isLive) {
188 for (
Liveness *argumentLattice : argumentLattices) {
189 LDBG() <<
"make lattice: " << argumentLattice <<
" live";
199 LDBG() <<
"setToExitState for lattice: " << lattice;
201 LDBG() <<
"Lattice already live, nothing to do";
205 LDBG() <<
"Marking lattice live due to exit state";
215 LDBG() <<
"Constructing RunLivenessAnalysis for op: " << op->
getName();
220 LDBG() <<
"Initializing and running solver";
221 (
void)solver.initializeAndRun(op);
222 LDBG() <<
"RunLivenessAnalysis initialized for op: " << op->
getName()
223 <<
" check on unreachable code now:";
230 LDBG() <<
"Result: " <<
result.index() <<
" of "
232 <<
" has no liveness info (unreachable), mark dead";
236 for (
auto &block : region) {
237 for (
auto blockArg : llvm::enumerate(block.getArguments())) {
240 LDBG() <<
"Block argument: " << blockArg.index() <<
" of "
242 <<
" has no liveness info, mark dead";
243 solver.getOrCreateState<
Liveness>(blockArg.value());
251 return solver.lookupState<
Liveness>(val);
static LogicalResult visitOp(Operation *op, OpBuilder &builder)
void addDependency(AnalysisState *state, ProgramPoint *point)
Create a dependency between the given analysis state and lattice anchor on this analysis.
void propagateIfChanged(AnalysisState *state, ChangeResult changed)
Propagate an update to a state if it changed.
ProgramPoint * getProgramPointAfter(Operation *op)
IRValueT get() const
Return the current value being used by this operand.
This class represents an operand of an operation.
Set of flags used to control the behavior of the various IR print methods (e.g.
A wrapper class that allows for printing an operation with a set of flags, useful to act as a "stream...
Operation is the basic unit of execution within MLIR.
Operation * getParentOp()
Returns the closest surrounding operation that contains this operation or nullptr if this is a top-le...
OperationName getName()
The name of an operation is the key identifier for it.
MutableArrayRef< Region > getRegions()
Returns the regions held by this operation.
std::enable_if_t< llvm::function_traits< std::decay_t< FnT > >::num_args==1, RetT > walk(FnT &&callback)
Walk the operation by calling the callback for each nested operation (including this one),...
result_range getResults()
This class represents a successor of a region.
Region * getSuccessor() const
Return the given region successor.
unsigned getRegionNumber()
Return the number of this region in the parent operation.
Operation * getParentOp()
Return the parent operation this region is attached to.
This class represents a collection of SymbolTables.
This class represents an instance of an SSA value in the MLIR system, representing a computable value...
void meet(AbstractSparseLattice *lhs, const AbstractSparseLattice &rhs)
Join the lattice element and propagate and update if it changed.
An analysis that, by going backwards along the dataflow graph, annotates each value with a boolean st...
void setToExitState(Liveness *lattice) override
Set the given lattice element(s) at control flow exit point(s).
void visitBranchOperand(OpOperand &operand) override
void visitCallOperand(OpOperand &operand) override
void visitNonControlFlowArguments(RegionSuccessor &successor, ArrayRef< BlockArgument > arguments) override
LogicalResult visitOperation(Operation *op, ArrayRef< Liveness * > operands, ArrayRef< const Liveness * > results) override
For every value, liveness analysis determines whether or not it is "live".
Liveness * getLatticeElement(Value value) override
Operation * getOwner() const
Return the owner of this operand.
void loadBaselineAnalyses(DataFlowSolver &solver)
Populates a DataFlowSolver with analyses that are required to ensure user-defined analyses are run pr...
Include the generated interface declarations.
ChangeResult
A result type used to indicate if a change happened.
bool wouldOpBeTriviallyDead(Operation *op)
Return true if the given operation would be dead if unused, and has no side effects on memory that wo...
This lattice represents, for a given value, whether or not it is "live".
void print(raw_ostream &os) const override
AbstractSparseLattice(Value value)
Lattices can only be created for values.
ChangeResult meet(const AbstractSparseLattice &other) override
Meet (intersect) the information in this lattice with 'rhs'.
RunLivenessAnalysis(Operation *op)
const Liveness * getLiveness(Value val)