mir: LoopBuilder if-merge – generate PHIs per assigned var and only for actual predecessors; avoid bogus incoming when branch terminates
This commit is contained in:
@ -549,7 +549,7 @@ impl<'a> LoopBuilder<'a> {
|
|||||||
}
|
}
|
||||||
let then_var_map_end = self.get_current_variable_map();
|
let then_var_map_end = self.get_current_variable_map();
|
||||||
// Only jump to merge if not already terminated (e.g., continue/break)
|
// Only jump to merge if not already terminated (e.g., continue/break)
|
||||||
{
|
let then_reaches_merge = {
|
||||||
let cur_id = self.current_block()?;
|
let cur_id = self.current_block()?;
|
||||||
let need_jump = {
|
let need_jump = {
|
||||||
if let Some(ref fun_ro) = self.parent_builder.current_function {
|
if let Some(ref fun_ro) = self.parent_builder.current_function {
|
||||||
@ -564,8 +564,11 @@ impl<'a> LoopBuilder<'a> {
|
|||||||
};
|
};
|
||||||
if need_jump {
|
if need_jump {
|
||||||
self.emit_jump(merge_bb)?;
|
self.emit_jump(merge_bb)?;
|
||||||
|
true
|
||||||
|
} else {
|
||||||
|
false
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
|
|
||||||
// else
|
// else
|
||||||
self.set_current_block(else_bb)?;
|
self.set_current_block(else_bb)?;
|
||||||
@ -593,7 +596,7 @@ impl<'a> LoopBuilder<'a> {
|
|||||||
}
|
}
|
||||||
else_var_map_end_opt = Some(self.get_current_variable_map());
|
else_var_map_end_opt = Some(self.get_current_variable_map());
|
||||||
}
|
}
|
||||||
{
|
let else_reaches_merge = {
|
||||||
let cur_id = self.current_block()?;
|
let cur_id = self.current_block()?;
|
||||||
let need_jump = {
|
let need_jump = {
|
||||||
if let Some(ref fun_ro) = self.parent_builder.current_function {
|
if let Some(ref fun_ro) = self.parent_builder.current_function {
|
||||||
@ -608,8 +611,11 @@ impl<'a> LoopBuilder<'a> {
|
|||||||
};
|
};
|
||||||
if need_jump {
|
if need_jump {
|
||||||
self.emit_jump(merge_bb)?;
|
self.emit_jump(merge_bb)?;
|
||||||
|
true
|
||||||
|
} else {
|
||||||
|
false
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
|
|
||||||
// Continue at merge
|
// Continue at merge
|
||||||
self.set_current_block(merge_bb)?;
|
self.set_current_block(merge_bb)?;
|
||||||
@ -657,14 +663,29 @@ impl<'a> LoopBuilder<'a> {
|
|||||||
.or_else(|| pre_then_var_value.get(&var_name).copied());
|
.or_else(|| pre_then_var_value.get(&var_name).copied());
|
||||||
|
|
||||||
if let (Some(tv), Some(ev)) = (then_val, else_val) {
|
if let (Some(tv), Some(ev)) = (then_val, else_val) {
|
||||||
let phi_id = self.new_value();
|
// Build incoming list only for predecessors that actually reach merge
|
||||||
if self.no_phi_mode {
|
let mut incomings: Vec<(BasicBlockId, ValueId)> = Vec::new();
|
||||||
self.parent_builder.insert_edge_copy(then_bb, phi_id, tv)?;
|
if then_reaches_merge { incomings.push((then_bb, tv)); }
|
||||||
self.parent_builder.insert_edge_copy(else_bb, phi_id, ev)?;
|
if else_reaches_merge { incomings.push((else_bb, ev)); }
|
||||||
} else {
|
match incomings.len() {
|
||||||
self.emit_phi_at_block_start(merge_bb, phi_id, vec![(then_bb, tv), (else_bb, ev)])?;
|
0 => { /* neither branch reaches merge: nothing to bind */ }
|
||||||
|
1 => {
|
||||||
|
// Single predecessor reaching merge: no PHI needed
|
||||||
|
let (_pred, v) = incomings[0];
|
||||||
|
self.parent_builder.variable_map.insert(var_name, v);
|
||||||
|
}
|
||||||
|
_ => {
|
||||||
|
let phi_id = self.new_value();
|
||||||
|
if self.no_phi_mode {
|
||||||
|
for (pred, v) in incomings.iter().copied() {
|
||||||
|
self.parent_builder.insert_edge_copy(pred, phi_id, v)?;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
self.emit_phi_at_block_start(merge_bb, phi_id, incomings)?;
|
||||||
|
}
|
||||||
|
self.parent_builder.variable_map.insert(var_name, phi_id);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
self.parent_builder.variable_map.insert(var_name, phi_id);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
let void_id = self.new_value();
|
let void_id = self.new_value();
|
||||||
|
|||||||
Reference in New Issue
Block a user