[all-commits] [llvm/llvm-project] 62f1da: [mlir] Avoid rewriting unreachable blocks in the g...
Vijay Kandiah via All-commits
all-commits at lists.llvm.org
Wed Sep 30 15:41:42 PDT 2026
Branch: refs/heads/users/mamini/greedy-rewrite-reachability
Home: https://github.com/llvm/llvm-project
Commit: 62f1dacdb773dc57b5f4d65ab82580c4d6f1ad70
https://github.com/llvm/llvm-project/commit/62f1dacdb773dc57b5f4d65ab82580c4d6f1ad70
Author: Vijay Kandiah <vkandiah at nvidia.com>
Date: 2026-09-30 (Wed, 30 Sep 2026)
Changed paths:
M mlir/include/mlir/Transforms/GreedyPatternRewriteDriver.h
M mlir/lib/Transforms/Utils/GreedyPatternRewriteDriver.cpp
A mlir/test/Transforms/canonicalize-cfg-reachability.mlir
M mlir/test/Transforms/canonicalize-dce.mlir
A mlir/test/Transforms/greedy-cfg-reachability.mlir
M mlir/test/Transforms/test-strict-pattern-driver.mlir
M mlir/test/lib/Dialect/Test/TestEnumDefs.td
M mlir/test/lib/Dialect/Test/TestOpDefs.cpp
M mlir/test/lib/Dialect/Test/TestOps.td
M mlir/test/lib/Dialect/Test/TestPatterns.cpp
Log Message:
-----------
[mlir] Avoid rewriting unreachable blocks in the greedy driver
A rewrite can disconnect a block after the iteration's initial CFG
sweep. Queued operations can develop self-referential SSA uses in
unreachable code, causing crashes or repeated rewrites that prevent the
worklist pass from returning. Track reachability through rewriter
notifications and skip these operations until the next iteration removes
their blocks.
The reproducer in #221152 exposes this gap in the initial sweep added by
#153957 for #153732. #154038 similarly skips unreachable blocks in the
walk-based driver. Reachable graph-region self-cycles in #194824 and
#205064 remain separate; #207185 proposes a fold-specific fix for them.
A forwarding ReachabilityListener sits between the rewriter and the
worklist driver and records, per region, which blocks changed their
terminator and which blocks were removed. Queries happen between
rewrites, once per popped operation, and update a per-region cache of
reachable blocks and their successors incrementally: added edges extend
the reachable set, a lost edge whose target is gone is dropped when its
successors remain reachable through the changed block, and any other lost
edge leaves the blocks behind its target uncertain until a query for one
of them traverses the region. In-place folds are reported to the listener
by the driver. Nested regions check their containing blocks up to the
scope. Caches are cleared at worklist-pass boundaries. With expensive
pattern API checks enabled, every query is compared against a fresh
traversal. The class comment describes the scheme in detail.
Canonicalizing 20000 blocks shows no measurable difference with and
without this change for a chain of constant conditional branches, a
chain of diamonds whose pass-through blocks fold away, the same chains
placed behind a loop header so that they cannot merge into the entry
block, a chain of constant conditional branches into a shared dead block
that exits, and 200000 single-block operations. Invalidating the cache
whenever a block is inserted or erased, or traversing the region after
every lost edge, makes the loop variants quadratic, up to 50 times slower
than without this change. The incremental scheme has a quadratic worst
case of its own: a lost edge into a loop whose target keeps other
predecessors cannot be decided without a traversal, and when the next
popped operation is behind that target, every such rewrite traverses the
region. A chain of 20000 constant conditional branches into a shared
block that branches back to the loop header takes 5.2s instead of 0.04s;
5000 such blocks take 0.26s instead of 0.02s. Top-down processing tends
to pop the operations behind the target next; bottom-up processing has
usually popped them already.
Tests cover inserted and redirected blocks, blocks connected before
rewrite completion, nested regions, block moves and merges, entry-block
insertion and erasure, edges lost by two blocks in one rewrite, a
disconnected block that retargets its branch in the same rewrite, a lost
edge into a loop, a block reconnected after being disconnected, in-place
folds that retarget a branch, an undecidable lost edge with an SSA cycle
behind it, nested CFG and scf.if regions in a disconnected block, and
explicit op lists. Observer diagnostics check whether affected operations
are processed within a single greedy iteration. Skipped operations are
not automatically retried if a later rewrite makes their block reachable;
this is documented and tested in each strictness mode.
Assisted-by: Codex
Assisted-by: Claude Code
To unsubscribe from these emails, change your notification settings at https://github.com/llvm/llvm-project/settings/notifications
More information about the All-commits
mailing list