Skip to content

Commit

Permalink
Cranelift: use more iconst_[su] in opts, notably enabling some i128…
Browse files Browse the repository at this point in the history
… patterns (#7693)

* Cranelift: use more `iconst_[su]` in opts, notably re-enabling some i128 cases

`iconst_u` and `iconst_s` support `$I128`, so we can now enable these even though they had to be excluded before to avoid generating `iconst.i128` that doesn't exist.

* Update for PR feedback
  • Loading branch information
scottmcm authored Dec 18, 2023
1 parent 42456a2 commit 36b1091
Show file tree
Hide file tree
Showing 8 changed files with 214 additions and 83 deletions.
2 changes: 1 addition & 1 deletion cranelift/codegen/src/opts/arithmetic.isle
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@
(subsume inner))

;; x-x == 0.
(rule (simplify (isub (fits_in_64 (ty_int ty)) x x)) (subsume (iconst_u ty 0)))
(rule (simplify (isub (ty_int ty) x x)) (subsume (iconst_u ty 0)))

;; x*1 == x.
(rule (simplify (imul ty
Expand Down
25 changes: 12 additions & 13 deletions cranelift/codegen/src/opts/bitops.isle
Original file line number Diff line number Diff line change
Expand Up @@ -15,16 +15,15 @@
(subsume x))

;; x ^ x == 0.
(rule (simplify (bxor (fits_in_64 (ty_int ty)) x x))
(rule (simplify (bxor (ty_int ty) x x))
(subsume (iconst_u ty 0)))

;; x ^ not(x) == not(x) ^ x == x | not(x) == not(x) | x == -1.
;; This identity also holds for non-integer types, vectors, and wider types.
;; But `iconst` is only valid for integers up to 64 bits wide.
(rule (simplify (bxor (fits_in_64 (ty_int ty)) x (bnot ty x))) (subsume (iconst ty (imm64 (ty_mask ty)))))
(rule (simplify (bxor (fits_in_64 (ty_int ty)) (bnot ty x) x)) (subsume (iconst ty (imm64 (ty_mask ty)))))
(rule (simplify (bor (fits_in_64 (ty_int ty)) x (bnot ty x))) (subsume (iconst ty (imm64 (ty_mask ty)))))
(rule (simplify (bor (fits_in_64 (ty_int ty)) (bnot ty x) x)) (subsume (iconst ty (imm64 (ty_mask ty)))))
(rule (simplify (bxor (ty_int ty) x (bnot ty x))) (subsume (iconst_s ty -1)))
(rule (simplify (bxor (ty_int ty) (bnot ty x) x)) (subsume (iconst_s ty -1)))
(rule (simplify (bor (ty_int ty) x (bnot ty x))) (subsume (iconst_s ty -1)))
(rule (simplify (bor (ty_int ty) (bnot ty x) x)) (subsume (iconst_s ty -1)))

;; x & x == x & -1 == x.
(rule (simplify (band ty x x)) (subsume x))
Expand All @@ -33,8 +32,8 @@

;; x & 0 == x & not(x) == not(x) & x == 0.
(rule (simplify (band ty _ zero @ (iconst_u ty 0))) (subsume zero))
(rule (simplify (band (fits_in_64 (ty_int ty)) x (bnot ty x))) (subsume (iconst_u ty 0)))
(rule (simplify (band (fits_in_64 (ty_int ty)) (bnot ty x) x)) (subsume (iconst_u ty 0)))
(rule (simplify (band (ty_int ty) x (bnot ty x))) (subsume (iconst_u ty 0)))
(rule (simplify (band (ty_int ty) (bnot ty x) x)) (subsume (iconst_u ty 0)))

;; not(not(x)) == x.
(rule (simplify (bnot ty (bnot ty x))) (subsume x))
Expand Down Expand Up @@ -69,8 +68,8 @@
;; (No need to duplicate for commutative `bor` for this constant version because
;; we move constants to the right.)
(rule (simplify (bor ty
(band ty x (iconst ty (u64_from_imm64 y)))
z @ (iconst ty (u64_from_imm64 zk))))
(band ty x (iconst_u ty y))
z @ (iconst_u ty zk)))
(if-let $true (u64_eq (u64_and (ty_mask ty) zk)
(u64_and (ty_mask ty) (u64_not y))))
(bor ty x z))
Expand All @@ -83,11 +82,11 @@
;;
;; (x | -x) sets the sign bit to 1 if x is nonzero, and 0 if x is zero. sshr propagates
;; the sign bit to the rest of the value.
(rule (simplify (sshr ty (bor ty x (ineg ty x)) (iconst ty (u64_from_imm64 shift_amt))))
(rule (simplify (sshr ty (bor ty x (ineg ty x)) (iconst_u ty shift_amt)))
(if-let $true (u64_eq shift_amt (ty_shift_mask ty)))
(bmask ty x))

(rule (simplify (sshr ty (bor ty (ineg ty x) x) (iconst ty (u64_from_imm64 shift_amt))))
(rule (simplify (sshr ty (bor ty (ineg ty x) x) (iconst_u ty shift_amt)))
(if-let $true (u64_eq shift_amt (ty_shift_mask ty)))
(bmask ty x))

Expand All @@ -104,7 +103,7 @@
(rule (truthy (popcnt _ x)) x)
(rule (truthy (rotl _ x _)) x)
(rule (truthy (rotr _ x _)) x)
(rule (truthy (select _ x (iconst _ (u64_from_imm64 (u64_nonzero _))) (iconst _ (u64_from_imm64 0)))) x)
(rule (truthy (select _ x (iconst_u _ (u64_nonzero _)) (iconst_u _ 0))) x)
;; (ne ty (iconst 0) v) is also canonicalized into this form via another rule
(rule (truthy (ne _ x (iconst_u _ 0))) x)

Expand Down
22 changes: 11 additions & 11 deletions cranelift/codegen/src/opts/cprop.isle
Original file line number Diff line number Diff line change
Expand Up @@ -73,11 +73,12 @@
(rule (simplify (ireduce narrow (iconst (fits_in_64 _) (u64_from_imm64 imm))))
(subsume (iconst narrow (imm64_masked narrow imm))))

(rule (simplify (uextend (fits_in_64 wide) (iconst narrow imm)))
(subsume (iconst wide (imm64 (u64_uextend_imm64 narrow imm)))))

(rule (simplify (sextend (fits_in_64 wide) (iconst narrow imm)))
(subsume (iconst wide (imm64_masked wide (i64_as_u64 (i64_sextend_imm64 narrow imm))))))
;; iconst_[su] support $I128, but do so by extending, so restricting to
;; 64-bit or smaller keeps it from just remaking essentially the same thing.
(rule (simplify (uextend (fits_in_64 wide) (iconst_u narrow k)))
(subsume (iconst_u wide k)))
(rule (simplify (sextend (fits_in_64 wide) (iconst_s narrow k)))
(subsume (iconst_s wide k)))

(rule (simplify
(icmp result_ty
Expand Down Expand Up @@ -167,10 +168,10 @@
(bxor ty x (bxor ty k1 k2)))

(rule (simplify
(select ty (iconst _ (u64_from_imm64 (u64_nonzero _))) x y))
(select ty (iconst_u _ (u64_nonzero _)) x y))
x)
(rule (simplify
(select ty (iconst _ (u64_from_imm64 0)) x y))
(select ty (iconst_u _ 0) x y))
y)

;; Replace subtraction by a "negative" constant with addition.
Expand All @@ -179,10 +180,9 @@
;; TODO: it would be nice to do this for `x + (-1) == x - 1` as well, but
;; that needs work in lowering first to avoid regressing addressing modes.

(rule (simplify (isub ty x (iconst ty k1)))
(if-let k2 (i64_sextend_imm64 ty k1))
(if-let $true (u64_lt (i64_as_u64 (i64_neg k2)) (i64_as_u64 k2)))
(iadd ty x (iconst ty (imm64_masked ty (i64_as_u64 (i64_neg k2))))))
(rule (simplify (isub ty x (iconst_s ty k)))
(if-let $true (u64_lt (i64_as_u64 (i64_neg k)) (i64_as_u64 k)))
(iadd ty x (iconst ty (imm64_masked ty (i64_as_u64 (i64_neg k))))))

;; TODO: fadd, fsub, fmul, fdiv, fneg, fabs

Expand Down
13 changes: 11 additions & 2 deletions cranelift/codegen/src/opts/extends.isle
Original file line number Diff line number Diff line change
Expand Up @@ -14,13 +14,13 @@

;; Masking out any of the top bits of the result of `uextend` is a no-op. (This
;; is like a cheap version of known-bits analysis.)
(rule (simplify (band wide x @ (uextend _ (value_type narrow)) (iconst _ (u64_from_imm64 mask))))
(rule (simplify (band wide x @ (uextend _ (value_type narrow)) (iconst_u _ mask)))
; Check that `narrow_mask` has a subset of the bits that `mask` does.
(if-let $true (let ((narrow_mask u64 (ty_mask narrow))) (u64_eq narrow_mask (u64_and mask narrow_mask))))
x)

;; Masking out the sign-extended bits of an `sextend` turns it into a `uextend`.
(rule (simplify (band wide (sextend _ x @ (value_type narrow)) (iconst _ (u64_from_imm64 mask))))
(rule (simplify (band wide (sextend _ x @ (value_type narrow)) (iconst_u _ mask)))
(if-let $true (u64_eq mask (ty_mask narrow)))
(uextend wide x))

Expand Down Expand Up @@ -49,3 +49,12 @@
;; actually doing the extend in the first place.
(rule (simplify (ireduce ty (sextend _ x @ (value_type ty)))) x)
(rule (simplify (ireduce ty (uextend _ x @ (value_type ty)))) x)

;; `band`, `bor`, and `bxor` can't affect any bits that aren't set in the one of
;; the inputs, so they can be pushed down inside `uextend`s
(rule (simplify (band bigty (uextend _ x@(value_type smallty)) (uextend _ y@(value_type smallty))))
(uextend bigty (band smallty x y)))
(rule (simplify (bor bigty (uextend _ x@(value_type smallty)) (uextend _ y@(value_type smallty))))
(uextend bigty (bor smallty x y)))
(rule (simplify (bxor bigty (uextend _ x@(value_type smallty)) (uextend _ y@(value_type smallty))))
(uextend bigty (bxor smallty x y)))
44 changes: 22 additions & 22 deletions cranelift/codegen/src/opts/icmp.isle
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,16 @@

;; `x == x` is always true for integers; `x != x` is false. Strict
;; inequalities are false, and loose inequalities are true.
(rule (simplify (eq (fits_in_64 (ty_int ty)) x x)) (iconst_u ty 1))
(rule (simplify (ne (fits_in_64 (ty_int ty)) x x)) (iconst_u ty 0))
(rule (simplify (ugt (fits_in_64 (ty_int ty)) x x)) (iconst_u ty 0))
(rule (simplify (uge (fits_in_64 (ty_int ty)) x x)) (iconst_u ty 1))
(rule (simplify (sgt (fits_in_64 (ty_int ty)) x x)) (iconst_u ty 0))
(rule (simplify (sge (fits_in_64 (ty_int ty)) x x)) (iconst_u ty 1))
(rule (simplify (ult (fits_in_64 (ty_int ty)) x x)) (iconst_u ty 0))
(rule (simplify (ule (fits_in_64 (ty_int ty)) x x)) (iconst_u ty 1))
(rule (simplify (slt (fits_in_64 (ty_int ty)) x x)) (iconst_u ty 0))
(rule (simplify (sle (fits_in_64 (ty_int ty)) x x)) (iconst_u ty 1))
(rule (simplify (eq (ty_int ty) x x)) (iconst_u ty 1))
(rule (simplify (ne (ty_int ty) x x)) (iconst_u ty 0))
(rule (simplify (ugt (ty_int ty) x x)) (iconst_u ty 0))
(rule (simplify (uge (ty_int ty) x x)) (iconst_u ty 1))
(rule (simplify (sgt (ty_int ty) x x)) (iconst_u ty 0))
(rule (simplify (sge (ty_int ty) x x)) (iconst_u ty 1))
(rule (simplify (ult (ty_int ty) x x)) (iconst_u ty 0))
(rule (simplify (ule (ty_int ty) x x)) (iconst_u ty 1))
(rule (simplify (slt (ty_int ty) x x)) (iconst_u ty 0))
(rule (simplify (sle (ty_int ty) x x)) (iconst_u ty 1))

;; Optimize icmp-of-icmp.
(rule (simplify (ne ty
Expand Down Expand Up @@ -65,62 +65,62 @@
(subsume (iconst_u bty 1)))

;; ult(x, UMAX) == ne(x, UMAX).
(rule (simplify (ult (fits_in_64 (ty_int bty)) x umax @ (iconst cty (u64_from_imm64 y))))
(rule (simplify (ult (fits_in_64 (ty_int bty)) x umax @ (iconst_u cty y)))
(if-let $true (u64_eq y (ty_umax cty)))
(ne bty x umax))

;; ule(x, UMAX) == true.
(rule (simplify (ule (fits_in_64 (ty_int bty)) x umax @ (iconst cty (u64_from_imm64 y))))
(rule (simplify (ule (fits_in_64 (ty_int bty)) x umax @ (iconst_u cty y)))
(if-let $true (u64_eq y (ty_umax cty)))
(subsume (iconst_u bty 1)))

;; ugt(x, UMAX) == false.
(rule (simplify (ugt (fits_in_64 (ty_int bty)) x umax @ (iconst cty (u64_from_imm64 y))))
(rule (simplify (ugt (fits_in_64 (ty_int bty)) x umax @ (iconst_u cty y)))
(if-let $true (u64_eq y (ty_umax cty)))
(subsume (iconst_u bty 0)))

;; uge(x, UMAX) == eq(x, UMAX).
(rule (simplify (uge (fits_in_64 (ty_int bty)) x umax @ (iconst cty (u64_from_imm64 y))))
(rule (simplify (uge (fits_in_64 (ty_int bty)) x umax @ (iconst_u cty y)))
(if-let $true (u64_eq y (ty_umax cty)))
(eq bty x umax))

;; slt(x, SMIN) == false.
(rule (simplify (slt (fits_in_64 (ty_int bty)) x smin @ (iconst cty (u64_from_imm64 y))))
(rule (simplify (slt (fits_in_64 (ty_int bty)) x smin @ (iconst_u cty y)))
(if-let $true (u64_eq y (ty_smin cty)))
(subsume (iconst_u bty 0)))

;; sle(x, SMIN) == eq(x, SMIN).
(rule (simplify (sle (fits_in_64 (ty_int bty)) x smin @ (iconst cty (u64_from_imm64 y))))
(rule (simplify (sle (fits_in_64 (ty_int bty)) x smin @ (iconst_u cty y)))
(if-let $true (u64_eq y (ty_smin cty)))
(eq bty x smin))

;; sgt(x, SMIN) == ne(x, SMIN).
(rule (simplify (sgt (fits_in_64 (ty_int bty)) x smin @ (iconst cty (u64_from_imm64 y))))
(rule (simplify (sgt (fits_in_64 (ty_int bty)) x smin @ (iconst_u cty y)))
(if-let $true (u64_eq y (ty_smin cty)))
(ne bty x smin))

;; sge(x, SMIN) == true.
(rule (simplify (sge (fits_in_64 (ty_int bty)) x smin @ (iconst cty (u64_from_imm64 y))))
(rule (simplify (sge (fits_in_64 (ty_int bty)) x smin @ (iconst_u cty y)))
(if-let $true (u64_eq y (ty_smin cty)))
(subsume (iconst_u bty 1)))

;; slt(x, SMAX) == ne(x, SMAX).
(rule (simplify (slt (fits_in_64 (ty_int bty)) x smax @ (iconst cty (u64_from_imm64 y))))
(rule (simplify (slt (fits_in_64 (ty_int bty)) x smax @ (iconst_u cty y)))
(if-let $true (u64_eq y (ty_smax cty)))
(ne bty x smax))

;; sle(x, SMAX) == true.
(rule (simplify (sle (fits_in_64 (ty_int bty)) x smax @ (iconst cty (u64_from_imm64 y))))
(rule (simplify (sle (fits_in_64 (ty_int bty)) x smax @ (iconst_u cty y)))
(if-let $true (u64_eq y (ty_smax cty)))
(subsume (iconst_u bty 1)))

;; sgt(x, SMAX) == false.
(rule (simplify (sgt (fits_in_64 (ty_int bty)) x smax @ (iconst cty (u64_from_imm64 y))))
(rule (simplify (sgt (fits_in_64 (ty_int bty)) x smax @ (iconst_u cty y)))
(if-let $true (u64_eq y (ty_smax cty)))
(subsume (iconst_u bty 0)))

;; sge(x, SMAX) == eq(x, SMAX).
(rule (simplify (sge (fits_in_64 (ty_int bty)) x smax @ (iconst cty (u64_from_imm64 y))))
(rule (simplify (sge (fits_in_64 (ty_int bty)) x smax @ (iconst_u cty y)))
(if-let $true (u64_eq y (ty_smax cty)))
(eq bty x smax))

Expand Down
57 changes: 27 additions & 30 deletions cranelift/codegen/src/opts/shifts.isle
Original file line number Diff line number Diff line change
Expand Up @@ -50,9 +50,8 @@
(rule (simplify (sshr wide
(ishl wide
(uextend wide x @ (value_type narrow))
(iconst _ shift))
(iconst _ shift)))
(if-let (u64_from_imm64 shift_u64) shift)
(iconst_u _ shift_u64))
(iconst_u _ shift_u64)))
(if-let $true (u64_eq shift_u64 (u64_sub (ty_bits_u64 wide) (ty_bits_u64 narrow))))
(sextend wide x))

Expand All @@ -62,9 +61,8 @@
(rule (simplify (sshr wide
(ishl wide
x @ (uextend wide (value_type narrow))
(iconst _ shift))
(iconst _ shift)))
(if-let (u64_from_imm64 shift_u64) shift)
(iconst_u _ shift_u64))
(iconst_u _ shift_u64)))
(if-let $true (u64_lt shift_u64 (u64_sub (ty_bits_u64 wide) (ty_bits_u64 narrow))))
x)

Expand All @@ -73,9 +71,8 @@
(rule (simplify (sshr wide
(ishl wide
x @ (sextend wide (value_type narrow))
(iconst _ shift))
(iconst _ shift)))
(if-let (u64_from_imm64 shift_u64) shift)
(iconst_u _ shift_u64))
(iconst_u _ shift_u64)))
(if-let $true (u64_le shift_u64 (u64_sub (ty_bits_u64 wide) (ty_bits_u64 narrow))))
x)

Expand All @@ -99,7 +96,7 @@
(rule (shift_amt_to_type 32) $I32)

;; ineg(ushr(x, k)) == sshr(x, k) when k == ty_bits - 1.
(rule (simplify (ineg ty (ushr ty x sconst @ (iconst ty (u64_from_imm64 shift_amt)))))
(rule (simplify (ineg ty (ushr ty x sconst @ (iconst_u ty shift_amt))))
(if-let $true (u64_eq shift_amt (ty_shift_mask ty)))
(sshr ty x sconst))

Expand Down Expand Up @@ -153,26 +150,26 @@
;; (ushr (ushr x k1) k2) == (ushr x (add k1 k2)) if shift_mask(k1) + shift_mask(k2) < ty_bits
;; (sshr (sshr x k1) k2) == (sshr x (add k1 k2)) if shift_mask(k1) + shift_mask(k2) < ty_bits
(rule (simplify (ishl ty
(ishl ty x (iconst kty (u64_from_imm64 k1)))
(iconst _ (u64_from_imm64 k2))))
(ishl ty x (iconst_u kty k1))
(iconst_u _ k2)))
(if-let shift_amt (u64_add
(u64_and k1 (ty_shift_mask ty))
(u64_and k2 (ty_shift_mask ty))))
(if-let $true (u64_lt shift_amt (ty_bits_u64 (lane_type ty))))
(ishl ty x (iconst_u kty shift_amt)))

(rule (simplify (ushr ty
(ushr ty x (iconst kty (u64_from_imm64 k1)))
(iconst _ (u64_from_imm64 k2))))
(ushr ty x (iconst_u kty k1))
(iconst_u _ k2)))
(if-let shift_amt (u64_add
(u64_and k1 (ty_shift_mask ty))
(u64_and k2 (ty_shift_mask ty))))
(if-let $true (u64_lt shift_amt (ty_bits_u64 (lane_type ty))))
(ushr ty x (iconst_u kty shift_amt)))

(rule (simplify (sshr ty
(sshr ty x (iconst kty (u64_from_imm64 k1)))
(iconst _ (u64_from_imm64 k2))))
(sshr ty x (iconst_u kty k1))
(iconst_u _ k2)))
(if-let shift_amt (u64_add
(u64_and k1 (ty_shift_mask ty))
(u64_and k2 (ty_shift_mask ty))))
Expand All @@ -185,17 +182,17 @@
;; (ishl (ishl x k1) k2) == 0 if shift_mask(k1) + shift_mask(k2) >= ty_bits
;; (ushr (ushr x k1) k2) == 0 if shift_mask(k1) + shift_mask(k2) >= ty_bits
(rule (simplify (ishl ty
(ishl ty x (iconst _ (u64_from_imm64 k1)))
(iconst _ (u64_from_imm64 k2))))
(ishl ty x (iconst_u _ k1))
(iconst_u _ k2)))
(if-let shift_amt (u64_add
(u64_and k1 (ty_shift_mask ty))
(u64_and k2 (ty_shift_mask ty))))
(if-let $true (u64_le (ty_bits_u64 ty) shift_amt))
(subsume (iconst_u ty 0)))

(rule (simplify (ushr ty
(ushr ty x (iconst _ (u64_from_imm64 k1)))
(iconst _ (u64_from_imm64 k2))))
(ushr ty x (iconst_u _ k1))
(iconst_u _ k2)))
(if-let shift_amt (u64_add
(u64_and k1 (ty_shift_mask ty))
(u64_and k2 (ty_shift_mask ty))))
Expand Down Expand Up @@ -293,18 +290,18 @@
;; (op x k) == (op x (and k (ty_shift_mask ty)))
;;
;; where `op` is one of ishl, ushr, sshr, rotl, rotr
(rule (simplify (ishl ty x (iconst kty (u64_from_imm64 k))))
(rule (simplify (ishl ty x (iconst_u kty k)))
(if-let $false (u64_eq k (u64_and k (ty_shift_mask ty))))
(ishl ty x (iconst kty (imm64 (u64_and k (ty_shift_mask ty))))))
(rule (simplify (ushr ty x (iconst kty (u64_from_imm64 k))))
(ishl ty x (iconst_u kty (u64_and k (ty_shift_mask ty)))))
(rule (simplify (ushr ty x (iconst_u kty k)))
(if-let $false (u64_eq k (u64_and k (ty_shift_mask ty))))
(ushr ty x (iconst kty (imm64 (u64_and k (ty_shift_mask ty))))))
(rule (simplify (sshr ty x (iconst kty (u64_from_imm64 k))))
(ushr ty x (iconst_u kty (u64_and k (ty_shift_mask ty)))))
(rule (simplify (sshr ty x (iconst_u kty k)))
(if-let $false (u64_eq k (u64_and k (ty_shift_mask ty))))
(sshr ty x (iconst kty (imm64 (u64_and k (ty_shift_mask ty))))))
(rule (simplify (rotr ty x (iconst kty (u64_from_imm64 k))))
(sshr ty x (iconst_u kty (u64_and k (ty_shift_mask ty)))))
(rule (simplify (rotr ty x (iconst_u kty k)))
(if-let $false (u64_eq k (u64_and k (ty_shift_mask ty))))
(rotr ty x (iconst kty (imm64 (u64_and k (ty_shift_mask ty))))))
(rule (simplify (rotl ty x (iconst kty (u64_from_imm64 k))))
(rotr ty x (iconst_u kty (u64_and k (ty_shift_mask ty)))))
(rule (simplify (rotl ty x (iconst_u kty k)))
(if-let $false (u64_eq k (u64_and k (ty_shift_mask ty))))
(rotl ty x (iconst kty (imm64 (u64_and k (ty_shift_mask ty))))))
(rotl ty x (iconst_u kty (u64_and k (ty_shift_mask ty)))))
1 change: 1 addition & 0 deletions cranelift/filetests/filetests/egraph/extends.clif
Original file line number Diff line number Diff line change
Expand Up @@ -117,3 +117,4 @@ block0(v0: i8):
; check: v4 = iconst.i8 0
; check: v5 = icmp ne v0, v4
; check: return v5

Loading

0 comments on commit 36b1091

Please sign in to comment.