cranelift: Rework pinned register lowering (#5249)

Rework pinned register lowering to avoid the use of pinned virtual registers, instead using the MovFromPReg and MovToPReg pseudo instructions.
This commit is contained in:
Trevor Elliott
2022-11-10 16:19:25 -08:00
committed by GitHub
parent 7717d8fa55
commit 0367fbc2d4
14 changed files with 150 additions and 71 deletions

View File

@@ -95,8 +95,13 @@
;; Like `MovRR` but with a physical register source (for implementing
;; CLIF instructions like `get_stack_pointer`).
(MovPReg (src PReg)
(dst WritableGpr))
(MovFromPReg (src PReg)
(dst WritableGpr))
;; Like `MovRR` but with a physical register destination (for
;; implementing CLIF instructions like `set_pinned_reg`).
(MovToPReg (src Gpr)
(dst PReg))
;; Zero-extended loads, except for 64 bits: movz (bl bq wl wq lq) addr
;; reg.
@@ -1200,10 +1205,6 @@
(decl temp_writable_xmm () WritableXmm)
(extern constructor temp_writable_xmm temp_writable_xmm)
;; Fetch the special pinned register.
(decl pinned_writable_gpr () WritableGpr)
(extern constructor pinned_writable_gpr pinned_writable_gpr)
;; Construct a new `XmmMem` from the given `RegMem`.
;;
;; Asserts that the `RegMem`'s register, if any, is an XMM register.
@@ -3701,12 +3702,11 @@
(decl read_pinned_gpr () Gpr)
(rule (read_pinned_gpr)
(pinned_writable_gpr))
(mov_from_preg (preg_pinned)))
(decl write_pinned_gpr (Gpr) SideEffectNoResult)
(rule (write_pinned_gpr val)
(let ((dst WritableGpr (pinned_writable_gpr)))
(SideEffectNoResult.Inst (gen_move $I64 dst val))))
(mov_to_preg (preg_pinned) val))
;;;; Shuffle ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
@@ -3882,26 +3882,33 @@
(decl const_to_synthetic_amode (VCodeConstant) SyntheticAmode)
(extern constructor const_to_synthetic_amode const_to_synthetic_amode)
;; Helper for creating `MovPReg` instructions.
(decl mov_preg (PReg) Reg)
(rule (mov_preg preg)
;; Helper for creating `MovFromPReg` instructions.
(decl mov_from_preg (PReg) Reg)
(rule (mov_from_preg preg)
(let ((dst WritableGpr (temp_writable_gpr))
(_ Unit (emit (MInst.MovPReg preg dst))))
(_ Unit (emit (MInst.MovFromPReg preg dst))))
dst))
(decl mov_to_preg (PReg Gpr) SideEffectNoResult)
(rule (mov_to_preg dst src)
(SideEffectNoResult.Inst (MInst.MovToPReg src dst)))
(decl preg_rbp () PReg)
(extern constructor preg_rbp preg_rbp)
(decl preg_rsp () PReg)
(extern constructor preg_rsp preg_rsp)
(decl preg_pinned () PReg)
(extern constructor preg_pinned preg_pinned)
(decl x64_rbp () Reg)
(rule (x64_rbp)
(mov_preg (preg_rbp)))
(mov_from_preg (preg_rbp)))
(decl x64_rsp () Reg)
(rule (x64_rsp)
(mov_preg (preg_rsp)))
(mov_from_preg (preg_rsp)))
;;;; Helpers for Emitting LibCalls ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

View File

@@ -698,9 +698,9 @@ pub(crate) fn emit(
);
}
Inst::MovPReg { src, dst } => {
Inst::MovFromPReg { src, dst } => {
let src: Reg = (*src).into();
debug_assert!([regs::rsp(), regs::rbp()].contains(&src));
debug_assert!([regs::rsp(), regs::rbp(), regs::pinned_reg()].contains(&src));
let src = Gpr::new(src).unwrap();
let size = OperandSize::Size64;
let dst = allocs.next(dst.to_reg().to_reg());
@@ -708,6 +708,16 @@ pub(crate) fn emit(
Inst::MovRR { size, src, dst }.emit(&[], sink, info, state);
}
Inst::MovToPReg { src, dst } => {
let src = allocs.next(src.to_reg());
let src = Gpr::new(src).unwrap();
let dst: Reg = (*dst).into();
debug_assert!([regs::rsp(), regs::rbp(), regs::pinned_reg()].contains(&dst));
let dst = WritableGpr::from_writable_reg(Writable::from_reg(dst)).unwrap();
let size = OperandSize::Size64;
Inst::MovRR { size, src, dst }.emit(&[], sink, info, state);
}
Inst::MovzxRmR { ext_mode, src, dst } => {
let dst = allocs.next(dst.to_reg().to_reg());
let (opcodes, num_opcodes, mut rex_flags) = match ext_mode {

View File

@@ -92,7 +92,8 @@ impl Inst {
| Inst::Mov64MR { .. }
| Inst::MovRM { .. }
| Inst::MovRR { .. }
| Inst::MovPReg { .. }
| Inst::MovFromPReg { .. }
| Inst::MovToPReg { .. }
| Inst::MovsxRmR { .. }
| Inst::MovzxRmR { .. }
| Inst::MulHi { .. }
@@ -1233,13 +1234,20 @@ impl PrettyPrint for Inst {
)
}
Inst::MovPReg { src, dst } => {
Inst::MovFromPReg { src, dst } => {
let src: Reg = (*src).into();
let src = regs::show_ireg_sized(src, 8);
let dst = pretty_print_reg(dst.to_reg().to_reg(), 8, allocs);
format!("{} {}, {}", ljustify("movq".to_string()), src, dst)
}
Inst::MovToPReg { src, dst } => {
let src = pretty_print_reg(src.to_reg(), 8, allocs);
let dst: Reg = (*dst).into();
let dst = regs::show_ireg_sized(dst, 8);
format!("{} {}, {}", ljustify("movq".to_string()), src, dst)
}
Inst::MovzxRmR {
ext_mode, src, dst, ..
} => {
@@ -1877,11 +1885,16 @@ fn x64_get_operands<F: Fn(VReg) -> VReg>(inst: &Inst, collector: &mut OperandCol
collector.reg_use(src.to_reg());
collector.reg_def(dst.to_writable_reg());
}
Inst::MovPReg { dst, src } => {
debug_assert!([regs::rsp(), regs::rbp()].contains(&(*src).into()));
Inst::MovFromPReg { dst, src } => {
debug_assert!([regs::rsp(), regs::rbp(), regs::pinned_reg()].contains(&(*src).into()));
debug_assert!(dst.to_reg().to_reg().is_virtual());
collector.reg_def(dst.to_writable_reg());
}
Inst::MovToPReg { dst, src } => {
debug_assert!(src.to_reg().is_virtual());
debug_assert!([regs::rsp(), regs::rbp(), regs::pinned_reg()].contains(&(*dst).into()));
collector.reg_use(src.to_reg());
}
Inst::XmmToGpr { src, dst, .. } => {
collector.reg_use(src.to_reg());
collector.reg_def(dst.to_writable_reg());

View File

@@ -640,6 +640,11 @@ impl Context for IsleContext<'_, '_, MInst, Flags, IsaFlags, 6> {
regs::rsp().to_real_reg().unwrap().into()
}
#[inline]
fn preg_pinned(&mut self) -> PReg {
regs::pinned_reg().to_real_reg().unwrap().into()
}
fn libcall_1(&mut self, libcall: &LibCall, a: Reg) -> Reg {
let call_conv = self.lower_ctx.abi().call_conv(self.lower_ctx.sigs());
let ret_ty = libcall.signature(call_conv).returns[0].value_type;
@@ -769,11 +774,6 @@ impl Context for IsleContext<'_, '_, MInst, Flags, IsaFlags, 6> {
.use_constant(VCodeConstantData::WellKnown(&UMAX_MASK))
}
#[inline]
fn pinned_writable_gpr(&mut self) -> WritableGpr {
Writable::from_reg(Gpr::new(regs::pinned_reg()).unwrap())
}
#[inline]
fn shuffle_0_31_mask(&mut self, mask: &VecMask) -> VCodeConstant {
let mask = mask