Allocate a temporary for 64-bit constant loads in the s390x backend (#5357)
Avoid reusing a destination virtual register for 64-bit constants in the s390x backend. This change addresses a case identified by the regalloc2 ssa validator, as the destination register was written to twice when constants were generated via the MachInst::gen_constant function.
This commit is contained in:
@@ -104,7 +104,7 @@ pub fn mem_finalize(
|
||||
} else {
|
||||
let tmp = writable_spilltmp_reg();
|
||||
assert!(base != tmp.to_reg());
|
||||
insts.extend(Inst::load_constant64(tmp, off as u64));
|
||||
insts.extend(Inst::load_constant64(tmp, off as u64, |_| tmp));
|
||||
MemArg::reg_plus_reg(base, tmp.to_reg(), mem.get_flags())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -335,7 +335,12 @@ impl Inst {
|
||||
}
|
||||
|
||||
/// Create an instruction that loads a 64-bit integer constant.
|
||||
pub fn load_constant64(rd: Writable<Reg>, value: u64) -> SmallVec<[Inst; 4]> {
|
||||
pub fn load_constant64<F: FnMut(Type) -> Writable<Reg>>(
|
||||
rd: Writable<Reg>,
|
||||
value: u64,
|
||||
mut alloc_tmp: F,
|
||||
) -> SmallVec<[Inst; 4]> {
|
||||
crate::trace!("loading a constant! {}", value);
|
||||
if let Ok(imm) = i16::try_from(value as i64) {
|
||||
// 16-bit signed immediate
|
||||
smallvec![Inst::Mov64SImm16 { rd, imm }]
|
||||
@@ -353,12 +358,13 @@ impl Inst {
|
||||
let hi = value & 0xffff_ffff_0000_0000u64;
|
||||
let lo = value & 0x0000_0000_ffff_ffffu64;
|
||||
|
||||
let hi_rd = alloc_tmp(types::I64);
|
||||
if let Some(imm) = UImm16Shifted::maybe_from_u64(hi) {
|
||||
// 16-bit shifted immediate
|
||||
insts.push(Inst::Mov64UImm16Shifted { rd, imm });
|
||||
insts.push(Inst::Mov64UImm16Shifted { rd: hi_rd, imm });
|
||||
} else if let Some(imm) = UImm32Shifted::maybe_from_u64(hi) {
|
||||
// 32-bit shifted immediate
|
||||
insts.push(Inst::Mov64UImm32Shifted { rd, imm });
|
||||
insts.push(Inst::Mov64UImm32Shifted { rd: hi_rd, imm });
|
||||
} else {
|
||||
unreachable!();
|
||||
}
|
||||
@@ -367,14 +373,14 @@ impl Inst {
|
||||
// 16-bit shifted immediate
|
||||
insts.push(Inst::Insert64UImm16Shifted {
|
||||
rd,
|
||||
ri: rd.to_reg(),
|
||||
ri: hi_rd.to_reg(),
|
||||
imm,
|
||||
});
|
||||
} else if let Some(imm) = UImm32Shifted::maybe_from_u64(lo) {
|
||||
// 32-bit shifted immediate
|
||||
insts.push(Inst::Insert64UImm32Shifted {
|
||||
rd,
|
||||
ri: rd.to_reg(),
|
||||
ri: hi_rd.to_reg(),
|
||||
imm,
|
||||
});
|
||||
} else {
|
||||
@@ -1172,7 +1178,7 @@ impl MachInst for Inst {
|
||||
to_regs: ValueRegs<Writable<Reg>>,
|
||||
value: u128,
|
||||
ty: Type,
|
||||
_alloc_tmp: F,
|
||||
alloc_tmp: F,
|
||||
) -> SmallVec<[Inst; 4]> {
|
||||
let to_reg = to_regs
|
||||
.only_reg()
|
||||
@@ -1204,7 +1210,7 @@ impl MachInst for Inst {
|
||||
));
|
||||
ret
|
||||
}
|
||||
types::I64 | types::R64 => Inst::load_constant64(to_reg, value as u64),
|
||||
types::I64 | types::R64 => Inst::load_constant64(to_reg, value as u64, alloc_tmp),
|
||||
types::I8 | types::I16 | types::I32 => Inst::load_constant32(to_reg, value as u32),
|
||||
_ => unreachable!(),
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user