1; RUN: llc -enable-machine-outliner=never -verify-machineinstrs %s -o - -mtriple=aarch64-linux-gnu -aarch64-enable-atomic-cfg-tidy=0 | FileCheck %s
2; RUN: llc -global-isel -enable-machine-outliner=never -verify-machineinstrs %s -o - -mtriple=aarch64-linux-gnu -aarch64-enable-atomic-cfg-tidy=0 | FileCheck %s --check-prefix=GISEL
3
4; FIXME: GISel only knows how to handle explicit G_SEXT instructions. So when
5; G_SEXT is lowered to anything else, it won't fold in a stx*.
6; FIXME: GISel doesn't currently handle folding the addressing mode into a cmp.
7
8@var8 = global i8 0
9@var16 = global i16 0
10@var32 = global i32 0
11@var64 = global i64 0
12
13define void @addsub_i8rhs() minsize {
14; CHECK-LABEL: addsub_i8rhs:
15; GISEL-LABEL: addsub_i8rhs:
16    %val8_tmp = load i8, i8* @var8
17    %lhs32 = load i32, i32* @var32
18    %lhs64 = load i64, i64* @var64
19
20    ; Need this to prevent extension upon load and give a vanilla i8 operand.
21    %val8 = add i8 %val8_tmp, 123
22
23
24; Zero-extending to 32-bits
25    %rhs32_zext = zext i8 %val8 to i32
26    %res32_zext = add i32 %lhs32, %rhs32_zext
27    store volatile i32 %res32_zext, i32* @var32
28; CHECK: add {{w[0-9]+}}, {{w[0-9]+}}, {{w[0-9]+}}, uxtb
29; GISEL: add {{w[0-9]+}}, {{w[0-9]+}}, {{w[0-9]+}}, uxtb
30
31   %rhs32_zext_shift = shl i32 %rhs32_zext, 3
32   %res32_zext_shift = add i32 %lhs32, %rhs32_zext_shift
33   store volatile i32 %res32_zext_shift, i32* @var32
34; CHECK: add {{w[0-9]+}}, {{w[0-9]+}}, {{w[0-9]+}}, uxtb #3
35; GISEL: add {{w[0-9]+}}, {{w[0-9]+}}, {{w[0-9]+}}, uxtb #3
36
37; Zero-extending to 64-bits
38    %rhs64_zext = zext i8 %val8 to i64
39    %res64_zext = add i64 %lhs64, %rhs64_zext
40    store volatile i64 %res64_zext, i64* @var64
41; CHECK: add {{x[0-9]+}}, {{x[0-9]+}}, {{w[0-9]+}}, uxtb
42; GISEL: add {{x[0-9]+}}, {{x[0-9]+}}, {{w[0-9]+}}, uxtb
43
44   %rhs64_zext_shift = shl i64 %rhs64_zext, 1
45   %res64_zext_shift = add i64 %lhs64, %rhs64_zext_shift
46   store volatile i64 %res64_zext_shift, i64* @var64
47; CHECK: add {{x[0-9]+}}, {{x[0-9]+}}, {{w[0-9]+}}, uxtb #1
48; GISEL: add {{x[0-9]+}}, {{x[0-9]+}}, {{w[0-9]+}}, uxtb #1
49
50; Sign-extending to 32-bits
51    %rhs32_sext = sext i8 %val8 to i32
52    %res32_sext = add i32 %lhs32, %rhs32_sext
53    store volatile i32 %res32_sext, i32* @var32
54; CHECK: add {{w[0-9]+}}, {{w[0-9]+}}, {{w[0-9]+}}, sxtb
55
56   %rhs32_sext_shift = shl i32 %rhs32_sext, 1
57   %res32_sext_shift = add i32 %lhs32, %rhs32_sext_shift
58   store volatile i32 %res32_sext_shift, i32* @var32
59; CHECK: add {{w[0-9]+}}, {{w[0-9]+}}, {{w[0-9]+}}, sxtb #1
60
61; Sign-extending to 64-bits
62    %rhs64_sext = sext i8 %val8 to i64
63    %res64_sext = add i64 %lhs64, %rhs64_sext
64    store volatile i64 %res64_sext, i64* @var64
65; CHECK: add {{x[0-9]+}}, {{x[0-9]+}}, {{w[0-9]+}}, sxtb
66
67   %rhs64_sext_shift = shl i64 %rhs64_sext, 4
68   %res64_sext_shift = add i64 %lhs64, %rhs64_sext_shift
69   store volatile i64 %res64_sext_shift, i64* @var64
70; CHECK: add {{x[0-9]+}}, {{x[0-9]+}}, {{w[0-9]+}}, sxtb #4
71
72
73; CMP variants
74    %tst = icmp slt i32 %lhs32, %rhs32_zext
75    br i1 %tst, label %end, label %test2
76; CHECK: cmp {{w[0-9]+}}, {{w[0-9]+}}, uxtb
77
78test2:
79    %cmp_sext = sext i8 %val8 to i64
80    %tst2 = icmp eq i64 %lhs64, %cmp_sext
81    br i1 %tst2, label %other, label %end
82; CHECK: cmp {{x[0-9]+}}, {{w[0-9]+}}, sxtb
83
84other:
85    store volatile i32 %lhs32, i32* @var32
86    ret void
87
88end:
89    ret void
90}
91
92define void @sub_i8rhs() minsize {
93; CHECK-LABEL: sub_i8rhs:
94    %val8_tmp = load i8, i8* @var8
95    %lhs32 = load i32, i32* @var32
96    %lhs64 = load i64, i64* @var64
97
98    ; Need this to prevent extension upon load and give a vanilla i8 operand.
99    %val8 = add i8 %val8_tmp, 123
100
101
102; Zero-extending to 32-bits
103    %rhs32_zext = zext i8 %val8 to i32
104    %res32_zext = sub i32 %lhs32, %rhs32_zext
105    store volatile i32 %res32_zext, i32* @var32
106; CHECK: sub {{w[0-9]+}}, {{w[0-9]+}}, {{w[0-9]+}}, uxtb
107; GISEL: subs {{w[0-9]+}}, {{w[0-9]+}}, {{w[0-9]+}}, uxtb
108
109   %rhs32_zext_shift = shl i32 %rhs32_zext, 3
110   %res32_zext_shift = sub i32 %lhs32, %rhs32_zext_shift
111   store volatile i32 %res32_zext_shift, i32* @var32
112; CHECK: sub {{w[0-9]+}}, {{w[0-9]+}}, {{w[0-9]+}}, uxtb #3
113; GISEL: subs {{w[0-9]+}}, {{w[0-9]+}}, {{w[0-9]+}}, uxtb #3
114
115; Zero-extending to 64-bits
116    %rhs64_zext = zext i8 %val8 to i64
117    %res64_zext = sub i64 %lhs64, %rhs64_zext
118    store volatile i64 %res64_zext, i64* @var64
119; CHECK: sub {{x[0-9]+}}, {{x[0-9]+}}, {{w[0-9]+}}, uxtb
120; GISEL: subs {{x[0-9]+}}, {{x[0-9]+}}, {{w[0-9]+}}, uxtb
121
122   %rhs64_zext_shift = shl i64 %rhs64_zext, 1
123   %res64_zext_shift = sub i64 %lhs64, %rhs64_zext_shift
124   store volatile i64 %res64_zext_shift, i64* @var64
125; CHECK: sub {{x[0-9]+}}, {{x[0-9]+}}, {{w[0-9]+}}, uxtb #1
126; GISEL: subs {{x[0-9]+}}, {{x[0-9]+}}, {{w[0-9]+}}, uxtb #1
127
128; Sign-extending to 32-bits
129    %rhs32_sext = sext i8 %val8 to i32
130    %res32_sext = sub i32 %lhs32, %rhs32_sext
131    store volatile i32 %res32_sext, i32* @var32
132; CHECK: sub {{w[0-9]+}}, {{w[0-9]+}}, {{w[0-9]+}}, sxtb
133
134   %rhs32_sext_shift = shl i32 %rhs32_sext, 1
135   %res32_sext_shift = sub i32 %lhs32, %rhs32_sext_shift
136   store volatile i32 %res32_sext_shift, i32* @var32
137; CHECK: sub {{w[0-9]+}}, {{w[0-9]+}}, {{w[0-9]+}}, sxtb #1
138
139; Sign-extending to 64-bits
140    %rhs64_sext = sext i8 %val8 to i64
141    %res64_sext = sub i64 %lhs64, %rhs64_sext
142    store volatile i64 %res64_sext, i64* @var64
143; CHECK: sub {{x[0-9]+}}, {{x[0-9]+}}, {{w[0-9]+}}, sxtb
144
145   %rhs64_sext_shift = shl i64 %rhs64_sext, 4
146   %res64_sext_shift = sub i64 %lhs64, %rhs64_sext_shift
147   store volatile i64 %res64_sext_shift, i64* @var64
148; CHECK: sub {{x[0-9]+}}, {{x[0-9]+}}, {{w[0-9]+}}, sxtb #4
149
150    ret void
151}
152
153define void @addsub_i16rhs() minsize {
154; CHECK-LABEL: addsub_i16rhs:
155; GISEL-LABEL: addsub_i16rhs:
156    %val16_tmp = load i16, i16* @var16
157    %lhs32 = load i32, i32* @var32
158    %lhs64 = load i64, i64* @var64
159
160    ; Need this to prevent extension upon load and give a vanilla i16 operand.
161    %val16 = add i16 %val16_tmp, 123
162
163
164; Zero-extending to 32-bits
165    %rhs32_zext = zext i16 %val16 to i32
166    %res32_zext = add i32 %lhs32, %rhs32_zext
167    store volatile i32 %res32_zext, i32* @var32
168; CHECK: add {{w[0-9]+}}, {{w[0-9]+}}, {{w[0-9]+}}, uxth
169; GISEL: add {{w[0-9]+}}, {{w[0-9]+}}, {{w[0-9]+}}, uxth
170
171   %rhs32_zext_shift = shl i32 %rhs32_zext, 3
172   %res32_zext_shift = add i32 %lhs32, %rhs32_zext_shift
173   store volatile i32 %res32_zext_shift, i32* @var32
174; CHECK: add {{w[0-9]+}}, {{w[0-9]+}}, {{w[0-9]+}}, uxth #3
175; GISEL: add {{w[0-9]+}}, {{w[0-9]+}}, {{w[0-9]+}}, uxth #3
176
177; Zero-extending to 64-bits
178    %rhs64_zext = zext i16 %val16 to i64
179    %res64_zext = add i64 %lhs64, %rhs64_zext
180    store volatile i64 %res64_zext, i64* @var64
181; CHECK: add {{x[0-9]+}}, {{x[0-9]+}}, {{w[0-9]+}}, uxth
182; GISEL: add {{x[0-9]+}}, {{x[0-9]+}}, {{w[0-9]+}}, uxth
183
184   %rhs64_zext_shift = shl i64 %rhs64_zext, 1
185   %res64_zext_shift = add i64 %lhs64, %rhs64_zext_shift
186   store volatile i64 %res64_zext_shift, i64* @var64
187; CHECK: add {{x[0-9]+}}, {{x[0-9]+}}, {{w[0-9]+}}, uxth #1
188; GISEL: add {{x[0-9]+}}, {{x[0-9]+}}, {{w[0-9]+}}, uxth #1
189
190; Sign-extending to 32-bits
191    %rhs32_sext = sext i16 %val16 to i32
192    %res32_sext = add i32 %lhs32, %rhs32_sext
193    store volatile i32 %res32_sext, i32* @var32
194; CHECK: add {{w[0-9]+}}, {{w[0-9]+}}, {{w[0-9]+}}, sxth
195
196   %rhs32_sext_shift = shl i32 %rhs32_sext, 1
197   %res32_sext_shift = add i32 %lhs32, %rhs32_sext_shift
198   store volatile i32 %res32_sext_shift, i32* @var32
199; CHECK: add {{w[0-9]+}}, {{w[0-9]+}}, {{w[0-9]+}}, sxth #1
200
201; Sign-extending to 64-bits
202    %rhs64_sext = sext i16 %val16 to i64
203    %res64_sext = add i64 %lhs64, %rhs64_sext
204    store volatile i64 %res64_sext, i64* @var64
205; CHECK: add {{x[0-9]+}}, {{x[0-9]+}}, {{w[0-9]+}}, sxth
206
207   %rhs64_sext_shift = shl i64 %rhs64_sext, 4
208   %res64_sext_shift = add i64 %lhs64, %rhs64_sext_shift
209   store volatile i64 %res64_sext_shift, i64* @var64
210; CHECK: add {{x[0-9]+}}, {{x[0-9]+}}, {{w[0-9]+}}, sxth #4
211
212
213; CMP variants
214    %tst = icmp slt i32 %lhs32, %rhs32_zext
215    br i1 %tst, label %end, label %test2
216; CHECK: cmp {{w[0-9]+}}, {{w[0-9]+}}, uxth
217
218test2:
219    %cmp_sext = sext i16 %val16 to i64
220    %tst2 = icmp eq i64 %lhs64, %cmp_sext
221    br i1 %tst2, label %other, label %end
222; CHECK: cmp {{x[0-9]+}}, {{w[0-9]+}}, sxth
223
224other:
225    store volatile i32 %lhs32, i32* @var32
226    ret void
227
228end:
229    ret void
230}
231
232define void @sub_i16rhs() minsize {
233; CHECK-LABEL: sub_i16rhs:
234; GISEL-LABEL: sub_i16rhs:
235    %val16_tmp = load i16, i16* @var16
236    %lhs32 = load i32, i32* @var32
237    %lhs64 = load i64, i64* @var64
238
239    ; Need this to prevent extension upon load and give a vanilla i16 operand.
240    %val16 = add i16 %val16_tmp, 123
241
242
243; Zero-extending to 32-bits
244    %rhs32_zext = zext i16 %val16 to i32
245    %res32_zext = sub i32 %lhs32, %rhs32_zext
246    store volatile i32 %res32_zext, i32* @var32
247; CHECK: sub {{w[0-9]+}}, {{w[0-9]+}}, {{w[0-9]+}}, uxth
248; GISEL: subs {{w[0-9]+}}, {{w[0-9]+}}, {{w[0-9]+}}, uxth
249
250   %rhs32_zext_shift = shl i32 %rhs32_zext, 3
251   %res32_zext_shift = sub i32 %lhs32, %rhs32_zext_shift
252   store volatile i32 %res32_zext_shift, i32* @var32
253; CHECK: sub {{w[0-9]+}}, {{w[0-9]+}}, {{w[0-9]+}}, uxth #3
254; GISEL: subs {{w[0-9]+}}, {{w[0-9]+}}, {{w[0-9]+}}, uxth #3
255
256; Zero-extending to 64-bits
257    %rhs64_zext = zext i16 %val16 to i64
258    %res64_zext = sub i64 %lhs64, %rhs64_zext
259    store volatile i64 %res64_zext, i64* @var64
260; CHECK: sub {{x[0-9]+}}, {{x[0-9]+}}, {{w[0-9]+}}, uxth
261; GISEL: subs {{x[0-9]+}}, {{x[0-9]+}}, {{w[0-9]+}}, uxth
262
263   %rhs64_zext_shift = shl i64 %rhs64_zext, 1
264   %res64_zext_shift = sub i64 %lhs64, %rhs64_zext_shift
265   store volatile i64 %res64_zext_shift, i64* @var64
266; CHECK: sub {{x[0-9]+}}, {{x[0-9]+}}, {{w[0-9]+}}, uxth #1
267; GISEL: subs {{x[0-9]+}}, {{x[0-9]+}}, {{w[0-9]+}}, uxth #1
268
269; Sign-extending to 32-bits
270    %rhs32_sext = sext i16 %val16 to i32
271    %res32_sext = sub i32 %lhs32, %rhs32_sext
272    store volatile i32 %res32_sext, i32* @var32
273; CHECK: sub {{w[0-9]+}}, {{w[0-9]+}}, {{w[0-9]+}}, sxth
274
275   %rhs32_sext_shift = shl i32 %rhs32_sext, 1
276   %res32_sext_shift = sub i32 %lhs32, %rhs32_sext_shift
277   store volatile i32 %res32_sext_shift, i32* @var32
278; CHECK: sub {{w[0-9]+}}, {{w[0-9]+}}, {{w[0-9]+}}, sxth #1
279
280; Sign-extending to 64-bits
281    %rhs64_sext = sext i16 %val16 to i64
282    %res64_sext = sub i64 %lhs64, %rhs64_sext
283    store volatile i64 %res64_sext, i64* @var64
284; CHECK: sub {{x[0-9]+}}, {{x[0-9]+}}, {{w[0-9]+}}, sxth
285
286   %rhs64_sext_shift = shl i64 %rhs64_sext, 4
287   %res64_sext_shift = sub i64 %lhs64, %rhs64_sext_shift
288   store volatile i64 %res64_sext_shift, i64* @var64
289; CHECK: sub {{x[0-9]+}}, {{x[0-9]+}}, {{w[0-9]+}}, sxth #4
290
291    ret void
292}
293
294; N.b. we could probably check more here ("add w2, w3, w1, uxtw" for
295; example), but the remaining instructions are probably not idiomatic
296; in the face of "add/sub (shifted register)" so I don't intend to.
297define void @addsub_i32rhs(i32 %in32) minsize {
298; CHECK-LABEL: addsub_i32rhs:
299; GISEL-LABEL: addsub_i32rhs:
300    %val32_tmp = load i32, i32* @var32
301    %lhs64 = load i64, i64* @var64
302
303    %val32 = add i32 %val32_tmp, 123
304
305    %rhs64_zext = zext i32 %in32 to i64
306    %res64_zext = add i64 %lhs64, %rhs64_zext
307    store volatile i64 %res64_zext, i64* @var64
308; CHECK: add {{x[0-9]+}}, {{x[0-9]+}}, {{w[0-9]+}}, uxtw
309; GISEL: add {{x[0-9]+}}, {{x[0-9]+}}, {{w[0-9]+}}, uxtw
310
311    %rhs64_zext2 = zext i32 %val32 to i64
312    %rhs64_zext_shift = shl i64 %rhs64_zext2, 2
313    %res64_zext_shift = add i64 %lhs64, %rhs64_zext_shift
314    store volatile i64 %res64_zext_shift, i64* @var64
315; CHECK: add {{x[0-9]+}}, {{x[0-9]+}}, {{w[0-9]+}}, uxtw #2
316; GISEL: add {{x[0-9]+}}, {{x[0-9]+}}, {{w[0-9]+}}, uxtw #2
317
318    %rhs64_sext = sext i32 %val32 to i64
319    %res64_sext = add i64 %lhs64, %rhs64_sext
320    store volatile i64 %res64_sext, i64* @var64
321; CHECK: add {{x[0-9]+}}, {{x[0-9]+}}, {{w[0-9]+}}, sxtw
322; GISEL: add {{x[0-9]+}}, {{x[0-9]+}}, {{w[0-9]+}}, sxtw
323
324    %rhs64_sext_shift = shl i64 %rhs64_sext, 2
325    %res64_sext_shift = add i64 %lhs64, %rhs64_sext_shift
326    store volatile i64 %res64_sext_shift, i64* @var64
327; CHECK: add {{x[0-9]+}}, {{x[0-9]+}}, {{w[0-9]+}}, sxtw #2
328; GISEL: add {{x[0-9]+}}, {{x[0-9]+}}, {{w[0-9]+}}, sxtw #2
329
330    ret void
331}
332
333define void @sub_i32rhs(i32 %in32) minsize {
334; CHECK-LABEL: sub_i32rhs:
335    %val32_tmp = load i32, i32* @var32
336    %lhs64 = load i64, i64* @var64
337
338    %val32 = add i32 %val32_tmp, 123
339
340    %rhs64_zext = zext i32 %in32 to i64
341    %res64_zext = sub i64 %lhs64, %rhs64_zext
342    store volatile i64 %res64_zext, i64* @var64
343; CHECK: sub {{x[0-9]+}}, {{x[0-9]+}}, {{w[0-9]+}}, uxtw
344; GISEL: subs {{x[0-9]+}}, {{x[0-9]+}}, {{w[0-9]+}}, uxtw
345
346    %rhs64_zext2 = zext i32 %val32 to i64
347    %rhs64_zext_shift = shl i64 %rhs64_zext2, 2
348    %res64_zext_shift = sub i64 %lhs64, %rhs64_zext_shift
349    store volatile i64 %res64_zext_shift, i64* @var64
350; CHECK: sub {{x[0-9]+}}, {{x[0-9]+}}, {{w[0-9]+}}, uxtw #2
351; GISEL: subs {{x[0-9]+}}, {{x[0-9]+}}, {{w[0-9]+}}, uxtw #2
352
353    %rhs64_sext = sext i32 %val32 to i64
354    %res64_sext = sub i64 %lhs64, %rhs64_sext
355    store volatile i64 %res64_sext, i64* @var64
356; CHECK: sub {{x[0-9]+}}, {{x[0-9]+}}, {{w[0-9]+}}, sxtw
357
358    %rhs64_sext_shift = shl i64 %rhs64_sext, 2
359    %res64_sext_shift = sub i64 %lhs64, %rhs64_sext_shift
360    store volatile i64 %res64_sext_shift, i64* @var64
361; CHECK: sub {{x[0-9]+}}, {{x[0-9]+}}, {{w[0-9]+}}, sxtw #2
362
363    ret void
364}
365
366; Check that implicit zext from w reg write is used instead of uxtw form of add.
367define i64 @add_fold_uxtw(i32 %x, i64 %y) {
368; CHECK-LABEL: add_fold_uxtw:
369; GISEL-LABEL: add_fold_uxtw:
370entry:
371; CHECK: and w[[TMP:[0-9]+]], w0, #0x3
372; GISEL: and w[[TMP:[0-9]+]], w0, #0x3
373; FIXME: Global ISel produces an unncessary ubfx here.
374  %m = and i32 %x, 3
375  %ext = zext i32 %m to i64
376; CHECK-NEXT: add x0, x1, x[[TMP]]
377; GISEL: add x0, x1, x[[TMP]]
378  %ret = add i64 %y, %ext
379  ret i64 %ret
380}
381
382; Check that implicit zext from w reg write is used instead of uxtw
383; form of sub and that mov WZR is folded to form a neg instruction.
384define i64 @sub_fold_uxtw_xzr(i32 %x)  {
385; CHECK-LABEL: sub_fold_uxtw_xzr:
386; GISEL-LABEL: sub_fold_uxtw_xzr:
387entry:
388; CHECK: and w[[TMP:[0-9]+]], w0, #0x3
389; GISEL: and w[[TMP:[0-9]+]], w0, #0x3
390  %m = and i32 %x, 3
391  %ext = zext i32 %m to i64
392; CHECK-NEXT: neg x0, x[[TMP]]
393; GISEL: negs x0, x[[TMP]]
394  %ret = sub i64 0, %ext
395  ret i64 %ret
396}
397
398; Check that implicit zext from w reg write is used instead of uxtw form of subs/cmp.
399define i1 @cmp_fold_uxtw(i32 %x, i64 %y) {
400; CHECK-LABEL: cmp_fold_uxtw:
401entry:
402; CHECK: and w[[TMP:[0-9]+]], w0, #0x3
403  %m = and i32 %x, 3
404  %ext = zext i32 %m to i64
405; CHECK-NEXT: cmp x1, x[[TMP]]
406; CHECK-NEXT: cset
407  %ret = icmp eq i64 %y, %ext
408  ret i1 %ret
409}
410
411; Check that implicit zext from w reg write is used instead of uxtw
412; form of add, leading to madd selection.
413define i64 @madd_fold_uxtw(i32 %x, i64 %y) {
414; CHECK-LABEL: madd_fold_uxtw:
415; GISEL-LABEL: madd_fold_uxtw:
416entry:
417; CHECK: and w[[TMP:[0-9]+]], w0, #0x3
418; GISEL: and w[[TMP:[0-9]+]], w0, #0x3
419  %m = and i32 %x, 3
420  %ext = zext i32 %m to i64
421; GISEL: madd x0, x1, x1, x[[TMP]]
422; CHECK-NEXT: madd x0, x1, x1, x[[TMP]]
423  %mul = mul i64 %y, %y
424  %ret = add i64 %mul, %ext
425  ret i64 %ret
426}
427
428; Check that implicit zext from w reg write is used instead of uxtw
429; form of sub, leading to sub/cmp folding.
430; Check that implicit zext from w reg write is used instead of uxtw form of subs/cmp.
431define i1 @cmp_sub_fold_uxtw(i32 %x, i64 %y, i64 %z) {
432; CHECK-LABEL: cmp_sub_fold_uxtw:
433entry:
434; CHECK: and w[[TMP:[0-9]+]], w0, #0x3
435  %m = and i32 %x, 3
436  %ext = zext i32 %m to i64
437; CHECK-NEXT: cmp x[[TMP2:[0-9]+]], x[[TMP]]
438; CHECK-NEXT: cset
439  %sub = sub i64 %z, %ext
440  %ret = icmp eq i64 %sub, 0
441  ret i1 %ret
442}
443
444; Check that implicit zext from w reg write is used instead of uxtw
445; form of add and add of -1 gets selected as sub.
446define i64 @add_imm_fold_uxtw(i32 %x) {
447; CHECK-LABEL: add_imm_fold_uxtw:
448; GISEL-LABEL: add_imm_fold_uxtw:
449entry:
450; CHECK: and w[[TMP:[0-9]+]], w0, #0x3
451; GISEL: and w[[TMP:[0-9]+]], w0, #0x3
452  %m = and i32 %x, 3
453  %ext = zext i32 %m to i64
454; CHECK-NEXT: sub x0, x[[TMP]], #1
455; GISEL: subs x0, x[[TMP]], #1
456  %ret = add i64 %ext, -1
457  ret i64 %ret
458}
459
460; Check that implicit zext from w reg write is used instead of uxtw
461; form of add and add lsl form gets selected.
462define i64 @add_lsl_fold_uxtw(i32 %x, i64 %y) {
463; CHECK-LABEL: add_lsl_fold_uxtw:
464; GISEL-LABEL: add_lsl_fold_uxtw:
465entry:
466; CHECK: orr w[[TMP:[0-9]+]], w0, #0x3
467; GISEL: orr w[[TMP:[0-9]+]], w0, #0x3
468  %m = or i32 %x, 3
469  %ext = zext i32 %m to i64
470  %shift = shl i64 %y, 3
471; CHECK-NEXT: add x0, x[[TMP]], x1, lsl #3
472; GISEL: add x0, x[[TMP]], x1, lsl #3
473  %ret = add i64 %ext, %shift
474  ret i64 %ret
475}
476