Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Cranelift: More simplification opts for iadd/isub #7654

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
23 changes: 13 additions & 10 deletions cranelift/codegen/src/opts/arithmetic.isle
Expand Up @@ -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))

Expand Down Expand Up @@ -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
Expand Down
20 changes: 4 additions & 16 deletions 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))
Expand All @@ -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))))

Expand Down
11 changes: 11 additions & 0 deletions cranelift/codegen/src/opts/cprop.isle
Expand Up @@ -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
Expand Down
54 changes: 50 additions & 4 deletions cranelift/filetests/filetests/egraph/arithmetic.clif
Expand Up @@ -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
Expand Down Expand Up @@ -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):
Expand All @@ -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):
Expand Down Expand Up @@ -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):
Expand Down
22 changes: 22 additions & 0 deletions cranelift/filetests/filetests/egraph/cprop.clif
Expand Up @@ -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 changes: 4 additions & 4 deletions cranelift/filetests/filetests/egraph/shifts.clif
Expand Up @@ -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):
Expand All @@ -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):
Expand Down