xref: /llvm-project/llvm/test/CodeGen/AArch64/addsub.ll (revision deab451e7a7f2dff42097049274637052c87eabd)
1; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
2; RUN: llc -verify-machineinstrs < %s -mtriple=aarch64-linux-gnu -verify-machineinstrs | FileCheck %s
3
4; Note that this should be refactored (for efficiency if nothing else)
5; when the PCS is implemented so we don't have to worry about the
6; loads and stores.
7
8@var_i32 = global i32 42
9@var2_i32 = global i32 43
10@var_i64 = global i64 0
11
12; Add pure 12-bit immediates:
13define void @add_small() {
14; CHECK-LABEL: add_small:
15; CHECK:       // %bb.0:
16; CHECK-NEXT:    adrp x8, :got:var_i32
17; CHECK-NEXT:    adrp x9, :got:var_i64
18; CHECK-NEXT:    ldr x8, [x8, :got_lo12:var_i32]
19; CHECK-NEXT:    ldr x9, [x9, :got_lo12:var_i64]
20; CHECK-NEXT:    ldr w10, [x8]
21; CHECK-NEXT:    ldr x11, [x9]
22; CHECK-NEXT:    add w10, w10, #4095
23; CHECK-NEXT:    add x11, x11, #52
24; CHECK-NEXT:    str w10, [x8]
25; CHECK-NEXT:    str x11, [x9]
26; CHECK-NEXT:    ret
27
28  %val32 = load i32, ptr @var_i32
29  %newval32 = add i32 %val32, 4095
30  store i32 %newval32, ptr @var_i32
31
32  %val64 = load i64, ptr @var_i64
33  %newval64 = add i64 %val64, 52
34  store i64 %newval64, ptr @var_i64
35
36  ret void
37}
38
39; Make sure we grab the imm variant when the register operand
40; can be implicitly zero-extend.
41; We used to generate something horrible like this:
42; wA = ldrb
43; xB = ldimm 12
44; xC = add xB, wA, uxtb
45; whereas this can be achieved with:
46; wA = ldrb
47; xC = add xA, #12 ; <- xA implicitly zero extend wA.
48define void @add_small_imm(ptr %p, ptr %q, i32 %b, ptr %addr) {
49; CHECK-LABEL: add_small_imm:
50; CHECK:       // %bb.0: // %entry
51; CHECK-NEXT:    ldrb w8, [x0]
52; CHECK-NEXT:    add w9, w8, w2
53; CHECK-NEXT:    add x8, x8, #12
54; CHECK-NEXT:    str w9, [x3]
55; CHECK-NEXT:    str x8, [x1]
56; CHECK-NEXT:    ret
57entry:
58
59  %t = load i8, ptr %p
60  %promoted = zext i8 %t to i64
61  %zextt = zext i8 %t to i32
62  %add = add nuw i32 %zextt, %b
63
64  %add2 = add nuw i64 %promoted, 12
65  store i32 %add, ptr %addr
66
67  store i64 %add2, ptr %q
68  ret void
69}
70
71; Add 12-bit immediates, shifted left by 12 bits
72define void @add_med() {
73; CHECK-LABEL: add_med:
74; CHECK:       // %bb.0:
75; CHECK-NEXT:    adrp x8, :got:var_i32
76; CHECK-NEXT:    adrp x9, :got:var_i64
77; CHECK-NEXT:    ldr x8, [x8, :got_lo12:var_i32]
78; CHECK-NEXT:    ldr x9, [x9, :got_lo12:var_i64]
79; CHECK-NEXT:    ldr w10, [x8]
80; CHECK-NEXT:    ldr x11, [x9]
81; CHECK-NEXT:    add w10, w10, #3567, lsl #12 // =14610432
82; CHECK-NEXT:    add x11, x11, #4095, lsl #12 // =16773120
83; CHECK-NEXT:    str w10, [x8]
84; CHECK-NEXT:    str x11, [x9]
85; CHECK-NEXT:    ret
86
87  %val32 = load i32, ptr @var_i32
88  %newval32 = add i32 %val32, 14610432 ; =0xdef000
89  store i32 %newval32, ptr @var_i32
90
91  %val64 = load i64, ptr @var_i64
92  %newval64 = add i64 %val64, 16773120 ; =0xfff000
93  store i64 %newval64, ptr @var_i64
94
95  ret void
96}
97
98; Subtract 12-bit immediates
99define void @sub_small() {
100; CHECK-LABEL: sub_small:
101; CHECK:       // %bb.0:
102; CHECK-NEXT:    adrp x8, :got:var_i32
103; CHECK-NEXT:    adrp x9, :got:var_i64
104; CHECK-NEXT:    ldr x8, [x8, :got_lo12:var_i32]
105; CHECK-NEXT:    ldr x9, [x9, :got_lo12:var_i64]
106; CHECK-NEXT:    ldr w10, [x8]
107; CHECK-NEXT:    ldr x11, [x9]
108; CHECK-NEXT:    sub w10, w10, #4095
109; CHECK-NEXT:    sub x11, x11, #52
110; CHECK-NEXT:    str w10, [x8]
111; CHECK-NEXT:    str x11, [x9]
112; CHECK-NEXT:    ret
113
114  %val32 = load i32, ptr @var_i32
115  %newval32 = sub i32 %val32, 4095
116  store i32 %newval32, ptr @var_i32
117
118  %val64 = load i64, ptr @var_i64
119  %newval64 = sub i64 %val64, 52
120  store i64 %newval64, ptr @var_i64
121
122  ret void
123}
124
125; Subtract 12-bit immediates, shifted left by 12 bits
126define void @sub_med() {
127; CHECK-LABEL: sub_med:
128; CHECK:       // %bb.0:
129; CHECK-NEXT:    adrp x8, :got:var_i32
130; CHECK-NEXT:    adrp x9, :got:var_i64
131; CHECK-NEXT:    ldr x8, [x8, :got_lo12:var_i32]
132; CHECK-NEXT:    ldr x9, [x9, :got_lo12:var_i64]
133; CHECK-NEXT:    ldr w10, [x8]
134; CHECK-NEXT:    ldr x11, [x9]
135; CHECK-NEXT:    sub w10, w10, #3567, lsl #12 // =14610432
136; CHECK-NEXT:    sub x11, x11, #4095, lsl #12 // =16773120
137; CHECK-NEXT:    str w10, [x8]
138; CHECK-NEXT:    str x11, [x9]
139; CHECK-NEXT:    ret
140
141  %val32 = load i32, ptr @var_i32
142  %newval32 = sub i32 %val32, 14610432 ; =0xdef000
143  store i32 %newval32, ptr @var_i32
144
145  %val64 = load i64, ptr @var_i64
146  %newval64 = sub i64 %val64, 16773120 ; =0xfff000
147  store i64 %newval64, ptr @var_i64
148
149  ret void
150}
151
152define i64 @add_two_parts_imm_i64(i64 %a) {
153; CHECK-LABEL: add_two_parts_imm_i64:
154; CHECK:       // %bb.0:
155; CHECK-NEXT:    add x8, x0, #2730, lsl #12 // =11182080
156; CHECK-NEXT:    add x0, x8, #1365
157; CHECK-NEXT:    ret
158  %b = add i64 %a, 11183445
159  ret i64 %b
160}
161
162define i32 @add_two_parts_imm_i32(i32 %a) {
163; CHECK-LABEL: add_two_parts_imm_i32:
164; CHECK:       // %bb.0:
165; CHECK-NEXT:    add w8, w0, #2730, lsl #12 // =11182080
166; CHECK-NEXT:    add w0, w8, #1365
167; CHECK-NEXT:    ret
168  %b = add i32 %a, 11183445
169  ret i32 %b
170}
171
172define i64 @add_two_parts_imm_i64_neg(i64 %a) {
173; CHECK-LABEL: add_two_parts_imm_i64_neg:
174; CHECK:       // %bb.0:
175; CHECK-NEXT:    sub x8, x0, #2730, lsl #12 // =11182080
176; CHECK-NEXT:    sub x0, x8, #1365
177; CHECK-NEXT:    ret
178  %b = add i64 %a, -11183445
179  ret i64 %b
180}
181
182define i32 @add_two_parts_imm_i32_neg(i32 %a) {
183; CHECK-LABEL: add_two_parts_imm_i32_neg:
184; CHECK:       // %bb.0:
185; CHECK-NEXT:    sub w8, w0, #2730, lsl #12 // =11182080
186; CHECK-NEXT:    sub w0, w8, #1365
187; CHECK-NEXT:    ret
188  %b = add i32 %a, -11183445
189  ret i32 %b
190}
191
192define i64 @sub_two_parts_imm_i64(i64 %a) {
193; CHECK-LABEL: sub_two_parts_imm_i64:
194; CHECK:       // %bb.0:
195; CHECK-NEXT:    sub x8, x0, #2730, lsl #12 // =11182080
196; CHECK-NEXT:    sub x0, x8, #1365
197; CHECK-NEXT:    ret
198  %b = sub i64 %a, 11183445
199  ret i64 %b
200}
201
202define i32 @sub_two_parts_imm_i32(i32 %a) {
203; CHECK-LABEL: sub_two_parts_imm_i32:
204; CHECK:       // %bb.0:
205; CHECK-NEXT:    sub w8, w0, #2730, lsl #12 // =11182080
206; CHECK-NEXT:    sub w0, w8, #1365
207; CHECK-NEXT:    ret
208  %b = sub i32 %a, 11183445
209  ret i32 %b
210}
211
212define i64 @sub_two_parts_imm_i64_neg(i64 %a) {
213; CHECK-LABEL: sub_two_parts_imm_i64_neg:
214; CHECK:       // %bb.0:
215; CHECK-NEXT:    add x8, x0, #2730, lsl #12 // =11182080
216; CHECK-NEXT:    add x0, x8, #1365
217; CHECK-NEXT:    ret
218  %b = sub i64 %a, -11183445
219  ret i64 %b
220}
221
222define i32 @sub_two_parts_imm_i32_neg(i32 %a) {
223; CHECK-LABEL: sub_two_parts_imm_i32_neg:
224; CHECK:       // %bb.0:
225; CHECK-NEXT:    add w8, w0, #2730, lsl #12 // =11182080
226; CHECK-NEXT:    add w0, w8, #1365
227; CHECK-NEXT:    ret
228  %b = sub i32 %a, -11183445
229  ret i32 %b
230}
231
232define i32 @add_27962026(i32 %a) {
233; CHECK-LABEL: add_27962026:
234; CHECK:       // %bb.0:
235; CHECK-NEXT:    mov w8, #43690 // =0xaaaa
236; CHECK-NEXT:    movk w8, #426, lsl #16
237; CHECK-NEXT:    add w0, w0, w8
238; CHECK-NEXT:    ret
239  %b = add i32 %a, 27962026
240  ret i32 %b
241}
242
243define i32 @add_65534(i32 %a) {
244; CHECK-LABEL: add_65534:
245; CHECK:       // %bb.0:
246; CHECK-NEXT:    mov w8, #65534 // =0xfffe
247; CHECK-NEXT:    add w0, w0, w8
248; CHECK-NEXT:    ret
249  %b = add i32 %a, 65534
250  ret i32 %b
251}
252
253declare i32 @foox(i32)
254
255define void @add_in_loop(i32 %0) {
256; CHECK-LABEL: add_in_loop:
257; CHECK:       // %bb.0:
258; CHECK-NEXT:    stp x30, x19, [sp, #-16]! // 16-byte Folded Spill
259; CHECK-NEXT:    .cfi_def_cfa_offset 16
260; CHECK-NEXT:    .cfi_offset w19, -8
261; CHECK-NEXT:    .cfi_offset w30, -16
262; CHECK-NEXT:    mov w19, #43690 // =0xaaaa
263; CHECK-NEXT:    movk w19, #170, lsl #16
264; CHECK-NEXT:  .LBB15_1: // =>This Inner Loop Header: Depth=1
265; CHECK-NEXT:    add w0, w0, w19
266; CHECK-NEXT:    bl foox
267; CHECK-NEXT:    b .LBB15_1
268  br label %2
2692:
270  %3 = phi i32 [ %0, %1 ], [ %5, %2 ]
271  %4 = add nsw i32 %3, 11184810
272  %5 = tail call i32 @foox(i32 %4) #2
273  br label %2
274}
275
276define void @testing() {
277; CHECK-LABEL: testing:
278; CHECK:       // %bb.0:
279; CHECK-NEXT:    adrp x8, :got:var_i32
280; CHECK-NEXT:    ldr x8, [x8, :got_lo12:var_i32]
281; CHECK-NEXT:    ldr w9, [x8]
282; CHECK-NEXT:    cmp w9, #4095
283; CHECK-NEXT:    b.ne .LBB16_6
284; CHECK-NEXT:  // %bb.1: // %test2
285; CHECK-NEXT:    adrp x10, :got:var2_i32
286; CHECK-NEXT:    add w11, w9, #1
287; CHECK-NEXT:    ldr x10, [x10, :got_lo12:var2_i32]
288; CHECK-NEXT:    str w11, [x8]
289; CHECK-NEXT:    ldr w10, [x10]
290; CHECK-NEXT:    cmp w10, #3567, lsl #12 // =14610432
291; CHECK-NEXT:    b.lo .LBB16_6
292; CHECK-NEXT:  // %bb.2: // %test3
293; CHECK-NEXT:    add w11, w9, #2
294; CHECK-NEXT:    cmp w9, #123
295; CHECK-NEXT:    str w11, [x8]
296; CHECK-NEXT:    b.lt .LBB16_6
297; CHECK-NEXT:  // %bb.3: // %test4
298; CHECK-NEXT:    add w11, w9, #3
299; CHECK-NEXT:    cmp w10, #321
300; CHECK-NEXT:    str w11, [x8]
301; CHECK-NEXT:    b.gt .LBB16_6
302; CHECK-NEXT:  // %bb.4: // %test5
303; CHECK-NEXT:    add w11, w9, #4
304; CHECK-NEXT:    cmn w10, #443
305; CHECK-NEXT:    str w11, [x8]
306; CHECK-NEXT:    b.ge .LBB16_6
307; CHECK-NEXT:  // %bb.5: // %test6
308; CHECK-NEXT:    add w9, w9, #5
309; CHECK-NEXT:    str w9, [x8]
310; CHECK-NEXT:  .LBB16_6: // %common.ret
311; CHECK-NEXT:    ret
312  %val = load i32, ptr @var_i32
313  %val2 = load i32, ptr @var2_i32
314
315  %cmp_pos_small = icmp ne i32 %val, 4095
316  br i1 %cmp_pos_small, label %ret, label %test2
317
318test2:
319  %newval2 = add i32 %val, 1
320  store i32 %newval2, ptr @var_i32
321  %cmp_pos_big = icmp ult i32 %val2, 14610432
322  br i1 %cmp_pos_big, label %ret, label %test3
323
324test3:
325  %newval3 = add i32 %val, 2
326  store i32 %newval3, ptr @var_i32
327  %cmp_pos_slt = icmp slt i32 %val, 123
328  br i1 %cmp_pos_slt, label %ret, label %test4
329
330test4:
331  %newval4 = add i32 %val, 3
332  store i32 %newval4, ptr @var_i32
333  %cmp_pos_sgt = icmp sgt i32 %val2, 321
334  br i1 %cmp_pos_sgt, label %ret, label %test5
335
336test5:
337  %newval5 = add i32 %val, 4
338  store i32 %newval5, ptr @var_i32
339  %cmp_neg_uge = icmp sgt i32 %val2, -444
340  br i1 %cmp_neg_uge, label %ret, label %test6
341
342test6:
343  %newval6 = add i32 %val, 5
344  store i32 %newval6, ptr @var_i32
345  ret void
346
347ret:
348  ret void
349}
350
351declare {i32, i1} @llvm.sadd.with.overflow.i32(i32 %a, i32 %b)
352
353define i1 @sadd_add(i32 %a, i32 %b, ptr %p) {
354; CHECK-LABEL: sadd_add:
355; CHECK:       // %bb.0:
356; CHECK-NEXT:    mvn w8, w0
357; CHECK-NEXT:    adds w8, w8, w1
358; CHECK-NEXT:    cset w0, vs
359; CHECK-NEXT:    add w8, w8, #1
360; CHECK-NEXT:    str w8, [x2]
361; CHECK-NEXT:    ret
362  %nota = xor i32 %a, -1
363  %a0 = call {i32, i1} @llvm.sadd.with.overflow.i32(i32 %nota, i32 %b)
364  %e0 = extractvalue {i32, i1} %a0, 0
365  %e1 = extractvalue {i32, i1} %a0, 1
366  %res = add i32 %e0, 1
367  store i32 %res, ptr %p
368  ret i1 %e1
369}
370
371declare {i8, i1} @llvm.uadd.with.overflow.i8(i8 %a, i8 %b)
372
373define i1 @uadd_add(i8 %a, i8 %b, ptr %p) {
374; CHECK-LABEL: uadd_add:
375; CHECK:       // %bb.0:
376; CHECK-NEXT:    mov w8, #255 // =0xff
377; CHECK-NEXT:    bic w8, w8, w0
378; CHECK-NEXT:    add w8, w8, w1, uxtb
379; CHECK-NEXT:    lsr w0, w8, #8
380; CHECK-NEXT:    add w8, w8, #1
381; CHECK-NEXT:    strb w8, [x2]
382; CHECK-NEXT:    ret
383  %nota = xor i8 %a, -1
384  %a0 = call {i8, i1} @llvm.uadd.with.overflow.i8(i8 %nota, i8 %b)
385  %e0 = extractvalue {i8, i1} %a0, 0
386  %e1 = extractvalue {i8, i1} %a0, 1
387  %res = add i8 %e0, 1
388  store i8 %res, ptr %p
389  ret i1 %e1
390}
391
392; This is a unique edge case that will generate the following MIR
393;   MOVi32imm -1000000
394;   SUBREG_TO_REG 0, killed %1, %subreg.sub_32
395; When using a 64-bit unsigned for the "-1000000" immediate, the code
396; must make sure to zero out the top 32 bits since SUBREG_TO_REG is
397; zero extending the value
398define i64 @addl_0x80000000(i64 %a) {
399; CHECK-LABEL: addl_0x80000000:
400; CHECK:       // %bb.0:
401; CHECK-NEXT:    mov w8, #48576 // =0xbdc0
402; CHECK-NEXT:    movk w8, #65520, lsl #16
403; CHECK-NEXT:    add x0, x0, x8
404; CHECK-NEXT:    ret
405  %b = add i64 %a, 4293967296
406  ret i64 %b
407}
408
409; ADDS and SUBS Optimizations
410; Checks with all types first, then checks that only EQ and NE optimize
411define i1 @eq_i(i32 %0) {
412; CHECK-LABEL: eq_i:
413; CHECK:       // %bb.0:
414; CHECK-NEXT:    sub w8, w0, #273, lsl #12 // =1118208
415; CHECK-NEXT:    cmp w8, #273
416; CHECK-NEXT:    cset w0, eq
417; CHECK-NEXT:    ret
418  %2 = icmp eq i32 %0, 1118481
419  ret i1 %2
420}
421
422define i1 @eq_l(i64 %0) {
423; CHECK-LABEL: eq_l:
424; CHECK:       // %bb.0:
425; CHECK-NEXT:    sub x8, x0, #273, lsl #12 // =1118208
426; CHECK-NEXT:    cmp x8, #273
427; CHECK-NEXT:    cset w0, eq
428; CHECK-NEXT:    ret
429  %2 = icmp eq i64 %0, 1118481
430  ret i1 %2
431}
432
433define i1 @ne_i(i32 %0) {
434; CHECK-LABEL: ne_i:
435; CHECK:       // %bb.0:
436; CHECK-NEXT:    sub w8, w0, #273, lsl #12 // =1118208
437; CHECK-NEXT:    cmp w8, #273
438; CHECK-NEXT:    cset w0, ne
439; CHECK-NEXT:    ret
440  %2 = icmp ne i32 %0, 1118481
441  ret i1 %2
442}
443
444define i1 @ne_l(i64 %0) {
445; CHECK-LABEL: ne_l:
446; CHECK:       // %bb.0:
447; CHECK-NEXT:    sub x8, x0, #273, lsl #12 // =1118208
448; CHECK-NEXT:    cmp x8, #273
449; CHECK-NEXT:    cset w0, ne
450; CHECK-NEXT:    ret
451  %2 = icmp ne i64 %0, 1118481
452  ret i1 %2
453}
454
455define i1 @eq_in(i32 %0) {
456; CHECK-LABEL: eq_in:
457; CHECK:       // %bb.0:
458; CHECK-NEXT:    add w8, w0, #273, lsl #12 // =1118208
459; CHECK-NEXT:    cmn w8, #273
460; CHECK-NEXT:    cset w0, eq
461; CHECK-NEXT:    ret
462  %2 = icmp eq i32 %0, -1118481
463  ret i1 %2
464}
465
466define i1 @eq_ln(i64 %0) {
467; CHECK-LABEL: eq_ln:
468; CHECK:       // %bb.0:
469; CHECK-NEXT:    add x8, x0, #273, lsl #12 // =1118208
470; CHECK-NEXT:    cmn x8, #273
471; CHECK-NEXT:    cset w0, eq
472; CHECK-NEXT:    ret
473  %2 = icmp eq i64 %0, -1118481
474  ret i1 %2
475}
476
477define i1 @ne_in(i32 %0) {
478; CHECK-LABEL: ne_in:
479; CHECK:       // %bb.0:
480; CHECK-NEXT:    add w8, w0, #273, lsl #12 // =1118208
481; CHECK-NEXT:    cmn w8, #273
482; CHECK-NEXT:    cset w0, ne
483; CHECK-NEXT:    ret
484  %2 = icmp ne i32 %0, -1118481
485  ret i1 %2
486}
487
488define i1 @ne_ln(i64 %0) {
489; CHECK-LABEL: ne_ln:
490; CHECK:       // %bb.0:
491; CHECK-NEXT:    add x8, x0, #273, lsl #12 // =1118208
492; CHECK-NEXT:    cmn x8, #273
493; CHECK-NEXT:    cset w0, ne
494; CHECK-NEXT:    ret
495  %2 = icmp ne i64 %0, -1118481
496  ret i1 %2
497}
498
499define i1 @reject_eq(i32 %0) {
500; CHECK-LABEL: reject_eq:
501; CHECK:       // %bb.0:
502; CHECK-NEXT:    mov w8, #51712 // =0xca00
503; CHECK-NEXT:    movk w8, #15258, lsl #16
504; CHECK-NEXT:    cmp w0, w8
505; CHECK-NEXT:    cset w0, eq
506; CHECK-NEXT:    ret
507  %2 = icmp eq i32 %0, 1000000000
508  ret i1 %2
509}
510
511define i1 @reject_non_eqne_csinc(i32 %0) {
512; CHECK-LABEL: reject_non_eqne_csinc:
513; CHECK:       // %bb.0:
514; CHECK-NEXT:    mov w8, #4369 // =0x1111
515; CHECK-NEXT:    movk w8, #17, lsl #16
516; CHECK-NEXT:    cmp w0, w8
517; CHECK-NEXT:    cset w0, lo
518; CHECK-NEXT:    ret
519  %2 = icmp ult i32 %0, 1118481
520  ret i1 %2
521}
522
523define i32 @accept_csel(i32 %0) {
524; CHECK-LABEL: accept_csel:
525; CHECK:       // %bb.0:
526; CHECK-NEXT:    sub w9, w0, #273, lsl #12 // =1118208
527; CHECK-NEXT:    mov w8, #17 // =0x11
528; CHECK-NEXT:    cmp w9, #273
529; CHECK-NEXT:    mov w9, #11 // =0xb
530; CHECK-NEXT:    csel w0, w9, w8, eq
531; CHECK-NEXT:    ret
532  %2 = icmp eq i32 %0, 1118481
533  %3 = select i1 %2, i32 11, i32 17
534  ret i32 %3
535}
536
537define i32 @reject_non_eqne_csel(i32 %0) {
538; CHECK-LABEL: reject_non_eqne_csel:
539; CHECK:       // %bb.0:
540; CHECK-NEXT:    mov w8, #4369 // =0x1111
541; CHECK-NEXT:    mov w9, #11 // =0xb
542; CHECK-NEXT:    movk w8, #17, lsl #16
543; CHECK-NEXT:    cmp w0, w8
544; CHECK-NEXT:    mov w8, #17 // =0x11
545; CHECK-NEXT:    csel w0, w9, w8, lo
546; CHECK-NEXT:    ret
547  %2 = icmp ult i32 %0, 1118481
548  %3 = select i1 %2, i32 11, i32 17
549  ret i32 %3
550}
551
552declare void @fooy()
553
554define void @accept_branch(i32 %0) {
555; CHECK-LABEL: accept_branch:
556; CHECK:       // %bb.0:
557; CHECK-NEXT:    sub w8, w0, #291, lsl #12 // =1191936
558; CHECK-NEXT:    cmp w8, #1110
559; CHECK-NEXT:    b.eq .LBB32_2
560; CHECK-NEXT:  // %bb.1:
561; CHECK-NEXT:    ret
562; CHECK-NEXT:  .LBB32_2:
563; CHECK-NEXT:    b fooy
564  %2 = icmp ne i32 %0, 1193046
565  br i1 %2, label %4, label %3
5663:                                                ; preds = %1
567  tail call void @fooy()
568  br label %4
5694:                                                ; preds = %3, %1
570  ret void
571}
572
573define void @reject_non_eqne_branch(i32 %0) {
574; CHECK-LABEL: reject_non_eqne_branch:
575; CHECK:       // %bb.0:
576; CHECK-NEXT:    mov w8, #13398 // =0x3456
577; CHECK-NEXT:    movk w8, #18, lsl #16
578; CHECK-NEXT:    cmp w0, w8
579; CHECK-NEXT:    b.le .LBB33_2
580; CHECK-NEXT:  // %bb.1:
581; CHECK-NEXT:    ret
582; CHECK-NEXT:  .LBB33_2:
583; CHECK-NEXT:    b fooy
584  %2 = icmp sgt i32 %0, 1193046
585  br i1 %2, label %4, label %3
5863:                                                ; preds = %1
587  tail call void @fooy()
588  br label %4
5894:                                                ; preds = %3, %1
590  ret void
591}
592
593define i32 @reject_multiple_usages(i32 %0) {
594; CHECK-LABEL: reject_multiple_usages:
595; CHECK:       // %bb.0:
596; CHECK-NEXT:    mov w8, #4369 // =0x1111
597; CHECK-NEXT:    mov w9, #3 // =0x3
598; CHECK-NEXT:    mov w10, #17 // =0x11
599; CHECK-NEXT:    movk w8, #17, lsl #16
600; CHECK-NEXT:    mov w11, #12 // =0xc
601; CHECK-NEXT:    cmp w0, w8
602; CHECK-NEXT:    mov w8, #9 // =0x9
603; CHECK-NEXT:    csel w8, w8, w9, eq
604; CHECK-NEXT:    csel w9, w11, w10, hi
605; CHECK-NEXT:    mov w10, #53312 // =0xd040
606; CHECK-NEXT:    movk w10, #2, lsl #16
607; CHECK-NEXT:    add w8, w8, w9
608; CHECK-NEXT:    mov w9, #26304 // =0x66c0
609; CHECK-NEXT:    cmp w0, w10
610; CHECK-NEXT:    movk w9, #1433, lsl #16
611; CHECK-NEXT:    csel w0, w8, w9, hi
612; CHECK-NEXT:    ret
613  %2 = icmp eq i32 %0, 1118481
614  %3 = icmp ugt i32 %0, 1118481
615  %4 = select i1 %2, i32 9, i32 3
616  %5 = select i1 %3, i32 12, i32 17
617  %6 = add i32 %4, %5
618  %7 = icmp ugt i32 %0, 184384
619  %8 = select i1 %7, i32 %6, i32 93939392
620  ret i32 %8
621}
622
623; Unique case found in ClangBuiltLinux where the DstReg is not Virtual and
624; caused an assertion failure
625define dso_local i32 @neigh_periodic_work_tbl_1() {
626; CHECK-LABEL: neigh_periodic_work_tbl_1:
627; CHECK:       // %bb.0: // %entry
628; CHECK-NEXT:    adrp x8, neigh_periodic_work_tbl_1
629; CHECK-NEXT:    add x8, x8, :lo12:neigh_periodic_work_tbl_1
630; CHECK-NEXT:    add x8, x8, #18, lsl #12 // =73728
631; CHECK-NEXT:    cmn x8, #1272
632; CHECK-NEXT:    b.mi .LBB35_2
633; CHECK-NEXT:  // %bb.1: // %if.end
634; CHECK-NEXT:    ret
635; CHECK-NEXT:  .LBB35_2: // %for.cond
636; CHECK-NEXT:    // =>This Inner Loop Header: Depth=1
637; CHECK-NEXT:    b .LBB35_2
638entry:
639  %cmp = icmp slt i64 add (i64 ptrtoint (ptr @neigh_periodic_work_tbl_1 to i64), i64 75000), 0
640  br i1 %cmp, label %for.cond, label %if.end
641for.cond:                                         ; preds = %entry, %for.cond
642  br label %for.cond
643if.end:                                           ; preds = %entry
644  ret i32 undef
645}
646
647@jiffies = dso_local local_unnamed_addr global i32 0, align 4
648@primary_crng = dso_local local_unnamed_addr global i32 0, align 4
649@input_pool = dso_local global i32 0, align 4
650declare dso_local i32 @crng_reseed(...) local_unnamed_addr
651; Function Attrs: nounwind uwtable
652define dso_local i32 @_extract_crng_crng() {
653; CHECK-LABEL: _extract_crng_crng:
654; CHECK:       // %bb.0: // %entry
655; CHECK-NEXT:    adrp x8, _extract_crng_crng
656; CHECK-NEXT:    add x8, x8, :lo12:_extract_crng_crng
657; CHECK-NEXT:    tbnz x8, #63, .LBB36_2
658; CHECK-NEXT:  // %bb.1: // %lor.lhs.false
659; CHECK-NEXT:    adrp x9, jiffies
660; CHECK-NEXT:    ldrsw x9, [x9, :lo12:jiffies]
661; CHECK-NEXT:    sub x8, x8, x9
662; CHECK-NEXT:    add x8, x8, #18, lsl #12 // =73728
663; CHECK-NEXT:    cmn x8, #1272
664; CHECK-NEXT:    b.pl .LBB36_3
665; CHECK-NEXT:  .LBB36_2: // %if.then
666; CHECK-NEXT:    adrp x8, primary_crng
667; CHECK-NEXT:    ldr w8, [x8, :lo12:primary_crng]
668; CHECK-NEXT:    cmp w8, #0
669; CHECK-NEXT:    adrp x8, input_pool
670; CHECK-NEXT:    add x8, x8, :lo12:input_pool
671; CHECK-NEXT:    csel x0, xzr, x8, eq
672; CHECK-NEXT:    b crng_reseed
673; CHECK-NEXT:  .LBB36_3: // %if.end
674; CHECK-NEXT:    ret
675entry:
676  %cmp2 = icmp slt ptr @_extract_crng_crng, null
677  br i1 %cmp2, label %if.then, label %lor.lhs.false
678lor.lhs.false:                                    ; preds = %entry
679  %0 = load i32, ptr @jiffies, align 4
680  %idx.ext = sext i32 %0 to i64
681  %idx.neg = sub nsw i64 0, %idx.ext
682  %add.ptr = getelementptr i8, ptr getelementptr (i8, ptr @_extract_crng_crng, i64 75000), i64 %idx.neg
683  %cmp = icmp slt ptr %add.ptr, null
684  br i1 %cmp, label %if.then, label %if.end
685if.then:                                          ; preds = %lor.lhs.false, %entry
686  %1 = load i32, ptr @primary_crng, align 4
687  %tobool.not = icmp eq i32 %1, 0
688  %cond = select i1 %tobool.not, ptr null, ptr @input_pool
689  %call = tail call i32 @crng_reseed(ptr noundef %cond)
690  br label %if.end
691if.end:                                           ; preds = %if.then, %lor.lhs.false
692  ret i32 undef
693}
694
695; ((X << C) - Y) + Z --> (Z - Y) + (X << C)
696define i32 @commute_subop0(i32 %x, i32 %y, i32 %z) {
697; CHECK-LABEL: commute_subop0:
698; CHECK:       // %bb.0:
699; CHECK-NEXT:    sub w8, w2, w1
700; CHECK-NEXT:    add w0, w8, w0, lsl #3
701; CHECK-NEXT:    ret
702  %shl = shl i32 %x, 3
703  %sub = sub i32 %shl, %y
704  %add = add i32 %sub, %z
705  ret i32 %add
706}
707
708; ((X >> C) - Y) + Z --> (Z - Y) + (X >> C)
709define i32 @commute_subop0_lshr(i32 %x, i32 %y, i32 %z) {
710; CHECK-LABEL: commute_subop0_lshr:
711; CHECK:       // %bb.0:
712; CHECK-NEXT:    sub w8, w2, w1
713; CHECK-NEXT:    add w0, w8, w0, lsr #3
714; CHECK-NEXT:    ret
715  %lshr = lshr i32 %x, 3
716  %sub = sub i32 %lshr, %y
717  %add = add i32 %sub, %z
718  ret i32 %add
719}
720
721; ((X >> C) - Y) + Z --> (Z - Y) + (X >> C)
722define i32 @commute_subop0_ashr(i32 %x, i32 %y, i32 %z) {
723; CHECK-LABEL: commute_subop0_ashr:
724; CHECK:       // %bb.0:
725; CHECK-NEXT:    sub w8, w2, w1
726; CHECK-NEXT:    add w0, w8, w0, asr #3
727; CHECK-NEXT:    ret
728  %ashr = ashr i32 %x, 3
729  %sub = sub i32 %ashr, %y
730  %add = add i32 %sub, %z
731  ret i32 %add
732}
733
734; ((sext X) - Y) + Z --> (Z - Y) + (sext X)
735define i64 @commute_subop0_sext(i32 %x, i64 %y, i64 %z) {
736; CHECK-LABEL: commute_subop0_sext:
737; CHECK:       // %bb.0:
738; CHECK-NEXT:    sub x8, x2, x1
739; CHECK-NEXT:    add x0, x8, w0, sxtw
740; CHECK-NEXT:    ret
741  %sext = sext i32 %x to i64
742  %sub = sub i64 %sext, %y
743  %add = add i64 %sub, %z
744  ret i64 %add
745}
746
747; ((sext_inreg X) - Y) + Z --> (Z - Y) + (sext_inreg X)
748define i64 @commute_subop0_sext_inreg(i64 %x, i64 %y, i64 %z) {
749; CHECK-LABEL: commute_subop0_sext_inreg:
750; CHECK:       // %bb.0:
751; CHECK-NEXT:    sub x8, x2, x1
752; CHECK-NEXT:    add x0, x8, w0, sxth
753; CHECK-NEXT:    ret
754  %shl = shl i64 %x, 48
755  %ashr = ashr i64 %shl, 48
756  %sub = sub i64 %ashr, %y
757  %add = add i64 %sub, %z
758  ret i64 %add
759}
760
761; ((zext X) - Y) + Z --> (Z - Y) + (zext X)
762define i32 @commute_subop0_zext(i16 %x, i32 %y, i32 %z) {
763; CHECK-LABEL: commute_subop0_zext:
764; CHECK:       // %bb.0:
765; CHECK-NEXT:    sub w8, w2, w1
766; CHECK-NEXT:    add w0, w8, w0, uxth
767; CHECK-NEXT:    ret
768  %zext = zext i16 %x to i32
769  %sub = sub i32 %zext, %y
770  %add = add i32 %sub, %z
771  ret i32 %add
772}
773
774
775; ((anyext X) - Y) + Z --> (Z - Y) + (anyext X)
776define i8 @commute_subop0_anyext(i16 %a, i16 %b, i32 %c) {
777; CHECK-LABEL: commute_subop0_anyext:
778; CHECK:       // %bb.0:
779; CHECK-NEXT:    mov w8, #111 // =0x6f
780; CHECK-NEXT:    sub w9, w2, w1
781; CHECK-NEXT:    madd w8, w0, w8, w9
782; CHECK-NEXT:    lsl w8, w8, #3
783; CHECK-NEXT:    sub w0, w8, #1776
784; CHECK-NEXT:    ret
785  %aa = mul i16 %a, 111
786  %bb = add i16 %b, 222
787  %a_32 = zext i16 %aa to i32
788  %b_32 = zext i16 %bb to i32
789  %sub = sub i32 %a_32, %b_32
790  %add = add i32 %sub, %c
791  %trunc = trunc i32 %add to i8
792  %r = shl i8 %trunc, 3
793  ret i8 %r
794}
795
796; ((X and C) - Y) + Z --> (Z - Y) + (X and C)
797define i32 @commute_subop0_and(i32 %x, i32 %y, i32 %z) {
798; CHECK-LABEL: commute_subop0_and:
799; CHECK:       // %bb.0:
800; CHECK-NEXT:    sub w8, w2, w1
801; CHECK-NEXT:    add w0, w8, w0, uxtb
802; CHECK-NEXT:    ret
803  %and = and i32 %x, 255
804  %sub = sub i32 %and, %y
805  %add = add i32 %sub, %z
806  ret i32 %add
807}
808
809; Z + ((X << C) - Y) --> (Z - Y) + (X << C)
810define i32 @commute_subop0_cadd(i32 %x, i32 %y, i32 %z) {
811; CHECK-LABEL: commute_subop0_cadd:
812; CHECK:       // %bb.0:
813; CHECK-NEXT:    sub w8, w2, w1
814; CHECK-NEXT:    add w0, w8, w0, lsl #3
815; CHECK-NEXT:    ret
816  %shl = shl i32 %x, 3
817  %sub = sub i32 %shl, %y
818  %add = add i32 %z, %sub
819  ret i32 %add
820}
821
822; Y + ((X << C) - X) --> (Y - X) + (X << C)
823define i32 @commute_subop0_mul(i32 %x, i32 %y) {
824; CHECK-LABEL: commute_subop0_mul:
825; CHECK:       // %bb.0:
826; CHECK-NEXT:    sub w8, w1, w0
827; CHECK-NEXT:    add w0, w8, w0, lsl #3
828; CHECK-NEXT:    ret
829  %mul = mul i32 %x, 7
830  %add = add i32 %mul, %y
831  ret i32 %add
832}
833
834; negative case for ((X << C) - Y) + Z --> (Z - Y) + (X << C)
835; Y can't be constant to avoid dead loop
836define i32 @commute_subop0_zconst(i32 %x, i32 %y) {
837; CHECK-LABEL: commute_subop0_zconst:
838; CHECK:       // %bb.0:
839; CHECK-NEXT:    lsl w8, w0, #3
840; CHECK-NEXT:    sub w8, w8, w1
841; CHECK-NEXT:    add w0, w8, #1
842; CHECK-NEXT:    ret
843  %shl = shl i32 %x, 3
844  %sub = sub i32 %shl, %y
845  %add = add i32 %sub, 1
846  ret i32 %add
847}
848
849; negative case for ((X << C) - Y) + Z --> (Z - Y) + (X << C)
850; Y can't be shift C also to avoid dead loop
851define i32 @commute_subop0_zshiftc_oneuse(i32 %x, i32 %y, i32 %z) {
852; CHECK-LABEL: commute_subop0_zshiftc_oneuse:
853; CHECK:       // %bb.0:
854; CHECK-NEXT:    lsl w8, w0, #3
855; CHECK-NEXT:    sub w8, w8, w1
856; CHECK-NEXT:    add w0, w8, w2, lsl #2
857; CHECK-NEXT:    ret
858  %xshl = shl i32 %x, 3
859  %sub = sub i32 %xshl, %y
860  %zshl = shl i32 %z, 2
861  %add = add i32 %sub, %zshl
862  ret i32 %add
863}
864
865define i32 @commute_subop0_zshiftc(i32 %x, i32 %y, i32 %z) {
866; CHECK-LABEL: commute_subop0_zshiftc:
867; CHECK:       // %bb.0:
868; CHECK-NEXT:    lsl w8, w2, #2
869; CHECK-NEXT:    sub w9, w8, w1
870; CHECK-NEXT:    add w9, w9, w0, lsl #3
871; CHECK-NEXT:    eor w0, w8, w9
872; CHECK-NEXT:    ret
873  %xshl = shl i32 %x, 3
874  %sub = sub i32 %xshl, %y
875  %zshl = shl i32 %z, 2
876  %add = add i32 %sub, %zshl
877  %r = xor i32 %zshl, %add
878  ret i32 %r
879}
880