cranelift: Remove booleans (#5031)

Remove the boolean types from cranelift, and the associated instructions breduce, bextend, bconst, and bint. Standardize on using 1/0 for the return value from instructions that produce scalar boolean results, and -1/0 for boolean vector elements.

Fixes #3205

Co-authored-by: Afonso Bordado <afonso360@users.noreply.github.com>
Co-authored-by: Ulrich Weigand <ulrich.weigand@de.ibm.com>
Co-authored-by: Chris Fallin <chris@cfallin.org>
This commit is contained in:
Trevor Elliott
2022-10-17 16:00:27 -07:00
committed by GitHub
parent 766ecb561e
commit 32a7593c94
242 changed files with 7695 additions and 10010 deletions

View File

@@ -16,14 +16,6 @@
(imm ty n))
;;;; Rules for `bconst` ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(rule (lower (has_type ty (bconst $false)))
(imm ty 0))
(rule (lower (has_type ty (bconst $true)))
(imm ty 1))
;;;; Rules for `f32const` ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(rule (lower (f32const (u64_from_ieee32 x)))
@@ -1163,92 +1155,10 @@
(vec_select ty y z x))
;;;; Rules for `breduce` ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;; Rules for `bmask` ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Up to 64-bit source type: Always a no-op.
(rule 1 (lower (breduce x @ (value_type (fits_in_64 _ty))))
x)
;; 128-bit source type: Extract the low half.
(rule (lower (breduce x @ (value_type (vr128_ty _ty))))
(vec_extract_lane $I64X2 x 1 (zero_reg)))
;;;; Rules for `bextend` and `bmask` ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Use a common helper to type cast bools to either bool or integer types.
(decl cast_bool (Type Value) Reg)
(rule (lower (has_type ty (bextend x)))
(cast_bool ty x))
(rule (lower (has_type ty (bmask x)))
(cast_bool ty x))
;; If the target has the same or a smaller size than the source, it's a no-op.
(rule 8 (cast_bool $B1 x @ (value_type $B1)) x)
(rule 8 (cast_bool $B1 x @ (value_type $B8)) x)
(rule 8 (cast_bool $B8 x @ (value_type $B8)) x)
(rule 8 (cast_bool $I8 x @ (value_type $B8)) x)
(rule 7 (cast_bool (fits_in_16 _ty) x @ (value_type $B16)) x)
(rule 6 (cast_bool (fits_in_32 _ty) x @ (value_type $B32)) x)
(rule 5 (cast_bool (fits_in_64 _ty) x @ (value_type $B64)) x)
(rule 4 (cast_bool (vr128_ty _ty) x @ (value_type $B128)) x)
(rule 5 (cast_bool (fits_in_64 _ty) x @ (value_type $B128))
(vec_extract_lane $I64X2 x 1 (zero_reg)))
;; Single-bit values are sign-extended via a pair of shifts.
(rule 0 (cast_bool (gpr32_ty ty) x @ (value_type $B1))
(ashr_imm $I32 (lshl_imm $I32 x 31) 31))
(rule 1 (cast_bool (gpr64_ty ty) x @ (value_type $B1))
(ashr_imm $I64 (lshl_imm $I64 x 63) 63))
(rule 4 (cast_bool (vr128_ty ty) x @ (value_type $B1))
(let ((gpr Reg (ashr_imm $I64 (lshl_imm $I64 x 63) 63)))
(mov_to_vec128 ty gpr gpr)))
;; Other values are just sign-extended normally.
(rule 0 (cast_bool (gpr32_ty _ty) x @ (value_type $B8))
(sext32_reg $I8 x))
(rule 0 (cast_bool (gpr32_ty _ty) x @ (value_type $B16))
(sext32_reg $I16 x))
(rule 1(cast_bool (gpr64_ty _ty) x @ (value_type $B8))
(sext64_reg $I8 x))
(rule 1(cast_bool (gpr64_ty _ty) x @ (value_type $B16))
(sext64_reg $I16 x))
(rule 1(cast_bool (gpr64_ty _ty) x @ (value_type $B32))
(sext64_reg $I32 x))
(rule 3 (cast_bool (vr128_ty ty) x @ (value_type (gpr32_ty src_ty)))
(let ((x_ext Reg (sext64_reg src_ty x)))
(mov_to_vec128 ty x_ext x_ext)))
(rule 2 (cast_bool (vr128_ty ty) x @ (value_type (gpr64_ty src_ty)))
(mov_to_vec128 ty x x))
;;;; Rules for `bint` ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Mask with 1 to get a 0/1 result (8- or 16-bit result types).
(rule 5 (lower (has_type (fits_in_16 ty) (bint x @ (value_type (fits_in_64 _)))))
(and_uimm16shifted ty x (uimm16shifted 1 0)))
;; Mask with 1 to get a 0/1 result (32-bit result types).
(rule 4 (lower (has_type (fits_in_32 ty) (bint x @ (value_type (fits_in_64 _)))))
(and_uimm32shifted ty x (uimm32shifted 1 0)))
;; Mask with 1 to get a 0/1 result (64-bit result types).
(rule 3 (lower (has_type (fits_in_64 ty) (bint x @ (value_type (fits_in_64 _)))))
(and_reg ty x (imm ty 1)))
;; Mask with 1 to get a 0/1 result (128-bit result types).
(rule 1 (lower (has_type (vr128_ty ty) (bint x @ (value_type (fits_in_64 _)))))
(let ((x_ext Reg (and_uimm16shifted $I8 x (uimm16shifted 1 0))))
(vec_insert_lane $I8X16 (vec_imm ty 0) x_ext 15 (zero_reg))))
;; Mask with 1 to get a 0/1 result (128-bit source types).
(rule 2 (lower (has_type (fits_in_64 ty) (bint x @ (value_type (vr128_ty _)))))
(let ((x_gpr Reg (vec_extract_lane $I8X16 x 15 (zero_reg))))
(and_uimm16shifted ty x_gpr (uimm16shifted 1 0))))
;; Mask with 1 to get a 0/1 result (128-bit source and result types).
(rule 0 (lower (has_type (vr128_ty ty) (bint x @ (value_type (vr128_ty _)))))
(vec_and ty x (vec_imm ty 1)))
(lower_bool_to_mask ty (value_nonzero x)))
;;;; Rules for `bitrev` ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
@@ -1864,7 +1774,7 @@
(rule 1 (lower (insertlane x @ (value_type ty)
y @ (value_type in_ty)
(u8_from_uimm8 idx)))
(if (ty_int_bool_ref_scalar_64 in_ty))
(if (ty_int_ref_scalar_64 in_ty))
(vec_insert_lane ty x y (be_lane_idx ty idx) (zero_reg)))
;; Insert vector lane from floating-point register.
@@ -1980,7 +1890,7 @@
;; Extract vector lane to general-purpose register.
(rule 1 (lower (has_type out_ty
(extractlane x @ (value_type ty) (u8_from_uimm8 idx))))
(if (ty_int_bool_ref_scalar_64 out_ty))
(if (ty_int_ref_scalar_64 out_ty))
(vec_extract_lane ty x (be_lane_idx ty idx) (zero_reg)))
;; Extract vector lane to floating-point register.
@@ -2037,7 +1947,7 @@
;; Load replicated value from general-purpose register.
(rule 1 (lower (has_type ty (splat x @ (value_type in_ty))))
(if (ty_int_bool_ref_scalar_64 in_ty))
(if (ty_int_ref_scalar_64 in_ty))
(vec_replicate_lane ty (vec_insert_lane_undef ty x 0 (zero_reg)) 0))
;; Load replicated value from floating-point register.
@@ -2097,7 +2007,7 @@
;; Load scalar value from general-purpose register.
(rule 1 (lower (has_type ty (scalar_to_vector
x @ (value_type in_ty))))
(if (ty_int_bool_ref_scalar_64 in_ty))
(if (ty_int_ref_scalar_64 in_ty))
(vec_insert_lane ty (vec_imm ty 0) x (be_lane_idx ty 0) (zero_reg)))
;; Load scalar value from floating-point register.
@@ -3783,14 +3693,14 @@
;;;; Rules for `is_null` and `is_invalid` ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Null references are represented by the constant value 0.
(rule (lower (has_type $B1 (is_null x @ (value_type $R64))))
(lower_bool $B1 (bool (icmps_simm16 $I64 x 0)
(rule (lower (has_type $I8 (is_null x @ (value_type $R64))))
(lower_bool $I8 (bool (icmps_simm16 $I64 x 0)
(intcc_as_cond (IntCC.Equal)))))
;; Invalid references are represented by the constant value -1.
(rule (lower (has_type $B1 (is_invalid x @ (value_type $R64))))
(lower_bool $B1 (bool (icmps_simm16 $I64 x -1)
(rule (lower (has_type $I8 (is_invalid x @ (value_type $R64))))
(lower_bool $I8 (bool (icmps_simm16 $I64 x -1)
(intcc_as_cond (IntCC.Equal)))))
@@ -3798,10 +3708,9 @@
;; Return a `ProducesBool` to capture the fact that the input value is nonzero.
;; In the common case where that input is the result of an `icmp` or `fcmp`
;; instruction (possibly via an intermediate `bint`), directly use that compare.
;; Note that it is not safe to sink memory loads here, see the `icmp` comment.
;; instruction, directly use that compare. Note that it is not safe to sink
;; memory loads here, see the `icmp` comment.
(decl value_nonzero (Value) ProducesBool)
(rule (value_nonzero (bint val)) (value_nonzero val))
(rule (value_nonzero (icmp int_cc x y)) (icmp_val $false int_cc x y))
(rule (value_nonzero (fcmp float_cc x y)) (fcmp_val float_cc x y))
(rule -1 (value_nonzero val @ (value_type (gpr32_ty ty)))