[RISCV] Match vcompress during shuffle lowering (#117748)
[llvm-project.git] / llvm / test / CodeGen / RISCV / rv32zbb-zbkb.ll
blobb6344f88cddaa59c355b56e768857037b7c2e260
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-ZBKB
6 ; RUN: llc -mtriple=riscv32 -mattr=+zbkb -verify-machineinstrs < %s \
7 ; RUN:   | FileCheck %s -check-prefixes=CHECK,RV32ZBB-ZBKB
9 define i32 @andn_i32(i32 %a, i32 %b) nounwind {
10 ; RV32I-LABEL: andn_i32:
11 ; RV32I:       # %bb.0:
12 ; RV32I-NEXT:    not a1, a1
13 ; RV32I-NEXT:    and a0, a1, a0
14 ; RV32I-NEXT:    ret
16 ; RV32ZBB-ZBKB-LABEL: andn_i32:
17 ; RV32ZBB-ZBKB:       # %bb.0:
18 ; RV32ZBB-ZBKB-NEXT:    andn a0, a0, a1
19 ; RV32ZBB-ZBKB-NEXT:    ret
20   %neg = xor i32 %b, -1
21   %and = and i32 %neg, %a
22   ret i32 %and
25 define i64 @andn_i64(i64 %a, i64 %b) nounwind {
26 ; RV32I-LABEL: andn_i64:
27 ; RV32I:       # %bb.0:
28 ; RV32I-NEXT:    not a3, a3
29 ; RV32I-NEXT:    not a2, a2
30 ; RV32I-NEXT:    and a0, a2, a0
31 ; RV32I-NEXT:    and a1, a3, a1
32 ; RV32I-NEXT:    ret
34 ; RV32ZBB-ZBKB-LABEL: andn_i64:
35 ; RV32ZBB-ZBKB:       # %bb.0:
36 ; RV32ZBB-ZBKB-NEXT:    andn a0, a0, a2
37 ; RV32ZBB-ZBKB-NEXT:    andn a1, a1, a3
38 ; RV32ZBB-ZBKB-NEXT:    ret
39   %neg = xor i64 %b, -1
40   %and = and i64 %neg, %a
41   ret i64 %and
44 define i32 @orn_i32(i32 %a, i32 %b) nounwind {
45 ; RV32I-LABEL: orn_i32:
46 ; RV32I:       # %bb.0:
47 ; RV32I-NEXT:    not a1, a1
48 ; RV32I-NEXT:    or a0, a1, a0
49 ; RV32I-NEXT:    ret
51 ; RV32ZBB-ZBKB-LABEL: orn_i32:
52 ; RV32ZBB-ZBKB:       # %bb.0:
53 ; RV32ZBB-ZBKB-NEXT:    orn a0, a0, a1
54 ; RV32ZBB-ZBKB-NEXT:    ret
55   %neg = xor i32 %b, -1
56   %or = or i32 %neg, %a
57   ret i32 %or
60 define i64 @orn_i64(i64 %a, i64 %b) nounwind {
61 ; RV32I-LABEL: orn_i64:
62 ; RV32I:       # %bb.0:
63 ; RV32I-NEXT:    not a3, a3
64 ; RV32I-NEXT:    not a2, a2
65 ; RV32I-NEXT:    or a0, a2, a0
66 ; RV32I-NEXT:    or a1, a3, a1
67 ; RV32I-NEXT:    ret
69 ; RV32ZBB-ZBKB-LABEL: orn_i64:
70 ; RV32ZBB-ZBKB:       # %bb.0:
71 ; RV32ZBB-ZBKB-NEXT:    orn a0, a0, a2
72 ; RV32ZBB-ZBKB-NEXT:    orn a1, a1, a3
73 ; RV32ZBB-ZBKB-NEXT:    ret
74   %neg = xor i64 %b, -1
75   %or = or i64 %neg, %a
76   ret i64 %or
79 define i32 @xnor_i32(i32 %a, i32 %b) nounwind {
80 ; RV32I-LABEL: xnor_i32:
81 ; RV32I:       # %bb.0:
82 ; RV32I-NEXT:    xor a0, a0, a1
83 ; RV32I-NEXT:    not a0, a0
84 ; RV32I-NEXT:    ret
86 ; RV32ZBB-ZBKB-LABEL: xnor_i32:
87 ; RV32ZBB-ZBKB:       # %bb.0:
88 ; RV32ZBB-ZBKB-NEXT:    xnor a0, a0, a1
89 ; RV32ZBB-ZBKB-NEXT:    ret
90   %neg = xor i32 %a, -1
91   %xor = xor i32 %neg, %b
92   ret i32 %xor
95 define i64 @xnor_i64(i64 %a, i64 %b) nounwind {
96 ; RV32I-LABEL: xnor_i64:
97 ; RV32I:       # %bb.0:
98 ; RV32I-NEXT:    xor a1, a1, a3
99 ; RV32I-NEXT:    xor a0, a0, a2
100 ; RV32I-NEXT:    not a0, a0
101 ; RV32I-NEXT:    not a1, a1
102 ; RV32I-NEXT:    ret
104 ; RV32ZBB-ZBKB-LABEL: xnor_i64:
105 ; RV32ZBB-ZBKB:       # %bb.0:
106 ; RV32ZBB-ZBKB-NEXT:    xnor a0, a0, a2
107 ; RV32ZBB-ZBKB-NEXT:    xnor a1, a1, a3
108 ; RV32ZBB-ZBKB-NEXT:    ret
109   %neg = xor i64 %a, -1
110   %xor = xor i64 %neg, %b
111   ret i64 %xor
114 declare i32 @llvm.fshl.i32(i32, i32, i32)
116 define i32 @rol_i32(i32 %a, i32 %b) nounwind {
117 ; RV32I-LABEL: rol_i32:
118 ; RV32I:       # %bb.0:
119 ; RV32I-NEXT:    sll a2, a0, a1
120 ; RV32I-NEXT:    neg a1, a1
121 ; RV32I-NEXT:    srl a0, a0, a1
122 ; RV32I-NEXT:    or a0, a2, a0
123 ; RV32I-NEXT:    ret
125 ; RV32ZBB-ZBKB-LABEL: rol_i32:
126 ; RV32ZBB-ZBKB:       # %bb.0:
127 ; RV32ZBB-ZBKB-NEXT:    rol a0, a0, a1
128 ; RV32ZBB-ZBKB-NEXT:    ret
129   %or = tail call i32 @llvm.fshl.i32(i32 %a, i32 %a, i32 %b)
130   ret i32 %or
133 ; This test is presented here in case future expansions of the Bitmanip
134 ; extensions introduce instructions suitable for this pattern.
136 declare i64 @llvm.fshl.i64(i64, i64, i64)
138 define i64 @rol_i64(i64 %a, i64 %b) nounwind {
139 ; CHECK-LABEL: rol_i64:
140 ; CHECK:       # %bb.0:
141 ; CHECK-NEXT:    slli a5, a2, 26
142 ; CHECK-NEXT:    srli a5, a5, 31
143 ; CHECK-NEXT:    mv a3, a1
144 ; CHECK-NEXT:    bnez a5, .LBB7_2
145 ; CHECK-NEXT:  # %bb.1:
146 ; CHECK-NEXT:    mv a3, a0
147 ; CHECK-NEXT:  .LBB7_2:
148 ; CHECK-NEXT:    sll a4, a3, a2
149 ; CHECK-NEXT:    bnez a5, .LBB7_4
150 ; CHECK-NEXT:  # %bb.3:
151 ; CHECK-NEXT:    mv a0, a1
152 ; CHECK-NEXT:  .LBB7_4:
153 ; CHECK-NEXT:    srli a1, a0, 1
154 ; CHECK-NEXT:    not a5, a2
155 ; CHECK-NEXT:    sll a2, a0, a2
156 ; CHECK-NEXT:    srli a3, a3, 1
157 ; CHECK-NEXT:    srl a0, a1, a5
158 ; CHECK-NEXT:    srl a1, a3, a5
159 ; CHECK-NEXT:    or a0, a4, a0
160 ; CHECK-NEXT:    or a1, a2, a1
161 ; CHECK-NEXT:    ret
162   %or = tail call i64 @llvm.fshl.i64(i64 %a, i64 %a, i64 %b)
163   ret i64 %or
166 declare i32 @llvm.fshr.i32(i32, i32, i32)
168 define i32 @ror_i32(i32 %a, i32 %b) nounwind {
169 ; RV32I-LABEL: ror_i32:
170 ; RV32I:       # %bb.0:
171 ; RV32I-NEXT:    srl a2, a0, a1
172 ; RV32I-NEXT:    neg a1, a1
173 ; RV32I-NEXT:    sll a0, a0, a1
174 ; RV32I-NEXT:    or a0, a2, a0
175 ; RV32I-NEXT:    ret
177 ; RV32ZBB-ZBKB-LABEL: ror_i32:
178 ; RV32ZBB-ZBKB:       # %bb.0:
179 ; RV32ZBB-ZBKB-NEXT:    ror a0, a0, a1
180 ; RV32ZBB-ZBKB-NEXT:    ret
181   %or = tail call i32 @llvm.fshr.i32(i32 %a, i32 %a, i32 %b)
182   ret i32 %or
185 ; This test is presented here in case future expansions of the Bitmanip
186 ; extensions introduce instructions suitable for this pattern.
188 declare i64 @llvm.fshr.i64(i64, i64, i64)
190 define i64 @ror_i64(i64 %a, i64 %b) nounwind {
191 ; CHECK-LABEL: ror_i64:
192 ; CHECK:       # %bb.0:
193 ; CHECK-NEXT:    andi a5, a2, 32
194 ; CHECK-NEXT:    mv a3, a0
195 ; CHECK-NEXT:    beqz a5, .LBB9_2
196 ; CHECK-NEXT:  # %bb.1:
197 ; CHECK-NEXT:    mv a3, a1
198 ; CHECK-NEXT:  .LBB9_2:
199 ; CHECK-NEXT:    srl a4, a3, a2
200 ; CHECK-NEXT:    beqz a5, .LBB9_4
201 ; CHECK-NEXT:  # %bb.3:
202 ; CHECK-NEXT:    mv a1, a0
203 ; CHECK-NEXT:  .LBB9_4:
204 ; CHECK-NEXT:    slli a0, a1, 1
205 ; CHECK-NEXT:    not a5, a2
206 ; CHECK-NEXT:    srl a1, a1, a2
207 ; CHECK-NEXT:    slli a3, a3, 1
208 ; CHECK-NEXT:    sll a0, a0, a5
209 ; CHECK-NEXT:    sll a2, a3, a5
210 ; CHECK-NEXT:    or a0, a0, a4
211 ; CHECK-NEXT:    or a1, a2, a1
212 ; CHECK-NEXT:    ret
213   %or = tail call i64 @llvm.fshr.i64(i64 %a, i64 %a, i64 %b)
214   ret i64 %or
217 define i32 @rori_i32_fshl(i32 %a) nounwind {
218 ; RV32I-LABEL: rori_i32_fshl:
219 ; RV32I:       # %bb.0:
220 ; RV32I-NEXT:    srli a1, a0, 1
221 ; RV32I-NEXT:    slli a0, a0, 31
222 ; RV32I-NEXT:    or a0, a0, a1
223 ; RV32I-NEXT:    ret
225 ; RV32ZBB-ZBKB-LABEL: rori_i32_fshl:
226 ; RV32ZBB-ZBKB:       # %bb.0:
227 ; RV32ZBB-ZBKB-NEXT:    rori a0, a0, 1
228 ; RV32ZBB-ZBKB-NEXT:    ret
229   %1 = tail call i32 @llvm.fshl.i32(i32 %a, i32 %a, i32 31)
230   ret i32 %1
233 define i32 @rori_i32_fshr(i32 %a) nounwind {
234 ; RV32I-LABEL: rori_i32_fshr:
235 ; RV32I:       # %bb.0:
236 ; RV32I-NEXT:    slli a1, a0, 1
237 ; RV32I-NEXT:    srli a0, a0, 31
238 ; RV32I-NEXT:    or a0, a0, a1
239 ; RV32I-NEXT:    ret
241 ; RV32ZBB-ZBKB-LABEL: rori_i32_fshr:
242 ; RV32ZBB-ZBKB:       # %bb.0:
243 ; RV32ZBB-ZBKB-NEXT:    rori a0, a0, 31
244 ; RV32ZBB-ZBKB-NEXT:    ret
245   %1 = tail call i32 @llvm.fshr.i32(i32 %a, i32 %a, i32 31)
246   ret i32 %1
249 define i64 @rori_i64(i64 %a) nounwind {
250 ; CHECK-LABEL: rori_i64:
251 ; CHECK:       # %bb.0:
252 ; CHECK-NEXT:    srli a2, a0, 1
253 ; CHECK-NEXT:    slli a3, a1, 31
254 ; CHECK-NEXT:    srli a1, a1, 1
255 ; CHECK-NEXT:    slli a4, a0, 31
256 ; CHECK-NEXT:    or a0, a3, a2
257 ; CHECK-NEXT:    or a1, a4, a1
258 ; CHECK-NEXT:    ret
259   %1 = tail call i64 @llvm.fshl.i64(i64 %a, i64 %a, i64 63)
260   ret i64 %1
263 define i64 @rori_i64_fshr(i64 %a) nounwind {
264 ; CHECK-LABEL: rori_i64_fshr:
265 ; CHECK:       # %bb.0:
266 ; CHECK-NEXT:    srli a2, a1, 31
267 ; CHECK-NEXT:    slli a3, a0, 1
268 ; CHECK-NEXT:    srli a4, a0, 31
269 ; CHECK-NEXT:    slli a1, a1, 1
270 ; CHECK-NEXT:    or a0, a3, a2
271 ; CHECK-NEXT:    or a1, a1, a4
272 ; CHECK-NEXT:    ret
273   %1 = tail call i64 @llvm.fshr.i64(i64 %a, i64 %a, i64 63)
274   ret i64 %1
277 define i32 @not_shl_one_i32(i32 %x) {
278 ; RV32I-LABEL: not_shl_one_i32:
279 ; RV32I:       # %bb.0:
280 ; RV32I-NEXT:    li a1, 1
281 ; RV32I-NEXT:    sll a0, a1, a0
282 ; RV32I-NEXT:    not a0, a0
283 ; RV32I-NEXT:    ret
285 ; RV32ZBB-ZBKB-LABEL: not_shl_one_i32:
286 ; RV32ZBB-ZBKB:       # %bb.0:
287 ; RV32ZBB-ZBKB-NEXT:    li a1, -2
288 ; RV32ZBB-ZBKB-NEXT:    rol a0, a1, a0
289 ; RV32ZBB-ZBKB-NEXT:    ret
290   %1 = shl i32 1, %x
291   %2 = xor i32 %1, -1
292   ret i32 %2
295 define i64 @not_shl_one_i64(i64 %x) {
296 ; CHECK-LABEL: not_shl_one_i64:
297 ; CHECK:       # %bb.0:
298 ; CHECK-NEXT:    addi a1, a0, -32
299 ; CHECK-NEXT:    li a2, 1
300 ; CHECK-NEXT:    slti a1, a1, 0
301 ; CHECK-NEXT:    sll a0, a2, a0
302 ; CHECK-NEXT:    neg a2, a1
303 ; CHECK-NEXT:    addi a1, a1, -1
304 ; CHECK-NEXT:    and a2, a2, a0
305 ; CHECK-NEXT:    and a1, a1, a0
306 ; CHECK-NEXT:    not a0, a2
307 ; CHECK-NEXT:    not a1, a1
308 ; CHECK-NEXT:    ret
309   %1 = shl i64 1, %x
310   %2 = xor i64 %1, -1
311   ret i64 %2
314 define i8 @srli_i8(i8 %a) nounwind {
315 ; CHECK-LABEL: srli_i8:
316 ; CHECK:       # %bb.0:
317 ; CHECK-NEXT:    slli a0, a0, 24
318 ; CHECK-NEXT:    srli a0, a0, 30
319 ; CHECK-NEXT:    ret
320   %1 = lshr i8 %a, 6
321   ret i8 %1
324 ; We could use sext.b+srai, but slli+srai offers more opportunities for
325 ; comppressed instructions.
326 define i8 @srai_i8(i8 %a) nounwind {
327 ; CHECK-LABEL: srai_i8:
328 ; CHECK:       # %bb.0:
329 ; CHECK-NEXT:    slli a0, a0, 24
330 ; CHECK-NEXT:    srai a0, a0, 29
331 ; CHECK-NEXT:    ret
332   %1 = ashr i8 %a, 5
333   ret i8 %1
336 ; We could use zext.h+srli, but slli+srli offers more opportunities for
337 ; comppressed instructions.
338 define i16 @srli_i16(i16 %a) nounwind {
339 ; CHECK-LABEL: srli_i16:
340 ; CHECK:       # %bb.0:
341 ; CHECK-NEXT:    slli a0, a0, 16
342 ; CHECK-NEXT:    srli a0, a0, 22
343 ; CHECK-NEXT:    ret
344   %1 = lshr i16 %a, 6
345   ret i16 %1
348 ; We could use sext.h+srai, but slli+srai offers more opportunities for
349 ; comppressed instructions.
350 define i16 @srai_i16(i16 %a) nounwind {
351 ; CHECK-LABEL: srai_i16:
352 ; CHECK:       # %bb.0:
353 ; CHECK-NEXT:    slli a0, a0, 16
354 ; CHECK-NEXT:    srai a0, a0, 25
355 ; CHECK-NEXT:    ret
356   %1 = ashr i16 %a, 9
357   ret i16 %1
360 define i1 @andn_seqz_i32(i32 %a, i32 %b) nounwind {
361 ; RV32I-LABEL: andn_seqz_i32:
362 ; RV32I:       # %bb.0:
363 ; RV32I-NEXT:    and a0, a0, a1
364 ; RV32I-NEXT:    xor a0, a0, a1
365 ; RV32I-NEXT:    seqz a0, a0
366 ; RV32I-NEXT:    ret
368 ; RV32ZBB-ZBKB-LABEL: andn_seqz_i32:
369 ; RV32ZBB-ZBKB:       # %bb.0:
370 ; RV32ZBB-ZBKB-NEXT:    andn a0, a1, a0
371 ; RV32ZBB-ZBKB-NEXT:    seqz a0, a0
372 ; RV32ZBB-ZBKB-NEXT:    ret
373   %and = and i32 %a, %b
374   %cmpeq = icmp eq i32 %and, %b
375   ret i1 %cmpeq
378 define i1 @andn_seqz_i64(i64 %a, i64 %b) nounwind {
379 ; RV32I-LABEL: andn_seqz_i64:
380 ; RV32I:       # %bb.0:
381 ; RV32I-NEXT:    not a0, a0
382 ; RV32I-NEXT:    not a1, a1
383 ; RV32I-NEXT:    and a1, a1, a3
384 ; RV32I-NEXT:    and a0, a0, a2
385 ; RV32I-NEXT:    or a0, a0, a1
386 ; RV32I-NEXT:    seqz a0, a0
387 ; RV32I-NEXT:    ret
389 ; RV32ZBB-ZBKB-LABEL: andn_seqz_i64:
390 ; RV32ZBB-ZBKB:       # %bb.0:
391 ; RV32ZBB-ZBKB-NEXT:    andn a1, a3, a1
392 ; RV32ZBB-ZBKB-NEXT:    andn a0, a2, a0
393 ; RV32ZBB-ZBKB-NEXT:    or a0, a0, a1
394 ; RV32ZBB-ZBKB-NEXT:    seqz a0, a0
395 ; RV32ZBB-ZBKB-NEXT:    ret
396   %and = and i64 %a, %b
397   %cmpeq = icmp eq i64 %and, %b
398   ret i1 %cmpeq
401 define i1 @andn_snez_i32(i32 %a, i32 %b) nounwind {
402 ; RV32I-LABEL: andn_snez_i32:
403 ; RV32I:       # %bb.0:
404 ; RV32I-NEXT:    and a0, a0, a1
405 ; RV32I-NEXT:    xor a0, a0, a1
406 ; RV32I-NEXT:    snez a0, a0
407 ; RV32I-NEXT:    ret
409 ; RV32ZBB-ZBKB-LABEL: andn_snez_i32:
410 ; RV32ZBB-ZBKB:       # %bb.0:
411 ; RV32ZBB-ZBKB-NEXT:    andn a0, a1, a0
412 ; RV32ZBB-ZBKB-NEXT:    snez a0, a0
413 ; RV32ZBB-ZBKB-NEXT:    ret
414   %and = and i32 %a, %b
415   %cmpeq = icmp ne i32 %and, %b
416   ret i1 %cmpeq
419 define i1 @andn_snez_i64(i64 %a, i64 %b) nounwind {
420 ; RV32I-LABEL: andn_snez_i64:
421 ; RV32I:       # %bb.0:
422 ; RV32I-NEXT:    not a0, a0
423 ; RV32I-NEXT:    not a1, a1
424 ; RV32I-NEXT:    and a1, a1, a3
425 ; RV32I-NEXT:    and a0, a0, a2
426 ; RV32I-NEXT:    or a0, a0, a1
427 ; RV32I-NEXT:    snez a0, a0
428 ; RV32I-NEXT:    ret
430 ; RV32ZBB-ZBKB-LABEL: andn_snez_i64:
431 ; RV32ZBB-ZBKB:       # %bb.0:
432 ; RV32ZBB-ZBKB-NEXT:    andn a1, a3, a1
433 ; RV32ZBB-ZBKB-NEXT:    andn a0, a2, a0
434 ; RV32ZBB-ZBKB-NEXT:    or a0, a0, a1
435 ; RV32ZBB-ZBKB-NEXT:    snez a0, a0
436 ; RV32ZBB-ZBKB-NEXT:    ret
437   %and = and i64 %a, %b
438   %cmpeq = icmp ne i64 %and, %b
439   ret i1 %cmpeq