Bump version to 19.1.0-rc3
[llvm-project.git] / llvm / test / CodeGen / AArch64 / addsub.ll
blob3a4955cd1fea45ec8240c6aa6e8a7dca26ea0551
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
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.
8 @var_i32 = global i32 42
9 @var2_i32 = global i32 43
10 @var_i64 = global i64 0
12 ; Add pure 12-bit immediates:
13 define 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
28   %val32 = load i32, ptr @var_i32
29   %newval32 = add i32 %val32, 4095
30   store i32 %newval32, ptr @var_i32
32   %val64 = load i64, ptr @var_i64
33   %newval64 = add i64 %val64, 52
34   store i64 %newval64, ptr @var_i64
36   ret void
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.
48 define 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
57 entry:
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
64   %add2 = add nuw i64 %promoted, 12
65   store i32 %add, ptr %addr
67   store i64 %add2, ptr %q
68   ret void
71 ; Add 12-bit immediates, shifted left by 12 bits
72 define 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
87   %val32 = load i32, ptr @var_i32
88   %newval32 = add i32 %val32, 14610432 ; =0xdef000
89   store i32 %newval32, ptr @var_i32
91   %val64 = load i64, ptr @var_i64
92   %newval64 = add i64 %val64, 16773120 ; =0xfff000
93   store i64 %newval64, ptr @var_i64
95   ret void
98 ; Subtract 12-bit immediates
99 define 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
114   %val32 = load i32, ptr @var_i32
115   %newval32 = sub i32 %val32, 4095
116   store i32 %newval32, ptr @var_i32
118   %val64 = load i64, ptr @var_i64
119   %newval64 = sub i64 %val64, 52
120   store i64 %newval64, ptr @var_i64
122   ret void
125 ; Subtract 12-bit immediates, shifted left by 12 bits
126 define 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
141   %val32 = load i32, ptr @var_i32
142   %newval32 = sub i32 %val32, 14610432 ; =0xdef000
143   store i32 %newval32, ptr @var_i32
145   %val64 = load i64, ptr @var_i64
146   %newval64 = sub i64 %val64, 16773120 ; =0xfff000
147   store i64 %newval64, ptr @var_i64
149   ret void
152 define 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
162 define 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
172 define 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
182 define 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
192 define 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
202 define 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
212 define 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
222 define 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
232 define 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
243 define 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
253 declare i32 @foox(i32)
255 define 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
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
276 define 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
315   %cmp_pos_small = icmp ne i32 %val, 4095
316   br i1 %cmp_pos_small, label %ret, label %test2
318 test2:
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
324 test3:
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
330 test4:
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
336 test5:
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
342 test6:
343   %newval6 = add i32 %val, 5
344   store i32 %newval6, ptr @var_i32
345   ret void
347 ret:
348   ret void
351 declare {i32, i1} @llvm.sadd.with.overflow.i32(i32 %a, i32 %b)
353 define 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
371 declare {i8, i1} @llvm.uadd.with.overflow.i8(i8 %a, i8 %b)
373 define 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
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
398 define 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
409 ; ADDS and SUBS Optimizations
410 ; Checks with all types first, then checks that only EQ and NE optimize
411 define 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
422 define 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
433 define 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
444 define 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
455 define 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
466 define 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
477 define 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
488 define 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
499 define 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
511 define 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
523 define 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
537 define 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
552 declare void @fooy()
554 define 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
566 3:                                                ; preds = %1
567   tail call void @fooy()
568   br label %4
569 4:                                                ; preds = %3, %1
570   ret void
573 define 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
586 3:                                                ; preds = %1
587   tail call void @fooy()
588   br label %4
589 4:                                                ; preds = %3, %1
590   ret void
593 define 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
623 ; Unique case found in ClangBuiltLinux where the DstReg is not Virtual and
624 ; caused an assertion failure
625 define 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
638 entry:
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
641 for.cond:                                         ; preds = %entry, %for.cond
642   br label %for.cond
643 if.end:                                           ; preds = %entry
644   ret i32 undef
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
650 declare dso_local i32 @crng_reseed(...) local_unnamed_addr
651 ; Function Attrs: nounwind uwtable
652 define 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
675 entry:
676   %cmp2 = icmp slt ptr @_extract_crng_crng, null
677   br i1 %cmp2, label %if.then, label %lor.lhs.false
678 lor.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
685 if.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
691 if.end:                                           ; preds = %if.then, %lor.lhs.false
692   ret i32 undef
695 ; ((X << C) - Y) + Z --> (Z - Y) + (X << C)
696 define 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
708 ; ((X >> C) - Y) + Z --> (Z - Y) + (X >> C)
709 define 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
721 ; ((X >> C) - Y) + Z --> (Z - Y) + (X >> C)
722 define 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
734 ; ((sext X) - Y) + Z --> (Z - Y) + (sext X)
735 define 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
747 ; ((sext_inreg X) - Y) + Z --> (Z - Y) + (sext_inreg X)
748 define 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
761 ; ((zext X) - Y) + Z --> (Z - Y) + (zext X)
762 define 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
775 ; ((anyext X) - Y) + Z --> (Z - Y) + (anyext X)
776 define 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
796 ; ((X and C) - Y) + Z --> (Z - Y) + (X and C)
797 define 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
809 ; Z + ((X << C) - Y) --> (Z - Y) + (X << C)
810 define 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
822 ; Y + ((X << C) - X) --> (Y - X) + (X << C)
823 define 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
834 ; negative case for ((X << C) - Y) + Z --> (Z - Y) + (X << C)
835 ; Y can't be constant to avoid dead loop
836 define 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
849 ; negative case for ((X << C) - Y) + Z --> (Z - Y) + (X << C)
850 ; Y can't be shift C also to avoid dead loop
851 define 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
865 define 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