Phase 61-6.2 実装完了: A/B 比較観察コード完全削除 ## 変更内容 ### if_phi_spec.rs - ✅ extract_phi_spec_from_builder() 削除(L85-115, 31行) - ✅ compare_and_log_phi_specs() 削除(L117-140, 24行) - ✅ 未使用 import 削除(ValueId, BTreeMap) - ✅ 削除記録コメント追加(L85-91) - ✅ SSOT 確立: compute_phi_spec_from_joinir() のみが PHI 仕様計算 ### if_lowering.rs - ✅ A/B 比較ブロック削除(L271-295, 25行) - ✅ 簡潔な削除理由コメント追加(L271-273) ## 削減効果 - **純削減**: -71 行(予想 -50 行を大幅に上回る) - **SSOT 確立**: JoinIR 経路のみが PHI 計算の責務を持つ - **観察コード完全削除**: PhiBuilderBox 経路の観察用コード根絶 ## テスト結果 - ✅ JoinIR tests 全通過(56 passed) - ✅ ビルド成功(0 error, 0 warning) ## 技術的成果 - Phase 61-3 で JoinIR 経路が完全動作確認済み - A/B 比較は完了、観察用コードは不要に - PhiBuilderBox 経路はフォールバック専用に ## Phase 61-6 総計 - Wave 1: set_if_context 削除(-26 行) - Wave 2: A/B テスト削除(-71 行) - **合計削減**: -97 行(予想 -76 行を 27% 上回る成果) 次: Phase 61-7 or Phase 62 (更なる統合・削除)
128 lines
3.7 KiB
Rust
128 lines
3.7 KiB
Rust
//! Phase 61-2: JoinIR経路でのPHI仕様計算
|
||
//!
|
||
//! JoinInst(Select/IfMerge)から、どの変数がPHIを必要とするかを計算する。
|
||
|
||
use crate::mir::join_ir::lowering::if_phi_context::IfPhiContext;
|
||
use crate::mir::join_ir::JoinInst;
|
||
// Phase 61-6.2: ValueId, BTreeMap 削除(A/B観察関数削除で不要に)
|
||
use std::collections::BTreeSet;
|
||
|
||
/// PHI仕様(どの変数がPHIを持つべきか)
|
||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||
pub struct PhiSpec {
|
||
/// Header PHI候補(ループキャリア変数)
|
||
pub header_phis: BTreeSet<String>,
|
||
|
||
/// Exit PHI候補(ループ脱出時の値)
|
||
pub exit_phis: BTreeSet<String>,
|
||
}
|
||
|
||
impl PhiSpec {
|
||
pub fn new() -> Self {
|
||
Self {
|
||
header_phis: BTreeSet::new(),
|
||
exit_phis: BTreeSet::new(),
|
||
}
|
||
}
|
||
|
||
/// Header PHI数を取得
|
||
pub fn header_count(&self) -> usize {
|
||
self.header_phis.len()
|
||
}
|
||
|
||
/// Exit PHI数を取得
|
||
pub fn exit_count(&self) -> usize {
|
||
self.exit_phis.len()
|
||
}
|
||
|
||
/// 2つのPhiSpecが一致するか検証
|
||
pub fn matches(&self, other: &PhiSpec) -> bool {
|
||
self.header_phis == other.header_phis && self.exit_phis == other.exit_phis
|
||
}
|
||
}
|
||
|
||
/// JoinInstからPHI仕様を計算
|
||
///
|
||
/// # Arguments
|
||
///
|
||
/// * `ctx` - If-in-loopコンテキスト(carrier_names情報)
|
||
/// * `join_inst` - JoinIR命令(Select/IfMerge)
|
||
///
|
||
/// # Returns
|
||
///
|
||
/// PHI仕様(header/exit PHI候補)
|
||
pub fn compute_phi_spec_from_joinir(ctx: &IfPhiContext, join_inst: &JoinInst) -> PhiSpec {
|
||
let mut spec = PhiSpec::new();
|
||
|
||
match join_inst {
|
||
JoinInst::Select { .. } => {
|
||
// Select命令: 単一変数のPHI
|
||
// carrier_namesに含まれる変数をheader PHIとして扱う
|
||
// TODO Phase 61-3: dstからvariable_nameを逆引き(MIR Builderのvariable_map参照)
|
||
spec.header_phis = ctx.carrier_names.clone();
|
||
}
|
||
JoinInst::IfMerge { merges, .. } => {
|
||
// IfMerge命令: 複数変数のPHI
|
||
// TODO Phase 61-3: merge_pair.dstからvariable_nameを逆引き
|
||
// 暫定: carrier_namesに含まれる変数をheader PHIとして扱う
|
||
spec.header_phis = ctx.carrier_names.clone();
|
||
|
||
if ctx.in_loop_body {
|
||
eprintln!(
|
||
"[Phase 61-2] IfMerge with {} merge pairs in loop body",
|
||
merges.len()
|
||
);
|
||
}
|
||
}
|
||
_ => {
|
||
eprintln!("[Phase 61-2] ⚠️ Unexpected JoinInst variant for PHI spec");
|
||
}
|
||
}
|
||
|
||
spec
|
||
}
|
||
|
||
// Phase 61-6.2: A/B観察関数削除(JoinIR経路完全動作確認済み)
|
||
//
|
||
// 削除された関数:
|
||
// - extract_phi_spec_from_builder(): PhiBuilderBox経路の観察用
|
||
// - compare_and_log_phi_specs(): A/B比較ログ出力
|
||
//
|
||
// SSOT確立: compute_phi_spec_from_joinir() のみが PHI 仕様の計算ロジック
|
||
|
||
#[cfg(test)]
|
||
mod tests {
|
||
use super::*;
|
||
|
||
#[test]
|
||
fn test_phi_spec_creation() {
|
||
let spec = PhiSpec::new();
|
||
assert_eq!(spec.header_count(), 0);
|
||
assert_eq!(spec.exit_count(), 0);
|
||
}
|
||
|
||
#[test]
|
||
fn test_phi_spec_matches() {
|
||
let mut spec1 = PhiSpec::new();
|
||
spec1.header_phis.insert("x".to_string());
|
||
spec1.header_phis.insert("y".to_string());
|
||
|
||
let mut spec2 = PhiSpec::new();
|
||
spec2.header_phis.insert("x".to_string());
|
||
spec2.header_phis.insert("y".to_string());
|
||
|
||
assert!(spec1.matches(&spec2));
|
||
}
|
||
|
||
#[test]
|
||
fn test_phi_spec_mismatch() {
|
||
let mut spec1 = PhiSpec::new();
|
||
spec1.header_phis.insert("x".to_string());
|
||
|
||
let mut spec2 = PhiSpec::new();
|
||
spec2.header_phis.insert("y".to_string());
|
||
|
||
assert!(!spec1.matches(&spec2));
|
||
}
|
||
}
|