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