1 ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
2 ; RUN: llc -mtriple=riscv32 -verify-machineinstrs < %s \
3 ; RUN: | FileCheck %s -check-prefixes=CHECK,RV32I
4 ; RUN: llc -mtriple=riscv32 -mattr=+zbb -verify-machineinstrs < %s \
5 ; RUN: | FileCheck %s -check-prefixes=CHECK,RV32ZBB-ZBP-ZBKB
6 ; RUN: llc -mtriple=riscv32 -mattr=+experimental-zbp -verify-machineinstrs < %s \
7 ; RUN: | FileCheck %s -check-prefixes=CHECK,RV32ZBB-ZBP-ZBKB
8 ; RUN: llc -mtriple=riscv32 -mattr=+zbkb -verify-machineinstrs < %s \
9 ; RUN: | FileCheck %s -check-prefixes=CHECK,RV32ZBB-ZBP-ZBKB
11 define i32 @andn_i32(i32 %a, i32 %b) nounwind {
12 ; RV32I-LABEL: andn_i32:
14 ; RV32I-NEXT: not a1, a1
15 ; RV32I-NEXT: and a0, a1, a0
18 ; RV32ZBB-ZBP-ZBKB-LABEL: andn_i32:
19 ; RV32ZBB-ZBP-ZBKB: # %bb.0:
20 ; RV32ZBB-ZBP-ZBKB-NEXT: andn a0, a0, a1
21 ; RV32ZBB-ZBP-ZBKB-NEXT: ret
23 %and = and i32 %neg, %a
27 define i64 @andn_i64(i64 %a, i64 %b) nounwind {
28 ; RV32I-LABEL: andn_i64:
30 ; RV32I-NEXT: not a3, a3
31 ; RV32I-NEXT: not a2, a2
32 ; RV32I-NEXT: and a0, a2, a0
33 ; RV32I-NEXT: and a1, a3, a1
36 ; RV32ZBB-ZBP-ZBKB-LABEL: andn_i64:
37 ; RV32ZBB-ZBP-ZBKB: # %bb.0:
38 ; RV32ZBB-ZBP-ZBKB-NEXT: andn a0, a0, a2
39 ; RV32ZBB-ZBP-ZBKB-NEXT: andn a1, a1, a3
40 ; RV32ZBB-ZBP-ZBKB-NEXT: ret
42 %and = and i64 %neg, %a
46 define i32 @orn_i32(i32 %a, i32 %b) nounwind {
47 ; RV32I-LABEL: orn_i32:
49 ; RV32I-NEXT: not a1, a1
50 ; RV32I-NEXT: or a0, a1, a0
53 ; RV32ZBB-ZBP-ZBKB-LABEL: orn_i32:
54 ; RV32ZBB-ZBP-ZBKB: # %bb.0:
55 ; RV32ZBB-ZBP-ZBKB-NEXT: orn a0, a0, a1
56 ; RV32ZBB-ZBP-ZBKB-NEXT: ret
62 define i64 @orn_i64(i64 %a, i64 %b) nounwind {
63 ; RV32I-LABEL: orn_i64:
65 ; RV32I-NEXT: not a3, a3
66 ; RV32I-NEXT: not a2, a2
67 ; RV32I-NEXT: or a0, a2, a0
68 ; RV32I-NEXT: or a1, a3, a1
71 ; RV32ZBB-ZBP-ZBKB-LABEL: orn_i64:
72 ; RV32ZBB-ZBP-ZBKB: # %bb.0:
73 ; RV32ZBB-ZBP-ZBKB-NEXT: orn a0, a0, a2
74 ; RV32ZBB-ZBP-ZBKB-NEXT: orn a1, a1, a3
75 ; RV32ZBB-ZBP-ZBKB-NEXT: ret
81 define i32 @xnor_i32(i32 %a, i32 %b) nounwind {
82 ; RV32I-LABEL: xnor_i32:
84 ; RV32I-NEXT: xor a0, a0, a1
85 ; RV32I-NEXT: not a0, a0
88 ; RV32ZBB-ZBP-ZBKB-LABEL: xnor_i32:
89 ; RV32ZBB-ZBP-ZBKB: # %bb.0:
90 ; RV32ZBB-ZBP-ZBKB-NEXT: xnor a0, a0, a1
91 ; RV32ZBB-ZBP-ZBKB-NEXT: ret
93 %xor = xor i32 %neg, %b
97 define i64 @xnor_i64(i64 %a, i64 %b) nounwind {
98 ; RV32I-LABEL: xnor_i64:
100 ; RV32I-NEXT: xor a1, a1, a3
101 ; RV32I-NEXT: xor a0, a0, a2
102 ; RV32I-NEXT: not a0, a0
103 ; RV32I-NEXT: not a1, a1
106 ; RV32ZBB-ZBP-ZBKB-LABEL: xnor_i64:
107 ; RV32ZBB-ZBP-ZBKB: # %bb.0:
108 ; RV32ZBB-ZBP-ZBKB-NEXT: xnor a0, a0, a2
109 ; RV32ZBB-ZBP-ZBKB-NEXT: xnor a1, a1, a3
110 ; RV32ZBB-ZBP-ZBKB-NEXT: ret
111 %neg = xor i64 %a, -1
112 %xor = xor i64 %neg, %b
116 declare i32 @llvm.fshl.i32(i32, i32, i32)
118 define i32 @rol_i32(i32 %a, i32 %b) nounwind {
119 ; RV32I-LABEL: rol_i32:
121 ; RV32I-NEXT: sll a2, a0, a1
122 ; RV32I-NEXT: neg a1, a1
123 ; RV32I-NEXT: srl a0, a0, a1
124 ; RV32I-NEXT: or a0, a2, a0
127 ; RV32ZBB-ZBP-ZBKB-LABEL: rol_i32:
128 ; RV32ZBB-ZBP-ZBKB: # %bb.0:
129 ; RV32ZBB-ZBP-ZBKB-NEXT: rol a0, a0, a1
130 ; RV32ZBB-ZBP-ZBKB-NEXT: ret
131 %or = tail call i32 @llvm.fshl.i32(i32 %a, i32 %a, i32 %b)
135 ; This test is presented here in case future expansions of the Bitmanip
136 ; extensions introduce instructions suitable for this pattern.
138 declare i64 @llvm.fshl.i64(i64, i64, i64)
140 define i64 @rol_i64(i64 %a, i64 %b) nounwind {
141 ; CHECK-LABEL: rol_i64:
143 ; CHECK-NEXT: slli a3, a2, 26
144 ; CHECK-NEXT: srli a5, a3, 31
145 ; CHECK-NEXT: mv a4, a1
146 ; CHECK-NEXT: bnez a5, .LBB7_2
147 ; CHECK-NEXT: # %bb.1:
148 ; CHECK-NEXT: mv a4, a0
149 ; CHECK-NEXT: .LBB7_2:
150 ; CHECK-NEXT: sll a3, a4, a2
151 ; CHECK-NEXT: bnez a5, .LBB7_4
152 ; CHECK-NEXT: # %bb.3:
153 ; CHECK-NEXT: mv a0, a1
154 ; CHECK-NEXT: .LBB7_4:
155 ; CHECK-NEXT: srli a1, a0, 1
156 ; CHECK-NEXT: not a5, a2
157 ; CHECK-NEXT: srl a1, a1, a5
158 ; CHECK-NEXT: or a3, a3, a1
159 ; CHECK-NEXT: sll a0, a0, a2
160 ; CHECK-NEXT: srli a1, a4, 1
161 ; CHECK-NEXT: srl a1, a1, a5
162 ; CHECK-NEXT: or a1, a0, a1
163 ; CHECK-NEXT: mv a0, a3
165 %or = tail call i64 @llvm.fshl.i64(i64 %a, i64 %a, i64 %b)
169 declare i32 @llvm.fshr.i32(i32, i32, i32)
171 define i32 @ror_i32(i32 %a, i32 %b) nounwind {
172 ; RV32I-LABEL: ror_i32:
174 ; RV32I-NEXT: srl a2, a0, a1
175 ; RV32I-NEXT: neg a1, a1
176 ; RV32I-NEXT: sll a0, a0, a1
177 ; RV32I-NEXT: or a0, a2, a0
180 ; RV32ZBB-ZBP-ZBKB-LABEL: ror_i32:
181 ; RV32ZBB-ZBP-ZBKB: # %bb.0:
182 ; RV32ZBB-ZBP-ZBKB-NEXT: ror a0, a0, a1
183 ; RV32ZBB-ZBP-ZBKB-NEXT: ret
184 %or = tail call i32 @llvm.fshr.i32(i32 %a, i32 %a, i32 %b)
188 ; This test is presented here in case future expansions of the Bitmanip
189 ; extensions introduce instructions suitable for this pattern.
191 declare i64 @llvm.fshr.i64(i64, i64, i64)
193 define i64 @ror_i64(i64 %a, i64 %b) nounwind {
194 ; CHECK-LABEL: ror_i64:
196 ; CHECK-NEXT: andi a5, a2, 32
197 ; CHECK-NEXT: mv a3, a0
198 ; CHECK-NEXT: beqz a5, .LBB9_2
199 ; CHECK-NEXT: # %bb.1:
200 ; CHECK-NEXT: mv a3, a1
201 ; CHECK-NEXT: .LBB9_2:
202 ; CHECK-NEXT: srl a4, a3, a2
203 ; CHECK-NEXT: beqz a5, .LBB9_4
204 ; CHECK-NEXT: # %bb.3:
205 ; CHECK-NEXT: mv a1, a0
206 ; CHECK-NEXT: .LBB9_4:
207 ; CHECK-NEXT: slli a0, a1, 1
208 ; CHECK-NEXT: not a5, a2
209 ; CHECK-NEXT: sll a0, a0, a5
210 ; CHECK-NEXT: or a0, a0, a4
211 ; CHECK-NEXT: srl a1, a1, a2
212 ; CHECK-NEXT: slli a2, a3, 1
213 ; CHECK-NEXT: sll a2, a2, a5
214 ; CHECK-NEXT: or a1, a2, a1
216 %or = tail call i64 @llvm.fshr.i64(i64 %a, i64 %a, i64 %b)
220 define i32 @rori_i32_fshl(i32 %a) nounwind {
221 ; RV32I-LABEL: rori_i32_fshl:
223 ; RV32I-NEXT: srli a1, a0, 1
224 ; RV32I-NEXT: slli a0, a0, 31
225 ; RV32I-NEXT: or a0, a0, a1
228 ; RV32ZBB-ZBP-ZBKB-LABEL: rori_i32_fshl:
229 ; RV32ZBB-ZBP-ZBKB: # %bb.0:
230 ; RV32ZBB-ZBP-ZBKB-NEXT: rori a0, a0, 1
231 ; RV32ZBB-ZBP-ZBKB-NEXT: ret
232 %1 = tail call i32 @llvm.fshl.i32(i32 %a, i32 %a, i32 31)
236 define i32 @rori_i32_fshr(i32 %a) nounwind {
237 ; RV32I-LABEL: rori_i32_fshr:
239 ; RV32I-NEXT: slli a1, a0, 1
240 ; RV32I-NEXT: srli a0, a0, 31
241 ; RV32I-NEXT: or a0, a0, a1
244 ; RV32ZBB-ZBP-ZBKB-LABEL: rori_i32_fshr:
245 ; RV32ZBB-ZBP-ZBKB: # %bb.0:
246 ; RV32ZBB-ZBP-ZBKB-NEXT: rori a0, a0, 31
247 ; RV32ZBB-ZBP-ZBKB-NEXT: ret
248 %1 = tail call i32 @llvm.fshr.i32(i32 %a, i32 %a, i32 31)
252 define i64 @rori_i64(i64 %a) nounwind {
253 ; CHECK-LABEL: rori_i64:
255 ; CHECK-NEXT: srli a2, a0, 1
256 ; CHECK-NEXT: slli a3, a1, 31
257 ; CHECK-NEXT: or a2, a3, a2
258 ; CHECK-NEXT: srli a1, a1, 1
259 ; CHECK-NEXT: slli a0, a0, 31
260 ; CHECK-NEXT: or a1, a0, a1
261 ; CHECK-NEXT: mv a0, a2
263 %1 = tail call i64 @llvm.fshl.i64(i64 %a, i64 %a, i64 63)
267 define i64 @rori_i64_fshr(i64 %a) nounwind {
268 ; CHECK-LABEL: rori_i64_fshr:
270 ; CHECK-NEXT: srli a2, a1, 31
271 ; CHECK-NEXT: slli a3, a0, 1
272 ; CHECK-NEXT: or a2, a3, a2
273 ; CHECK-NEXT: srli a0, a0, 31
274 ; CHECK-NEXT: slli a1, a1, 1
275 ; CHECK-NEXT: or a1, a1, a0
276 ; CHECK-NEXT: mv a0, a2
278 %1 = tail call i64 @llvm.fshr.i64(i64 %a, i64 %a, i64 63)
282 define i32 @not_shl_one_i32(i32 %x) {
283 ; RV32I-LABEL: not_shl_one_i32:
285 ; RV32I-NEXT: li a1, 1
286 ; RV32I-NEXT: sll a0, a1, a0
287 ; RV32I-NEXT: not a0, a0
290 ; RV32ZBB-ZBP-ZBKB-LABEL: not_shl_one_i32:
291 ; RV32ZBB-ZBP-ZBKB: # %bb.0:
292 ; RV32ZBB-ZBP-ZBKB-NEXT: li a1, -2
293 ; RV32ZBB-ZBP-ZBKB-NEXT: rol a0, a1, a0
294 ; RV32ZBB-ZBP-ZBKB-NEXT: ret
300 define i64 @not_shl_one_i64(i64 %x) {
301 ; RV32I-LABEL: not_shl_one_i64:
303 ; RV32I-NEXT: addi a3, a0, -32
304 ; RV32I-NEXT: li a2, 1
305 ; RV32I-NEXT: li a1, -1
306 ; RV32I-NEXT: bltz a3, .LBB15_2
307 ; RV32I-NEXT: # %bb.1:
308 ; RV32I-NEXT: sll a0, a2, a3
309 ; RV32I-NEXT: not a1, a0
310 ; RV32I-NEXT: li a0, -1
312 ; RV32I-NEXT: .LBB15_2:
313 ; RV32I-NEXT: sll a0, a2, a0
314 ; RV32I-NEXT: not a0, a0
317 ; RV32ZBB-ZBP-ZBKB-LABEL: not_shl_one_i64:
318 ; RV32ZBB-ZBP-ZBKB: # %bb.0:
319 ; RV32ZBB-ZBP-ZBKB-NEXT: addi a3, a0, -32
320 ; RV32ZBB-ZBP-ZBKB-NEXT: li a2, -2
321 ; RV32ZBB-ZBP-ZBKB-NEXT: li a1, -1
322 ; RV32ZBB-ZBP-ZBKB-NEXT: bltz a3, .LBB15_2
323 ; RV32ZBB-ZBP-ZBKB-NEXT: # %bb.1:
324 ; RV32ZBB-ZBP-ZBKB-NEXT: rol a1, a2, a3
325 ; RV32ZBB-ZBP-ZBKB-NEXT: li a0, -1
326 ; RV32ZBB-ZBP-ZBKB-NEXT: ret
327 ; RV32ZBB-ZBP-ZBKB-NEXT: .LBB15_2:
328 ; RV32ZBB-ZBP-ZBKB-NEXT: rol a0, a2, a0
329 ; RV32ZBB-ZBP-ZBKB-NEXT: ret
335 define i8 @srli_i8(i8 %a) nounwind {
336 ; CHECK-LABEL: srli_i8:
338 ; CHECK-NEXT: slli a0, a0, 24
339 ; CHECK-NEXT: srli a0, a0, 30
345 ; We could use sext.b+srai, but slli+srai offers more opportunities for
346 ; comppressed instructions.
347 define i8 @srai_i8(i8 %a) nounwind {
348 ; CHECK-LABEL: srai_i8:
350 ; CHECK-NEXT: slli a0, a0, 24
351 ; CHECK-NEXT: srai a0, a0, 29
357 ; We could use zext.h+srli, but slli+srli offers more opportunities for
358 ; comppressed instructions.
359 define i16 @srli_i16(i16 %a) nounwind {
360 ; CHECK-LABEL: srli_i16:
362 ; CHECK-NEXT: slli a0, a0, 16
363 ; CHECK-NEXT: srli a0, a0, 22
369 ; We could use sext.h+srai, but slli+srai offers more opportunities for
370 ; comppressed instructions.
371 define i16 @srai_i16(i16 %a) nounwind {
372 ; CHECK-LABEL: srai_i16:
374 ; CHECK-NEXT: slli a0, a0, 16
375 ; CHECK-NEXT: srai a0, a0, 25
381 define i1 @andn_seqz_i32(i32 %a, i32 %b) nounwind {
382 ; RV32I-LABEL: andn_seqz_i32:
384 ; RV32I-NEXT: and a0, a0, a1
385 ; RV32I-NEXT: xor a0, a0, a1
386 ; RV32I-NEXT: seqz a0, a0
389 ; RV32ZBB-ZBP-ZBKB-LABEL: andn_seqz_i32:
390 ; RV32ZBB-ZBP-ZBKB: # %bb.0:
391 ; RV32ZBB-ZBP-ZBKB-NEXT: andn a0, a1, a0
392 ; RV32ZBB-ZBP-ZBKB-NEXT: seqz a0, a0
393 ; RV32ZBB-ZBP-ZBKB-NEXT: ret
394 %and = and i32 %a, %b
395 %cmpeq = icmp eq i32 %and, %b
399 define i1 @andn_seqz_i64(i64 %a, i64 %b) nounwind {
400 ; RV32I-LABEL: andn_seqz_i64:
402 ; RV32I-NEXT: not a0, a0
403 ; RV32I-NEXT: not a1, a1
404 ; RV32I-NEXT: and a1, a1, a3
405 ; RV32I-NEXT: and a0, a0, a2
406 ; RV32I-NEXT: or a0, a0, a1
407 ; RV32I-NEXT: seqz a0, a0
410 ; RV32ZBB-ZBP-ZBKB-LABEL: andn_seqz_i64:
411 ; RV32ZBB-ZBP-ZBKB: # %bb.0:
412 ; RV32ZBB-ZBP-ZBKB-NEXT: andn a1, a3, a1
413 ; RV32ZBB-ZBP-ZBKB-NEXT: andn a0, a2, a0
414 ; RV32ZBB-ZBP-ZBKB-NEXT: or a0, a0, a1
415 ; RV32ZBB-ZBP-ZBKB-NEXT: seqz a0, a0
416 ; RV32ZBB-ZBP-ZBKB-NEXT: ret
417 %and = and i64 %a, %b
418 %cmpeq = icmp eq i64 %and, %b
422 define i1 @andn_snez_i32(i32 %a, i32 %b) nounwind {
423 ; RV32I-LABEL: andn_snez_i32:
425 ; RV32I-NEXT: and a0, a0, a1
426 ; RV32I-NEXT: xor a0, a0, a1
427 ; RV32I-NEXT: snez a0, a0
430 ; RV32ZBB-ZBP-ZBKB-LABEL: andn_snez_i32:
431 ; RV32ZBB-ZBP-ZBKB: # %bb.0:
432 ; RV32ZBB-ZBP-ZBKB-NEXT: andn a0, a1, a0
433 ; RV32ZBB-ZBP-ZBKB-NEXT: snez a0, a0
434 ; RV32ZBB-ZBP-ZBKB-NEXT: ret
435 %and = and i32 %a, %b
436 %cmpeq = icmp ne i32 %and, %b
440 define i1 @andn_snez_i64(i64 %a, i64 %b) nounwind {
441 ; RV32I-LABEL: andn_snez_i64:
443 ; RV32I-NEXT: not a0, a0
444 ; RV32I-NEXT: not a1, a1
445 ; RV32I-NEXT: and a1, a1, a3
446 ; RV32I-NEXT: and a0, a0, a2
447 ; RV32I-NEXT: or a0, a0, a1
448 ; RV32I-NEXT: snez a0, a0
451 ; RV32ZBB-ZBP-ZBKB-LABEL: andn_snez_i64:
452 ; RV32ZBB-ZBP-ZBKB: # %bb.0:
453 ; RV32ZBB-ZBP-ZBKB-NEXT: andn a1, a3, a1
454 ; RV32ZBB-ZBP-ZBKB-NEXT: andn a0, a2, a0
455 ; RV32ZBB-ZBP-ZBKB-NEXT: or a0, a0, a1
456 ; RV32ZBB-ZBP-ZBKB-NEXT: snez a0, a0
457 ; RV32ZBB-ZBP-ZBKB-NEXT: ret
458 %and = and i64 %a, %b
459 %cmpeq = icmp ne i64 %and, %b