# Phase 41 — asm-first gate audit(FAST build で “呼ばれてる gate” だけ削る) Phase 40 の教訓: - “gate を定数化すれば速い” は常に真ではない(layout tax で符号反転する)。 - perf self% だけで gate 税を推定しない(header work 等の実体が混ざる)。 よって Phase 41 は **asm-first**(実際に branch/call が残っているものだけ)で進める。 --- ## ゴール FAST build(`make perf_fast`)で、hot path に残る “純粋な gate” を減らして **+0.5% 以上**を狙う。 判定(build-level): - GO: +0.5% 以上(Mixed 10-run mean) - NEUTRAL: ±0.5% - NO-GO: -0.5% 以下(revert) --- ## Step 0: ベースライン固定 1) `make perf_fast` を回して baseline(FAST v3)の mean/median を記録。 2) そのログを `docs/analysis/PHASE41_ASM_FIRST_GATE_AUDIT_RESULTS.md` に貼る(まずは baseline だけ)。 --- ## Step 1: asm inspection(必須) 目的: “gate を消したつもりが既に最適化されていた/逆に layout を壊した” を避ける。 ### 1-A) 対象 gate の存在確認(例) 対象候補(Phase 40 準備の優先順から): - `mid_v3_enabled()`(`core/box/mid_hotbox_v3_env_box.h`) - `mid_v3_debug_enabled()`(同上) 確認コマンド例(最小): ```sh objdump -d ./bench_random_mixed_hakmem_minimal | rg -n "mid_v3_enabled|mid_v3_debug_enabled" -n ``` ### 判定 - **asm に gate が見える**(call/branch が残っている) → Step 2 へ - **asm に出ない**(既に消えている) → その候補は skip --- ## Step 2: 低リスクの “呼ばれないようにする” を先に Phase 40 は「関数自体の定数化」で layout 税を踏んだ。 まずは **呼び出し回数を減らす(条件順序の見直し)**を優先する。 ### 2-A) alloc 側: size range を先に見る 例(パターン): - 悪い: `if (mid_v3_enabled() && size_in_range) ...`(常に gate が呼ばれる) - 良い: `if (size_in_range && mid_v3_enabled()) ...`(範囲外なら gate を呼ばない) 候補箇所: - `core/box/hak_alloc_api.inc.h` の MID v3 分岐(`mid_v3_enabled()` を含む if) 期待: +0.2〜0.5% --- ## Step 3: BENCH_MINIMAL 定数化(最後の手段) Step 2 で不足する場合のみ、FAST build 限定で gate を定数化する。 ### 3-A) mid_v3_enabled/debug を FAST で固定 OFF 条件: - Mixed/FAST のプリセットで MID v3 がデフォルト OFF(研究箱)であることが Step 0 で確認できている。 実装: - `core/box/mid_hotbox_v3_env_box.h` に `#include "../hakmem_build_flags.h"` を追加 - `#if HAKMEM_BENCH_MINIMAL` のとき `mid_v3_enabled()` / `mid_v3_debug_enabled()` は `return 0;` - Standard/OBSERVE は現状維持 注意: - layout 税が出る可能性があるので、**必ず 10-run** で判定する。 --- ## Step 4: A/B(FAST 10-run) 毎回これを正とする: - `make perf_fast`(FAST binary を `BENCH_BIN` で指定して 10-run) 結果を `docs/analysis/PHASE41_ASM_FIRST_GATE_AUDIT_RESULTS.md` に追記して確定判定する。