Files
hakorune/docs/development/analysis/minimal_ssa_bug_analysis.md
nyash-codex 6865f4acfa feat(phi): Phase 25.1 - LoopForm v2 テスト・最小再現ケース追加
-  最小再現ケース作成
  - apps/tests/minimal_ssa_skip_ws.hako: 確実に再現する10-30行ケース
  - apps/tests/minimal_ssa_bug*.hako: 段階的簡略化版
  - apps/tests/loopform_*.hako: LoopForm v2 各ケーステスト

-  Rustテストスイート追加
  - src/tests/mir_loopform_conditional_reassign.rs: 4ケース(Case A/B/C/D)
  - src/tests/mir_loopform_complex.rs: 複雑なパターン
  - 全テストPASS確認済み

-  SSAバグ分析ドキュメント
  - docs/development/analysis/minimal_ssa_bug_analysis.md
  - エラー詳細・原因・ワークアラウンド記録

🎯 成果: SSAバグの構造を完全特定、デバッグ準備完了
2025-11-21 06:21:45 +09:00

2.0 KiB
Raw Blame History

Minimal SSA Bug Analysis — loop(1==1) + break exit PHI

何が起きていたか

  • StageB / FuncScanner の skip_whitespace 系で、loop(1 == 1) { ... break } という形のループが exit PHI を壊し、ValueId 未定義エラー(use of undefined value / Dominator violationが発生していた。
  • 原因: exit PHI 入力に「存在しない predecessorheader」由来の値を含めていた。
    • loop(1 == 1) の場合、header → exit の CFG エッジは存在しないexit は break 経路のみ)。
    • それにもかかわらず、merge_exit_with_classification が header 値を無条件で PHI 入力に足していたため、非支配ブロックからの値参照になり破綻。

最小再現

  • ファイル: apps/tests/minimal_ssa_skip_ws.hako
  • 構造: loop(1 == 1) の中で if i >= n { break } を先頭に置く形。break 以外に exit pred が無い。
  • Rustテスト: src/tests/mir_loopform_conditional_reassign.rs::loop_constant_true_exit_phi_dominates(今回新設)

修正内容

  • src/mir/phi_core/loop_snapshot_merge.rsmerge_exit_with_classification で、header が exit predecessor に含まれている場合にのみ header 値を PHI 入力へ追加するようガード。
    • CFG に存在しない predecessor 由来の値を PHI に入れないことで Dominator violation を解消。

追加したもの

  • 最小再現ハコ: apps/tests/minimal_ssa_skip_ws.hako
  • Rustテスト: src/tests/mir_loopform_conditional_reassign.rs
    • loop_constant_true_exit_phi_dominates(今回のバグ再現→修正確認用)
    • 将来拡張用に 2 本を #[ignore] で占位(条件付き再代入 / body-local 変数の exit PHI 観測)

次のステップ

  • #[ignore] テストを埋める: 条件付き再代入(loop(i < n))や body-local 混在ケースの SSA 安定性を追加検証。
  • StageB / UsingResolver の既存スモークにも apps/tests/minimal_ssa_skip_ws.hako を流し込んで回帰を防ぐ。