[NFC][RemoveDIs] Prefer iterators over inst-pointers in InstCombine
[llvm-project.git] / llvm / test / CodeGen / AArch64 / cgp-usubo.ll
blob2f081cf96d8b88fb69b45a8863919e13e8a77bec
1 ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
2 ; RUN: llc < %s -mtriple=aarch64-- | FileCheck %s
4 ; CodeGenPrepare is expected to form overflow intrinsics to improve DAG/isel.
6 define i1 @usubo_ult_i64(i64 %x, i64 %y, ptr %p) nounwind {
7 ; CHECK-LABEL: usubo_ult_i64:
8 ; CHECK:       // %bb.0:
9 ; CHECK-NEXT:    subs x8, x0, x1
10 ; CHECK-NEXT:    cset w0, lo
11 ; CHECK-NEXT:    str x8, [x2]
12 ; CHECK-NEXT:    ret
13   %s = sub i64 %x, %y
14   store i64 %s, ptr %p
15   %ov = icmp ult i64 %x, %y
16   ret i1 %ov
19 ; Verify insertion point for single-BB. Toggle predicate.
21 define i1 @usubo_ugt_i32(i32 %x, i32 %y, ptr %p) nounwind {
22 ; CHECK-LABEL: usubo_ugt_i32:
23 ; CHECK:       // %bb.0:
24 ; CHECK-NEXT:    subs w8, w0, w1
25 ; CHECK-NEXT:    cset w0, lo
26 ; CHECK-NEXT:    str w8, [x2]
27 ; CHECK-NEXT:    ret
28   %ov = icmp ugt i32 %y, %x
29   %s = sub i32 %x, %y
30   store i32 %s, ptr %p
31   ret i1 %ov
34 ; Constant operand should match.
36 define i1 @usubo_ugt_constant_op0_i8(i8 %x, ptr %p) nounwind {
37 ; CHECK-LABEL: usubo_ugt_constant_op0_i8:
38 ; CHECK:       // %bb.0:
39 ; CHECK-NEXT:    and w8, w0, #0xff
40 ; CHECK-NEXT:    mov w9, #42 // =0x2a
41 ; CHECK-NEXT:    cmp w8, #42
42 ; CHECK-NEXT:    sub w9, w9, w0
43 ; CHECK-NEXT:    cset w8, hi
44 ; CHECK-NEXT:    strb w9, [x1]
45 ; CHECK-NEXT:    mov w0, w8
46 ; CHECK-NEXT:    ret
47   %s = sub i8 42, %x
48   %ov = icmp ugt i8 %x, 42
49   store i8 %s, ptr %p
50   ret i1 %ov
53 ; Compare with constant operand 0 is canonicalized by commuting, but verify match for non-canonical form.
55 define i1 @usubo_ult_constant_op0_i16(i16 %x, ptr %p) nounwind {
56 ; CHECK-LABEL: usubo_ult_constant_op0_i16:
57 ; CHECK:       // %bb.0:
58 ; CHECK-NEXT:    and w8, w0, #0xffff
59 ; CHECK-NEXT:    mov w9, #43 // =0x2b
60 ; CHECK-NEXT:    cmp w8, #43
61 ; CHECK-NEXT:    sub w9, w9, w0
62 ; CHECK-NEXT:    cset w8, hi
63 ; CHECK-NEXT:    strh w9, [x1]
64 ; CHECK-NEXT:    mov w0, w8
65 ; CHECK-NEXT:    ret
66   %s = sub i16 43, %x
67   %ov = icmp ult i16 43, %x
68   store i16 %s, ptr %p
69   ret i1 %ov
72 ; Subtract with constant operand 1 is canonicalized to add.
74 define i1 @usubo_ult_constant_op1_i16(i16 %x, ptr %p) nounwind {
75 ; CHECK-LABEL: usubo_ult_constant_op1_i16:
76 ; CHECK:       // %bb.0:
77 ; CHECK-NEXT:    and w8, w0, #0xffff
78 ; CHECK-NEXT:    sub w9, w0, #44
79 ; CHECK-NEXT:    cmp w8, #44
80 ; CHECK-NEXT:    strh w9, [x1]
81 ; CHECK-NEXT:    cset w8, lo
82 ; CHECK-NEXT:    mov w0, w8
83 ; CHECK-NEXT:    ret
84   %s = add i16 %x, -44
85   %ov = icmp ult i16 %x, 44
86   store i16 %s, ptr %p
87   ret i1 %ov
90 define i1 @usubo_ugt_constant_op1_i8(i8 %x, ptr %p) nounwind {
91 ; CHECK-LABEL: usubo_ugt_constant_op1_i8:
92 ; CHECK:       // %bb.0:
93 ; CHECK-NEXT:    and w8, w0, #0xff
94 ; CHECK-NEXT:    sub w9, w0, #45
95 ; CHECK-NEXT:    cmp w8, #45
96 ; CHECK-NEXT:    strb w9, [x1]
97 ; CHECK-NEXT:    cset w8, lo
98 ; CHECK-NEXT:    mov w0, w8
99 ; CHECK-NEXT:    ret
100   %ov = icmp ugt i8 45, %x
101   %s = add i8 %x, -45
102   store i8 %s, ptr %p
103   ret i1 %ov
106 ; Special-case: subtract 1 changes the compare predicate and constant.
108 define i1 @usubo_eq_constant1_op1_i32(i32 %x, ptr %p) nounwind {
109 ; CHECK-LABEL: usubo_eq_constant1_op1_i32:
110 ; CHECK:       // %bb.0:
111 ; CHECK-NEXT:    cmp w0, #0
112 ; CHECK-NEXT:    sub w9, w0, #1
113 ; CHECK-NEXT:    cset w8, eq
114 ; CHECK-NEXT:    str w9, [x1]
115 ; CHECK-NEXT:    mov w0, w8
116 ; CHECK-NEXT:    ret
117   %s = add i32 %x, -1
118   %ov = icmp eq i32 %x, 0
119   store i32 %s, ptr %p
120   ret i1 %ov
123 ; Verify insertion point for multi-BB.
125 declare void @call(i1)
127 define i1 @usubo_ult_sub_dominates_i64(i64 %x, i64 %y, ptr %p, i1 %cond) nounwind {
128 ; CHECK-LABEL: usubo_ult_sub_dominates_i64:
129 ; CHECK:       // %bb.0: // %entry
130 ; CHECK-NEXT:    tbz w3, #0, .LBB7_2
131 ; CHECK-NEXT:  // %bb.1: // %t
132 ; CHECK-NEXT:    subs x8, x0, x1
133 ; CHECK-NEXT:    cset w3, lo
134 ; CHECK-NEXT:    str x8, [x2]
135 ; CHECK-NEXT:  .LBB7_2: // %common.ret
136 ; CHECK-NEXT:    and w0, w3, #0x1
137 ; CHECK-NEXT:    ret
138 entry:
139   br i1 %cond, label %t, label %f
142   %s = sub i64 %x, %y
143   store i64 %s, ptr %p
144   br i1 %cond, label %end, label %f
147   ret i1 %cond
149 end:
150   %ov = icmp ult i64 %x, %y
151   ret i1 %ov
154 define i1 @usubo_ult_cmp_dominates_i64(i64 %x, i64 %y, ptr %p, i1 %cond) nounwind {
155 ; CHECK-LABEL: usubo_ult_cmp_dominates_i64:
156 ; CHECK:       // %bb.0: // %entry
157 ; CHECK-NEXT:    stp x30, x23, [sp, #-48]! // 16-byte Folded Spill
158 ; CHECK-NEXT:    stp x20, x19, [sp, #32] // 16-byte Folded Spill
159 ; CHECK-NEXT:    mov w19, w3
160 ; CHECK-NEXT:    stp x22, x21, [sp, #16] // 16-byte Folded Spill
161 ; CHECK-NEXT:    tbz w3, #0, .LBB8_3
162 ; CHECK-NEXT:  // %bb.1: // %t
163 ; CHECK-NEXT:    cmp x0, x1
164 ; CHECK-NEXT:    mov x23, x0
165 ; CHECK-NEXT:    mov x20, x2
166 ; CHECK-NEXT:    cset w21, lo
167 ; CHECK-NEXT:    mov x22, x1
168 ; CHECK-NEXT:    mov w0, w21
169 ; CHECK-NEXT:    bl call
170 ; CHECK-NEXT:    subs x8, x23, x22
171 ; CHECK-NEXT:    b.hs .LBB8_3
172 ; CHECK-NEXT:  // %bb.2: // %end
173 ; CHECK-NEXT:    mov w19, w21
174 ; CHECK-NEXT:    str x8, [x20]
175 ; CHECK-NEXT:  .LBB8_3: // %common.ret
176 ; CHECK-NEXT:    and w0, w19, #0x1
177 ; CHECK-NEXT:    ldp x20, x19, [sp, #32] // 16-byte Folded Reload
178 ; CHECK-NEXT:    ldp x22, x21, [sp, #16] // 16-byte Folded Reload
179 ; CHECK-NEXT:    ldp x30, x23, [sp], #48 // 16-byte Folded Reload
180 ; CHECK-NEXT:    ret
181 entry:
182   br i1 %cond, label %t, label %f
185   %ov = icmp ult i64 %x, %y
186   call void @call(i1 %ov)
187   br i1 %ov, label %end, label %f
190   ret i1 %cond
192 end:
193   %s = sub i64 %x, %y
194   store i64 %s, ptr %p
195   ret i1 %ov