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 {
|
} else {
|
||||||
let tmp = writable_spilltmp_reg();
|
let tmp = writable_spilltmp_reg();
|
||||||
assert!(base != tmp.to_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())
|
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.
|
/// 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) {
|
if let Ok(imm) = i16::try_from(value as i64) {
|
||||||
// 16-bit signed immediate
|
// 16-bit signed immediate
|
||||||
smallvec![Inst::Mov64SImm16 { rd, imm }]
|
smallvec![Inst::Mov64SImm16 { rd, imm }]
|
||||||
@@ -353,12 +358,13 @@ impl Inst {
|
|||||||
let hi = value & 0xffff_ffff_0000_0000u64;
|
let hi = value & 0xffff_ffff_0000_0000u64;
|
||||||
let lo = value & 0x0000_0000_ffff_ffffu64;
|
let lo = value & 0x0000_0000_ffff_ffffu64;
|
||||||
|
|
||||||
|
let hi_rd = alloc_tmp(types::I64);
|
||||||
if let Some(imm) = UImm16Shifted::maybe_from_u64(hi) {
|
if let Some(imm) = UImm16Shifted::maybe_from_u64(hi) {
|
||||||
// 16-bit shifted immediate
|
// 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) {
|
} else if let Some(imm) = UImm32Shifted::maybe_from_u64(hi) {
|
||||||
// 32-bit shifted immediate
|
// 32-bit shifted immediate
|
||||||
insts.push(Inst::Mov64UImm32Shifted { rd, imm });
|
insts.push(Inst::Mov64UImm32Shifted { rd: hi_rd, imm });
|
||||||
} else {
|
} else {
|
||||||
unreachable!();
|
unreachable!();
|
||||||
}
|
}
|
||||||
@@ -367,14 +373,14 @@ impl Inst {
|
|||||||
// 16-bit shifted immediate
|
// 16-bit shifted immediate
|
||||||
insts.push(Inst::Insert64UImm16Shifted {
|
insts.push(Inst::Insert64UImm16Shifted {
|
||||||
rd,
|
rd,
|
||||||
ri: rd.to_reg(),
|
ri: hi_rd.to_reg(),
|
||||||
imm,
|
imm,
|
||||||
});
|
});
|
||||||
} else if let Some(imm) = UImm32Shifted::maybe_from_u64(lo) {
|
} else if let Some(imm) = UImm32Shifted::maybe_from_u64(lo) {
|
||||||
// 32-bit shifted immediate
|
// 32-bit shifted immediate
|
||||||
insts.push(Inst::Insert64UImm32Shifted {
|
insts.push(Inst::Insert64UImm32Shifted {
|
||||||
rd,
|
rd,
|
||||||
ri: rd.to_reg(),
|
ri: hi_rd.to_reg(),
|
||||||
imm,
|
imm,
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
@@ -1172,7 +1178,7 @@ impl MachInst for Inst {
|
|||||||
to_regs: ValueRegs<Writable<Reg>>,
|
to_regs: ValueRegs<Writable<Reg>>,
|
||||||
value: u128,
|
value: u128,
|
||||||
ty: Type,
|
ty: Type,
|
||||||
_alloc_tmp: F,
|
alloc_tmp: F,
|
||||||
) -> SmallVec<[Inst; 4]> {
|
) -> SmallVec<[Inst; 4]> {
|
||||||
let to_reg = to_regs
|
let to_reg = to_regs
|
||||||
.only_reg()
|
.only_reg()
|
||||||
@@ -1204,7 +1210,7 @@ impl MachInst for Inst {
|
|||||||
));
|
));
|
||||||
ret
|
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),
|
types::I8 | types::I16 | types::I32 => Inst::load_constant32(to_reg, value as u32),
|
||||||
_ => unreachable!(),
|
_ => unreachable!(),
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user