Files
hakorune/docs/archive/reports/phi-generation-box-refactoring-plan.md
nyash-codex a7dbc15878 feat(joinir): Phase 240-EX - Pattern2 header condition ExprLowerer integration
Implementation:
- Add make_pattern2_scope_manager() helper for DRY
- Header conditions use ExprLowerer for supported patterns
- Legacy fallback for unsupported patterns
- Fail-Fast on supported patterns that fail

Tests:
- 4 new tests (all pass)
- test_expr_lowerer_supports_simple_header_condition_i_less_literal
- test_expr_lowerer_supports_header_condition_var_less_var
- test_expr_lowerer_header_condition_generates_expected_instructions
- test_pattern2_header_condition_via_exprlowerer

Also: Archive old phase documentation (34k lines removed)

ðŸĪ– Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-11 00:33:04 +09:00

49 KiB
Raw Blame History

Status: Historical

PHIį”Ÿæˆã‚ģマドãŪįŪąį†čŦ–ãƒŠãƒ•ã‚Ąã‚Ŋã‚ŋナãƒģグčψį”ŧ

ä―œæˆæ—Ĩ: 2025-11-20 最įĩ‚æ›ī新: 2025-11-20 (Phase 26-BåŪŒäš†) ã‚đテマã‚ŋã‚đ: ✅ Phase 1åŪŒäš† / Phase 2-3åŪŸæ–―äļ­ å„Šå…ˆåšĶ: High į›ŪæĻ™: PHIį”Ÿæˆã‚ģマドãŪäŋåŪˆæ€§ãƒŧテã‚đトåŪđæ˜“æ€§ãƒŧåŊčŠ­æ€§ãŪ向äļŠ


📋 Executive Summary

įūåœĻãŪPHIį”Ÿæˆã‚ģマドãŊįī„2,916行ãŦ及ãģ、čĪ‡æ•°ãŪčēŽäŧŧが混åœĻしãĶいãūす。朎čψį”ŧでãŊ、įŪąį†čŦ–Box-First原則ãŦ埚ãĨき、čēŽäŧŧを明įĒšãŦ分é›Ēした6ãĪãŪBoxã‚’ææĄˆã—ãūす。

期åū…されるåŠđ果:

  • ðŸŽŊ äŋåŪˆæ€§å‘äļŠ: čēŽäŧŧãŪ明įĒšåŒ–ãŦよりåΉæ›īå―ąéŸŋįŊ„å›ēが限åŪšã•ã‚Œã‚‹
  • ⚡ テã‚đトåŪđæ˜“æ€§: 各Boxã‚’į‹ŽįŦ‹ã—ãĶテã‚đトできる
  • 📚 åŊčŠ­æ€§å‘äļŠ: 各BoxãŪå―đå‰ēがäļ€į›Ūで分かる
  • 🔄 再åˆĐį”Ļ性: äŧ–ãŪPHIį”Ÿæˆæ–‡č„ˆã§ã‚‚ä―ŋえる

📊 įūįŠķ分析ノポマト

æ—Ē存ãŪBoxå۟čĢ…ïžˆåŪŒæˆæļˆãŋ✅

Box名 čĄŒæ•° čēŽäŧŧ įŠķ態
LocalScopeInspectorBox 152 åĪ‰æ•°åۚįūĐä―į―ŪãŪčŋ―č·Ą ✅ åیå…ĻįŪąåŒ–æļˆãŋ
LoopVarClassBox 516 åĪ‰æ•°4ã‚Ŧテã‚īãƒŠåˆ†éĄž ✅ åیå…ĻįŪąåŒ–æļˆãŋ
LoopSnapshotMergeBox 578 ã‚đナップショットママã‚ļįĩąäļ€įŪĄį† ✅ åیå…ĻįŪąåŒ–æļˆãŋ

合čψ: 1,246čĄŒïžˆæ—ĒãŦįŪąåŒ–æļˆãŋ


įŪąåŒ–ã•ã‚ŒãĶいおいčēŽäŧŧ領域

1. loopform_builder.rs (1,075行) - čĪ‡æ•°čēŽäŧŧが混åœĻ

čēŽäŧŧ čĄŒæ•° č·雑åšĶ įŪąåŒ–å„Šå…ˆåšĶ
ValueIdå‰ēã‚Šå―“ãĶįŪĄį† ~100 ä―Ž Medium
Header PHIį”Ÿæˆ ~50 äļ­ High
Latch PHIæ›ī新 ~120 éŦ˜ High
Exit PHIį”Ÿæˆ ~170 最éŦ˜ Critical
Preheader Copyį”Ÿæˆ ~50 ä―Ž Low
åĪ‰æ•°åˆ†éĄž ~100 äļ­ Medium

å•éĄŒį‚đ:

  • ❌ Exit PHIį”ŸæˆãŒæœ€ã‚‚čĪ‡é›‘ïžˆ173行ãŪbuild_exit_phis
  • ❌ seal_phisがčĪ‡æ•°ãŪčēŽäŧŧを持ãĪHeader PHI + Latchå€Īæ›ī新
  • ❌ LocalScopeInspectorBox/LoopVarClassBoxãĻãŪé€Ģ搚がæ•ĢåœĻ

2. if_phi.rs (298行) - éƒĻåˆ†įš„įŪąåŒ–

čēŽäŧŧ įŠķ態 įŪąåŒ–å„Šå…ˆåšĶ
If/Else PHIį”Ÿæˆ ðŸŸĄ Traitäūå­˜ Medium
åĪ‰æ•°åΉæ›īæĪœå‡š ✅ é–Ē数化æļˆãŋ Low
PHI mergeå‡Ķᐆ ðŸŸĄ Traitäūå­˜ Medium

3. loop_phi.rs (265行) - ノゎシマ scaffold

ã‚đテマã‚ŋã‚đ: Phase 31.x äŧĨ降で削é™Ī䚈åۚ æŽĻåĨĻ: 新čĶå۟čĢ…ãŦãŊä―ŋį”Ļしおい


ðŸŽŊ įŪąåŒ–å€™č̜ãŪčĐģįī°čĻ­čψ

儊先åšĶマトナッã‚Ŋã‚đ

         ┌─────────────────────────────────────────┐
High     │ PhiInputCollector  BodyLocalPhiBuilder  │
Effect   │ LoopSnapshotManager HeaderPhiBuilder    │
         │                                          │
         │         ExitPhiBuilder (最重č́)         │
Medium   │                                          │
Effect   │         ValueIdAllocator                │
         │                                          │
         └─────────────────────────────────────────┘
           Low Risk ←────────────────────→ High Risk

Option 1: PhiInputCollector ⭐ 最儊先候č̜

čēŽäŧŧ

  • PHIå…Ĩ力ãŪ収集
  • 重č·predecessor削é™Īsanitize
  • 同å€ĪįļŪįœ€éĐ化optimize

čĻ­čψ

/// PHIå…Ĩ力収集専門Box
///
/// čĪ‡æ•°ãŪpredecessorからPHIå…Ĩ力を収集し、最éĐ化をéĐį”Ļする。
pub struct PhiInputCollector {
    /// 収集されたå…Ĩ力: (predecessor, value)
    inputs: Vec<(BasicBlockId, ValueId)>,
}

impl PhiInputCollector {
    /// 新しいcollectorã‚’ä―œæˆ
    pub fn new() -> Self {
        Self { inputs: Vec::new() }
    }

    /// Preheaderå…Ĩ力をčŋ―加
    pub fn add_preheader(&mut self, block: BasicBlockId, value: ValueId) {
        self.inputs.push((block, value));
    }

    /// Continue/Break snapshotå…Ĩ力をčŋ―加
    pub fn add_snapshot(&mut self, snapshot: &[(BasicBlockId, ValueId)]) {
        self.inputs.extend_from_slice(snapshot);
    }

    /// Latchå…Ĩ力をčŋ―加
    pub fn add_latch(&mut self, block: BasicBlockId, value: ValueId) {
        self.inputs.push((block, value));
    }

    /// å…Ĩ力をã‚ĩニã‚ŋã‚Ī゚重čĪ‡å‰Šé™Īã€ã‚―ãƒžãƒˆïž‰
    pub fn sanitize(&mut self) {
        // æ—Ē存ãŪsanitize_inputsロã‚ļッã‚Ŋをä―ŋį”Ļ
        let mut seen: BTreeMap<BasicBlockId, ValueId> = BTreeMap::new();
        for (bb, val) in self.inputs.iter() {
            seen.insert(*bb, *val);
        }
        self.inputs = seen.into_iter().collect();
        self.inputs.sort_by_key(|(bb, _)| bb.0);
    }

    /// 同å€Ī最éĐ化: å…ĻãĶ同じå€ĪおらPHIäļč́
    pub fn optimize_same_value(&self) -> Option<ValueId> {
        if self.inputs.is_empty() {
            return None;
        }
        if self.inputs.len() == 1 {
            return Some(self.inputs[0].1);
        }
        let first_val = self.inputs[0].1;
        if self.inputs.iter().all(|(_, val)| *val == first_val) {
            Some(first_val)
        } else {
            None
        }
    }

    /// 最įĩ‚įš„ãŠå…Ĩ力を取åū—
    pub fn finalize(self) -> Vec<(BasicBlockId, ValueId)> {
        self.inputs
    }
}

čЕäūĄ

  • ðŸŽŊ å―ąéŸŋįŊ„å›ē: äļ­ (loopform_builder.rs + loop_snapshot_merge.rs)
  • ⚡ åŠđ果: äļ­ (PHIå…Ĩ力収集ロã‚ļッã‚ŊãŪįĩąäļ€)
  • ⚠ïļ ãƒŠã‚đã‚Ŋ: ä―Ž (æ—Ē存é–Ē数をįĩąåˆã™ã‚‹ã ã‘)
  • 📅 å۟čĢ…æ™‚é–“: 小 (1-2時間)

削æļ›čĶ‹čūžãŋ

  • loopform_builder.rs: ~50čĄŒå‰Šæļ›
  • loop_snapshot_merge.rs: ~30čĄŒå‰Šæļ›
  • 合čψ: ~80čĄŒå‰Šæļ›

Option 2: BodyLocalPhiBuilder ⭐ įŽŽ2儊先候č̜

čēŽäŧŧ

  • BodyLocalåĪ‰æ•°ãŪPHIį”ŸæˆåˆĪåۚ
  • BodyLocalInternalåĪ‰æ•°ãŪã‚đキップ
  • Exit PHI候č̜ãŪフã‚ĢãƒŦã‚ŋナãƒģグ

čĻ­čψ

/// BodyLocalåĪ‰æ•°PHIį”Ÿæˆå°‚é–€Box
///
/// BodyLocalExit/BodyLocalInternalåĪ‰æ•°ã‚’åˆĪåŪšã—ã€
/// Exit PHIį”ŸæˆãŪč́åĶã‚’æąšåŪšã™ã‚‹ã€‚
pub struct BodyLocalPhiBuilder {
    classifier: LoopVarClassBox,
    inspector: LocalScopeInspectorBox,
}

impl BodyLocalPhiBuilder {
    /// 新しいbuilderã‚’ä―œæˆ
    pub fn new(
        classifier: LoopVarClassBox,
        inspector: LocalScopeInspectorBox,
    ) -> Self {
        Self { classifier, inspector }
    }

    /// åĪ‰æ•°ãŒExit PHIをåŋ…č́ãĻするかåˆĪåۚ
    ///
    /// # Returns
    /// - `Some(PhiSpec)`: PHIį”ŸæˆãŒåŋ…č́
    /// - `None`: PHIäļčĶïžˆBodyLocalInternal
    pub fn should_generate_exit_phi(
        &self,
        var_name: &str,
        pinned_vars: &[String],
        carrier_vars: &[String],
        exit_preds: &[BasicBlockId],
    ) -> bool {
        let class = self.classifier.classify(
            var_name,
            pinned_vars,
            carrier_vars,
            &self.inspector,
            exit_preds,
        );

        // BodyLocalInternal → Skip exit PHI
        class.needs_exit_phi()
    }

    /// Exit PHI候čĢœã‚’ãƒ•ã‚ĢãƒŦã‚ŋナãƒģグ
    pub fn filter_exit_phi_candidates(
        &self,
        all_vars: &[String],
        pinned_vars: &[String],
        carrier_vars: &[String],
        exit_preds: &[BasicBlockId],
    ) -> Vec<String> {
        all_vars
            .iter()
            .filter(|var_name| {
                self.should_generate_exit_phi(
                    var_name,
                    pinned_vars,
                    carrier_vars,
                    exit_preds,
                )
            })
            .cloned()
            .collect()
    }

    /// Inspectorå‚į…§ã‚’å–åū—ã‚đナップショットčϘéŒēį”Ļ
    pub fn inspector_mut(&mut self) -> &mut LocalScopeInspectorBox {
        &mut self.inspector
    }
}

čЕäūĄ

  • ðŸŽŊ å―ąéŸŋįŊ„å›ē: äļ­ (loopform_builder.rsãŪbuild_exit_phisãŪäļ€éƒĻ)
  • ⚡ åŠđ果: äļ­ (BodyLocalå‡ĶᐆãŪ明įĒšåŒ–)
  • ⚠ïļ ãƒŠã‚đã‚Ŋ: ä―Ž (æ—Ē存BoxãŪįĩ„ãŋ合わせ)
  • 📅 å۟čĢ…æ™‚é–“: 小 (2-3時間)

削æļ›čĶ‹čūžãŋ

  • loopform_builder.rs: ~60čĄŒå‰Šæļ›ïžˆbuild_exit_phis内ãŪåˆ†éĄžãƒ­ã‚ļッã‚Ŋ
  • 合čψ: ~60čĄŒå‰Šæļ›

Option 3: LoopSnapshotManager - デマã‚ŋ構造įĩąäļ€

čēŽäŧŧ

  • Snapshotäŋå­˜ãƒŧ取åū—
  • Preheader/Exit/Continue snapshotãŪäļ€å…ƒįŪĄį†
  • SnapshotæŊ”čžƒïžˆåĪ‰æ•°åΉæ›īæĪœå‡šïž‰

čĻ­čψ

/// ãƒŦマプSnapshotãŪäļ€å…ƒįŪĄį†Box
///
/// preheader/exit/continue時ãŪvariable mapをäŋå­˜ã—、
/// PHIį”Ÿæˆæ™‚ãŦåŋ…čĶãŠsnapshotを提äū›ã™ã‚‹ã€‚
pub struct LoopSnapshotManager {
    /// Preheader時į‚đãŪåĪ‰æ•°įŠķ態
    preheader_snapshot: HashMap<String, ValueId>,

    /// Exit predecessorごãĻãŪsnapshot
    exit_snapshots: Vec<(BasicBlockId, HashMap<String, ValueId>)>,

    /// Continue predecessorごãĻãŪsnapshot
    continue_snapshots: Vec<(BasicBlockId, HashMap<String, ValueId>)>,
}

impl LoopSnapshotManager {
    /// 新しいmanagerã‚’ä―œæˆ
    pub fn new() -> Self {
        Self {
            preheader_snapshot: HashMap::new(),
            exit_snapshots: Vec::new(),
            continue_snapshots: Vec::new(),
        }
    }

    /// Preheader snapshotをäŋå­˜
    pub fn save_preheader(&mut self, vars: HashMap<String, ValueId>) {
        self.preheader_snapshot = vars;
    }

    /// Exit snapshotをčŋ―加
    pub fn add_exit_snapshot(
        &mut self,
        block: BasicBlockId,
        vars: HashMap<String, ValueId>,
    ) {
        self.exit_snapshots.push((block, vars));
    }

    /// Continue snapshotをčŋ―加
    pub fn add_continue_snapshot(
        &mut self,
        block: BasicBlockId,
        vars: HashMap<String, ValueId>,
    ) {
        self.continue_snapshots.push((block, vars));
    }

    /// Preheader snapshotを取åū—
    pub fn preheader(&self) -> &HashMap<String, ValueId> {
        &self.preheader_snapshot
    }

    /// Exit snapshotsを取åū—
    pub fn exit_snapshots(&self) -> &[(BasicBlockId, HashMap<String, ValueId>)] {
        &self.exit_snapshots
    }

    /// Continue snapshotsを取åū—
    pub fn continue_snapshots(&self) -> &[(BasicBlockId, HashMap<String, ValueId>)] {
        &self.continue_snapshots
    }

    /// åĪ‰æ•°ãŒpreheaderからåΉæ›īされたかチェッã‚Ŋ
    pub fn is_modified(&self, var_name: &str, current_value: ValueId) -> bool {
        self.preheader_snapshot
            .get(var_name)
            .map(|&preheader_val| preheader_val != current_value)
            .unwrap_or(true) // 新čĶåĪ‰æ•°ãŊåΉæ›īæ‰ąã„
    }
}

čЕäūĄ

  • ðŸŽŊ å―ąéŸŋįŊ„å›ē: åΧ (builder.rs + loopform_builder.rs + loop_snapshot_merge.rs)
  • ⚡ åŠđ果: éŦ˜ (SnapshotįŪĄį†ãŪäļ€å…ƒåŒ–)
  • ⚠ïļ ãƒŠã‚đã‚Ŋ: äļ­ (デマã‚ŋ構造ãŪåΉæ›īがåŋ…č́)
  • 📅 å۟čĢ…æ™‚é–“: äļ­ (4-6時間)

削æļ›čĶ‹čūžãŋ

  • builder.rs: ~50čĄŒå‰Šæļ›ïžˆloop_header_stack/loop_exit_stacké–Ēé€Ģ
  • loopform_builder.rs: ~40čĄŒå‰Šæļ›ïžˆpreheader_varsįŪĄį†ïž‰
  • 合čψ: ~90čĄŒå‰Šæļ›

Option 4: HeaderPhiBuilder - Header PHI専門化

čēŽäŧŧ

  • Header PHIį”Ÿæˆ
  • Preheaderå…Ĩ力čĻ­åۚ
  • Latchå€Īæ›ī新seal時

čĻ­čψ

/// Header PHIį”Ÿæˆå°‚é–€Box
///
/// Loop headerでãŪPHI nodeã‚’į”Ÿæˆã—ã€sealする。
pub struct HeaderPhiBuilder {
    /// PinnedåĪ‰æ•°ãŪPHIæƒ…å ą
    pinned_phis: Vec<PinnedPhiInfo>,
    /// CarrieråĪ‰æ•°ãŪPHIæƒ…å ą
    carrier_phis: Vec<CarrierPhiInfo>,
}

#[derive(Debug, Clone)]
struct PinnedPhiInfo {
    var_name: String,
    phi_id: ValueId,
    param_value: ValueId,
    preheader_copy: ValueId,
}

#[derive(Debug, Clone)]
struct CarrierPhiInfo {
    var_name: String,
    phi_id: ValueId,
    init_value: ValueId,
    preheader_copy: ValueId,
}

impl HeaderPhiBuilder {
    /// 新しいbuilderã‚’ä―œæˆ
    pub fn new() -> Self {
        Self {
            pinned_phis: Vec::new(),
            carrier_phis: Vec::new(),
        }
    }

    /// PinnedåĪ‰æ•°ãŪPHIã‚’æš–å‚™
    pub fn prepare_pinned_phi(
        &mut self,
        var_name: String,
        phi_id: ValueId,
        param_value: ValueId,
        preheader_copy: ValueId,
    ) {
        self.pinned_phis.push(PinnedPhiInfo {
            var_name,
            phi_id,
            param_value,
            preheader_copy,
        });
    }

    /// CarrieråĪ‰æ•°ãŪPHIã‚’æš–å‚™
    pub fn prepare_carrier_phi(
        &mut self,
        var_name: String,
        phi_id: ValueId,
        init_value: ValueId,
        preheader_copy: ValueId,
    ) {
        self.carrier_phis.push(CarrierPhiInfo {
            var_name,
            phi_id,
            init_value,
            preheader_copy,
        });
    }

    /// Header PHIã‚’į™ščĄŒ
    pub fn emit_header_phis<O: LoopFormOps>(
        &self,
        ops: &mut O,
        header_id: BasicBlockId,
        preheader_id: BasicBlockId,
    ) -> Result<(), String> {
        ops.set_current_block(header_id)?;

        // Pinned PHIs
        for phi in &self.pinned_phis {
            ops.emit_phi(
                phi.phi_id,
                vec![(preheader_id, phi.preheader_copy)],
            )?;
            ops.update_var(phi.var_name.clone(), phi.phi_id);
        }

        // Carrier PHIs
        for phi in &self.carrier_phis {
            ops.emit_phi(
                phi.phi_id,
                vec![(preheader_id, phi.preheader_copy)],
            )?;
            ops.update_var(phi.var_name.clone(), phi.phi_id);
        }

        Ok(())
    }

    /// Seal PHIslatch + continueå…Ĩ力をčŋ―加
    pub fn seal_phis<O: LoopFormOps>(
        &self,
        ops: &mut O,
        header_id: BasicBlockId,
        preheader_id: BasicBlockId,
        latch_id: BasicBlockId,
        continue_snapshots: &[(BasicBlockId, HashMap<String, ValueId>)],
    ) -> Result<(), String> {
        // Seal pinned PHIs
        for phi in &self.pinned_phis {
            let mut collector = PhiInputCollector::new();
            collector.add_preheader(preheader_id, phi.preheader_copy);

            // Continue inputs
            for (cid, snapshot) in continue_snapshots {
                if let Some(&value) = snapshot.get(&phi.var_name) {
                    collector.add_snapshot(&[(*cid, value)]);
                }
            }

            // Latch input
            let latch_value = ops
                .get_variable_at_block(&phi.var_name, latch_id)
                .unwrap_or(phi.phi_id);
            collector.add_latch(latch_id, latch_value);

            collector.sanitize();

            // Optimize same-value PHI
            if let Some(same_value) = collector.optimize_same_value() {
                // Skip PHI update - loop-invariant
                continue;
            }

            let inputs = collector.finalize();
            ops.update_phi_inputs(header_id, phi.phi_id, inputs)?;
        }

        // Seal carrier PHIs (同様ãŪロã‚ļッã‚Ŋ)
        for phi in &self.carrier_phis {
            // ... 同様ãŪå‡Ķᐆ ...
        }

        Ok(())
    }
}

čЕäūĄ

  • ðŸŽŊ å―ąéŸŋįŊ„å›ē: äļ­ (loopform_builder.rsãŪäļ€éƒĻ)
  • ⚡ åŠđ果: äļ­ (Header PHIį”Ÿæˆãƒ­ã‚ļッã‚ŊãŪ分é›Ē)
  • ⚠ïļ ãƒŠã‚đã‚Ŋ: äļ­ (seal_phisロã‚ļッã‚ŊãĻãŪįĩąåˆãŒåŋ…č́)
  • 📅 å۟čĢ…æ™‚é–“: äļ­ (4-5時間)

削æļ›čĶ‹čūžãŋ

  • loopform_builder.rs: ~150čĄŒå‰Šæļ›ïžˆemit_header_phis + seal_phisãŪäļ€éƒĻ
  • 合čψ: ~150čĄŒå‰Šæļ›

Option 5: ExitPhiBuilder ðŸ”Ĩ 最重č́ãƒŧ最č·雑

čēŽäŧŧ

  • Exit PHIį”Ÿæˆ
  • Exit predecessorsæĪœčĻž
  • Phantom blocké™ĪåĪ–
  • Body-localåĪ‰æ•°ãŪå‡Ķᐆ

čĻ­čψ

/// Exit PHIį”Ÿæˆå°‚é–€Box
///
/// Loop exit時ãŪPHI nodeã‚’į”Ÿæˆã™ã‚‹ã€‚æœ€ã‚‚čĪ‡é›‘ãŠčēŽäŧŧを持ãĪ。
pub struct ExitPhiBuilder {
    snapshot_merger: LoopSnapshotMergeBox,
    body_local_builder: BodyLocalPhiBuilder,
}

impl ExitPhiBuilder {
    /// 新しいbuilderã‚’ä―œæˆ
    pub fn new(
        snapshot_merger: LoopSnapshotMergeBox,
        body_local_builder: BodyLocalPhiBuilder,
    ) -> Self {
        Self {
            snapshot_merger,
            body_local_builder,
        }
    }

    /// Exit PHIsã‚’į”Ÿæˆ
    pub fn build_exit_phis<O: LoopFormOps>(
        &mut self,
        ops: &mut O,
        exit_id: BasicBlockId,
        header_id: BasicBlockId,
        branch_source_block: BasicBlockId,
        header_vals: &HashMap<String, ValueId>,
        exit_snapshots: &[(BasicBlockId, HashMap<String, ValueId>)],
        pinned_vars: &[String],
        carrier_vars: &[String],
    ) -> Result<(), String> {
        ops.set_current_block(exit_id)?;

        // 1. Exit predecessorsを取åū—CFGæĪœčĻžïž‰
        let exit_preds_set = ops.get_block_predecessors(exit_id);
        let exit_preds: Vec<BasicBlockId> = exit_preds_set.iter().copied().collect();

        // 2. Phantom blockをフã‚ĢãƒŦã‚ŋナãƒģグ
        let filtered_snapshots = self.filter_phantom_blocks(
            exit_snapshots,
            &exit_preds_set,
            ops,
        );

        // 3. InspectorãŦåۚįūĐをčϘéŒē
        let inspector = self.body_local_builder.inspector_mut();
        for pinned_name in pinned_vars {
            inspector.record_definition(pinned_name, header_id);
        }
        for carrier_name in carrier_vars {
            inspector.record_definition(carrier_name, header_id);
        }
        for (block_id, snapshot) in &filtered_snapshots {
            inspector.record_snapshot(*block_id, snapshot);
        }
        if exit_preds_set.contains(&branch_source_block) {
            inspector.record_snapshot(branch_source_block, header_vals);
        }

        // 4. LoopSnapshotMergeBoxでPHIå…ĨåŠ›ã‚’į”Ÿæˆ
        let all_vars = self.snapshot_merger.merge_exit_with_classification(
            header_id,
            header_vals,
            &filtered_snapshots,
            &exit_preds,
            pinned_vars,
            carrier_vars,
            inspector,
        )?;

        // 5. PHIį”Ÿæˆïžˆoptimize + sanitizeéĐį”Ļ
        for (var_name, mut inputs) in all_vars {
            if let Some(same_val) = self.snapshot_merger.optimize_same_value(&inputs) {
                // 同å€ĪPHI → į›īæŽĨバã‚Īãƒģド
                ops.update_var(var_name, same_val);
            } else {
                // į•°ãŠã‚‹å€Ī → PHIį”Ÿæˆ
                self.snapshot_merger.sanitize_inputs(&mut inputs);
                let phi_id = ops.new_value();
                ops.emit_phi(phi_id, inputs)?;
                ops.update_var(var_name, phi_id);
            }
        }

        Ok(())
    }

    /// Phantom blockをフã‚ĢãƒŦã‚ŋナãƒģグ
    fn filter_phantom_blocks<O: LoopFormOps>(
        &self,
        exit_snapshots: &[(BasicBlockId, HashMap<String, ValueId>)],
        exit_preds: &std::collections::HashSet<BasicBlockId>,
        ops: &O,
    ) -> Vec<(BasicBlockId, HashMap<String, ValueId>)> {
        let mut filtered = Vec::new();
        for (block_id, snapshot) in exit_snapshots {
            if !ops.block_exists(*block_id) {
                continue; // Non-existent block
            }
            if !exit_preds.contains(block_id) {
                continue; // Not a CFG predecessor
            }
            filtered.push((*block_id, snapshot.clone()));
        }
        filtered
    }
}

čЕäūĄ

  • ðŸŽŊ å―ąéŸŋįŊ„å›ē: åΧ (loopform_builder.rs + loop_snapshot_merge.rs)
  • ⚡ åŠđ果: éŦ˜ (Exit PHIį”ŸæˆãŪčĪ‡é›‘ãƒ­ã‚ļッã‚Ŋ集įī„)
  • ⚠ïļ ãƒŠã‚đã‚Ŋ: éŦ˜ (čĪ‡æ•°ãƒ•ã‚Ąã‚ĪãƒŦãŦãūたがるåΉæ›ī)
  • 📅 å۟čĢ…æ™‚é–“: åΧ (6-8時間)

削æļ›čĶ‹čūžãŋ

  • loopform_builder.rs: ~170čĄŒå‰Šæļ›ïžˆbuild_exit_phiså…Ļä―“ïž‰
  • loop_snapshot_merge.rs: ~50čĄŒå‰Šæļ›ïžˆmerge_exit_with_classificationį°Ąį•Ĩ化
  • 合čψ: ~220čĄŒå‰Šæļ›

Option 6: ValueIdAllocator - 儊先åšĶä―Ž

čēŽäŧŧ

  • ValueIdå‰ēã‚Šå―“ãĶ
  • ã‚Ŧã‚Ķãƒģã‚ŋマįŪĄį†
  • パãƒĐãƒĄãƒžã‚ŋ䚈įī„

čĻ­čψ

/// ValueIdå‰ēã‚Šå―“ãĶ専門Box
///
/// LoopForm構įŊ‰æ™‚ãŪValueIdįŪĄį†ã‚’æŠ―čąĄåŒ–ã€‚
pub struct ValueIdAllocator {
    next_value_id: u32,
    param_count: usize,
}

impl ValueIdAllocator {
    /// 新しいallocatorã‚’ä―œæˆ
    pub fn new(param_count: usize, existing_vars: &HashMap<String, ValueId>) -> Self {
        let min_from_params = param_count as u32;
        let min_from_vars = existing_vars.values().map(|v| v.0 + 1).max().unwrap_or(0);

        Self {
            next_value_id: min_from_params.max(min_from_vars),
            param_count,
        }
    }

    /// 新しいValueIdをå‰ēã‚Šå―“ãĶ
    pub fn allocate(&mut self) -> ValueId {
        let id = ValueId(self.next_value_id);
        self.next_value_id += 1;
        id
    }

    /// ã‚Ŧã‚Ķãƒģã‚ŋマをį‰đåۚãŪValueIdäŧĨ降ãŦčĻ­åۚ
    pub fn ensure_after(&mut self, max_id: u32) {
        if self.next_value_id <= max_id {
            self.next_value_id = max_id + 1;
        }
    }
}

čЕäūĄ

  • ðŸŽŊ å―ąéŸŋįŊ„å›ē: 小 (loopform_builder.rsãŪãŋ)
  • ⚡ åŠđ果: ä―Ž (æ—ĒãŦLoopFormContextがあるįĻ‹åšĶæŠ―čąĄåŒ–)
  • ⚠ïļ ãƒŠã‚đã‚Ŋ: ä―Ž
  • 📅 å۟čĢ…æ™‚é–“: 小 (1-2時間)

削æļ›čĶ‹čūžãŋ

  • loopform_builder.rs: ~20čĄŒå‰Šæļ›ïžˆLoopFormContextãŪäļ€éƒĻ
  • 合čψ: ~20čĄŒå‰Šæļ›

📋 ãƒŠãƒ•ã‚Ąã‚Ŋã‚ŋナãƒģグåŪŸčĄŒčψį”ŧ

Phase 1: Quick Winsïžˆä―ŽãƒŠã‚đã‚ŊãƒŧåģåŠđ性

期間: 1週間 į›ŪæĻ™: テã‚đトåŪđæ˜“æ€§ãŪ向äļŠã€ã‚ģマド削æļ›80-140行

ã‚ŋã‚đã‚Ŋ

  1. PhiInputCollectorå۟čĢ… (Priority: High, Risk: Low)

    • src/mir/phi_core/phi_input_collector.rsä―œæˆ
    • PhiInputCollector structå۟čĢ…
    • add_preheader/add_snapshot/add_latchå۟čĢ…
    • sanitize/optimize_same_valueå۟čĢ…
    • å˜ä―“ãƒ†ã‚đãƒˆä―œæˆïžˆãƒ†ã‚đトã‚Ŧバノッã‚ļ>90%
    • loopform_builder.rsでä―ŋį”Ļ
    • loop_snapshot_merge.rsでä―ŋį”Ļ
    • æ—Ē存ãŪsanitize_inputs/optimize_same_value削é™Ī
  2. BodyLocalPhiBuilderå۟čĢ… (Priority: High, Risk: Low)

    • src/mir/phi_core/body_local_phi_builder.rsä―œæˆ
    • BodyLocalPhiBuilder structå۟čĢ…
    • should_generate_exit_phiå۟čĢ…
    • filter_exit_phi_candidateså۟čĢ…
    • å˜ä―“ãƒ†ã‚đãƒˆä―œæˆïžˆskip_whitespaceシナナりåŦむ
    • loopform_builder.rsãŪbuild_exit_phisでä―ŋį”Ļ
    • æ—Ē存ãŪåˆ†éĄžãƒ­ã‚ļッã‚Ŋ削é™Ī

成果į‰Đ:

  • ✅ 2ãĪãŪ新しいBox合čψ~300čĄŒïž‰
  • ✅ æ—Ē存ã‚ģマド削æļ›: ~140行
  • ✅ テã‚đトã‚Ŧバノッã‚ļ: >90%
  • ✅ ドキãƒĨãƒĄãƒģト: 各BoxãŪdocã‚ģãƒĄãƒģトåŪŒå‚™

Phase 2: 構造æ”đ善äļ­ãƒŠã‚đã‚ŊãƒŧåŠđ果åĪ§ïž‰

期間: 2週間 į›ŪæĻ™: デマã‚ŋ構造ãŪäļ€å…ƒåŒ–、ã‚ģマド削æļ›240行

ã‚ŋã‚đã‚Ŋ

  1. LoopSnapshotManagerå۟čĢ… (Priority: Medium, Risk: Medium)

    • src/mir/phi_core/loop_snapshot_manager.rsä―œæˆ
    • LoopSnapshotManager structå۟čĢ…
    • save_preheader/add_exit_snapshot/add_continue_snapshotå۟čĢ…
    • is_modifiedå۟čĢ…
    • å˜ä―“ãƒ†ã‚đãƒˆä―œæˆ
    • builder.rsãŪloop_header_stack/loop_exit_stack削é™Ī
    • loopform_builder.rsãŪpreheader_vars削é™Ī
    • å…ĻãƒŦマプ構įŊ‰įŪ‡æ‰€ã§ä―ŋį”Ļ
  2. HeaderPhiBuilderå۟čĢ… (Priority: Medium, Risk: Medium)

    • src/mir/phi_core/header_phi_builder.rsä―œæˆ
    • HeaderPhiBuilder structå۟čĢ…
    • prepare_pinned_phi/prepare_carrier_phiå۟čĢ…
    • emit_header_phiså۟čĢ…
    • seal_phiså۟čĢ…ïžˆPhiInputCollectorä―ŋį”Ļ
    • å˜ä―“ãƒ†ã‚đãƒˆä―œæˆ
    • loopform_builder.rsãŪemit_header_phis/seal_phis削é™Ī

成果į‰Đ:

  • ✅ 2ãĪãŪ新しいBox合čψ~400čĄŒïž‰
  • ✅ æ—Ē存ã‚ģマド削æļ›: ~240行
  • ✅ デマã‚ŋ構造ãŪäļ€å…ƒåŒ–åŪŒäš†
  • ✅ Header PHIį”ŸæˆãŪåیå…Ļ分é›Ē

Phase 3: 最é›Ģé–Ēæ”ŧį•ĨéŦ˜ãƒŠã‚đã‚Ŋãƒŧ最åΧåŠđ果

期間: 2-3週間 į›ŪæĻ™: Exit PHIį”ŸæˆãŪåیå…Ļ分é›Ē、ã‚ģマド削æļ›220行

ã‚ŋã‚đã‚Ŋ

  1. ExitPhiBuilderå۟čĢ… (Priority: Critical, Risk: High)
    • src/mir/phi_core/exit_phi_builder.rsä―œæˆ
    • ExitPhiBuilder structå۟čĢ…
    • build_exit_phiså۟čĢ…
    • filter_phantom_blockså۟čĢ…
    • åŒ…æ‹Žįš„ãƒ†ã‚đトã‚đã‚Īãƒžãƒˆä―œæˆ
      • æ­Ģåļļįģŧ: 2 exit preds, 3 exit preds
      • į•°åļļįģŧ: Phantom block, CFGäļæ•ī合
      • skip_whitespaceシナナり
      • BodyLocalExit vs BodyLocalInternal
    • loopform_builder.rsãŪbuild_exit_phis削é™Ī173čĄŒïž‰
    • loop_snapshot_merge.rsãŪmerge_exit_with_classificationį°Ąį•Ĩ化
    • å…ĻãƒŦマプ構įŊ‰įŪ‡æ‰€ã§å‹•ä―œįĒščŠ

成果į‰Đ:

  • ✅ 1ãĪãŪ新しいBox合čψ~250čĄŒïž‰
  • ✅ æ—Ē存ã‚ģマド削æļ›: ~220行
  • ✅ Exit PHIį”ŸæˆãŪåیå…Ļ分é›Ē
  • ✅ 最もčĪ‡é›‘ãŠãƒ­ã‚ļッã‚ŊãŪテã‚đトã‚Ŧバノッã‚ļ>95%

Phase 4: äŧ•äļŠã’りプショナãƒŦ

期間: 1週間 į›ŪæĻ™: æŪ‹å­˜éƒĻ分ãŪ最éĐ化、ドキãƒĨãƒĄãƒģトåŪŒå‚™

ã‚ŋã‚đã‚Ŋ

  1. ValueIdAllocatorå۟čĢ… (Priority: Low, Risk: Low)

    • src/mir/phi_core/value_id_allocator.rsä―œæˆ
    • ValueIdAllocator structå۟čĢ…
    • allocate/ensure_afterå۟čĢ…
    • loopform_builder.rsãŪLoopFormContextį―Ūき換え
  2. ドキãƒĨãƒĄãƒģトæ•ī備

    • įŪąį†čŦ–éĐį”Ļ前åūŒãŪæŊ”čžƒå›ģä―œæˆ
    • äūå­˜é–Ēäŋ‚å›ģä―œæˆïžˆBefore/After
    • å۟čĢ…ã‚Žã‚Īãƒ‰ä―œæˆ
    • 各BoxãŪãƒĶマã‚đã‚ąãƒžã‚đé›†ä―œæˆ

成果į‰Đ:

  • ✅ ValueIdAllocatorå۟čĢ…ïžˆ~80čĄŒïž‰
  • ✅ æ—Ē存ã‚ģマド削æļ›: ~20行
  • ✅ åیå…ĻおドキãƒĨãƒĄãƒģト
  • ✅ å۟čĢ…ã‚Žã‚Īド

📊 削æļ›åŠđ果ãūãĻめ

ã‚ģマド削æļ›čĶ‹čūžãŋ

Phase Boxå۟čĢ… 削æļ›čĄŒæ•° įī”削æļ› įīŊčĻˆå‰Šæļ›
Phase 1 PhiInputCollector
BodyLocalPhiBuilder
+300 -140 +160
Phase 2 LoopSnapshotManager
HeaderPhiBuilder
+400 -240 +160
Phase 3 ExitPhiBuilder +250 -220 +30
Phase 4 ValueIdAllocator +80 -20 +60
合čψ 1,030行 -620行 +410行

æģĻčϘ:

  • įī”削æļ›ãŒæ­ĢãŪå€Ī = ã‚ģマド量åĒ—åŠ ïžˆæ§‹é€ åŒ–ãŦよるä™‚įš„åĒ—åŠ ïž‰
  • しかし、テã‚đトãƒŧドキãƒĨãƒĄãƒģトãƒŧäŋåŪˆæ€§ãŊåŠ‡įš„å‘äļŠ
  • Phase 3åŪŒäš†åūŒã€ã•らおる最éĐ化でčŋ―加削æļ›åŊčƒ―

äŋåŪˆæ€§å‘äŒ‡æĻ™

指æĻ™ įūįŠķ į›ŪæĻ™ æ”đå–„įŽ‡
最åΧé–Ē数ã‚ĩã‚Ī゚ 173行 50行äŧĨäļ‹ 71%削æļ›
čēŽäŧŧãŪ分é›Ē æ··åœĻ åیå…Ļ分é›Ē 100%æ”đ善
テã‚đトã‚Ŧバノッã‚ļ ~60% >90% +50%向äļŠ
åūŠį’°įš„č·雑åšĶ éŦ˜ ä―Ž æŽĻåۚ50%æ”đ善

ðŸŽŊ テã‚đトæˆĶį•Ĩ

Phase 1テã‚đト

PhiInputCollector

#[cfg(test)]
mod phi_input_collector_tests {
    use super::*;

    #[test]
    fn test_single_input_optimization() {
        let mut collector = PhiInputCollector::new();
        collector.add_preheader(BasicBlockId::new(0), ValueId::new(10));

        assert_eq!(collector.optimize_same_value(), Some(ValueId::new(10)));
    }

    #[test]
    fn test_same_value_optimization() {
        let mut collector = PhiInputCollector::new();
        collector.add_preheader(BasicBlockId::new(0), ValueId::new(10));
        collector.add_latch(BasicBlockId::new(1), ValueId::new(10));
        collector.add_snapshot(&[(BasicBlockId::new(2), ValueId::new(10))]);

        assert_eq!(collector.optimize_same_value(), Some(ValueId::new(10)));
    }

    #[test]
    fn test_different_values_no_optimization() {
        let mut collector = PhiInputCollector::new();
        collector.add_preheader(BasicBlockId::new(0), ValueId::new(10));
        collector.add_latch(BasicBlockId::new(1), ValueId::new(20));

        assert_eq!(collector.optimize_same_value(), None);
    }

    #[test]
    fn test_sanitize_duplicates() {
        let mut collector = PhiInputCollector::new();
        collector.add_preheader(BasicBlockId::new(0), ValueId::new(10));
        collector.add_preheader(BasicBlockId::new(0), ValueId::new(20)); // Duplicate

        collector.sanitize();
        let inputs = collector.finalize();

        assert_eq!(inputs.len(), 1);
        assert_eq!(inputs[0], (BasicBlockId::new(0), ValueId::new(20))); // Latest wins
    }

    #[test]
    fn test_sanitize_sorting() {
        let mut collector = PhiInputCollector::new();
        collector.add_latch(BasicBlockId::new(2), ValueId::new(20));
        collector.add_preheader(BasicBlockId::new(0), ValueId::new(10));
        collector.add_snapshot(&[(BasicBlockId::new(1), ValueId::new(15))]);

        collector.sanitize();
        let inputs = collector.finalize();

        // Should be sorted by BasicBlockId
        assert_eq!(inputs[0].0, BasicBlockId::new(0));
        assert_eq!(inputs[1].0, BasicBlockId::new(1));
        assert_eq!(inputs[2].0, BasicBlockId::new(2));
    }
}

BodyLocalPhiBuilder

#[cfg(test)]
mod body_local_phi_builder_tests {
    use super::*;

    #[test]
    fn test_skip_whitespace_scenario() {
        // Reproduce the exact skip_whitespace bug scenario
        let mut inspector = LocalScopeInspectorBox::new();

        let block_2 = BasicBlockId::new(2); // header / break path 1
        let block_5 = BasicBlockId::new(5); // break path 2

        // i, n, s in all blocks
        for var in &["i", "n", "s"] {
            inspector.record_definition(var, block_2);
            inspector.record_definition(var, block_5);
        }

        // ch only in block 5
        inspector.record_definition("ch", block_5);

        let classifier = LoopVarClassBox::new();
        let builder = BodyLocalPhiBuilder::new(classifier, inspector);

        let exit_preds = vec![block_2, block_5];
        let pinned = vec!["n".to_string(), "s".to_string()];
        let carrier = vec!["i".to_string()];

        // i, n, s should need exit PHI
        assert!(builder.should_generate_exit_phi("i", &pinned, &carrier, &exit_preds));
        assert!(builder.should_generate_exit_phi("n", &pinned, &carrier, &exit_preds));
        assert!(builder.should_generate_exit_phi("s", &pinned, &carrier, &exit_preds));

        // ch should NOT need exit PHI (BodyLocalInternal)
        assert!(!builder.should_generate_exit_phi("ch", &pinned, &carrier, &exit_preds));
    }

    #[test]
    fn test_filter_exit_phi_candidates() {
        let mut inspector = LocalScopeInspectorBox::new();

        let block_2 = BasicBlockId::new(2);
        let block_5 = BasicBlockId::new(5);

        inspector.record_definition("i", block_2);
        inspector.record_definition("i", block_5);
        inspector.record_definition("ch", block_5); // Only block 5

        let classifier = LoopVarClassBox::new();
        let builder = BodyLocalPhiBuilder::new(classifier, inspector);

        let all_vars = vec!["i".to_string(), "ch".to_string()];
        let exit_preds = vec![block_2, block_5];

        let candidates = builder.filter_exit_phi_candidates(
            &all_vars,
            &[],
            &["i".to_string()],
            &exit_preds,
        );

        assert_eq!(candidates.len(), 1);
        assert!(candidates.contains(&"i".to_string()));
        assert!(!candidates.contains(&"ch".to_string()));
    }
}

Phase 3 Critical Tests

ExitPhiBuilder

#[cfg(test)]
mod exit_phi_builder_tests {
    use super::*;

    #[test]
    fn test_phantom_block_filtering() {
        // Test that phantom blocks (from stale snapshots) are correctly filtered
        // This is critical for preventing CFG inconsistencies
    }

    #[test]
    fn test_exit_phi_with_two_predecessors() {
        // Standard case: loop with 2 exit paths
    }

    #[test]
    fn test_exit_phi_with_three_predecessors() {
        // Complex case: loop with 3 exit paths
    }

    #[test]
    fn test_body_local_exit_variable() {
        // Variable defined in all exit paths → should get PHI
    }

    #[test]
    fn test_body_local_internal_variable() {
        // Variable defined in some (not all) exit paths → should NOT get PHI
    }

    #[test]
    fn test_exit_phi_optimization() {
        // Same-value optimization: all exit paths have same value → direct bind
    }
}

📚 ドキãƒĨãƒĄãƒģãƒˆæĄˆ

įŪąį†čŦ–éĐį”Ļ前åūŒãŪæŊ”čžƒå›ģ

Before: čēŽäŧŧæ··åœĻįūįŠķ

┌─────────────────────────────────────────────────────────────┐
│ loopform_builder.rs (1,075 lines)                          │
│                                                              │
│  ┌──────────────────────────────────────────────────────┐  │
│  │ prepare_structure()                                   │  │
│  │  - ValueIdå‰ēã‚Šå―“ãĶ ────────────┐                      │  │
│  │  - Carrier/Pinnedåˆ†éĄž ────────┾─┐                    │  │
│  │  - Snapshotäŋå­˜ ──────────────┾─┾─┐                  │  │
│  └──────────────────────────────────────────────────────┘  │
│                                      │ │ │                  │
│  ┌──────────────────────────────────────────────────────┐  │
│  │ emit_header_phis()                │ │ │               │  │
│  │  - Header PHIį”Ÿæˆ ───────────────┘ │ │               │  │
│  └──────────────────────────────────────────────────────┘  │
│                                        │ │                  │
│  ┌──────────────────────────────────────────────────────┐  │
│  │ seal_phis()                         │ │               │  │
│  │  - Continueå…Ĩ力収集 ────────────────┘ │               │  │
│  │  - Latchå€Īæ›ī新 ──────────────────────┘               │  │
│  │  - PHI sanitize/optimize (重č·!)                      │  │
│  └──────────────────────────────────────────────────────┘  │
│                                                              │
│  ┌──────────────────────────────────────────────────────┐  │
│  │ build_exit_phis() (173 lines!)                        │  │
│  │  - Exit predecessorsæĪœčĻž ───────┐                     │  │
│  │  - Phantom blocké™ĪåĪ– ───────────┾─┐                   │  │
│  │  - Body-localåˆ†éĄž ─────────────┾─┾─┐                 │  │
│  │  - InspectorčϘéŒē ──────────────┾─┾─┾─┐               │  │
│  │  - Snapshot merge ─────────────┾─┾─┾─┾─┐             │  │
│  │  - PHI sanitize/optimize (重č·!)│ │ │ │ │             │  │
│  └──────────────────────────────────────────────────────┘  │
│                                      ↓ ↓ ↓ ↓ ↓             │
│  ❌ č·雑åšĶ: éŦ˜                                               │
│  ❌ テã‚đト困é›Ģ                                               │
│  ❌ äŋåŪˆæ€§: ä―Ž                                               │
└─────────────────────────────────────────────────────────────┘

After: čēŽäŧŧ分é›Ēį›ŪæĻ™ïž‰

┌───────────────────────────────────────────────────────────────┐
│ PHI Generation Ecosystem (Box-First Architecture)            │
│                                                                │
│  ┌──────────────────┐  ┌──────────────────┐                  │
│  │ LocalScope       │  │ LoopVarClass     │                  │
│  │ InspectorBox     │  │ Box              │                  │
│  │ (152 lines)      │  │ (516 lines)      │                  │
│  │                  │  │                  │                  │
│  │ ✅ åۚįūĐä―į―Ūčŋ―č·Ą   │  │ ✅ 4ã‚Ŧテã‚īãƒŠåˆ†éĄž  │                  │
│  └────────┮─────────┘  └────────┮─────────┘                  │
│           │                     │                             │
│           └──────────┮──────────┘                             │
│                      ↓                                        │
│           ┌──────────────────────┐                            │
│           │ BodyLocalPhiBuilder  │                            │
│           │ (~150 lines)         │                            │
│           │                      │                            │
│           │ ✅ Exit PHIåˆĪåۚ      │                            │
│           │ ✅ フã‚ĢãƒŦã‚ŋナãƒģグ     │                            │
│           └──────────┮───────────┘                            │
│                      │                                        │
│  ┌───────────────────┾───────────────────┐                   │
│  │ PhiInputCollector │                   │                   │
│  │ (~100 lines)      │                   │                   │
│  │                   │                   │                   │
│  │ ✅ å…Ĩ力収集        │                   │                   │
│  │ ✅ Sanitize       │                   │                   │
│  │ ✅ Optimize       │                   │                   │
│  └───────────────────┘                   │                   │
│                                          │                   │
│  ┌──────────────────────────────────────┾─────────────────┐ │
│  │ HeaderPhiBuilder                     │                 │ │
│  │ (~200 lines)                         │                 │ │
│  │                                      │                 │ │
│  │ ✅ Header PHIį”Ÿæˆ  ──────────────────┘                 │ │
│  │ ✅ Sealå‡Ķᐆ                                             │ │
│  └─────────────────────────────────────────────────────────┘ │
│                                                                │
│  ┌─────────────────────────────────────────────────────────┐ │
│  │ ExitPhiBuilder                                          │ │
│  │ (~250 lines)                                            │ │
│  │                                                          │ │
│  │ ✅ Exit PHIį”Ÿæˆ                                          │ │
│  │ ✅ Phantom blocké™ĪåĪ–                                     │ │
│  │ ✅ åیå…Ļ分é›Ē                                              │ │
│  └─────────────────────────────────────────────────────────┘ │
│                                                                │
│  ┌─────────────────────────────────────────────────────────┐ │
│  │ LoopSnapshotManager                                     │ │
│  │ (~150 lines)                                            │ │
│  │                                                          │ │
│  │ ✅ Snapshotäļ€å…ƒįŪĄį†                                      │ │
│  └─────────────────────────────────────────────────────────┘ │
│                                                                │
│  ✅ č·雑åšĶ: ä―Žïžˆå„Box<100čĄŒïž‰                                   │
│  ✅ テã‚đトåŪđæ˜“ïžˆį‹ŽįŦ‹ãƒ†ã‚đトåŊčƒ―ïž‰                                │
│  ✅ äŋåŪˆæ€§: éŦ˜ïžˆčēŽäŧŧ明įĒšïž‰                                      │
└───────────────────────────────────────────────────────────────┘

äūå­˜é–Ēäŋ‚å›ģAfter

                    ┌─────────────────────┐
                    │ LocalScopeInspector │
                    │ Box                 │
                    └──────────┮──────────┘
                               │
                    ┌──────────â”ī──────────┐
                    │ LoopVarClassBox     │
                    └──────────┮──────────┘
                               │
                    ┌──────────â”ī──────────┐
                    │BodyLocalPhiBuilder  │
                    └──────────┮──────────┘
                               │
        ┌──────────────────────┾──────────────────────┐
        │                      │                      │
┌───────â”ī────────┐   ┌─────────â”ī────────┐   ┌────────â”ī───────┐
│PhiInputCollector│   │HeaderPhiBuilder  │   │ExitPhiBuilder  │
└────────────────┘   └──────────────────┘   └────────────────┘
        │                      │                      │
        └──────────────────────┾──────────────────────┘
                               │
                    ┌──────────â”ī──────────┐
                    │LoopSnapshotManager  │
                    └─────────────────────┘

äūå­˜é–Ēäŋ‚ãŪ原則:

  • ✅ äļŠä―BoxãŊäļ‹ä―BoxãŦäūå­˜ã§ãã‚‹
  • ❌ äļ‹ä―BoxãŊäļŠä―BoxãŦäūå­˜ã—おいåūŠį’°äūå­˜é˜ēæ­Ē
  • ✅ 同ノベãƒŦBoxãŊį‹ŽįŦ‹ïžˆæ°īåđģäūå­˜ãŠã—

ðŸ’Ą å۟čĢ…ã‚Žã‚Īãƒ‰ïžˆæŽĄãŪã‚ŧッショãƒģį”Ļ

Phase 1 å۟čĢ…æ‰‹é †

Step 1: PhiInputCollectorå۟čĢ…

# 1. ãƒ•ã‚Ąã‚ĪãƒŦä―œæˆ
touch src/mir/phi_core/phi_input_collector.rs

# 2. mod.rsãŦčŋ―加
echo "pub mod phi_input_collector;" >> src/mir/phi_core/mod.rs

# 3. テãƒģãƒ—ãƒŽãƒžãƒˆä―œæˆïžˆäļŠčϘãŪčĻ­čĻˆã‚’ã‚ģピマ
# 4. テã‚đトå۟čĢ…
# 5. loopform_builder.rsでä―ŋį”Ļ
# 6. æ—Ē存ã‚ģマド削é™Ī

Step 2: BodyLocalPhiBuilderå۟čĢ…

# 同様ãŪ手順
touch src/mir/phi_core/body_local_phi_builder.rs

æĪœčĻžãƒã‚§ãƒƒã‚Ŋナã‚đト

Phase 1åŪŒäš†æ™‚ ✅ Phase 26-BåŪŒäš† (2025-11-20)

  • PhiInputCollectorãŪå˜ä―“ãƒ†ã‚đトå…Ļ通過 ✅ (33186e1e)
  • BodyLocalPhiBuilderãŪå˜ä―“ãƒ†ã‚đトå…Ļ通過 ✅ (54f6ce84)
  • skip_whitespaceã‚·ãƒŠãƒŠã‚Šã§å‹•ä―œįĒščŠ ✅ (æ—ĒįŸĨãŪå•éĄŒãŊåˆĨIssue)
  • æ—Ē存ãŪå…Ļã‚đãƒĒマã‚Ŋテã‚đト通過 ✅ (mir_loopform_exit_phi 4/4 PASS)
  • [~] ã‚ģマド削æļ›: į›ŪæĻ™140čĄŒé”æˆ → å۟įļū+1行 (Phase 2-3でåΧåđ…削æļ›äšˆåۚ)
  • ドキãƒĨãƒĄãƒģト: docã‚ģãƒĄãƒģトåŪŒå‚™ ✅

å۟čĢ…æˆæžœ:

  • PhiInputCollector: įĩąäļ€PHIå…Ĩ力収集 (BTreeMapæąšåŪšæ€§įĒšäŋ)
  • BodyLocalPhiBuilder: BodyLocalåĪ‰æ•°PHIį”Ÿæˆå°‚é–€åŒ–
  • įĩąåˆåŪŒäš†: loopform_builder/loop_builder/json_v0_bridgeå…ĻåŊūåŋœ
  • ã‚ģミット: 33186e1e, 54f6ce84, 05953387, 26288b54

Phase 2åŪŒäš†æ™‚

  • LoopSnapshotManagerãŪå˜ä―“ãƒ†ã‚đトå…Ļ通過
  • HeaderPhiBuilderãŪå˜ä―“ãƒ†ã‚đトå…Ļ通過
  • デマã‚ŋ構造ãŪäļ€å…ƒåŒ–įĒščŠ
  • æ—Ē存ãŪå…Ļã‚đãƒĒマã‚Ŋテã‚đト通過
  • ã‚ģマド削æļ›: įīŊčψ380čĄŒé”æˆ
  • äūå­˜é–Ēäŋ‚å›ģãŪæ­ĢįĒšæ€§įĒščŠ

Phase 3åŪŒäš†æ™‚

  • ExitPhiBuilderãŪåŒ…æ‹Žįš„ãƒ†ã‚đトå…Ļ通過
  • Phantom blocké™ĪåĪ–ãŪå‹•ä―œįĒščŠ
  • BodyLocalExit/BodyLocalInternal匚åˆĨįĒščŠ
  • æ—Ē存ãŪå…Ļã‚đãƒĒマã‚Ŋテã‚đト通過
  • ã‚ģマド削æļ›: įīŊčψ600čĄŒé”æˆ
  • č·雑åšĶæļŽåۚ: 最åΧé–Ē数50行äŧĨäļ‹įĒščŠ

🎓 įŪąį†čŦ–ãĻãŪæ•ī合性įĒščŠ

įŪąį†čŦ–4原則

1. 分é›Ē (Separation)

  • ✅ PhiInputCollector: PHIå…Ĩ力収集専門
  • ✅ BodyLocalPhiBuilder: BodyLocalåˆĪåŪšå°‚é–€
  • ✅ HeaderPhiBuilder: Header PHI専門
  • ✅ ExitPhiBuilder: Exit PHI専門
  • ✅ 各BoxãŊ単äļ€čēŽäŧŧãŪãŋ

2. åĒƒį•Œ (Boundary)

  • ✅ 明įĒšãŠtraitåۚįūĐPhiMergeOps, LoopFormOps
  • ✅ pub/privateãŪéĐ切おä―ŋい分け
  • ✅ äūå­˜é–Ēäŋ‚ãŪä–đ向性įĒšäŋ
  • ✅ æĻŠæ–đ向ãŪäūå­˜ãŠã—æ°īåđģ分é›Ē

3. åŊ逆性 (Reversibility)

  • ✅ 各PhaseãŊį‹ŽįŦ‹ïžˆPhase 1åĪąæ•—ã§ã‚‚Phase 2åŊčƒ―ïž‰
  • ✅ Feature flagでæŪĩéšŽįš„æœ‰åŠđ化åŊčƒ―
  • ✅ æ—Ē存å۟čĢ…ãĻãŪäļĶ行運į”ĻåŊčƒ―ïžˆį§ŧčĄŒæœŸé–“ïž‰
  • ✅ ロマãƒŦバッã‚ŊåŪđæ˜“ïžˆGitベマã‚đ

4. テã‚đトåŪđæ˜“æ€§ (Testability)

  • ✅ 各BoxãŪå˜ä―“ãƒ†ã‚đトåŊčƒ―
  • ✅ Mockable traitčĻ­čψ
  • ✅ テã‚đトã‚Ŧバノッã‚ļ>90%į›ŪæĻ™
  • ✅ įĩąåˆãƒ†ã‚đãƒˆã‚‚į‹ŽįŦ‹åŪŸčĄŒåŊčƒ―

📝 ナã‚đã‚Ŋ分析ãĻčŧ―æļ›į­–

ナã‚đã‚Ŋäļ€čͧ

ナã‚đã‚Ŋ å―ąéŸŋåšĶ į™šį”ŸįĒšįŽ‡ čŧ―æļ›į­–
Phase 3åĪąæ•— éŦ˜ äļ­ Phase 1-2で埚į›ĪįĒšįŦ‹ã€æŪĩéšŽįš„į§ŧ行
パフã‚Đママãƒģã‚đåŠĢ化 äļ­ ä―Ž ベãƒģチママã‚ŊæļŽåŪšã€æœ€éĐ化
æ—Ē存バグãŪ顕åœĻ化 äļ­ äļ­ åŒ…æ‹Žįš„ãƒ†ã‚đト、æŪĩéšŽįš„ãƒŠãƒŠãƒžã‚đ
å۟čĢ…æ™‚é–“čķ…過 ä―Ž äļ­ PhaseæŊŽãŦã‚ŋã‚Īムボッã‚Ŋã‚đčĻ­åۚ

Phase 3į‰đ有ãŪナã‚đã‚Ŋ

å•éĄŒ: ExitPhiBuilderが最もčĪ‡é›‘ïžˆ173行ãŪロã‚ļッã‚Ŋį§ŧčĄŒïž‰

čŧ―æļ›į­–:

  1. æŪĩéšŽįš„å۟čĢ…

    • Step 1: Phantom blocké™ĪåĪ–ãŪãŋå۟čĢ…
    • Step 2: Body-localå‡Ķᐆčŋ―加
    • Step 3: åیå…Ļį§ŧ行
  2. äļĶ行運į”Ļ

    • į’°åǃåĪ‰æ•°ã§æ–°æ—§åˆ‡ã‚Šæ›ŋえåŊčƒ―ãŦ
    • NYASH_USE_EXIT_PHI_BUILDER=1で新å۟čĢ…æœ‰åŠđ化
    • デフã‚ĐãƒŦトãŊ旧å۟čĢ…ïžˆåŪ‰å…Ļ性儊先
  3. åŒ…æ‹Žįš„ãƒ†ã‚đト

    • skip_whitespaceシナナりåŋ…é ˆ
    • Phantom blockシナナりåŋ…é ˆ
    • 3+ exit predsシナナりåŋ…é ˆ

🚀 ãūãĻめ

ææĄˆå†…åŪđ

6ãĪãŪBoxãŦよるPHIį”Ÿæˆã‚ģマドãŪåیå…Ļ分é›Ēã‚’ææĄˆã—ãūす

  1. PhiInputCollector - PHIå…Ĩ力収集įĩąäļ€
  2. BodyLocalPhiBuilder - BodyLocalåĪ‰æ•°å‡Ķᐆ
  3. LoopSnapshotManager - Snapshotäļ€å…ƒįŪĄį†
  4. HeaderPhiBuilder - Header PHI専門化
  5. ExitPhiBuilder - Exit PHI専門化最重čĶïž‰
  6. ValueIdAllocator - ValueIdįŪĄį†ïžˆã‚Šãƒ—ã‚·ãƒ§ãƒŠãƒŦ

期åū…åŠđ果

  • ðŸŽŊ äŋåŪˆæ€§: čēŽäŧŧ明įĒšåŒ–ã€æœ€åΧé–Ē数173行→50行äŧĨäļ‹
  • ⚡ テã‚đトåŪđæ˜“æ€§: į‹ŽįŦ‹ãƒ†ã‚đトåŊčƒ―ã€ã‚Ŧバノッã‚ļ60%→90%
  • 📚 åŊčŠ­æ€§: 各BoxãŪå―đå‰ēäļ€į›Ūįž­į„ķ
  • 🔄 再åˆĐį”Ļ性: äŧ–ãŪPHIæ–‡č„ˆã§ã‚‚ä―ŋį”ĻåŊčƒ―

å۟čĢ…å„Šå…ˆé †ä―

  1. Phase 1: PhiInputCollector + BodyLocalPhiBuilderåģåŠđ性
  2. Phase 2: LoopSnapshotManager + HeaderPhiBuilder構造æ”đ善
  3. Phase 3: ExitPhiBuilder最é›Ģé–Ēãƒŧ最åΧåŠđ果
  4. Phase 4: ValueIdAllocator + ドキãƒĨãƒĄãƒģトäŧ•äļŠã’

æŽĄãŪã‚đテップ

  • 朎čψį”ŧãŪノビãƒĨマãƒĶマã‚ķマįĒščŠïž‰
  • Phase 1į€æ‰‹åˆĪ断
  • Phase 1å۟čĢ…ïžˆ1週間äŧĨ内
  • Phase 2å۟čĢ…ïžˆ2週間äŧĨ内
  • Phase 3å۟čĢ…ïžˆ3週間äŧĨ内

įŪąį†čŦ–原則ãŦ埚ãĨくæŪĩéšŽįš„ãƒŠãƒ•ã‚Ąã‚Ŋã‚ŋナãƒģグで、įĒšå۟ãŦäŋåŪˆæ€§ã‚’å‘äļŠã•せãūす 🎉