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)。