Cranelift: fix regalloc2 integration bug wrt blockparam branch args. (#4042)

Previously, the block successor accumulation and the blockparam branch
arg setup were decoupled. The lowering backend implicitly specified
the order of successor edges via its `MachTerminator` enum on the last
instruction in the block, while the `Lower` toplevel
machine-independent driver set up blockparam branch args in the edge
order seen in CLIF.

In some cases, these orders did not match -- for example, when the
conditional branch depended on an FP condition that was implemented by
swapping taken/not-taken edges and inverting the condition code.

This PR refactors the successor handling to be centralized in `Lower`
rather than flow through the terminator `MachInst`, and adds a
successor block and its blockparam args at the same time, ensuring the
orders match.
This commit is contained in:
Chris Fallin
2022-04-18 09:53:57 -07:00
committed by GitHub
parent 7cf5f05830
commit 5774e068b7
7 changed files with 44 additions and 68 deletions

View File

@@ -98,7 +98,6 @@ pub struct CallIndInfo {
pub struct JTSequenceInfo {
pub targets: Vec<BranchTarget>,
pub default_target: BranchTarget,
pub targets_for_term: Vec<MachLabel>, // needed for MachTerminator.
}
fn count_zero_half_words(mut value: u64, num_half_words: u8) -> usize {
@@ -1091,17 +1090,13 @@ impl MachInst for Inst {
}
}
fn is_term<'a>(&'a self) -> MachTerminator<'a> {
fn is_term(&self) -> MachTerminator {
match self {
&Inst::Ret { .. } | &Inst::EpiloguePlaceholder => MachTerminator::Ret,
&Inst::Jump { dest } => MachTerminator::Uncond(dest.as_label().unwrap()),
&Inst::CondBr {
taken, not_taken, ..
} => MachTerminator::Cond(taken.as_label().unwrap(), not_taken.as_label().unwrap()),
&Inst::IndirectBr { ref targets, .. } => MachTerminator::Indirect(&targets[..]),
&Inst::JTSequence { ref info, .. } => {
MachTerminator::Indirect(&info.targets_for_term[..])
}
&Inst::Jump { .. } => MachTerminator::Uncond,
&Inst::CondBr { .. } => MachTerminator::Cond,
&Inst::IndirectBr { .. } => MachTerminator::Indirect,
&Inst::JTSequence { .. } => MachTerminator::Indirect,
_ => MachTerminator::None,
}
}

View File

@@ -2739,7 +2739,6 @@ pub(crate) fn lower_branch<C: LowerCtx<I = Inst>>(
.map(|bix| BranchTarget::Label(*bix))
.collect();
let default_target = BranchTarget::Label(targets[0]);
let targets_for_term: Vec<MachLabel> = targets.to_vec();
ctx.emit(Inst::JTSequence {
ridx,
rtmp1,
@@ -2747,7 +2746,6 @@ pub(crate) fn lower_branch<C: LowerCtx<I = Inst>>(
info: Box::new(JTSequenceInfo {
targets: jt_targets,
default_target,
targets_for_term,
}),
});
}

View File

@@ -733,19 +733,17 @@ impl MachInst for Inst {
}
}
fn is_term<'a>(&'a self) -> MachTerminator<'a> {
fn is_term(&self) -> MachTerminator {
match self {
&Inst::Ret { .. } | &Inst::EpiloguePlaceholder => MachTerminator::Ret,
&Inst::Jump { dest } => MachTerminator::Uncond(dest),
&Inst::CondBr {
taken, not_taken, ..
} => MachTerminator::Cond(taken, not_taken),
&Inst::Jump { .. } => MachTerminator::Uncond,
&Inst::CondBr { .. } => MachTerminator::Cond,
&Inst::OneWayCondBr { .. } => {
// Explicitly invisible to CFG processing.
MachTerminator::None
}
&Inst::IndirectBr { ref targets, .. } => MachTerminator::Indirect(&targets[..]),
&Inst::JTSequence { ref targets, .. } => MachTerminator::Indirect(&targets[..]),
&Inst::IndirectBr { .. } => MachTerminator::Indirect,
&Inst::JTSequence { .. } => MachTerminator::Indirect,
_ => MachTerminator::None,
}
}

View File

@@ -2119,18 +2119,13 @@ impl MachInst for Inst {
}
}
fn is_term<'a>(&'a self) -> MachTerminator<'a> {
fn is_term(&self) -> MachTerminator {
match self {
// Interesting cases.
&Self::Ret { .. } | &Self::EpiloguePlaceholder => MachTerminator::Ret,
&Self::JmpKnown { dst } => MachTerminator::Uncond(dst),
&Self::JmpCond {
taken, not_taken, ..
} => MachTerminator::Cond(taken, not_taken),
&Self::JmpTableSeq {
ref targets_for_term,
..
} => MachTerminator::Indirect(&targets_for_term[..]),
&Self::JmpKnown { .. } => MachTerminator::Uncond,
&Self::JmpCond { .. } => MachTerminator::Cond,
&Self::JmpTableSeq { .. } => MachTerminator::Indirect,
// All other cases are boring.
_ => MachTerminator::None,
}