refactor(phi): Phase 59 PhiInputCollector inline in loopform_builder

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 <noreply@anthropic.com>
This commit is contained in:
nyash-codex
2025-11-29 09:43:17 +09:00
parent c10ffa4c2b
commit b40a17079a

View File

@ -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<BasicBlockId, ValueId> =
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<BasicBlockId, ValueId> =
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<BasicBlockId, ValueId> =
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!(