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

@@ -167,10 +167,16 @@
;; Like `Move` but with a particular `PReg` source (for implementing CLIF
;; instructions like `get_stack_pointer`).
(MovPReg
(MovFromPReg
(rd WritableReg)
(rm PReg))
;; Like `Move` but with a particular `PReg` destination (for
;; implementing CLIF instructions like `set_pinned_reg`).
(MovToPReg
(rd PReg)
(rm Reg))
;; A MOV[Z,N] with a 16-bit immediate.
(MovWide
(op MoveWideOp)
@@ -3061,12 +3067,16 @@
dst))
;; Helper for emitting `MInst.MovPReg` instructions.
(decl mov_preg (PReg) Reg)
(rule (mov_preg src)
(decl mov_from_preg (PReg) Reg)
(rule (mov_from_preg src)
(let ((dst WritableReg (temp_writable_reg $I64))
(_ Unit (emit (MInst.MovPReg dst src))))
(_ Unit (emit (MInst.MovFromPReg dst src))))
dst))
(decl mov_to_preg (PReg Reg) SideEffectNoResult)
(rule (mov_to_preg dst src)
(SideEffectNoResult.Inst (MInst.MovToPReg dst src)))
(decl preg_sp () PReg)
(extern constructor preg_sp preg_sp)
@@ -3076,13 +3086,16 @@
(decl preg_link () PReg)
(extern constructor preg_link preg_link)
(decl preg_pinned () PReg)
(extern constructor preg_pinned preg_pinned)
(decl aarch64_sp () Reg)
(rule (aarch64_sp)
(mov_preg (preg_sp)))
(mov_from_preg (preg_sp)))
(decl aarch64_fp () Reg)
(rule (aarch64_fp)
(mov_preg (preg_fp)))
(mov_from_preg (preg_fp)))
(decl aarch64_link () Reg)
(rule 1 (aarch64_link)
@@ -3111,7 +3124,7 @@
(lr WritableReg (writable_link_reg))
(_ Unit (emit (MInst.ULoad64 lr addr (mem_flags_trusted))))
(_ Unit (emit (MInst.Xpaclri))))
(mov_preg (preg_link))))
(mov_from_preg (preg_link))))
;; Helper for getting the maximum shift amount for a type.
@@ -3270,16 +3283,9 @@
;; Helpers for pinned register manipulation.
(decl writable_pinned_reg () WritableReg)
(extern constructor writable_pinned_reg writable_pinned_reg)
(decl pinned_reg () Reg)
(rule (pinned_reg) (writable_pinned_reg))
(decl write_pinned_reg (Reg) SideEffectNoResult)
(rule (write_pinned_reg val)
(let ((dst WritableReg (writable_pinned_reg)))
(SideEffectNoResult.Inst (gen_move $I64 dst val))))
(mov_to_preg (preg_pinned) val))
;; Helpers for stackslot effective address generation.

View File

@@ -1367,15 +1367,36 @@ impl MachInstEmit for Inst {
}
}
}
&Inst::MovPReg { rd, rm } => {
&Inst::MovFromPReg { rd, rm } => {
let rd = allocs.next_writable(rd);
let rm: Reg = rm.into();
debug_assert!([regs::fp_reg(), regs::stack_reg(), regs::link_reg()].contains(&rm));
debug_assert!([
regs::fp_reg(),
regs::stack_reg(),
regs::link_reg(),
regs::pinned_reg()
]
.contains(&rm));
assert!(rm.class() == RegClass::Int);
assert!(rd.to_reg().class() == rm.class());
let size = OperandSize::Size64;
Inst::Mov { size, rd, rm }.emit(&[], sink, emit_info, state);
}
&Inst::MovToPReg { rd, rm } => {
let rd: Writable<Reg> = Writable::from_reg(rd.into());
let rm = allocs.next(rm);
debug_assert!([
regs::fp_reg(),
regs::stack_reg(),
regs::link_reg(),
regs::pinned_reg()
]
.contains(&rd.to_reg()));
assert!(rd.to_reg().class() == RegClass::Int);
assert!(rm.class() == rd.to_reg().class());
let size = OperandSize::Size64;
Inst::Mov { size, rd, rm }.emit(&[], sink, emit_info, state);
}
&Inst::MovWide { op, rd, imm, size } => {
let rd = allocs.next_writable(rd);
sink.put4(enc_move_wide(op, rd, imm, size));

View File

@@ -654,13 +654,28 @@ fn aarch64_get_operands<F: Fn(VReg) -> VReg>(inst: &Inst, collector: &mut Operan
collector.reg_def(rd);
collector.reg_use(rm);
}
&Inst::MovPReg { rd, rm } => {
debug_assert!(
[regs::fp_reg(), regs::stack_reg(), regs::link_reg()].contains(&rm.into())
);
&Inst::MovFromPReg { rd, rm } => {
debug_assert!([
regs::fp_reg(),
regs::stack_reg(),
regs::link_reg(),
regs::pinned_reg()
]
.contains(&rm.into()));
debug_assert!(rd.to_reg().is_virtual());
collector.reg_def(rd);
}
&Inst::MovToPReg { rd, rm } => {
debug_assert!([
regs::fp_reg(),
regs::stack_reg(),
regs::link_reg(),
regs::pinned_reg()
]
.contains(&rd.into()));
debug_assert!(rm.is_virtual());
collector.reg_use(rm);
}
&Inst::MovK { rd, rn, .. } => {
collector.reg_use(rn);
collector.reg_reuse_def(rd, 0); // `rn` == `rd`.
@@ -1551,11 +1566,16 @@ impl Inst {
let rm = pretty_print_ireg(rm, size, allocs);
format!("mov {}, {}", rd, rm)
}
&Inst::MovPReg { rd, rm } => {
&Inst::MovFromPReg { rd, rm } => {
let rd = pretty_print_ireg(rd.to_reg(), OperandSize::Size64, allocs);
let rm = show_ireg_sized(rm.into(), OperandSize::Size64);
format!("mov {}, {}", rd, rm)
}
&Inst::MovToPReg { rd, rm } => {
let rd = show_ireg_sized(rd.into(), OperandSize::Size64);
let rm = pretty_print_ireg(rm, OperandSize::Size64, allocs);
format!("mov {}, {}", rd, rm)
}
&Inst::MovWide {
op,
rd,

View File

@@ -93,6 +93,11 @@ pub fn link_reg() -> Reg {
xreg(30)
}
/// Get a reference to the pinned register (x21).
pub fn pinned_reg() -> Reg {
xreg(PINNED_REG)
}
/// Get a writable reference to the link register.
pub fn writable_link_reg() -> Writable<Reg> {
Writable::from_reg(link_reg())

View File

@@ -2189,7 +2189,7 @@
;;; Rules for `{get,set}_pinned_reg` ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(rule (lower (get_pinned_reg))
(pinned_reg))
(mov_from_preg (preg_pinned)))
(rule (lower (set_pinned_reg val))
(side_effect (write_pinned_reg val)))

View File

@@ -794,6 +794,6 @@ impl LowerBackend for AArch64Backend {
}
fn maybe_pinned_reg(&self) -> Option<Reg> {
Some(xreg(PINNED_REG))
Some(regs::pinned_reg())
}
}

View File

@@ -559,6 +559,10 @@ impl Context for IsleContext<'_, '_, MInst, Flags, IsaFlags, 6> {
super::regs::link_reg().to_real_reg().unwrap().into()
}
fn preg_pinned(&mut self) -> PReg {
super::regs::pinned_reg().to_real_reg().unwrap().into()
}
fn branch_target(&mut self, elements: &VecMachLabel, idx: u8) -> BranchTarget {
BranchTarget::Label(elements[idx as usize])
}
@@ -718,8 +722,4 @@ impl Context for IsleContext<'_, '_, MInst, Flags, IsaFlags, 6> {
);
}
}
fn writable_pinned_reg(&mut self) -> WritableReg {
super::regs::writable_xreg(super::regs::PINNED_REG)
}
}