# Phase 131 P1.5: Root Cause Analysis Summary

Status: Analysis Complete
Date: 2025-12-18
Scope: Phase 131 P1.5 variable propagation failure diagnosis

## TL;DR

**Problem**: loop(true) { x=1; break }; return x → returns 0 instead of 1

**Root Cause**: Using PHI-based merge pipeline for Normalized IR's continuation-based control flow

**Solution**: Option B - Direct env→host wiring via ExitReconnectorBox (PHI-free, matches Normalized design)

## Investigation Timeline

### Step 1: Verify ExitMeta Creation ✅

**Location**: `src/mir/control_tree/normalized_shadow/loop_true_break_once.rs:317-327`

**Code**:
```rust
let mut exit_values = Vec::new();
for (i, var_name) in env_layout.writes.iter().enumerate() {
    let k_exit_param_vid = k_exit_func.params[i];
    exit_values.push((var_name.clone(), k_exit_param_vid));
}
let exit_meta = ExitMeta { exit_values };
```

**Trace Evidence**:
```
[trace:exit-line] collector: Collecting 1 exit values
[trace:exit-line] collector: checking carrier 'x' in variable_ctx.variable_map
[trace:exit-line] collector: collected 'x' JoinIR ValueId(6) → HOST ValueId(2), role=LoopState
```

**Conclusion**: ✅ ExitMeta is created correctly. `x` → `ValueId(6)` (k_exit param) is captured.

### Step 2: Verify ExitMetaCollector ✅

**Location**: `src/mir/builder/control_flow/joinir/merge/exit_line/meta_collector.rs:77-261`

**Trace Evidence**:
```
[trace:exit-line] collector: collected 1 bindings: [LoopExitBinding {
  carrier_name: "x",
  join_exit_value: ValueId(6),
  host_slot: ValueId(2),
  role: LoopState
}]
```

**Conclusion**: ✅ ExitMetaCollector works correctly. Boundary is created with proper mapping.

### Step 3: Verify variable_map Update ✅

**Trace Evidence**:
```
[joinir/exit-line] variable_ctx.variable_map['x'] ValueId(2) → ValueId(10)
```

**Conclusion**: ✅ variable_map is updated with exit PHI result.

### Step 4: Identify PHI Mismatch ❌

**Trace Evidence**:
```
[DEBUG-177] Exit block PHI (carrier 'x'):
  ValueId(10) = phi [(BasicBlockId(39), ValueId(4))]

[ERROR] ❌ [rust-vm] VM error: Invalid instruction:
phi pred mismatch at ValueId(10): no input for predecessor BasicBlockId(42)
```

**Conclusion**: ❌ **PHI node has wrong predecessors**
- Has input from: BasicBlockId(39)
- Expected input from: BasicBlockId(42)
- This is a **CFG structure mismatch**

## Root Cause: CFG Structure Incompatibility

### Standard Loop CFG (Pattern 1-4)

```
entry
  ↓
header ←─────┐
  ├─→ body   │
  │    ↓     │
  │  latch ──┘  (loop back edge)
  ↓
exit
  ↓
  PHI = merge(break_edge, fallthrough)
```

**PHI needs inputs from**:
- Break edge from loop body
- Fallthrough from header (condition false)

### Normalized IR CFG (Continuation-based)

```
main(env)
  ↓ TailCall
loop_step(env)
  ├─→ (true) TailCall → loop_body(env)
  │                       ↓ TailCall
  ↓                     k_exit(env) ──→ return env.x
  └─→ (false) TailCall → k_exit(env) ──→ return env.x
```

**No loop back edge!** All connections are tail-calls.

**k_exit receives env as parameter** - this IS the final value (SSOT), no merging needed!

## Why PHI Generation Fails

The merge pipeline (`JoinIRConversionPipeline`) assumes:
1. Loop has a header with PHI nodes (for loop variables)
2. Exit block needs PHI to merge values from multiple loop exits
3. CFG has loop back edges and break edges

**But Normalized IR**:
1. No header PHI (env parameters are passed via tail-calls)
2. k_exit env parameter IS the final value (no merge needed)
3. No loop back edges (only forward tail-calls)

**The PHI generation logic doesn't match Normalized's control flow structure.**

## Why Option B is Correct

### Option B: Direct env→host Wiring (PHI-free)

**Principle**: k_exit env parameters are SSOT for final values

**Implementation**:
```rust
// For Normalized IR only
for (var_name, k_exit_param_vid) in exit_meta.exit_values {
    // k_exit_param_vid is already the final value!
    variable_map.insert(var_name, k_exit_param_vid);
}
// No PHI generation needed
```

**Why it works**:
1. **Matches Normalized design**: PHI-free continuations
2. **SSOT**: k_exit parameters are the canonical final values
3. **Simple**: No CFG analysis, no predecessor tracking
4. **Maintainable**: Works regardless of Normalized IR structure

### Option A: Fix PHI Generation (Rejected)

**Would require**:
1. Analyze Normalized IR's tail-call CFG structure
2. Map k_exit parameters to PHI inputs
3. Handle edge cases (conditional jumps, multiple exits)
4. Keep in sync with Normalized IR structure changes

**Problems**:
1. **Violates PHI-free design**: Normalized IR shouldn't generate PHI
2. **Complex**: CFG analysis for continuation-based control flow
3. **Fragile**: Breaks when Normalized IR structure changes
4. **Wrong abstraction**: k_exit params ARE the truth, why create PHI?

## Solution: ExitReconnectorBox

### Responsibility

Generate direct Copy instructions from k_exit env params to host variable_map (Normalized IR only)

### Contract

**Input**:
- `env_layout.writes`: Variables written in loop
- `k_exit_params`: k_exit function parameters (SSOT for final values)
- `exit_values`: Mapping from ExitMeta

**Output**:
- Direct variable_map updates (no PHI)

**Invariant**:
- Only used for Normalized shadow path
- Standard loops (Pattern 1-4) continue using existing merge pipeline

### Location

`src/mir/control_tree/normalized_shadow/exit_reconnector.rs`

**Rationale**: Normalized-specific logic stays in normalized_shadow/ module

## Verification Strategy

### Unit Tests

1. ExitReconnectorBox::reconnect() basic cases
2. Strict mode catches missing variables
3. Empty writes → empty bindings

### Integration Tests

1. phase131_loop_true_break_once_vm.sh → RC=1 (expected)
2. phase131_loop_true_break_once_llvm_exe.sh → RC=1
3. Regression: phase130, phase97 (既定挙動不変)

## Key Insights

1. **ExitMeta creation was NOT the problem** - it was already working correctly
2. **Boundary creation was NOT the problem** - ExitMetaCollector worked correctly
3. **The problem was using PHI-based merge** for a continuation-based control flow
4. **k_exit env parameters are SSOT** - no merging/PHI needed
5. **Option B respects Normalized IR's PHI-free design** - the right abstraction

## Next Steps

See `p1.5-option-b-analysis.md` for:
- Detailed implementation plan
- Testing strategy
- Commit sequence
- Fail-Fast verifier design

## Related Documents

- Phase 131 README: `docs/development/current/main/phases/phase-131/README.md`
- Option B Analysis: `docs/development/current/main/phases/phase-131/p1.5-option-b-analysis.md`
- Now: `docs/development/current/main/10-Now.md`
