Files
hakorune/src/mir/phi_core/conservative.rs

149 lines
5.5 KiB
Rust
Raw Normal View History

//! 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<String>,
/// 実際に変更された変数のセット(デバッグ/ヒント用)
pub changed_vars: HashSet<String>,
}
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<String, ValueId>, // Phase 25.1: BTreeMap化
then_end: &BTreeMap<String, ValueId>, // Phase 25.1: BTreeMap化
else_end_opt: &Option<BTreeMap<String, ValueId>>, // 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"));
}
}