MLIR  20.0.0git
LivenessAnalysis.h
Go to the documentation of this file.
1 //===- LivenessAnalysis.h - Liveness analysis -------------------*- C++ -*-===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // This file implements liveness analysis using the sparse backward data-flow
10 // analysis framework. Theoretically, liveness analysis assigns liveness to each
11 // (value, program point) pair in the program and it is thus a dense analysis.
12 // However, since values are immutable in MLIR, a sparse analysis, which will
13 // assign liveness to each value in the program, suffices here.
14 //
15 // Liveness analysis has many applications. It can be used to avoid the
16 // computation of extraneous operations that have no effect on the memory or the
17 // final output of a program. It can also be used to optimize register
18 // allocation. Both of these applications help achieve one very important goal:
19 // reducing runtime.
20 //
21 //===----------------------------------------------------------------------===//
22 
23 #ifndef MLIR_ANALYSIS_DATAFLOW_LIVENESSANALYSIS_H
24 #define MLIR_ANALYSIS_DATAFLOW_LIVENESSANALYSIS_H
25 
27 #include <optional>
28 
29 namespace mlir::dataflow {
30 
31 //===----------------------------------------------------------------------===//
32 // Liveness
33 //===----------------------------------------------------------------------===//
34 
35 /// This lattice represents, for a given value, whether or not it is "live".
36 ///
37 /// A value is considered "live" iff it:
38 /// (1) has memory effects OR
39 /// (2) is returned by a public function OR
40 /// (3) is used to compute a value of type (1) or (2).
41 /// It is also to be noted that a value could be of multiple types (1/2/3) at
42 /// the same time.
43 ///
44 /// A value "has memory effects" iff it:
45 /// (1.a) is an operand of an op with memory effects OR
46 /// (1.b) is a non-forwarded branch operand and its branch op could take the
47 /// control to a block that has an op with memory effects OR
48 /// (1.c) is a non-forwarded call operand.
49 ///
50 /// A value `A` is said to be "used to compute" value `B` iff `B` cannot be
51 /// computed in the absence of `A`. Thus, in this implementation, we say that
52 /// value `A` is used to compute value `B` iff:
53 /// (3.a) `B` is a result of an op with operand `A` OR
54 /// (3.b) `A` is used to compute some value `C` and `C` is used to compute
55 /// `B`.
59 
60  void print(raw_ostream &os) const override;
61 
63 
64  ChangeResult meet(const AbstractSparseLattice &other) override;
65 
66  // At the beginning of the analysis, everything is marked "not live" and as
67  // the analysis progresses, values are marked "live" if they are found to be
68  // live.
69  bool isLive = false;
70 };
71 
72 //===----------------------------------------------------------------------===//
73 // LivenessAnalysis
74 //===----------------------------------------------------------------------===//
75 
76 /// An analysis that, by going backwards along the dataflow graph, annotates
77 /// each value with a boolean storing true iff it is "live".
79 public:
81 
82  LogicalResult visitOperation(Operation *op, ArrayRef<Liveness *> operands,
83  ArrayRef<const Liveness *> results) override;
84 
85  void visitBranchOperand(OpOperand &operand) override;
86 
87  void visitCallOperand(OpOperand &operand) override;
88 
89  void setToExitState(Liveness *lattice) override;
90 };
91 
92 //===----------------------------------------------------------------------===//
93 // RunLivenessAnalysis
94 //===----------------------------------------------------------------------===//
95 
96 /// Runs liveness analysis on the IR defined by `op`.
98 public:
100 
102 
103  const Liveness *getLiveness(Value val);
104 
105 private:
106  /// Stores the result of the liveness analysis that was run.
107  DataFlowSolver solver;
108 };
109 
110 } // end namespace mlir::dataflow
111 
112 #endif // MLIR_ANALYSIS_DATAFLOW_LIVENESSANALYSIS_H
#define MLIR_DEFINE_EXPLICIT_INTERNAL_INLINE_TYPE_ID(CLASS_NAME)
Definition: TypeID.h:274
The general data-flow analysis solver.
This class represents an operand of an operation.
Definition: Value.h:267
Operation is the basic unit of execution within MLIR.
Definition: Operation.h:88
This class represents an instance of an SSA value in the MLIR system, representing a computable value...
Definition: Value.h:96
This class represents an abstract lattice.
AbstractSparseLattice(Value value)
Lattices can only be created for values.
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
LogicalResult visitOperation(Operation *op, ArrayRef< Liveness * > operands, ArrayRef< const Liveness * > results) override
For every value, liveness analysis determines whether or not it is "live".
A sparse (backward) data-flow analysis for propagating SSA value lattices backwards across the IR by ...
SparseBackwardDataFlowAnalysis(DataFlowSolver &solver, SymbolTableCollection &symbolTable)
ChangeResult
A result type used to indicate if a change happened.
This lattice represents, for a given value, whether or not it is "live".
void print(raw_ostream &os) const override
Print the contents of the analysis state.
ChangeResult meet(const AbstractSparseLattice &other) override
Meet (intersect) the information in this lattice with 'rhs'.
Runs liveness analysis on the IR defined by op.
const Liveness * getLiveness(Value val)