feat(joinir): Phase 227 - CarrierRole separation (LoopState vs ConditionOnly)
- Add CarrierRole enum to distinguish state carriers from condition-only carriers - ConditionOnly carriers (is_digit_pos) skip exit PHI but keep header PHI - Update all test struct literals with role field - 877/884 tests PASS (7 pre-existing failures unrelated) Remaining: ValueId(0) undefined - header PHI initialization for ConditionOnly 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
@ -89,10 +89,12 @@ impl ExitMetaCollector {
|
||||
|
||||
// Look up host slot from variable_map
|
||||
if let Some(&host_slot) = builder.variable_map.get(carrier_name) {
|
||||
use crate::mir::join_ir::lowering::carrier_info::CarrierRole;
|
||||
let binding = LoopExitBinding {
|
||||
carrier_name: carrier_name.clone(),
|
||||
join_exit_value: *join_exit_value,
|
||||
host_slot,
|
||||
role: CarrierRole::LoopState, // Phase 227: Default to LoopState (caller should update if needed)
|
||||
};
|
||||
|
||||
eprintln!(
|
||||
|
||||
@ -134,6 +134,7 @@ mod tests {
|
||||
carrier_name: "sum".to_string(),
|
||||
join_exit_value: ValueId(18),
|
||||
host_slot: ValueId(5),
|
||||
role: crate::mir::join_ir::lowering::carrier_info::CarrierRole::LoopState,
|
||||
};
|
||||
|
||||
let remapper = JoinIrIdRemapper::new();
|
||||
|
||||
@ -607,8 +607,19 @@ pub(super) fn merge_and_rewrite(
|
||||
//
|
||||
// For each carrier, use the header PHI dst instead of
|
||||
// the undefined exit binding value.
|
||||
//
|
||||
// Phase 227: Filter out ConditionOnly carriers from exit PHI
|
||||
if let Some(b) = boundary {
|
||||
for binding in &b.exit_bindings {
|
||||
// Phase 227: Skip ConditionOnly carriers (they don't need exit PHI)
|
||||
if binding.role == crate::mir::join_ir::lowering::carrier_info::CarrierRole::ConditionOnly {
|
||||
eprintln!(
|
||||
"[DEBUG-177] Phase 227: Skipping ConditionOnly carrier '{}' from exit PHI",
|
||||
binding.carrier_name
|
||||
);
|
||||
continue;
|
||||
}
|
||||
|
||||
if let Some(phi_dst) = loop_header_phi_info.get_carrier_phi(&binding.carrier_name) {
|
||||
carrier_inputs.entry(binding.carrier_name.clone())
|
||||
.or_insert_with(Vec::new)
|
||||
|
||||
@ -82,6 +82,7 @@ impl LoopHeaderPhiBuilder {
|
||||
phi_dst: loop_var_phi_dst,
|
||||
entry_incoming: (entry_block, loop_var_init),
|
||||
latch_incoming: None,
|
||||
role: crate::mir::join_ir::lowering::carrier_info::CarrierRole::LoopState, // Phase 227: Loop var is always LoopState
|
||||
},
|
||||
);
|
||||
// Phase 177-STRUCT-2: Record insertion order
|
||||
@ -103,6 +104,7 @@ impl LoopHeaderPhiBuilder {
|
||||
phi_dst,
|
||||
entry_incoming: (entry_block, *init_value),
|
||||
latch_incoming: None,
|
||||
role: crate::mir::join_ir::lowering::carrier_info::CarrierRole::LoopState, // Phase 227: Default to LoopState (will be updated later if needed)
|
||||
},
|
||||
);
|
||||
// Phase 177-STRUCT-2: Record insertion order
|
||||
|
||||
@ -11,6 +11,7 @@
|
||||
//! - ExitLineReconnector: to update variable_map with final values
|
||||
|
||||
use crate::mir::{BasicBlockId, ValueId};
|
||||
use crate::mir::join_ir::lowering::carrier_info::CarrierRole;
|
||||
use std::collections::BTreeMap;
|
||||
|
||||
/// Information about loop header PHIs
|
||||
@ -55,6 +56,9 @@ pub struct CarrierPhiEntry {
|
||||
|
||||
/// Latch edge: (from_block, updated_value) - set after instruction rewrite
|
||||
pub latch_incoming: Option<(BasicBlockId, ValueId)>,
|
||||
|
||||
/// Phase 227: Role of this carrier (LoopState or ConditionOnly)
|
||||
pub role: CarrierRole,
|
||||
}
|
||||
|
||||
impl LoopHeaderPhiInfo {
|
||||
@ -152,6 +156,7 @@ mod tests {
|
||||
phi_dst: ValueId(100),
|
||||
entry_incoming: (BasicBlockId(1), ValueId(5)),
|
||||
latch_incoming: None,
|
||||
role: CarrierRole::LoopState,
|
||||
},
|
||||
);
|
||||
|
||||
|
||||
@ -162,6 +162,7 @@ impl CommonPatternInitializer {
|
||||
name: name.clone(),
|
||||
host_id: ValueId(0), // Dummy
|
||||
join_id: None,
|
||||
role: crate::mir::join_ir::lowering::carrier_info::CarrierRole::LoopState, // Phase 227: Default
|
||||
})
|
||||
} else {
|
||||
None
|
||||
|
||||
@ -142,6 +142,7 @@ mod tests {
|
||||
name: "sum".to_string(),
|
||||
host_id: ValueId(10),
|
||||
join_id: None,
|
||||
role: crate::mir::join_ir::lowering::carrier_info::CarrierRole::LoopState,
|
||||
}],
|
||||
);
|
||||
|
||||
@ -181,11 +182,13 @@ mod tests {
|
||||
name: "printed".to_string(),
|
||||
host_id: ValueId(11),
|
||||
join_id: None,
|
||||
role: crate::mir::join_ir::lowering::carrier_info::CarrierRole::LoopState,
|
||||
},
|
||||
CarrierVar {
|
||||
name: "sum".to_string(),
|
||||
host_id: ValueId(10),
|
||||
join_id: None,
|
||||
role: crate::mir::join_ir::lowering::carrier_info::CarrierRole::LoopState,
|
||||
},
|
||||
],
|
||||
);
|
||||
@ -228,6 +231,7 @@ mod tests {
|
||||
name: "sum".to_string(),
|
||||
host_id: ValueId(10),
|
||||
join_id: None,
|
||||
role: crate::mir::join_ir::lowering::carrier_info::CarrierRole::LoopState,
|
||||
}],
|
||||
);
|
||||
|
||||
@ -256,6 +260,7 @@ mod tests {
|
||||
name: "sum".to_string(),
|
||||
host_id: ValueId(10),
|
||||
join_id: None,
|
||||
role: crate::mir::join_ir::lowering::carrier_info::CarrierRole::LoopState,
|
||||
}],
|
||||
);
|
||||
|
||||
@ -284,6 +289,7 @@ mod tests {
|
||||
name: "sum".to_string(),
|
||||
host_id: ValueId(10),
|
||||
join_id: None,
|
||||
role: crate::mir::join_ir::lowering::carrier_info::CarrierRole::LoopState,
|
||||
}],
|
||||
);
|
||||
|
||||
@ -315,6 +321,7 @@ mod tests {
|
||||
name: "sum".to_string(),
|
||||
host_id: ValueId(10),
|
||||
join_id: None,
|
||||
role: crate::mir::join_ir::lowering::carrier_info::CarrierRole::LoopState,
|
||||
}],
|
||||
);
|
||||
|
||||
|
||||
@ -52,6 +52,7 @@ pub fn apply_exit_bindings_to_boundary(
|
||||
carrier_name: carrier.name.clone(),
|
||||
host_slot: post_loop_id,
|
||||
join_exit_value: join_exit_id,
|
||||
role: carrier.role, // Phase 227: Propagate role from CarrierInfo
|
||||
});
|
||||
|
||||
join_outputs.push(join_exit_id);
|
||||
@ -83,10 +84,12 @@ pub fn apply_exit_bindings_to_boundary(
|
||||
///
|
||||
/// LoopExitBinding for the loop variable
|
||||
pub fn create_loop_var_exit_binding(carrier_info: &CarrierInfo) -> LoopExitBinding {
|
||||
use crate::mir::join_ir::lowering::carrier_info::CarrierRole;
|
||||
LoopExitBinding {
|
||||
carrier_name: carrier_info.loop_var_name.clone(),
|
||||
join_exit_value: carrier_info.loop_var_id, // Loop var maps to itself
|
||||
host_slot: carrier_info.loop_var_id,
|
||||
role: CarrierRole::LoopState, // Phase 227: Loop var is always LoopState
|
||||
}
|
||||
}
|
||||
|
||||
@ -104,6 +107,7 @@ mod tests {
|
||||
name: "sum".to_string(),
|
||||
host_id: ValueId(10),
|
||||
join_id: None,
|
||||
role: crate::mir::join_ir::lowering::carrier_info::CarrierRole::LoopState,
|
||||
}],
|
||||
);
|
||||
|
||||
|
||||
@ -40,6 +40,7 @@ pub fn build_loop_exit_bindings(
|
||||
carrier_name: carrier.name.clone(),
|
||||
join_exit_value: join_exit_id,
|
||||
host_slot: carrier.host_id,
|
||||
role: carrier.role, // Phase 227: Propagate role from CarrierInfo
|
||||
});
|
||||
|
||||
// Allocate new ValueId for post-loop carrier value
|
||||
@ -90,6 +91,7 @@ mod tests {
|
||||
name: "sum".to_string(),
|
||||
host_id: ValueId(10),
|
||||
join_id: None,
|
||||
role: crate::mir::join_ir::lowering::carrier_info::CarrierRole::LoopState,
|
||||
}],
|
||||
);
|
||||
|
||||
@ -127,11 +129,13 @@ mod tests {
|
||||
name: "printed".to_string(),
|
||||
host_id: ValueId(11),
|
||||
join_id: None,
|
||||
role: crate::mir::join_ir::lowering::carrier_info::CarrierRole::LoopState,
|
||||
},
|
||||
CarrierVar {
|
||||
name: "sum".to_string(),
|
||||
host_id: ValueId(10),
|
||||
join_id: None,
|
||||
role: crate::mir::join_ir::lowering::carrier_info::CarrierRole::LoopState,
|
||||
},
|
||||
],
|
||||
);
|
||||
|
||||
@ -69,6 +69,7 @@ mod tests {
|
||||
name: "sum".to_string(),
|
||||
host_id: ValueId(10),
|
||||
join_id: None,
|
||||
role: crate::mir::join_ir::lowering::carrier_info::CarrierRole::LoopState,
|
||||
}],
|
||||
);
|
||||
|
||||
@ -88,11 +89,13 @@ mod tests {
|
||||
name: "printed".to_string(),
|
||||
host_id: ValueId(11),
|
||||
join_id: None,
|
||||
role: crate::mir::join_ir::lowering::carrier_info::CarrierRole::LoopState,
|
||||
},
|
||||
CarrierVar {
|
||||
name: "sum".to_string(),
|
||||
host_id: ValueId(10),
|
||||
join_id: None,
|
||||
role: crate::mir::join_ir::lowering::carrier_info::CarrierRole::LoopState,
|
||||
},
|
||||
],
|
||||
);
|
||||
@ -115,6 +118,7 @@ mod tests {
|
||||
name: "sum".to_string(),
|
||||
host_id: ValueId(10),
|
||||
join_id: None,
|
||||
role: crate::mir::join_ir::lowering::carrier_info::CarrierRole::LoopState,
|
||||
}],
|
||||
);
|
||||
|
||||
@ -135,6 +139,7 @@ mod tests {
|
||||
name: "sum".to_string(),
|
||||
host_id: ValueId(10),
|
||||
join_id: None,
|
||||
role: crate::mir::join_ir::lowering::carrier_info::CarrierRole::LoopState,
|
||||
}],
|
||||
);
|
||||
|
||||
@ -155,6 +160,7 @@ mod tests {
|
||||
name: "sum".to_string(),
|
||||
host_id: ValueId(10),
|
||||
join_id: None,
|
||||
role: crate::mir::join_ir::lowering::carrier_info::CarrierRole::LoopState,
|
||||
}],
|
||||
);
|
||||
|
||||
|
||||
@ -475,9 +475,13 @@ impl MirBuilder {
|
||||
// Issue: CommonPatternInitializer includes all variables in variable_map as carriers,
|
||||
// but only variables with updates in the loop body are true carriers.
|
||||
// Condition-only variables (like 'len', 's') should be excluded.
|
||||
//
|
||||
// Phase 227: Keep ConditionOnly carriers even if they don't have updates
|
||||
// (they're used in loop/break conditions, not updated)
|
||||
let original_carrier_count = carrier_info.carriers.len();
|
||||
carrier_info.carriers.retain(|carrier| {
|
||||
carrier_updates.contains_key(&carrier.name)
|
||||
use crate::mir::join_ir::lowering::carrier_info::CarrierRole;
|
||||
carrier_updates.contains_key(&carrier.name) || carrier.role == CarrierRole::ConditionOnly
|
||||
});
|
||||
|
||||
eprintln!(
|
||||
|
||||
@ -276,16 +276,19 @@ mod tests {
|
||||
name: "i".to_string(),
|
||||
host_id: ValueId(1),
|
||||
join_id: None,
|
||||
role: crate::mir::join_ir::lowering::carrier_info::CarrierRole::LoopState,
|
||||
},
|
||||
CarrierVar {
|
||||
name: "sum".to_string(),
|
||||
host_id: ValueId(2),
|
||||
join_id: None,
|
||||
role: crate::mir::join_ir::lowering::carrier_info::CarrierRole::LoopState,
|
||||
},
|
||||
CarrierVar {
|
||||
name: "M".to_string(),
|
||||
host_id: ValueId(3),
|
||||
join_id: None,
|
||||
role: crate::mir::join_ir::lowering::carrier_info::CarrierRole::LoopState,
|
||||
},
|
||||
],
|
||||
trim_helper: None,
|
||||
|
||||
@ -396,11 +396,13 @@ mod tests {
|
||||
name: "sum".to_string(),
|
||||
host_id: ValueId(10),
|
||||
join_id: None,
|
||||
role: crate::mir::join_ir::lowering::carrier_info::CarrierRole::LoopState,
|
||||
},
|
||||
CarrierVar {
|
||||
name: "count".to_string(),
|
||||
host_id: ValueId(11),
|
||||
join_id: None,
|
||||
role: crate::mir::join_ir::lowering::carrier_info::CarrierRole::LoopState,
|
||||
},
|
||||
],
|
||||
trim_helper: None,
|
||||
|
||||
Reference in New Issue
Block a user