feat(joinir): Phase 257 P1.1/P1.2/P1.3 - Pattern6 SSOT + LoopHeaderPhi CFG fix
P1.1: Pattern6 false positive fix (SSOT approach) - can_lower() now calls extract_scan_with_init_parts() for SSOT - index_of_string/2 no longer triggers false positive - Graceful fall-through with Ok(None) P1.2: LoopHeaderPhi CFG-based correction - Step 0: Manual successor update from terminators - CFG-based entry predecessor computation (header_preds - latch) - Multi-entry-pred support (bb0 host + bb10 JoinIR main) - Explicit host_entry_block addition (emit_jump runs after finalize) P1.3: Smoke script validation - phase254_p0_index_of_vm.sh: --verify + VM error detection - phase257 smokes updated Acceptance criteria (all PASS): ✅ phase254_p0_index_of_min.hako verify ✅ phase257_p0_last_index_of_min.hako verify ✅ ./tools/smokes/v2/run.sh --profile quick (no Pattern6 false positive) Technical discovery: - Host entry block (bb0) Jump set in Phase 6 (after finalize) - instruction_rewriter bypasses set_terminator(), skips successor update 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
This commit is contained in:
@ -6,6 +6,28 @@
|
||||
- Phase 143-loopvocab P3+: 条件スコープ拡張(impure conditions 対応)
|
||||
- 詳細: `docs/development/current/main/30-Backlog.md`
|
||||
|
||||
## 2025-12-20:Phase 257 P1.1/P1.2/P1.3 完了 ✅
|
||||
|
||||
- **P1.1**: Pattern6 SSOT fix(false positive 根治)
|
||||
- `can_lower()` が `extract_scan_with_init_parts()` を呼び出して SSOT を確立
|
||||
- `index_of_string/2` の誤検出が解消(`Ok(None)` で graceful fall-through)
|
||||
- **P1.2**: LoopHeaderPhi CFG correction(entry predecessor 自動計算)
|
||||
- Step 0: `update_successors_from_terminator()` を手動実行(instruction_rewriter が set_terminator() をバイパスするため)
|
||||
- CFG から entry predecessors を計算(header_preds - latch_block)
|
||||
- 複数 entry preds 対応(bb0 host + bb10 JoinIR main)
|
||||
- host_entry_block を明示的に追加(emit_jump が finalize() 後に実行されるため)
|
||||
- **P1.3**: Smoke script validation(既存実装確認)
|
||||
- `phase254_p0_index_of_vm.sh`:`--verify` + VM error detection で false positive 回避
|
||||
|
||||
**検証結果**:
|
||||
- ✅ `phase254_p0_index_of_min.hako` verify → PASS
|
||||
- ✅ `phase257_p0_last_index_of_min.hako` verify → PASS
|
||||
- ✅ `./tools/smokes/v2/run.sh --profile quick` → Pattern6 false positive なし(別の未サポートパターンで止まる)
|
||||
|
||||
**技術的発見**:
|
||||
- JoinIR merge では host entry block (bb0) の Jump が Phase 6 で設定されるため、Phase 4.5 の finalize() 時点で CFG に現れない
|
||||
- 解決策:`builder.current_block` を捕捉し、CFG 計算後に明示的に entry_preds へ追加
|
||||
|
||||
## 2025-12-19:Phase 146/147 完了 ✅
|
||||
|
||||
- Phase 146 README: `docs/development/current/main/phases/phase-146/README.md`
|
||||
@ -70,6 +92,12 @@
|
||||
- Phase 257 README: `docs/development/current/main/phases/phase-257/README.md`
|
||||
- Goal: `StringUtils.last_index_of/2` を JoinIR で受理し、`--profile quick` を緑に戻す
|
||||
- Investigation(最小再現/論点): `docs/development/current/main/investigations/phase-257-last-index-of-loop-shape.md`
|
||||
- Status: Pattern6 reverse scan + PHI/CFG 安定化は完了(最初の FAIL は次へ移動)
|
||||
- Current first FAIL: `json_lint_vm / StringUtils.is_integer/1`(nested-if + loop pattern, unsupported)
|
||||
|
||||
## 2025-12-20:Phase 258(is_integer nested-if + loop)🔜
|
||||
|
||||
- Phase 258 README: `docs/development/current/main/phases/phase-258/README.md`
|
||||
|
||||
## 2025-12-19:Phase 254(index_of loop pattern)✅ 完了(Blocked by Phase 255)
|
||||
|
||||
|
||||
@ -13,6 +13,13 @@ Related:
|
||||
- `json_lint_vm` が `StringUtils.last_index_of/2` で停止
|
||||
- エラー: `[joinir/freeze] Loop lowering failed: JoinIR does not support this pattern, and LoopBuilder has been removed.`
|
||||
|
||||
更新(P0/P1後):
|
||||
|
||||
- Pattern6 を reverse scan 対応した後、`phi pred mismatch` が露出したが、P1 で以下により根治した:
|
||||
- MIR verifier で PHI predecessor を fail-fast 検証
|
||||
- loop header PHI の entry edge を CFG から復元(self pred 防止)
|
||||
- smoke の false positive(exit=1衝突)を `--verify` + VM error 検出で抑止
|
||||
|
||||
## Minimal Fixture
|
||||
|
||||
- `apps/tests/phase257_p0_last_index_of_min.hako`
|
||||
@ -47,6 +54,13 @@ JoinIR パターンがこの形を受理できていないのが本体。
|
||||
- Pattern7(SplitScan)は適用対象外。
|
||||
- Pattern3/1 は `return` を含む loop を扱わない(or 目的が違う)。
|
||||
|
||||
更新(P0/P1後):
|
||||
|
||||
- Pattern6 の検出/生成はできているが、merge 側が “CFG(successors/preds)と terminator” の同期を前提にしていた。
|
||||
- joinir merge 中で `terminator` 直書きがあり、`successors` が未同期になることがある(CFG 解析が欠ける)
|
||||
- finalize 時点では host entry jump が未設定なため、header preds だけでは entry pred を復元できない場合がある
|
||||
- これらは P1 で補正済み(fail-fast + 復元ロジック)
|
||||
|
||||
## Decision(Phase 257 の方針)
|
||||
|
||||
Phase 257 では、以下で進める:
|
||||
@ -54,6 +68,11 @@ Phase 257 では、以下で進める:
|
||||
- Pattern6(ScanWithInit)を “scan direction” 付きに一般化し、reverse scan + early return を受理する。
|
||||
- Phase 256 で固めた Contract(`JumpArgsLayout`, pipeline contract checks)に従い、merge 側で推測しない。
|
||||
|
||||
追加(P1):
|
||||
|
||||
- MIR verifier に `InvalidPhi` チェックを追加し、`phi pred mismatch` を `--verify` で fail-fast にする
|
||||
- loop header PHI の entry edge source を正す(必要なら preheader を生成)
|
||||
|
||||
## Questions(将来に残す設計論点)
|
||||
|
||||
1. `LoopPatternKind` に Pattern6/7 を増やすべきか?(router 側での分類SSOTを揃える)
|
||||
|
||||
@ -8,9 +8,9 @@ Related:
|
||||
|
||||
## Current Status (SSOT)
|
||||
|
||||
- Target first FAIL: `json_lint_vm / StringUtils.last_index_of/2`
|
||||
- Pattern: Loop with early return (backward scan)
|
||||
- Approach: Extend Pattern6(ScanWithInit)to support reverse scan + early return
|
||||
- Former first FAIL: `json_lint_vm / StringUtils.last_index_of/2`(P0/P1で解消)
|
||||
- Current first FAIL: `json_lint_vm / StringUtils.is_integer/1`(nested-if + loop, still unsupported)
|
||||
- Approach (done): Pattern6(ScanWithInit)を reverse scan + early return に拡張し、PHI/CFG を fail-fast + 自動補正で安定化
|
||||
|
||||
---
|
||||
|
||||
@ -120,6 +120,60 @@ Pattern6(ScanWithInit)を “scan direction” を持つ形に一般化す
|
||||
- Phase 256 系の契約(`JumpArgsLayout` / contract checks)に従い、推測しない
|
||||
- `expr_result` は `return i` の経路でのみ使用(not-found は `-1`)
|
||||
|
||||
---
|
||||
|
||||
## Progress
|
||||
|
||||
### P0(完了)
|
||||
|
||||
- Pattern6 を双方向 scan に拡張(forward/reverse)
|
||||
- reverse scan 用 lowerer を追加(`scan_with_init_reverse.rs`)
|
||||
- `apps/tests/phase257_p0_last_index_of_min.hako` を追加
|
||||
- ただし現状は「PHI predecessor mismatch」が先に露出しており、P1 でインフラ不変条件を固定する必要がある
|
||||
|
||||
## Phase 257 P1(次の指示書 / SSOT)
|
||||
|
||||
### Goal
|
||||
|
||||
- Pattern6 の実行時 `phi pred mismatch` を根治し、`index_of` / `last_index_of` が VM で正常に走る
|
||||
- `./tools/smokes/v2/run.sh --profile quick` の最初の FAIL を次へ進める
|
||||
|
||||
### Tasks(順序)
|
||||
|
||||
1) MIR verifier を強化して `InvalidPhi` を検出する(fail-fast)
|
||||
- 期待: phi inputs が「ブロックの predecessor 全部」をカバーし、自己ブロック(self)を含まない
|
||||
2) Pattern6 の loop header PHI の entry edge source を正す
|
||||
- `entry_block == header_block` になっているケースを禁止し、必要なら preheader を作る or merge entry を main に寄せる
|
||||
3) smoke の false positive を防ぐ
|
||||
- `phase254_p0_index_of_vm.sh` は `--verify` を併用するか、VM error を検出して FAIL にする
|
||||
|
||||
---
|
||||
|
||||
## Progress
|
||||
|
||||
### P0(完了)
|
||||
|
||||
- Pattern6 を双方向 scan に拡張(forward/reverse)
|
||||
- reverse scan 用 lowerer を追加
|
||||
- fixture: `apps/tests/phase257_p0_last_index_of_min.hako`
|
||||
|
||||
### P1(完了)
|
||||
|
||||
- Pattern6 の誤検出を防止(detect/extract SSOT 化)
|
||||
- `index_of_string/2` など “近いが別形” を `Ok(None)` で fall-through させる
|
||||
- MIR verifier に PHI predecessor 検証を追加(fail-fast)
|
||||
- unreachable pred は除外して現実的に運用
|
||||
- loop header PHI の entry edge を CFG から復元(self pred 根治)
|
||||
- merge 内で `terminator` 直書きにより `successors` が同期されないケースを補正
|
||||
- finalize 時点で host entry jump が未設定なため、host entry predecessor を明示的に補う
|
||||
- smoke の false positive を抑止(`--verify` + VM error 検出)
|
||||
|
||||
## Next (Phase 258 proposal)
|
||||
|
||||
- `StringUtils.is_integer/1` の loop を JoinIR で受理する(caps=If,Loop,NestedIf,Return)
|
||||
- ループ形: `loop(i < s.length()) { if not is_digit(...) return false; i=i+1 } return true`
|
||||
- 前処理に nested-if がある(`start` の決定)
|
||||
|
||||
**Option B: Pattern8_ReverseScanReturn 新設**
|
||||
|
||||
Pattern6 を触らずに、reverse scan 専用パターンとして箱を追加する。
|
||||
|
||||
Reference in New Issue
Block a user