feat(phi): Phase 26-E-2 - PhiBuilderBox If PHI生成完全実装

Phase 26-E Phase 2 完了: PhiBuilderBox による If PHI生成SSOT統一化

**実装内容:**
1. PhiBuilderBox 作成 (444行)
   - If PHI生成: generate_if_phis() 完全実装
   - Conservative戦略: void emission 含む完全対応
   - 決定的順序: BTreeSet/BTreeMap で非決定性排除

2. PhiBuilderOps trait (7メソッド)
   - 最小PHI生成インターフェース
   - new_value, emit_phi, update_var, get_block_predecessors
   - emit_void, set_current_block, block_exists

3. loop_builder.rs 統合
   - PhiBuilderOps trait 実装 (Ops構造体)
   - If PHI呼び出し箇所統合 (line 1136-1144)
   - Legacy if_phi::merge_modified_with_control 置換完了

**技術的成果:**
- Conservative PHI生成: 全経路カバー + void fallback
- 決定的変数順序: BTreeSet で変更変数をソート
- 決定的PHI入力順序: pred_bb.0 でソート
- テスタビリティ: MockOps でユニットテスト可能

**Phase 3 設計方針 (ChatGPT提案):**
- trait 階層化: LoopFormOps: PhiBuilderOps
- blanket impl: impl<T: LoopFormOps> PhiBuilderOps for T
- PhiBuilderBox: PhiBuilderOps 最小セットのみに依存
- 段階的移行: 既存コード保護しながら統一化

**削減見込み:**
- Phase 2: -80行 (If側重複削除)
- Phase 4: -287行 (loop_phi.rs Legacy削除)
- 合計: -367行 (純削減)

**関連ファイル:**
- src/mir/phi_core/phi_builder_box.rs (新規, 444行)
- src/mir/phi_core/mod.rs (module登録)
- src/mir/loop_builder.rs (PhiBuilderOps実装)
- CURRENT_TASK.md (Phase 26-E記録)

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

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
nyash-codex
2025-11-22 07:05:21 +09:00
parent 7812c3d4c1
commit b9a034293d
4 changed files with 593 additions and 11 deletions

View File

@ -1051,8 +1051,11 @@ impl<'a> LoopBuilder<'a> {
// Reset to pre-if map before rebinding to ensure a clean environment
self.parent_builder.variable_map = pre_if_var_map.clone();
// Use shared helper to merge modified variables at merge block
// Phase 26-E: PhiBuilderBox 統合
// Ops構造体: PhiMergeOpsLegacyと PhiBuilderOpsの両対応
struct Ops<'b, 'a>(&'b mut LoopBuilder<'a>);
impl<'b, 'a> crate::mir::phi_core::if_phi::PhiMergeOps for Ops<'b, 'a> {
fn new_value(&mut self) -> ValueId {
self.0.new_value()
@ -1078,6 +1081,53 @@ impl<'a> LoopBuilder<'a> {
}
}
}
// Phase 26-E: PhiBuilderOps trait 実装(箱理論統一)
impl<'b, 'a> crate::mir::phi_core::phi_builder_box::PhiBuilderOps for Ops<'b, 'a> {
fn new_value(&mut self) -> ValueId {
self.0.new_value()
}
fn emit_phi(
&mut self,
block: BasicBlockId,
dst: ValueId,
inputs: Vec<(BasicBlockId, ValueId)>,
) -> Result<(), String> {
self.0.emit_phi_at_block_start(block, dst, inputs)
}
fn update_var(&mut self, name: String, value: ValueId) {
self.0.parent_builder.variable_map.insert(name, value);
}
fn get_block_predecessors(&self, block: BasicBlockId) -> Vec<BasicBlockId> {
if let Some(ref func) = self.0.parent_builder.current_function {
func.blocks
.get(&block)
.map(|bb| bb.predecessors.iter().copied().collect())
.unwrap_or_default()
} else {
Vec::new()
}
}
fn emit_void(&mut self) -> ValueId {
let void_id = self.0.new_value();
let _ = self.0.emit_const(void_id, ConstValue::Void);
void_id
}
// Phase 3-A: Loop PHI生成用メソッド実装
fn set_current_block(&mut self, block: BasicBlockId) -> Result<(), String> {
self.0.parent_builder.current_block = Some(block);
Ok(())
}
fn block_exists(&self, block: BasicBlockId) -> bool {
if let Some(ref func) = self.0.parent_builder.current_function {
func.blocks.contains_key(&block)
} else {
false
}
}
}
// Reset to pre-if snapshot, then delegate to shared helper
self.parent_builder.variable_map = pre_if_var_map.clone();
@ -1097,16 +1147,15 @@ impl<'a> LoopBuilder<'a> {
let mut ops = Ops(self);
crate::mir::phi_core::if_phi::merge_modified_with_control(
&mut ops,
&form,
&pre_if_var_map,
&then_var_map_end,
&else_var_map_end_opt,
None,
then_pred_to_merge,
else_pred_to_merge,
)?;
// Phase 26-E: PhiBuilderBox SSOT統合If PHI生成
// Legacy: merge_modified_with_control() → New: PhiBuilderBox::generate_phis()
let mut phi_builder = crate::mir::phi_core::phi_builder_box::PhiBuilderBox::new();
let post_snapshots = if let Some(ref else_map) = else_var_map_end_opt {
vec![then_var_map_end.clone(), else_map.clone()]
} else {
vec![then_var_map_end.clone()]
};
phi_builder.generate_phis(&mut ops, &form, &pre_if_var_map, &post_snapshots)?;
// ControlForm 観測: 環境フラグ未設定時は既定ONのとき IfShape をダンプ
if is_control_form_trace_on() {