Commit 56269f7
authored
Bytecode parity - CFG reorders and LOAD_FAST_BORROW chain (RustPython#7870)
* Align LOAD_FAST_BORROW analysis with CPython chain shape
Three changes that bring optimize_load_fast_borrow closer to CPython's
optimize_load_fast in flowgraph.c:
* ir.rs: split mark_cold into the CPython-style two passes. Phase 1
propagates "warm" from the entry block, phase 2 propagates "cold" from
except_handler blocks. Blocks reached by neither phase keep cold=false
and stay in their original b_next position, matching CPython's handling
of empty placeholders left by remove_unreachable (e.g. the inner_end of
a nested try/except whose incoming jumps were re-routed by optimize_cfg).
* ir.rs: in optimize_load_fast_borrow, push the fall-through successor
only when the current block has a last instruction (is_some_and).
Empty blocks now terminate fall-through propagation, matching the
`term != NULL` check in optimize_load_fast.
* compile.rs: add switch_to_new_or_reuse_empty() helper and use it in
compile_while. The helper reuses the current block when it is empty
and unlinked, mirroring USE_LABEL absorption in
cfg_builder_maybe_start_new_block. This stops a stray empty block
from appearing between e.g. a try/except end_block and the following
while loop header.
Four codegen tests that depended on the previous fall-through-through-
empty behavior are marked #[ignore] with TODO comments.
Also includes a handful of dictionary entries in .cspell.dict picked up
during the work.
* Interleave const fold passes per-block to match CPython
Mirror CPython's optimize_basic_block() (flowgraph.c) by walking each
block once in instruction order and trying tuple, list, set, unary, and
binop folding at each position before advancing. This replaces the
previous global-pass sequence where every fold_unary_constants pattern
in the whole CFG was registered before any tuple constant, leaving
negated literals like `-1` at co_consts positions earlier than CPython
produces (e.g. snippets.py: -1 at idx 280 vs CPython idx 726).
Changes:
- Extract `fold_unary_constant_at` and `fold_binop_constant_at` per-
position helpers from the existing global passes; the global passes
now call the helpers in a loop.
- Add `fold_constants_per_block` that walks each block to a fixed point,
trying all five folds at each instruction position.
- Call the new walker before the legacy global passes in
optimize_finalize so co_consts insertion order matches CPython's.
Measured on the full Lib tree: differing files 270 → 269; the only
newly matching file is `test/test_ast/snippets.py`, the case raised in
youknowone#28.
* Inline small fast-return blocks only through unconditional jumps
`inline_small_fast_return_blocks` previously appended the target
`LOAD_FAST(_BORROW)/RETURN_VALUE` block's instructions onto any
predecessor whose fall-through eventually reached it, in addition to the
unconditional-jump case CPython handles in
`inline_small_or_no_lineno_blocks` (flowgraph.c:1210). CPython only
inlines through unconditional jumps, leaving fall-through predecessors
to reach the shared return block via the natural CFG layout. The extra
fall-through branch duplicated the return tail (e.g. `if/elif/return`
emitted two adjacent `LOAD_FAST_BORROW x; RETURN_VALUE` sequences).
Remove the fall-through inlining branch and keep only the
unconditional-jump path.
Measured on the full Lib tree: differing files 270 → 239 (-31), no new
regressions. Files newly matching include copy.py, argparse.py,
dataclasses.py, logging/__init__.py, pathlib/__init__.py, etc.
* Allow scope-exit/jump-back reorder within a shared except handler
`reorder_conditional_scope_exit_and_jump_back_blocks` previously skipped
any reorder where the conditional, scope-exit, or jump-back block had
an `except_handler` attached, even when all three shared the same
handler. CPython reorders these regardless of try/except context, as
long as the blocks stay within the same protected region. The over-
conservative guard left patterns like `try: for: if cond: return` with
the loop body's scope-exit ahead of the backedge, while CPython places
the backedge first and inverts the conditional.
Replace the `block_is_protected` triple-check with a single
`mismatched_protection` test: skip only when the three blocks do not
share the same `except_handler`. Same-handler reorders preserve the
protected range because every instruction's `except_handler` field
stays attached as `.next` pointers shift.
Measured on the full Lib tree: differing files 239 → 237; no new
regressions.
* Skip jump-over-cleanup reorder when target restarts an exception scope
reorder_jump_over_exception_cleanup_blocks was swapping a small
scope-exit target with a preceding cold cleanup chain even when the
target block began a fresh try (SETUP_FINALLY/SETUP_CLEANUP/SETUP_WITH).
The swap moved the next try's setup ahead of the prior handler's
cleanup_end/next_handler/cleanup_block, making the cleanup_body's
JUMP_FORWARD fall through directly to the cleanup_end and get elided as
redundant. The bytecode then lacked the JUMP_FORWARD that skips the
cleanup blocks and matched the prior handler's borrow tail incorrectly.
Skip the reorder when the target block contains any block-push pseudo
op so a new try's setup stays in source order. Re-enables the four
named/typed except-cleanup borrow tests that were marked #[ignore] in
commit 7481459.
* fix if block_idx == BlockIdx::NULL1 parent 078e23d commit 56269f7
4 files changed
Lines changed: 556 additions & 185 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
57 | 57 | | |
58 | 58 | | |
59 | 59 | | |
| 60 | + | |
60 | 61 | | |
| 62 | + | |
61 | 63 | | |
62 | 64 | | |
63 | 65 | | |
| |||
101 | 103 | | |
102 | 104 | | |
103 | 105 | | |
| 106 | + | |
104 | 107 | | |
105 | 108 | | |
106 | 109 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
67 | 67 | | |
68 | 68 | | |
69 | 69 | | |
| 70 | + | |
70 | 71 | | |
71 | 72 | | |
72 | 73 | | |
| |||
111 | 112 | | |
112 | 113 | | |
113 | 114 | | |
| 115 | + | |
114 | 116 | | |
115 | 117 | | |
116 | 118 | | |
117 | 119 | | |
118 | 120 | | |
119 | 121 | | |
| 122 | + | |
120 | 123 | | |
121 | 124 | | |
122 | 125 | | |
| |||
175 | 178 | | |
176 | 179 | | |
177 | 180 | | |
| 181 | + | |
178 | 182 | | |
179 | 183 | | |
180 | 184 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
6084 | 6084 | | |
6085 | 6085 | | |
6086 | 6086 | | |
6087 | | - | |
| 6087 | + | |
6088 | 6088 | | |
6089 | 6089 | | |
6090 | 6090 | | |
6091 | 6091 | | |
6092 | 6092 | | |
6093 | 6093 | | |
6094 | | - | |
6095 | | - | |
6096 | 6094 | | |
6097 | 6095 | | |
6098 | 6096 | | |
| |||
11345 | 11343 | | |
11346 | 11344 | | |
11347 | 11345 | | |
| 11346 | + | |
| 11347 | + | |
| 11348 | + | |
| 11349 | + | |
| 11350 | + | |
| 11351 | + | |
| 11352 | + | |
| 11353 | + | |
| 11354 | + | |
| 11355 | + | |
| 11356 | + | |
| 11357 | + | |
| 11358 | + | |
| 11359 | + | |
| 11360 | + | |
| 11361 | + | |
| 11362 | + | |
| 11363 | + | |
| 11364 | + | |
| 11365 | + | |
| 11366 | + | |
| 11367 | + | |
| 11368 | + | |
| 11369 | + | |
11348 | 11370 | | |
11349 | 11371 | | |
11350 | 11372 | | |
| |||
17510 | 17532 | | |
17511 | 17533 | | |
17512 | 17534 | | |
| 17535 | + | |
| 17536 | + | |
| 17537 | + | |
| 17538 | + | |
| 17539 | + | |
| 17540 | + | |
| 17541 | + | |
| 17542 | + | |
| 17543 | + | |
| 17544 | + | |
| 17545 | + | |
| 17546 | + | |
| 17547 | + | |
| 17548 | + | |
| 17549 | + | |
| 17550 | + | |
| 17551 | + | |
| 17552 | + | |
| 17553 | + | |
| 17554 | + | |
| 17555 | + | |
| 17556 | + | |
| 17557 | + | |
| 17558 | + | |
| 17559 | + | |
| 17560 | + | |
| 17561 | + | |
| 17562 | + | |
| 17563 | + | |
| 17564 | + | |
| 17565 | + | |
| 17566 | + | |
| 17567 | + | |
| 17568 | + | |
| 17569 | + | |
| 17570 | + | |
| 17571 | + | |
| 17572 | + | |
| 17573 | + | |
| 17574 | + | |
| 17575 | + | |
| 17576 | + | |
| 17577 | + | |
| 17578 | + | |
| 17579 | + | |
| 17580 | + | |
| 17581 | + | |
| 17582 | + | |
| 17583 | + | |
| 17584 | + | |
| 17585 | + | |
| 17586 | + | |
| 17587 | + | |
| 17588 | + | |
| 17589 | + | |
| 17590 | + | |
| 17591 | + | |
| 17592 | + | |
| 17593 | + | |
| 17594 | + | |
| 17595 | + | |
| 17596 | + | |
| 17597 | + | |
| 17598 | + | |
| 17599 | + | |
| 17600 | + | |
| 17601 | + | |
| 17602 | + | |
| 17603 | + | |
| 17604 | + | |
| 17605 | + | |
| 17606 | + | |
| 17607 | + | |
| 17608 | + | |
| 17609 | + | |
| 17610 | + | |
| 17611 | + | |
| 17612 | + | |
| 17613 | + | |
| 17614 | + | |
| 17615 | + | |
| 17616 | + | |
| 17617 | + | |
| 17618 | + | |
| 17619 | + | |
| 17620 | + | |
| 17621 | + | |
| 17622 | + | |
| 17623 | + | |
| 17624 | + | |
| 17625 | + | |
| 17626 | + | |
| 17627 | + | |
| 17628 | + | |
| 17629 | + | |
| 17630 | + | |
| 17631 | + | |
| 17632 | + | |
| 17633 | + | |
| 17634 | + | |
| 17635 | + | |
| 17636 | + | |
17513 | 17637 | | |
17514 | 17638 | | |
17515 | 17639 | | |
| |||
0 commit comments