From b40a17079ae7702362eff4c0a08106a11eb7946a Mon Sep 17 00:00:00 2001 From: nyash-codex Date: Sat, 29 Nov 2025 09:43:17 +0900 Subject: [PATCH] refactor(phi): Phase 59 PhiInputCollector inline in loopform_builder MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Phase 59: PhiBuilderBox / PhiInputCollector JoinIR統合(部分完了) ## 変更内容 - loopform_builder.rs: PhiInputCollector使用を完全にインライン化 - seal_pinned_phis (L455): インライン化 - seal_carrier_phis (L528): インライン化 - build_exit_phis (L746): インライン化 - PhiInputCollector import を削除 ## インライン化されたロジック 1. 入力収集: Vec<(BasicBlockId, ValueId)> 2. sanitize: BTreeMapで重複削除&ソート 3. optimize_same_value: 全同値ならPHI不要 4. finalize: Vec返却 ## 残存callsite - loop_builder.rs:524 (continue merge) - JoinIRに概念なし、現状維持 ## テスト結果 - loopform: 14 passed / 0 failed - JoinIR: 56 passed / 0 failed 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude --- src/mir/phi_core/loopform_builder.rs | 122 +++++++++++++++++++++------ 1 file changed, 95 insertions(+), 27 deletions(-) diff --git a/src/mir/phi_core/loopform_builder.rs b/src/mir/phi_core/loopform_builder.rs index 6c70b6ea..90c5b4d2 100644 --- a/src/mir/phi_core/loopform_builder.rs +++ b/src/mir/phi_core/loopform_builder.rs @@ -9,7 +9,8 @@ */ use crate::mir::phi_core::loop_snapshot_merge::LoopSnapshotMergeBox; -use crate::mir::phi_core::phi_input_collector::PhiInputCollector; +// Phase 59: PhiInputCollector使用廃止(インライン化完了) +// use crate::mir::phi_core::phi_input_collector::PhiInputCollector; use crate::mir::{BasicBlockId, ValueId}; use std::collections::BTreeMap; @@ -452,32 +453,56 @@ impl LoopFormBuilder { continue; } - let mut collector = PhiInputCollector::new(); - collector.add_preheader(self.preheader_id, pinned.preheader_copy); + // ======================================== + // Phase 59: PhiInputCollector インライン化 + // ======================================== + // Step 1: 入力収集 + let mut raw_inputs: Vec<(BasicBlockId, ValueId)> = Vec::new(); + raw_inputs.push((self.preheader_id, pinned.preheader_copy)); for (cid, snapshot) in continue_snapshots { if let Some(&value) = snapshot.get(&pinned.name) { - collector.add_snapshot(&[(*cid, value)]); + raw_inputs.push((*cid, value)); } } let latch_value = ops .get_variable_at_block(&pinned.name, latch_id) .unwrap_or(pinned.header_phi); - collector.add_latch(latch_id, latch_value); - collector.sanitize(); + raw_inputs.push((latch_id, latch_value)); - if let Some(same_value) = collector.optimize_same_value() { + // Step 2: sanitize (BTreeMapで重複削除&ソート) + let mut sanitized: std::collections::BTreeMap = + std::collections::BTreeMap::new(); + for (bb, val) in &raw_inputs { + sanitized.insert(*bb, *val); + } + let inputs: Vec<(BasicBlockId, ValueId)> = sanitized.into_iter().collect(); + + // Step 3: optimize_same_value + let same_value = if inputs.is_empty() { + None + } else if inputs.len() == 1 { + Some(inputs[0].1) + } else { + let first_val = inputs[0].1; + if inputs.iter().all(|(_, val)| *val == first_val) { + Some(first_val) + } else { + None + } + }; + + if let Some(same_val) = same_value { if debug { eprintln!( "[loopform/seal_phis] OPTIMIZED pinned '{}': phi={:?} → same_value={:?} (loop-invariant)", - pinned.name, pinned.header_phi, same_value + pinned.name, pinned.header_phi, same_val ); } continue; } - let inputs = collector.finalize(); if debug { eprintln!( "[loopform/seal_phis] pinned '{}' phi={:?} inputs={:?}", @@ -525,29 +550,53 @@ impl LoopFormBuilder { ) })?; - let mut collector = PhiInputCollector::new(); - collector.add_preheader(self.preheader_id, carrier.preheader_copy); + // ======================================== + // Phase 59: PhiInputCollector インライン化 + // ======================================== + // Step 1: 入力収集 + let mut raw_inputs: Vec<(BasicBlockId, ValueId)> = Vec::new(); + raw_inputs.push((self.preheader_id, carrier.preheader_copy)); for (cid, snapshot) in continue_snapshots { if let Some(&value) = snapshot.get(&carrier.name) { - collector.add_snapshot(&[(*cid, value)]); + raw_inputs.push((*cid, value)); } } - collector.add_latch(latch_id, carrier.latch_value); - collector.sanitize(); + raw_inputs.push((latch_id, carrier.latch_value)); - if let Some(same_value) = collector.optimize_same_value() { + // Step 2: sanitize (BTreeMapで重複削除&ソート) + let mut sanitized: std::collections::BTreeMap = + std::collections::BTreeMap::new(); + for (bb, val) in &raw_inputs { + sanitized.insert(*bb, *val); + } + let inputs: Vec<(BasicBlockId, ValueId)> = sanitized.into_iter().collect(); + + // Step 3: optimize_same_value + let same_value = if inputs.is_empty() { + None + } else if inputs.len() == 1 { + Some(inputs[0].1) + } else { + let first_val = inputs[0].1; + if inputs.iter().all(|(_, val)| *val == first_val) { + Some(first_val) + } else { + None + } + }; + + if let Some(same_val) = same_value { if debug { eprintln!( "[loopform/seal_phis] OPTIMIZED carrier '{}': phi={:?} → same_value={:?} (misclassified as carrier, actually loop-invariant)", - carrier.name, carrier.header_phi, same_value + carrier.name, carrier.header_phi, same_val ); } continue; } - let inputs = collector.finalize(); if debug { eprintln!( "[loopform/seal_phis] carrier '{}' phi={:?} inputs={:?}", @@ -740,23 +789,44 @@ impl LoopFormBuilder { inspector, )?; - // 4. PHI 生成(Phase 26-B-3: PhiInputCollectorを使用) + // ======================================== + // Phase 59: PHI生成(PhiInputCollectorインライン化) + // ======================================== + // 旧: PhiInputCollector::new() + add_snapshot + sanitize + optimize_same_value + // 新: BTreeMapで直接処理(同等のロジックをインライン展開) for (var_name, inputs) in all_vars { - // Phase 26-B-3: Use PhiInputCollector for unified PHI input handling - let mut collector = PhiInputCollector::new(); - collector.add_snapshot(&inputs); - collector.sanitize(); + // Step 1: sanitize - BTreeMapで重複削除&ソート + let mut sanitized: std::collections::BTreeMap = + std::collections::BTreeMap::new(); + for (bb, val) in &inputs { + sanitized.insert(*bb, *val); + } + let final_inputs: Vec<(BasicBlockId, ValueId)> = sanitized.into_iter().collect(); if debug { eprintln!( "[DEBUG/exit_phi] Variable '{}': {} inputs", var_name, - collector.len() + final_inputs.len() ); } - // Phase 25.2: optimize_same_value() で最適化判定 - if let Some(same_val) = collector.optimize_same_value() { + // Step 2: optimize_same_value - 全て同じ値ならPHI不要 + let same_value = if final_inputs.is_empty() { + None + } else if final_inputs.len() == 1 { + Some(final_inputs[0].1) + } else { + let first_val = final_inputs[0].1; + if final_inputs.iter().all(|(_, val)| *val == first_val) { + Some(first_val) + } else { + None + } + }; + + // Step 3: PHI生成 or 直接バインド + if let Some(same_val) = same_value { // 全て同じ値 or 単一入力 → PHI 不要 if debug { eprintln!( @@ -767,8 +837,6 @@ impl LoopFormBuilder { ops.update_var(var_name, same_val); } else { // 異なる値を持つ場合は PHI ノードを生成 - let final_inputs = collector.finalize(); - let phi_id = ops.new_value(); if debug { eprintln!(