x64: port atomic_cas to ISLE (#4223)

This commit is contained in:
Andrew Brown
2022-06-06 13:20:33 -07:00
committed by GitHub
parent d8ba1ddc86
commit 6df56e6aa6
4 changed files with 23 additions and 26 deletions

View File

@@ -1058,6 +1058,11 @@
(decl encode_fcmp_imm (FcmpImm) u8)
(extern constructor encode_fcmp_imm encode_fcmp_imm)
;;;; Registers ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(decl rax () WritableGpr)
(extern constructor rax rax)
;;;; Newtypes for Different Register Classes ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(type Gpr (primitive Gpr))
@@ -2876,6 +2881,11 @@
(rule (x64_mfence)
(SideEffectNoResult.Inst (MInst.Fence (FenceKind.MFence))))
(decl x64_cmpxchg (Type Gpr Gpr SyntheticAmode) Gpr)
(rule (x64_cmpxchg ty expected replacement addr)
(let ((_ Unit (emit (MInst.LockCmpxchg ty replacement expected addr (rax)))))
(rax)))
;;;; Automatic conversions ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(convert Gpr InstOutput output_gpr)

View File

@@ -2812,3 +2812,9 @@
(side_effect (side_effect_concat
(x64_movrm ty (to_amode flags address (zero_offset)) value)
(x64_mfence))))
;; Rules for `atomic_cas` ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(rule (lower (has_type (and (fits_in_64 ty) (ty_int _))
(atomic_cas flags address expected replacement)))
(x64_cmpxchg ty expected replacement (to_amode flags address (zero_offset))))

View File

@@ -2205,32 +2205,7 @@ fn lower_insn_to_regs<C: LowerCtx<I = Inst>>(
}
Opcode::AtomicCas => {
// This is very similar to, but not identical to, the `AtomicRmw` case. As with
// `AtomicRmw`, there's no need to zero-extend narrow values here.
let dst = get_output_reg(ctx, outputs[0]).only_reg().unwrap();
let addr = lower_to_amode(ctx, inputs[0], 0);
let expected = put_input_in_reg(ctx, inputs[1]);
let replacement = put_input_in_reg(ctx, inputs[2]);
let ty_access = ty.unwrap();
assert!(is_valid_atomic_transaction_ty(ty_access));
// Move the expected value into %rax. Because there's only one fixed register on
// the input side, we don't have to use `ensure_in_vreg`, as is necessary in the
// `AtomicRmw` case.
ctx.emit(Inst::gen_move(
Writable::from_reg(regs::rax()),
expected,
types::I64,
));
ctx.emit(Inst::LockCmpxchg {
ty: ty_access,
mem: addr.into(),
replacement,
expected: regs::rax(),
dst_old: Writable::from_reg(regs::rax()),
});
// And finally, copy the old value at the location to its destination reg.
ctx.emit(Inst::gen_move(dst, regs::rax(), types::I64));
implemented_in_isle(ctx);
}
Opcode::AtomicLoad => {

View File

@@ -547,6 +547,12 @@ where
fn zero_offset(&mut self) -> Offset32 {
Offset32::new(0)
}
#[inline]
fn rax(&mut self) -> WritableGpr {
let gpr = Gpr::new(regs::rax()).unwrap();
WritableGpr::from_reg(gpr)
}
}
// Since x64 doesn't have 8x16 shifts and we must use a 16x8 shift instead, we