Browse Source

Cranelift: More simplification opts for `iadd`/`isub` (#7654)

pull/7658/head
scottmcm 11 months ago
committed by GitHub
parent
commit
76f71d83f2
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 23
      cranelift/codegen/src/opts/arithmetic.isle
  2. 20
      cranelift/codegen/src/opts/bitops.isle
  3. 11
      cranelift/codegen/src/opts/cprop.isle
  4. 54
      cranelift/filetests/filetests/egraph/arithmetic.clif
  5. 22
      cranelift/filetests/filetests/egraph/cprop.clif
  6. 8
      cranelift/filetests/filetests/egraph/shifts.clif

23
cranelift/codegen/src/opts/arithmetic.isle

@ -20,6 +20,17 @@
x))
(ineg ty x))
;; x + -y == -y + x == -(y - x) == x - y
(rule (simplify (iadd ty x (ineg ty y)))
(isub ty x y))
(rule (simplify (iadd ty (ineg ty y) x))
(isub ty x y))
(rule (simplify (ineg ty (isub ty y x)))
(isub ty x y))
;; x - -y == x + y
(rule (simplify (isub ty x (ineg ty y)))
(iadd ty x y))
;; ineg(ineg(x)) == x.
(rule (simplify (ineg ty (ineg ty x))) (subsume x))
@ -55,24 +66,16 @@
(if-let -1 (i64_sextend_imm64 ty c))
(ineg ty x))
;; (!x) + 1 == 1 + (!x) == !(x) - (-1) == ineg(x)
;; (!x) + 1 == ineg(x)
(rule (simplify (iadd ty (bnot ty x) (iconst ty (u64_from_imm64 1))))
(ineg ty x))
(rule (simplify (iadd ty (iconst ty (u64_from_imm64 1)) (bnot ty x)))
(ineg ty x))
(rule (simplify (isub ty (bnot ty x) (iconst ty c)))
(if-let -1 (i64_sextend_imm64 ty c))
(ineg ty x))
;; !(x - 1) == !(x + (-1)) == !((-1) + x) == ineg(x)
;; !(x - 1) == !(x + (-1)) == ineg(x)
(rule (simplify (bnot ty (isub ty x (iconst ty (u64_from_imm64 1)))))
(ineg ty x))
(rule (simplify (bnot ty (iadd ty x (iconst ty c))))
(if-let -1 (i64_sextend_imm64 ty c))
(ineg ty x))
(rule (simplify (bnot ty (iadd ty (iconst ty c) x)))
(if-let -1 (i64_sextend_imm64 ty c))
(ineg ty x))
;; x/1 == x.
(rule (simplify (sdiv ty

20
cranelift/codegen/src/opts/bitops.isle

@ -1,26 +1,18 @@
;; Rewrites for `band`, `bnot`, `bor`, `bxor`
;; x | 0 == 0 | x == x | x == x.
;; x | 0 == x | x == x.
(rule (simplify (bor ty
x
(iconst ty (u64_from_imm64 0))))
(subsume x))
(rule (simplify (bor ty
(iconst ty (u64_from_imm64 0))
x))
(subsume x))
(rule (simplify (bor ty x x))
(subsume x))
;; x ^ 0 == 0 ^ x == x.
;; x ^ 0 == x.
(rule (simplify (bxor ty
x
(iconst ty (u64_from_imm64 0))))
(subsume x))
(rule (simplify (bxor ty
(iconst ty (u64_from_imm64 0))
x))
(subsume x))
;; x ^ x == 0.
(rule (simplify (bxor (fits_in_64 (ty_int ty)) x x))
@ -34,18 +26,14 @@
(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)))))
;; x & -1 == -1 & x == x & x == x.
;; x & x == x & -1 == x.
(rule (simplify (band ty x x)) (subsume x))
(rule (simplify (band ty x (iconst ty k)))
(if-let -1 (i64_sextend_imm64 ty k))
(subsume x))
(rule (simplify (band ty (iconst ty k) x))
(if-let -1 (i64_sextend_imm64 ty k))
(subsume x))
;; x & 0 == 0 & x == x & not(x) == not(x) & x == 0.
;; x & 0 == x & not(x) == not(x) & x == 0.
(rule (simplify (band ty _ zero @ (iconst ty (u64_from_imm64 0)))) (subsume zero))
(rule (simplify (band ty zero @ (iconst ty (u64_from_imm64 0)) _)) (subsume zero))
(rule (simplify (band (fits_in_64 (ty_int ty)) x (bnot ty x))) (subsume (iconst ty (imm64 0))))
(rule (simplify (band (fits_in_64 (ty_int ty)) (bnot ty x) x)) (subsume (iconst ty (imm64 0))))

11
cranelift/codegen/src/opts/cprop.isle

@ -173,6 +173,17 @@
(select ty (iconst _ (u64_from_imm64 0)) x y))
y)
;; Replace subtraction by a "negative" constant with addition.
;; Notably, this gives `x - (-1) == x + 1`, so other patterns don't have to
;; match the subtract-negative-one version too.
;; 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))))))
;; TODO: fadd, fsub, fmul, fdiv, fneg, fabs
;; A splat of a constant can become a direct `vconst` with the appropriate bit

54
cranelift/filetests/filetests/egraph/arithmetic.clif

@ -20,6 +20,42 @@ block0(v0: i32):
; check: return v0
}
function %add_ineg(i32, i32) -> i32 {
block0(v0: i32, v1: i32):
v2 = ineg v1
v3 = iadd v0, v2
return v3
; check: v4 = isub v0, v1
; check: return v4
}
function %ineg_add(i32, i32) -> i32 {
block0(v0: i32, v1: i32):
v2 = ineg v0
v3 = iadd v2, v1
return v3
; check: v4 = isub v1, v0
; check: return v4
}
function %sub_ineg(i32, i32) -> i32 {
block0(v0: i32, v1: i32):
v2 = ineg v1
v3 = isub v0, v2
return v3
; check: v4 = iadd v0, v1
; check: return v4
}
function %sub_then_ineg(i32, i32) -> i32 {
block0(v0: i32, v1: i32):
v2 = isub v0, v1
v3 = ineg v2
return v3
; check: v4 = isub v1, v0
; check: return v4
}
function %imul_ineg_cancel(i32, i32) -> i32 {
block0(v0: i32, v1: i32):
v2 = ineg v0
@ -125,8 +161,8 @@ block0(v0: i32):
return v3
}
; check: v4 = ineg v0
; check: return v4
; check: v5 = ineg v0
; check: return v5
function %ineg_not_minus_neg_1(i32) -> i32 {
block0(v0: i32):
@ -136,8 +172,8 @@ block0(v0: i32):
return v3
}
; check: v4 = ineg v0
; check: return v4
; check: v6 = ineg v0
; check: return v6
function %ineg_not_sub_one(i32) -> i32 {
block0(v0: i32):
@ -172,7 +208,17 @@ block0(v0: i32):
; check: v6 = ineg v0
; check: return v6
function %byte_sub_smax_twice(i8) -> i8 {
block0(v0: i8):
v1 = iconst.i8 127
v2 = isub v0, v1
v3 = isub v2, v1
return v3
}
; check: v6 = iconst.i8 2
; check: v7 = iadd v0, v6 ; v6 = 2
; check: return v7
function %double_fneg(f32) -> f32 {
block0(v1: f32):

22
cranelift/filetests/filetests/egraph/cprop.clif

@ -260,3 +260,25 @@ block0:
; check: v3 = iconst.i32 0xfff6
; nextln: return v3
function %sub_u8max(i8) -> i8 {
block0(v0: i8):
v1 = iconst.i8 255
v2 = isub v0, v1
return v2
}
; check: v3 = iconst.i8 1
; nextln: v4 = iadd v0, v3 ; v3 = 1
; nextln: return v4
function %sub_u32max(i32) -> i32 {
block0(v0: i32):
v1 = iconst.i32 0xFFFF_FFFF
v2 = isub v0, v1
return v2
}
; check: v3 = iconst.i32 1
; nextln: v4 = iadd v0, v3 ; v3 = 1
; nextln: return v4

8
cranelift/filetests/filetests/egraph/shifts.clif

@ -701,8 +701,8 @@ block0(v0: i8):
}
; check: v2 = iconst.i8 1
; check: v21 = rotr v0, v2 ; v2 = 1
; check: return v21
; check: v16 = rotr v0, v2 ; v2 = 1
; check: return v16
function %rotl_rotr_add(i8, i8, i8) -> i8 {
block0(v0: i8, v1: i8, v2: i8):
@ -725,8 +725,8 @@ block0(v0: i8):
}
; check: v2 = iconst.i8 1
; check: v21 = rotl v0, v2 ; v2 = 1
; check: return v21
; check: v16 = rotl v0, v2 ; v2 = 1
; check: return v16
function %rotl_rotr_add(i8, i8, i8) -> i8 {
block0(v0: i8, v1: i8, v2: i8):

Loading…
Cancel
Save