xref: /llvm-project/llvm/test/CodeGen/RISCV/rv32zbb-zbkb.ll (revision 9122c5235ec85ce0c0ad337e862b006e7b349d84)
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
8
9define 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
15;
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
23}
24
25define 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
33;
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
42}
43
44define 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
50;
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
58}
59
60define 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
68;
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
77}
78
79define 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
85;
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
93}
94
95define 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
103;
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
112}
113
114declare i32 @llvm.fshl.i32(i32, i32, i32)
115
116define 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
124;
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
131}
132
133; This test is presented here in case future expansions of the Bitmanip
134; extensions introduce instructions suitable for this pattern.
135
136declare i64 @llvm.fshl.i64(i64, i64, i64)
137
138define 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
164}
165
166declare i32 @llvm.fshr.i32(i32, i32, i32)
167
168define 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
176;
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
183}
184
185; This test is presented here in case future expansions of the Bitmanip
186; extensions introduce instructions suitable for this pattern.
187
188declare i64 @llvm.fshr.i64(i64, i64, i64)
189
190define 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
215}
216
217define 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
224;
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
231}
232
233define 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
240;
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
247}
248
249define 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
261}
262
263define 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
275}
276
277define 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
284;
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
293}
294
295define 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
312}
313
314define 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
322}
323
324; We could use sext.b+srai, but slli+srai offers more opportunities for
325; comppressed instructions.
326define 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
334}
335
336; We could use zext.h+srli, but slli+srli offers more opportunities for
337; comppressed instructions.
338define 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
346}
347
348; We could use sext.h+srai, but slli+srai offers more opportunities for
349; comppressed instructions.
350define 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
358}
359
360define 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
367;
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
376}
377
378define 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
388;
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
399}
400
401define 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
408;
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
417}
418
419define 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
429;
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
440}
441