//! Conservative PHI Generation - Box Theory Application //! //! Theory: Conservative ∘ Elimination = Minimal SSA //! - Conservative (this): correctness-first, generate all PHIs //! - Elimination (future): efficiency optimization, remove unused PHIs //! //! Phase 25.1q: Conservative PHI戦略の一元化 //! - phi.rs の Conservative PHI ロジック(L23-117)を統一 //! - void emission、predecessor fallback の一貫性保証 //! //! # Phase 35-39 PHI削減計画 //! //! ## 概要 //! //! Conservative ∘ Elimination = Minimal SSA の理論に基づく保守的PHI生成。 //! 非対称分岐(else なし)での void emission と predecessor fallback を扱う。 //! //! ## 🔜 Phase 40で部分削除予定(Level 2、30行) //! //! - ConservativeMerge struct inline (30行) //! - **Phase 40-4**: JoinIrConservativeAnalyzerに吸収 //! - **保持**: 理論コメント、Conservative ∘ Elimination説明 //! - **削除**: 構造体定義、実装コード //! //! ## ⏳ Phase 41+で完全削除予定(Level 3、約138行) //! //! - 残りのconservative logic全て //! - **削除条件**: JoinIR Verifier完全移行 //! - **難易度**: MEDIUM-HIGH //! //! ## 参照 //! //! - Phase 37分析: `docs/.../phase-37-if-phi-reduction/conservative_responsibility_table.md` //! - Phase 39設計: `docs/.../phase-39-if-phi-level2/joinir_extension_design.md` use crate::mir::ValueId; use std::collections::{BTreeMap, BTreeSet, HashSet}; // Phase 25.1: BTreeMap化, Phase 47: BTreeSet追加 /// Conservative PHI 戦略による変数マージ分析 /// /// # Phase 40削減計画 /// /// - **Phase 40-4**: JoinIrConservativeAnalyzerにインライン化 /// - **削減効果**: 30行(構造体定義+実装) /// - **保持**: Conservative ∘ Elimination理論コメント pub struct ConservativeMerge { // TODO(Phase 40-4): JoinIrConservativeAnalyzerに移行予定 /// 全ブランチに存在する変数のユニオン(Conservative戦略) pub all_vars: HashSet, /// 実際に変更された変数のセット(デバッグ/ヒント用) pub changed_vars: HashSet, } impl ConservativeMerge { /// 全変数のユニオンを計算(Conservative戦略) /// /// # Arguments /// * `pre_if` - if文前のスナップショット /// * `then_end` - then-branch終了時の変数マップ /// * `else_end_opt` - else-branch終了時の変数マップ(Noneの場合はempty else) /// /// # Phase 40-2で使用される(compute_modified_names削除時) pub fn analyze( pre_if: &BTreeMap, // Phase 25.1: BTreeMap化 then_end: &BTreeMap, // Phase 25.1: BTreeMap化 else_end_opt: &Option>, // Phase 25.1: BTreeMap化 ) -> Self { // TODO(Phase 40-2/40-4): JoinIR Verifierに移行 let mut all_vars = HashSet::new(); all_vars.extend(pre_if.keys().cloned()); all_vars.extend(then_end.keys().cloned()); if let Some(ref else_map) = else_end_opt { all_vars.extend(else_map.keys().cloned()); } // Phase 47: compute_modified_names インライン化(if_phi.rs から削除) // 決定的順序のためBTreeSet使用 let mut names: BTreeSet<&str> = BTreeSet::new(); for k in then_end.keys() { names.insert(k.as_str()); } if let Some(emap) = else_end_opt.as_ref() { for k in emap.keys() { names.insert(k.as_str()); } } let mut changed_vars = HashSet::new(); // アルファベット順で決定的にイテレート for &name in &names { let pre = pre_if.get(name); let t = then_end.get(name); let e = else_end_opt.as_ref().and_then(|m| m.get(name)); if (t.is_some() && Some(*t.unwrap()) != pre.copied()) || (e.is_some() && Some(*e.unwrap()) != pre.copied()) { changed_vars.insert(name.to_string()); } } Self { all_vars, changed_vars, } } // Phase 41-1削除済み(2025-11-29) // - get_conservative_values (48行) - PhiBuilderBox::get_conservative_if_values()に置き換え済み // Phase 42削除済み(2025-11-28) // - trace_if_enabled (29行) - phi_merge.rs の既存 trace_conservative と重複していたため削除 } #[cfg(test)] mod tests { use super::*; #[test] fn test_conservative_merge_both_defined() { let mut pre_if = BTreeMap::new(); pre_if.insert("x".to_string(), ValueId::new(1)); let mut then_end = BTreeMap::new(); then_end.insert("x".to_string(), ValueId::new(2)); let mut else_end = BTreeMap::new(); else_end.insert("x".to_string(), ValueId::new(3)); let merge = ConservativeMerge::analyze(&pre_if, &then_end, &Some(else_end)); assert_eq!(merge.all_vars.len(), 1); assert!(merge.all_vars.contains("x")); } #[test] fn test_conservative_merge_union() { let pre_if = BTreeMap::new(); let mut then_end = BTreeMap::new(); then_end.insert("x".to_string(), ValueId::new(1)); let mut else_end = BTreeMap::new(); else_end.insert("y".to_string(), ValueId::new(2)); let merge = ConservativeMerge::analyze(&pre_if, &then_end, &Some(else_end)); assert_eq!(merge.all_vars.len(), 2); assert!(merge.all_vars.contains("x")); assert!(merge.all_vars.contains("y")); } }