1 ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
2 ; RUN: llc -mtriple=riscv32 -global-isel -verify-machineinstrs < %s \
3 ; RUN: | FileCheck %s -check-prefixes=CHECK,RV32I
4 ; RUN: llc -mtriple=riscv32 -global-isel -mattr=+zbb -verify-machineinstrs < %s \
5 ; RUN: | FileCheck %s -check-prefixes=CHECK,RV32ZBB-ZBKB,RV32ZBB
6 ; RUN: llc -mtriple=riscv32 -global-isel -mattr=+zbkb -verify-machineinstrs < %s \
7 ; RUN: | FileCheck %s -check-prefixes=CHECK,RV32ZBB-ZBKB,RV32ZBKB
9 define i32 @andn_i32(i32 %a, i32 %b) nounwind {
10 ; RV32I-LABEL: andn_i32:
12 ; RV32I-NEXT: not a1, a1
13 ; RV32I-NEXT: and a0, a1, a0
16 ; RV32ZBB-ZBKB-LABEL: andn_i32:
17 ; RV32ZBB-ZBKB: # %bb.0:
18 ; RV32ZBB-ZBKB-NEXT: andn a0, a0, a1
19 ; RV32ZBB-ZBKB-NEXT: ret
21 %and = and i32 %neg, %a
25 define i64 @andn_i64(i64 %a, i64 %b) nounwind {
26 ; RV32I-LABEL: andn_i64:
28 ; RV32I-NEXT: not a2, a2
29 ; RV32I-NEXT: not a3, a3
30 ; RV32I-NEXT: and a0, a2, a0
31 ; RV32I-NEXT: and a1, a3, a1
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
40 %and = and i64 %neg, %a
44 define i32 @orn_i32(i32 %a, i32 %b) nounwind {
45 ; RV32I-LABEL: orn_i32:
47 ; RV32I-NEXT: not a1, a1
48 ; RV32I-NEXT: or a0, a1, a0
51 ; RV32ZBB-ZBKB-LABEL: orn_i32:
52 ; RV32ZBB-ZBKB: # %bb.0:
53 ; RV32ZBB-ZBKB-NEXT: orn a0, a0, a1
54 ; RV32ZBB-ZBKB-NEXT: ret
60 define i64 @orn_i64(i64 %a, i64 %b) nounwind {
61 ; RV32I-LABEL: orn_i64:
63 ; RV32I-NEXT: not a2, a2
64 ; RV32I-NEXT: not a3, a3
65 ; RV32I-NEXT: or a0, a2, a0
66 ; RV32I-NEXT: or a1, a3, a1
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
79 define i32 @xnor_i32(i32 %a, i32 %b) nounwind {
80 ; RV32I-LABEL: xnor_i32:
82 ; RV32I-NEXT: not a0, a0
83 ; RV32I-NEXT: xor a0, a0, a1
86 ; RV32ZBB-ZBKB-LABEL: xnor_i32:
87 ; RV32ZBB-ZBKB: # %bb.0:
88 ; RV32ZBB-ZBKB-NEXT: xnor a0, a0, a1
89 ; RV32ZBB-ZBKB-NEXT: ret
91 %xor = xor i32 %neg, %b
95 define i64 @xnor_i64(i64 %a, i64 %b) nounwind {
96 ; RV32I-LABEL: xnor_i64:
98 ; RV32I-NEXT: not a0, a0
99 ; RV32I-NEXT: not a1, a1
100 ; RV32I-NEXT: xor a0, a0, a2
101 ; RV32I-NEXT: xor a1, a1, a3
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
114 declare i32 @llvm.fshl.i32(i32, i32, i32)
116 define i32 @rol_i32(i32 %a, i32 %b) nounwind {
117 ; RV32I-LABEL: rol_i32:
119 ; RV32I-NEXT: neg a2, a1
120 ; RV32I-NEXT: sll a1, a0, a1
121 ; RV32I-NEXT: srl a0, a0, a2
122 ; RV32I-NEXT: or a0, a1, a0
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)
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:
141 ; CHECK-NEXT: andi a6, a2, 63
142 ; CHECK-NEXT: li a4, 32
143 ; CHECK-NEXT: bltu a6, a4, .LBB7_2
144 ; CHECK-NEXT: # %bb.1:
145 ; CHECK-NEXT: li a3, 0
146 ; CHECK-NEXT: sll a7, a0, a6
147 ; CHECK-NEXT: j .LBB7_3
148 ; CHECK-NEXT: .LBB7_2:
149 ; CHECK-NEXT: sll a3, a0, a2
150 ; CHECK-NEXT: neg a5, a6
151 ; CHECK-NEXT: srl a5, a0, a5
152 ; CHECK-NEXT: sll a7, a1, a2
153 ; CHECK-NEXT: or a7, a5, a7
154 ; CHECK-NEXT: .LBB7_3:
155 ; CHECK-NEXT: neg a5, a2
156 ; CHECK-NEXT: mv a2, a1
157 ; CHECK-NEXT: beqz a6, .LBB7_5
158 ; CHECK-NEXT: # %bb.4:
159 ; CHECK-NEXT: mv a2, a7
160 ; CHECK-NEXT: .LBB7_5:
161 ; CHECK-NEXT: andi a6, a5, 63
162 ; CHECK-NEXT: bltu a6, a4, .LBB7_7
163 ; CHECK-NEXT: # %bb.6:
164 ; CHECK-NEXT: srl a7, a1, a6
165 ; CHECK-NEXT: bnez a6, .LBB7_8
166 ; CHECK-NEXT: j .LBB7_9
167 ; CHECK-NEXT: .LBB7_7:
168 ; CHECK-NEXT: srl a7, a0, a5
169 ; CHECK-NEXT: neg t0, a6
170 ; CHECK-NEXT: sll t0, a1, t0
171 ; CHECK-NEXT: or a7, a7, t0
172 ; CHECK-NEXT: beqz a6, .LBB7_9
173 ; CHECK-NEXT: .LBB7_8:
174 ; CHECK-NEXT: mv a0, a7
175 ; CHECK-NEXT: .LBB7_9:
176 ; CHECK-NEXT: bltu a6, a4, .LBB7_11
177 ; CHECK-NEXT: # %bb.10:
178 ; CHECK-NEXT: li a1, 0
179 ; CHECK-NEXT: j .LBB7_12
180 ; CHECK-NEXT: .LBB7_11:
181 ; CHECK-NEXT: srl a1, a1, a5
182 ; CHECK-NEXT: .LBB7_12:
183 ; CHECK-NEXT: or a0, a3, a0
184 ; CHECK-NEXT: or a1, a2, a1
186 %or = tail call i64 @llvm.fshl.i64(i64 %a, i64 %a, i64 %b)
190 declare i32 @llvm.fshr.i32(i32, i32, i32)
192 define i32 @ror_i32(i32 %a, i32 %b) nounwind {
193 ; RV32I-LABEL: ror_i32:
195 ; RV32I-NEXT: neg a2, a1
196 ; RV32I-NEXT: srl a1, a0, a1
197 ; RV32I-NEXT: sll a0, a0, a2
198 ; RV32I-NEXT: or a0, a1, a0
201 ; RV32ZBB-ZBKB-LABEL: ror_i32:
202 ; RV32ZBB-ZBKB: # %bb.0:
203 ; RV32ZBB-ZBKB-NEXT: ror a0, a0, a1
204 ; RV32ZBB-ZBKB-NEXT: ret
205 %or = tail call i32 @llvm.fshr.i32(i32 %a, i32 %a, i32 %b)
209 ; This test is presented here in case future expansions of the Bitmanip
210 ; extensions introduce instructions suitable for this pattern.
212 declare i64 @llvm.fshr.i64(i64, i64, i64)
214 define i64 @ror_i64(i64 %a, i64 %b) nounwind {
215 ; CHECK-LABEL: ror_i64:
217 ; CHECK-NEXT: andi a5, a2, 63
218 ; CHECK-NEXT: li a4, 32
219 ; CHECK-NEXT: bltu a5, a4, .LBB9_2
220 ; CHECK-NEXT: # %bb.1:
221 ; CHECK-NEXT: srl a6, a1, a5
222 ; CHECK-NEXT: mv a3, a0
223 ; CHECK-NEXT: bnez a5, .LBB9_3
224 ; CHECK-NEXT: j .LBB9_4
225 ; CHECK-NEXT: .LBB9_2:
226 ; CHECK-NEXT: srl a3, a0, a2
227 ; CHECK-NEXT: neg a6, a5
228 ; CHECK-NEXT: sll a6, a1, a6
229 ; CHECK-NEXT: or a6, a3, a6
230 ; CHECK-NEXT: mv a3, a0
231 ; CHECK-NEXT: beqz a5, .LBB9_4
232 ; CHECK-NEXT: .LBB9_3:
233 ; CHECK-NEXT: mv a3, a6
234 ; CHECK-NEXT: .LBB9_4:
235 ; CHECK-NEXT: neg a6, a2
236 ; CHECK-NEXT: bltu a5, a4, .LBB9_7
237 ; CHECK-NEXT: # %bb.5:
238 ; CHECK-NEXT: li a2, 0
239 ; CHECK-NEXT: andi a5, a6, 63
240 ; CHECK-NEXT: bgeu a5, a4, .LBB9_8
241 ; CHECK-NEXT: .LBB9_6:
242 ; CHECK-NEXT: sll a4, a0, a6
243 ; CHECK-NEXT: neg a7, a5
244 ; CHECK-NEXT: srl a0, a0, a7
245 ; CHECK-NEXT: sll a6, a1, a6
246 ; CHECK-NEXT: or a0, a0, a6
247 ; CHECK-NEXT: bnez a5, .LBB9_9
248 ; CHECK-NEXT: j .LBB9_10
249 ; CHECK-NEXT: .LBB9_7:
250 ; CHECK-NEXT: srl a2, a1, a2
251 ; CHECK-NEXT: andi a5, a6, 63
252 ; CHECK-NEXT: bltu a5, a4, .LBB9_6
253 ; CHECK-NEXT: .LBB9_8:
254 ; CHECK-NEXT: li a4, 0
255 ; CHECK-NEXT: sll a0, a0, a5
256 ; CHECK-NEXT: beqz a5, .LBB9_10
257 ; CHECK-NEXT: .LBB9_9:
258 ; CHECK-NEXT: mv a1, a0
259 ; CHECK-NEXT: .LBB9_10:
260 ; CHECK-NEXT: or a0, a3, a4
261 ; CHECK-NEXT: or a1, a2, a1
263 %or = tail call i64 @llvm.fshr.i64(i64 %a, i64 %a, i64 %b)
267 define i32 @rori_i32_fshl(i32 %a) nounwind {
268 ; RV32I-LABEL: rori_i32_fshl:
270 ; RV32I-NEXT: slli a1, a0, 31
271 ; RV32I-NEXT: srli a0, a0, 1
272 ; RV32I-NEXT: or a0, a1, a0
275 ; RV32ZBB-ZBKB-LABEL: rori_i32_fshl:
276 ; RV32ZBB-ZBKB: # %bb.0:
277 ; RV32ZBB-ZBKB-NEXT: rori a0, a0, 1
278 ; RV32ZBB-ZBKB-NEXT: ret
279 %1 = tail call i32 @llvm.fshl.i32(i32 %a, i32 %a, i32 31)
283 define i32 @rori_i32_fshr(i32 %a) nounwind {
284 ; RV32I-LABEL: rori_i32_fshr:
286 ; RV32I-NEXT: srli a1, a0, 31
287 ; RV32I-NEXT: slli a0, a0, 1
288 ; RV32I-NEXT: or a0, a1, a0
291 ; RV32ZBB-ZBKB-LABEL: rori_i32_fshr:
292 ; RV32ZBB-ZBKB: # %bb.0:
293 ; RV32ZBB-ZBKB-NEXT: rori a0, a0, 31
294 ; RV32ZBB-ZBKB-NEXT: ret
295 %1 = tail call i32 @llvm.fshr.i32(i32 %a, i32 %a, i32 31)
299 define i64 @rori_i64(i64 %a) nounwind {
300 ; CHECK-LABEL: rori_i64:
302 ; CHECK-NEXT: slli a2, a0, 31
303 ; CHECK-NEXT: srli a0, a0, 1
304 ; CHECK-NEXT: slli a3, a1, 31
305 ; CHECK-NEXT: srli a1, a1, 1
306 ; CHECK-NEXT: or a0, a0, a3
307 ; CHECK-NEXT: or a1, a2, a1
309 %1 = tail call i64 @llvm.fshl.i64(i64 %a, i64 %a, i64 63)
313 define i64 @rori_i64_fshr(i64 %a) nounwind {
314 ; CHECK-LABEL: rori_i64_fshr:
316 ; CHECK-NEXT: srli a2, a1, 31
317 ; CHECK-NEXT: slli a3, a0, 1
318 ; CHECK-NEXT: slli a1, a1, 1
319 ; CHECK-NEXT: srli a0, a0, 31
320 ; CHECK-NEXT: or a1, a1, a0
321 ; CHECK-NEXT: or a0, a2, a3
323 %1 = tail call i64 @llvm.fshr.i64(i64 %a, i64 %a, i64 63)
327 define i8 @srli_i8(i8 %a) nounwind {
328 ; CHECK-LABEL: srli_i8:
330 ; CHECK-NEXT: andi a0, a0, 255
331 ; CHECK-NEXT: srli a0, a0, 6
337 ; FIXME: We should use slli+srai with Zbb for better compression.
338 define i8 @srai_i8(i8 %a) nounwind {
339 ; RV32I-LABEL: srai_i8:
341 ; RV32I-NEXT: slli a0, a0, 24
342 ; RV32I-NEXT: srai a0, a0, 29
345 ; RV32ZBB-LABEL: srai_i8:
347 ; RV32ZBB-NEXT: sext.b a0, a0
348 ; RV32ZBB-NEXT: srai a0, a0, 5
351 ; RV32ZBKB-LABEL: srai_i8:
353 ; RV32ZBKB-NEXT: slli a0, a0, 24
354 ; RV32ZBKB-NEXT: srai a0, a0, 29
360 ; FIXME: We should use slli+srli.
361 define i16 @srli_i16(i16 %a) nounwind {
362 ; RV32I-LABEL: srli_i16:
364 ; RV32I-NEXT: lui a1, 16
365 ; RV32I-NEXT: addi a1, a1, -1
366 ; RV32I-NEXT: and a0, a0, a1
367 ; RV32I-NEXT: srli a0, a0, 6
370 ; RV32ZBB-ZBKB-LABEL: srli_i16:
371 ; RV32ZBB-ZBKB: # %bb.0:
372 ; RV32ZBB-ZBKB-NEXT: zext.h a0, a0
373 ; RV32ZBB-ZBKB-NEXT: srli a0, a0, 6
374 ; RV32ZBB-ZBKB-NEXT: ret
379 ; FIXME: We should use slli+srai with Zbb/Zbkb for better compression.
380 define i16 @srai_i16(i16 %a) nounwind {
381 ; RV32I-LABEL: srai_i16:
383 ; RV32I-NEXT: slli a0, a0, 16
384 ; RV32I-NEXT: srai a0, a0, 25
387 ; RV32ZBB-LABEL: srai_i16:
389 ; RV32ZBB-NEXT: sext.h a0, a0
390 ; RV32ZBB-NEXT: srai a0, a0, 9
393 ; RV32ZBKB-LABEL: srai_i16:
395 ; RV32ZBKB-NEXT: slli a0, a0, 16
396 ; RV32ZBKB-NEXT: srai a0, a0, 25