cold block reordering and jump normalization#7210
cold block reordering and jump normalization#7210youknowone merged 2 commits intoRustPython:mainfrom
Conversation
|
Caution Review failedThe pull request is closed. ℹ️ Recent review infoConfiguration used: Path: .coderabbit.yml Review profile: CHILL Plan: Pro ⛔ Files ignored due to path filters (6)
📒 Files selected for processing (5)
📝 WalkthroughWalkthroughThis change adds IR cold-block analysis and reordering, inserts jump-normalization, changes exception-cleanup jumps from Changes
Sequence Diagram(s)sequenceDiagram
participant Frontend as Frontend/Bytecode
participant Codegen as Codegen(IR)
participant Finalizer as CodeInfo::finalize_code
participant Compiler as compile.rs
participant JIT as JIT/StackMachine
Frontend->>Codegen: produce basic blocks & jumps
Codegen->>Finalizer: finalize_code(blocks)
Note over Finalizer: runs label_exception_targets\nthen mark_cold -> push_cold_blocks_to_end -> normalize_jumps
Finalizer-->>Codegen: reordered/normalized blocks
Codegen->>Compiler: emit control-flow (Jump / JumpNoInterrupt)
Note over Compiler: exception cleanup paths now use JumpNoInterrupt
Compiler->>JIT: lower/emit instructions (includes NotTaken)
JIT->>JIT: treat NotTaken as NOP during codegen/execution
Estimated code review effort🎯 4 (Complex) | ⏱️ ~45 minutes Possibly related PRs
Suggested reviewers
Poem
🚥 Pre-merge checks | ✅ 3✅ Passed checks (3 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
339cc4d to
9aab866
Compare
|
Code has been automatically formatted The code in this PR has been formatted using:
git pull origin cold-and-jump |
37691ba to
1da0e65
Compare
📦 Library DependenciesThe following Lib/ modules were modified. Here are their dependencies: [ ] test: cpython/Lib/test/test_compile.py (TODO: 24) dependencies: dependent tests: (no tests depend on compile) Legend:
|
There was a problem hiding this comment.
Actionable comments posted: 1
🧹 Nitpick comments (2)
crates/codegen/src/ir.rs (2)
1164-1210: Consider extracting the repeatedhas_fallthroughpredicate.The same three-line pattern:
.last().map(|ins| !ins.instr.is_scope_exit() && !ins.instr.is_unconditional_jump()).unwrap_or(true)appears in
mark_cold(line 1183–1185),push_cold_blocks_to_end(line 1231–1234), andlabel_exception_targets. A small free function would eliminate the duplication.♻️ Proposed helper
+/// Returns true if `block` falls through to its `next` block +/// (i.e. its last instruction is neither a scope exit nor an unconditional jump). +fn block_has_fallthrough(block: &Block) -> bool { + block + .instructions + .last() + .map(|ins| !ins.instr.is_scope_exit() && !ins.instr.is_unconditional_jump()) + .unwrap_or(true) +}🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@crates/codegen/src/ir.rs` around lines 1164 - 1210, The three-line fallthrough predicate (.instructions.last().map(|ins| !ins.instr.is_scope_exit() && !ins.instr.is_unconditional_jump()).unwrap_or(true)) is duplicated across mark_cold, push_cold_blocks_to_end, and label_exception_targets; extract it as a small free function (e.g., fn last_allows_fallthrough(block: &Block) -> bool or fn instr_allows_fallthrough(ins: Option<&InstrWrapper>) -> bool) and replace the inline expression in those functions with a call to the new helper, keeping semantics identical (true when no last instruction, otherwise !is_scope_exit && !is_unconditional_jump).
1252-1271: Document the cold→warm jump invariant at the insertion site.
PseudoInstruction::JumpNoInterruptis correctly included inis_unconditional_jump()for both the fixup filter andnormalize_jumps, so no functional issue exists there.However, the ordering invariant that enables the unconditional conversion to
JumpBackwardNoInterruptinfinalize_code(line 318) is implicit:JumpNoInterruptis inserted here before cold blocks are reordered to the end, and only after reordering does every cold→warm jump become backward. This dependency should be documented at the insertion site (around line 1257) to clarify why the later conversion is safe, and optionally reinforced with adebug_assert!at conversion time.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@crates/codegen/src/ir.rs` around lines 1252 - 1271, Document that the JumpNoInterrupt insertion relies on the invariant that cold blocks are moved to the end later so that any cold→warm JumpNoInterrupt becomes a backward jump during finalize_code; add a brief comment at the jump insertion site (around jump_block creation / PseudoInstruction::JumpNoInterrupt) explaining this dependency and referencing normalize_jumps and finalize_code, and add a debug_assert! in finalize_code near the conversion to JumpBackwardNoInterrupt that checks the jump target is backward for JumpNoInterrupt (so the invariant is validated in debug builds).
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@crates/codegen/src/ir.rs`:
- Around line 1328-1339: The is_conditional_jump function currently only matches
PopJumpIf* variants; update its match in is_conditional_jump to also include
Instruction::ForIter { .. } and Instruction::Send { .. } so those
conditional-jump instructions (which have target labels and require NOT_TAKEN
hints) are treated as conditional jumps alongside
Instruction::PopJumpIfFalse/True/None/NotNone.
---
Nitpick comments:
In `@crates/codegen/src/ir.rs`:
- Around line 1164-1210: The three-line fallthrough predicate
(.instructions.last().map(|ins| !ins.instr.is_scope_exit() &&
!ins.instr.is_unconditional_jump()).unwrap_or(true)) is duplicated across
mark_cold, push_cold_blocks_to_end, and label_exception_targets; extract it as a
small free function (e.g., fn last_allows_fallthrough(block: &Block) -> bool or
fn instr_allows_fallthrough(ins: Option<&InstrWrapper>) -> bool) and replace the
inline expression in those functions with a call to the new helper, keeping
semantics identical (true when no last instruction, otherwise !is_scope_exit &&
!is_unconditional_jump).
- Around line 1252-1271: Document that the JumpNoInterrupt insertion relies on
the invariant that cold blocks are moved to the end later so that any cold→warm
JumpNoInterrupt becomes a backward jump during finalize_code; add a brief
comment at the jump insertion site (around jump_block creation /
PseudoInstruction::JumpNoInterrupt) explaining this dependency and referencing
normalize_jumps and finalize_code, and add a debug_assert! in finalize_code near
the conversion to JumpBackwardNoInterrupt that checks the jump target is
backward for JumpNoInterrupt (so the invariant is validated in debug builds).
ℹ️ Review info
Configuration used: Path: .coderabbit.yml
Review profile: CHILL
Plan: Pro
⛔ Files ignored due to path filters (6)
Lib/test/test_peepholer.pyis excluded by!Lib/**crates/codegen/src/snapshots/rustpython_codegen__compile__tests__if_ands.snapis excluded by!**/*.snapcrates/codegen/src/snapshots/rustpython_codegen__compile__tests__if_mixed.snapis excluded by!**/*.snapcrates/codegen/src/snapshots/rustpython_codegen__compile__tests__if_ors.snapis excluded by!**/*.snapcrates/codegen/src/snapshots/rustpython_codegen__compile__tests__nested_bool_op.snapis excluded by!**/*.snapcrates/codegen/src/snapshots/rustpython_codegen__compile__tests__nested_double_async_with.snapis excluded by!**/*.snap
📒 Files selected for processing (5)
crates/codegen/src/compile.rscrates/codegen/src/ir.rscrates/compiler-core/src/bytecode/instruction.rscrates/jit/src/instructions.rscrates/jit/tests/common.rs
Add mark_cold, push_cold_blocks_to_end, and normalize_jumps passes to the codegen CFG pipeline. Use JumpNoInterrupt for exception handler exit paths in try-except-finally compilation.
1b9eb37 to
38e342a
Compare
Add mark_cold, push_cold_blocks_to_end, and normalize_jumps passes to the codegen CFG pipeline. Use JumpNoInterrupt for exception handler exit paths in try-except-finally compilation.
Summary by CodeRabbit
Bug Fixes
Refactor
Tests