xref: /llvm-project/llvm/test/CodeGen/RISCV/selectcc-to-shiftand.ll (revision 15895daa6862ad15bfac18b03811d066d4550713)
1; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
2; RUN: llc < %s -mtriple=riscv32 \
3; RUN:   | FileCheck %s --check-prefixes=CHECK,RV32,RV32I
4; RUN: llc < %s -mtriple=riscv64 \
5; RUN:   | FileCheck %s --check-prefixes=CHECK,RV64,RV64I
6; RUN: llc < %s -mtriple=riscv32 -mattr=+zbb \
7; RUN:   | FileCheck %s --check-prefixes=CHECK,RV32,RV32ZBB
8; RUN: llc < %s -mtriple=riscv64 -mattr=+zbb \
9; RUN:   | FileCheck %s --check-prefixes=CHECK,RV64,RV64ZBB
10
11; Compare if negative and select of constants where one constant is zero.
12define i32 @neg_sel_constants(i32 signext %a) {
13; RV32-LABEL: neg_sel_constants:
14; RV32:       # %bb.0:
15; RV32-NEXT:    srai a0, a0, 31
16; RV32-NEXT:    andi a0, a0, 5
17; RV32-NEXT:    ret
18;
19; RV64-LABEL: neg_sel_constants:
20; RV64:       # %bb.0:
21; RV64-NEXT:    srai a0, a0, 63
22; RV64-NEXT:    andi a0, a0, 5
23; RV64-NEXT:    ret
24  %tmp.1 = icmp slt i32 %a, 0
25  %retval = select i1 %tmp.1, i32 5, i32 0
26  ret i32 %retval
27}
28
29; Compare if negative and select of constants where one constant is zero and the
30; other is a single bit.
31define i32 @neg_sel_special_constant(i32 signext %a) {
32; RV32-LABEL: neg_sel_special_constant:
33; RV32:       # %bb.0:
34; RV32-NEXT:    srli a0, a0, 31
35; RV32-NEXT:    slli a0, a0, 9
36; RV32-NEXT:    ret
37;
38; RV64-LABEL: neg_sel_special_constant:
39; RV64:       # %bb.0:
40; RV64-NEXT:    srliw a0, a0, 31
41; RV64-NEXT:    slli a0, a0, 9
42; RV64-NEXT:    ret
43  %tmp.1 = icmp slt i32 %a, 0
44  %retval = select i1 %tmp.1, i32 512, i32 0
45  ret i32 %retval
46}
47
48; Compare if negative and select variable or zero.
49define i32 @neg_sel_variable_and_zero(i32 signext %a, i32 signext %b) {
50; CHECK-LABEL: neg_sel_variable_and_zero:
51; CHECK:       # %bb.0:
52; CHECK-NEXT:    srai a0, a0, 31
53; CHECK-NEXT:    and a0, a0, a1
54; CHECK-NEXT:    ret
55  %tmp.1 = icmp slt i32 %a, 0
56  %retval = select i1 %tmp.1, i32 %b, i32 0
57  ret i32 %retval
58}
59
60; Compare if not positive and select the same variable as being compared:
61; smin(a, 0).
62define i32 @not_pos_sel_same_variable(i32 signext %a) {
63; CHECK-LABEL: not_pos_sel_same_variable:
64; CHECK:       # %bb.0:
65; CHECK-NEXT:    srai a1, a0, 31
66; CHECK-NEXT:    and a0, a1, a0
67; CHECK-NEXT:    ret
68  %tmp = icmp slt i32 %a, 1
69  %min = select i1 %tmp, i32 %a, i32 0
70  ret i32 %min
71}
72
73; Flipping the comparison condition can be handled by getting the bitwise not of
74; the sign mask.
75; TODO: We aren't doing a good job of this.
76
77; Compare if positive and select of constants where one constant is zero.
78define i32 @pos_sel_constants(i32 signext %a) {
79; CHECK-LABEL: pos_sel_constants:
80; CHECK:       # %bb.0:
81; CHECK-NEXT:    slti a0, a0, 0
82; CHECK-NEXT:    addi a0, a0, -1
83; CHECK-NEXT:    andi a0, a0, 5
84; CHECK-NEXT:    ret
85  %tmp.1 = icmp sgt i32 %a, -1
86  %retval = select i1 %tmp.1, i32 5, i32 0
87  ret i32 %retval
88}
89
90; Compare if positive and select of constants where one constant is zero and the
91; other is a single bit.
92; TODO: Why do RV32 and RV64 generate different code? RV64 uses more registers,
93; but the addi isn't part of the dependency chain of %a so may be faster.
94define i32 @pos_sel_special_constant(i32 signext %a) {
95; RV32-LABEL: pos_sel_special_constant:
96; RV32:       # %bb.0:
97; RV32-NEXT:    not a0, a0
98; RV32-NEXT:    srli a0, a0, 31
99; RV32-NEXT:    slli a0, a0, 9
100; RV32-NEXT:    ret
101;
102; RV64-LABEL: pos_sel_special_constant:
103; RV64:       # %bb.0:
104; RV64-NEXT:    slti a0, a0, 0
105; RV64-NEXT:    xori a0, a0, 1
106; RV64-NEXT:    slli a0, a0, 9
107; RV64-NEXT:    ret
108  %tmp.1 = icmp sgt i32 %a, -1
109  %retval = select i1 %tmp.1, i32 512, i32 0
110  ret i32 %retval
111}
112
113; Compare if positive and select variable or zero.
114define i32 @pos_sel_variable_and_zero(i32 signext %a, i32 signext %b) {
115; RV32I-LABEL: pos_sel_variable_and_zero:
116; RV32I:       # %bb.0:
117; RV32I-NEXT:    slti a0, a0, 0
118; RV32I-NEXT:    addi a0, a0, -1
119; RV32I-NEXT:    and a0, a0, a1
120; RV32I-NEXT:    ret
121;
122; RV64I-LABEL: pos_sel_variable_and_zero:
123; RV64I:       # %bb.0:
124; RV64I-NEXT:    slti a0, a0, 0
125; RV64I-NEXT:    addi a0, a0, -1
126; RV64I-NEXT:    and a0, a0, a1
127; RV64I-NEXT:    ret
128;
129; RV32ZBB-LABEL: pos_sel_variable_and_zero:
130; RV32ZBB:       # %bb.0:
131; RV32ZBB-NEXT:    srai a0, a0, 31
132; RV32ZBB-NEXT:    andn a0, a1, a0
133; RV32ZBB-NEXT:    ret
134;
135; RV64ZBB-LABEL: pos_sel_variable_and_zero:
136; RV64ZBB:       # %bb.0:
137; RV64ZBB-NEXT:    srai a0, a0, 31
138; RV64ZBB-NEXT:    andn a0, a1, a0
139; RV64ZBB-NEXT:    ret
140  %tmp.1 = icmp sgt i32 %a, -1
141  %retval = select i1 %tmp.1, i32 %b, i32 0
142  ret i32 %retval
143}
144
145; Compare if not negative or zero and select the same variable as being
146; compared: smax(a, 0).
147define i32 @not_neg_sel_same_variable(i32 signext %a) {
148; RV32I-LABEL: not_neg_sel_same_variable:
149; RV32I:       # %bb.0:
150; RV32I-NEXT:    sgtz a1, a0
151; RV32I-NEXT:    neg a1, a1
152; RV32I-NEXT:    and a0, a1, a0
153; RV32I-NEXT:    ret
154;
155; RV64I-LABEL: not_neg_sel_same_variable:
156; RV64I:       # %bb.0:
157; RV64I-NEXT:    sgtz a1, a0
158; RV64I-NEXT:    neg a1, a1
159; RV64I-NEXT:    and a0, a1, a0
160; RV64I-NEXT:    ret
161;
162; RV32ZBB-LABEL: not_neg_sel_same_variable:
163; RV32ZBB:       # %bb.0:
164; RV32ZBB-NEXT:    max a0, a0, zero
165; RV32ZBB-NEXT:    ret
166;
167; RV64ZBB-LABEL: not_neg_sel_same_variable:
168; RV64ZBB:       # %bb.0:
169; RV64ZBB-NEXT:    max a0, a0, zero
170; RV64ZBB-NEXT:    ret
171  %tmp = icmp sgt i32 %a, 0
172  %min = select i1 %tmp, i32 %a, i32 0
173  ret i32 %min
174}
175
176; ret = (x-y) > 0 ? x-y : 0
177define i32 @sub_clamp_zero(i32 signext %x, i32 signext %y) {
178; RV32I-LABEL: sub_clamp_zero:
179; RV32I:       # %bb.0:
180; RV32I-NEXT:    sub a0, a0, a1
181; RV32I-NEXT:    sgtz a1, a0
182; RV32I-NEXT:    neg a1, a1
183; RV32I-NEXT:    and a0, a1, a0
184; RV32I-NEXT:    ret
185;
186; RV64I-LABEL: sub_clamp_zero:
187; RV64I:       # %bb.0:
188; RV64I-NEXT:    subw a0, a0, a1
189; RV64I-NEXT:    sgtz a1, a0
190; RV64I-NEXT:    neg a1, a1
191; RV64I-NEXT:    and a0, a1, a0
192; RV64I-NEXT:    ret
193;
194; RV32ZBB-LABEL: sub_clamp_zero:
195; RV32ZBB:       # %bb.0:
196; RV32ZBB-NEXT:    sub a0, a0, a1
197; RV32ZBB-NEXT:    max a0, a0, zero
198; RV32ZBB-NEXT:    ret
199;
200; RV64ZBB-LABEL: sub_clamp_zero:
201; RV64ZBB:       # %bb.0:
202; RV64ZBB-NEXT:    subw a0, a0, a1
203; RV64ZBB-NEXT:    max a0, a0, zero
204; RV64ZBB-NEXT:    ret
205  %sub = sub nsw i32 %x, %y
206  %cmp = icmp sgt i32 %sub, 0
207  %sel = select i1 %cmp, i32 %sub, i32 0
208  ret i32 %sel
209}
210
211define i8 @sel_shift_bool_i8(i1 %t) {
212; RV32-LABEL: sel_shift_bool_i8:
213; RV32:       # %bb.0:
214; RV32-NEXT:    slli a0, a0, 31
215; RV32-NEXT:    srai a0, a0, 31
216; RV32-NEXT:    andi a0, a0, -128
217; RV32-NEXT:    ret
218;
219; RV64-LABEL: sel_shift_bool_i8:
220; RV64:       # %bb.0:
221; RV64-NEXT:    slli a0, a0, 63
222; RV64-NEXT:    srai a0, a0, 63
223; RV64-NEXT:    andi a0, a0, -128
224; RV64-NEXT:    ret
225  %shl = select i1 %t, i8 128, i8 0
226  ret i8 %shl
227}
228
229define i16 @sel_shift_bool_i16(i1 %t) {
230; CHECK-LABEL: sel_shift_bool_i16:
231; CHECK:       # %bb.0:
232; CHECK-NEXT:    andi a0, a0, 1
233; CHECK-NEXT:    slli a0, a0, 7
234; CHECK-NEXT:    ret
235  %shl = select i1 %t, i16 128, i16 0
236  ret i16 %shl
237}
238
239define i32 @sel_shift_bool_i32(i1 %t) {
240; CHECK-LABEL: sel_shift_bool_i32:
241; CHECK:       # %bb.0:
242; CHECK-NEXT:    andi a0, a0, 1
243; CHECK-NEXT:    slli a0, a0, 6
244; CHECK-NEXT:    ret
245  %shl = select i1 %t, i32 64, i32 0
246  ret i32 %shl
247}
248
249define i64 @sel_shift_bool_i64(i1 %t) {
250; RV32-LABEL: sel_shift_bool_i64:
251; RV32:       # %bb.0:
252; RV32-NEXT:    andi a0, a0, 1
253; RV32-NEXT:    slli a0, a0, 16
254; RV32-NEXT:    li a1, 0
255; RV32-NEXT:    ret
256;
257; RV64-LABEL: sel_shift_bool_i64:
258; RV64:       # %bb.0:
259; RV64-NEXT:    andi a0, a0, 1
260; RV64-NEXT:    slli a0, a0, 16
261; RV64-NEXT:    ret
262  %shl = select i1 %t, i64 65536, i64 0
263  ret i64 %shl
264}
265
266; FIXME: This should use sraiw+and
267define i64 @sraiw_andi(i32 signext %0, i32 signext %1) nounwind {
268; RV32-LABEL: sraiw_andi:
269; RV32:       # %bb.0: # %entry
270; RV32-NEXT:    add a0, a0, a1
271; RV32-NEXT:    srai a0, a0, 2
272; RV32-NEXT:    srli a0, a0, 29
273; RV32-NEXT:    li a1, 0
274; RV32-NEXT:    ret
275;
276; RV64-LABEL: sraiw_andi:
277; RV64:       # %bb.0: # %entry
278; RV64-NEXT:    add a0, a0, a1
279; RV64-NEXT:    sraiw a0, a0, 31
280; RV64-NEXT:    andi a0, a0, 7
281; RV64-NEXT:    ret
282entry:
283  %3 = add i32 %0, %1
284  %4 = icmp sgt i32 %3, -1
285  %5 = select i1 %4, i64 0, i64 7
286  ret i64 %5
287}
288