1b9a58148SKarl Meakin;; rewrites for integer and floating-point arithmetic
2b9a58148SKarl Meakin;; eg: `iadd`, `isub`, `ineg`, `imul`, `fadd`, `fsub`, `fmul`
3b9a58148SKarl Meakin
4d2887abaSscottmcm;; For commutative instructions, we depend on cprop.isle pushing immediates to
5d2887abaSscottmcm;; the right, and thus only simplify patterns like `x+0`, not `0+x`.
6d2887abaSscottmcm
7d2887abaSscottmcm;; x+0 == x.
8b9a58148SKarl Meakin(rule (simplify (iadd ty
9b9a58148SKarl Meakin                      x
102a367f4eSscottmcm                      (iconst_u ty 0)))
11b9a58148SKarl Meakin      (subsume x))
12b9a58148SKarl Meakin;; x-0 == x.
13b9a58148SKarl Meakin(rule (simplify (isub ty
14b9a58148SKarl Meakin                      x
152a367f4eSscottmcm                      (iconst_u ty 0)))
16b9a58148SKarl Meakin      (subsume x))
17b9a58148SKarl Meakin;; 0-x == (ineg x).
18b9a58148SKarl Meakin(rule (simplify (isub ty
192a367f4eSscottmcm                      (iconst_u ty 0)
20b9a58148SKarl Meakin                      x))
21b9a58148SKarl Meakin      (ineg ty x))
22b9a58148SKarl Meakin
2376f71d83Sscottmcm;; x + -y == -y + x == -(y - x) == x - y
2476f71d83Sscottmcm(rule (simplify (iadd ty x (ineg ty y)))
2576f71d83Sscottmcm      (isub ty x y))
2676f71d83Sscottmcm(rule (simplify (iadd ty (ineg ty y) x))
2776f71d83Sscottmcm      (isub ty x y))
2876f71d83Sscottmcm(rule (simplify (ineg ty (isub ty y x)))
2976f71d83Sscottmcm      (isub ty x y))
3076f71d83Sscottmcm;; x - -y == x + y
3176f71d83Sscottmcm(rule (simplify (isub ty x (ineg ty y)))
3276f71d83Sscottmcm      (iadd ty x y))
3376f71d83Sscottmcm
34b9a58148SKarl Meakin;; ineg(ineg(x)) == x.
35b9a58148SKarl Meakin(rule (simplify (ineg ty (ineg ty x))) (subsume x))
36b9a58148SKarl Meakin
37b9a58148SKarl Meakin;; ineg(x) * ineg(y) == x*y.
38b9a58148SKarl Meakin(rule (simplify (imul ty (ineg ty x) (ineg ty y)))
39b9a58148SKarl Meakin      (subsume (imul ty x y)))
40b9a58148SKarl Meakin
41b9a58148SKarl Meakin;; iabs(ineg(x)) == iabs(x).
42b9a58148SKarl Meakin(rule (simplify (iabs ty (ineg ty x)))
43b9a58148SKarl Meakin      (iabs ty x))
44b9a58148SKarl Meakin
45b9a58148SKarl Meakin;; iabs(iabs(x)) == iabs(x).
46b9a58148SKarl Meakin(rule (simplify (iabs ty inner @ (iabs ty x)))
47b9a58148SKarl Meakin      (subsume inner))
48b9a58148SKarl Meakin
49b9a58148SKarl Meakin;; x-x == 0.
5036b10914Sscottmcm(rule (simplify (isub (ty_int ty) x x)) (subsume (iconst_u ty 0)))
51b9a58148SKarl Meakin
52d2887abaSscottmcm;; x*1 == x.
53b9a58148SKarl Meakin(rule (simplify (imul ty
54b9a58148SKarl Meakin                      x
552a367f4eSscottmcm                      (iconst_u ty 1)))
56b9a58148SKarl Meakin      (subsume x))
57b9a58148SKarl Meakin
58d2887abaSscottmcm;; x*0 == 0.
59b9a58148SKarl Meakin(rule (simplify (imul ty
60b9a58148SKarl Meakin                      _
612a367f4eSscottmcm                      zero @ (iconst_u ty 0)))
62b9a58148SKarl Meakin      (subsume zero))
63b9a58148SKarl Meakin
64d2887abaSscottmcm;; x*-1 == ineg(x).
652a367f4eSscottmcm(rule (simplify (imul ty x (iconst_s ty -1)))
66b9a58148SKarl Meakin      (ineg ty x))
67b9a58148SKarl Meakin
6876f71d83Sscottmcm;; (!x) + 1 == ineg(x)
692a367f4eSscottmcm(rule (simplify (iadd ty (bnot ty x) (iconst_u ty 1)))
709e1ff972SAfonso Bordado      (ineg ty x))
719e1ff972SAfonso Bordado
7276f71d83Sscottmcm;; !(x - 1) == !(x + (-1)) == ineg(x)
732a367f4eSscottmcm(rule (simplify (bnot ty (isub ty x (iconst_s ty 1))))
749e1ff972SAfonso Bordado      (ineg ty x))
752a367f4eSscottmcm(rule (simplify (bnot ty (iadd ty x (iconst_s ty -1))))
769e1ff972SAfonso Bordado      (ineg ty x))
779e1ff972SAfonso Bordado
78b9a58148SKarl Meakin;; x / 1 == x.
797bf31723SNick Fitzgerald(rule (simplify_skeleton (sdiv x (iconst_s ty 1))) x)
807bf31723SNick Fitzgerald(rule (simplify_skeleton (udiv x (iconst_u ty 1))) x)
81b9a58148SKarl Meakin
82f678260bSNick Fitzgerald;; Unsigned `x / d == x >> ilog2(d)` when d is a power of two.
83f678260bSNick Fitzgerald(rule (simplify_skeleton (udiv x (iconst_u ty (u64_extract_power_of_two d))))
84f678260bSNick Fitzgerald      (ushr ty x (iconst_u ty (u64_ilog2 d))))
85f678260bSNick Fitzgerald
86f678260bSNick Fitzgerald;; Signed `x / d` when d is a power of two is a bit more involved...
87f678260bSNick Fitzgerald(rule (simplify_skeleton (sdiv x (iconst_u ty (u64_extract_power_of_two d))))
88f678260bSNick Fitzgerald      (if-let true (u64_gt d 1))
89f95d2dabSEmma Turner      ;; This rule musn't fire for the most negative number - which looks like
90f95d2dabSEmma Turner      ;; a power of two (sign bit set and otherwise all zeros)
91f95d2dabSEmma Turner      (if-let true (u32_lt (u64_trailing_zeros d)
92f95d2dabSEmma Turner                           (u32_sub (ty_bits ty) 1)))
93f678260bSNick Fitzgerald      (let ((k u32 (u64_trailing_zeros d))
94f678260bSNick Fitzgerald            (t1 Value (sshr ty x (iconst_u ty (u32_sub k 1))))
95f678260bSNick Fitzgerald            (t2 Value (ushr ty t1 (iconst_u ty (u32_sub (ty_bits ty) k))))
96f678260bSNick Fitzgerald            (t3 Value (iadd ty x t2))
97f678260bSNick Fitzgerald            (t4 Value (sshr ty t3 (iconst_s ty k))))
98f678260bSNick Fitzgerald        t4))
99f678260bSNick Fitzgerald
100f678260bSNick Fitzgerald;; And signed `x / d` when d is a negative power of two is the same, but with a
101f678260bSNick Fitzgerald;; negation.
102f678260bSNick Fitzgerald(rule (simplify_skeleton (sdiv x (iconst_s ty d)))
103f678260bSNick Fitzgerald      (if-let true (i64_is_negative_power_of_two d))
104f678260bSNick Fitzgerald      (if-let true (i64_ne d -1))
105f678260bSNick Fitzgerald      (let ((k u32 (i64_trailing_zeros d))
106f678260bSNick Fitzgerald            (t1 Value (sshr ty x (iconst_u ty (u32_sub k 1))))
107f678260bSNick Fitzgerald            (t2 Value (ushr ty t1 (iconst_u ty (u32_sub (ty_bits ty) k))))
108f678260bSNick Fitzgerald            (t3 Value (iadd ty x t2))
109f678260bSNick Fitzgerald            (t4 Value (sshr ty t3 (iconst_s ty k)))
110f678260bSNick Fitzgerald            (t5 Value (ineg ty t4)))
111f678260bSNick Fitzgerald        t5))
112f678260bSNick Fitzgerald
113f678260bSNick Fitzgerald;; General cases for `udiv` with constant divisors.
114f678260bSNick Fitzgerald(rule (simplify_skeleton (udiv x (iconst_u $I32 (u64_extract_non_zero (u32_from_u64 d)))))
115f678260bSNick Fitzgerald      (if-let false (u32_is_power_of_two d))
116f678260bSNick Fitzgerald      (apply_div_const_magic_u32 (Opcode.Udiv) x d))
117f678260bSNick Fitzgerald(rule (simplify_skeleton (udiv x (iconst_u $I64 (u64_extract_non_zero d))))
118f678260bSNick Fitzgerald      (if-let false (u64_is_power_of_two d))
119f678260bSNick Fitzgerald      (apply_div_const_magic_u64 (Opcode.Udiv) x d))
120f678260bSNick Fitzgerald
121f678260bSNick Fitzgerald;; General cases for `sdiv` with constant divisors.
122f678260bSNick Fitzgerald(rule (simplify_skeleton (sdiv x (iconst_s $I32 (i64_extract_non_zero (i32_from_i64 d)))))
123f678260bSNick Fitzgerald      (if-let false (i64_is_any_sign_power_of_two d))
124f678260bSNick Fitzgerald      (apply_div_const_magic_s32 (Opcode.Sdiv) x d))
125f678260bSNick Fitzgerald(rule (simplify_skeleton (sdiv x (iconst_s $I64 (i64_extract_non_zero d))))
126f678260bSNick Fitzgerald      (if-let false (i64_is_any_sign_power_of_two d))
127f678260bSNick Fitzgerald      (apply_div_const_magic_s64 (Opcode.Sdiv) x d))
128f678260bSNick Fitzgerald
129f678260bSNick Fitzgerald;; x % 1 == 0
130f678260bSNick Fitzgerald(rule (simplify_skeleton (urem x (iconst_u ty 1))) (iconst_u ty 0))
131f678260bSNick Fitzgerald(rule (simplify_skeleton (srem x (iconst_u ty 1))) (iconst_u ty 0))
132a21aba2dSAlex Crichton(rule (simplify_skeleton (srem x (iconst_s ty -1))) (iconst_u ty 0))
133f678260bSNick Fitzgerald
134f678260bSNick Fitzgerald;; Unsigned `x % d == x & ((1 << ilog2(d)) - 1)` when `d` is a power of two.
135f678260bSNick Fitzgerald(rule (simplify_skeleton (urem x (iconst_u ty (u64_extract_power_of_two d))))
136f678260bSNick Fitzgerald      (if-let true (u64_gt d 1))
137f678260bSNick Fitzgerald      (let ((mask Value (iconst_u ty (u64_sub (u64_shl 1 (u64_ilog2 d)) 1))))
138f678260bSNick Fitzgerald        (band ty x mask)))
139f678260bSNick Fitzgerald
140f678260bSNick Fitzgerald;; Signed `x % d` when `d` is a (possibly negative) power of two is a little
141f678260bSNick Fitzgerald;; more complicated.
142f678260bSNick Fitzgerald(rule (simplify_skeleton (srem x d_val @ (iconst_s ty d)))
143f678260bSNick Fitzgerald      ;; Interestingly, this same sequence works for both positive and negative
144f678260bSNick Fitzgerald      ;; powers of two.
145f678260bSNick Fitzgerald      (if-let true (i64_is_any_sign_power_of_two d))
146f678260bSNick Fitzgerald      (if-let true (i64_ne d 1))
147f678260bSNick Fitzgerald      (if-let true (i64_ne d -1))
148f678260bSNick Fitzgerald      (let ((k u32 (i64_trailing_zeros d))
149f678260bSNick Fitzgerald            (t1 Value (sshr ty x (iconst_u ty (u32_sub k 1))))
150f678260bSNick Fitzgerald            (t2 Value (ushr ty t1 (iconst_u ty (u32_sub (ty_bits ty) k))))
151f678260bSNick Fitzgerald            (t3 Value (iadd ty x t2))
152f678260bSNick Fitzgerald            (t4 Value (band ty t3 (iconst_s ty (i64_wrapping_neg (i64_shl 1 k)))))
153f678260bSNick Fitzgerald            (t5 Value (isub ty x t4)))
154f678260bSNick Fitzgerald        t5))
155f678260bSNick Fitzgerald
156f678260bSNick Fitzgerald;; General cases for `urem` with constant divisors.
157f678260bSNick Fitzgerald(rule (simplify_skeleton (urem x (iconst_u $I32 (u64_extract_non_zero (u32_from_u64 d)))))
158f678260bSNick Fitzgerald      (if-let false (u32_is_power_of_two d))
159f678260bSNick Fitzgerald      (apply_div_const_magic_u32 (Opcode.Urem) x d))
160f678260bSNick Fitzgerald(rule (simplify_skeleton (urem x (iconst_u $I64 (u64_extract_non_zero d))))
161f678260bSNick Fitzgerald      (if-let false (u64_is_power_of_two d))
162f678260bSNick Fitzgerald      (apply_div_const_magic_u64 (Opcode.Urem) x d))
163f678260bSNick Fitzgerald
164f678260bSNick Fitzgerald;; General cases for `srem` with constant divisors.
165f678260bSNick Fitzgerald(rule (simplify_skeleton (srem x (iconst_s $I32 (i64_extract_non_zero (i32_from_i64 d)))))
166f678260bSNick Fitzgerald      (if-let false (i64_is_any_sign_power_of_two d))
167f678260bSNick Fitzgerald      (apply_div_const_magic_s32 (Opcode.Srem) x d))
168f678260bSNick Fitzgerald(rule (simplify_skeleton (srem x (iconst_s $I64 (i64_extract_non_zero d))))
169f678260bSNick Fitzgerald      (if-let false (i64_is_any_sign_power_of_two d))
170f678260bSNick Fitzgerald      (apply_div_const_magic_s64 (Opcode.Srem) x d))
171b9a58148SKarl Meakin
172d2887abaSscottmcm;; x*2 == x+x.
1732a367f4eSscottmcm(rule (simplify (imul ty x (iconst_u _ 2)))
174b9a58148SKarl Meakin      (iadd ty x x))
175b9a58148SKarl Meakin
176b9a58148SKarl Meakin;; x*c == x<<log2(c) when c is a power of two.
177f678260bSNick Fitzgerald;;
178b9a58148SKarl Meakin;; Note that the type of `iconst` must be the same as the type of `imul`,
179b9a58148SKarl Meakin;; so these rules can only fire in situations where it's safe to construct an
180b9a58148SKarl Meakin;; `iconst` of that type.
181b9a58148SKarl Meakin(rule (simplify (imul ty x (iconst _ (imm64_power_of_two c))))
182b9a58148SKarl Meakin      (ishl ty x (iconst ty (imm64 c))))
183b9a58148SKarl Meakin(rule (simplify (imul ty (iconst _ (imm64_power_of_two c)) x))
184b9a58148SKarl Meakin      (ishl ty x (iconst ty (imm64 c))))
185b9a58148SKarl Meakin
186b9a58148SKarl Meakin;; fneg(fneg(x)) == x.
187b9a58148SKarl Meakin(rule (simplify (fneg ty (fneg ty x))) (subsume x))
188b9a58148SKarl Meakin
189b9a58148SKarl Meakin;; If both of the multiplied arguments to an `fma` are negated then remove
190b9a58148SKarl Meakin;; both of them since they cancel out.
191b9a58148SKarl Meakin(rule (simplify (fma ty (fneg ty x) (fneg ty y) z))
192b9a58148SKarl Meakin      (fma ty x y z))
193b9a58148SKarl Meakin
194b9a58148SKarl Meakin;; If both of the multiplied arguments to an `fmul` are negated then remove
195b9a58148SKarl Meakin;; both of them since they cancel out.
196b9a58148SKarl Meakin(rule (simplify (fmul ty (fneg ty x) (fneg ty y)))
197b9a58148SKarl Meakin      (fmul ty x y))
19872534b0fSNick Fitzgerald
199d12e4237Sscottmcm;; Detect people open-coding `mulhi`: (x as big * y as big) >> bits
200d12e4237Sscottmcm;; LLVM doesn't have an intrinsic for it, so you'll see it in code like
201d12e4237Sscottmcm;; <https://github.com/rust-lang/rust/blob/767453eb7ca188e991ac5568c17b984dd4893e77/library/core/src/num/mod.rs#L174-L180>
202d12e4237Sscottmcm(rule (simplify (sshr ty (imul ty (sextend _ x@(value_type half_ty))
203d12e4237Sscottmcm                                  (sextend _ y@(value_type half_ty)))
204d12e4237Sscottmcm                         (iconst_u _ k)))
205bb886ffcSKarl Meakin      (if-let true (ty_equal half_ty (ty_half_width ty)))
206bb886ffcSKarl Meakin      (if-let true (u64_eq k (ty_bits_u64 half_ty)))
207d12e4237Sscottmcm      (sextend ty (smulhi half_ty x y)))
208d12e4237Sscottmcm(rule (simplify (ushr ty (imul ty (uextend _ x@(value_type half_ty))
209d12e4237Sscottmcm                                  (uextend _ y@(value_type half_ty)))
210d12e4237Sscottmcm                         (iconst_u _ k)))
211bb886ffcSKarl Meakin      (if-let true (ty_equal half_ty (ty_half_width ty)))
212bb886ffcSKarl Meakin      (if-let true (u64_eq k (ty_bits_u64 half_ty)))
213d12e4237Sscottmcm      (uextend ty (umulhi half_ty x y)))
214492811deSAlex Crichton
215492811deSAlex Crichton;; Cranelift's `fcvt_from_{u,s}int` instructions are polymorphic over the input
216492811deSAlex Crichton;; type so remove any unnecessary `uextend` or `sextend` to give backends
217492811deSAlex Crichton;; the chance to convert from the smallest integral type to the float. This
218492811deSAlex Crichton;; can help lowerings on x64 for example which has a less efficient u64-to-float
219492811deSAlex Crichton;; conversion than other bit widths.
220492811deSAlex Crichton(rule (simplify (fcvt_from_uint ty (uextend _ val)))
221492811deSAlex Crichton      (fcvt_from_uint ty val))
222492811deSAlex Crichton(rule (simplify (fcvt_from_sint ty (sextend _ val)))
223492811deSAlex Crichton      (fcvt_from_sint ty val))
22494477009SBongjun Jang
22594477009SBongjun Jang
22694477009SBongjun Jang;; or(x, C) + (-C)  -->  and(x, ~C)
22794477009SBongjun Jang(rule
22894477009SBongjun Jang  (simplify (iadd ty
22994477009SBongjun Jang              (bor ty x (iconst_s ty n))
23094477009SBongjun Jang              (iconst_s ty m)))
231cfe17cb1SNick Fitzgerald  (if-let m (i64_checked_neg n))
232cfe17cb1SNick Fitzgerald  (band ty x (iconst ty (imm64_masked ty (i64_cast_unsigned (i64_not n))))))
2338022f719SBongjun Jang
2348022f719SBongjun Jang;; (x + y) - (x | y) --> x & y
2358022f719SBongjun Jang(rule (simplify (isub ty (iadd ty x y) (bor ty x y))) (band ty x y))
236c5dcca75SBongjun Jang
237c5dcca75SBongjun Jang;; x * (1 << y) == x << y
238c5dcca75SBongjun Jang(rule (simplify (imul ty x (ishl ty (iconst_s ty 1) y))) (ishl ty x y))
23962ce9e5aSBongjun Jang
24062ce9e5aSBongjun Jang;; (x - y) + x --> x
24162ce9e5aSBongjun Jang(rule (simplify (iadd ty (isub ty x y) y)) x)
24262ce9e5aSBongjun Jang(rule (simplify (iadd ty y (isub ty x y))) x)
24362ce9e5aSBongjun Jang
24462ce9e5aSBongjun Jang;; (x + y) - y --> x
24562ce9e5aSBongjun Jang(rule (simplify (isub ty (iadd ty x y) x)) y)
24662ce9e5aSBongjun Jang(rule (simplify (isub ty (iadd ty x y) y)) x)
247b58cd171SBongjun Jang
248b58cd171SBongjun Jang;; (x - y) - x => -y
249b58cd171SBongjun Jang(rule (simplify (isub ty (isub ty x y) x))(ineg ty y))
250b58cd171SBongjun Jang
25153d36524SBongjun Jang;; (x * C) (==/!=) D --> x (==/!=) (D / C) when C is odd and divides D
25253d36524SBongjun Jang(rule
25353d36524SBongjun Jang  (simplify (ne ty (iconst_u ty1 x) (imul ty1 y (iconst_u ty1 z))))
254b4509241SAlex Crichton  (if-let 0 (u64_checked_rem x z))
25553d36524SBongjun Jang  (if-let 1 (u64_rem z 2))
25653d36524SBongjun Jang  (ne ty y (iconst ty1 (imm64 (u64_div x z)))))
25753d36524SBongjun Jang(rule
25853d36524SBongjun Jang  (simplify (ne ty (iconst_u ty1 x) (imul ty1 (iconst_u ty1 y) z)))
259b4509241SAlex Crichton  (if-let 0 (u64_checked_rem x y))
26053d36524SBongjun Jang  (if-let 1 (u64_rem y 2))
26153d36524SBongjun Jang  (ne ty z (iconst ty1 (imm64 (u64_div x y)))))
26253d36524SBongjun Jang(rule
26353d36524SBongjun Jang  (simplify (ne ty (imul ty1 x (iconst_u ty1 y)) (iconst_u ty1 z)))
264b4509241SAlex Crichton  (if-let 0 (u64_checked_rem z y))
26553d36524SBongjun Jang  (if-let 1 (u64_rem y 2))
26653d36524SBongjun Jang  (ne ty x (iconst ty1 (imm64 (u64_div z y)))))
26753d36524SBongjun Jang(rule
26853d36524SBongjun Jang  (simplify (ne ty (imul ty1 (iconst_u ty1 x) y) (iconst_u ty1 z)))
269b4509241SAlex Crichton  (if-let 0 (u64_checked_rem z x))
27053d36524SBongjun Jang  (if-let 1 (u64_rem x 2))
27153d36524SBongjun Jang  (ne ty y (iconst ty1 (imm64 (u64_div z x)))))
27253d36524SBongjun Jang
27353d36524SBongjun Jang
27453d36524SBongjun Jang(rule
27553d36524SBongjun Jang  (simplify (eq ty (iconst_u ty1 x) (imul ty1 y (iconst_u ty1 z))))
276b4509241SAlex Crichton  (if-let 0 (u64_checked_rem x z))
27753d36524SBongjun Jang  (if-let 1 (u64_rem z 2))
27853d36524SBongjun Jang  (eq ty y (iconst ty1 (imm64 (u64_div x z)))))
27953d36524SBongjun Jang(rule
28053d36524SBongjun Jang  (simplify (eq ty (iconst_u ty1 x) (imul ty1 (iconst_u ty1 y) z)))
281b4509241SAlex Crichton  (if-let 0 (u64_checked_rem x y))
28253d36524SBongjun Jang  (if-let 1 (u64_rem y 2))
28353d36524SBongjun Jang  (eq ty z (iconst ty1 (imm64 (u64_div x y)))))
28453d36524SBongjun Jang(rule
28553d36524SBongjun Jang  (simplify (eq ty (imul ty1 x (iconst_u ty1 y)) (iconst_u ty1 z)))
286b4509241SAlex Crichton  (if-let 0 (u64_checked_rem z y))
28753d36524SBongjun Jang  (if-let 1 (u64_rem y 2))
28853d36524SBongjun Jang  (eq ty x (iconst ty1 (imm64 (u64_div z y)))))
28953d36524SBongjun Jang(rule
29053d36524SBongjun Jang  (simplify (eq ty (imul ty1 (iconst_u ty1 x) y) (iconst_u ty1 z)))
291b4509241SAlex Crichton  (if-let 0 (u64_checked_rem z x))
29253d36524SBongjun Jang  (if-let 1 (u64_rem x 2))
29353d36524SBongjun Jang  (eq ty y (iconst ty1 (imm64 (u64_div z x)))))
2946e780a67SHyunbin Kim
2956e780a67SHyunbin Kim;; (x + y) + (-y) ==> x
2966e780a67SHyunbin Kim;; and equivalent operand-order variants.
2976e780a67SHyunbin Kim(rule (simplify (iadd ty (iadd ty x y) (ineg ty y))) x)
2986e780a67SHyunbin Kim(rule (simplify (iadd ty (ineg ty y) (iadd ty x y))) x)
2996e780a67SHyunbin Kim(rule (simplify (iadd ty (iadd ty y x) (ineg ty y))) x)
3006e780a67SHyunbin Kim(rule (simplify (iadd ty (ineg ty y) (iadd ty y x))) x)
3016e780a67SHyunbin Kim
3026e780a67SHyunbin Kim;; (x | y) - (x & y)  ==>  (x ^ y)
3036e780a67SHyunbin Kim(rule (simplify (isub ty (bor ty x y) (band ty x y))) (bxor ty x y))
3046e780a67SHyunbin Kim(rule (simplify (isub ty (bor ty x y) (band ty y x))) (bxor ty x y))
3056e780a67SHyunbin Kim(rule (simplify (isub ty (bor ty y x) (band ty x y))) (bxor ty x y))
3066e780a67SHyunbin Kim(rule (simplify (isub ty (bor ty y x) (band ty y x))) (bxor ty x y))
3076e780a67SHyunbin Kim
3086e780a67SHyunbin Kim;; (x + y) - (x & y)  ==>  (x | y)
3096e780a67SHyunbin Kim(rule (simplify (isub ty (iadd ty x y) (band ty x y))) (bor ty x y))
3106e780a67SHyunbin Kim(rule (simplify (isub ty (iadd ty x y) (band ty y x))) (bor ty x y))
3116e780a67SHyunbin Kim(rule (simplify (isub ty (iadd ty y x) (band ty x y))) (bor ty x y))
3126e780a67SHyunbin Kim(rule (simplify (isub ty (iadd ty y x) (band ty y x))) (bor ty x y))
3136e780a67SHyunbin Kim
3146e780a67SHyunbin Kim;; (x | y) - (x ^ y)  ==>  (x & y)
3156e780a67SHyunbin Kim(rule (simplify (isub ty (bor ty x y) (bxor ty x y))) (band ty x y))
3166e780a67SHyunbin Kim(rule (simplify (isub ty (bor ty x y) (bxor ty y x))) (band ty x y))
3176e780a67SHyunbin Kim(rule (simplify (isub ty (bor ty y x) (bxor ty x y))) (band ty x y))
3186e780a67SHyunbin Kim(rule (simplify (isub ty (bor ty y x) (bxor ty y x))) (band ty x y))
3196e780a67SHyunbin Kim
3206e780a67SHyunbin Kim;; (~x) + x == -1
321bb5a8454SHyunbin Kim;; Keep the generic fold for <=64-bit types, and handle i128 explicitly.
322bb5a8454SHyunbin Kim(rule (simplify (iadd (fits_in_64 ty) (bnot ty x) x)) (iconst_s ty -1))
323bb5a8454SHyunbin Kim(rule (simplify (iadd (fits_in_64 ty) x (bnot ty x))) (iconst_s ty -1))
324bb5a8454SHyunbin Kim
325bb5a8454SHyunbin Kim(rule (simplify (iadd $I128 (bnot $I128 x) x)) (sextend $I128 (iconst_s $I64 -1)))
326bb5a8454SHyunbin Kim(rule (simplify (iadd $I128 x (bnot $I128 x))) (sextend $I128 (iconst_s $I64 -1)))
32715783254SHyunbin Kim
32815783254SHyunbin Kim;; ((x + y) - (x + z)) --> (y - z)
32915783254SHyunbin Kim(rule (simplify (isub ty (iadd ty x y) (iadd ty x z))) (isub ty y z))
33015783254SHyunbin Kim(rule (simplify (isub ty (iadd ty x y) (iadd ty z x))) (isub ty y z))
33115783254SHyunbin Kim(rule (simplify (isub ty (iadd ty y x) (iadd ty x z))) (isub ty y z))
33215783254SHyunbin Kim(rule (simplify (isub ty (iadd ty y x) (iadd ty z x))) (isub ty y z))
33315783254SHyunbin Kim
33415783254SHyunbin Kim;; ((x - z) - (y - z)) --> (x - y)
33515783254SHyunbin Kim(rule (simplify (isub ty (isub ty x z) (isub ty y z))) (isub ty x y))
33615783254SHyunbin Kim
33715783254SHyunbin Kim;; ((x - y) - (x - z)) --> (z - y)
33815783254SHyunbin Kim(rule (simplify (isub ty (isub ty x y) (isub ty x z))) (isub ty z y))
33915783254SHyunbin Kim
34015783254SHyunbin Kim;; umin(x, y) + umax(x, y) --> x + y
34115783254SHyunbin Kim(rule (simplify (iadd ty (umin ty x y) (umax ty x y))) (iadd ty x y))
34215783254SHyunbin Kim(rule (simplify (iadd ty (umax ty x y) (umin ty x y))) (iadd ty x y))
34315783254SHyunbin Kim(rule (simplify (iadd ty (umin ty x y) (umax ty y x))) (iadd ty x y))
34415783254SHyunbin Kim(rule (simplify (iadd ty (umax ty y x) (umin ty x y))) (iadd ty x y))
34515783254SHyunbin Kim(rule (simplify (iadd ty (umin ty y x) (umax ty x y))) (iadd ty x y))
34615783254SHyunbin Kim(rule (simplify (iadd ty (umax ty x y) (umin ty y x))) (iadd ty x y))
34715783254SHyunbin Kim(rule (simplify (iadd ty (umin ty y x) (umax ty y x))) (iadd ty x y))
34815783254SHyunbin Kim(rule (simplify (iadd ty (umax ty y x) (umin ty y x))) (iadd ty x y))
34915783254SHyunbin Kim
35015783254SHyunbin Kim;; smin(x, y) + smax(x, y) --> x + y
35115783254SHyunbin Kim(rule (simplify (iadd ty (smin ty x y) (smax ty x y))) (iadd ty x y))
35215783254SHyunbin Kim(rule (simplify (iadd ty (smax ty x y) (smin ty x y))) (iadd ty x y))
35315783254SHyunbin Kim(rule (simplify (iadd ty (smin ty x y) (smax ty y x))) (iadd ty x y))
35415783254SHyunbin Kim(rule (simplify (iadd ty (smax ty y x) (smin ty x y))) (iadd ty x y))
35515783254SHyunbin Kim(rule (simplify (iadd ty (smin ty y x) (smax ty x y))) (iadd ty x y))
35615783254SHyunbin Kim(rule (simplify (iadd ty (smax ty x y) (smin ty y x))) (iadd ty x y))
35715783254SHyunbin Kim(rule (simplify (iadd ty (smin ty y x) (smax ty y x))) (iadd ty x y))
35815783254SHyunbin Kim(rule (simplify (iadd ty (smax ty y x) (smin ty y x))) (iadd ty x y))
35915783254SHyunbin Kim
36015783254SHyunbin Kim;; ((x + z) - (y + z)) --> (x - y)
36115783254SHyunbin Kim(rule (simplify (isub ty (iadd ty x z) (iadd ty y z))) (isub ty x y))
36215783254SHyunbin Kim(rule (simplify (isub ty (iadd ty x z) (iadd ty z y))) (isub ty x y))
36315783254SHyunbin Kim(rule (simplify (isub ty (iadd ty z x) (iadd ty y z))) (isub ty x y))
36415783254SHyunbin Kim(rule (simplify (isub ty (iadd ty z x) (iadd ty z y))) (isub ty x y))
36515783254SHyunbin Kim
36615783254SHyunbin Kim;; ((x - y) + (y + z)) --> (x + z)
36715783254SHyunbin Kim(rule (simplify (iadd ty (isub ty x y) (iadd ty y z))) (iadd ty x z))
36815783254SHyunbin Kim(rule (simplify (iadd ty (iadd ty y z) (isub ty x y))) (iadd ty x z))
36915783254SHyunbin Kim(rule (simplify (iadd ty (isub ty x y) (iadd ty z y))) (iadd ty x z))
37015783254SHyunbin Kim(rule (simplify (iadd ty (iadd ty z y) (isub ty x y))) (iadd ty x z))
37115783254SHyunbin Kim
37215783254SHyunbin Kim;; (x - (x + y)) --> -y
37315783254SHyunbin Kim(rule (simplify (isub ty x (iadd ty x y))) (ineg ty y))
37415783254SHyunbin Kim(rule (simplify (isub ty x (iadd ty y x))) (ineg ty y))
37515783254SHyunbin Kim
37615783254SHyunbin Kim;; (x + (y + (z - x))) --> (y + z)
37715783254SHyunbin Kim(rule (simplify (iadd ty x (iadd ty y (isub ty z x)))) (iadd ty y z))
37815783254SHyunbin Kim(rule (simplify (iadd ty (iadd ty y (isub ty z x)) x)) (iadd ty y z))
37915783254SHyunbin Kim(rule (simplify (iadd ty x (iadd ty (isub ty z x) y))) (iadd ty y z))
38015783254SHyunbin Kim(rule (simplify (iadd ty (iadd ty (isub ty z x) y) x)) (iadd ty y z))
38115783254SHyunbin Kim
38215783254SHyunbin Kim;; (x + y) == (y + x) --> true
3831e73c1f1SAlex Crichton(rule (simplify (eq (ty_int ty) (iadd cty x y) (iadd cty y x))) (iconst_u ty 1))
3841e73c1f1SAlex Crichton(rule (simplify (eq (ty_int ty) (iadd cty y x) (iadd cty x y))) (iconst_u ty 1))
3851e73c1f1SAlex Crichton(rule (simplify (eq (ty_int ty) (iadd cty x y) (iadd cty x y))) (iconst_u ty 1))
3861e73c1f1SAlex Crichton(rule (simplify (eq (ty_int ty) (iadd cty y x) (iadd cty y x))) (iconst_u ty 1))
38715783254SHyunbin Kim
38815783254SHyunbin Kim;; (x - y) != x --> y != 0
389*eb4c5279STill Schneidereit(rule (simplify (ne cty (isub (ty_int ty) x y) x)) (ne cty y (iconst_u ty 0)))
390*eb4c5279STill Schneidereit(rule (simplify (ne cty x (isub (ty_int ty) x y))) (ne cty y (iconst_u ty 0)))
391