Files
hakorune/docs/development/current/main/phases/phase-260/README.md

5.3 KiB
Raw Blame History

Phase 260: Block-Parameterized CFGedge-args段階導入

Status: In progress
Last updated: 2025-12-20

進捗(セーブポイント)

  • P0併存導入の芯: 完了(読む側 SSOT を out_edges()/edge_args_to() に寄せた)
    • Commit: 4dfe3349b
  • P0.1hardening: 完了legacy layout 無し禁止 + DCE/verify の参照点整理)
    • Commit: 1fe5be347

目的P0

JoinIR→MIR の暗黙 ABIjump_args / carriers / expr_result slot / successorsを減らし、将来的な block-parameterized CFGedge-args を第一級に持つCFGへ収束するための「大工事パート」を開始する。

このフェーズは “一括置換” ではなく、**併存導入Strangler**で可逆に進める。

背景Phase 256-259 で露出した型)

  • jump_args が IR 外メタとして存在すると、DCE/verify/CFG 更新が「忘れると壊れる」になる
  • spans が並行 Vec だと、最適化や変換で同期漏れが起きやすい
  • continuation / entry / exit の識別と args 順序が散在すると、推測・補正が増殖する

North Star: docs/development/current/main/design/join-explicit-cfg-construction.md

方針2段正規化

  • Semantic Normalization意味SSOT: terminator 語彙の固定(例: cond付きJumpを正規形から禁止しBranchへ
  • Plumbing Normalization配線SSOT: edge-args / CFG successor / spans を IR 構造に閉じ込め、写像に縮退

スコープPhase 260

In scope

  • MIR に「edge-args を持つ terminator 表現」を 併存導入する(旧 BasicBlock.jump_args は残す)
  • “読む側” を単一APIに寄せるBranch を含むので “複数 edge” 前提で一本化する)
    • 例: block.out_edges() / block.edge_args_to(target)
  • 互換期間は 一致検証を Fail-Fast(両方ある場合は矛盾で即死)

Out of scopeP0ではやらない

  • BasicBlock.jump_args の削除(削除は Phase 261+
  • spans の内部表現を Vec<Spanned<_>> に一気に切替Phase 261+ で段階導入)
  • JoinIR を削除するbuilder DSL 降格は長期)

実装タスクP0

  1. MirTerminator(または既存 terminator に edge-args を持てる variantを追加併存導入
    • Jump だけでなく Branch を含むため、API は “複数 edge” を前提にする
  2. bridge が Jump/Branch の edge-args を terminator operand としてもセット旧jump_argsも併記してよい
  3. merge/ExitLine/DCE/verify/printer が参照する入口を一本化(読む側の Strangler
    • 推奨: block.out_edges() / block.edge_args_to(target) のような APIedge_args() 単発は Branch で曖昧)
  4. Fail-Fast 契約チェック(--verify 時に必須)
    • “両方ある場合は一致” を verify で保証
    • 追加: “terminator から計算した successors” と “block.successors キャッシュ” の一致も verify で保証(同期漏れを即死)

受け入れ基準P0

  • cargo build --release が通る
  • ./tools/smokes/v2/run.sh --profile quick が少なくとも悪化しないsame first FAIL 以上)
  • --verify の既存テストが壊れないPHI/CFG検証が健全
  • legacy 依存の “推測” が増えていない(新規の env var 追加なし)
  • rg "jump_args" を走らせて、移行コードと API 以外に参照が増えていない(読む側の寄せ漏れを検出)
  • DCE 回帰が 1 本以上あり、「edge-args だけで使われる値」が消されないことを固定できている

ロードマップP0→P3

P0併存導入の芯

  • 単一参照APIを作るBranch を含むので “複数 edge” 前提)
    • 例: BasicBlock::out_edges() / BasicBlock::edge_args_to(target)
  • MIR terminator に edge-args を持てる表現を追加(旧 jump_args併存
    • 推奨: EdgeArgs { layout: JumpArgsLayout, values: Vec<ValueId> } のように “意味layout” も同梱する
  • bridge が edge-args を terminator operand に必ず埋める旧jump_argsも同内容でセットしてよい
  • merge/ExitLine/DCE/verify/printer は参照点を out_edges()/edge_args_to(...) に寄せる
  • 両方ある場合の 一致検証を Fail-Fast--verify で必須)

P1切替

  • jump_args を読む経路を段階的に減らす(参照点は out_edges()/edge_args_to(...) のみ)
  • terminator 更新の API一本化successors/preds の同期漏れを構造で潰す)
    • 読む側だけでなく、書く側terminator 設定/edge-args 設定)も API 経由に寄せる
  • DCE/verify が terminator operand から自然に use/pred を追えることを固定する

P2削除

  • BasicBlock.jump_args を削除(併存チェックも撤去)
  • jump_args 特例の DCE/verify コードを削除terminator operand が SSOT

P3spans 収束)

  • instructions + instruction_spans の並行 Vec を段階導入で廃止
    • 先に編集APIを一本化 → 最終的に Vec<Spanned<MirInstruction>>

メモ設計SSOT

  • 相談パケット: docs/development/current/main/investigations/phase-259-block-parameterized-cfg-consult.md
  • decisions: docs/development/current/main/20-Decisions.md