From 6df56e6aa60e20dbb21c7449a47fe711b668f82d Mon Sep 17 00:00:00 2001 From: Andrew Brown Date: Mon, 6 Jun 2022 13:20:33 -0700 Subject: [PATCH] x64: port `atomic_cas` to ISLE (#4223) --- cranelift/codegen/src/isa/x64/inst.isle | 10 ++++++++ cranelift/codegen/src/isa/x64/lower.isle | 6 +++++ cranelift/codegen/src/isa/x64/lower.rs | 27 +-------------------- cranelift/codegen/src/isa/x64/lower/isle.rs | 6 +++++ 4 files changed, 23 insertions(+), 26 deletions(-) diff --git a/cranelift/codegen/src/isa/x64/inst.isle b/cranelift/codegen/src/isa/x64/inst.isle index cab888bc26..8a403c5244 100644 --- a/cranelift/codegen/src/isa/x64/inst.isle +++ b/cranelift/codegen/src/isa/x64/inst.isle @@ -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) diff --git a/cranelift/codegen/src/isa/x64/lower.isle b/cranelift/codegen/src/isa/x64/lower.isle index 16e5689ec0..13419cade9 100644 --- a/cranelift/codegen/src/isa/x64/lower.isle +++ b/cranelift/codegen/src/isa/x64/lower.isle @@ -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)))) diff --git a/cranelift/codegen/src/isa/x64/lower.rs b/cranelift/codegen/src/isa/x64/lower.rs index 594ffc94f0..0b049942d9 100644 --- a/cranelift/codegen/src/isa/x64/lower.rs +++ b/cranelift/codegen/src/isa/x64/lower.rs @@ -2205,32 +2205,7 @@ fn lower_insn_to_regs>( } 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 => { diff --git a/cranelift/codegen/src/isa/x64/lower/isle.rs b/cranelift/codegen/src/isa/x64/lower/isle.rs index 2c428ec292..6de416b3b3 100644 --- a/cranelift/codegen/src/isa/x64/lower/isle.rs +++ b/cranelift/codegen/src/isa/x64/lower/isle.rs @@ -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