Skip to content

feat(ir): move and splice statements, blocks and CFGs in Rewriter - #848

Open
alexcgatea wants to merge 5 commits into
rustfrom
alex/code-motion
Open

alexcgatea wants to merge 5 commits into
rustfrom
alex/code-motion

Conversation

@alexcgatea

Copy link
Copy Markdown
Collaborator

Summary

Adds the Rewriter operations for code motion: moving statements, splicing a block's statements, and splicing a whole CFG. Walks now detect when the statement being visited is moved.

New operations

Operation What it does
replace_uses_if, replace_all_uses_except_stmt(s) replace_all_uses restricted to selected use sites
move_before / move_after Move a statement next to an anchor in any block body
splice_block_before / splice_block_after Move a block's statements next to an anchor, redirecting its arguments
splice_cfg_after Move all blocks of a CFG after an anchor block in another CFG

Each records a new event (MovedStatement, SplicedBlock, SplicedCfg). Moving a statement into its own bodies, or splicing a block or CFG into itself, is rejected (MovedIntoItself, SplicedIntoItself, CfgSplicedIntoItself).

API changes

  • drain_events is replaced by into_events(self), so the event log only grows while a Rewriter lives, and positions in it stay valid.

Walk safety

Moving or splicing the statement being visited breaks pre-order, post-order and BFS walks, which find the next statement through the visited one. walk_mut now checks the Rewriter's event log after each visit (MovedStatement, SplicedBlock, SplicedCfg, compared against a VisitedPlace recorded before the visit) and reports WalkError::VisitedMoved. Reverse BFS orders, which build their order up front, still allow it. A loop driving a cursor by hand records VisitedPlace::of(stage, stmt) and the event-log length before each visit, and calls WalkOrder::check_not_moved_since itself.

alexcgatea and others added 5 commits November 10, 2026 08:21
Add replace_uses_if, replace_all_uses_except_stmt and
replace_all_uses_except_stmts, which redirect only the use sites a
predicate accepts. ReplacedUses is recorded only once the old value has no
uses left.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The event log now only grows while a Rewriter lives, so positions in
events() stay valid. Tests track positions with an EventCursor helper.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Moves record MovedStatement; walk_mut rejects moving the visited
statement in link-following orders.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…ore/after

Moves every non-terminator statement of a block next to an anchor and
redirects its arguments; records SplicedBlock, which walk_mut checks.
Drops the planned block move (step 3).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Moves every block of a CFG after an anchor block in another CFG; records
SplicedCfg. walk_mut now records a VisitedPlace (block and CFG) before
each visit to check splices against.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant