Skip to content

Commit 3c2a620

Browse files
committed
[NFC][mlir][DataFlow] Add visitBlockTransfer hook to dense analyses
Add a customizable `visitBlockTransfer` method to dense forward and backward dataflow analyses, allowing subclasses to customize lattice propagation behavior along control flow edges between blocks. Default implementation preserves existing join/meet semantics. This change mirrors the exiting structure of both dense dataflow classes, where `RegionBranchOpInterface` and callables are allowed to be customized by subclasses. Signed-off-by: Fabian Mora <[email protected]>
1 parent 562e3bf commit 3c2a620

File tree

2 files changed

+76
-3
lines changed

2 files changed

+76
-3
lines changed

mlir/include/mlir/Analysis/DataFlow/DenseAnalysis.h

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -127,6 +127,19 @@ class AbstractDenseForwardDataFlowAnalysis : public DataFlowAnalysis {
127127
/// them into the same equivalent class.
128128
virtual void buildOperationEquivalentLatticeAnchor(Operation *op) {}
129129

130+
/// Visit a block and propagate the dense lattice forward along the control
131+
/// flow edge from predecessor to block. `point` corresponds to the program
132+
/// point before `block`. The default implementation merges in the state from
133+
/// the predecessor's terminator.
134+
virtual void visitBlockTransfer(Block *block, ProgramPoint *point,
135+
Block *predecessor,
136+
const AbstractDenseLattice &before,
137+
AbstractDenseLattice *after) {
138+
// Merge in the state from the predecessor's terminator.
139+
join(after, *getLatticeFor(
140+
point, getProgramPointAfter(predecessor->getTerminator())));
141+
}
142+
130143
/// Propagate the dense lattice forward along the control flow edge from
131144
/// `regionFrom` to `regionTo` regions of the `branch` operation. `nullopt`
132145
/// values correspond to control flow branches originating at or targeting the
@@ -259,6 +272,22 @@ class DenseForwardDataFlowAnalysis
259272
branch, regionFrom, regionTo, before, after);
260273
}
261274

275+
/// Hook for customizing the behavior of lattice propagation along the control
276+
/// flow edges between blocks. The control flows from `predecessor` to
277+
/// `block`. The lattice is propagated forward along this edge. The lattices
278+
/// are as follows:
279+
/// - `before` is the lattice at the end of the predecessor block;
280+
/// - `after` is the lattice at the beginning of the block.
281+
/// By default, the `after` state is simply joined with the `before` state.
282+
/// Concrete analyses can override this behavior or delegate to the parent
283+
/// call for the default behavior.
284+
virtual void visitBlockTransfer(Block *block, ProgramPoint *point,
285+
Block *predecessor, const LatticeT &before,
286+
LatticeT *after) {
287+
AbstractDenseForwardDataFlowAnalysis::visitBlockTransfer(
288+
block, point, predecessor, before, after);
289+
}
290+
262291
protected:
263292
/// Get the dense lattice on this lattice anchor.
264293
LatticeT *getLattice(LatticeAnchor anchor) override {
@@ -306,6 +335,13 @@ class DenseForwardDataFlowAnalysis
306335
static_cast<const LatticeT &>(before),
307336
static_cast<LatticeT *>(after));
308337
}
338+
void visitBlockTransfer(Block *block, ProgramPoint *point, Block *predecessor,
339+
const AbstractDenseLattice &before,
340+
AbstractDenseLattice *after) final {
341+
visitBlockTransfer(block, point, predecessor,
342+
static_cast<const LatticeT &>(before),
343+
static_cast<LatticeT *>(after));
344+
}
309345
};
310346

311347
//===----------------------------------------------------------------------===//
@@ -388,6 +424,17 @@ class AbstractDenseBackwardDataFlowAnalysis : public DataFlowAnalysis {
388424
/// them into the same equivalent class.
389425
virtual void buildOperationEquivalentLatticeAnchor(Operation *op) {}
390426

427+
/// Visit a block and propagate the dense lattice backward along the control
428+
/// flow edge from successor to block. `point` corresponds to the program
429+
/// point after `block`. The default implementation merges in the state from
430+
/// the successor's first operation or the block itself when empty.
431+
virtual void visitBlockTransfer(Block *block, ProgramPoint *point,
432+
Block *successor,
433+
const AbstractDenseLattice &after,
434+
AbstractDenseLattice *before) {
435+
meet(before, *getLatticeFor(point, getProgramPointBefore(successor)));
436+
}
437+
391438
/// Propagate the dense lattice backwards along the control flow edge from
392439
/// `regionFrom` to `regionTo` regions of the `branch` operation. `nullopt`
393440
/// values correspond to control flow branches originating at or targeting the
@@ -531,6 +578,22 @@ class DenseBackwardDataFlowAnalysis
531578
branch, regionFrom, regionTo, after, before);
532579
}
533580

581+
/// Hook for customizing the behavior of lattice propagation along the control
582+
/// flow edges between blocks. The control flows from `successor` to
583+
/// `block`. The lattice is propagated back along this edge. The lattices
584+
/// are as follows:
585+
/// - `after` is the lattice at the beginning of the successor block;
586+
/// - `before` is the lattice at the end of the block.
587+
/// By default, the `before` state is simply met with the `after` state.
588+
/// Concrete analyses can override this behavior or delegate to the parent
589+
/// call for the default behavior.
590+
virtual void visitBlockTransfer(Block *block, ProgramPoint *point,
591+
Block *successor, const LatticeT &after,
592+
LatticeT *before) {
593+
AbstractDenseBackwardDataFlowAnalysis::visitBlockTransfer(
594+
block, point, successor, after, before);
595+
}
596+
534597
protected:
535598
/// Get the dense lattice at the given lattice anchor.
536599
LatticeT *getLattice(LatticeAnchor anchor) override {
@@ -577,6 +640,13 @@ class DenseBackwardDataFlowAnalysis
577640
static_cast<const LatticeT &>(after),
578641
static_cast<LatticeT *>(before));
579642
}
643+
void visitBlockTransfer(Block *block, ProgramPoint *point, Block *successor,
644+
const AbstractDenseLattice &after,
645+
AbstractDenseLattice *before) final {
646+
visitBlockTransfer(block, point, successor,
647+
static_cast<const LatticeT &>(after),
648+
static_cast<LatticeT *>(before));
649+
}
580650
};
581651

582652
} // end namespace dataflow

mlir/lib/Analysis/DataFlow/DenseAnalysis.cpp

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -266,9 +266,10 @@ void AbstractDenseForwardDataFlowAnalysis::visitBlock(Block *block) {
266266
}
267267

268268
LDBG() << " Joining state from predecessor " << predecessor;
269+
const AbstractDenseLattice &before = *getLatticeFor(
270+
point, getProgramPointAfter(predecessor->getTerminator()));
269271
// Merge in the state from the predecessor's terminator.
270-
join(after, *getLatticeFor(
271-
point, getProgramPointAfter(predecessor->getTerminator())));
272+
visitBlockTransfer(block, point, predecessor, before, after);
272273
}
273274
}
274275

@@ -614,7 +615,9 @@ void AbstractDenseBackwardDataFlowAnalysis::visitBlock(Block *block) {
614615
LDBG() << " Meeting state from successor " << successor;
615616
// Merge in the state from the successor: either the first operation, or the
616617
// block itself when empty.
617-
meet(before, *getLatticeFor(point, getProgramPointBefore(successor)));
618+
visitBlockTransfer(block, point, successor,
619+
*getLatticeFor(point, getProgramPointBefore(successor)),
620+
before);
618621
}
619622
}
620623

0 commit comments

Comments
 (0)