xref: /llvm-project/llvm/test/CodeGen/AArch64/addsub_ext.ll (revision 7d42eb3af7792fc3e8429f8a1581fd8c7dc5e7f5)
1; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
2; RUN: llc -debugify-and-strip-all-safe -enable-machine-outliner=never -verify-machineinstrs %s -o - -mtriple=aarch64-linux-gnu -aarch64-enable-atomic-cfg-tidy=0 | FileCheck %s
3; RUN: llc -debugify-and-strip-all-safe -global-isel -enable-machine-outliner=never -verify-machineinstrs %s -o - -mtriple=aarch64-linux-gnu -aarch64-enable-atomic-cfg-tidy=0 | FileCheck %s
4
5define i32 @add_z_i8i32(i8 %v, i32 %lhs) minsize {
6; CHECK-LABEL: add_z_i8i32:
7; CHECK:       // %bb.0:
8; CHECK-NEXT:    add w0, w1, w0, uxtb
9; CHECK-NEXT:    ret
10  %vz = zext i8 %v to i32
11  %r = add i32 %lhs, %vz
12  ret i32 %r
13}
14
15define i32 @add_z_shli8i32(i8 %v, i32 %lhs) minsize {
16; CHECK-LABEL: add_z_shli8i32:
17; CHECK:       // %bb.0:
18; CHECK-NEXT:    add w0, w1, w0, uxtb #3
19; CHECK-NEXT:    ret
20  %vz = zext i8 %v to i32
21  %s = shl i32 %vz, 3
22  %r = add i32 %lhs, %s
23  ret i32 %r
24}
25
26define i64 @add_z_i8i64(i8 %v, i64 %lhs) minsize {
27; CHECK-LABEL: add_z_i8i64:
28; CHECK:       // %bb.0:
29; CHECK-NEXT:    // kill: def $w0 killed $w0 def $x0
30; CHECK-NEXT:    add x0, x1, w0, uxtb
31; CHECK-NEXT:    ret
32  %vz = zext i8 %v to i64
33  %r = add i64 %lhs, %vz
34  ret i64 %r
35}
36
37define i64 @add_z_shli8i64(i8 %v, i64 %lhs) minsize {
38; CHECK-LABEL: add_z_shli8i64:
39; CHECK:       // %bb.0:
40; CHECK-NEXT:    // kill: def $w0 killed $w0 def $x0
41; CHECK-NEXT:    add x0, x1, w0, uxtb #3
42; CHECK-NEXT:    ret
43  %vz = zext i8 %v to i64
44  %s = shl i64 %vz, 3
45  %r = add i64 %lhs, %s
46  ret i64 %r
47}
48
49define i32 @add_s_i8i32(i8 %v, i32 %lhs) minsize {
50; CHECK-LABEL: add_s_i8i32:
51; CHECK:       // %bb.0:
52; CHECK-NEXT:    add w0, w1, w0, sxtb
53; CHECK-NEXT:    ret
54  %vz = sext i8 %v to i32
55  %r = add i32 %lhs, %vz
56  ret i32 %r
57}
58
59define i32 @add_s_shli8i32(i8 %v, i32 %lhs) minsize {
60; CHECK-LABEL: add_s_shli8i32:
61; CHECK:       // %bb.0:
62; CHECK-NEXT:    add w0, w1, w0, sxtb #3
63; CHECK-NEXT:    ret
64  %vz = sext i8 %v to i32
65  %s = shl i32 %vz, 3
66  %r = add i32 %lhs, %s
67  ret i32 %r
68}
69
70define i64 @add_s_i8i64(i8 %v, i64 %lhs) minsize {
71; CHECK-LABEL: add_s_i8i64:
72; CHECK:       // %bb.0:
73; CHECK-NEXT:    // kill: def $w0 killed $w0 def $x0
74; CHECK-NEXT:    add x0, x1, w0, sxtb
75; CHECK-NEXT:    ret
76  %vz = sext i8 %v to i64
77  %r = add i64 %lhs, %vz
78  ret i64 %r
79}
80
81define i64 @add_s_shli8i64(i8 %v, i64 %lhs) minsize {
82; CHECK-LABEL: add_s_shli8i64:
83; CHECK:       // %bb.0:
84; CHECK-NEXT:    // kill: def $w0 killed $w0 def $x0
85; CHECK-NEXT:    add x0, x1, w0, sxtb #3
86; CHECK-NEXT:    ret
87  %vz = sext i8 %v to i64
88  %s = shl i64 %vz, 3
89  %r = add i64 %lhs, %s
90  ret i64 %r
91}
92
93define i32 @add_z_i16i32(i16 %v, i32 %lhs) minsize {
94; CHECK-LABEL: add_z_i16i32:
95; CHECK:       // %bb.0:
96; CHECK-NEXT:    add w0, w1, w0, uxth
97; CHECK-NEXT:    ret
98  %vz = zext i16 %v to i32
99  %r = add i32 %lhs, %vz
100  ret i32 %r
101}
102
103define i32 @add_z_shli16i32(i16 %v, i32 %lhs) minsize {
104; CHECK-LABEL: add_z_shli16i32:
105; CHECK:       // %bb.0:
106; CHECK-NEXT:    add w0, w1, w0, uxth #3
107; CHECK-NEXT:    ret
108  %vz = zext i16 %v to i32
109  %s = shl i32 %vz, 3
110  %r = add i32 %lhs, %s
111  ret i32 %r
112}
113
114define i64 @add_z_i16i64(i16 %v, i64 %lhs) minsize {
115; CHECK-LABEL: add_z_i16i64:
116; CHECK:       // %bb.0:
117; CHECK-NEXT:    // kill: def $w0 killed $w0 def $x0
118; CHECK-NEXT:    add x0, x1, w0, uxth
119; CHECK-NEXT:    ret
120  %vz = zext i16 %v to i64
121  %r = add i64 %lhs, %vz
122  ret i64 %r
123}
124
125define i64 @add_z_shli16i64(i16 %v, i64 %lhs) minsize {
126; CHECK-LABEL: add_z_shli16i64:
127; CHECK:       // %bb.0:
128; CHECK-NEXT:    // kill: def $w0 killed $w0 def $x0
129; CHECK-NEXT:    add x0, x1, w0, uxth #3
130; CHECK-NEXT:    ret
131  %vz = zext i16 %v to i64
132  %s = shl i64 %vz, 3
133  %r = add i64 %lhs, %s
134  ret i64 %r
135}
136
137define i64 @add_z_i32i64(i32 %v, i64 %lhs) minsize {
138; CHECK-LABEL: add_z_i32i64:
139; CHECK:       // %bb.0:
140; CHECK-NEXT:    add x0, x1, w0, uxtw
141; CHECK-NEXT:    ret
142  %vz = zext i32 %v to i64
143  %r = add i64 %lhs, %vz
144  ret i64 %r
145}
146
147define i64 @add_z_shli32i64(i32 %v, i64 %lhs) minsize {
148; CHECK-LABEL: add_z_shli32i64:
149; CHECK:       // %bb.0:
150; CHECK-NEXT:    add x0, x1, w0, uxtw #3
151; CHECK-NEXT:    ret
152  %vz = zext i32 %v to i64
153  %s = shl i64 %vz, 3
154  %r = add i64 %lhs, %s
155  ret i64 %r
156}
157
158define i32 @add_s_i16i32(i16 %v, i32 %lhs) minsize {
159; CHECK-LABEL: add_s_i16i32:
160; CHECK:       // %bb.0:
161; CHECK-NEXT:    add w0, w1, w0, sxth
162; CHECK-NEXT:    ret
163  %vz = sext i16 %v to i32
164  %r = add i32 %lhs, %vz
165  ret i32 %r
166}
167
168define i32 @add_s_shli16i32(i16 %v, i32 %lhs) minsize {
169; CHECK-LABEL: add_s_shli16i32:
170; CHECK:       // %bb.0:
171; CHECK-NEXT:    add w0, w1, w0, sxth #3
172; CHECK-NEXT:    ret
173  %vz = sext i16 %v to i32
174  %s = shl i32 %vz, 3
175  %r = add i32 %lhs, %s
176  ret i32 %r
177}
178
179define i64 @add_s_i16i64(i16 %v, i64 %lhs) minsize {
180; CHECK-LABEL: add_s_i16i64:
181; CHECK:       // %bb.0:
182; CHECK-NEXT:    // kill: def $w0 killed $w0 def $x0
183; CHECK-NEXT:    add x0, x1, w0, sxth
184; CHECK-NEXT:    ret
185  %vz = sext i16 %v to i64
186  %r = add i64 %lhs, %vz
187  ret i64 %r
188}
189
190define i64 @add_s_shli16i64(i16 %v, i64 %lhs) minsize {
191; CHECK-LABEL: add_s_shli16i64:
192; CHECK:       // %bb.0:
193; CHECK-NEXT:    // kill: def $w0 killed $w0 def $x0
194; CHECK-NEXT:    add x0, x1, w0, sxth #3
195; CHECK-NEXT:    ret
196  %vz = sext i16 %v to i64
197  %s = shl i64 %vz, 3
198  %r = add i64 %lhs, %s
199  ret i64 %r
200}
201
202define i64 @add_s_i32i64(i32 %v, i64 %lhs) minsize {
203; CHECK-LABEL: add_s_i32i64:
204; CHECK:       // %bb.0:
205; CHECK-NEXT:    add x0, x1, w0, sxtw
206; CHECK-NEXT:    ret
207  %vz = sext i32 %v to i64
208  %r = add i64 %lhs, %vz
209  ret i64 %r
210}
211
212define i64 @add_s_shli32i64(i32 %v, i64 %lhs) minsize {
213; CHECK-LABEL: add_s_shli32i64:
214; CHECK:       // %bb.0:
215; CHECK-NEXT:    add x0, x1, w0, sxtw #3
216; CHECK-NEXT:    ret
217  %vz = sext i32 %v to i64
218  %s = shl i64 %vz, 3
219  %r = add i64 %lhs, %s
220  ret i64 %r
221}
222
223define i32 @sub_z_i8i32(i8 %v, i32 %lhs) minsize {
224; CHECK-LABEL: sub_z_i8i32:
225; CHECK:       // %bb.0:
226; CHECK-NEXT:    sub w0, w1, w0, uxtb
227; CHECK-NEXT:    ret
228  %vz = zext i8 %v to i32
229  %r = sub i32 %lhs, %vz
230  ret i32 %r
231}
232
233define i32 @sub_z_shli8i32(i8 %v, i32 %lhs) minsize {
234; CHECK-LABEL: sub_z_shli8i32:
235; CHECK:       // %bb.0:
236; CHECK-NEXT:    sub w0, w1, w0, uxtb #3
237; CHECK-NEXT:    ret
238  %vz = zext i8 %v to i32
239  %s = shl i32 %vz, 3
240  %r = sub i32 %lhs, %s
241  ret i32 %r
242}
243
244define i64 @sub_z_i8i64(i8 %v, i64 %lhs) minsize {
245; CHECK-LABEL: sub_z_i8i64:
246; CHECK:       // %bb.0:
247; CHECK-NEXT:    // kill: def $w0 killed $w0 def $x0
248; CHECK-NEXT:    sub x0, x1, w0, uxtb
249; CHECK-NEXT:    ret
250  %vz = zext i8 %v to i64
251  %r = sub i64 %lhs, %vz
252  ret i64 %r
253}
254
255define i64 @sub_z_shli8i64(i8 %v, i64 %lhs) minsize {
256; CHECK-LABEL: sub_z_shli8i64:
257; CHECK:       // %bb.0:
258; CHECK-NEXT:    // kill: def $w0 killed $w0 def $x0
259; CHECK-NEXT:    sub x0, x1, w0, uxtb #3
260; CHECK-NEXT:    ret
261  %vz = zext i8 %v to i64
262  %s = shl i64 %vz, 3
263  %r = sub i64 %lhs, %s
264  ret i64 %r
265}
266
267define i32 @sub_s_i8i32(i8 %v, i32 %lhs) minsize {
268; CHECK-LABEL: sub_s_i8i32:
269; CHECK:       // %bb.0:
270; CHECK-NEXT:    sub w0, w1, w0, sxtb
271; CHECK-NEXT:    ret
272  %vz = sext i8 %v to i32
273  %r = sub i32 %lhs, %vz
274  ret i32 %r
275}
276
277define i32 @sub_s_shli8i32(i8 %v, i32 %lhs) minsize {
278; CHECK-LABEL: sub_s_shli8i32:
279; CHECK:       // %bb.0:
280; CHECK-NEXT:    sub w0, w1, w0, sxtb #3
281; CHECK-NEXT:    ret
282  %vz = sext i8 %v to i32
283  %s = shl i32 %vz, 3
284  %r = sub i32 %lhs, %s
285  ret i32 %r
286}
287
288define i64 @sub_s_i8i64(i8 %v, i64 %lhs) minsize {
289; CHECK-LABEL: sub_s_i8i64:
290; CHECK:       // %bb.0:
291; CHECK-NEXT:    // kill: def $w0 killed $w0 def $x0
292; CHECK-NEXT:    sub x0, x1, w0, sxtb
293; CHECK-NEXT:    ret
294  %vz = sext i8 %v to i64
295  %r = sub i64 %lhs, %vz
296  ret i64 %r
297}
298
299define i64 @sub_s_shli8i64(i8 %v, i64 %lhs) minsize {
300; CHECK-LABEL: sub_s_shli8i64:
301; CHECK:       // %bb.0:
302; CHECK-NEXT:    // kill: def $w0 killed $w0 def $x0
303; CHECK-NEXT:    sub x0, x1, w0, sxtb #3
304; CHECK-NEXT:    ret
305  %vz = sext i8 %v to i64
306  %s = shl i64 %vz, 3
307  %r = sub i64 %lhs, %s
308  ret i64 %r
309}
310
311define i32 @sub_z_i16i32(i16 %v, i32 %lhs) minsize {
312; CHECK-LABEL: sub_z_i16i32:
313; CHECK:       // %bb.0:
314; CHECK-NEXT:    sub w0, w1, w0, uxth
315; CHECK-NEXT:    ret
316  %vz = zext i16 %v to i32
317  %r = sub i32 %lhs, %vz
318  ret i32 %r
319}
320
321define i32 @sub_z_shli16i32(i16 %v, i32 %lhs) minsize {
322; CHECK-LABEL: sub_z_shli16i32:
323; CHECK:       // %bb.0:
324; CHECK-NEXT:    sub w0, w1, w0, uxth #3
325; CHECK-NEXT:    ret
326  %vz = zext i16 %v to i32
327  %s = shl i32 %vz, 3
328  %r = sub i32 %lhs, %s
329  ret i32 %r
330}
331
332define i64 @sub_z_i16i64(i16 %v, i64 %lhs) minsize {
333; CHECK-LABEL: sub_z_i16i64:
334; CHECK:       // %bb.0:
335; CHECK-NEXT:    // kill: def $w0 killed $w0 def $x0
336; CHECK-NEXT:    sub x0, x1, w0, uxth
337; CHECK-NEXT:    ret
338  %vz = zext i16 %v to i64
339  %r = sub i64 %lhs, %vz
340  ret i64 %r
341}
342
343define i64 @sub_z_shli16i64(i16 %v, i64 %lhs) minsize {
344; CHECK-LABEL: sub_z_shli16i64:
345; CHECK:       // %bb.0:
346; CHECK-NEXT:    // kill: def $w0 killed $w0 def $x0
347; CHECK-NEXT:    sub x0, x1, w0, uxth #3
348; CHECK-NEXT:    ret
349  %vz = zext i16 %v to i64
350  %s = shl i64 %vz, 3
351  %r = sub i64 %lhs, %s
352  ret i64 %r
353}
354
355define i64 @sub_z_i32i64(i32 %v, i64 %lhs) minsize {
356; CHECK-LABEL: sub_z_i32i64:
357; CHECK:       // %bb.0:
358; CHECK-NEXT:    sub x0, x1, w0, uxtw
359; CHECK-NEXT:    ret
360  %vz = zext i32 %v to i64
361  %r = sub i64 %lhs, %vz
362  ret i64 %r
363}
364
365define i64 @sub_z_shli32i64(i32 %v, i64 %lhs) minsize {
366; CHECK-LABEL: sub_z_shli32i64:
367; CHECK:       // %bb.0:
368; CHECK-NEXT:    sub x0, x1, w0, uxtw #3
369; CHECK-NEXT:    ret
370  %vz = zext i32 %v to i64
371  %s = shl i64 %vz, 3
372  %r = sub i64 %lhs, %s
373  ret i64 %r
374}
375
376define i32 @sub_s_i16i32(i16 %v, i32 %lhs) minsize {
377; CHECK-LABEL: sub_s_i16i32:
378; CHECK:       // %bb.0:
379; CHECK-NEXT:    sub w0, w1, w0, sxth
380; CHECK-NEXT:    ret
381  %vz = sext i16 %v to i32
382  %r = sub i32 %lhs, %vz
383  ret i32 %r
384}
385
386define i32 @sub_s_shli16i32(i16 %v, i32 %lhs) minsize {
387; CHECK-LABEL: sub_s_shli16i32:
388; CHECK:       // %bb.0:
389; CHECK-NEXT:    sub w0, w1, w0, sxth #3
390; CHECK-NEXT:    ret
391  %vz = sext i16 %v to i32
392  %s = shl i32 %vz, 3
393  %r = sub i32 %lhs, %s
394  ret i32 %r
395}
396
397define i64 @sub_s_i16i64(i16 %v, i64 %lhs) minsize {
398; CHECK-LABEL: sub_s_i16i64:
399; CHECK:       // %bb.0:
400; CHECK-NEXT:    // kill: def $w0 killed $w0 def $x0
401; CHECK-NEXT:    sub x0, x1, w0, sxth
402; CHECK-NEXT:    ret
403  %vz = sext i16 %v to i64
404  %r = sub i64 %lhs, %vz
405  ret i64 %r
406}
407
408define i64 @sub_s_shli16i64(i16 %v, i64 %lhs) minsize {
409; CHECK-LABEL: sub_s_shli16i64:
410; CHECK:       // %bb.0:
411; CHECK-NEXT:    // kill: def $w0 killed $w0 def $x0
412; CHECK-NEXT:    sub x0, x1, w0, sxth #3
413; CHECK-NEXT:    ret
414  %vz = sext i16 %v to i64
415  %s = shl i64 %vz, 3
416  %r = sub i64 %lhs, %s
417  ret i64 %r
418}
419
420define i64 @sub_s_i32i64(i32 %v, i64 %lhs) minsize {
421; CHECK-LABEL: sub_s_i32i64:
422; CHECK:       // %bb.0:
423; CHECK-NEXT:    sub x0, x1, w0, sxtw
424; CHECK-NEXT:    ret
425  %vz = sext i32 %v to i64
426  %r = sub i64 %lhs, %vz
427  ret i64 %r
428}
429
430define i64 @sub_s_shli32i64(i32 %v, i64 %lhs) minsize {
431; CHECK-LABEL: sub_s_shli32i64:
432; CHECK:       // %bb.0:
433; CHECK-NEXT:    sub x0, x1, w0, sxtw #3
434; CHECK-NEXT:    ret
435  %vz = sext i32 %v to i64
436  %s = shl i64 %vz, 3
437  %r = sub i64 %lhs, %s
438  ret i64 %r
439}
440
441define i32 @cmp_s_i8i32(i8 %v, i32 %lhs) minsize {
442; CHECK-LABEL: cmp_s_i8i32:
443; CHECK:       // %bb.0:
444; CHECK-NEXT:    cmp w1, w0, uxtb
445; CHECK-NEXT:    b.ge .LBB40_2
446; CHECK-NEXT:  // %bb.1: // %then
447; CHECK-NEXT:    mov w0, #1
448; CHECK-NEXT:    ret
449; CHECK-NEXT:  .LBB40_2: // %end
450; CHECK-NEXT:    mov w0, w1
451; CHECK-NEXT:    ret
452  %vz = zext i8 %v to i32
453  %c = icmp slt i32 %lhs, %vz
454  br i1 %c, label %then, label %end
455then:
456  ret i32 1
457end:
458  ret i32 %lhs
459}
460
461define i64 @cmp_s_i8i64(i8 %v, i64 %lhs) minsize {
462; CHECK-LABEL: cmp_s_i8i64:
463; CHECK:       // %bb.0:
464; CHECK-NEXT:    // kill: def $w0 killed $w0 def $x0
465; CHECK-NEXT:    cmp x1, w0, sxtb
466; CHECK-NEXT:    b.ge .LBB41_2
467; CHECK-NEXT:  // %bb.1: // %then
468; CHECK-NEXT:    mov w0, #1
469; CHECK-NEXT:    ret
470; CHECK-NEXT:  .LBB41_2: // %end
471; CHECK-NEXT:    mov x0, x1
472; CHECK-NEXT:    ret
473  %vz = sext i8 %v to i64
474  %c = icmp slt i64 %lhs, %vz
475  br i1 %c, label %then, label %end
476then:
477  ret i64 1
478end:
479  ret i64 %lhs
480}
481
482define i32 @cmp_s_i16i32(i16 %v, i32 %lhs) minsize {
483; CHECK-LABEL: cmp_s_i16i32:
484; CHECK:       // %bb.0:
485; CHECK-NEXT:    cmp w1, w0, uxth
486; CHECK-NEXT:    b.ge .LBB42_2
487; CHECK-NEXT:  // %bb.1: // %then
488; CHECK-NEXT:    mov w0, #1
489; CHECK-NEXT:    ret
490; CHECK-NEXT:  .LBB42_2: // %end
491; CHECK-NEXT:    mov w0, w1
492; CHECK-NEXT:    ret
493  %vz = zext i16 %v to i32
494  %c = icmp slt i32 %lhs, %vz
495  br i1 %c, label %then, label %end
496then:
497  ret i32 1
498end:
499  ret i32 %lhs
500}
501
502define i64 @cmp_s_i16i64(i16 %v, i64 %lhs) minsize {
503; CHECK-LABEL: cmp_s_i16i64:
504; CHECK:       // %bb.0:
505; CHECK-NEXT:    // kill: def $w0 killed $w0 def $x0
506; CHECK-NEXT:    cmp x1, w0, sxth
507; CHECK-NEXT:    b.ge .LBB43_2
508; CHECK-NEXT:  // %bb.1: // %then
509; CHECK-NEXT:    mov w0, #1
510; CHECK-NEXT:    ret
511; CHECK-NEXT:  .LBB43_2: // %end
512; CHECK-NEXT:    mov x0, x1
513; CHECK-NEXT:    ret
514  %vz = sext i16 %v to i64
515  %c = icmp slt i64 %lhs, %vz
516  br i1 %c, label %then, label %end
517then:
518  ret i64 1
519end:
520  ret i64 %lhs
521}
522
523
524; Check that implicit zext from w reg write is used instead of uxtw form of add.
525define dso_local i64 @add_fold_uxtw(i32 %x, i64 %y) {
526; CHECK-LABEL: add_fold_uxtw:
527; CHECK:       // %bb.0: // %entry
528; CHECK-NEXT:    and w8, w0, #0x3
529; CHECK-NEXT:    add x0, x1, x8
530; CHECK-NEXT:    ret
531entry:
532  %m = and i32 %x, 3
533  %ext = zext i32 %m to i64
534  %ret = add i64 %y, %ext
535  ret i64 %ret
536}
537
538; Check that implicit zext from w reg write is used instead of uxtw
539; form of sub and that mov WZR is folded to form a neg instruction.
540define dso_local i64 @sub_fold_uxtw_xzr(i32 %x)  {
541; CHECK-LABEL: sub_fold_uxtw_xzr:
542; CHECK:       // %bb.0: // %entry
543; CHECK-NEXT:    and w8, w0, #0x3
544; CHECK-NEXT:    neg x0, x8
545; CHECK-NEXT:    ret
546entry:
547  %m = and i32 %x, 3
548  %ext = zext i32 %m to i64
549  %ret = sub i64 0, %ext
550  ret i64 %ret
551}
552
553; Check that implicit zext from w reg write is used instead of uxtw form of subs/cmp.
554define dso_local i1 @cmp_fold_uxtw(i32 %x, i64 %y) {
555; CHECK-LABEL: cmp_fold_uxtw:
556; CHECK:       // %bb.0: // %entry
557; CHECK-NEXT:    and w8, w0, #0x3
558; CHECK-NEXT:    cmp x1, x8
559; CHECK-NEXT:    cset w0, eq
560; CHECK-NEXT:    ret
561entry:
562  %m = and i32 %x, 3
563  %ext = zext i32 %m to i64
564  %ret = icmp eq i64 %y, %ext
565  ret i1 %ret
566}
567
568; Check that implicit zext from w reg write is used instead of uxtw
569; form of add, leading to madd selection.
570define dso_local i64 @madd_fold_uxtw(i32 %x, i64 %y) {
571; CHECK-LABEL: madd_fold_uxtw:
572; CHECK:       // %bb.0: // %entry
573; CHECK-NEXT:    and w8, w0, #0x3
574; CHECK-NEXT:    madd x0, x1, x1, x8
575; CHECK-NEXT:    ret
576entry:
577  %m = and i32 %x, 3
578  %ext = zext i32 %m to i64
579  %mul = mul i64 %y, %y
580  %ret = add i64 %mul, %ext
581  ret i64 %ret
582}
583
584; Check that implicit zext from w reg write is used instead of uxtw
585; form of sub, leading to sub/cmp folding.
586; Check that implicit zext from w reg write is used instead of uxtw form of subs/cmp.
587define dso_local i1 @cmp_sub_fold_uxtw(i32 %x, i64 %y, i64 %z) {
588; CHECK-LABEL: cmp_sub_fold_uxtw:
589; CHECK:       // %bb.0: // %entry
590; CHECK-NEXT:    and w8, w0, #0x3
591; CHECK-NEXT:    cmp x2, x8
592; CHECK-NEXT:    cset w0, eq
593; CHECK-NEXT:    ret
594entry:
595  %m = and i32 %x, 3
596  %ext = zext i32 %m to i64
597  %sub = sub i64 %z, %ext
598  %ret = icmp eq i64 %sub, 0
599  ret i1 %ret
600}
601
602; Check that implicit zext from w reg write is used instead of uxtw
603; form of add and add of -1 gets selected as sub.
604define dso_local i64 @add_imm_fold_uxtw(i32 %x) {
605; CHECK-LABEL: add_imm_fold_uxtw:
606; CHECK:       // %bb.0: // %entry
607; CHECK-NEXT:    and w8, w0, #0x3
608; CHECK-NEXT:    sub x0, x8, #1
609; CHECK-NEXT:    ret
610entry:
611  %m = and i32 %x, 3
612  %ext = zext i32 %m to i64
613  %ret = add i64 %ext, -1
614  ret i64 %ret
615}
616
617; Check that implicit zext from w reg write is used instead of uxtw
618; form of add and add lsl form gets selected.
619define dso_local i64 @add_lsl_fold_uxtw(i32 %x, i64 %y) {
620; CHECK-LABEL: add_lsl_fold_uxtw:
621; CHECK:       // %bb.0: // %entry
622; CHECK-NEXT:    orr w8, w0, #0x3
623; CHECK-NEXT:    add x0, x8, x1, lsl #3
624; CHECK-NEXT:    ret
625entry:
626  %m = or i32 %x, 3
627  %ext = zext i32 %m to i64
628  %shift = shl i64 %y, 3
629  %ret = add i64 %ext, %shift
630  ret i64 %ret
631}
632