Skip to content

Commit

Permalink
[mlir] [dataflow] Refactoring the definition of program points in dat…
Browse files Browse the repository at this point in the history
…a flow analysis (llvm#105656)

This patch distinguishes between program points and lattice anchors in
data flow analysis, where lattice anchors represent locations where a
lattice can be attached, while program points denote points in program
execution.

Related discussions:
https://discourse.llvm.org/t/rfc-unify-the-semantics-of-program-points/80671/8
  • Loading branch information
cxy-1993 authored and dmpolukhin committed Sep 2, 2024
1 parent d9523b8 commit 1323129
Show file tree
Hide file tree
Showing 13 changed files with 237 additions and 204 deletions.
16 changes: 8 additions & 8 deletions mlir/include/mlir/Analysis/DataFlow/DeadCodeAnalysis.h
Original file line number Diff line number Diff line change
Expand Up @@ -35,21 +35,21 @@ namespace dataflow {
//===----------------------------------------------------------------------===//

/// This is a simple analysis state that represents whether the associated
/// program point (either a block or a control-flow edge) is live.
/// lattice anchor (either a block or a control-flow edge) is live.
class Executable : public AnalysisState {
public:
using AnalysisState::AnalysisState;

/// Set the state of the program point to live.
/// Set the state of the lattice anchor to live.
ChangeResult setToLive();

/// Get whether the program point is live.
/// Get whether the lattice anchor is live.
bool isLive() const { return live; }

/// Print the liveness.
void print(raw_ostream &os) const override;

/// When the state of the program point is changed to live, re-invoke
/// When the state of the lattice anchor is changed to live, re-invoke
/// subscribed analyses on the operations in the block and on the block
/// itself.
void onUpdate(DataFlowSolver *solver) const override;
Expand All @@ -60,8 +60,8 @@ class Executable : public AnalysisState {
}

private:
/// Whether the program point is live. Optimistically assume that the program
/// point is dead.
/// Whether the lattice anchor is live. Optimistically assume that the lattice
/// anchor is dead.
bool live = false;

/// A set of analyses that should be updated when this state changes.
Expand Down Expand Up @@ -140,10 +140,10 @@ class PredecessorState : public AnalysisState {
// CFGEdge
//===----------------------------------------------------------------------===//

/// This program point represents a control-flow edge between a block and one
/// This lattice anchor represents a control-flow edge between a block and one
/// of its successors.
class CFGEdge
: public GenericProgramPointBase<CFGEdge, std::pair<Block *, Block *>> {
: public GenericLatticeAnchorBase<CFGEdge, std::pair<Block *, Block *>> {
public:
using Base::Base;

Expand Down
37 changes: 19 additions & 18 deletions mlir/include/mlir/Analysis/DataFlow/DenseAnalysis.h
Original file line number Diff line number Diff line change
Expand Up @@ -91,15 +91,16 @@ class AbstractDenseForwardDataFlowAnalysis : public DataFlowAnalysis {
const AbstractDenseLattice &before,
AbstractDenseLattice *after) = 0;

/// Get the dense lattice after the execution of the given program point.
virtual AbstractDenseLattice *getLattice(ProgramPoint point) = 0;
/// Get the dense lattice after the execution of the given lattice anchor.
virtual AbstractDenseLattice *getLattice(LatticeAnchor anchor) = 0;

/// Get the dense lattice after the execution of the given program point and
/// add it as a dependency to a program point. That is, every time the lattice
/// after point is updated, the dependent program point must be visited, and
/// the newly triggered visit might update the lattice after dependent.
/// add it as a dependency to a lattice anchor. That is, every time the
/// lattice after anchor is updated, the dependent program point must be
/// visited, and the newly triggered visit might update the lattice after
/// dependent.
const AbstractDenseLattice *getLatticeFor(ProgramPoint dependent,
ProgramPoint point);
LatticeAnchor anchor);

/// Set the dense lattice at control flow entry point and propagate an update
/// if it changed.
Expand Down Expand Up @@ -249,9 +250,9 @@ class DenseForwardDataFlowAnalysis
}

protected:
/// Get the dense lattice after this program point.
LatticeT *getLattice(ProgramPoint point) override {
return getOrCreate<LatticeT>(point);
/// Get the dense lattice on this lattice anchor.
LatticeT *getLattice(LatticeAnchor anchor) override {
return getOrCreate<LatticeT>(anchor);
}

/// Set the dense lattice at control flow entry point and propagate an update
Expand Down Expand Up @@ -331,16 +332,16 @@ class AbstractDenseBackwardDataFlowAnalysis : public DataFlowAnalysis {
const AbstractDenseLattice &after,
AbstractDenseLattice *before) = 0;

/// Get the dense lattice before the execution of the program point. That is,
/// Get the dense lattice before the execution of the lattice anchor. That is,
/// before the execution of the given operation or after the execution of the
/// block.
virtual AbstractDenseLattice *getLattice(ProgramPoint point) = 0;
virtual AbstractDenseLattice *getLattice(LatticeAnchor anchor) = 0;

/// Get the dense lattice before the execution of the program point `point`
/// and declare that the `dependent` program point must be updated every time
/// `point` is.
/// Get the dense lattice before the execution of the program point in
/// `anchor` and declare that the `dependent` program point must be updated
/// every time `point` is.
const AbstractDenseLattice *getLatticeFor(ProgramPoint dependent,
ProgramPoint point);
LatticeAnchor anchor);

/// Set the dense lattice before at the control flow exit point and propagate
/// the update if it changed.
Expand Down Expand Up @@ -500,9 +501,9 @@ class DenseBackwardDataFlowAnalysis
}

protected:
/// Get the dense lattice at the given program point.
LatticeT *getLattice(ProgramPoint point) override {
return getOrCreate<LatticeT>(point);
/// Get the dense lattice at the given lattice anchor.
LatticeT *getLattice(LatticeAnchor anchor) override {
return getOrCreate<LatticeT>(anchor);
}

/// Set the dense lattice at control flow exit point (after the terminator)
Expand Down
2 changes: 1 addition & 1 deletion mlir/include/mlir/Analysis/DataFlow/IntegerRangeAnalysis.h
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ class IntegerRangeAnalysis
/// At an entry point, we cannot reason about interger value ranges.
void setToEntryState(IntegerValueRangeLattice *lattice) override {
propagateIfChanged(lattice, lattice->join(IntegerValueRange::getMaxRange(
lattice->getPoint())));
lattice->getAnchor())));
}

/// Visit an operation. Invoke the transfer function on each operation that
Expand Down
8 changes: 4 additions & 4 deletions mlir/include/mlir/Analysis/DataFlow/SparseAnalysis.h
Original file line number Diff line number Diff line change
Expand Up @@ -36,8 +36,8 @@ class AbstractSparseLattice : public AnalysisState {
/// Lattices can only be created for values.
AbstractSparseLattice(Value value) : AnalysisState(value) {}

/// Return the program point this lattice is located at.
Value getPoint() const { return AnalysisState::getPoint().get<Value>(); }
/// Return the value this lattice is located at.
Value getAnchor() const { return AnalysisState::getAnchor().get<Value>(); }

/// Join the information contained in 'rhs' into this lattice. Returns
/// if the value of the lattice changed.
Expand Down Expand Up @@ -86,8 +86,8 @@ class Lattice : public AbstractSparseLattice {
public:
using AbstractSparseLattice::AbstractSparseLattice;

/// Return the program point this lattice is located at.
Value getPoint() const { return point.get<Value>(); }
/// Return the value this lattice is located at.
Value getAnchor() const { return anchor.get<Value>(); }

/// Return the value held by this lattice. This requires that the value is
/// initialized.
Expand Down
Loading

0 comments on commit 1323129

Please sign in to comment.