1 ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
2 ; RUN: llc -mtriple=riscv64 -verify-machineinstrs < %s \
3 ; RUN: | FileCheck %s -check-prefix=RV64I
4 ; RUN: llc -mtriple=riscv64 -mattr=+experimental-b -verify-machineinstrs < %s \
5 ; RUN: | FileCheck %s -check-prefix=RV64B
6 ; RUN: llc -mtriple=riscv64 -mattr=+experimental-zbt -verify-machineinstrs < %s \
7 ; RUN: | FileCheck %s -check-prefix=RV64ZBT
9 define signext i32 @cmix_i32(i32 signext %a, i32 signext %b, i32 signext %c) nounwind {
10 ; RV64I-LABEL: cmix_i32:
12 ; RV64I-NEXT: and a0, a1, a0
13 ; RV64I-NEXT: not a1, a1
14 ; RV64I-NEXT: and a1, a1, a2
15 ; RV64I-NEXT: or a0, a1, a0
18 ; RV64B-LABEL: cmix_i32:
20 ; RV64B-NEXT: cmix a0, a1, a0, a2
23 ; RV64ZBT-LABEL: cmix_i32:
25 ; RV64ZBT-NEXT: cmix a0, a1, a0, a2
29 %and1 = and i32 %neg, %c
30 %or = or i32 %and1, %and
34 define i64 @cmix_i64(i64 %a, i64 %b, i64 %c) nounwind {
35 ; RV64I-LABEL: cmix_i64:
37 ; RV64I-NEXT: and a0, a1, a0
38 ; RV64I-NEXT: not a1, a1
39 ; RV64I-NEXT: and a1, a1, a2
40 ; RV64I-NEXT: or a0, a1, a0
43 ; RV64B-LABEL: cmix_i64:
45 ; RV64B-NEXT: cmix a0, a1, a0, a2
48 ; RV64ZBT-LABEL: cmix_i64:
50 ; RV64ZBT-NEXT: cmix a0, a1, a0, a2
54 %and1 = and i64 %neg, %c
55 %or = or i64 %and1, %and
59 define signext i32 @cmov_i32(i32 signext %a, i32 signext %b, i32 signext %c) nounwind {
60 ; RV64I-LABEL: cmov_i32:
62 ; RV64I-NEXT: beqz a1, .LBB2_2
63 ; RV64I-NEXT: # %bb.1:
64 ; RV64I-NEXT: mv a2, a0
65 ; RV64I-NEXT: .LBB2_2:
66 ; RV64I-NEXT: mv a0, a2
69 ; RV64B-LABEL: cmov_i32:
71 ; RV64B-NEXT: cmov a0, a1, a0, a2
74 ; RV64ZBT-LABEL: cmov_i32:
76 ; RV64ZBT-NEXT: cmov a0, a1, a0, a2
78 %tobool.not = icmp eq i32 %b, 0
79 %cond = select i1 %tobool.not, i32 %c, i32 %a
83 define signext i32 @cmov_sle_i32(i32 signext %a, i32 signext %b, i32 signext %c, i32 signext %d) nounwind {
84 ; RV64I-LABEL: cmov_sle_i32:
86 ; RV64I-NEXT: bge a2, a1, .LBB3_2
87 ; RV64I-NEXT: # %bb.1:
88 ; RV64I-NEXT: mv a0, a3
89 ; RV64I-NEXT: .LBB3_2:
92 ; RV64B-LABEL: cmov_sle_i32:
94 ; RV64B-NEXT: slt a1, a2, a1
95 ; RV64B-NEXT: cmov a0, a1, a3, a0
98 ; RV64ZBT-LABEL: cmov_sle_i32:
100 ; RV64ZBT-NEXT: slt a1, a2, a1
101 ; RV64ZBT-NEXT: cmov a0, a1, a3, a0
103 %tobool = icmp sle i32 %b, %c
104 %cond = select i1 %tobool, i32 %a, i32 %d
108 define signext i32 @cmov_sge_i32(i32 signext %a, i32 signext %b, i32 signext %c, i32 signext %d) nounwind {
109 ; RV64I-LABEL: cmov_sge_i32:
111 ; RV64I-NEXT: bge a1, a2, .LBB4_2
112 ; RV64I-NEXT: # %bb.1:
113 ; RV64I-NEXT: mv a0, a3
114 ; RV64I-NEXT: .LBB4_2:
117 ; RV64B-LABEL: cmov_sge_i32:
119 ; RV64B-NEXT: slt a1, a1, a2
120 ; RV64B-NEXT: cmov a0, a1, a3, a0
123 ; RV64ZBT-LABEL: cmov_sge_i32:
125 ; RV64ZBT-NEXT: slt a1, a1, a2
126 ; RV64ZBT-NEXT: cmov a0, a1, a3, a0
128 %tobool = icmp sge i32 %b, %c
129 %cond = select i1 %tobool, i32 %a, i32 %d
133 define signext i32 @cmov_ule_i32(i32 signext %a, i32 signext %b, i32 signext %c, i32 signext %d) nounwind {
134 ; RV64I-LABEL: cmov_ule_i32:
136 ; RV64I-NEXT: bgeu a2, a1, .LBB5_2
137 ; RV64I-NEXT: # %bb.1:
138 ; RV64I-NEXT: mv a0, a3
139 ; RV64I-NEXT: .LBB5_2:
142 ; RV64B-LABEL: cmov_ule_i32:
144 ; RV64B-NEXT: sltu a1, a2, a1
145 ; RV64B-NEXT: cmov a0, a1, a3, a0
148 ; RV64ZBT-LABEL: cmov_ule_i32:
150 ; RV64ZBT-NEXT: sltu a1, a2, a1
151 ; RV64ZBT-NEXT: cmov a0, a1, a3, a0
153 %tobool = icmp ule i32 %b, %c
154 %cond = select i1 %tobool, i32 %a, i32 %d
158 define signext i32 @cmov_uge_i32(i32 signext %a, i32 signext %b, i32 signext %c, i32 signext %d) nounwind {
159 ; RV64I-LABEL: cmov_uge_i32:
161 ; RV64I-NEXT: bgeu a1, a2, .LBB6_2
162 ; RV64I-NEXT: # %bb.1:
163 ; RV64I-NEXT: mv a0, a3
164 ; RV64I-NEXT: .LBB6_2:
167 ; RV64B-LABEL: cmov_uge_i32:
169 ; RV64B-NEXT: sltu a1, a1, a2
170 ; RV64B-NEXT: cmov a0, a1, a3, a0
173 ; RV64ZBT-LABEL: cmov_uge_i32:
175 ; RV64ZBT-NEXT: sltu a1, a1, a2
176 ; RV64ZBT-NEXT: cmov a0, a1, a3, a0
178 %tobool = icmp uge i32 %b, %c
179 %cond = select i1 %tobool, i32 %a, i32 %d
183 define i64 @cmov_i64(i64 %a, i64 %b, i64 %c) nounwind {
184 ; RV64I-LABEL: cmov_i64:
186 ; RV64I-NEXT: beqz a1, .LBB7_2
187 ; RV64I-NEXT: # %bb.1:
188 ; RV64I-NEXT: mv a2, a0
189 ; RV64I-NEXT: .LBB7_2:
190 ; RV64I-NEXT: mv a0, a2
193 ; RV64B-LABEL: cmov_i64:
195 ; RV64B-NEXT: cmov a0, a1, a0, a2
198 ; RV64ZBT-LABEL: cmov_i64:
200 ; RV64ZBT-NEXT: cmov a0, a1, a0, a2
202 %tobool.not = icmp eq i64 %b, 0
203 %cond = select i1 %tobool.not, i64 %c, i64 %a
207 define i64 @cmov_sle_i64(i64 %a, i64 %b, i64 %c, i64 %d) nounwind {
208 ; RV64I-LABEL: cmov_sle_i64:
210 ; RV64I-NEXT: bge a2, a1, .LBB8_2
211 ; RV64I-NEXT: # %bb.1:
212 ; RV64I-NEXT: mv a0, a3
213 ; RV64I-NEXT: .LBB8_2:
216 ; RV64B-LABEL: cmov_sle_i64:
218 ; RV64B-NEXT: slt a1, a2, a1
219 ; RV64B-NEXT: cmov a0, a1, a3, a0
222 ; RV64ZBT-LABEL: cmov_sle_i64:
224 ; RV64ZBT-NEXT: slt a1, a2, a1
225 ; RV64ZBT-NEXT: cmov a0, a1, a3, a0
227 %tobool = icmp sle i64 %b, %c
228 %cond = select i1 %tobool, i64 %a, i64 %d
232 define i64 @cmov_sge_i64(i64 %a, i64 %b, i64 %c, i64 %d) nounwind {
233 ; RV64I-LABEL: cmov_sge_i64:
235 ; RV64I-NEXT: bge a1, a2, .LBB9_2
236 ; RV64I-NEXT: # %bb.1:
237 ; RV64I-NEXT: mv a0, a3
238 ; RV64I-NEXT: .LBB9_2:
241 ; RV64B-LABEL: cmov_sge_i64:
243 ; RV64B-NEXT: slt a1, a1, a2
244 ; RV64B-NEXT: cmov a0, a1, a3, a0
247 ; RV64ZBT-LABEL: cmov_sge_i64:
249 ; RV64ZBT-NEXT: slt a1, a1, a2
250 ; RV64ZBT-NEXT: cmov a0, a1, a3, a0
252 %tobool = icmp sge i64 %b, %c
253 %cond = select i1 %tobool, i64 %a, i64 %d
257 define i64 @cmov_ule_i64(i64 %a, i64 %b, i64 %c, i64 %d) nounwind {
258 ; RV64I-LABEL: cmov_ule_i64:
260 ; RV64I-NEXT: bgeu a2, a1, .LBB10_2
261 ; RV64I-NEXT: # %bb.1:
262 ; RV64I-NEXT: mv a0, a3
263 ; RV64I-NEXT: .LBB10_2:
266 ; RV64B-LABEL: cmov_ule_i64:
268 ; RV64B-NEXT: sltu a1, a2, a1
269 ; RV64B-NEXT: cmov a0, a1, a3, a0
272 ; RV64ZBT-LABEL: cmov_ule_i64:
274 ; RV64ZBT-NEXT: sltu a1, a2, a1
275 ; RV64ZBT-NEXT: cmov a0, a1, a3, a0
277 %tobool = icmp ule i64 %b, %c
278 %cond = select i1 %tobool, i64 %a, i64 %d
282 define i64 @cmov_uge_i64(i64 %a, i64 %b, i64 %c, i64 %d) nounwind {
283 ; RV64I-LABEL: cmov_uge_i64:
285 ; RV64I-NEXT: bgeu a1, a2, .LBB11_2
286 ; RV64I-NEXT: # %bb.1:
287 ; RV64I-NEXT: mv a0, a3
288 ; RV64I-NEXT: .LBB11_2:
291 ; RV64B-LABEL: cmov_uge_i64:
293 ; RV64B-NEXT: sltu a1, a1, a2
294 ; RV64B-NEXT: cmov a0, a1, a3, a0
297 ; RV64ZBT-LABEL: cmov_uge_i64:
299 ; RV64ZBT-NEXT: sltu a1, a1, a2
300 ; RV64ZBT-NEXT: cmov a0, a1, a3, a0
302 %tobool = icmp uge i64 %b, %c
303 %cond = select i1 %tobool, i64 %a, i64 %d
307 declare i32 @llvm.fshl.i32(i32, i32, i32)
309 define signext i32 @fshl_i32(i32 signext %a, i32 signext %b, i32 signext %c) nounwind {
310 ; RV64I-LABEL: fshl_i32:
312 ; RV64I-NEXT: slli a0, a0, 32
313 ; RV64I-NEXT: slli a1, a1, 32
314 ; RV64I-NEXT: srli a1, a1, 32
315 ; RV64I-NEXT: or a0, a0, a1
316 ; RV64I-NEXT: andi a1, a2, 31
317 ; RV64I-NEXT: sll a0, a0, a1
318 ; RV64I-NEXT: srai a0, a0, 32
321 ; RV64B-LABEL: fshl_i32:
323 ; RV64B-NEXT: andi a2, a2, 31
324 ; RV64B-NEXT: fslw a0, a0, a1, a2
327 ; RV64ZBT-LABEL: fshl_i32:
329 ; RV64ZBT-NEXT: andi a2, a2, 31
330 ; RV64ZBT-NEXT: fslw a0, a0, a1, a2
332 %1 = tail call i32 @llvm.fshl.i32(i32 %a, i32 %b, i32 %c)
336 ; Similar to fshl_i32 but result is not sign extended.
337 define void @fshl_i32_nosext(i32 signext %a, i32 signext %b, i32 signext %c, i32* %x) nounwind {
338 ; RV64I-LABEL: fshl_i32_nosext:
340 ; RV64I-NEXT: slli a0, a0, 32
341 ; RV64I-NEXT: slli a1, a1, 32
342 ; RV64I-NEXT: srli a1, a1, 32
343 ; RV64I-NEXT: or a0, a0, a1
344 ; RV64I-NEXT: andi a1, a2, 31
345 ; RV64I-NEXT: sll a0, a0, a1
346 ; RV64I-NEXT: srli a0, a0, 32
347 ; RV64I-NEXT: sw a0, 0(a3)
350 ; RV64B-LABEL: fshl_i32_nosext:
352 ; RV64B-NEXT: andi a2, a2, 31
353 ; RV64B-NEXT: fslw a0, a0, a1, a2
354 ; RV64B-NEXT: sw a0, 0(a3)
357 ; RV64ZBT-LABEL: fshl_i32_nosext:
359 ; RV64ZBT-NEXT: andi a2, a2, 31
360 ; RV64ZBT-NEXT: fslw a0, a0, a1, a2
361 ; RV64ZBT-NEXT: sw a0, 0(a3)
363 %1 = tail call i32 @llvm.fshl.i32(i32 %a, i32 %b, i32 %c)
364 store i32 %1, i32* %x
368 declare i64 @llvm.fshl.i64(i64, i64, i64)
370 define i64 @fshl_i64(i64 %a, i64 %b, i64 %c) nounwind {
371 ; RV64I-LABEL: fshl_i64:
373 ; RV64I-NEXT: sll a0, a0, a2
374 ; RV64I-NEXT: not a2, a2
375 ; RV64I-NEXT: srli a1, a1, 1
376 ; RV64I-NEXT: srl a1, a1, a2
377 ; RV64I-NEXT: or a0, a0, a1
380 ; RV64B-LABEL: fshl_i64:
382 ; RV64B-NEXT: andi a2, a2, 63
383 ; RV64B-NEXT: fsl a0, a0, a1, a2
386 ; RV64ZBT-LABEL: fshl_i64:
388 ; RV64ZBT-NEXT: andi a2, a2, 63
389 ; RV64ZBT-NEXT: fsl a0, a0, a1, a2
391 %1 = tail call i64 @llvm.fshl.i64(i64 %a, i64 %b, i64 %c)
395 declare i32 @llvm.fshr.i32(i32, i32, i32)
397 define signext i32 @fshr_i32(i32 signext %a, i32 signext %b, i32 signext %c) nounwind {
398 ; RV64I-LABEL: fshr_i32:
400 ; RV64I-NEXT: slli a0, a0, 32
401 ; RV64I-NEXT: slli a1, a1, 32
402 ; RV64I-NEXT: srli a1, a1, 32
403 ; RV64I-NEXT: or a0, a0, a1
404 ; RV64I-NEXT: andi a1, a2, 31
405 ; RV64I-NEXT: srl a0, a0, a1
406 ; RV64I-NEXT: sext.w a0, a0
409 ; RV64B-LABEL: fshr_i32:
411 ; RV64B-NEXT: andi a2, a2, 31
412 ; RV64B-NEXT: fsrw a0, a1, a0, a2
415 ; RV64ZBT-LABEL: fshr_i32:
417 ; RV64ZBT-NEXT: andi a2, a2, 31
418 ; RV64ZBT-NEXT: fsrw a0, a1, a0, a2
420 %1 = tail call i32 @llvm.fshr.i32(i32 %a, i32 %b, i32 %c)
424 ; Similar to fshr_i32 but result is not sign extended.
425 define void @fshr_i32_nosext(i32 signext %a, i32 signext %b, i32 signext %c, i32* %x) nounwind {
426 ; RV64I-LABEL: fshr_i32_nosext:
428 ; RV64I-NEXT: slli a0, a0, 32
429 ; RV64I-NEXT: slli a1, a1, 32
430 ; RV64I-NEXT: srli a1, a1, 32
431 ; RV64I-NEXT: or a0, a0, a1
432 ; RV64I-NEXT: andi a1, a2, 31
433 ; RV64I-NEXT: srl a0, a0, a1
434 ; RV64I-NEXT: sw a0, 0(a3)
437 ; RV64B-LABEL: fshr_i32_nosext:
439 ; RV64B-NEXT: andi a2, a2, 31
440 ; RV64B-NEXT: fsrw a0, a1, a0, a2
441 ; RV64B-NEXT: sw a0, 0(a3)
444 ; RV64ZBT-LABEL: fshr_i32_nosext:
446 ; RV64ZBT-NEXT: andi a2, a2, 31
447 ; RV64ZBT-NEXT: fsrw a0, a1, a0, a2
448 ; RV64ZBT-NEXT: sw a0, 0(a3)
450 %1 = tail call i32 @llvm.fshr.i32(i32 %a, i32 %b, i32 %c)
451 store i32 %1, i32* %x
455 declare i64 @llvm.fshr.i64(i64, i64, i64)
457 define i64 @fshr_i64(i64 %a, i64 %b, i64 %c) nounwind {
458 ; RV64I-LABEL: fshr_i64:
460 ; RV64I-NEXT: srl a1, a1, a2
461 ; RV64I-NEXT: not a2, a2
462 ; RV64I-NEXT: slli a0, a0, 1
463 ; RV64I-NEXT: sll a0, a0, a2
464 ; RV64I-NEXT: or a0, a0, a1
467 ; RV64B-LABEL: fshr_i64:
469 ; RV64B-NEXT: andi a2, a2, 63
470 ; RV64B-NEXT: fsr a0, a1, a0, a2
473 ; RV64ZBT-LABEL: fshr_i64:
475 ; RV64ZBT-NEXT: andi a2, a2, 63
476 ; RV64ZBT-NEXT: fsr a0, a1, a0, a2
478 %1 = tail call i64 @llvm.fshr.i64(i64 %a, i64 %b, i64 %c)
482 define signext i32 @fshri_i32(i32 signext %a, i32 signext %b) nounwind {
483 ; RV64I-LABEL: fshri_i32:
485 ; RV64I-NEXT: srliw a1, a1, 5
486 ; RV64I-NEXT: slli a0, a0, 27
487 ; RV64I-NEXT: or a0, a0, a1
488 ; RV64I-NEXT: sext.w a0, a0
491 ; RV64B-LABEL: fshri_i32:
493 ; RV64B-NEXT: fsriw a0, a1, a0, 5
496 ; RV64ZBT-LABEL: fshri_i32:
498 ; RV64ZBT-NEXT: fsriw a0, a1, a0, 5
500 %1 = tail call i32 @llvm.fshr.i32(i32 %a, i32 %b, i32 5)
504 ; Similar to fshr_i32 but result is not sign extended.
505 define void @fshri_i32_nosext(i32 signext %a, i32 signext %b, i32* %x) nounwind {
506 ; RV64I-LABEL: fshri_i32_nosext:
508 ; RV64I-NEXT: srliw a1, a1, 5
509 ; RV64I-NEXT: slli a0, a0, 27
510 ; RV64I-NEXT: or a0, a0, a1
511 ; RV64I-NEXT: sw a0, 0(a2)
514 ; RV64B-LABEL: fshri_i32_nosext:
516 ; RV64B-NEXT: fsriw a0, a1, a0, 5
517 ; RV64B-NEXT: sw a0, 0(a2)
520 ; RV64ZBT-LABEL: fshri_i32_nosext:
522 ; RV64ZBT-NEXT: fsriw a0, a1, a0, 5
523 ; RV64ZBT-NEXT: sw a0, 0(a2)
525 %1 = tail call i32 @llvm.fshr.i32(i32 %a, i32 %b, i32 5)
526 store i32 %1, i32* %x
530 define i64 @fshri_i64(i64 %a, i64 %b) nounwind {
531 ; RV64I-LABEL: fshri_i64:
533 ; RV64I-NEXT: srli a1, a1, 5
534 ; RV64I-NEXT: slli a0, a0, 59
535 ; RV64I-NEXT: or a0, a0, a1
538 ; RV64B-LABEL: fshri_i64:
540 ; RV64B-NEXT: fsri a0, a1, a0, 5
543 ; RV64ZBT-LABEL: fshri_i64:
545 ; RV64ZBT-NEXT: fsri a0, a1, a0, 5
547 %1 = tail call i64 @llvm.fshr.i64(i64 %a, i64 %b, i64 5)
551 define signext i32 @fshli_i32(i32 signext %a, i32 signext %b) nounwind {
552 ; RV64I-LABEL: fshli_i32:
554 ; RV64I-NEXT: srliw a1, a1, 27
555 ; RV64I-NEXT: slli a0, a0, 5
556 ; RV64I-NEXT: or a0, a0, a1
557 ; RV64I-NEXT: sext.w a0, a0
560 ; RV64B-LABEL: fshli_i32:
562 ; RV64B-NEXT: fsriw a0, a1, a0, 27
565 ; RV64ZBT-LABEL: fshli_i32:
567 ; RV64ZBT-NEXT: fsriw a0, a1, a0, 27
569 %1 = tail call i32 @llvm.fshl.i32(i32 %a, i32 %b, i32 5)
573 ; Similar to fshl_i32 but result is not sign extended.
574 define void @fshli_i32_nosext(i32 signext %a, i32 signext %b, i32* %x) nounwind {
575 ; RV64I-LABEL: fshli_i32_nosext:
577 ; RV64I-NEXT: srliw a1, a1, 27
578 ; RV64I-NEXT: slli a0, a0, 5
579 ; RV64I-NEXT: or a0, a0, a1
580 ; RV64I-NEXT: sw a0, 0(a2)
583 ; RV64B-LABEL: fshli_i32_nosext:
585 ; RV64B-NEXT: fsriw a0, a1, a0, 27
586 ; RV64B-NEXT: sw a0, 0(a2)
589 ; RV64ZBT-LABEL: fshli_i32_nosext:
591 ; RV64ZBT-NEXT: fsriw a0, a1, a0, 27
592 ; RV64ZBT-NEXT: sw a0, 0(a2)
594 %1 = tail call i32 @llvm.fshl.i32(i32 %a, i32 %b, i32 5)
595 store i32 %1, i32* %x
599 define i64 @fshli_i64(i64 %a, i64 %b) nounwind {
600 ; RV64I-LABEL: fshli_i64:
602 ; RV64I-NEXT: srli a1, a1, 59
603 ; RV64I-NEXT: slli a0, a0, 5
604 ; RV64I-NEXT: or a0, a0, a1
607 ; RV64B-LABEL: fshli_i64:
609 ; RV64B-NEXT: fsri a0, a1, a0, 59
612 ; RV64ZBT-LABEL: fshli_i64:
614 ; RV64ZBT-NEXT: fsri a0, a1, a0, 59
616 %1 = tail call i64 @llvm.fshl.i64(i64 %a, i64 %b, i64 5)