feat(phi): Step 5-3 partial - Skip __pin$ in prepare_structure()

Step 5-5-C & Step 5-3-partial implementation:
- loopform_builder.rs: Skip __pin$ variables in prepare_structure()
- loopform_builder.rs: Use header_phi as latch_value for __pin$ carriers
- Result: ValueId error improved 318→256, dominator errors reduced

Technical Details:
- __pin$ compiler temps are now BodyLocalInternal (no PHIs)
- Prevents undefined ValueId from break snapshots being used at latch
- Dominator violation errors dramatically reduced

Test Status: 267 PASS / 1 FAIL (no regressions)
Remaining: ValueId(256) at BasicBlockId(429) - different root cause

🐛 PHI Bug Option C実装: 箱分割設計で根本修正
This commit is contained in:
nyash-codex
2025-11-20 14:56:26 +09:00
parent c4d25e7773
commit 38a028bb5e
2 changed files with 43 additions and 9 deletions

View File

@ -157,6 +157,15 @@ impl LoopFormBuilder {
// Separate variables into carriers and pinned based on parameter status
for (name, &value) in current_vars.iter() {
// Step 5-3: Skip __pin$ temporary variables (BodyLocalInternal)
// These are compiler-generated temporaries that should not have PHI nodes
if name.starts_with("__pin$") && name.contains("$@") {
if debug_enabled {
eprintln!("[loopform/prepare] SKIP __pin$ variable: {}", name);
}
continue;
}
// Phase 26-A-4: ValueIdベース判定に変更名前ベース → 型安全)
if ops.is_parameter(value) {
param_count += 1;
@ -382,11 +391,19 @@ impl LoopFormBuilder {
// - each continue block (early jump to header),
// - latch (normal end-of-iteration backedge).
for carrier in &mut self.carriers {
carrier.latch_value = ops
.get_variable_at_block(&carrier.name, latch_id)
.ok_or_else(|| {
format!("Carrier variable '{}' not found at latch block", carrier.name)
})?;
// Step 5-5-C: Fix __pin$ temporary variables at latch
// __pin$ variables are body-local temps that are filtered from body_end_vars.
// They don't have explicit values at the latch block, so we use the header PHI
// itself as the latch value (creating a self-referencing PHI that will be
// optimized by PHI reduction).
carrier.latch_value = if carrier.name.starts_with("__pin$") && carrier.name.contains("$@") {
carrier.header_phi // Use the PHI value itself as the latch input
} else {
ops.get_variable_at_block(&carrier.name, latch_id)
.ok_or_else(|| {
format!("Carrier variable '{}' not found at latch block", carrier.name)
})?
};
let mut inputs: Vec<(BasicBlockId, ValueId)> =
vec![(self.preheader_id, carrier.preheader_copy)];