216 lines
6.3 KiB
Markdown
216 lines
6.3 KiB
Markdown
|
|
# Exit PHI Design - Phase 132 Architecture
|
|||
|
|
|
|||
|
|
## Overview
|
|||
|
|
|
|||
|
|
Phase 132 で完成した Exit PHI アーキテクチャの責務分離設計。
|
|||
|
|
|
|||
|
|
## Three-Layer Responsibility Model
|
|||
|
|
|
|||
|
|
### Layer 1: JoinIR (Frontend - データ生成層)
|
|||
|
|
|
|||
|
|
**責務**: ループ脱出時の変数バインディング情報を生成
|
|||
|
|
|
|||
|
|
**実装箇所**: `src/mir/join_ir/lowering/inline_boundary/`
|
|||
|
|
|
|||
|
|
**主要コンポーネント**:
|
|||
|
|
- `LoopExitBinding`: ループ脱出時の変数バインディング構造
|
|||
|
|
```rust
|
|||
|
|
pub struct LoopExitBinding {
|
|||
|
|
pub carrier_name: String, // 変数名 (e.g., "i")
|
|||
|
|
pub join_exit_value: ValueId, // JoinIR k_exit 関数の引数
|
|||
|
|
pub host_slot: ValueId, // Host MIR の PHI dst
|
|||
|
|
}
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
**データフロー**:
|
|||
|
|
```
|
|||
|
|
Pattern 1 Minimal:
|
|||
|
|
loop_step → Jump(k_exit, [i_param]) → exit_bindings = [LoopExitBinding { "i", i_param, host_slot }]
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
**Phase 132 貢献**:
|
|||
|
|
- `exit_bindings` フィールド追加(`JoinInlineBoundary` 構造体)
|
|||
|
|
- Pattern 1-5 各パターンで exit binding 生成ロジック実装
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
### Layer 2: Boundary (Middleware - 接続実行層)
|
|||
|
|
|
|||
|
|
**責務**: JoinIR の exit_bindings を使って Host MIR に Exit PHI を接続
|
|||
|
|
|
|||
|
|
**実装箇所**: `src/mir/builder/control_flow/joinir/merge/`
|
|||
|
|
|
|||
|
|
**主要コンポーネント**:
|
|||
|
|
- `ExitLineReconnector`: Exit PHI 接続 Box (Phase 33-10 で箱化)
|
|||
|
|
```rust
|
|||
|
|
impl ExitLineReconnector {
|
|||
|
|
fn connect_exit_line(
|
|||
|
|
&self,
|
|||
|
|
boundary: &JoinInlineBoundary,
|
|||
|
|
exit_block_id: BasicBlockId,
|
|||
|
|
exit_predecessor: BasicBlockId,
|
|||
|
|
builder: &mut Builder,
|
|||
|
|
) -> Result<(), String>
|
|||
|
|
}
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
**処理フロー**:
|
|||
|
|
1. `exit_bindings` をイテレート
|
|||
|
|
2. 各 binding について:
|
|||
|
|
- `host_slot` (PHI dst) に対して
|
|||
|
|
- `(exit_predecessor, join_exit_value)` を incoming として追加
|
|||
|
|
|
|||
|
|
**Phase 132 貢献**:
|
|||
|
|
- `exit_bindings` を読み取る発火ロジック実装
|
|||
|
|
- Phase 131 の metadata 参照ロジックを完全削除(SSOT化)
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
### Layer 3: LLVM Backend (Execution - PHI保護層)
|
|||
|
|
|
|||
|
|
**責務**: builder.vmap 内の PHI を SSOT として保護・管理
|
|||
|
|
|
|||
|
|
**実装箇所**: `src/llvm_py/`
|
|||
|
|
|
|||
|
|
**主要コンポーネント** (Phase 132-Post):
|
|||
|
|
- `PhiManager` Box: PHI ライフサイクル管理
|
|||
|
|
```python
|
|||
|
|
class PhiManager:
|
|||
|
|
def register_phi(bid: int, vid: int, phi_value)
|
|||
|
|
def is_phi_owned(bid: int, vid: int) -> bool
|
|||
|
|
def filter_vmap_preserve_phis(vmap: dict, target_bid: int) -> dict
|
|||
|
|
def sync_protect_phis(target_vmap: dict, source_vmap: dict)
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
**SSOT Principle**:
|
|||
|
|
- `builder.vmap` の PHI は **Single Source of Truth**
|
|||
|
|
- PHI は絶対に上書きしない
|
|||
|
|
- ブロック間で PHI 所有権を明確に管理
|
|||
|
|
|
|||
|
|
**Phase 132 貢献**:
|
|||
|
|
- `predeclared_ret_phis` dict による PHI ownership tracking
|
|||
|
|
- vmap filtering: ブロック外の PHI を除外
|
|||
|
|
- sync protection: 既存 PHI を上書きしない
|
|||
|
|
|
|||
|
|
**Phase 132-Post 貢献** (Box-First Refactoring):
|
|||
|
|
- `PhiManager` Box 化で PHI 管理ロジック集約
|
|||
|
|
- `filter_vmap_preserve_phis()`: PHI フィルタリングをカプセル化
|
|||
|
|
- `sync_protect_phis()`: PHI 保護ロジックをカプセル化
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## Data Flow Example (Pattern 1 Minimal)
|
|||
|
|
|
|||
|
|
```
|
|||
|
|
【JoinIR Layer】
|
|||
|
|
loop_step 関数:
|
|||
|
|
Jump(k_exit, [i_param], cond=exit_cond)
|
|||
|
|
↓
|
|||
|
|
Pattern 1 lowering:
|
|||
|
|
exit_bindings = [
|
|||
|
|
LoopExitBinding {
|
|||
|
|
carrier_name: "i",
|
|||
|
|
join_exit_value: ValueId(1003), // JoinIR i_param
|
|||
|
|
host_slot: ValueId(3), // Host MIR PHI dst
|
|||
|
|
}
|
|||
|
|
]
|
|||
|
|
|
|||
|
|
【Boundary Layer】
|
|||
|
|
ExitLineReconnector::connect_exit_line():
|
|||
|
|
for binding in exit_bindings:
|
|||
|
|
builder.add_phi_incoming(
|
|||
|
|
block: exit_block_id,
|
|||
|
|
dst: ValueId(3), // host_slot
|
|||
|
|
incoming: (bb6, ValueId(3)) // (exit_pred, remapped join_exit_value)
|
|||
|
|
)
|
|||
|
|
↓
|
|||
|
|
Host MIR:
|
|||
|
|
bb3: ValueId(3) = phi [(bb6, ValueId(3))]
|
|||
|
|
|
|||
|
|
【LLVM Layer】
|
|||
|
|
PhiManager::register_phi(3, 3, phi_value) // PHI を登録
|
|||
|
|
↓
|
|||
|
|
block_lower.py Pass A (非終端命令処理):
|
|||
|
|
vmap_cur = PhiManager.filter_vmap_preserve_phis(builder.vmap, 3)
|
|||
|
|
# → bb3 所有の PHI(3) のみ保持、他ブロックの PHI は除外
|
|||
|
|
↓
|
|||
|
|
Pass A sync:
|
|||
|
|
PhiManager.sync_protect_phis(builder.vmap, vmap_cur)
|
|||
|
|
# → builder.vmap の PHI を上書きしない
|
|||
|
|
↓
|
|||
|
|
Pass B (PHI finalization):
|
|||
|
|
phi_3.add_incoming(val_3, bb6)
|
|||
|
|
↓
|
|||
|
|
Pass C (終端命令処理):
|
|||
|
|
ret phi_3
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## Design Principles
|
|||
|
|
|
|||
|
|
### 1. **Separation of Concerns**
|
|||
|
|
- **JoinIR**: データ生成のみ(実行なし)
|
|||
|
|
- **Boundary**: 接続実行のみ(データ保護なし)
|
|||
|
|
- **LLVM**: PHI保護・管理のみ(生成なし)
|
|||
|
|
|
|||
|
|
### 2. **Box-First Architecture** (Phase 132-Post)
|
|||
|
|
- ロジックを Box (クラス/メソッド) にカプセル化
|
|||
|
|
- `ExitLineReconnector` Box (Boundary)
|
|||
|
|
- `PhiManager` Box (LLVM)
|
|||
|
|
|
|||
|
|
### 3. **SSOT (Single Source of Truth)**
|
|||
|
|
- `exit_bindings` が変数バインディングの唯一の真実
|
|||
|
|
- `builder.vmap` の PHI が SSA 値の唯一の真実
|
|||
|
|
- metadata 参照の完全排除
|
|||
|
|
|
|||
|
|
### 4. **Fail-Fast**
|
|||
|
|
- エラーは早期に明示的に失敗
|
|||
|
|
- フォールバック処理は禁止
|
|||
|
|
- PHI 上書きは panic
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## Migration from Phase 131
|
|||
|
|
|
|||
|
|
### Phase 131 (Before)
|
|||
|
|
- ❌ Jump metadata (`jump_args`) から exit PHI を復元
|
|||
|
|
- ❌ Block.metadata 参照の散在
|
|||
|
|
- ❌ PHI 管理ロジックの分散
|
|||
|
|
|
|||
|
|
### Phase 132 (After)
|
|||
|
|
- ✅ `exit_bindings` で明示的データフロー
|
|||
|
|
- ✅ Boundary 層での一元的 PHI 接続
|
|||
|
|
- ✅ metadata 完全削除(Block からも削除)
|
|||
|
|
|
|||
|
|
### Phase 132-Post (Box-First Refactoring)
|
|||
|
|
- ✅ `PhiManager` Box による PHI 管理ロジック集約
|
|||
|
|
- ✅ `filter_vmap_preserve_phis()` でフィルタリング簡潔化
|
|||
|
|
- ✅ `sync_protect_phis()` で保護ロジック再利用可能
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## Future Work
|
|||
|
|
|
|||
|
|
### Pattern 2-5 への拡張
|
|||
|
|
- Pattern 2 (If-in-Loop): 複数変数 exit bindings
|
|||
|
|
- Pattern 3 (Loop-with-If): exit line 分岐処理
|
|||
|
|
- Pattern 4-5: 複雑な exit 条件
|
|||
|
|
|
|||
|
|
### PhiManager 拡張候補
|
|||
|
|
- PHI タイプヒント管理
|
|||
|
|
- PHI incoming 検証
|
|||
|
|
- PHI 最適化ヒント
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## References
|
|||
|
|
|
|||
|
|
- Phase 132 実装ログ: `docs/development/current/main/phases/phase-132/`
|
|||
|
|
- Boundary アーキテクチャ: `docs/development/architecture/phase-33-modularization.md`
|
|||
|
|
- JoinIR 全体設計: `docs/development/current/main/joinir-architecture-overview.md`
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
Last Updated: 2025-12-15 (Phase 132-Post Box-First Refactoring)
|