1 ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
2 ; RUN: llc < %s -mtriple=aarch64-linux-gnuabi -O2 | FileCheck %s
4 ; The following cases are for i16
6 %struct.s_signed_i16 = type { i16, i16, i16 }
7 %struct.s_unsigned_i16 = type { i16, i16, i16 }
9 @cost_s_i8_i16 = common global %struct.s_signed_i16 zeroinitializer, align 2
10 @cost_u_i16 = common global %struct.s_unsigned_i16 zeroinitializer, align 2
12 define void @test_i16_2cmp_signed_1() {
13 ; CHECK-LABEL: test_i16_2cmp_signed_1:
14 ; CHECK: // %bb.0: // %entry
15 ; CHECK-NEXT: adrp x8, :got:cost_s_i8_i16
16 ; CHECK-NEXT: ldr x8, [x8, :got_lo12:cost_s_i8_i16]
17 ; CHECK-NEXT: ldrsh w9, [x8, #2]
18 ; CHECK-NEXT: ldrsh w10, [x8, #4]
19 ; CHECK-NEXT: cmp w9, w10
20 ; CHECK-NEXT: b.lt .LBB0_2
21 ; CHECK-NEXT: // %bb.1: // %if.end8.sink.split
22 ; CHECK-NEXT: strh w9, [x8]
23 ; CHECK-NEXT: .LBB0_2: // %if.end8
26 %0 = load i16, ptr getelementptr inbounds (%struct.s_signed_i16, ptr @cost_s_i8_i16, i64 0, i32 1), align 2
27 %1 = load i16, ptr getelementptr inbounds (%struct.s_signed_i16, ptr @cost_s_i8_i16, i64 0, i32 2), align 2
28 %cmp = icmp sgt i16 %0, %1
29 br i1 %cmp, label %if.then, label %if.else
31 if.then: ; preds = %entry
32 store i16 %0, ptr @cost_s_i8_i16, align 2
35 if.else: ; preds = %entry
36 %cmp5 = icmp eq i16 %0, %1
37 br i1 %cmp5, label %if.then7, label %if.end8
39 if.then7: ; preds = %if.else
40 store i16 %0, ptr @cost_s_i8_i16, align 2
43 if.end8: ; preds = %if.else, %if.then7, %if.then
47 define void @test_i16_2cmp_signed_2() {
48 ; CHECK-LABEL: test_i16_2cmp_signed_2:
49 ; CHECK: // %bb.0: // %entry
50 ; CHECK-NEXT: adrp x8, :got:cost_s_i8_i16
51 ; CHECK-NEXT: ldr x8, [x8, :got_lo12:cost_s_i8_i16]
52 ; CHECK-NEXT: ldrsh w9, [x8, #2]
53 ; CHECK-NEXT: ldrsh w10, [x8, #4]
54 ; CHECK-NEXT: cmp w9, w10
55 ; CHECK-NEXT: b.gt .LBB1_2
56 ; CHECK-NEXT: // %bb.1: // %if.else
57 ; CHECK-NEXT: mov w9, w10
58 ; CHECK-NEXT: b.ge .LBB1_3
59 ; CHECK-NEXT: .LBB1_2: // %if.end8.sink.split
60 ; CHECK-NEXT: strh w9, [x8]
61 ; CHECK-NEXT: .LBB1_3: // %if.end8
64 %0 = load i16, ptr getelementptr inbounds (%struct.s_signed_i16, ptr @cost_s_i8_i16, i64 0, i32 1), align 2
65 %1 = load i16, ptr getelementptr inbounds (%struct.s_signed_i16, ptr @cost_s_i8_i16, i64 0, i32 2), align 2
66 %cmp = icmp sgt i16 %0, %1
67 br i1 %cmp, label %if.then, label %if.else
69 if.then: ; preds = %entry
70 store i16 %0, ptr @cost_s_i8_i16, align 2
73 if.else: ; preds = %entry
74 %cmp5 = icmp slt i16 %0, %1
75 br i1 %cmp5, label %if.then7, label %if.end8
77 if.then7: ; preds = %if.else
78 store i16 %1, ptr @cost_s_i8_i16, align 2
81 if.end8: ; preds = %if.else, %if.then7, %if.then
85 define void @test_i16_2cmp_unsigned_1() {
86 ; CHECK-LABEL: test_i16_2cmp_unsigned_1:
87 ; CHECK: // %bb.0: // %entry
88 ; CHECK-NEXT: adrp x8, :got:cost_u_i16
89 ; CHECK-NEXT: ldr x8, [x8, :got_lo12:cost_u_i16]
90 ; CHECK-NEXT: ldrh w9, [x8, #2]
91 ; CHECK-NEXT: ldrh w10, [x8, #4]
92 ; CHECK-NEXT: cmp w9, w10
93 ; CHECK-NEXT: b.lo .LBB2_2
94 ; CHECK-NEXT: // %bb.1: // %if.end8.sink.split
95 ; CHECK-NEXT: strh w9, [x8]
96 ; CHECK-NEXT: .LBB2_2: // %if.end8
99 %0 = load i16, ptr getelementptr inbounds (%struct.s_unsigned_i16, ptr @cost_u_i16, i64 0, i32 1), align 2
100 %1 = load i16, ptr getelementptr inbounds (%struct.s_unsigned_i16, ptr @cost_u_i16, i64 0, i32 2), align 2
101 %cmp = icmp ugt i16 %0, %1
102 br i1 %cmp, label %if.then, label %if.else
104 if.then: ; preds = %entry
105 store i16 %0, ptr @cost_u_i16, align 2
108 if.else: ; preds = %entry
109 %cmp5 = icmp eq i16 %0, %1
110 br i1 %cmp5, label %if.then7, label %if.end8
112 if.then7: ; preds = %if.else
113 store i16 %0, ptr @cost_u_i16, align 2
116 if.end8: ; preds = %if.else, %if.then7, %if.then
120 define void @test_i16_2cmp_unsigned_2() {
121 ; CHECK-LABEL: test_i16_2cmp_unsigned_2:
122 ; CHECK: // %bb.0: // %entry
123 ; CHECK-NEXT: adrp x8, :got:cost_u_i16
124 ; CHECK-NEXT: ldr x8, [x8, :got_lo12:cost_u_i16]
125 ; CHECK-NEXT: ldrh w9, [x8, #2]
126 ; CHECK-NEXT: ldrh w10, [x8, #4]
127 ; CHECK-NEXT: cmp w9, w10
128 ; CHECK-NEXT: b.hi .LBB3_2
129 ; CHECK-NEXT: // %bb.1: // %if.else
130 ; CHECK-NEXT: mov w9, w10
131 ; CHECK-NEXT: b.hs .LBB3_3
132 ; CHECK-NEXT: .LBB3_2: // %if.end8.sink.split
133 ; CHECK-NEXT: strh w9, [x8]
134 ; CHECK-NEXT: .LBB3_3: // %if.end8
137 %0 = load i16, ptr getelementptr inbounds (%struct.s_unsigned_i16, ptr @cost_u_i16, i64 0, i32 1), align 2
138 %1 = load i16, ptr getelementptr inbounds (%struct.s_unsigned_i16, ptr @cost_u_i16, i64 0, i32 2), align 2
139 %cmp = icmp ugt i16 %0, %1
140 br i1 %cmp, label %if.then, label %if.else
142 if.then: ; preds = %entry
143 store i16 %0, ptr @cost_u_i16, align 2
146 if.else: ; preds = %entry
147 %cmp5 = icmp ult i16 %0, %1
148 br i1 %cmp5, label %if.then7, label %if.end8
150 if.then7: ; preds = %if.else
151 store i16 %1, ptr @cost_u_i16, align 2
154 if.end8: ; preds = %if.else, %if.then7, %if.then
158 ; The following cases are for i8
160 %struct.s_signed_i8 = type { i8, i8, i8 }
161 %struct.s_unsigned_i8 = type { i8, i8, i8 }
163 @cost_s = common global %struct.s_signed_i8 zeroinitializer, align 2
164 @cost_u_i8 = common global %struct.s_unsigned_i8 zeroinitializer, align 2
167 define void @test_i8_2cmp_signed_1() {
168 ; CHECK-LABEL: test_i8_2cmp_signed_1:
169 ; CHECK: // %bb.0: // %entry
170 ; CHECK-NEXT: adrp x8, :got:cost_s
171 ; CHECK-NEXT: ldr x8, [x8, :got_lo12:cost_s]
172 ; CHECK-NEXT: ldrsb w9, [x8, #1]
173 ; CHECK-NEXT: ldrsb w10, [x8, #2]
174 ; CHECK-NEXT: cmp w9, w10
175 ; CHECK-NEXT: b.lt .LBB4_2
176 ; CHECK-NEXT: // %bb.1: // %if.end8.sink.split
177 ; CHECK-NEXT: strb w9, [x8]
178 ; CHECK-NEXT: .LBB4_2: // %if.end8
181 %0 = load i8, ptr getelementptr inbounds (%struct.s_signed_i8, ptr @cost_s, i64 0, i32 1), align 2
182 %1 = load i8, ptr getelementptr inbounds (%struct.s_signed_i8, ptr @cost_s, i64 0, i32 2), align 2
183 %cmp = icmp sgt i8 %0, %1
184 br i1 %cmp, label %if.then, label %if.else
186 if.then: ; preds = %entry
187 store i8 %0, ptr @cost_s, align 2
190 if.else: ; preds = %entry
191 %cmp5 = icmp eq i8 %0, %1
192 br i1 %cmp5, label %if.then7, label %if.end8
194 if.then7: ; preds = %if.else
195 store i8 %0, ptr @cost_s, align 2
198 if.end8: ; preds = %if.else, %if.then7, %if.then
202 define void @test_i8_2cmp_signed_2() {
203 ; CHECK-LABEL: test_i8_2cmp_signed_2:
204 ; CHECK: // %bb.0: // %entry
205 ; CHECK-NEXT: adrp x8, :got:cost_s
206 ; CHECK-NEXT: ldr x8, [x8, :got_lo12:cost_s]
207 ; CHECK-NEXT: ldrsb w9, [x8, #1]
208 ; CHECK-NEXT: ldrsb w10, [x8, #2]
209 ; CHECK-NEXT: cmp w9, w10
210 ; CHECK-NEXT: b.gt .LBB5_2
211 ; CHECK-NEXT: // %bb.1: // %if.else
212 ; CHECK-NEXT: mov w9, w10
213 ; CHECK-NEXT: b.ge .LBB5_3
214 ; CHECK-NEXT: .LBB5_2: // %if.end8.sink.split
215 ; CHECK-NEXT: strb w9, [x8]
216 ; CHECK-NEXT: .LBB5_3: // %if.end8
219 %0 = load i8, ptr getelementptr inbounds (%struct.s_signed_i8, ptr @cost_s, i64 0, i32 1), align 2
220 %1 = load i8, ptr getelementptr inbounds (%struct.s_signed_i8, ptr @cost_s, i64 0, i32 2), align 2
221 %cmp = icmp sgt i8 %0, %1
222 br i1 %cmp, label %if.then, label %if.else
224 if.then: ; preds = %entry
225 store i8 %0, ptr @cost_s, align 2
228 if.else: ; preds = %entry
229 %cmp5 = icmp slt i8 %0, %1
230 br i1 %cmp5, label %if.then7, label %if.end8
232 if.then7: ; preds = %if.else
233 store i8 %1, ptr @cost_s, align 2
236 if.end8: ; preds = %if.else, %if.then7, %if.then
240 define void @test_i8_2cmp_unsigned_1() {
241 ; CHECK-LABEL: test_i8_2cmp_unsigned_1:
242 ; CHECK: // %bb.0: // %entry
243 ; CHECK-NEXT: adrp x8, :got:cost_u_i8
244 ; CHECK-NEXT: ldr x8, [x8, :got_lo12:cost_u_i8]
245 ; CHECK-NEXT: ldrb w9, [x8, #1]
246 ; CHECK-NEXT: ldrb w10, [x8, #2]
247 ; CHECK-NEXT: cmp w9, w10
248 ; CHECK-NEXT: b.lo .LBB6_2
249 ; CHECK-NEXT: // %bb.1: // %if.end8.sink.split
250 ; CHECK-NEXT: strb w9, [x8]
251 ; CHECK-NEXT: .LBB6_2: // %if.end8
254 %0 = load i8, ptr getelementptr inbounds (%struct.s_unsigned_i8, ptr @cost_u_i8, i64 0, i32 1), align 2
255 %1 = load i8, ptr getelementptr inbounds (%struct.s_unsigned_i8, ptr @cost_u_i8, i64 0, i32 2), align 2
256 %cmp = icmp ugt i8 %0, %1
257 br i1 %cmp, label %if.then, label %if.else
259 if.then: ; preds = %entry
260 store i8 %0, ptr @cost_u_i8, align 2
263 if.else: ; preds = %entry
264 %cmp5 = icmp eq i8 %0, %1
265 br i1 %cmp5, label %if.then7, label %if.end8
267 if.then7: ; preds = %if.else
268 store i8 %0, ptr @cost_u_i8, align 2
271 if.end8: ; preds = %if.else, %if.then7, %if.then
275 define void @test_i8_2cmp_unsigned_2() {
276 ; CHECK-LABEL: test_i8_2cmp_unsigned_2:
277 ; CHECK: // %bb.0: // %entry
278 ; CHECK-NEXT: adrp x8, :got:cost_u_i8
279 ; CHECK-NEXT: ldr x8, [x8, :got_lo12:cost_u_i8]
280 ; CHECK-NEXT: ldrb w9, [x8, #1]
281 ; CHECK-NEXT: ldrb w10, [x8, #2]
282 ; CHECK-NEXT: cmp w9, w10
283 ; CHECK-NEXT: b.hi .LBB7_2
284 ; CHECK-NEXT: // %bb.1: // %if.else
285 ; CHECK-NEXT: mov w9, w10
286 ; CHECK-NEXT: b.hs .LBB7_3
287 ; CHECK-NEXT: .LBB7_2: // %if.end8.sink.split
288 ; CHECK-NEXT: strb w9, [x8]
289 ; CHECK-NEXT: .LBB7_3: // %if.end8
292 %0 = load i8, ptr getelementptr inbounds (%struct.s_unsigned_i8, ptr @cost_u_i8, i64 0, i32 1), align 2
293 %1 = load i8, ptr getelementptr inbounds (%struct.s_unsigned_i8, ptr @cost_u_i8, i64 0, i32 2), align 2
294 %cmp = icmp ugt i8 %0, %1
295 br i1 %cmp, label %if.then, label %if.else
297 if.then: ; preds = %entry
298 store i8 %0, ptr @cost_u_i8, align 2
301 if.else: ; preds = %entry
302 %cmp5 = icmp ult i8 %0, %1
303 br i1 %cmp5, label %if.then7, label %if.end8
305 if.then7: ; preds = %if.else
306 store i8 %1, ptr @cost_u_i8, align 2
309 if.end8: ; preds = %if.else, %if.then7, %if.then
313 ; Make sure the case below won't crash.
315 ; The optimization of ZERO_EXTEND and SIGN_EXTEND in type legalization stage can't assert
316 ; the operand of a set_cc is always a TRUNCATE.
318 define i1 @foo(float %inl, float %inr) {
321 ; CHECK-NEXT: fcvtzs w8, s0
322 ; CHECK-NEXT: fcvtzs w9, s1
323 ; CHECK-NEXT: cmp w8, w9
324 ; CHECK-NEXT: cset w0, eq
326 %lval = fptosi float %inl to i8
327 %rval = fptosi float %inr to i8
328 %sum = icmp eq i8 %lval, %rval