xref: /llvm-project/llvm/test/CodeGen/AArch64/combine-comparisons-by-cse.ll (revision d2d4a1bbdc455a30d600743eb59fb1c69205967a)
1; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
2; RUN: llc -debugify-and-strip-all-safe < %s -mtriple=aarch64-linux-gnu | FileCheck %s
3
4; marked as external to prevent possible optimizations
5@a = external global i32
6@b = external global i32
7@c = external global i32
8@d = external global i32
9
10; (a > 10 && b == c) || (a >= 10 && b == d)
11define i32 @combine_gt_ge_10() #0 {
12; CHECK-LABEL: combine_gt_ge_10:
13; CHECK:       // %bb.0: // %entry
14; CHECK-NEXT:    adrp x8, :got:a
15; CHECK-NEXT:    ldr x8, [x8, :got_lo12:a]
16; CHECK-NEXT:    ldr w8, [x8]
17; CHECK-NEXT:    cmp w8, #10
18; CHECK-NEXT:    adrp x8, :got:b
19; CHECK-NEXT:    ldr x8, [x8, :got_lo12:b]
20; CHECK-NEXT:    b.le .LBB0_3
21; CHECK-NEXT:  // %bb.1: // %land.lhs.true
22; CHECK-NEXT:    adrp x9, :got:c
23; CHECK-NEXT:    ldr x9, [x9, :got_lo12:c]
24; CHECK-NEXT:    ldr w10, [x8]
25; CHECK-NEXT:    ldr w9, [x9]
26; CHECK-NEXT:    cmp w10, w9
27; CHECK-NEXT:    b.ne .LBB0_4
28; CHECK-NEXT:  // %bb.2:
29; CHECK-NEXT:    mov w0, #1 // =0x1
30; CHECK-NEXT:    ret
31; CHECK-NEXT:  .LBB0_3: // %lor.lhs.false
32; CHECK-NEXT:    b.lt .LBB0_6
33; CHECK-NEXT:  .LBB0_4: // %land.lhs.true3
34; CHECK-NEXT:    adrp x9, :got:d
35; CHECK-NEXT:    ldr x9, [x9, :got_lo12:d]
36; CHECK-NEXT:    ldr w8, [x8]
37; CHECK-NEXT:    ldr w9, [x9]
38; CHECK-NEXT:    cmp w8, w9
39; CHECK-NEXT:    b.ne .LBB0_6
40; CHECK-NEXT:  // %bb.5:
41; CHECK-NEXT:    mov w0, #1 // =0x1
42; CHECK-NEXT:    ret
43; CHECK-NEXT:  .LBB0_6: // %if.end
44; CHECK-NEXT:    mov w0, wzr
45; CHECK-NEXT:    ret
46entry:
47  %0 = load i32, ptr @a, align 4
48  %cmp = icmp sgt i32 %0, 10
49  br i1 %cmp, label %land.lhs.true, label %lor.lhs.false
50
51land.lhs.true:                                    ; preds = %entry
52  %1 = load i32, ptr @b, align 4
53  %2 = load i32, ptr @c, align 4
54  %cmp1 = icmp eq i32 %1, %2
55  br i1 %cmp1, label %return, label %land.lhs.true3
56
57lor.lhs.false:                                    ; preds = %entry
58  %cmp2 = icmp sgt i32 %0, 9
59  br i1 %cmp2, label %land.lhs.true3, label %if.end
60
61land.lhs.true3:                                   ; preds = %lor.lhs.false, %land.lhs.true
62  %3 = load i32, ptr @b, align 4
63  %4 = load i32, ptr @d, align 4
64  %cmp4 = icmp eq i32 %3, %4
65  br i1 %cmp4, label %return, label %if.end
66
67if.end:                                           ; preds = %land.lhs.true3, %lor.lhs.false
68  br label %return
69
70return:                                           ; preds = %if.end, %land.lhs.true3, %land.lhs.true
71  %retval.0 = phi i32 [ 0, %if.end ], [ 1, %land.lhs.true3 ], [ 1, %land.lhs.true ]
72  ret i32 %retval.0
73}
74
75; (a > 5 && b == c) || (a < 5 && b == d)
76define i32 @combine_gt_lt_5() #0 {
77; CHECK-LABEL: combine_gt_lt_5:
78; CHECK:       // %bb.0: // %entry
79; CHECK-NEXT:    adrp x8, :got:a
80; CHECK-NEXT:    ldr x8, [x8, :got_lo12:a]
81; CHECK-NEXT:    ldr w8, [x8]
82; CHECK-NEXT:    cmp w8, #5
83; CHECK-NEXT:    b.le .LBB1_3
84; CHECK-NEXT:  // %bb.1: // %land.lhs.true
85; CHECK-NEXT:    adrp x8, :got:b
86; CHECK-NEXT:    adrp x9, :got:c
87; CHECK-NEXT:    ldr x8, [x8, :got_lo12:b]
88; CHECK-NEXT:    ldr x9, [x9, :got_lo12:c]
89; CHECK-NEXT:    ldr w8, [x8]
90; CHECK-NEXT:    ldr w9, [x9]
91; CHECK-NEXT:    cmp w8, w9
92; CHECK-NEXT:    b.ne .LBB1_6
93; CHECK-NEXT:  // %bb.2:
94; CHECK-NEXT:    mov w0, #1 // =0x1
95; CHECK-NEXT:    ret
96; CHECK-NEXT:  .LBB1_3: // %lor.lhs.false
97; CHECK-NEXT:    b.ge .LBB1_6
98; CHECK-NEXT:  // %bb.4: // %land.lhs.true3
99; CHECK-NEXT:    adrp x8, :got:b
100; CHECK-NEXT:    adrp x9, :got:d
101; CHECK-NEXT:    ldr x8, [x8, :got_lo12:b]
102; CHECK-NEXT:    ldr x9, [x9, :got_lo12:d]
103; CHECK-NEXT:    ldr w8, [x8]
104; CHECK-NEXT:    ldr w9, [x9]
105; CHECK-NEXT:    cmp w8, w9
106; CHECK-NEXT:    b.ne .LBB1_6
107; CHECK-NEXT:  // %bb.5:
108; CHECK-NEXT:    mov w0, #1 // =0x1
109; CHECK-NEXT:    ret
110; CHECK-NEXT:  .LBB1_6: // %if.end
111; CHECK-NEXT:    mov w0, wzr
112; CHECK-NEXT:    ret
113entry:
114  %0 = load i32, ptr @a, align 4
115  %cmp = icmp sgt i32 %0, 5
116  br i1 %cmp, label %land.lhs.true, label %lor.lhs.false
117
118land.lhs.true:                                    ; preds = %entry
119  %1 = load i32, ptr @b, align 4
120  %2 = load i32, ptr @c, align 4
121  %cmp1 = icmp eq i32 %1, %2
122  br i1 %cmp1, label %return, label %if.end
123
124lor.lhs.false:                                    ; preds = %entry
125  %cmp2 = icmp slt i32 %0, 5
126  br i1 %cmp2, label %land.lhs.true3, label %if.end
127
128land.lhs.true3:                                   ; preds = %lor.lhs.false
129  %3 = load i32, ptr @b, align 4
130  %4 = load i32, ptr @d, align 4
131  %cmp4 = icmp eq i32 %3, %4
132  br i1 %cmp4, label %return, label %if.end
133
134if.end:                                           ; preds = %land.lhs.true3, %lor.lhs.false, %land.lhs.true
135  br label %return
136
137return:                                           ; preds = %if.end, %land.lhs.true3, %land.lhs.true
138  %retval.0 = phi i32 [ 0, %if.end ], [ 1, %land.lhs.true3 ], [ 1, %land.lhs.true ]
139  ret i32 %retval.0
140}
141
142; (a < 5 && b == c) || (a <= 5 && b == d)
143define i32 @combine_lt_ge_5() #0 {
144; CHECK-LABEL: combine_lt_ge_5:
145; CHECK:       // %bb.0: // %entry
146; CHECK-NEXT:    adrp x8, :got:a
147; CHECK-NEXT:    ldr x8, [x8, :got_lo12:a]
148; CHECK-NEXT:    ldr w8, [x8]
149; CHECK-NEXT:    cmp w8, #5
150; CHECK-NEXT:    adrp x8, :got:b
151; CHECK-NEXT:    ldr x8, [x8, :got_lo12:b]
152; CHECK-NEXT:    b.ge .LBB2_3
153; CHECK-NEXT:  // %bb.1: // %land.lhs.true
154; CHECK-NEXT:    adrp x9, :got:c
155; CHECK-NEXT:    ldr x9, [x9, :got_lo12:c]
156; CHECK-NEXT:    ldr w10, [x8]
157; CHECK-NEXT:    ldr w9, [x9]
158; CHECK-NEXT:    cmp w10, w9
159; CHECK-NEXT:    b.ne .LBB2_4
160; CHECK-NEXT:  // %bb.2:
161; CHECK-NEXT:    mov w0, #1 // =0x1
162; CHECK-NEXT:    ret
163; CHECK-NEXT:  .LBB2_3: // %lor.lhs.false
164; CHECK-NEXT:    b.gt .LBB2_6
165; CHECK-NEXT:  .LBB2_4: // %land.lhs.true3
166; CHECK-NEXT:    adrp x9, :got:d
167; CHECK-NEXT:    ldr x9, [x9, :got_lo12:d]
168; CHECK-NEXT:    ldr w8, [x8]
169; CHECK-NEXT:    ldr w9, [x9]
170; CHECK-NEXT:    cmp w8, w9
171; CHECK-NEXT:    b.ne .LBB2_6
172; CHECK-NEXT:  // %bb.5:
173; CHECK-NEXT:    mov w0, #1 // =0x1
174; CHECK-NEXT:    ret
175; CHECK-NEXT:  .LBB2_6: // %if.end
176; CHECK-NEXT:    mov w0, wzr
177; CHECK-NEXT:    ret
178entry:
179  %0 = load i32, ptr @a, align 4
180  %cmp = icmp slt i32 %0, 5
181  br i1 %cmp, label %land.lhs.true, label %lor.lhs.false
182
183land.lhs.true:                                    ; preds = %entry
184  %1 = load i32, ptr @b, align 4
185  %2 = load i32, ptr @c, align 4
186  %cmp1 = icmp eq i32 %1, %2
187  br i1 %cmp1, label %return, label %land.lhs.true3
188
189lor.lhs.false:                                    ; preds = %entry
190  %cmp2 = icmp slt i32 %0, 6
191  br i1 %cmp2, label %land.lhs.true3, label %if.end
192
193land.lhs.true3:                                   ; preds = %lor.lhs.false, %land.lhs.true
194  %3 = load i32, ptr @b, align 4
195  %4 = load i32, ptr @d, align 4
196  %cmp4 = icmp eq i32 %3, %4
197  br i1 %cmp4, label %return, label %if.end
198
199if.end:                                           ; preds = %land.lhs.true3, %lor.lhs.false
200  br label %return
201
202return:                                           ; preds = %if.end, %land.lhs.true3, %land.lhs.true
203  %retval.0 = phi i32 [ 0, %if.end ], [ 1, %land.lhs.true3 ], [ 1, %land.lhs.true ]
204  ret i32 %retval.0
205}
206
207; (a < 5 && b == c) || (a > 5 && b == d)
208define i32 @combine_lt_gt_5() #0 {
209; CHECK-LABEL: combine_lt_gt_5:
210; CHECK:       // %bb.0: // %entry
211; CHECK-NEXT:    adrp x8, :got:a
212; CHECK-NEXT:    ldr x8, [x8, :got_lo12:a]
213; CHECK-NEXT:    ldr w8, [x8]
214; CHECK-NEXT:    cmp w8, #5
215; CHECK-NEXT:    b.ge .LBB3_3
216; CHECK-NEXT:  // %bb.1: // %land.lhs.true
217; CHECK-NEXT:    adrp x8, :got:b
218; CHECK-NEXT:    adrp x9, :got:c
219; CHECK-NEXT:    ldr x8, [x8, :got_lo12:b]
220; CHECK-NEXT:    ldr x9, [x9, :got_lo12:c]
221; CHECK-NEXT:    ldr w8, [x8]
222; CHECK-NEXT:    ldr w9, [x9]
223; CHECK-NEXT:    cmp w8, w9
224; CHECK-NEXT:    b.ne .LBB3_6
225; CHECK-NEXT:  // %bb.2:
226; CHECK-NEXT:    mov w0, #1 // =0x1
227; CHECK-NEXT:    ret
228; CHECK-NEXT:  .LBB3_3: // %lor.lhs.false
229; CHECK-NEXT:    b.le .LBB3_6
230; CHECK-NEXT:  // %bb.4: // %land.lhs.true3
231; CHECK-NEXT:    adrp x8, :got:b
232; CHECK-NEXT:    adrp x9, :got:d
233; CHECK-NEXT:    ldr x8, [x8, :got_lo12:b]
234; CHECK-NEXT:    ldr x9, [x9, :got_lo12:d]
235; CHECK-NEXT:    ldr w8, [x8]
236; CHECK-NEXT:    ldr w9, [x9]
237; CHECK-NEXT:    cmp w8, w9
238; CHECK-NEXT:    b.ne .LBB3_6
239; CHECK-NEXT:  // %bb.5:
240; CHECK-NEXT:    mov w0, #1 // =0x1
241; CHECK-NEXT:    ret
242; CHECK-NEXT:  .LBB3_6: // %if.end
243; CHECK-NEXT:    mov w0, wzr
244; CHECK-NEXT:    ret
245entry:
246  %0 = load i32, ptr @a, align 4
247  %cmp = icmp slt i32 %0, 5
248  br i1 %cmp, label %land.lhs.true, label %lor.lhs.false
249
250land.lhs.true:                                    ; preds = %entry
251  %1 = load i32, ptr @b, align 4
252  %2 = load i32, ptr @c, align 4
253  %cmp1 = icmp eq i32 %1, %2
254  br i1 %cmp1, label %return, label %if.end
255
256lor.lhs.false:                                    ; preds = %entry
257  %cmp2 = icmp sgt i32 %0, 5
258  br i1 %cmp2, label %land.lhs.true3, label %if.end
259
260land.lhs.true3:                                   ; preds = %lor.lhs.false
261  %3 = load i32, ptr @b, align 4
262  %4 = load i32, ptr @d, align 4
263  %cmp4 = icmp eq i32 %3, %4
264  br i1 %cmp4, label %return, label %if.end
265
266if.end:                                           ; preds = %land.lhs.true3, %lor.lhs.false, %land.lhs.true
267  br label %return
268
269return:                                           ; preds = %if.end, %land.lhs.true3, %land.lhs.true
270  %retval.0 = phi i32 [ 0, %if.end ], [ 1, %land.lhs.true3 ], [ 1, %land.lhs.true ]
271  ret i32 %retval.0
272}
273
274; (a > -5 && b == c) || (a < -5 && b == d)
275define i32 @combine_gt_lt_n5() #0 {
276; CHECK-LABEL: combine_gt_lt_n5:
277; CHECK:       // %bb.0: // %entry
278; CHECK-NEXT:    adrp x8, :got:a
279; CHECK-NEXT:    ldr x8, [x8, :got_lo12:a]
280; CHECK-NEXT:    ldr w8, [x8]
281; CHECK-NEXT:    cmn w8, #5
282; CHECK-NEXT:    b.le .LBB4_3
283; CHECK-NEXT:  // %bb.1: // %land.lhs.true
284; CHECK-NEXT:    adrp x8, :got:b
285; CHECK-NEXT:    adrp x9, :got:c
286; CHECK-NEXT:    ldr x8, [x8, :got_lo12:b]
287; CHECK-NEXT:    ldr x9, [x9, :got_lo12:c]
288; CHECK-NEXT:    ldr w8, [x8]
289; CHECK-NEXT:    ldr w9, [x9]
290; CHECK-NEXT:    cmp w8, w9
291; CHECK-NEXT:    b.ne .LBB4_6
292; CHECK-NEXT:  // %bb.2:
293; CHECK-NEXT:    mov w0, #1 // =0x1
294; CHECK-NEXT:    ret
295; CHECK-NEXT:  .LBB4_3: // %lor.lhs.false
296; CHECK-NEXT:    b.ge .LBB4_6
297; CHECK-NEXT:  // %bb.4: // %land.lhs.true3
298; CHECK-NEXT:    adrp x8, :got:b
299; CHECK-NEXT:    adrp x9, :got:d
300; CHECK-NEXT:    ldr x8, [x8, :got_lo12:b]
301; CHECK-NEXT:    ldr x9, [x9, :got_lo12:d]
302; CHECK-NEXT:    ldr w8, [x8]
303; CHECK-NEXT:    ldr w9, [x9]
304; CHECK-NEXT:    cmp w8, w9
305; CHECK-NEXT:    b.ne .LBB4_6
306; CHECK-NEXT:  // %bb.5:
307; CHECK-NEXT:    mov w0, #1 // =0x1
308; CHECK-NEXT:    ret
309; CHECK-NEXT:  .LBB4_6: // %if.end
310; CHECK-NEXT:    mov w0, wzr
311; CHECK-NEXT:    ret
312entry:
313  %0 = load i32, ptr @a, align 4
314  %cmp = icmp sgt i32 %0, -5
315  br i1 %cmp, label %land.lhs.true, label %lor.lhs.false
316
317land.lhs.true:                                    ; preds = %entry
318  %1 = load i32, ptr @b, align 4
319  %2 = load i32, ptr @c, align 4
320  %cmp1 = icmp eq i32 %1, %2
321  br i1 %cmp1, label %return, label %if.end
322
323lor.lhs.false:                                    ; preds = %entry
324  %cmp2 = icmp slt i32 %0, -5
325  br i1 %cmp2, label %land.lhs.true3, label %if.end
326
327land.lhs.true3:                                   ; preds = %lor.lhs.false
328  %3 = load i32, ptr @b, align 4
329  %4 = load i32, ptr @d, align 4
330  %cmp4 = icmp eq i32 %3, %4
331  br i1 %cmp4, label %return, label %if.end
332
333if.end:                                           ; preds = %land.lhs.true3, %lor.lhs.false, %land.lhs.true
334  br label %return
335
336return:                                           ; preds = %if.end, %land.lhs.true3, %land.lhs.true
337  %retval.0 = phi i32 [ 0, %if.end ], [ 1, %land.lhs.true3 ], [ 1, %land.lhs.true ]
338  ret i32 %retval.0
339}
340
341; (a < -5 && b == c) || (a > -5 && b == d)
342define i32 @combine_lt_gt_n5() #0 {
343; CHECK-LABEL: combine_lt_gt_n5:
344; CHECK:       // %bb.0: // %entry
345; CHECK-NEXT:    adrp x8, :got:a
346; CHECK-NEXT:    ldr x8, [x8, :got_lo12:a]
347; CHECK-NEXT:    ldr w8, [x8]
348; CHECK-NEXT:    cmn w8, #5
349; CHECK-NEXT:    b.ge .LBB5_3
350; CHECK-NEXT:  // %bb.1: // %land.lhs.true
351; CHECK-NEXT:    adrp x8, :got:b
352; CHECK-NEXT:    adrp x9, :got:c
353; CHECK-NEXT:    ldr x8, [x8, :got_lo12:b]
354; CHECK-NEXT:    ldr x9, [x9, :got_lo12:c]
355; CHECK-NEXT:    ldr w8, [x8]
356; CHECK-NEXT:    ldr w9, [x9]
357; CHECK-NEXT:    cmp w8, w9
358; CHECK-NEXT:    b.ne .LBB5_6
359; CHECK-NEXT:  // %bb.2:
360; CHECK-NEXT:    mov w0, #1 // =0x1
361; CHECK-NEXT:    ret
362; CHECK-NEXT:  .LBB5_3: // %lor.lhs.false
363; CHECK-NEXT:    b.le .LBB5_6
364; CHECK-NEXT:  // %bb.4: // %land.lhs.true3
365; CHECK-NEXT:    adrp x8, :got:b
366; CHECK-NEXT:    adrp x9, :got:d
367; CHECK-NEXT:    ldr x8, [x8, :got_lo12:b]
368; CHECK-NEXT:    ldr x9, [x9, :got_lo12:d]
369; CHECK-NEXT:    ldr w8, [x8]
370; CHECK-NEXT:    ldr w9, [x9]
371; CHECK-NEXT:    cmp w8, w9
372; CHECK-NEXT:    b.ne .LBB5_6
373; CHECK-NEXT:  // %bb.5:
374; CHECK-NEXT:    mov w0, #1 // =0x1
375; CHECK-NEXT:    ret
376; CHECK-NEXT:  .LBB5_6: // %if.end
377; CHECK-NEXT:    mov w0, wzr
378; CHECK-NEXT:    ret
379entry:
380  %0 = load i32, ptr @a, align 4
381  %cmp = icmp slt i32 %0, -5
382  br i1 %cmp, label %land.lhs.true, label %lor.lhs.false
383
384land.lhs.true:                                    ; preds = %entry
385  %1 = load i32, ptr @b, align 4
386  %2 = load i32, ptr @c, align 4
387  %cmp1 = icmp eq i32 %1, %2
388  br i1 %cmp1, label %return, label %if.end
389
390lor.lhs.false:                                    ; preds = %entry
391  %cmp2 = icmp sgt i32 %0, -5
392  br i1 %cmp2, label %land.lhs.true3, label %if.end
393
394land.lhs.true3:                                   ; preds = %lor.lhs.false
395  %3 = load i32, ptr @b, align 4
396  %4 = load i32, ptr @d, align 4
397  %cmp4 = icmp eq i32 %3, %4
398  br i1 %cmp4, label %return, label %if.end
399
400if.end:                                           ; preds = %land.lhs.true3, %lor.lhs.false, %land.lhs.true
401  br label %return
402
403return:                                           ; preds = %if.end, %land.lhs.true3, %land.lhs.true
404  %retval.0 = phi i32 [ 0, %if.end ], [ 1, %land.lhs.true3 ], [ 1, %land.lhs.true ]
405  ret i32 %retval.0
406}
407
408%struct.Struct = type { i64, i64 }
409
410@glob = internal unnamed_addr global ptr null, align 8
411
412declare ptr @Update(ptr) #1
413
414; no checks for this case, it just should be processed without errors
415define void @combine_non_adjacent_cmp_br(ptr nocapture readonly %hdCall) #0 {
416; CHECK-LABEL: combine_non_adjacent_cmp_br:
417; CHECK:       // %bb.0: // %entry
418; CHECK-NEXT:    str x30, [sp, #-48]! // 8-byte Folded Spill
419; CHECK-NEXT:    .cfi_def_cfa_offset 48
420; CHECK-NEXT:    stp x22, x21, [sp, #16] // 16-byte Folded Spill
421; CHECK-NEXT:    stp x20, x19, [sp, #32] // 16-byte Folded Spill
422; CHECK-NEXT:    .cfi_offset w19, -8
423; CHECK-NEXT:    .cfi_offset w20, -16
424; CHECK-NEXT:    .cfi_offset w21, -24
425; CHECK-NEXT:    .cfi_offset w22, -32
426; CHECK-NEXT:    .cfi_offset w30, -48
427; CHECK-NEXT:    ldr x20, [x0]
428; CHECK-NEXT:    mov w19, #24 // =0x18
429; CHECK-NEXT:    adrp x22, glob
430; CHECK-NEXT:    add x21, x20, #2
431; CHECK-NEXT:  .LBB6_1: // %land.rhs
432; CHECK-NEXT:    // =>This Inner Loop Header: Depth=1
433; CHECK-NEXT:    ldr x8, [x19]
434; CHECK-NEXT:    cmp x8, #1
435; CHECK-NEXT:    b.lt .LBB6_3
436; CHECK-NEXT:  // %bb.2: // %while.body
437; CHECK-NEXT:    // in Loop: Header=BB6_1 Depth=1
438; CHECK-NEXT:    ldr x0, [x22, :lo12:glob]
439; CHECK-NEXT:    bl Update
440; CHECK-NEXT:    sub x21, x21, #2
441; CHECK-NEXT:    cmp x20, x21
442; CHECK-NEXT:    b.lt .LBB6_1
443; CHECK-NEXT:  .LBB6_3: // %while.end
444; CHECK-NEXT:    ldp x20, x19, [sp, #32] // 16-byte Folded Reload
445; CHECK-NEXT:    ldp x22, x21, [sp, #16] // 16-byte Folded Reload
446; CHECK-NEXT:    ldr x30, [sp], #48 // 8-byte Folded Reload
447; CHECK-NEXT:    .cfi_def_cfa_offset 0
448; CHECK-NEXT:    .cfi_restore w19
449; CHECK-NEXT:    .cfi_restore w20
450; CHECK-NEXT:    .cfi_restore w21
451; CHECK-NEXT:    .cfi_restore w22
452; CHECK-NEXT:    .cfi_restore w30
453; CHECK-NEXT:    ret
454entry:
455  %0 = load i64, ptr %hdCall, align 8
456  br label %land.rhs
457
458land.rhs:
459  %rp.06 = phi i64 [ %0, %entry ], [ %sub, %while.body ]
460  %1 = load i64, ptr inttoptr (i64 24 to ptr), align 8
461  %cmp2 = icmp sgt i64 %1, 0
462  br i1 %cmp2, label %while.body, label %while.end
463
464while.body:
465  %2 = load ptr, ptr @glob, align 8
466  %call = tail call ptr @Update(ptr %2) #2
467  %sub = add nsw i64 %rp.06, -2
468  %cmp = icmp slt i64 %0, %rp.06
469  br i1 %cmp, label %land.rhs, label %while.end
470
471while.end:
472  ret void
473}
474
475; undefined external to prevent possible optimizations
476declare void @do_something() #1
477
478define i32 @do_nothing_if_resultant_opcodes_would_differ() #0 {
479; CHECK-LABEL: do_nothing_if_resultant_opcodes_would_differ:
480; CHECK:       // %bb.0: // %entry
481; CHECK-NEXT:    str x30, [sp, #-32]! // 8-byte Folded Spill
482; CHECK-NEXT:    .cfi_def_cfa_offset 32
483; CHECK-NEXT:    stp x20, x19, [sp, #16] // 16-byte Folded Spill
484; CHECK-NEXT:    .cfi_offset w19, -8
485; CHECK-NEXT:    .cfi_offset w20, -16
486; CHECK-NEXT:    .cfi_offset w30, -32
487; CHECK-NEXT:    adrp x19, :got:a
488; CHECK-NEXT:    ldr x19, [x19, :got_lo12:a]
489; CHECK-NEXT:    ldr w8, [x19]
490; CHECK-NEXT:    cmn w8, #2
491; CHECK-NEXT:    b.gt .LBB7_4
492; CHECK-NEXT:  // %bb.1: // %while.body.preheader
493; CHECK-NEXT:    sub w20, w8, #1
494; CHECK-NEXT:  .LBB7_2: // %while.body
495; CHECK-NEXT:    // =>This Inner Loop Header: Depth=1
496; CHECK-NEXT:    bl do_something
497; CHECK-NEXT:    adds w20, w20, #1
498; CHECK-NEXT:    b.mi .LBB7_2
499; CHECK-NEXT:  // %bb.3: // %while.cond.while.end_crit_edge
500; CHECK-NEXT:    ldr w8, [x19]
501; CHECK-NEXT:  .LBB7_4: // %while.end
502; CHECK-NEXT:    cmp w8, #1
503; CHECK-NEXT:    b.gt .LBB7_7
504; CHECK-NEXT:  // %bb.5: // %land.lhs.true
505; CHECK-NEXT:    adrp x8, :got:b
506; CHECK-NEXT:    adrp x9, :got:d
507; CHECK-NEXT:    ldr x8, [x8, :got_lo12:b]
508; CHECK-NEXT:    ldr x9, [x9, :got_lo12:d]
509; CHECK-NEXT:    ldr w8, [x8]
510; CHECK-NEXT:    ldr w9, [x9]
511; CHECK-NEXT:    cmp w8, w9
512; CHECK-NEXT:    b.ne .LBB7_7
513; CHECK-NEXT:  // %bb.6:
514; CHECK-NEXT:    mov w0, #123 // =0x7b
515; CHECK-NEXT:    b .LBB7_8
516; CHECK-NEXT:  .LBB7_7: // %if.end
517; CHECK-NEXT:    mov w0, wzr
518; CHECK-NEXT:  .LBB7_8: // %return
519; CHECK-NEXT:    ldp x20, x19, [sp, #16] // 16-byte Folded Reload
520; CHECK-NEXT:    ldr x30, [sp], #32 // 8-byte Folded Reload
521; CHECK-NEXT:    .cfi_def_cfa_offset 0
522; CHECK-NEXT:    .cfi_restore w19
523; CHECK-NEXT:    .cfi_restore w20
524; CHECK-NEXT:    .cfi_restore w30
525; CHECK-NEXT:    ret
526entry:
527  %0 = load i32, ptr @a, align 4
528  %cmp4 = icmp slt i32 %0, -1
529  br i1 %cmp4, label %while.body.preheader, label %while.end
530
531while.body.preheader:                             ; preds = %entry
532  br label %while.body
533
534while.body:                                       ; preds = %while.body, %while.body.preheader
535  %i.05 = phi i32 [ %inc, %while.body ], [ %0, %while.body.preheader ]
536  tail call void @do_something() #2
537  %inc = add nsw i32 %i.05, 1
538  %cmp = icmp slt i32 %i.05, 0
539  br i1 %cmp, label %while.body, label %while.cond.while.end_crit_edge
540
541while.cond.while.end_crit_edge:                   ; preds = %while.body
542  %.pre = load i32, ptr @a, align 4
543  br label %while.end
544
545while.end:                                        ; preds = %while.cond.while.end_crit_edge, %entry
546  %1 = phi i32 [ %.pre, %while.cond.while.end_crit_edge ], [ %0, %entry ]
547  %cmp1 = icmp slt i32 %1, 2
548  br i1 %cmp1, label %land.lhs.true, label %if.end
549
550land.lhs.true:                                    ; preds = %while.end
551  %2 = load i32, ptr @b, align 4
552  %3 = load i32, ptr @d, align 4
553  %cmp2 = icmp eq i32 %2, %3
554  br i1 %cmp2, label %return, label %if.end
555
556if.end:                                           ; preds = %land.lhs.true, %while.end
557  br label %return
558
559return:                                           ; preds = %if.end, %land.lhs.true
560  %retval.0 = phi i32 [ 0, %if.end ], [ 123, %land.lhs.true ]
561  ret i32 %retval.0
562}
563
564define i32 @do_nothing_if_compares_can_not_be_adjusted_to_each_other() #0 {
565; CHECK-LABEL: do_nothing_if_compares_can_not_be_adjusted_to_each_other:
566; CHECK:       // %bb.0: // %entry
567; CHECK-NEXT:    stp x30, x19, [sp, #-16]! // 16-byte Folded Spill
568; CHECK-NEXT:    .cfi_def_cfa_offset 16
569; CHECK-NEXT:    .cfi_offset w19, -8
570; CHECK-NEXT:    .cfi_offset w30, -16
571; CHECK-NEXT:    .cfi_remember_state
572; CHECK-NEXT:    adrp x8, :got:a
573; CHECK-NEXT:    ldr x8, [x8, :got_lo12:a]
574; CHECK-NEXT:    ldr w8, [x8]
575; CHECK-NEXT:    cmp w8, #0
576; CHECK-NEXT:    b.gt .LBB8_3
577; CHECK-NEXT:  // %bb.1: // %while.body.preheader
578; CHECK-NEXT:    sub w19, w8, #1
579; CHECK-NEXT:  .LBB8_2: // %while.body
580; CHECK-NEXT:    // =>This Inner Loop Header: Depth=1
581; CHECK-NEXT:    bl do_something
582; CHECK-NEXT:    adds w19, w19, #1
583; CHECK-NEXT:    b.mi .LBB8_2
584; CHECK-NEXT:  .LBB8_3: // %while.end
585; CHECK-NEXT:    adrp x8, :got:c
586; CHECK-NEXT:    ldr x8, [x8, :got_lo12:c]
587; CHECK-NEXT:    ldr w8, [x8]
588; CHECK-NEXT:    cmn w8, #2
589; CHECK-NEXT:    b.lt .LBB8_6
590; CHECK-NEXT:  // %bb.4: // %land.lhs.true
591; CHECK-NEXT:    adrp x8, :got:b
592; CHECK-NEXT:    adrp x9, :got:d
593; CHECK-NEXT:    ldr x8, [x8, :got_lo12:b]
594; CHECK-NEXT:    ldr x9, [x9, :got_lo12:d]
595; CHECK-NEXT:    ldr w8, [x8]
596; CHECK-NEXT:    ldr w9, [x9]
597; CHECK-NEXT:    cmp w8, w9
598; CHECK-NEXT:    b.ne .LBB8_6
599; CHECK-NEXT:  // %bb.5:
600; CHECK-NEXT:    mov w0, #123 // =0x7b
601; CHECK-NEXT:    ldp x30, x19, [sp], #16 // 16-byte Folded Reload
602; CHECK-NEXT:    .cfi_def_cfa_offset 0
603; CHECK-NEXT:    .cfi_restore w19
604; CHECK-NEXT:    .cfi_restore w30
605; CHECK-NEXT:    ret
606; CHECK-NEXT:  .LBB8_6: // %if.end
607; CHECK-NEXT:    .cfi_restore_state
608; CHECK-NEXT:    mov w0, wzr
609; CHECK-NEXT:    ldp x30, x19, [sp], #16 // 16-byte Folded Reload
610; CHECK-NEXT:    .cfi_def_cfa_offset 0
611; CHECK-NEXT:    .cfi_restore w19
612; CHECK-NEXT:    .cfi_restore w30
613; CHECK-NEXT:    ret
614entry:
615  %0 = load i32, ptr @a, align 4
616  %cmp4 = icmp slt i32 %0, 1
617  br i1 %cmp4, label %while.body.preheader, label %while.end
618
619while.body.preheader:                             ; preds = %entry
620  br label %while.body
621
622while.body:                                       ; preds = %while.body, %while.body.preheader
623  %i.05 = phi i32 [ %inc, %while.body ], [ %0, %while.body.preheader ]
624  tail call void @do_something() #2
625  %inc = add nsw i32 %i.05, 1
626  %cmp = icmp slt i32 %i.05, 0
627  br i1 %cmp, label %while.body, label %while.end.loopexit
628
629while.end.loopexit:                               ; preds = %while.body
630  br label %while.end
631
632while.end:                                        ; preds = %while.end.loopexit, %entry
633  %1 = load i32, ptr @c, align 4
634  %cmp1 = icmp sgt i32 %1, -3
635  br i1 %cmp1, label %land.lhs.true, label %if.end
636
637land.lhs.true:                                    ; preds = %while.end
638  %2 = load i32, ptr @b, align 4
639  %3 = load i32, ptr @d, align 4
640  %cmp2 = icmp eq i32 %2, %3
641  br i1 %cmp2, label %return, label %if.end
642
643if.end:                                           ; preds = %land.lhs.true, %while.end
644  br label %return
645
646return:                                           ; preds = %if.end, %land.lhs.true
647  %retval.0 = phi i32 [ 0, %if.end ], [ 123, %land.lhs.true ]
648  ret i32 %retval.0
649}
650
651; Test in the following case, we don't hit 'cmp' and trigger a false positive
652; cmp  w19, #0
653; cinc w0, w19, gt
654; ...
655; fcmp d8, #0.0
656; b.gt .LBB0_5
657
658define i32 @fcmpri(i32 %argc, ptr nocapture readonly %argv) #0 {
659; CHECK-LABEL: fcmpri:
660; CHECK:       // %bb.0: // %entry
661; CHECK-NEXT:    cmp w0, #2
662; CHECK-NEXT:    b.lt .LBB9_3
663; CHECK-NEXT:  // %bb.1: // %land.lhs.true
664; CHECK-NEXT:    ldr x8, [x1, #8]
665; CHECK-NEXT:    cbz x8, .LBB9_3
666; CHECK-NEXT:  // %bb.2:
667; CHECK-NEXT:    mov w0, #3 // =0x3
668; CHECK-NEXT:    ret
669; CHECK-NEXT:  .LBB9_3: // %if.end
670; CHECK-NEXT:    str d8, [sp, #-32]! // 8-byte Folded Spill
671; CHECK-NEXT:    .cfi_def_cfa_offset 32
672; CHECK-NEXT:    stp x30, x19, [sp, #16] // 16-byte Folded Spill
673; CHECK-NEXT:    .cfi_offset w19, -8
674; CHECK-NEXT:    .cfi_offset w30, -16
675; CHECK-NEXT:    .cfi_offset b8, -32
676; CHECK-NEXT:    mov w0, #1 // =0x1
677; CHECK-NEXT:    bl zoo
678; CHECK-NEXT:    mov w19, w0
679; CHECK-NEXT:    mov w0, #-1 // =0xffffffff
680; CHECK-NEXT:    bl yoo
681; CHECK-NEXT:    cmp w19, #0
682; CHECK-NEXT:    mov w1, #2 // =0x2
683; CHECK-NEXT:    fmov d8, d0
684; CHECK-NEXT:    cinc w0, w19, gt
685; CHECK-NEXT:    bl xoo
686; CHECK-NEXT:    fmov d0, #-1.00000000
687; CHECK-NEXT:    fcmp d8, #0.0
688; CHECK-NEXT:    fmov d1, #-2.00000000
689; CHECK-NEXT:    fadd d0, d8, d0
690; CHECK-NEXT:    fcsel d0, d8, d0, gt
691; CHECK-NEXT:    bl woo
692; CHECK-NEXT:    ldp x30, x19, [sp, #16] // 16-byte Folded Reload
693; CHECK-NEXT:    mov w0, #4 // =0x4
694; CHECK-NEXT:    ldr d8, [sp], #32 // 8-byte Folded Reload
695; CHECK-NEXT:    .cfi_def_cfa_offset 0
696; CHECK-NEXT:    .cfi_restore w19
697; CHECK-NEXT:    .cfi_restore w30
698; CHECK-NEXT:    .cfi_restore b8
699; CHECK-NEXT:    ret
700
701; CHECK-LABEL-DAG: .LBB9_3
702
703entry:
704  %cmp = icmp sgt i32 %argc, 1
705  br i1 %cmp, label %land.lhs.true, label %if.end
706
707land.lhs.true:                                    ; preds = %entry
708  %arrayidx = getelementptr inbounds ptr, ptr %argv, i64 1
709  %0 = load ptr, ptr %arrayidx, align 8
710  %cmp1 = icmp eq ptr %0, null
711  br i1 %cmp1, label %if.end, label %return
712
713if.end:                                           ; preds = %land.lhs.true, %entry
714  %call = call i32 @zoo(i32 1)
715  %call2 = call double @yoo(i32 -1)
716  %cmp4 = icmp sgt i32 %call, 0
717  %add = zext i1 %cmp4 to i32
718  %cond = add nsw i32 %add, %call
719  %call7 = call i32 @xoo(i32 %cond, i32 2)
720  %cmp9 = fcmp ogt double %call2, 0.000000e+00
721  br i1 %cmp9, label %cond.end14, label %cond.false12
722
723cond.false12:                                     ; preds = %if.end
724  %sub = fadd fast double %call2, -1.000000e+00
725  br label %cond.end14
726
727cond.end14:                                       ; preds = %if.end, %cond.false12
728  %cond15 = phi double [ %sub, %cond.false12 ], [ %call2, %if.end ]
729  %call16 = call i32 @woo(double %cond15, double -2.000000e+00)
730  br label %return
731
732return:                                           ; preds = %land.lhs.true, %cond.end14
733  %retval.0 = phi i32 [ 4, %cond.end14 ], [ 3, %land.lhs.true ]
734  ret i32 %retval.0
735}
736
737define void @cmp_shifted(i32 %in, i32 %lhs, i32 %rhs) #0 {
738; CHECK-LABEL: cmp_shifted:
739; CHECK:       // %bb.0: // %common.ret
740; CHECK-NEXT:    str x30, [sp, #-16]! // 8-byte Folded Spill
741; CHECK-NEXT:    .cfi_def_cfa_offset 16
742; CHECK-NEXT:    .cfi_offset w30, -16
743; CHECK-NEXT:    mov w8, #42 // =0x2a
744; CHECK-NEXT:    cmp w0, #0
745; CHECK-NEXT:    mov w9, #128 // =0x80
746; CHECK-NEXT:    csinc w8, w8, wzr, gt
747; CHECK-NEXT:    cmp w0, #2, lsl #12 // =8192
748; CHECK-NEXT:    csel w0, w9, w8, ge
749; CHECK-NEXT:    bl zoo
750; CHECK-NEXT:    ldr x30, [sp], #16 // 8-byte Folded Reload
751; CHECK-NEXT:    .cfi_def_cfa_offset 0
752; CHECK-NEXT:    .cfi_restore w30
753; CHECK-NEXT:    ret
754; [...]
755
756  %tst_low = icmp sgt i32 %in, 8191
757  br i1 %tst_low, label %true, label %false
758
759true:
760  call i32 @zoo(i32 128)
761  ret void
762
763false:
764  %tst = icmp sgt i32 %in, 0
765  br i1 %tst, label %truer, label %falser
766
767truer:
768  call i32 @zoo(i32 42)
769  ret void
770
771falser:
772  call i32 @zoo(i32 1)
773  ret void
774}
775
776define i32 @combine_gt_ge_sel(i64 %v, ptr %p) #0 {
777; CHECK-LABEL: combine_gt_ge_sel:
778; CHECK:       // %bb.0: // %entry
779; CHECK-NEXT:    adrp x8, :got:a
780; CHECK-NEXT:    ldr x8, [x8, :got_lo12:a]
781; CHECK-NEXT:    ldr w8, [x8]
782; CHECK-NEXT:    cmp w8, #0
783; CHECK-NEXT:    csel x9, x0, xzr, gt
784; CHECK-NEXT:    str x9, [x1]
785; CHECK-NEXT:    b.le .LBB11_2
786; CHECK-NEXT:  // %bb.1: // %lor.lhs.false
787; CHECK-NEXT:    cmp w8, #2
788; CHECK-NEXT:    b.ge .LBB11_4
789; CHECK-NEXT:    b .LBB11_6
790; CHECK-NEXT:  .LBB11_2: // %land.lhs.true
791; CHECK-NEXT:    adrp x8, :got:b
792; CHECK-NEXT:    adrp x9, :got:c
793; CHECK-NEXT:    ldr x8, [x8, :got_lo12:b]
794; CHECK-NEXT:    ldr x9, [x9, :got_lo12:c]
795; CHECK-NEXT:    ldr w8, [x8]
796; CHECK-NEXT:    ldr w9, [x9]
797; CHECK-NEXT:    cmp w8, w9
798; CHECK-NEXT:    b.ne .LBB11_4
799; CHECK-NEXT:  // %bb.3:
800; CHECK-NEXT:    mov w0, #1 // =0x1
801; CHECK-NEXT:    ret
802; CHECK-NEXT:  .LBB11_4: // %land.lhs.true3
803; CHECK-NEXT:    adrp x8, :got:b
804; CHECK-NEXT:    adrp x9, :got:d
805; CHECK-NEXT:    ldr x8, [x8, :got_lo12:b]
806; CHECK-NEXT:    ldr x9, [x9, :got_lo12:d]
807; CHECK-NEXT:    ldr w8, [x8]
808; CHECK-NEXT:    ldr w9, [x9]
809; CHECK-NEXT:    cmp w8, w9
810; CHECK-NEXT:    b.ne .LBB11_6
811; CHECK-NEXT:  // %bb.5:
812; CHECK-NEXT:    mov w0, #1 // =0x1
813; CHECK-NEXT:    ret
814; CHECK-NEXT:  .LBB11_6: // %if.end
815; CHECK-NEXT:    mov w0, wzr
816; CHECK-NEXT:    ret
817entry:
818  %0 = load i32, ptr @a, align 4
819  %cmp = icmp sgt i32 %0, 0
820  %m = select i1 %cmp, i64 %v, i64 0
821  store i64 %m, ptr %p
822  br i1 %cmp, label %lor.lhs.false, label %land.lhs.true
823
824land.lhs.true:                                    ; preds = %entry
825  %1 = load i32, ptr @b, align 4
826  %2 = load i32, ptr @c, align 4
827  %cmp1 = icmp eq i32 %1, %2
828  br i1 %cmp1, label %return, label %land.lhs.true3
829
830lor.lhs.false:                                    ; preds = %entry
831  %cmp2 = icmp sgt i32 %0, 1
832  br i1 %cmp2, label %land.lhs.true3, label %if.end
833
834land.lhs.true3:                                   ; preds = %lor.lhs.false, %land.lhs.true
835  %3 = load i32, ptr @b, align 4
836  %4 = load i32, ptr @d, align 4
837  %cmp4 = icmp eq i32 %3, %4
838  br i1 %cmp4, label %return, label %if.end
839
840if.end:                                           ; preds = %land.lhs.true3, %lor.lhs.false
841  br label %return
842
843return:                                           ; preds = %if.end, %land.lhs.true3, %land.lhs.true
844  %retval.0 = phi i32 [ 0, %if.end ], [ 1, %land.lhs.true3 ], [ 1, %land.lhs.true ]
845  ret i32 %retval.0
846}
847
848declare i32 @zoo(i32)
849
850declare double @yoo(i32)
851
852declare i32 @xoo(i32, i32)
853
854declare i32 @woo(double, double)
855
856attributes #0 = { uwtable }
857