1;; Constant propagation. 2 3(rule (simplify 4 (iadd (fits_in_64 ty) 5 (iconst ty (u64_from_imm64 k1)) 6 (iconst ty (u64_from_imm64 k2)))) 7 (subsume (iconst ty (imm64_masked ty (u64_wrapping_add k1 k2))))) 8 9(rule (simplify 10 (isub (fits_in_64 ty) 11 (iconst ty (u64_from_imm64 k1)) 12 (iconst ty (u64_from_imm64 k2)))) 13 (subsume (iconst ty (imm64_masked ty (u64_wrapping_sub k1 k2))))) 14 15(rule (simplify 16 (imul (fits_in_64 ty) 17 (iconst ty (u64_from_imm64 k1)) 18 (iconst ty (u64_from_imm64 k2)))) 19 (subsume (iconst ty (imm64_masked ty (u64_wrapping_mul k1 k2))))) 20 21(rule (simplify_skeleton 22 (sdiv (iconst ty k1) 23 (iconst _ k2))) 24 (if-let d (imm64_sdiv ty k1 k2)) 25 (iconst ty d)) 26 27(rule (simplify_skeleton 28 (udiv (iconst_u ty k1) 29 (iconst_u ty k2))) 30 (if-let d (u64_checked_div k1 k2)) 31 (iconst ty (imm64_masked ty d))) 32 33(rule (simplify 34 (bor (fits_in_64 ty) 35 (iconst ty (u64_from_imm64 k1)) 36 (iconst ty (u64_from_imm64 k2)))) 37 (subsume (iconst ty (imm64_masked ty (u64_or k1 k2))))) 38 39(rule (simplify 40 (band (fits_in_64 ty) 41 (iconst ty (u64_from_imm64 k1)) 42 (iconst ty (u64_from_imm64 k2)))) 43 (subsume (iconst ty (imm64_masked ty (u64_and k1 k2))))) 44 45(rule (simplify 46 (bxor (fits_in_64 ty) 47 (iconst ty (u64_from_imm64 k1)) 48 (iconst ty (u64_from_imm64 k2)))) 49 (subsume (iconst ty (imm64_masked ty (u64_xor k1 k2))))) 50 51(rule (simplify 52 (bnot (fits_in_64 ty) 53 (iconst ty (u64_from_imm64 k)))) 54 (subsume (iconst ty (imm64_masked ty (u64_not k))))) 55 56(rule (simplify (ishl (fits_in_64 ty) 57 (iconst ty k1) 58 (iconst _ k2))) 59 (subsume (iconst ty (imm64_shl ty k1 k2)))) 60 61(rule (simplify (ushr (fits_in_64 ty) 62 (iconst ty k1) 63 (iconst _ k2))) 64 (subsume (iconst ty (imm64_ushr ty k1 k2)))) 65 66(rule (simplify (sshr (fits_in_64 ty) 67 (iconst ty k1) 68 (iconst _ k2))) 69 (subsume (iconst ty (imm64_sshr ty k1 k2)))) 70 71(rule (simplify (ireduce narrow (iconst (fits_in_64 _) (u64_from_imm64 imm)))) 72 (subsume (iconst narrow (imm64_masked narrow imm)))) 73 74;; iconst_[su] support $I128, but do so by extending, so restricting to 75;; 64-bit or smaller keeps it from just remaking essentially the same thing. 76(rule (simplify (uextend (fits_in_64 wide) (iconst_u narrow k))) 77 (subsume (iconst_u wide k))) 78(rule (simplify (sextend (fits_in_64 wide) (iconst_s narrow k))) 79 (subsume (iconst_s wide k))) 80 81(rule (simplify 82 (icmp result_ty 83 cc 84 (iconst ty k1) 85 (iconst ty k2))) 86 (subsume (iconst result_ty (imm64_icmp ty cc k1 k2)))) 87 88 89;; Canonicalize via commutativity: push immediates to the right. 90;; 91;; (op k x) --> (op x k) 92 93(rule (simplify 94 (iadd ty k @ (iconst ty _) x)) 95 (iadd ty x k)) 96;; sub is not commutative, but we can flip the args and negate the 97;; whole thing. 98(rule (simplify 99 (isub ty k @ (iconst ty _) x)) 100 (ineg ty (isub ty x k))) 101(rule (simplify 102 (imul ty k @ (iconst ty _) x)) 103 (imul ty x k)) 104 105(rule (simplify 106 (bor ty k @ (iconst ty _) x)) 107 (bor ty x k)) 108(rule (simplify 109 (band ty k @ (iconst ty _) x)) 110 (band ty x k)) 111(rule (simplify 112 (bxor ty k @ (iconst ty _) x)) 113 (bxor ty x k)) 114 115(rule (simplify 116 (icmp ty cc k @ (iconst _ _) x)) 117 (icmp ty (intcc_swap_args cc) x k)) 118 119;; Canonicalize via associativity: reassociate to a right-heavy tree 120;; for constants. 121;; 122;; (op (op x k) k) --> (op x (op k k)) 123 124(rule (simplify 125 (iadd ty (iadd ty x k1 @ (iconst ty _)) k2 @ (iconst ty _))) 126 (iadd ty x (iadd ty k1 k2))) 127;; sub is not directly associative, but we can flip a sub to an add to 128;; make it work: 129;; - (sub (sub x k1) k2) -> (sub x (add k1 k2)) 130;; - (sub (sub k1 x) k2) -> (sub (sub k1 k2) x) 131;; - (sub (add x k1) k2) -> (sub x (sub k2 k1)) 132;; - (add (sub x k1) k2) -> (add x (sub k2 k1)) 133;; - (add (sub k1 x) k2) -> (sub (add k1 k2) x) 134(rule (simplify (isub ty 135 (isub ty x (iconst ty (u64_from_imm64 k1))) 136 (iconst ty (u64_from_imm64 k2)))) 137 (isub ty x (iconst ty (imm64_masked ty (u64_wrapping_add k1 k2))))) 138(rule (simplify (isub ty 139 (isub ty (iconst ty (u64_from_imm64 k1)) x) 140 (iconst ty (u64_from_imm64 k2)))) 141 (isub ty (iconst ty (imm64_masked ty (u64_wrapping_sub k1 k2))) x)) 142(rule (simplify (isub ty 143 (iadd ty x (iconst ty (u64_from_imm64 k1))) 144 (iconst ty (u64_from_imm64 k2)))) 145 (isub ty x (iconst ty (imm64_masked ty (u64_wrapping_sub k2 k1))))) 146(rule (simplify (iadd ty 147 (isub ty x (iconst ty (u64_from_imm64 k1))) 148 (iconst ty (u64_from_imm64 k2)))) 149 (iadd ty x (iconst ty (imm64_masked ty (u64_wrapping_sub k2 k1))))) 150(rule (simplify (iadd ty 151 (isub ty (iconst ty (u64_from_imm64 k1)) x) 152 (iconst ty (u64_from_imm64 k2)))) 153 (isub ty (iconst ty (imm64_masked ty (u64_wrapping_add k1 k2))) x)) 154 155(rule (simplify 156 (imul ty (imul ty x k1 @ (iconst ty _)) k2 @ (iconst ty _))) 157 (imul ty x (imul ty k1 k2))) 158(rule (simplify 159 (bor ty (bor ty x k1 @ (iconst ty _)) k2 @ (iconst ty _))) 160 (bor ty x (bor ty k1 k2))) 161(rule (simplify 162 (band ty (band ty x k1 @ (iconst ty _)) k2 @ (iconst ty _))) 163 (band ty x (band ty k1 k2))) 164(rule (simplify 165 (bxor ty (bxor ty x k1 @ (iconst ty _)) k2 @ (iconst ty _))) 166 (bxor ty x (bxor ty k1 k2))) 167 168(rule (simplify (select ty (iconst_u _ (u64_when_non_zero)) x _)) 169 (subsume x)) 170(rule (simplify (select ty (iconst_u _ 0) _ y)) 171 (subsume y)) 172 173;; Reassociate across `==`/`!=` when we can simplify a constant 174;; `x + K1 == K2` --> `x == K2 - K1` 175(rule (simplify (eq ty1 (iadd ty2 x k1@(iconst _ _)) k2@(iconst _ _))) 176 (eq ty1 x (isub ty2 k2 k1))) 177(rule (simplify (ne ty1 (iadd ty2 x k1@(iconst _ _)) k2@(iconst _ _))) 178 (ne ty1 x (isub ty2 k2 k1))) 179;; `x - K1 == K2` --> `x == K2 + K1` 180(rule (simplify (eq ty1 (isub ty2 x k1@(iconst _ _)) k2@(iconst _ _))) 181 (eq ty1 x (iadd ty2 k2 k1))) 182(rule (simplify (ne ty1 (isub ty2 x k1@(iconst _ _)) k2@(iconst _ _))) 183 (ne ty1 x (iadd ty2 k2 k1))) 184;; `x + K1 == y + K2` --> `x == y + (K2 - K1)` 185(rule (simplify (eq ty1 (iadd ty2 x k1@(iconst _ _)) (iadd ty3 y k2@(iconst _ _)))) 186 (eq ty1 x (iadd ty2 y (isub ty3 k2 k1)))) 187(rule (simplify (ne ty1 (iadd ty2 x k1@(iconst _ _)) (iadd ty3 y k2@(iconst _ _)))) 188 (ne ty1 x (iadd ty2 y (isub ty3 k2 k1)))) 189;; An icmp rule normalizes (eq sub sub), so we don't need to handle it here. 190 191;; Replace subtraction by a "negative" constant with addition. 192;; Notably, this gives `x - (-1) == x + 1`, so other patterns don't have to 193;; match the subtract-negative-one version too. 194;; TODO: it would be nice to do this for `x + (-1) == x - 1` as well, but 195;; that needs work in lowering first to avoid regressing addressing modes. 196 197(rule (simplify (isub ty x (iconst_s ty k))) 198 (if-let true (u64_lt (i64_cast_unsigned (i64_wrapping_neg k)) 199 (i64_cast_unsigned k))) 200 (iadd ty x (iconst ty (imm64_masked ty (i64_cast_unsigned (i64_wrapping_neg k)))))) 201 202;; A splat of a constant can become a direct `vconst` with the appropriate bit 203;; pattern. 204(rule (simplify (splat (ty_vec128 dst) (iconst $I8 n))) 205 (vconst dst (splat8 (u64_uextend_imm64 $I8 n)))) 206(rule (simplify (splat (ty_vec128 dst) (iconst $I16 n))) 207 (vconst dst (splat16 (u64_uextend_imm64 $I16 n)))) 208(rule (simplify (splat (ty_vec128 dst) (iconst $I32 n))) 209 (vconst dst (splat32 (u64_uextend_imm64 $I32 n)))) 210(rule (simplify (splat (ty_vec128 dst) (iconst $I64 n))) 211 (vconst dst (splat64 (u64_uextend_imm64 $I64 n)))) 212(rule (simplify (splat (ty_vec128 dst) (f32const _ (u32_from_ieee32 n)))) 213 (vconst dst (splat32 n))) 214(rule (simplify (splat (ty_vec128 dst) (f64const _ (u64_from_ieee64 n)))) 215 (vconst dst (splat64 n))) 216 217(decl splat8 (u64) Constant) 218(rule (splat8 n) (splat16 (u64_or n (u64_shl n 8)))) 219(decl splat16 (u64) Constant) 220(rule (splat16 n) (splat32 (u64_or n (u64_shl n 16)))) 221(decl splat32 (u64) Constant) 222(rule (splat32 n) (splat64 (u64_or n (u64_shl n 32)))) 223(decl splat64 (u64) Constant) 224(extern constructor splat64 splat64) 225 226;; Reassociate nested shifts of constants to put constants together for cprop. 227;; 228;; ((A shift b) shift C) ==> ((A shift C) shift b) 229(rule (simplify (ishl ty (ishl ty a@(iconst _ _) b) c@(iconst _ _))) 230 (ishl ty (ishl ty a c) b)) 231(rule (simplify (ushr ty (ushr ty a@(iconst _ _) b) c@(iconst _ _))) 232 (ushr ty (ushr ty a c) b)) 233(rule (simplify (sshr ty (sshr ty a@(iconst _ _) b) c@(iconst _ _))) 234 (sshr ty (sshr ty a c) b)) 235 236;; When we operations that are both commutative and associative, reassociate 237;; constants together for cprop: 238;; 239;; ((a op B) op (c op D)) ==> ((a op c) op (B op D)) 240;; 241;; Where `op` is one of: `iadd`, `imul`, `band`, `bor`, or `bxor`. 242(rule (simplify (iadd ty 243 (iadd ty a b@(iconst _ _)) 244 (iadd ty c d@(iconst _ _)))) 245 (iadd ty (iadd ty a c) (iadd ty b d))) 246(rule (simplify (imul ty 247 (imul ty a b@(iconst _ _)) 248 (imul ty c d@(iconst _ _)))) 249 (imul ty (imul ty a c) (imul ty b d))) 250(rule (simplify (band ty 251 (band ty a b@(iconst _ _)) 252 (band ty c d@(iconst _ _)))) 253 (band ty (band ty a c) (band ty b d))) 254(rule (simplify (bor ty 255 (bor ty a b@(iconst _ _)) 256 (bor ty c d@(iconst _ _)))) 257 (bor ty (bor ty a c) (bor ty b d))) 258(rule (simplify (bxor ty 259 (bxor ty a b@(iconst _ _)) 260 (bxor ty c d@(iconst _ _)))) 261 (bxor ty (bxor ty a c) (bxor ty b d))) 262 263 264;; Constant fold int-to-float conversions. 265(rule (simplify (fcvt_from_uint $F32 (iconst_u _ n))) 266 (f32const $F32 (f32_from_uint n))) 267(rule (simplify (fcvt_from_uint $F64 (iconst_u _ n))) 268 (f64const $F64 (f64_from_uint n))) 269(rule (simplify (fcvt_from_sint $F32 (iconst_s _ n))) 270 (f32const $F32 (f32_from_sint n))) 271(rule (simplify (fcvt_from_sint $F64 (iconst_s _ n))) 272 (f64const $F64 (f64_from_sint n))) 273 274(decl f32_from_uint (u64) Ieee32) 275(extern constructor f32_from_uint f32_from_uint) 276(decl f64_from_uint (u64) Ieee64) 277(extern constructor f64_from_uint f64_from_uint) 278(decl f32_from_sint (i64) Ieee32) 279(extern constructor f32_from_sint f32_from_sint) 280(decl f64_from_sint (i64) Ieee64) 281(extern constructor f64_from_sint f64_from_sint) 282 283;; Constant fold bswap of a constant. 284(rule (simplify (bswap $I16 (iconst ty (u64_from_imm64 n)))) 285 (subsume (iconst $I16 (imm64 (u64_bswap16 n))))) 286(rule (simplify (bswap $I32 (iconst ty (u64_from_imm64 n)))) 287 (subsume (iconst $I32 (imm64 (u64_bswap32 n))))) 288(rule (simplify (bswap $I64 (iconst ty (u64_from_imm64 n)))) 289 (subsume (iconst $I64 (imm64 (u64_bswap64 n))))) 290 291(decl pure u64_bswap16 (u64) u64) 292(extern constructor u64_bswap16 u64_bswap16) 293(decl pure u64_bswap32 (u64) u64) 294(extern constructor u64_bswap32 u64_bswap32) 295(decl pure u64_bswap64 (u64) u64) 296(extern constructor u64_bswap64 u64_bswap64) 297 298;; Constant fold float operations 299;; Note: With the exception of fabs, fneg and copysign, 300;; constant folding is only performed when the result of 301;; an instruction isn't NaN. We want the NaN bit patterns 302;; produced by an instruction to be consistent, and 303;; compile-time evaluation in a cross-compilation scenario 304;; risks producing different NaN bit patterns than the target 305;; would have at run-time. 306;; TODO: fcmp, fma, demote, promote, to-int ops 307(rule (simplify (fadd $F32 (f32const $F32 lhs) (f32const $F32 rhs))) 308 (if-let r (f32_add lhs rhs)) 309 (subsume (f32const $F32 r))) 310(rule (simplify (fadd $F64 (f64const $F64 lhs) (f64const $F64 rhs))) 311 (if-let r (f64_add lhs rhs)) 312 (subsume (f64const $F64 r))) 313 314(rule (simplify (fsub $F32 (f32const $F32 lhs) (f32const $F32 rhs))) 315 (if-let r (f32_sub lhs rhs)) 316 (subsume (f32const $F32 r))) 317(rule (simplify (fsub $F64 (f64const $F64 lhs) (f64const $F64 rhs))) 318 (if-let r (f64_sub lhs rhs)) 319 (subsume (f64const $F64 r))) 320 321(rule (simplify (fmul $F32 (f32const $F32 lhs) (f32const $F32 rhs))) 322 (if-let r (f32_mul lhs rhs)) 323 (subsume (f32const $F32 r))) 324(rule (simplify (fmul $F64 (f64const $F64 lhs) (f64const $F64 rhs))) 325 (if-let r (f64_mul lhs rhs)) 326 (subsume (f64const $F64 r))) 327 328(rule (simplify (fdiv $F32 (f32const $F32 lhs) (f32const $F32 rhs))) 329 (if-let r (f32_div lhs rhs)) 330 (subsume (f32const $F32 r))) 331(rule (simplify (fdiv $F64 (f64const $F64 lhs) (f64const $F64 rhs))) 332 (if-let r (f64_div lhs rhs)) 333 (subsume (f64const $F64 r))) 334 335(rule (simplify (sqrt $F32 (f32const $F32 n))) 336 (if-let r (f32_sqrt n)) 337 (subsume (f32const $F32 r))) 338(rule (simplify (sqrt $F64 (f64const $F64 n))) 339 (if-let r (f64_sqrt n)) 340 (subsume (f64const $F64 r))) 341 342(rule (simplify (ceil $F32 (f32const $F32 n))) 343 (if-let r (f32_ceil n)) 344 (subsume (f32const $F32 r))) 345(rule (simplify (ceil $F64 (f64const $F64 n))) 346 (if-let r (f64_ceil n)) 347 (subsume (f64const $F64 r))) 348 349(rule (simplify (floor $F32 (f32const $F32 n))) 350 (if-let r (f32_floor n)) 351 (subsume (f32const $F32 r))) 352(rule (simplify (floor $F64 (f64const $F64 n))) 353 (if-let r (f64_floor n)) 354 (subsume (f64const $F64 r))) 355 356(rule (simplify (trunc $F32 (f32const $F32 n))) 357 (if-let r (f32_trunc n)) 358 (subsume (f32const $F32 r))) 359(rule (simplify (trunc $F64 (f64const $F64 n))) 360 (if-let r (f64_trunc n)) 361 (subsume (f64const $F64 r))) 362 363(rule (simplify (nearest $F32 (f32const $F32 n))) 364 (if-let r (f32_nearest n)) 365 (subsume (f32const $F32 r))) 366(rule (simplify (nearest $F64 (f64const $F64 n))) 367 (if-let r (f64_nearest n)) 368 (subsume (f64const $F64 r))) 369 370(rule (simplify (fmin $F16 (f16const $F16 n) (f16const $F16 m))) 371 (if-let r (f16_min n m)) 372 (subsume (f16const $F32 r))) 373(rule (simplify (fmin $F32 (f32const $F32 n) (f32const $F32 m))) 374 (if-let r (f32_min n m)) 375 (subsume (f32const $F32 r))) 376(rule (simplify (fmin $F64 (f64const $F64 n) (f64const $F64 m))) 377 (if-let r (f64_min n m)) 378 (subsume (f64const $F64 r))) 379(rule (simplify (fmin $F128 (f128const $F128 (ieee128_constant n)) (f128const $F128 (ieee128_constant m)))) 380 (if-let r (f128_min n m)) 381 (subsume (f128const $F128 (ieee128_constant r)))) 382 383(rule (simplify (fmax $F16 (f16const $F16 n) (f16const $F16 m))) 384 (if-let r (f16_max n m)) 385 (subsume (f16const $F16 r))) 386(rule (simplify (fmax $F32 (f32const $F32 n) (f32const $F32 m))) 387 (if-let r (f32_max n m)) 388 (subsume (f32const $F32 r))) 389(rule (simplify (fmax $F64 (f64const $F64 n) (f64const $F64 m))) 390 (if-let r (f64_max n m)) 391 (subsume (f64const $F64 r))) 392(rule (simplify (fmax $F128 (f128const $F128 (ieee128_constant n)) (f128const $F128 (ieee128_constant m)))) 393 (if-let r (f128_max n m)) 394 (subsume (f128const $F128 (ieee128_constant r)))) 395 396(rule (simplify (fneg $F16 (f16const $F16 n))) 397 (subsume (f16const $F16 (f16_neg n)))) 398(rule (simplify (fneg $F32 (f32const $F32 n))) 399 (subsume (f32const $F32 (f32_neg n)))) 400(rule (simplify (fneg $F64 (f64const $F64 n))) 401 (subsume (f64const $F64 (f64_neg n)))) 402(rule (simplify (fneg $F128 (f128const $F128 (ieee128_constant n)))) 403 (subsume (f128const $F128 (ieee128_constant (f128_neg n))))) 404 405(rule (simplify (fabs $F16 (f16const $F16 n))) 406 (subsume (f16const $F16 (f16_abs n)))) 407(rule (simplify (fabs $F32 (f32const $F32 n))) 408 (subsume (f32const $F32 (f32_abs n)))) 409(rule (simplify (fabs $F64 (f64const $F64 n))) 410 (subsume (f64const $F64 (f64_abs n)))) 411(rule (simplify (fabs $F128 (f128const $F128 (ieee128_constant n)))) 412 (subsume (f128const $F128 (ieee128_constant (f128_abs n))))) 413 414(rule (simplify (fcopysign $F16 (f16const $F16 n) (f16const $F16 m))) 415 (subsume (f16const $F16 (f16_copysign n m)))) 416(rule (simplify (fcopysign $F32 (f32const $F32 n) (f32const $F32 m))) 417 (subsume (f32const $F32 (f32_copysign n m)))) 418(rule (simplify (fcopysign $F64 (f64const $F64 n) (f64const $F64 m))) 419 (subsume (f64const $F64 (f64_copysign n m)))) 420(rule (simplify (fcopysign $F128 (f128const $F128 (ieee128_constant n)) (f128const $F128 (ieee128_constant m)))) 421 (subsume (f128const $F128 (ieee128_constant (f128_copysign n m))))) 422 423(decl ieee128_constant (Ieee128) Constant) 424(extern constructor ieee128_constant ieee128_constant) 425(extern extractor ieee128_constant ieee128_constant_extractor) 426