Fix coalescer bug exposed by the gvn-unremovable-phi test.
When we detect interference between the values that have already been merged into the candidate virtual register and an EBB argument, we first try to resolve the conflict by splitting. We also check if the existing interfering value is fundamentally incompatible with the branch instruction so it needs to be removed from the virtual register, restarting the merge operation. However, this existing interfering value is not necessarily the only interference, so the split is not guaranteed to resolve the conflict. If it turns out that splitting didn't resolve the conflict, restart the merge after removing this second conflicting value.
This commit is contained in:
@@ -450,13 +450,21 @@ impl<'a> Context<'a> {
|
||||
return Some(a);
|
||||
}
|
||||
|
||||
// The local conflict could be avoided by splitting at this predecessor, so try
|
||||
// that. This split is not necessarily required, but it allows us to make progress.
|
||||
// The local conflict could likely be avoided by splitting at this predecessor, so
|
||||
// try that. This split is not necessarily required, but it allows us to make
|
||||
// progress.
|
||||
let new_val = self.split_pred(pred_inst, pred_ebb, argnum, pred_val);
|
||||
assert!(
|
||||
self.add_class(new_val).is_ok(),
|
||||
"Splitting didn't resolve conflict."
|
||||
);
|
||||
|
||||
// If this tiny new live range can't be merged, there is something in the already
|
||||
// merged values that is fundamentally incompatible with `pred_inst`, and we need
|
||||
// to start over after removing that value.
|
||||
// TODO: It is unfortunate that we discover this *after* splitting. It would have
|
||||
// been better if we could detect and isolate `merged` before splitting.
|
||||
if let Err((merged, _)) = self.add_class(new_val) {
|
||||
dbg!("Splitting didn't help: {} interferes", merged);
|
||||
// We need to start over, isolating the bad value.
|
||||
return Some(merged);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user