wip(phi): Step 5-5-A body-local PHI修正中 - pred mismatch解決も undefined value発生
🔧 **実装内容**: - Body-local PHI生成時にpreheader+latch両方の入力を追加 - レガシーsealingコード削除(PHI上書き防止) - Latch値をvariable mapからlookup(正しいブロックの値使用) ✅ **成果**: - PHI pred mismatch エラー解決!(ValueId(712) at BasicBlockId(125)) - 266/267テストPASS(ループ関連ユニットテスト全PASS) ❌ **新規課題**: - InvalidValue: undefined ValueId(313)発生 - Body-local変数のHeader PHI生成そのものが誤りの可能性 - Option C設計: BodyLocal変数はHeader PHI不要、Exit PHIのみ 📋 **次のステップ**: - Task先生に詳細調査依頼(body-local変数の正しい扱い) - Header PHI生成ロジックの根本見直し検討
This commit is contained in:
@ -383,6 +383,10 @@ impl<'a> LoopBuilder<'a> {
|
||||
// Phase 25.1c/k: body-local 変数の PHI 生成
|
||||
// BreakFinderBox / FuncScannerBox 等で、loop body 内で新規宣言された local 変数が
|
||||
// loop header に戻った時に undefined になる問題を修正
|
||||
//
|
||||
// Step 5-5-A: PHI pred mismatch 根本修正
|
||||
// - Preheader入力(poison)とLatch入力の両方を即座に追加
|
||||
// - 空PHI生成→後で埋める方式は不完全だった(seal_phisが処理しない)
|
||||
let trace_loop_phi = std::env::var("HAKO_LOOP_PHI_TRACE").ok().as_deref() == Some("1");
|
||||
if trace_loop_phi {
|
||||
eprintln!("[loop-phi/body-local] Checking for body-local variables");
|
||||
@ -401,15 +405,36 @@ impl<'a> LoopBuilder<'a> {
|
||||
eprintln!("[loop-phi/body-local] Found {} body-local variables", body_local_vars.len());
|
||||
}
|
||||
|
||||
// Add PHI nodes for body-local variables at header
|
||||
for (var_name, _latch_value) in &body_local_vars {
|
||||
// Step 5-5-A: Add PHI nodes with BOTH inputs (preheader + latch)
|
||||
for (var_name, _body_value) in &body_local_vars {
|
||||
if trace_loop_phi {
|
||||
eprintln!("[loop-phi/body-local] Adding PHI for body-local var: {}", var_name);
|
||||
}
|
||||
|
||||
let phi_id = self.new_value();
|
||||
|
||||
// Insert empty PHI at header (will be sealed by seal_phis or later)
|
||||
// Step 5-5-A: Preheader input is poison (variable doesn't exist yet)
|
||||
let preheader_poison = self.new_value();
|
||||
|
||||
// Emit Const::Poison instruction in preheader block
|
||||
if let Some(ref mut func) = self.parent_builder.current_function {
|
||||
if let Some(preheader_block) = func.blocks.get_mut(&preheader_id) {
|
||||
preheader_block.add_instruction(MirInstruction::Const {
|
||||
dst: preheader_poison,
|
||||
value: crate::mir::ConstValue::Null, // Poison semantics
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// Step 5-5-A FIX: Get latch value from current variable map
|
||||
// The variable map was updated at line 374-377 with body_end_vars,
|
||||
// so looking it up now gives us the correct ValueId for the latch block.
|
||||
let latch_value = self.get_current_variable_map()
|
||||
.get(var_name)
|
||||
.copied()
|
||||
.unwrap_or(phi_id); // Fallback to phi_id if not found
|
||||
|
||||
// Step 5-5-A: Insert PHI with BOTH inputs (preheader poison + latch value)
|
||||
if let Some(ref mut func) = self.parent_builder.current_function {
|
||||
if let Some(header_block) = func.blocks.get_mut(&header_id) {
|
||||
// Find position after existing PHIs
|
||||
@ -418,7 +443,10 @@ impl<'a> LoopBuilder<'a> {
|
||||
phi_count,
|
||||
MirInstruction::Phi {
|
||||
dst: phi_id,
|
||||
inputs: vec![], // Empty PHI, will be filled by seal_phis
|
||||
inputs: vec![
|
||||
(preheader_id, preheader_poison), // ← Preheader input (poison)
|
||||
(latch_id, latch_value), // ← Latch input (from variable map)
|
||||
],
|
||||
},
|
||||
);
|
||||
}
|
||||
@ -426,10 +454,17 @@ impl<'a> LoopBuilder<'a> {
|
||||
|
||||
// Rebind variable to PHI
|
||||
self.update_variable(var_name.clone(), phi_id);
|
||||
|
||||
if trace_loop_phi {
|
||||
eprintln!(
|
||||
"[loop-phi/body-local] Created PHI {}: preheader={} (poison), latch={} ({})",
|
||||
phi_id.0, preheader_poison.0, latch_id.0, latch_value.0
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
if trace_loop_phi {
|
||||
eprintln!("[loop-phi/body-local] Added {} body-local PHIs", body_local_vars.len());
|
||||
eprintln!("[loop-phi/body-local] Added {} body-local PHIs with complete inputs", body_local_vars.len());
|
||||
}
|
||||
}
|
||||
|
||||
@ -515,57 +550,15 @@ impl<'a> LoopBuilder<'a> {
|
||||
loopform.seal_phis(self, actual_latch_id, &continue_snaps, &writes)?;
|
||||
|
||||
// Step 3: seal body-local PHIs (complete the inputs)
|
||||
if !body_local_vars.is_empty() {
|
||||
if trace_loop_phi {
|
||||
eprintln!("[loop-phi/body-local] Sealing {} body-local PHIs", body_local_vars.len());
|
||||
}
|
||||
|
||||
for (var_name, _) in &body_local_vars {
|
||||
// Get the PHI we created earlier from current variable map
|
||||
let current_map = self.get_current_variable_map();
|
||||
let phi_id = current_map.get(var_name).copied()
|
||||
.ok_or_else(|| format!("Body-local variable '{}' not found in variable map", var_name))?;
|
||||
|
||||
// Build inputs: no preheader input (variable doesn't exist there),
|
||||
// add latch input and continue inputs
|
||||
let mut inputs: Vec<(BasicBlockId, ValueId)> = vec![];
|
||||
|
||||
// Add latch input
|
||||
let latch_value = self.get_variable_at_block(var_name, actual_latch_id)
|
||||
.unwrap_or(phi_id); // Fallback to phi_id if not found
|
||||
inputs.push((actual_latch_id, latch_value));
|
||||
|
||||
// Add continue inputs
|
||||
for (cid, snapshot) in &continue_snaps {
|
||||
if let Some(&value) = snapshot.get(var_name) {
|
||||
inputs.push((*cid, value));
|
||||
}
|
||||
}
|
||||
|
||||
// Update PHI inputs
|
||||
if let Some(ref mut func) = self.parent_builder.current_function {
|
||||
if let Some(header_block) = func.blocks.get_mut(&header_id) {
|
||||
// Find the PHI instruction for this variable
|
||||
for instr in &mut header_block.instructions {
|
||||
if let MirInstruction::Phi { dst, inputs: phi_inputs } = instr {
|
||||
if *dst == phi_id {
|
||||
*phi_inputs = inputs.clone();
|
||||
if trace_loop_phi {
|
||||
eprintln!("[loop-phi/body-local] Sealed '{}' phi={:?} inputs={:?}",
|
||||
var_name, phi_id, inputs);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if trace_loop_phi {
|
||||
eprintln!("[loop-phi/body-local] Sealed {} body-local PHIs", body_local_vars.len());
|
||||
}
|
||||
}
|
||||
// Step 5-5-A: REMOVED - PHIs now created complete with both inputs upfront
|
||||
// Old sealing code was overwriting our preheader+latch inputs with latch-only,
|
||||
// causing "phi pred mismatch" errors.
|
||||
//
|
||||
// Body-local PHIs are now created at line 408-456 with BOTH inputs:
|
||||
// - preheader: poison value (variable doesn't exist yet)
|
||||
// - latch: actual value from loop body
|
||||
//
|
||||
// No further sealing is needed!
|
||||
|
||||
// Exit block
|
||||
self.set_current_block(exit_id)?;
|
||||
|
||||
Reference in New Issue
Block a user