Skip to content

Commit faea882

Browse files
committed
AArch64: port misc ops to ISLE.
- get_pinned_reg / set_pinned_reg - bitcast - stack_addr - extractlane - insertlane - vhigh_bits - iadd_ifcout - fcvt_low_from_sint
1 parent ca6d648 commit faea882

9 files changed

Lines changed: 340 additions & 463 deletions

File tree

cranelift/codegen/src/isa/aarch64/inst.isle

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -952,11 +952,19 @@
952952

953953
;; Helper for calculating the `ScalarSize` corresponding to a type
954954
(decl scalar_size (Type) ScalarSize)
955+
955956
(rule (scalar_size $I8) (ScalarSize.Size8))
956957
(rule (scalar_size $I16) (ScalarSize.Size16))
957958
(rule (scalar_size $I32) (ScalarSize.Size32))
958959
(rule (scalar_size $I64) (ScalarSize.Size64))
959960
(rule (scalar_size $I128) (ScalarSize.Size128))
961+
962+
(rule (scalar_size $B8) (ScalarSize.Size8))
963+
(rule (scalar_size $B16) (ScalarSize.Size16))
964+
(rule (scalar_size $B32) (ScalarSize.Size32))
965+
(rule (scalar_size $B64) (ScalarSize.Size64))
966+
(rule (scalar_size $B128) (ScalarSize.Size128))
967+
960968
(rule (scalar_size $F32) (ScalarSize.Size32))
961969
(rule (scalar_size $F64) (ScalarSize.Size64))
962970

@@ -1452,6 +1460,9 @@
14521460
(decl pure lshl_from_imm64 (Type Imm64) ShiftOpAndAmt)
14531461
(extern constructor lshl_from_imm64 lshl_from_imm64)
14541462

1463+
(decl pure lshl_from_u64 (Type u64) ShiftOpAndAmt)
1464+
(extern constructor lshl_from_u64 lshl_from_u64)
1465+
14551466
(decl integral_ty (Type) Type)
14561467
(extern extractor integral_ty integral_ty)
14571468

@@ -1704,6 +1715,14 @@
17041715
(MInst.AluRRR (ALUOp.AddS) (operand_size ty) dst src1 src2)
17051716
dst)))
17061717

1718+
;; Helper for emitting `adds` instructions, setting flags in ambient
1719+
;; state. Used only for `iadd_ifcout`.
1720+
(decl add_with_flags (Type Reg Reg) Reg)
1721+
(rule (add_with_flags ty src1 src2)
1722+
(let ((dst WritableReg (temp_writable_reg $I64))
1723+
(_ Unit (emit (MInst.AluRRR (ALUOp.AddS) (operand_size ty) dst src1 src2))))
1724+
dst))
1725+
17071726
;; Helper for emitting `adc` instructions.
17081727
(decl adc_paired (Type Reg Reg) ConsumesFlags)
17091728
(rule (adc_paired ty src1 src2)
@@ -1927,6 +1946,13 @@
19271946
(_ Unit (emit (MInst.VecExtend op dst src high_half size))))
19281947
dst))
19291948

1949+
;; Helper for emitting `MInst.VecExtract` instructions.
1950+
(decl vec_extract (Reg Reg u8) Reg)
1951+
(rule (vec_extract src1 src2 idx)
1952+
(let ((dst WritableReg (temp_writable_reg $I8X16))
1953+
(_ Unit (emit (MInst.VecExtract dst src1 src2 idx))))
1954+
dst))
1955+
19301956
;; Helper for emitting `MInst.LoadAcquire` instructions.
19311957
(decl load_acquire (Type Reg) Reg)
19321958
(rule (load_acquire ty addr)
@@ -2118,6 +2144,10 @@
21182144
(decl addp (Reg Reg VectorSize) Reg)
21192145
(rule (addp x y size) (vec_rrr (VecALUOp.Addp) x y size))
21202146

2147+
;; Helper for generating `zip1` instructions.
2148+
(decl zip1 (Reg Reg VectorSize) Reg)
2149+
(rule (zip1 x y size) (vec_rrr (VecALUOp.Zip1) x y size))
2150+
21212151
;; Helper for generating vector `abs` instructions.
21222152
(decl vec_abs (Reg VectorSize) Reg)
21232153
(rule (vec_abs x size) (vec_misc (VecMisc2.Abs) x size))
@@ -2818,3 +2848,27 @@
28182848
(let ((dst WritableReg (temp_writable_reg $I8X16))
28192849
(_ Unit (emit (MInst.IntToFpu op dst src))))
28202850
dst))
2851+
2852+
;; Helpers for pinned register manipulation.
2853+
2854+
(decl gen_move (Type WritableReg Reg) MInst)
2855+
(extern constructor gen_move gen_move)
2856+
2857+
(decl writable_pinned_reg () WritableReg)
2858+
(extern constructor writable_pinned_reg writable_pinned_reg)
2859+
2860+
(decl pinned_reg () Reg)
2861+
(rule (pinned_reg) (writable_pinned_reg))
2862+
2863+
(decl write_pinned_reg (Reg) SideEffectNoResult)
2864+
(rule (write_pinned_reg val)
2865+
(let ((dst WritableReg (writable_pinned_reg)))
2866+
(SideEffectNoResult.Inst (gen_move $I64 dst val))))
2867+
2868+
;; Helpers for stackslot effective address generation.
2869+
2870+
(decl compute_stack_addr (StackSlot Offset32) Reg)
2871+
(rule (compute_stack_addr stack_slot offset)
2872+
(let ((dst WritableReg (temp_writable_reg $I64))
2873+
(_ Unit (emit (abi_stackslot_addr dst stack_slot offset))))
2874+
dst))

cranelift/codegen/src/isa/aarch64/lower.isle

Lines changed: 209 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2016,3 +2016,212 @@
20162016

20172017
(rule (lower (get_return_address))
20182018
(aarch64_link))
2019+
2020+
;;; Rules for `{get,set}_pinned_reg` ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
2021+
2022+
(rule (lower (get_pinned_reg))
2023+
(pinned_reg))
2024+
2025+
(rule (lower (set_pinned_reg val))
2026+
(side_effect (write_pinned_reg val)))
2027+
2028+
;;; Rules for `bitcast` ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
2029+
2030+
(rule (lower (has_type $I32 (bitcast src @ (value_type $F32))))
2031+
(mov_from_vec src 0 (ScalarSize.Size32)))
2032+
2033+
(rule (lower (has_type $F32 (bitcast src @ (value_type $I32))))
2034+
(mov_to_fpu src (ScalarSize.Size32)))
2035+
2036+
(rule (lower (has_type $I64 (bitcast src @ (value_type $F64))))
2037+
(mov_from_vec src 0 (ScalarSize.Size64)))
2038+
2039+
(rule (lower (has_type $F64 (bitcast src @ (value_type $I64))))
2040+
(mov_to_fpu src (ScalarSize.Size64)))
2041+
2042+
;;; Rules for `raw_bitcast` ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
2043+
2044+
(rule (lower (raw_bitcast val))
2045+
val)
2046+
2047+
;;; Rules for `extractlane` ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
2048+
2049+
;; extractlane with lane 0 can pass through the value unchanged; upper
2050+
;; bits are undefined when a narrower type is in a wider register.
2051+
(rule (lower (has_type (ty_scalar_float _) (extractlane val (u8_from_uimm8 0))))
2052+
val)
2053+
2054+
(rule (lower (has_type (ty_int_bool ty)
2055+
(extractlane val
2056+
(u8_from_uimm8 lane))))
2057+
(mov_from_vec val lane (scalar_size ty)))
2058+
2059+
(rule (lower (has_type (ty_scalar_float ty)
2060+
(extractlane val @ (value_type vty)
2061+
(u8_from_uimm8 lane))))
2062+
(fpu_move_from_vec val lane (vector_size vty)))
2063+
2064+
;;; Rules for `insertlane` ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
2065+
2066+
(rule (lower (insertlane vec @ (value_type vty)
2067+
val @ (value_type (ty_int_bool _))
2068+
(u8_from_uimm8 lane)))
2069+
(mov_to_vec vec val lane (vector_size vty)))
2070+
2071+
(rule (lower (insertlane vec @ (value_type vty)
2072+
val @ (value_type (ty_scalar_float _))
2073+
(u8_from_uimm8 lane)))
2074+
(mov_vec_elem vec val lane 0 (vector_size vty)))
2075+
2076+
;;; Rules for `copy` ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
2077+
2078+
(rule (lower (copy x))
2079+
x)
2080+
2081+
;;; Rules for `stack_addr` ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
2082+
2083+
(rule (lower (stack_addr stack_slot offset))
2084+
(compute_stack_addr stack_slot offset))
2085+
2086+
;;; Rules for `vhigh_bits` ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
2087+
2088+
;; All three sequences use one integer temporary and two vector
2089+
;; temporaries. The shift is done early so as to give the register
2090+
;; allocator the possibility of using the same reg for `tmp_v1` and
2091+
;; `src_v` in the case that this is the last use of `src_v`. See
2092+
;; https://github.com/WebAssembly/simd/pull/201 for the background and
2093+
;; derivation of these sequences. Alternative sequences are discussed
2094+
;; in https://github.com/bytecodealliance/wasmtime/issues/2296,
2095+
;; although they are not used here.
2096+
2097+
(rule (lower (vhigh_bits vec @ (value_type $I8X16)))
2098+
(let (
2099+
;; Replicate the MSB of each of the 16 byte lanes across
2100+
;; the whole lane (sshr is an arithmetic right shift).
2101+
(shifted Reg (vec_shift_imm (VecShiftImmOp.Sshr) 7 vec (VectorSize.Size8x16)))
2102+
;; Bitwise-and with a mask
2103+
;; `0x80402010_08040201_80402010_08040201` to get the bit
2104+
;; in the proper location for each group of 8 lanes.
2105+
(anded Reg (and_vec shifted (constant_f128 0x80402010_08040201_80402010_08040201) (VectorSize.Size8x16)))
2106+
;; Produce a version of `anded` with upper 8 lanes and
2107+
;; lower 8 lanes swapped.
2108+
(anded_swapped Reg (vec_extract anded anded 8))
2109+
;; Zip together the two; with the above this produces the lane permutation:
2110+
;; 15 7 14 6 13 5 12 4 11 3 10 2 9 1 8 0
2111+
(zipped Reg (zip1 anded anded_swapped (VectorSize.Size8x16)))
2112+
;; Add 16-bit lanes together ("add across vector"), so we
2113+
;; get, in the low 16 bits, 15+14+...+8 in the high byte
2114+
;; and 7+6+...+0 in the low byte. This effectively puts
2115+
;; the 16 MSBs together, giving our results.
2116+
;;
2117+
;; N.B.: `Size16x8` is not a typo!
2118+
(result Reg (addv zipped (VectorSize.Size16x8))))
2119+
(mov_from_vec result 0 (ScalarSize.Size16))))
2120+
2121+
(rule (lower (vhigh_bits vec @ (value_type $I16X8)))
2122+
(let (
2123+
;; Replicate the MSB of each of the 8 16-bit lanes across
2124+
;; the whole lane (sshr is an arithmetic right shift).
2125+
(shifted Reg (vec_shift_imm (VecShiftImmOp.Sshr) 15 vec (VectorSize.Size16x8)))
2126+
;; Bitwise-and with a mask
2127+
;; `0x0080_0040_0020_0010_0008_0004_0002_0001` to get the
2128+
;; bit in the proper location for each group of 4 lanes.
2129+
(anded Reg (and_vec shifted (constant_f128 0x0080_0040_0020_0010_0008_0004_0002_0001) (VectorSize.Size16x8)))
2130+
;; Add lanes together to get the 8 MSBs in the low byte.
2131+
(result Reg (addv anded (VectorSize.Size16x8))))
2132+
(mov_from_vec result 0 (ScalarSize.Size16))))
2133+
2134+
(rule (lower (vhigh_bits vec @ (value_type $I32X4)))
2135+
(let (
2136+
;; Replicate the MSB of each of the 4 32-bit lanes across
2137+
;; the whole lane (sshr is an arithmetic right shift).
2138+
(shifted Reg (vec_shift_imm (VecShiftImmOp.Sshr) 31 vec (VectorSize.Size32x4)))
2139+
;; Bitwise-and with a mask
2140+
;; `0x00000008_00000004_00000002_00000001` to get the bit
2141+
;; in the proper location for each group of 4 lanes.
2142+
(anded Reg (and_vec shifted (constant_f128 0x00000008_00000004_00000002_00000001) (VectorSize.Size32x4)))
2143+
;; Add lanes together to get the 4 MSBs in the low byte.
2144+
(result Reg (addv anded (VectorSize.Size32x4))))
2145+
(mov_from_vec result 0 (ScalarSize.Size32))))
2146+
2147+
(rule (lower (vhigh_bits vec @ (value_type $I64X2)))
2148+
(let (
2149+
;; Grab the MSB out of each of the lanes, right-shift to
2150+
;; LSB, and add with a left-shift of upper lane's MSB back
2151+
;; to bit 1. the whole lane (sshr is an arithmetic right
2152+
;; shift).
2153+
(upper_msb Reg (mov_from_vec vec 1 (ScalarSize.Size64)))
2154+
(lower_msb Reg (mov_from_vec vec 0 (ScalarSize.Size64)))
2155+
(upper_msb Reg (lsr_imm $I64 upper_msb (imm_shift_from_u8 63)))
2156+
(lower_msb Reg (lsr_imm $I64 lower_msb (imm_shift_from_u8 63))))
2157+
(add_shift $I64 lower_msb upper_msb (lshl_from_u64 $I64 1))))
2158+
2159+
;;; Rules for `iadd_ifcout` ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
2160+
2161+
;; This is a two-output instruction that is needed for the
2162+
;; legalizer's explicit heap-check sequence, among possible other
2163+
;; uses. Its second output is a flags output only ever meant to
2164+
;; check for overflow using the
2165+
;; `backend.unsigned_add_overflow_condition()` condition.
2166+
;;
2167+
;; Note that the CLIF validation will ensure that no flag-setting
2168+
;; operation comes between this IaddIfcout and its use (e.g., a
2169+
;; Trapif). Thus, we can rely on implicit communication through the
2170+
;; processor flags rather than explicitly generating flags into a
2171+
;; register. We simply use the variant of the add instruction that
2172+
;; sets flags (`adds`) here.
2173+
;;
2174+
;; Note that the second output (the flags) need not be generated,
2175+
;; because flags are never materialized into a register; the only
2176+
;; instructions that can use a value of type `iflags` or `fflags`
2177+
;; will look directly for the flags-producing instruction (which can
2178+
;; always be found, by construction) and merge it.
2179+
;;
2180+
;; Now handle the iadd as above, except use an AddS opcode that sets
2181+
;; flags.
2182+
2183+
(rule (lower (has_type (ty_int ty)
2184+
(iadd_ifcout a b)))
2185+
(output_pair
2186+
(add_with_flags ty a b)
2187+
(invalid_reg)))
2188+
2189+
;;; Rules for `tls_value` ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
2190+
2191+
;; TODO.
2192+
2193+
;;; Rules for `fcvt_low_from_sint` ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
2194+
2195+
(rule (lower (has_type $F64X2 (fcvt_low_from_sint val)))
2196+
(let ((extended Reg (vec_extend (VecExtendOp.Sxtl) val $false (ScalarSize.Size64)))
2197+
(converted Reg (vec_misc (VecMisc2.Scvtf) extended (VectorSize.Size64x2))))
2198+
converted))
2199+
2200+
;;; Rules for `fvpromote_low` ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
2201+
2202+
(rule (lower (fvpromote_low val))
2203+
(vec_rr_long (VecRRLongOp.Fcvtl32) val $false))
2204+
2205+
;;; Rules for `select` ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
2206+
2207+
;; TODO: requires icmp/fcmp first.
2208+
2209+
;;; Rules for `selectif` / `selectif_spectre_guard` ;;;;;;;;;;;;;;;;;;;;;;;;;;;;
2210+
2211+
;; TODO: requires icmp/fcmp first.
2212+
2213+
;;; Rules for `trueif` / `trueff` ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
2214+
2215+
;; TODO: requires icmp/fcmp first.
2216+
2217+
;;; Rules for `brz`/`brnz`/`brif`/`brff`/`bricmp` ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
2218+
2219+
;; TODO: requires icmp/fcmp first.
2220+
2221+
;;; Rules for `jump` ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
2222+
2223+
;; TODO.
2224+
2225+
;;; Rules for `br_table` ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
2226+
2227+
;; TODO.

cranelift/codegen/src/isa/aarch64/lower/isle.rs

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ use crate::{
2525
isa::aarch64::inst::args::{ShiftOp, ShiftOpShiftImm},
2626
isa::aarch64::lower::{writable_vreg, writable_xreg, xreg},
2727
isa::unwind::UnwindInst,
28-
machinst::{ty_bits, InsnOutput, Lower, VCodeConstant, VCodeConstantData},
28+
machinst::{ty_bits, InsnOutput, Lower, MachInst, VCodeConstant, VCodeConstantData},
2929
};
3030
use regalloc2::PReg;
3131
use std::boxed::Box;
@@ -120,7 +120,11 @@ impl generated_code::Context for IsleContext<'_, '_, MInst, Flags, IsaFlags, 6>
120120
}
121121

122122
fn lshl_from_imm64(&mut self, ty: Type, n: Imm64) -> Option<ShiftOpAndAmt> {
123-
let shiftimm = ShiftOpShiftImm::maybe_from_shift(n.bits() as u64)?;
123+
self.lshl_from_u64(ty, n.bits() as u64)
124+
}
125+
126+
fn lshl_from_u64(&mut self, ty: Type, n: u64) -> Option<ShiftOpAndAmt> {
127+
let shiftimm = ShiftOpShiftImm::maybe_from_shift(n)?;
124128
let shiftee_bits = ty_bits(ty);
125129
if shiftee_bits <= std::u8::MAX as usize {
126130
let shiftimm = shiftimm.mask(shiftee_bits as u8);
@@ -714,4 +718,12 @@ impl generated_code::Context for IsleContext<'_, '_, MInst, Flags, IsaFlags, 6>
714718
);
715719
}
716720
}
721+
722+
fn writable_pinned_reg(&mut self) -> WritableReg {
723+
super::regs::writable_xreg(super::regs::PINNED_REG)
724+
}
725+
726+
fn gen_move(&mut self, ty: Type, to: WritableReg, from: Reg) -> MInst {
727+
MInst::gen_move(to, from, ty)
728+
}
717729
}

0 commit comments

Comments
 (0)