Phase 33 NORM canon test: enforce normalized dev route for P1/P2/JP mini

This commit is contained in:
nyash-codex
2025-12-11 20:54:33 +09:00
parent 59a985b7fa
commit af6f95cd4b
170 changed files with 4423 additions and 1897 deletions

View File

@ -5,9 +5,9 @@
//! - Entry block への Copy instruction 挿入
//! - SSA 値空間の接続
use std::collections::BTreeMap; // Phase 222.5-E: HashMap → BTreeMap for determinism
use crate::mir::{BasicBlockId, MirFunction, MirInstruction, ValueId};
use crate::mir::join_ir::lowering::inline_boundary::JoinInlineBoundary;
use crate::mir::{BasicBlockId, MirFunction, MirInstruction, ValueId};
use std::collections::BTreeMap; // Phase 222.5-E: HashMap → BTreeMap for determinism
pub struct BoundaryInjector;
@ -56,10 +56,11 @@ impl BoundaryInjector {
func: &mut MirFunction,
entry_block_id: BasicBlockId,
boundary: &JoinInlineBoundary,
value_map: &BTreeMap<ValueId, ValueId>, // Phase 222.5-E: HashMap → BTreeMap for determinism
value_map: &BTreeMap<ValueId, ValueId>, // Phase 222.5-E: HashMap → BTreeMap for determinism
phi_dst_ids: &std::collections::HashSet<ValueId>,
debug: bool,
) -> Result<BTreeMap<ValueId, ValueId>, String> { // Phase 222.5-E: HashMap → BTreeMap for determinism
) -> Result<BTreeMap<ValueId, ValueId>, String> {
// Phase 222.5-E: HashMap → BTreeMap for determinism
// Phase 33-20: When loop_var_name is set, ALL join_inputs are handled by header PHIs
// This includes the loop variable AND all other carriers from exit_bindings.
// We skip ALL join_inputs Copy instructions, only condition_bindings remain.
@ -67,7 +68,7 @@ impl BoundaryInjector {
// Phase 171-fix: Check both join_inputs and condition_bindings
let effective_join_inputs = if skip_all_join_inputs {
0 // Phase 33-20: All join_inputs are handled by header PHIs
0 // Phase 33-20: All join_inputs are handled by header PHIs
} else {
boundary.join_inputs.len()
};
@ -104,7 +105,10 @@ impl BoundaryInjector {
let mut reallocations = BTreeMap::new();
for binding in &boundary.condition_bindings {
let remapped_join = value_map.get(&binding.join_value).copied().unwrap_or(binding.join_value);
let remapped_join = value_map
.get(&binding.join_value)
.copied()
.unwrap_or(binding.join_value);
if phi_dst_ids.contains(&remapped_join) {
// Collision detected! Allocate a fresh ValueId
@ -132,29 +136,27 @@ impl BoundaryInjector {
// Phase 171: Inject Copy instructions for join_inputs (loop parameters)
// Phase 33-20: Skip ALL join_inputs when loop_var_name is set (header PHIs handle them)
if !skip_all_join_inputs {
for (join_input, host_input) in boundary
.join_inputs
.iter()
.zip(boundary.host_inputs.iter())
for (join_input, host_input) in
boundary.join_inputs.iter().zip(boundary.host_inputs.iter())
{
// リマップ後の ValueId を取得
let remapped_join = value_map.get(join_input).copied().unwrap_or(*join_input);
let remapped_host = *host_input; // host_input is already in host space
// リマップ後の ValueId を取得
let remapped_join = value_map.get(join_input).copied().unwrap_or(*join_input);
let remapped_host = *host_input; // host_input is already in host space
// Copy instruction: remapped_join = Copy remapped_host
let copy_inst = MirInstruction::Copy {
dst: remapped_join,
src: remapped_host,
};
// Copy instruction: remapped_join = Copy remapped_host
let copy_inst = MirInstruction::Copy {
dst: remapped_join,
src: remapped_host,
};
copy_instructions.push(copy_inst);
copy_instructions.push(copy_inst);
if debug {
eprintln!(
"[BoundaryInjector] Join input: Copy {:?} = Copy {:?}",
remapped_join, remapped_host
);
}
if debug {
eprintln!(
"[BoundaryInjector] Join input: Copy {:?} = Copy {:?}",
remapped_join, remapped_host
);
}
}
}
@ -178,10 +180,16 @@ impl BoundaryInjector {
// Phase 177-3 Option B: Use pre-allocated reallocations for PHI collision cases
for binding in &boundary.condition_bindings {
// Look up the remapped JoinIR ValueId from value_map
let remapped_join = value_map.get(&binding.join_value).copied().unwrap_or(binding.join_value);
let remapped_join = value_map
.get(&binding.join_value)
.copied()
.unwrap_or(binding.join_value);
// Phase 177-3 Option B: Check if this binding was reallocated (PHI collision case)
let final_dst = reallocations.get(&binding.join_value).copied().unwrap_or(remapped_join);
let final_dst = reallocations
.get(&binding.join_value)
.copied()
.unwrap_or(remapped_join);
// Copy instruction: final_dst = Copy host_value
let copy_inst = MirInstruction::Copy {
@ -203,7 +211,9 @@ impl BoundaryInjector {
// Entry block の先頭に Copy instructions を挿入
// Reverse order to preserve original order when inserting at position 0
// Phase 189 FIX: Also insert corresponding spans
let default_span = entry_block.instruction_spans.first()
let default_span = entry_block
.instruction_spans
.first()
.copied()
.unwrap_or_else(crate::ast::Span::unknown);
for inst in copy_instructions.into_iter().rev() {