feat(joinir): Phase 183 LoopBodyLocal role separation + test fixes

Phase 183 Implementation:
- Added is_var_used_in_condition() helper for AST variable detection
- Implemented LoopBodyLocal filtering in TrimLoopLowerer
- Created 4 test files for P1/P2 patterns
- Added 5 unit tests for variable detection

Test Fixes:
- Fixed test_is_outer_scope_variable_pinned (BasicBlockId import)
- Fixed test_pattern2_accepts_loop_param_only (literal node usage)

Refactoring:
- Unified pattern detection documentation
- Consolidated CarrierInfo initialization
- Documented LoopScopeShape construction paths

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
nyash-codex
2025-12-08 23:43:26 +09:00
parent a3df5ecc7a
commit 440f8646b1
66 changed files with 279 additions and 183 deletions

View File

@ -583,13 +583,15 @@ pub(in crate::mir::builder) fn merge_joinir_mir_blocks(
#[cfg(debug_assertions)]
{
if let Some(boundary) = boundary {
verify_joinir_contracts(
builder.function(),
entry_block_remapped,
exit_block_id,
&loop_header_phi_info,
boundary,
);
if let Some(ref func) = builder.current_function {
verify_joinir_contracts(
func,
entry_block_remapped,
exit_block_id,
&loop_header_phi_info,
boundary,
);
}
if debug {
eprintln!("[cf_loop/joinir] Phase 200-3: Contract verification passed");
}
@ -647,7 +649,13 @@ fn verify_loop_header_phis(
) {
// Check 1: Loop variable PHI existence
if let Some(ref loop_var_name) = boundary.loop_var_name {
let header_block_data = &func.blocks[header_block.0];
let header_block_data = func.blocks.get(&header_block).unwrap_or_else(|| {
panic!(
"[JoinIRVerifier] Header block {} not found ({} blocks in func)",
header_block,
func.blocks.len()
)
});
let has_loop_var_phi = header_block_data
.instructions
.iter()
@ -663,7 +671,13 @@ fn verify_loop_header_phis(
// Check 2: Carrier PHI existence
if !loop_info.carrier_phis.is_empty() {
let header_block_data = &func.blocks[header_block.0];
let header_block_data = func.blocks.get(&header_block).unwrap_or_else(|| {
panic!(
"[JoinIRVerifier] Header block {} not found ({} blocks in func)",
header_block,
func.blocks.len()
)
});
let phi_count = header_block_data
.instructions
.iter()
@ -715,7 +729,7 @@ fn verify_exit_line(
boundary: &JoinInlineBoundary,
) {
// Check 1: Exit block exists
if exit_block.0 >= func.blocks.len() {
if !func.blocks.contains_key(&exit_block) {
panic!(
"[JoinIRVerifier] Exit block {} out of range (func has {} blocks)",
exit_block.0,