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