llvm.org GIT mirror llvm / 3a22eb4
[ARM] Fix select_cc lowering for fp16 When lowering a select_cc node where the true and false values are of type f16, we can't use a general conditional move because the FP16 instructions do not support conditional execution. Instead, we must ensure that the condition code is one of the four supported by the VSEL instruction. Differential revision: https://reviews.llvm.org/D58813 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@355385 91177308-0d34-0410-b5e6-96231b3b80d8 Oliver Stannard 7 months ago
2 changed file(s) with 687 addition(s) and 7 deletion(s). Raw diff Collapse all Expand all
44934493 // inverting the compare condition, swapping 'less' and 'greater') and
44944494 // sometimes need to swap the operands to the VSEL (which inverts the
44954495 // condition in the sense of firing whenever the previous condition didn't)
4496 if (Subtarget->hasFPARMv8() && (TrueVal.getValueType() == MVT::f32 ||
4496 if (Subtarget->hasFPARMv8() && (TrueVal.getValueType() == MVT::f16 ||
4497 TrueVal.getValueType() == MVT::f32 ||
44974498 TrueVal.getValueType() == MVT::f64)) {
44984499 ARMCC::CondCodes CondCode = IntCCToARMCC(CC);
44994500 if (CondCode == ARMCC::LT || CondCode == ARMCC::LE ||
45134514 bool InvalidOnQNaN;
45144515 FPCCToARMCC(CC, CondCode, CondCode2, InvalidOnQNaN);
45154516
4516 // Normalize the fp compare. If RHS is zero we keep it there so we match
4517 // CMPFPw0 instead of CMPFP.
4518 if (Subtarget->hasFPARMv8() && !isFloatingPointZero(RHS) &&
4519 (TrueVal.getValueType() == MVT::f16 ||
4520 TrueVal.getValueType() == MVT::f32 ||
4521 TrueVal.getValueType() == MVT::f64)) {
4517 // Normalize the fp compare. If RHS is zero we prefer to keep it there so we
4518 // match CMPFPw0 instead of CMPFP, though we don't do this for f16 because we
4519 // must use VSEL (limited condition codes), due to not having conditional f16
4520 // moves.
4521 if (Subtarget->hasFPARMv8() &&
4522 !(isFloatingPointZero(RHS) && TrueVal.getValueType() != MVT::f16) &&
4523 (TrueVal.getValueType() == MVT::f16 ||
4524 TrueVal.getValueType() == MVT::f32 ||
4525 TrueVal.getValueType() == MVT::f64)) {
45224526 bool swpCmpOps = false;
45234527 bool swpVselOps = false;
45244528 checkVSELConstraints(CC, CondCode, swpCmpOps, swpVselOps);
0 ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
1 ; RUN: llc < %s -mtriple=armv8a--none-eabi -mattr=+fullfp16 -float-abi=hard | FileCheck %s
2
3 @varhalf = global half 0.0
4 @vardouble = global double 0.0
5 define void @test_vsel32sgt(i32 %lhs, i32 %rhs, half* %a_ptr, half* %b_ptr) {
6 ; CHECK-LABEL: test_vsel32sgt:
7 ; CHECK: @ %bb.0:
8 ; CHECK-NEXT: vldr.16 s0, [r2]
9 ; CHECK-NEXT: vldr.16 s2, [r3]
10 ; CHECK-NEXT: cmp r0, r1
11 ; CHECK-NEXT: movw r0, :lower16:varhalf
12 ; CHECK-NEXT: vselgt.f16 s0, s0, s2
13 ; CHECK-NEXT: movt r0, :upper16:varhalf
14 ; CHECK-NEXT: vstr.16 s0, [r0]
15 ; CHECK-NEXT: bx lr
16 %a = load volatile half, half* %a_ptr
17 %b = load volatile half, half* %b_ptr
18 %tst1 = icmp sgt i32 %lhs, %rhs
19 %val1 = select i1 %tst1, half %a, half %b
20 store half %val1, half* @varhalf
21 ret void
22 }
23
24 define void @test_vsel32sge(i32 %lhs, i32 %rhs, half* %a_ptr, half* %b_ptr) {
25 ; CHECK-LABEL: test_vsel32sge:
26 ; CHECK: @ %bb.0:
27 ; CHECK-NEXT: vldr.16 s0, [r2]
28 ; CHECK-NEXT: vldr.16 s2, [r3]
29 ; CHECK-NEXT: cmp r0, r1
30 ; CHECK-NEXT: movw r0, :lower16:varhalf
31 ; CHECK-NEXT: vselge.f16 s0, s0, s2
32 ; CHECK-NEXT: movt r0, :upper16:varhalf
33 ; CHECK-NEXT: vstr.16 s0, [r0]
34 ; CHECK-NEXT: bx lr
35 %a = load volatile half, half* %a_ptr
36 %b = load volatile half, half* %b_ptr
37 %tst1 = icmp sge i32 %lhs, %rhs
38 %val1 = select i1 %tst1, half %a, half %b
39 store half %val1, half* @varhalf
40 ret void
41 }
42
43 define void @test_vsel32eq(i32 %lhs, i32 %rhs, half* %a_ptr, half* %b_ptr) {
44 ; CHECK-LABEL: test_vsel32eq:
45 ; CHECK: @ %bb.0:
46 ; CHECK-NEXT: vldr.16 s0, [r2]
47 ; CHECK-NEXT: vldr.16 s2, [r3]
48 ; CHECK-NEXT: cmp r0, r1
49 ; CHECK-NEXT: movw r0, :lower16:varhalf
50 ; CHECK-NEXT: vseleq.f16 s0, s0, s2
51 ; CHECK-NEXT: movt r0, :upper16:varhalf
52 ; CHECK-NEXT: vstr.16 s0, [r0]
53 ; CHECK-NEXT: bx lr
54 %a = load volatile half, half* %a_ptr
55 %b = load volatile half, half* %b_ptr
56 %tst1 = icmp eq i32 %lhs, %rhs
57 %val1 = select i1 %tst1, half %a, half %b
58 store half %val1, half* @varhalf
59 ret void
60 }
61
62 define void @test_vsel32slt(i32 %lhs, i32 %rhs, half* %a_ptr, half* %b_ptr) {
63 ; CHECK-LABEL: test_vsel32slt:
64 ; CHECK: @ %bb.0:
65 ; CHECK-NEXT: vldr.16 s0, [r2]
66 ; CHECK-NEXT: vldr.16 s2, [r3]
67 ; CHECK-NEXT: cmp r0, r1
68 ; CHECK-NEXT: movw r0, :lower16:varhalf
69 ; CHECK-NEXT: vselge.f16 s0, s2, s0
70 ; CHECK-NEXT: movt r0, :upper16:varhalf
71 ; CHECK-NEXT: vstr.16 s0, [r0]
72 ; CHECK-NEXT: bx lr
73 %a = load volatile half, half* %a_ptr
74 %b = load volatile half, half* %b_ptr
75 %tst1 = icmp slt i32 %lhs, %rhs
76 %val1 = select i1 %tst1, half %a, half %b
77 store half %val1, half* @varhalf
78 ret void
79 }
80
81 define void @test_vsel32sle(i32 %lhs, i32 %rhs, half* %a_ptr, half* %b_ptr) {
82 ; CHECK-LABEL: test_vsel32sle:
83 ; CHECK: @ %bb.0:
84 ; CHECK-NEXT: vldr.16 s0, [r2]
85 ; CHECK-NEXT: vldr.16 s2, [r3]
86 ; CHECK-NEXT: cmp r0, r1
87 ; CHECK-NEXT: movw r0, :lower16:varhalf
88 ; CHECK-NEXT: vselgt.f16 s0, s2, s0
89 ; CHECK-NEXT: movt r0, :upper16:varhalf
90 ; CHECK-NEXT: vstr.16 s0, [r0]
91 ; CHECK-NEXT: bx lr
92 %a = load volatile half, half* %a_ptr
93 %b = load volatile half, half* %b_ptr
94 %tst1 = icmp sle i32 %lhs, %rhs
95 %val1 = select i1 %tst1, half %a, half %b
96 store half %val1, half* @varhalf
97 ret void
98 }
99
100 define void @test_vsel32ogt(half* %lhs_ptr, half* %rhs_ptr, half* %a_ptr, half* %b_ptr) {
101 ; CHECK-LABEL: test_vsel32ogt:
102 ; CHECK: @ %bb.0:
103 ; CHECK-NEXT: vldr.16 s0, [r2]
104 ; CHECK-NEXT: vldr.16 s2, [r3]
105 ; CHECK-NEXT: vldr.16 s4, [r0]
106 ; CHECK-NEXT: vldr.16 s6, [r1]
107 ; CHECK-NEXT: movw r0, :lower16:varhalf
108 ; CHECK-NEXT: vcmpe.f16 s4, s6
109 ; CHECK-NEXT: movt r0, :upper16:varhalf
110 ; CHECK-NEXT: vmrs APSR_nzcv, fpscr
111 ; CHECK-NEXT: vselgt.f16 s0, s0, s2
112 ; CHECK-NEXT: vstr.16 s0, [r0]
113 ; CHECK-NEXT: bx lr
114 %a = load volatile half, half* %a_ptr
115 %b = load volatile half, half* %b_ptr
116 %lhs = load volatile half, half* %lhs_ptr
117 %rhs = load volatile half, half* %rhs_ptr
118 %tst1 = fcmp ogt half %lhs, %rhs
119 %val1 = select i1 %tst1, half %a, half %b
120 store half %val1, half* @varhalf
121 ret void
122 }
123
124 define void @test_vsel32oge(half* %lhs_ptr, half* %rhs_ptr, half* %a_ptr, half* %b_ptr) {
125 ; CHECK-LABEL: test_vsel32oge:
126 ; CHECK: @ %bb.0:
127 ; CHECK-NEXT: vldr.16 s0, [r2]
128 ; CHECK-NEXT: vldr.16 s2, [r3]
129 ; CHECK-NEXT: vldr.16 s4, [r0]
130 ; CHECK-NEXT: vldr.16 s6, [r1]
131 ; CHECK-NEXT: movw r0, :lower16:varhalf
132 ; CHECK-NEXT: vcmpe.f16 s4, s6
133 ; CHECK-NEXT: movt r0, :upper16:varhalf
134 ; CHECK-NEXT: vmrs APSR_nzcv, fpscr
135 ; CHECK-NEXT: vselge.f16 s0, s0, s2
136 ; CHECK-NEXT: vstr.16 s0, [r0]
137 ; CHECK-NEXT: bx lr
138 %a = load volatile half, half* %a_ptr
139 %b = load volatile half, half* %b_ptr
140 %lhs = load volatile half, half* %lhs_ptr
141 %rhs = load volatile half, half* %rhs_ptr
142 %tst1 = fcmp oge half %lhs, %rhs
143 %val1 = select i1 %tst1, half %a, half %b
144 store half %val1, half* @varhalf
145 ret void
146 }
147
148 define void @test_vsel32oeq(half* %lhs_ptr, half* %rhs_ptr, half* %a_ptr, half* %b_ptr) {
149 ; CHECK-LABEL: test_vsel32oeq:
150 ; CHECK: @ %bb.0:
151 ; CHECK-NEXT: vldr.16 s0, [r2]
152 ; CHECK-NEXT: vldr.16 s2, [r3]
153 ; CHECK-NEXT: vldr.16 s4, [r0]
154 ; CHECK-NEXT: vldr.16 s6, [r1]
155 ; CHECK-NEXT: movw r0, :lower16:varhalf
156 ; CHECK-NEXT: vcmp.f16 s4, s6
157 ; CHECK-NEXT: movt r0, :upper16:varhalf
158 ; CHECK-NEXT: vmrs APSR_nzcv, fpscr
159 ; CHECK-NEXT: vseleq.f16 s0, s0, s2
160 ; CHECK-NEXT: vstr.16 s0, [r0]
161 ; CHECK-NEXT: bx lr
162 %a = load volatile half, half* %a_ptr
163 %b = load volatile half, half* %b_ptr
164 %lhs = load volatile half, half* %lhs_ptr
165 %rhs = load volatile half, half* %rhs_ptr
166 %tst1 = fcmp oeq half %lhs, %rhs
167 %val1 = select i1 %tst1, half %a, half %b
168 store half %val1, half* @varhalf
169 ret void
170 }
171
172 define void @test_vsel32ugt(half* %lhs_ptr, half* %rhs_ptr, half* %a_ptr, half* %b_ptr) {
173 ; CHECK-LABEL: test_vsel32ugt:
174 ; CHECK: @ %bb.0:
175 ; CHECK-NEXT: vldr.16 s0, [r2]
176 ; CHECK-NEXT: vldr.16 s2, [r3]
177 ; CHECK-NEXT: vldr.16 s4, [r0]
178 ; CHECK-NEXT: vldr.16 s6, [r1]
179 ; CHECK-NEXT: movw r0, :lower16:varhalf
180 ; CHECK-NEXT: vcmpe.f16 s6, s4
181 ; CHECK-NEXT: movt r0, :upper16:varhalf
182 ; CHECK-NEXT: vmrs APSR_nzcv, fpscr
183 ; CHECK-NEXT: vselge.f16 s0, s2, s0
184 ; CHECK-NEXT: vstr.16 s0, [r0]
185 ; CHECK-NEXT: bx lr
186 %a = load volatile half, half* %a_ptr
187 %b = load volatile half, half* %b_ptr
188 %lhs = load volatile half, half* %lhs_ptr
189 %rhs = load volatile half, half* %rhs_ptr
190 %tst1 = fcmp ugt half %lhs, %rhs
191 %val1 = select i1 %tst1, half %a, half %b
192 store half %val1, half* @varhalf
193 ret void
194 }
195
196 define void @test_vsel32uge(half* %lhs_ptr, half* %rhs_ptr, half* %a_ptr, half* %b_ptr) {
197 ; CHECK-LABEL: test_vsel32uge:
198 ; CHECK: @ %bb.0:
199 ; CHECK-NEXT: vldr.16 s0, [r2]
200 ; CHECK-NEXT: vldr.16 s2, [r3]
201 ; CHECK-NEXT: vldr.16 s4, [r0]
202 ; CHECK-NEXT: vldr.16 s6, [r1]
203 ; CHECK-NEXT: movw r0, :lower16:varhalf
204 ; CHECK-NEXT: vcmpe.f16 s6, s4
205 ; CHECK-NEXT: movt r0, :upper16:varhalf
206 ; CHECK-NEXT: vmrs APSR_nzcv, fpscr
207 ; CHECK-NEXT: vselgt.f16 s0, s2, s0
208 ; CHECK-NEXT: vstr.16 s0, [r0]
209 ; CHECK-NEXT: bx lr
210 %a = load volatile half, half* %a_ptr
211 %b = load volatile half, half* %b_ptr
212 %lhs = load volatile half, half* %lhs_ptr
213 %rhs = load volatile half, half* %rhs_ptr
214 %tst1 = fcmp uge half %lhs, %rhs
215 %val1 = select i1 %tst1, half %a, half %b
216 store half %val1, half* @varhalf
217 ret void
218 }
219
220 define void @test_vsel32olt(half* %lhs_ptr, half* %rhs_ptr, half* %a_ptr, half* %b_ptr) {
221 ; CHECK-LABEL: test_vsel32olt:
222 ; CHECK: @ %bb.0:
223 ; CHECK-NEXT: vldr.16 s0, [r2]
224 ; CHECK-NEXT: vldr.16 s2, [r3]
225 ; CHECK-NEXT: vldr.16 s4, [r0]
226 ; CHECK-NEXT: vldr.16 s6, [r1]
227 ; CHECK-NEXT: movw r0, :lower16:varhalf
228 ; CHECK-NEXT: vcmpe.f16 s6, s4
229 ; CHECK-NEXT: movt r0, :upper16:varhalf
230 ; CHECK-NEXT: vmrs APSR_nzcv, fpscr
231 ; CHECK-NEXT: vselgt.f16 s0, s0, s2
232 ; CHECK-NEXT: vstr.16 s0, [r0]
233 ; CHECK-NEXT: bx lr
234 %a = load volatile half, half* %a_ptr
235 %b = load volatile half, half* %b_ptr
236 %lhs = load volatile half, half* %lhs_ptr
237 %rhs = load volatile half, half* %rhs_ptr
238 %tst1 = fcmp olt half %lhs, %rhs
239 %val1 = select i1 %tst1, half %a, half %b
240 store half %val1, half* @varhalf
241 ret void
242 }
243
244 define void @test_vsel32ult(half* %lhs_ptr, half* %rhs_ptr, half* %a_ptr, half* %b_ptr) {
245 ; CHECK-LABEL: test_vsel32ult:
246 ; CHECK: @ %bb.0:
247 ; CHECK-NEXT: vldr.16 s0, [r2]
248 ; CHECK-NEXT: vldr.16 s2, [r3]
249 ; CHECK-NEXT: vldr.16 s4, [r0]
250 ; CHECK-NEXT: vldr.16 s6, [r1]
251 ; CHECK-NEXT: movw r0, :lower16:varhalf
252 ; CHECK-NEXT: vcmpe.f16 s4, s6
253 ; CHECK-NEXT: movt r0, :upper16:varhalf
254 ; CHECK-NEXT: vmrs APSR_nzcv, fpscr
255 ; CHECK-NEXT: vselge.f16 s0, s2, s0
256 ; CHECK-NEXT: vstr.16 s0, [r0]
257 ; CHECK-NEXT: bx lr
258 %a = load volatile half, half* %a_ptr
259 %b = load volatile half, half* %b_ptr
260 %lhs = load volatile half, half* %lhs_ptr
261 %rhs = load volatile half, half* %rhs_ptr
262 %tst1 = fcmp ult half %lhs, %rhs
263 %val1 = select i1 %tst1, half %a, half %b
264 store half %val1, half* @varhalf
265 ret void
266 }
267
268 define void @test_vsel32ole(half* %lhs_ptr, half* %rhs_ptr, half* %a_ptr, half* %b_ptr) {
269 ; CHECK-LABEL: test_vsel32ole:
270 ; CHECK: @ %bb.0:
271 ; CHECK-NEXT: vldr.16 s0, [r2]
272 ; CHECK-NEXT: vldr.16 s2, [r3]
273 ; CHECK-NEXT: vldr.16 s4, [r0]
274 ; CHECK-NEXT: vldr.16 s6, [r1]
275 ; CHECK-NEXT: movw r0, :lower16:varhalf
276 ; CHECK-NEXT: vcmpe.f16 s6, s4
277 ; CHECK-NEXT: movt r0, :upper16:varhalf
278 ; CHECK-NEXT: vmrs APSR_nzcv, fpscr
279 ; CHECK-NEXT: vselge.f16 s0, s0, s2
280 ; CHECK-NEXT: vstr.16 s0, [r0]
281 ; CHECK-NEXT: bx lr
282 %a = load volatile half, half* %a_ptr
283 %b = load volatile half, half* %b_ptr
284 %lhs = load volatile half, half* %lhs_ptr
285 %rhs = load volatile half, half* %rhs_ptr
286 %tst1 = fcmp ole half %lhs, %rhs
287 %val1 = select i1 %tst1, half %a, half %b
288 store half %val1, half* @varhalf
289 ret void
290 }
291
292 define void @test_vsel32ule(half* %lhs_ptr, half* %rhs_ptr, half* %a_ptr, half* %b_ptr) {
293 ; CHECK-LABEL: test_vsel32ule:
294 ; CHECK: @ %bb.0:
295 ; CHECK-NEXT: vldr.16 s0, [r2]
296 ; CHECK-NEXT: vldr.16 s2, [r3]
297 ; CHECK-NEXT: vldr.16 s4, [r0]
298 ; CHECK-NEXT: vldr.16 s6, [r1]
299 ; CHECK-NEXT: movw r0, :lower16:varhalf
300 ; CHECK-NEXT: vcmpe.f16 s4, s6
301 ; CHECK-NEXT: movt r0, :upper16:varhalf
302 ; CHECK-NEXT: vmrs APSR_nzcv, fpscr
303 ; CHECK-NEXT: vselgt.f16 s0, s2, s0
304 ; CHECK-NEXT: vstr.16 s0, [r0]
305 ; CHECK-NEXT: bx lr
306 %a = load volatile half, half* %a_ptr
307 %b = load volatile half, half* %b_ptr
308 %lhs = load volatile half, half* %lhs_ptr
309 %rhs = load volatile half, half* %rhs_ptr
310 %tst1 = fcmp ule half %lhs, %rhs
311 %val1 = select i1 %tst1, half %a, half %b
312 store half %val1, half* @varhalf
313 ret void
314 }
315
316 define void @test_vsel32ord(half* %lhs_ptr, half* %rhs_ptr, half* %a_ptr, half* %b_ptr) {
317 ; CHECK-LABEL: test_vsel32ord:
318 ; CHECK: @ %bb.0:
319 ; CHECK-NEXT: vldr.16 s0, [r2]
320 ; CHECK-NEXT: vldr.16 s2, [r3]
321 ; CHECK-NEXT: vldr.16 s4, [r0]
322 ; CHECK-NEXT: vldr.16 s6, [r1]
323 ; CHECK-NEXT: movw r0, :lower16:varhalf
324 ; CHECK-NEXT: vcmpe.f16 s4, s6
325 ; CHECK-NEXT: movt r0, :upper16:varhalf
326 ; CHECK-NEXT: vmrs APSR_nzcv, fpscr
327 ; CHECK-NEXT: vselvs.f16 s0, s2, s0
328 ; CHECK-NEXT: vstr.16 s0, [r0]
329 ; CHECK-NEXT: bx lr
330 %a = load volatile half, half* %a_ptr
331 %b = load volatile half, half* %b_ptr
332 %lhs = load volatile half, half* %lhs_ptr
333 %rhs = load volatile half, half* %rhs_ptr
334 %tst1 = fcmp ord half %lhs, %rhs
335 %val1 = select i1 %tst1, half %a, half %b
336 store half %val1, half* @varhalf
337 ret void
338 }
339
340 define void @test_vsel32une(half* %lhs_ptr, half* %rhs_ptr, half* %a_ptr, half* %b_ptr) {
341 ; CHECK-LABEL: test_vsel32une:
342 ; CHECK: @ %bb.0:
343 ; CHECK-NEXT: vldr.16 s0, [r2]
344 ; CHECK-NEXT: vldr.16 s2, [r3]
345 ; CHECK-NEXT: vldr.16 s4, [r0]
346 ; CHECK-NEXT: vldr.16 s6, [r1]
347 ; CHECK-NEXT: movw r0, :lower16:varhalf
348 ; CHECK-NEXT: vcmp.f16 s4, s6
349 ; CHECK-NEXT: movt r0, :upper16:varhalf
350 ; CHECK-NEXT: vmrs APSR_nzcv, fpscr
351 ; CHECK-NEXT: vseleq.f16 s0, s2, s0
352 ; CHECK-NEXT: vstr.16 s0, [r0]
353 ; CHECK-NEXT: bx lr
354 %a = load volatile half, half* %a_ptr
355 %b = load volatile half, half* %b_ptr
356 %lhs = load volatile half, half* %lhs_ptr
357 %rhs = load volatile half, half* %rhs_ptr
358 %tst1 = fcmp une half %lhs, %rhs
359 %val1 = select i1 %tst1, half %a, half %b
360 store half %val1, half* @varhalf
361 ret void
362 }
363
364 define void @test_vsel32uno(half* %lhs_ptr, half* %rhs_ptr, half* %a_ptr, half* %b_ptr) {
365 ; CHECK-LABEL: test_vsel32uno:
366 ; CHECK: @ %bb.0:
367 ; CHECK-NEXT: vldr.16 s0, [r2]
368 ; CHECK-NEXT: vldr.16 s2, [r3]
369 ; CHECK-NEXT: vldr.16 s4, [r0]
370 ; CHECK-NEXT: vldr.16 s6, [r1]
371 ; CHECK-NEXT: movw r0, :lower16:varhalf
372 ; CHECK-NEXT: vcmpe.f16 s4, s6
373 ; CHECK-NEXT: movt r0, :upper16:varhalf
374 ; CHECK-NEXT: vmrs APSR_nzcv, fpscr
375 ; CHECK-NEXT: vselvs.f16 s0, s0, s2
376 ; CHECK-NEXT: vstr.16 s0, [r0]
377 ; CHECK-NEXT: bx lr
378 %a = load volatile half, half* %a_ptr
379 %b = load volatile half, half* %b_ptr
380 %lhs = load volatile half, half* %lhs_ptr
381 %rhs = load volatile half, half* %rhs_ptr
382 %tst1 = fcmp uno half %lhs, %rhs
383 %val1 = select i1 %tst1, half %a, half %b
384 store half %val1, half* @varhalf
385 ret void
386 }
387
388
389 define void @test_vsel32ogt_nnan(half* %lhs_ptr, half* %rhs_ptr, half* %a_ptr, half* %b_ptr) {
390 ; CHECK-LABEL: test_vsel32ogt_nnan:
391 ; CHECK: @ %bb.0:
392 ; CHECK-NEXT: vldr.16 s0, [r2]
393 ; CHECK-NEXT: vldr.16 s2, [r3]
394 ; CHECK-NEXT: vldr.16 s4, [r0]
395 ; CHECK-NEXT: vldr.16 s6, [r1]
396 ; CHECK-NEXT: movw r0, :lower16:varhalf
397 ; CHECK-NEXT: vcmpe.f16 s4, s6
398 ; CHECK-NEXT: movt r0, :upper16:varhalf
399 ; CHECK-NEXT: vmrs APSR_nzcv, fpscr
400 ; CHECK-NEXT: vselgt.f16 s0, s0, s2
401 ; CHECK-NEXT: vstr.16 s0, [r0]
402 ; CHECK-NEXT: bx lr
403 %a = load volatile half, half* %a_ptr
404 %b = load volatile half, half* %b_ptr
405 %lhs = load volatile half, half* %lhs_ptr
406 %rhs = load volatile half, half* %rhs_ptr
407 %tst1 = fcmp nnan ogt half %lhs, %rhs
408 %val1 = select i1 %tst1, half %a, half %b
409 store half %val1, half* @varhalf
410 ret void
411 }
412
413 define void @test_vsel32oge_nnan(half* %lhs_ptr, half* %rhs_ptr, half* %a_ptr, half* %b_ptr) {
414 ; CHECK-LABEL: test_vsel32oge_nnan:
415 ; CHECK: @ %bb.0:
416 ; CHECK-NEXT: vldr.16 s0, [r2]
417 ; CHECK-NEXT: vldr.16 s2, [r3]
418 ; CHECK-NEXT: vldr.16 s4, [r0]
419 ; CHECK-NEXT: vldr.16 s6, [r1]
420 ; CHECK-NEXT: movw r0, :lower16:varhalf
421 ; CHECK-NEXT: vcmpe.f16 s4, s6
422 ; CHECK-NEXT: movt r0, :upper16:varhalf
423 ; CHECK-NEXT: vmrs APSR_nzcv, fpscr
424 ; CHECK-NEXT: vselge.f16 s0, s0, s2
425 ; CHECK-NEXT: vstr.16 s0, [r0]
426 ; CHECK-NEXT: bx lr
427 %a = load volatile half, half* %a_ptr
428 %b = load volatile half, half* %b_ptr
429 %lhs = load volatile half, half* %lhs_ptr
430 %rhs = load volatile half, half* %rhs_ptr
431 %tst1 = fcmp nnan oge half %lhs, %rhs
432 %val1 = select i1 %tst1, half %a, half %b
433 store half %val1, half* @varhalf
434 ret void
435 }
436
437 define void @test_vsel32oeq_nnan(half* %lhs_ptr, half* %rhs_ptr, half* %a_ptr, half* %b_ptr) {
438 ; CHECK-LABEL: test_vsel32oeq_nnan:
439 ; CHECK: @ %bb.0:
440 ; CHECK-NEXT: vldr.16 s0, [r2]
441 ; CHECK-NEXT: vldr.16 s2, [r3]
442 ; CHECK-NEXT: vldr.16 s4, [r0]
443 ; CHECK-NEXT: vldr.16 s6, [r1]
444 ; CHECK-NEXT: movw r0, :lower16:varhalf
445 ; CHECK-NEXT: vcmp.f16 s4, s6
446 ; CHECK-NEXT: movt r0, :upper16:varhalf
447 ; CHECK-NEXT: vmrs APSR_nzcv, fpscr
448 ; CHECK-NEXT: vseleq.f16 s0, s0, s2
449 ; CHECK-NEXT: vstr.16 s0, [r0]
450 ; CHECK-NEXT: bx lr
451 %a = load volatile half, half* %a_ptr
452 %b = load volatile half, half* %b_ptr
453 %lhs = load volatile half, half* %lhs_ptr
454 %rhs = load volatile half, half* %rhs_ptr
455 %tst1 = fcmp nnan oeq half %lhs, %rhs
456 %val1 = select i1 %tst1, half %a, half %b
457 store half %val1, half* @varhalf
458 ret void
459 }
460
461 define void @test_vsel32ugt_nnan(half* %lhs_ptr, half* %rhs_ptr, half* %a_ptr, half* %b_ptr) {
462 ; CHECK-LABEL: test_vsel32ugt_nnan:
463 ; CHECK: @ %bb.0:
464 ; CHECK-NEXT: vldr.16 s0, [r2]
465 ; CHECK-NEXT: vldr.16 s2, [r3]
466 ; CHECK-NEXT: vldr.16 s4, [r0]
467 ; CHECK-NEXT: vldr.16 s6, [r1]
468 ; CHECK-NEXT: movw r0, :lower16:varhalf
469 ; CHECK-NEXT: vcmpe.f16 s4, s6
470 ; CHECK-NEXT: movt r0, :upper16:varhalf
471 ; CHECK-NEXT: vmrs APSR_nzcv, fpscr
472 ; CHECK-NEXT: vselgt.f16 s0, s0, s2
473 ; CHECK-NEXT: vstr.16 s0, [r0]
474 ; CHECK-NEXT: bx lr
475 %a = load volatile half, half* %a_ptr
476 %b = load volatile half, half* %b_ptr
477 %lhs = load volatile half, half* %lhs_ptr
478 %rhs = load volatile half, half* %rhs_ptr
479 %tst1 = fcmp nnan ugt half %lhs, %rhs
480 %val1 = select i1 %tst1, half %a, half %b
481 store half %val1, half* @varhalf
482 ret void
483 }
484
485 define void @test_vsel32uge_nnan(half* %lhs_ptr, half* %rhs_ptr, half* %a_ptr, half* %b_ptr) {
486 ; CHECK-LABEL: test_vsel32uge_nnan:
487 ; CHECK: @ %bb.0:
488 ; CHECK-NEXT: vldr.16 s0, [r2]
489 ; CHECK-NEXT: vldr.16 s2, [r3]
490 ; CHECK-NEXT: vldr.16 s4, [r0]
491 ; CHECK-NEXT: vldr.16 s6, [r1]
492 ; CHECK-NEXT: movw r0, :lower16:varhalf
493 ; CHECK-NEXT: vcmpe.f16 s4, s6
494 ; CHECK-NEXT: movt r0, :upper16:varhalf
495 ; CHECK-NEXT: vmrs APSR_nzcv, fpscr
496 ; CHECK-NEXT: vselge.f16 s0, s0, s2
497 ; CHECK-NEXT: vstr.16 s0, [r0]
498 ; CHECK-NEXT: bx lr
499 %a = load volatile half, half* %a_ptr
500 %b = load volatile half, half* %b_ptr
501 %lhs = load volatile half, half* %lhs_ptr
502 %rhs = load volatile half, half* %rhs_ptr
503 %tst1 = fcmp nnan uge half %lhs, %rhs
504 %val1 = select i1 %tst1, half %a, half %b
505 store half %val1, half* @varhalf
506 ret void
507 }
508
509 define void @test_vsel32olt_nnan(half* %lhs_ptr, half* %rhs_ptr, half* %a_ptr, half* %b_ptr) {
510 ; CHECK-LABEL: test_vsel32olt_nnan:
511 ; CHECK: @ %bb.0:
512 ; CHECK-NEXT: vldr.16 s0, [r2]
513 ; CHECK-NEXT: vldr.16 s2, [r3]
514 ; CHECK-NEXT: vldr.16 s4, [r0]
515 ; CHECK-NEXT: vldr.16 s6, [r1]
516 ; CHECK-NEXT: movw r0, :lower16:varhalf
517 ; CHECK-NEXT: vcmpe.f16 s6, s4
518 ; CHECK-NEXT: movt r0, :upper16:varhalf
519 ; CHECK-NEXT: vmrs APSR_nzcv, fpscr
520 ; CHECK-NEXT: vselgt.f16 s0, s0, s2
521 ; CHECK-NEXT: vstr.16 s0, [r0]
522 ; CHECK-NEXT: bx lr
523 %a = load volatile half, half* %a_ptr
524 %b = load volatile half, half* %b_ptr
525 %lhs = load volatile half, half* %lhs_ptr
526 %rhs = load volatile half, half* %rhs_ptr
527 %tst1 = fcmp nnan olt half %lhs, %rhs
528 %val1 = select i1 %tst1, half %a, half %b
529 store half %val1, half* @varhalf
530 ret void
531 }
532
533 define void @test_vsel32ult_nnan(half* %lhs_ptr, half* %rhs_ptr, half* %a_ptr, half* %b_ptr) {
534 ; CHECK-LABEL: test_vsel32ult_nnan:
535 ; CHECK: @ %bb.0:
536 ; CHECK-NEXT: vldr.16 s0, [r2]
537 ; CHECK-NEXT: vldr.16 s2, [r3]
538 ; CHECK-NEXT: vldr.16 s4, [r0]
539 ; CHECK-NEXT: vldr.16 s6, [r1]
540 ; CHECK-NEXT: movw r0, :lower16:varhalf
541 ; CHECK-NEXT: vcmpe.f16 s6, s4
542 ; CHECK-NEXT: movt r0, :upper16:varhalf
543 ; CHECK-NEXT: vmrs APSR_nzcv, fpscr
544 ; CHECK-NEXT: vselgt.f16 s0, s0, s2
545 ; CHECK-NEXT: vstr.16 s0, [r0]
546 ; CHECK-NEXT: bx lr
547 %a = load volatile half, half* %a_ptr
548 %b = load volatile half, half* %b_ptr
549 %lhs = load volatile half, half* %lhs_ptr
550 %rhs = load volatile half, half* %rhs_ptr
551 %tst1 = fcmp nnan ult half %lhs, %rhs
552 %val1 = select i1 %tst1, half %a, half %b
553 store half %val1, half* @varhalf
554 ret void
555 }
556
557 define void @test_vsel32ole_nnan(half* %lhs_ptr, half* %rhs_ptr, half* %a_ptr, half* %b_ptr) {
558 ; CHECK-LABEL: test_vsel32ole_nnan:
559 ; CHECK: @ %bb.0:
560 ; CHECK-NEXT: vldr.16 s0, [r2]
561 ; CHECK-NEXT: vldr.16 s2, [r3]
562 ; CHECK-NEXT: vldr.16 s4, [r0]
563 ; CHECK-NEXT: vldr.16 s6, [r1]
564 ; CHECK-NEXT: movw r0, :lower16:varhalf
565 ; CHECK-NEXT: vcmpe.f16 s6, s4
566 ; CHECK-NEXT: movt r0, :upper16:varhalf
567 ; CHECK-NEXT: vmrs APSR_nzcv, fpscr
568 ; CHECK-NEXT: vselge.f16 s0, s0, s2
569 ; CHECK-NEXT: vstr.16 s0, [r0]
570 ; CHECK-NEXT: bx lr
571 %a = load volatile half, half* %a_ptr
572 %b = load volatile half, half* %b_ptr
573 %lhs = load volatile half, half* %lhs_ptr
574 %rhs = load volatile half, half* %rhs_ptr
575 %tst1 = fcmp nnan ole half %lhs, %rhs
576 %val1 = select i1 %tst1, half %a, half %b
577 store half %val1, half* @varhalf
578 ret void
579 }
580
581 define void @test_vsel32ule_nnan(half* %lhs_ptr, half* %rhs_ptr, half* %a_ptr, half* %b_ptr) {
582 ; CHECK-LABEL: test_vsel32ule_nnan:
583 ; CHECK: @ %bb.0:
584 ; CHECK-NEXT: vldr.16 s0, [r2]
585 ; CHECK-NEXT: vldr.16 s2, [r3]
586 ; CHECK-NEXT: vldr.16 s4, [r0]
587 ; CHECK-NEXT: vldr.16 s6, [r1]
588 ; CHECK-NEXT: movw r0, :lower16:varhalf
589 ; CHECK-NEXT: vcmpe.f16 s6, s4
590 ; CHECK-NEXT: movt r0, :upper16:varhalf
591 ; CHECK-NEXT: vmrs APSR_nzcv, fpscr
592 ; CHECK-NEXT: vselge.f16 s0, s0, s2
593 ; CHECK-NEXT: vstr.16 s0, [r0]
594 ; CHECK-NEXT: bx lr
595 %a = load volatile half, half* %a_ptr
596 %b = load volatile half, half* %b_ptr
597 %lhs = load volatile half, half* %lhs_ptr
598 %rhs = load volatile half, half* %rhs_ptr
599 %tst1 = fcmp nnan ule half %lhs, %rhs
600 %val1 = select i1 %tst1, half %a, half %b
601 store half %val1, half* @varhalf
602 ret void
603 }
604
605 define void @test_vsel32ord_nnan(half* %lhs_ptr, half* %rhs_ptr, half* %a_ptr, half* %b_ptr) {
606 ; CHECK-LABEL: test_vsel32ord_nnan:
607 ; CHECK: @ %bb.0:
608 ; CHECK-NEXT: vldr.16 s0, [r2]
609 ; CHECK-NEXT: vldr.16 s2, [r3]
610 ; CHECK-NEXT: vldr.16 s4, [r0]
611 ; CHECK-NEXT: vldr.16 s6, [r1]
612 ; CHECK-NEXT: movw r0, :lower16:varhalf
613 ; CHECK-NEXT: vcmpe.f16 s4, s6
614 ; CHECK-NEXT: movt r0, :upper16:varhalf
615 ; CHECK-NEXT: vmrs APSR_nzcv, fpscr
616 ; CHECK-NEXT: vselvs.f16 s0, s2, s0
617 ; CHECK-NEXT: vstr.16 s0, [r0]
618 ; CHECK-NEXT: bx lr
619 %a = load volatile half, half* %a_ptr
620 %b = load volatile half, half* %b_ptr
621 %lhs = load volatile half, half* %lhs_ptr
622 %rhs = load volatile half, half* %rhs_ptr
623 %tst1 = fcmp nnan ord half %lhs, %rhs
624 %val1 = select i1 %tst1, half %a, half %b
625 store half %val1, half* @varhalf
626 ret void
627 }
628
629 define void @test_vsel32une_nnan(half* %lhs_ptr, half* %rhs_ptr, half* %a_ptr, half* %b_ptr) {
630 ; CHECK-LABEL: test_vsel32une_nnan:
631 ; CHECK: @ %bb.0:
632 ; CHECK-NEXT: vldr.16 s0, [r2]
633 ; CHECK-NEXT: vldr.16 s2, [r3]
634 ; CHECK-NEXT: vldr.16 s4, [r0]
635 ; CHECK-NEXT: vldr.16 s6, [r1]
636 ; CHECK-NEXT: movw r0, :lower16:varhalf
637 ; CHECK-NEXT: vcmp.f16 s4, s6
638 ; CHECK-NEXT: movt r0, :upper16:varhalf
639 ; CHECK-NEXT: vmrs APSR_nzcv, fpscr
640 ; CHECK-NEXT: vseleq.f16 s0, s2, s0
641 ; CHECK-NEXT: vstr.16 s0, [r0]
642 ; CHECK-NEXT: bx lr
643 %a = load volatile half, half* %a_ptr
644 %b = load volatile half, half* %b_ptr
645 %lhs = load volatile half, half* %lhs_ptr
646 %rhs = load volatile half, half* %rhs_ptr
647 %tst1 = fcmp nnan une half %lhs, %rhs
648 %val1 = select i1 %tst1, half %a, half %b
649 store half %val1, half* @varhalf
650 ret void
651 }
652
653 define void @test_vsel32uno_nnan(half* %lhs_ptr, half* %rhs_ptr, half* %a_ptr, half* %b_ptr) {
654 ; CHECK-LABEL: test_vsel32uno_nnan:
655 ; CHECK: @ %bb.0:
656 ; CHECK-NEXT: vldr.16 s0, [r2]
657 ; CHECK-NEXT: vldr.16 s2, [r3]
658 ; CHECK-NEXT: vldr.16 s4, [r0]
659 ; CHECK-NEXT: vldr.16 s6, [r1]
660 ; CHECK-NEXT: movw r0, :lower16:varhalf
661 ; CHECK-NEXT: vcmpe.f16 s4, s6
662 ; CHECK-NEXT: movt r0, :upper16:varhalf
663 ; CHECK-NEXT: vmrs APSR_nzcv, fpscr
664 ; CHECK-NEXT: vselvs.f16 s0, s0, s2
665 ; CHECK-NEXT: vstr.16 s0, [r0]
666 ; CHECK-NEXT: bx lr
667 %a = load volatile half, half* %a_ptr
668 %b = load volatile half, half* %b_ptr
669 %lhs = load volatile half, half* %lhs_ptr
670 %rhs = load volatile half, half* %rhs_ptr
671 %tst1 = fcmp nnan uno half %lhs, %rhs
672 %val1 = select i1 %tst1, half %a, half %b
673 store half %val1, half* @varhalf
674 ret void
675 }