## Phase 20.12 — Performance Optimization (AOT & VM) + PHI Localization 目的 - AOT(EXE)と VM の実行性能を、構造を崩さずに最適化する。 - 入口は AotBox(プラグイン優先)を維持し、最適化は箱の内側 or 上位スクリプト層で行う(Box‑First)。 性能目標(現実的レンジ) - EXE(AOT): C言語の 60〜80%(単純ループは過去計測で ≥60% を確認済み) - VM: Python(CPython)と同程度(±20%)を目指す - 備考: 箱(Box)生成コストがボトルネックのため、割付パターン/再利用の改善で達成を狙う 範囲 - AOT前処理(Hakoruneスクリプト層):AotPrepBox(JSON正規化/定数畳み込み/リンクフラグ生成) - VMホットパス(Hakoruneスクリプト層):VMHotPathBox(軽量ディスパッチ/メソッドマップ事前構築) - 既存C‑ABI/FFIの Fail‑Fast/短文診断方針は不変 ゲート(既定) - AOT 前処理: 20.12 では dev/quick プロファイルで既定 ON(`HAKO_AOT_PREP=1`, `HAKO_AOT_PREP_LANG=1`)。 - 失敗時は Rust 前処理へフォールバックし Fail‑Fast を維持。 - CI/integration プロファイルは段階移行中は既定 OFF を維持(安定後に昇格)。 - VM ホットパス: `HAKO_VM_FAST_PATH=1`(既定OFF、段階導入) 受け入れ基準(抜粋) - 代表マイクロベンチで EXE が C の 0.6× 以上、VM が Python 比 ±20% 以内 - 既存スモークは緑(Fail‑Fast/短文維持、SKIP方針は不変) - dist 形状での FFI 既定探索は docs の手順で再現可能 ベンチ指針(起動コスト対策) - subtract ベースライン(ret0 EXE)+固定N の net 時間で it/s を推定(`HAKO_BENCH_SUBTRACT_STARTUP=1`)。 - N 自動プローブ(`HAKO_BENCH_AUTOPROBE=1`, `HAKO_BENCH_MIN_DT=…`)で起動コスト影響を最小化。 - in‑process ベンチ(warm‑up → 計測のみ)を代表(sum/mul)として併用し、EXE の実力を定点観測。 デフォルト化の方針(AOT 前処理) - フェーズ 1(本フェーズ内): dev/quick で既定 ON。負例スモークと sidecar MIR 観測で回帰監視。 - フェーズ 2(次フェーズ) : integration-core で既定 ON に昇格。全ベンチ中央値が基準を満たすこと。 - ロールバック容易性 : いずれも `HAKO_AOT_PREP=0` または `HAKO_AOT_PREP_LANG=0` で即座に OFF。 リスクと対策 - 最適化で意味論が動くリスク → すべてゲート化+スモークでパリティ観測 - リンク環境差(Linuxのリンカ差)→ 既存回避策(-no-pie / lld 推奨)を引き続き提示 実装メモ(このパスで詰め済み) - AotPrep in‑place の対象関数選定を拡張:`main` 優先→存在しない場合は `functions[]` を順次走査し、最初に安全パターンが見つかった関数で in‑place 置換(const→ret)。 - CFG 正規化(最小):first block の instructions 配列に限定し、二重の const + binop(+/−/*) + ret の連鎖のみを畳み込み。その他のCFG/複数ブロックは恒等(Fail‑Fastなし)。 - VM HotPath v0.1:整数 Add/Mul/Sub の superinstruction を `HAKO_VM_FAST_PATH=1` 時にのみ有効化。quick プロファイルで既定 ON。 ### PHI Localization(LocalizationPhiBox) - 新規箱 `lowering/localize_phi.py` を導入。pred==1 の場合に限り、局所PHIを作らず pred 終端のSSAを i64 正規化して“そのまま”使う。 - `mir_call.py` の console 降ろしでは、`PhiDispatchPoint` が 0 を返した場合に LocalizationPhiBox を試行。multi‑pred の場合は pred スナップショットの最初の値を安全に採用(i64 正規化)し、最終的な意味論は predeclare→finalize の正道に委譲。 - predeclare は multi‑pred のみに限定(empty PHI を避ける)。PHI は常にブロック先頭で生成され、グルーピング/支配関係の LLVM 規約を維持。 - スモーク追加:`strict_print_loop_exe.sh`(ループ最終値の print が 1000)、`strict_print_if_merge_exe.sh`(if-merge の print が 1000)。