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:
@ -479,11 +479,28 @@ impl<'a> LoopBuilder<'a> {
|
|||||||
crate::mir::builder::loops::add_predecessor(self.parent_builder, header_id, continue_merge_id)?;
|
crate::mir::builder::loops::add_predecessor(self.parent_builder, header_id, continue_merge_id)?;
|
||||||
|
|
||||||
// Step 2: merged_snapshot を使って seal_phis を呼ぶ
|
// Step 2: merged_snapshot を使って seal_phis を呼ぶ
|
||||||
let continue_snaps: Vec<(BasicBlockId, HashMap<String, ValueId>)> =
|
// Phase 25.3: Continue merge PHI実装(Task先生の発見!)
|
||||||
if merged_snapshot.is_empty() {
|
// - continueが無いループでも、Latchブロックの値をHeader PHIに伝播する必要がある
|
||||||
vec![]
|
// - これにより、Exit PHIがHeader PHI経由で正しい値を受け取れる
|
||||||
} else {
|
let continue_snaps: Vec<(BasicBlockId, HashMap<String, ValueId>)> = {
|
||||||
|
// まず、merged_snapshot(continue merge PHI結果)を追加
|
||||||
|
let mut snaps = if !merged_snapshot.is_empty() {
|
||||||
vec![(continue_merge_id, merged_snapshot.clone())]
|
vec![(continue_merge_id, merged_snapshot.clone())]
|
||||||
|
} else {
|
||||||
|
vec![]
|
||||||
|
};
|
||||||
|
|
||||||
|
// continueが無い場合でも、Latchブロックのスナップショットを追加
|
||||||
|
// これにより、seal_phis()がLatchからの値をHeader PHIに正しく接続できる
|
||||||
|
if raw_continue_snaps.is_empty() {
|
||||||
|
// continue文が無い場合、Latchブロックの現在の変数マップをキャプチャ
|
||||||
|
// Note: このタイミングでは current_block == exit_id だが、
|
||||||
|
// variable_map はLatch実行後の状態を保持している
|
||||||
|
let latch_snapshot = self.get_current_variable_map();
|
||||||
|
snaps.push((actual_latch_id, latch_snapshot));
|
||||||
|
}
|
||||||
|
|
||||||
|
snaps
|
||||||
};
|
};
|
||||||
// Step 5-1/5-2: Pass writes 集合 for PHI縮約
|
// Step 5-1/5-2: Pass writes 集合 for PHI縮約
|
||||||
loopform.seal_phis(self, actual_latch_id, &continue_snaps, &writes)?;
|
loopform.seal_phis(self, actual_latch_id, &continue_snaps, &writes)?;
|
||||||
|
|||||||
@ -157,6 +157,15 @@ impl LoopFormBuilder {
|
|||||||
|
|
||||||
// Separate variables into carriers and pinned based on parameter status
|
// Separate variables into carriers and pinned based on parameter status
|
||||||
for (name, &value) in current_vars.iter() {
|
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ベース判定に変更(名前ベース → 型安全)
|
// Phase 26-A-4: ValueIdベース判定に変更(名前ベース → 型安全)
|
||||||
if ops.is_parameter(value) {
|
if ops.is_parameter(value) {
|
||||||
param_count += 1;
|
param_count += 1;
|
||||||
@ -382,11 +391,19 @@ impl LoopFormBuilder {
|
|||||||
// - each continue block (early jump to header),
|
// - each continue block (early jump to header),
|
||||||
// - latch (normal end-of-iteration backedge).
|
// - latch (normal end-of-iteration backedge).
|
||||||
for carrier in &mut self.carriers {
|
for carrier in &mut self.carriers {
|
||||||
carrier.latch_value = ops
|
// Step 5-5-C: Fix __pin$ temporary variables at latch
|
||||||
.get_variable_at_block(&carrier.name, latch_id)
|
// __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(|| {
|
.ok_or_else(|| {
|
||||||
format!("Carrier variable '{}' not found at latch block", carrier.name)
|
format!("Carrier variable '{}' not found at latch block", carrier.name)
|
||||||
})?;
|
})?
|
||||||
|
};
|
||||||
|
|
||||||
let mut inputs: Vec<(BasicBlockId, ValueId)> =
|
let mut inputs: Vec<(BasicBlockId, ValueId)> =
|
||||||
vec![(self.preheader_id, carrier.preheader_copy)];
|
vec![(self.preheader_id, carrier.preheader_copy)];
|
||||||
|
|||||||
Reference in New Issue
Block a user