Also move these optimization rules to cprop.isle; it's where all the other similar rules are. Like the other cprop rules, these can subsume any other rules. We can't do better than reducing an expression to a constant. The new i64_sextend_imm64 and u64_uextend_imm64 constructors are useful helpers to clean up other code. I applied them to `imm64_icmp` while I was here, as well as using the existing `ty_mask` helper to clean up `imm64_masked`.
474 lines
15 KiB
Common Lisp
474 lines
15 KiB
Common Lisp
;; This is a prelude of standard definitions for ISLE, the instruction-selector
|
|
;; DSL, as we use it bound to our interfaces.
|
|
;;
|
|
;; Note that all `extern` functions here are typically defined in the
|
|
;; `isle_prelude_methods` macro defined in `src/isa/isle.rs`
|
|
|
|
;;;; Primitive and External Types ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
|
|
;; `()`
|
|
(type Unit (primitive Unit))
|
|
|
|
(decl pure unit () Unit)
|
|
(extern constructor unit unit)
|
|
|
|
(type bool (primitive bool))
|
|
(extern const $true bool)
|
|
(extern const $false bool)
|
|
|
|
(type u8 (primitive u8))
|
|
(type u16 (primitive u16))
|
|
(type u32 (primitive u32))
|
|
(type u64 (primitive u64))
|
|
(type u128 (primitive u128))
|
|
(type usize (primitive usize))
|
|
|
|
(type i8 (primitive i8))
|
|
(type i16 (primitive i16))
|
|
(type i32 (primitive i32))
|
|
(type i64 (primitive i64))
|
|
(type i128 (primitive i128))
|
|
(type isize (primitive isize))
|
|
|
|
;; `cranelift-entity`-based identifiers.
|
|
(type Type (primitive Type))
|
|
(type Value (primitive Value))
|
|
(type ValueList (primitive ValueList))
|
|
(type BlockCall (primitive BlockCall))
|
|
|
|
;; ISLE representation of `&[Value]`.
|
|
(type ValueSlice (primitive ValueSlice))
|
|
|
|
;; Extract the type of a `Value`.
|
|
(decl value_type (Type) Value)
|
|
(extern extractor infallible value_type value_type)
|
|
|
|
(decl pure u32_add (u32 u32) u32)
|
|
(extern constructor u32_add u32_add)
|
|
|
|
;; Pure/fallible constructor that tries to add two `u32`s, interpreted
|
|
;; as signed values, and fails to match on overflow.
|
|
(decl pure partial s32_add_fallible (u32 u32) u32)
|
|
(extern constructor s32_add_fallible s32_add_fallible)
|
|
|
|
;; Extractor that matches a `u32` only if non-negative.
|
|
(decl u32_nonnegative (u32) u32)
|
|
(extern extractor u32_nonnegative u32_nonnegative)
|
|
|
|
;; Extractor that pulls apart an Offset32 into a u32 with the raw
|
|
;; signed-32-bit twos-complement bits.
|
|
(decl offset32 (u32) Offset32)
|
|
(extern extractor infallible offset32 offset32)
|
|
|
|
;; Pure/fallible constructor that tests if one u32 is less than or
|
|
;; equal to another.
|
|
(decl pure partial u32_lteq (u32 u32) Unit)
|
|
(extern constructor u32_lteq u32_lteq)
|
|
|
|
;; Pure/fallible constructor that tests if one u8 is less than or
|
|
;; equal to another.
|
|
(decl pure partial u8_lteq (u8 u8) Unit)
|
|
(extern constructor u8_lteq u8_lteq)
|
|
|
|
;; Pure/fallible constructor that tests if one u8 is strictly less
|
|
;; than another.
|
|
(decl pure partial u8_lt (u8 u8) Unit)
|
|
(extern constructor u8_lt u8_lt)
|
|
|
|
;; Get a signed 32-bit immediate in an u32 from an Imm64, if possible.
|
|
(decl simm32 (u32) Imm64)
|
|
(extern extractor simm32 simm32)
|
|
|
|
;; Get an unsigned 8-bit immediate in a u8 from an Imm64, if possible.
|
|
(decl uimm8 (u8) Imm64)
|
|
(extern extractor uimm8 uimm8)
|
|
|
|
(decl pure u8_and (u8 u8) u8)
|
|
(extern constructor u8_and u8_and)
|
|
|
|
;;;; Primitive Type Conversions ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
|
|
(decl pure u8_as_u32 (u8) u32)
|
|
(extern constructor u8_as_u32 u8_as_u32)
|
|
|
|
(decl pure u8_as_u64 (u8) u64)
|
|
(extern constructor u8_as_u64 u8_as_u64)
|
|
|
|
(decl pure u16_as_u64 (u16) u64)
|
|
(extern constructor u16_as_u64 u16_as_u64)
|
|
|
|
(decl pure u32_as_u64 (u32) u64)
|
|
(extern constructor u32_as_u64 u32_as_u64)
|
|
|
|
(decl pure i64_as_u64 (i64) u64)
|
|
(extern constructor i64_as_u64 i64_as_u64)
|
|
|
|
;;;; Primitive Arithmetic ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
|
|
(decl pure u64_add (u64 u64) u64)
|
|
(extern constructor u64_add u64_add)
|
|
|
|
(decl pure u64_sub (u64 u64) u64)
|
|
(extern constructor u64_sub u64_sub)
|
|
|
|
(decl pure u64_mul (u64 u64) u64)
|
|
(extern constructor u64_mul u64_mul)
|
|
|
|
(decl pure partial u64_sdiv (u64 u64) u64)
|
|
(extern constructor u64_sdiv u64_sdiv)
|
|
|
|
(decl pure partial u64_udiv (u64 u64) u64)
|
|
(extern constructor u64_udiv u64_udiv)
|
|
|
|
(decl pure u64_and (u64 u64) u64)
|
|
(extern constructor u64_and u64_and)
|
|
|
|
(decl pure u64_or (u64 u64) u64)
|
|
(extern constructor u64_or u64_or)
|
|
|
|
(decl pure u64_xor (u64 u64) u64)
|
|
(extern constructor u64_xor u64_xor)
|
|
|
|
(decl pure imm64_shl (Type Imm64 Imm64) Imm64)
|
|
(extern constructor imm64_shl imm64_shl)
|
|
|
|
(decl pure imm64_ushr (Type Imm64 Imm64) Imm64)
|
|
(extern constructor imm64_ushr imm64_ushr)
|
|
|
|
(decl pure imm64_sshr (Type Imm64 Imm64) Imm64)
|
|
(extern constructor imm64_sshr imm64_sshr)
|
|
|
|
(decl pure u64_not (u64) u64)
|
|
(extern constructor u64_not u64_not)
|
|
|
|
(decl pure u64_eq (u64 u64) bool)
|
|
(extern constructor u64_eq u64_eq)
|
|
|
|
(decl pure i64_sextend_imm64 (Type Imm64) i64)
|
|
(extern constructor i64_sextend_imm64 i64_sextend_imm64)
|
|
|
|
(decl pure u64_uextend_imm64 (Type Imm64) u64)
|
|
(extern constructor u64_uextend_imm64 u64_uextend_imm64)
|
|
|
|
(decl pure imm64_icmp (Type IntCC Imm64 Imm64) Imm64)
|
|
(extern constructor imm64_icmp imm64_icmp)
|
|
|
|
(decl u64_is_zero (bool) u64)
|
|
(extern extractor infallible u64_is_zero u64_is_zero)
|
|
|
|
(decl u64_zero () u64)
|
|
(extractor (u64_zero) (u64_is_zero $true))
|
|
|
|
(decl u64_nonzero (u64) u64)
|
|
(extractor (u64_nonzero x) (and (u64_is_zero $false) x))
|
|
|
|
(decl pure u64_is_odd (u64) bool)
|
|
(extern constructor u64_is_odd u64_is_odd)
|
|
|
|
;;;; `cranelift_codegen::ir::Type` ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
|
|
(extern const $I8 Type)
|
|
(extern const $I16 Type)
|
|
(extern const $I32 Type)
|
|
(extern const $I64 Type)
|
|
(extern const $I128 Type)
|
|
|
|
(extern const $R32 Type)
|
|
(extern const $R64 Type)
|
|
|
|
(extern const $F32 Type)
|
|
(extern const $F64 Type)
|
|
|
|
(extern const $I8X8 Type)
|
|
(extern const $I8X16 Type)
|
|
(extern const $I16X4 Type)
|
|
(extern const $I16X8 Type)
|
|
(extern const $I32X2 Type)
|
|
(extern const $I32X4 Type)
|
|
(extern const $I64X2 Type)
|
|
|
|
(extern const $F32X4 Type)
|
|
(extern const $F64X2 Type)
|
|
|
|
(extern const $I32X4XN Type)
|
|
|
|
;; Get the bit width of a given type.
|
|
(decl pure ty_bits (Type) u8)
|
|
(extern constructor ty_bits ty_bits)
|
|
|
|
;; Get the bit width of a given type.
|
|
(decl pure ty_bits_u16 (Type) u16)
|
|
(extern constructor ty_bits_u16 ty_bits_u16)
|
|
|
|
;; Get the bit width of a given type.
|
|
(decl pure ty_bits_u64 (Type) u64)
|
|
(extern constructor ty_bits_u64 ty_bits_u64)
|
|
|
|
;; Get a mask for the width of a given type.
|
|
(decl pure ty_mask (Type) u64)
|
|
(extern constructor ty_mask ty_mask)
|
|
|
|
;; Get the byte width of a given type.
|
|
(decl pure ty_bytes (Type) u16)
|
|
(extern constructor ty_bytes ty_bytes)
|
|
|
|
;; Get the type of each lane in the given type.
|
|
(decl pure lane_type (Type) Type)
|
|
(extern constructor lane_type lane_type)
|
|
|
|
;;;; `cranelift_codegen::ir::MemFlags ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
|
|
;; `MemFlags::trusted`
|
|
(decl pure mem_flags_trusted () MemFlags)
|
|
(extern constructor mem_flags_trusted mem_flags_trusted)
|
|
|
|
;;;; Helpers for Working with Flags ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
|
|
;; Reverse an IntCC flag.
|
|
(decl intcc_reverse (IntCC) IntCC)
|
|
(extern constructor intcc_reverse intcc_reverse)
|
|
|
|
;; Invert an IntCC flag.
|
|
(decl intcc_inverse (IntCC) IntCC)
|
|
(extern constructor intcc_inverse intcc_inverse)
|
|
|
|
;; Reverse an FloatCC flag.
|
|
(decl floatcc_reverse (FloatCC) FloatCC)
|
|
(extern constructor floatcc_reverse floatcc_reverse)
|
|
|
|
;; Invert an FloatCC flag.
|
|
(decl floatcc_inverse (FloatCC) FloatCC)
|
|
(extern constructor floatcc_inverse floatcc_inverse)
|
|
|
|
;; True when this FloatCC involves an unordered comparison.
|
|
(decl pure floatcc_unordered (FloatCC) bool)
|
|
(extern constructor floatcc_unordered floatcc_unordered)
|
|
|
|
;;;; Helper Clif Extractors ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
|
|
;; An extractor that only matches types that can fit in 16 bits.
|
|
(decl fits_in_16 (Type) Type)
|
|
(extern extractor fits_in_16 fits_in_16)
|
|
|
|
;; An extractor that only matches types that can fit in 32 bits.
|
|
(decl fits_in_32 (Type) Type)
|
|
(extern extractor fits_in_32 fits_in_32)
|
|
|
|
;; An extractor that only matches types that can fit in 32 bits.
|
|
(decl lane_fits_in_32 (Type) Type)
|
|
(extern extractor lane_fits_in_32 lane_fits_in_32)
|
|
|
|
;; An extractor that only matches types that can fit in 64 bits.
|
|
(decl fits_in_64 (Type) Type)
|
|
(extern extractor fits_in_64 fits_in_64)
|
|
|
|
;; An extractor that only matches types that fit in exactly 32 bits.
|
|
(decl ty_32 (Type) Type)
|
|
(extern extractor ty_32 ty_32)
|
|
|
|
;; An extractor that only matches types that fit in exactly 64 bits.
|
|
(decl ty_64 (Type) Type)
|
|
(extern extractor ty_64 ty_64)
|
|
|
|
;; A pure constructor that only matches scalar integers, and references that can
|
|
;; fit in 64 bits.
|
|
(decl pure partial ty_int_ref_scalar_64 (Type) Type)
|
|
(extern constructor ty_int_ref_scalar_64 ty_int_ref_scalar_64)
|
|
|
|
;; An extractor that matches 32- and 64-bit types only.
|
|
(decl ty_32_or_64 (Type) Type)
|
|
(extern extractor ty_32_or_64 ty_32_or_64)
|
|
|
|
;; An extractor that matches 8- and 16-bit types only.
|
|
(decl ty_8_or_16 (Type) Type)
|
|
(extern extractor ty_8_or_16 ty_8_or_16)
|
|
|
|
;; An extractor that matches int types that fit in 32 bits.
|
|
(decl int_fits_in_32 (Type) Type)
|
|
(extern extractor int_fits_in_32 int_fits_in_32)
|
|
|
|
;; An extractor that matches I64 or R64.
|
|
(decl ty_int_ref_64 (Type) Type)
|
|
(extern extractor ty_int_ref_64 ty_int_ref_64)
|
|
|
|
;; An extractor that only matches integers.
|
|
(decl ty_int (Type) Type)
|
|
(extern extractor ty_int ty_int)
|
|
|
|
;; An extractor that only matches scalar floating-point types--F32 or F64.
|
|
(decl ty_scalar_float (Type) Type)
|
|
(extern extractor ty_scalar_float ty_scalar_float)
|
|
|
|
;; An extractor that matches scalar floating-point types or vector types.
|
|
(decl ty_float_or_vec (Type) Type)
|
|
(extern extractor ty_float_or_vec ty_float_or_vec)
|
|
|
|
;; A pure constructor that only matches vector floating-point types.
|
|
(decl pure partial ty_vector_float (Type) Type)
|
|
(extern constructor ty_vector_float ty_vector_float)
|
|
|
|
;; A pure constructor that only matches vector types with lanes which
|
|
;; are not floating-point.
|
|
(decl pure partial ty_vector_not_float (Type) Type)
|
|
(extern constructor ty_vector_not_float ty_vector_not_float)
|
|
|
|
;; A pure constructor/extractor that only matches 64-bit vector types.
|
|
(decl pure partial ty_vec64 (Type) Type)
|
|
(extern constructor ty_vec64 ty_vec64_ctor)
|
|
(extern extractor ty_vec64 ty_vec64)
|
|
|
|
;; An extractor that only matches 128-bit vector types.
|
|
(decl ty_vec128 (Type) Type)
|
|
(extern extractor ty_vec128 ty_vec128)
|
|
|
|
;; An extractor that only matches dynamic vector types with a 64-bit
|
|
;; base type.
|
|
(decl ty_dyn_vec64 (Type) Type)
|
|
(extern extractor ty_dyn_vec64 ty_dyn_vec64)
|
|
|
|
;; An extractor that only matches dynamic vector types with a 128-bit
|
|
;; base type.
|
|
(decl ty_dyn_vec128 (Type) Type)
|
|
(extern extractor ty_dyn_vec128 ty_dyn_vec128)
|
|
|
|
;; An extractor that only matches 64-bit vector types with integer
|
|
;; lanes (I8X8, I16X4, I32X2)
|
|
(decl ty_vec64_int (Type) Type)
|
|
(extern extractor ty_vec64_int ty_vec64_int)
|
|
|
|
;; An extractor that only matches 128-bit vector types with integer
|
|
;; lanes (I8X16, I16X8, I32X4, I64X2).
|
|
(decl ty_vec128_int (Type) Type)
|
|
(extern extractor ty_vec128_int ty_vec128_int)
|
|
|
|
;; A pure constructor that matches everything except vectors with size 32X2.
|
|
(decl pure partial not_vec32x2 (Type) Type)
|
|
(extern constructor not_vec32x2 not_vec32x2)
|
|
|
|
;; An extractor that matches everything except I64X2
|
|
(decl not_i64x2 () Type)
|
|
(extern extractor not_i64x2 not_i64x2)
|
|
|
|
;; Extract a `u8` from an `Uimm8`.
|
|
(decl u8_from_uimm8 (u8) Uimm8)
|
|
(extern extractor infallible u8_from_uimm8 u8_from_uimm8)
|
|
|
|
;; Extract a `u64` from a `bool`.
|
|
(decl u64_from_bool (u64) bool)
|
|
(extern extractor infallible u64_from_bool u64_from_bool)
|
|
|
|
;; Extract a `u64` from an `Imm64`.
|
|
(decl u64_from_imm64 (u64) Imm64)
|
|
(extern extractor infallible u64_from_imm64 u64_from_imm64)
|
|
|
|
;; Extract a `u64` from an `Imm64` which is not zero.
|
|
(decl nonzero_u64_from_imm64 (u64) Imm64)
|
|
(extern extractor nonzero_u64_from_imm64 nonzero_u64_from_imm64)
|
|
|
|
;; If the given `Imm64` is a power-of-two, extract its log2 value.
|
|
(decl imm64_power_of_two (u64) Imm64)
|
|
(extern extractor imm64_power_of_two imm64_power_of_two)
|
|
|
|
;; Create a new Imm64.
|
|
(decl pure imm64 (u64) Imm64)
|
|
(extern constructor imm64 imm64)
|
|
|
|
;; Create a new Imm64, masked to the width of the given type.
|
|
(decl pure imm64_masked (Type u64) Imm64)
|
|
(extern constructor imm64_masked imm64_masked)
|
|
|
|
;; Extract a `u64` from an `Ieee32`.
|
|
(decl u64_from_ieee32 (u64) Ieee32)
|
|
(extern extractor infallible u64_from_ieee32 u64_from_ieee32)
|
|
|
|
;; Extract a `u64` from an `Ieee64`.
|
|
(decl u64_from_ieee64 (u64) Ieee64)
|
|
(extern extractor infallible u64_from_ieee64 u64_from_ieee64)
|
|
|
|
;; Match a multi-lane type, extracting (# bits per lane, # lanes) from the given
|
|
;; type. Will only match when there is more than one lane.
|
|
(decl multi_lane (u32 u32) Type)
|
|
(extern extractor multi_lane multi_lane)
|
|
|
|
;; Match a dynamic-lane type, extracting (# bits per lane) from the given
|
|
;; type.
|
|
(decl dynamic_lane (u32 u32) Type)
|
|
(extern extractor dynamic_lane dynamic_lane)
|
|
|
|
;; Match a dynamic-lane integer type, extracting (# bits per lane) from the given
|
|
;; type.
|
|
(decl dynamic_int_lane (u32) Type)
|
|
(extern extractor dynamic_int_lane dynamic_int_lane)
|
|
|
|
;; Match a dynamic-lane floating point type, extracting (# bits per lane)
|
|
;; from the given type.
|
|
(decl dynamic_fp_lane (u32) Type)
|
|
(extern extractor dynamic_fp_lane dynamic_fp_lane)
|
|
|
|
;; An extractor that only matches 64-bit dynamic vector types with integer
|
|
;; lanes (I8X8XN, I16X4XN, I32X2XN)
|
|
(decl ty_dyn64_int (Type) Type)
|
|
(extern extractor ty_dyn64_int ty_dyn64_int)
|
|
|
|
;; An extractor that only matches 128-bit dynamic vector types with integer
|
|
;; lanes (I8X16XN, I16X8XN, I32X4XN, I64X2XN).
|
|
(decl ty_dyn128_int (Type) Type)
|
|
(extern extractor ty_dyn128_int ty_dyn128_int)
|
|
|
|
;; Convert an `Offset32` to a primitive number.
|
|
(decl pure offset32_to_u32 (Offset32) u32)
|
|
(extern constructor offset32_to_u32 offset32_to_u32)
|
|
|
|
;; This is a direct import of `IntCC::unsigned`.
|
|
;; Get the corresponding IntCC with the signed component removed.
|
|
;; For conditions without a signed component, this is a no-op.
|
|
(decl pure intcc_unsigned (IntCC) IntCC)
|
|
(extern constructor intcc_unsigned intcc_unsigned)
|
|
|
|
;; Pure constructor that only matches signed integer cond codes.
|
|
(decl pure partial signed_cond_code (IntCC) IntCC)
|
|
(extern constructor signed_cond_code signed_cond_code)
|
|
|
|
;;;; Helpers for Working with TrapCode ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
|
|
(decl pure trap_code_division_by_zero () TrapCode)
|
|
(extern constructor trap_code_division_by_zero trap_code_division_by_zero)
|
|
|
|
(decl pure trap_code_integer_overflow () TrapCode)
|
|
(extern constructor trap_code_integer_overflow trap_code_integer_overflow)
|
|
|
|
(decl pure trap_code_bad_conversion_to_integer () TrapCode)
|
|
(extern constructor trap_code_bad_conversion_to_integer trap_code_bad_conversion_to_integer)
|
|
|
|
;;;; Helpers for tail recursion loops ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
|
|
;; A range of integers to loop through.
|
|
(type Range (primitive Range))
|
|
|
|
;; Create a new range from `start` through `end` (exclusive).
|
|
(decl pure range (usize usize) Range)
|
|
(extern constructor range range)
|
|
|
|
;; A view on the current state of the range.
|
|
(type RangeView extern
|
|
(enum
|
|
(Empty)
|
|
(NonEmpty (index usize) (rest Range))))
|
|
|
|
;; View the current state of the range.
|
|
(decl range_view (RangeView) Range)
|
|
(extern extractor infallible range_view range_view)
|
|
|
|
;; Extractor to test whether a range is empty.
|
|
(decl range_empty () Range)
|
|
(extractor (range_empty) (range_view (RangeView.Empty)))
|
|
|
|
;; Extractor to return the first value in the range, and a sub-range
|
|
;; containing the remaining values.
|
|
(decl range_unwrap (usize Range) Range)
|
|
(extractor (range_unwrap index rest) (range_view (RangeView.NonEmpty index rest)))
|
|
|
|
;;;; Automatic conversions ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
|
|
(convert Offset32 u32 offset32_to_u32)
|