1 ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
2 ; RUN: llc -mtriple=riscv32 -mattr=+d -target-abi=ilp32 -verify-machineinstrs < %s \
3 ; RUN: | FileCheck %s -check-prefix=RV32I
4 ; RUN: llc -mtriple=riscv64 -mattr=+d -target-abi=lp64 -verify-machineinstrs < %s \
5 ; RUN: | FileCheck %s -check-prefix=RV64I
7 ; Selects of wide values are split into two selects, which can easily cause
8 ; unnecessary control flow. Here we check some cases where we can currently
9 ; emit a sequence of selects with shared control flow.
11 define i64 @cmovcc64(i32 signext %a, i64 %b, i64 %c) nounwind {
12 ; RV32I-LABEL: cmovcc64:
13 ; RV32I: # %bb.0: # %entry
14 ; RV32I-NEXT: li a5, 123
15 ; RV32I-NEXT: beq a0, a5, .LBB0_2
16 ; RV32I-NEXT: # %bb.1: # %entry
17 ; RV32I-NEXT: mv a1, a3
18 ; RV32I-NEXT: mv a2, a4
19 ; RV32I-NEXT: .LBB0_2: # %entry
20 ; RV32I-NEXT: mv a0, a1
21 ; RV32I-NEXT: mv a1, a2
24 ; RV64I-LABEL: cmovcc64:
25 ; RV64I: # %bb.0: # %entry
26 ; RV64I-NEXT: li a3, 123
27 ; RV64I-NEXT: beq a0, a3, .LBB0_2
28 ; RV64I-NEXT: # %bb.1: # %entry
29 ; RV64I-NEXT: mv a1, a2
30 ; RV64I-NEXT: .LBB0_2: # %entry
31 ; RV64I-NEXT: mv a0, a1
34 %cmp = icmp eq i32 %a, 123
35 %cond = select i1 %cmp, i64 %b, i64 %c
39 define i128 @cmovcc128(i64 signext %a, i128 %b, i128 %c) nounwind {
40 ; RV32I-LABEL: cmovcc128:
41 ; RV32I: # %bb.0: # %entry
42 ; RV32I-NEXT: xori a1, a1, 123
43 ; RV32I-NEXT: or a1, a1, a2
44 ; RV32I-NEXT: mv a2, a3
45 ; RV32I-NEXT: beqz a1, .LBB1_2
46 ; RV32I-NEXT: # %bb.1: # %entry
47 ; RV32I-NEXT: mv a2, a4
48 ; RV32I-NEXT: .LBB1_2: # %entry
49 ; RV32I-NEXT: beqz a1, .LBB1_5
50 ; RV32I-NEXT: # %bb.3: # %entry
51 ; RV32I-NEXT: addi a5, a4, 4
52 ; RV32I-NEXT: bnez a1, .LBB1_6
53 ; RV32I-NEXT: .LBB1_4:
54 ; RV32I-NEXT: addi a6, a3, 8
55 ; RV32I-NEXT: j .LBB1_7
56 ; RV32I-NEXT: .LBB1_5:
57 ; RV32I-NEXT: addi a5, a3, 4
58 ; RV32I-NEXT: beqz a1, .LBB1_4
59 ; RV32I-NEXT: .LBB1_6: # %entry
60 ; RV32I-NEXT: addi a6, a4, 8
61 ; RV32I-NEXT: .LBB1_7: # %entry
62 ; RV32I-NEXT: lw a2, 0(a2)
63 ; RV32I-NEXT: lw a5, 0(a5)
64 ; RV32I-NEXT: lw a6, 0(a6)
65 ; RV32I-NEXT: beqz a1, .LBB1_9
66 ; RV32I-NEXT: # %bb.8: # %entry
67 ; RV32I-NEXT: addi a3, a4, 12
68 ; RV32I-NEXT: j .LBB1_10
69 ; RV32I-NEXT: .LBB1_9:
70 ; RV32I-NEXT: addi a3, a3, 12
71 ; RV32I-NEXT: .LBB1_10: # %entry
72 ; RV32I-NEXT: lw a1, 0(a3)
73 ; RV32I-NEXT: sw a1, 12(a0)
74 ; RV32I-NEXT: sw a6, 8(a0)
75 ; RV32I-NEXT: sw a5, 4(a0)
76 ; RV32I-NEXT: sw a2, 0(a0)
79 ; RV64I-LABEL: cmovcc128:
80 ; RV64I: # %bb.0: # %entry
81 ; RV64I-NEXT: li a5, 123
82 ; RV64I-NEXT: beq a0, a5, .LBB1_2
83 ; RV64I-NEXT: # %bb.1: # %entry
84 ; RV64I-NEXT: mv a1, a3
85 ; RV64I-NEXT: mv a2, a4
86 ; RV64I-NEXT: .LBB1_2: # %entry
87 ; RV64I-NEXT: mv a0, a1
88 ; RV64I-NEXT: mv a1, a2
91 %cmp = icmp eq i64 %a, 123
92 %cond = select i1 %cmp, i128 %b, i128 %c
96 define i64 @cmov64(i1 %a, i64 %b, i64 %c) nounwind {
97 ; RV32I-LABEL: cmov64:
98 ; RV32I: # %bb.0: # %entry
99 ; RV32I-NEXT: andi a5, a0, 1
100 ; RV32I-NEXT: mv a0, a1
101 ; RV32I-NEXT: bnez a5, .LBB2_2
102 ; RV32I-NEXT: # %bb.1: # %entry
103 ; RV32I-NEXT: mv a0, a3
104 ; RV32I-NEXT: mv a2, a4
105 ; RV32I-NEXT: .LBB2_2: # %entry
106 ; RV32I-NEXT: mv a1, a2
109 ; RV64I-LABEL: cmov64:
110 ; RV64I: # %bb.0: # %entry
111 ; RV64I-NEXT: andi a3, a0, 1
112 ; RV64I-NEXT: mv a0, a1
113 ; RV64I-NEXT: bnez a3, .LBB2_2
114 ; RV64I-NEXT: # %bb.1: # %entry
115 ; RV64I-NEXT: mv a0, a2
116 ; RV64I-NEXT: .LBB2_2: # %entry
119 %cond = select i1 %a, i64 %b, i64 %c
123 define i128 @cmov128(i1 %a, i128 %b, i128 %c) nounwind {
124 ; RV32I-LABEL: cmov128:
125 ; RV32I: # %bb.0: # %entry
126 ; RV32I-NEXT: andi a1, a1, 1
127 ; RV32I-NEXT: mv a4, a2
128 ; RV32I-NEXT: bnez a1, .LBB3_2
129 ; RV32I-NEXT: # %bb.1: # %entry
130 ; RV32I-NEXT: mv a4, a3
131 ; RV32I-NEXT: .LBB3_2: # %entry
132 ; RV32I-NEXT: bnez a1, .LBB3_5
133 ; RV32I-NEXT: # %bb.3: # %entry
134 ; RV32I-NEXT: addi a5, a3, 4
135 ; RV32I-NEXT: beqz a1, .LBB3_6
136 ; RV32I-NEXT: .LBB3_4:
137 ; RV32I-NEXT: addi a6, a2, 8
138 ; RV32I-NEXT: j .LBB3_7
139 ; RV32I-NEXT: .LBB3_5:
140 ; RV32I-NEXT: addi a5, a2, 4
141 ; RV32I-NEXT: bnez a1, .LBB3_4
142 ; RV32I-NEXT: .LBB3_6: # %entry
143 ; RV32I-NEXT: addi a6, a3, 8
144 ; RV32I-NEXT: .LBB3_7: # %entry
145 ; RV32I-NEXT: lw a4, 0(a4)
146 ; RV32I-NEXT: lw a5, 0(a5)
147 ; RV32I-NEXT: lw a6, 0(a6)
148 ; RV32I-NEXT: bnez a1, .LBB3_9
149 ; RV32I-NEXT: # %bb.8: # %entry
150 ; RV32I-NEXT: addi a2, a3, 12
151 ; RV32I-NEXT: j .LBB3_10
152 ; RV32I-NEXT: .LBB3_9:
153 ; RV32I-NEXT: addi a2, a2, 12
154 ; RV32I-NEXT: .LBB3_10: # %entry
155 ; RV32I-NEXT: lw a1, 0(a2)
156 ; RV32I-NEXT: sw a1, 12(a0)
157 ; RV32I-NEXT: sw a6, 8(a0)
158 ; RV32I-NEXT: sw a5, 4(a0)
159 ; RV32I-NEXT: sw a4, 0(a0)
162 ; RV64I-LABEL: cmov128:
163 ; RV64I: # %bb.0: # %entry
164 ; RV64I-NEXT: andi a5, a0, 1
165 ; RV64I-NEXT: mv a0, a1
166 ; RV64I-NEXT: bnez a5, .LBB3_2
167 ; RV64I-NEXT: # %bb.1: # %entry
168 ; RV64I-NEXT: mv a0, a3
169 ; RV64I-NEXT: mv a2, a4
170 ; RV64I-NEXT: .LBB3_2: # %entry
171 ; RV64I-NEXT: mv a1, a2
174 %cond = select i1 %a, i128 %b, i128 %c
178 define float @cmovfloat(i1 %a, float %b, float %c, float %d, float %e) nounwind {
179 ; RV32I-LABEL: cmovfloat:
180 ; RV32I: # %bb.0: # %entry
181 ; RV32I-NEXT: andi a0, a0, 1
182 ; RV32I-NEXT: bnez a0, .LBB4_2
183 ; RV32I-NEXT: # %bb.1: # %entry
184 ; RV32I-NEXT: fmv.w.x fa5, a4
185 ; RV32I-NEXT: fmv.w.x fa4, a2
186 ; RV32I-NEXT: j .LBB4_3
187 ; RV32I-NEXT: .LBB4_2:
188 ; RV32I-NEXT: fmv.w.x fa5, a3
189 ; RV32I-NEXT: fmv.w.x fa4, a1
190 ; RV32I-NEXT: .LBB4_3: # %entry
191 ; RV32I-NEXT: fadd.s fa5, fa4, fa5
192 ; RV32I-NEXT: fmv.x.w a0, fa5
195 ; RV64I-LABEL: cmovfloat:
196 ; RV64I: # %bb.0: # %entry
197 ; RV64I-NEXT: andi a0, a0, 1
198 ; RV64I-NEXT: bnez a0, .LBB4_2
199 ; RV64I-NEXT: # %bb.1: # %entry
200 ; RV64I-NEXT: fmv.w.x fa5, a4
201 ; RV64I-NEXT: fmv.w.x fa4, a2
202 ; RV64I-NEXT: j .LBB4_3
203 ; RV64I-NEXT: .LBB4_2:
204 ; RV64I-NEXT: fmv.w.x fa5, a3
205 ; RV64I-NEXT: fmv.w.x fa4, a1
206 ; RV64I-NEXT: .LBB4_3: # %entry
207 ; RV64I-NEXT: fadd.s fa5, fa4, fa5
208 ; RV64I-NEXT: fmv.x.w a0, fa5
211 %cond1 = select i1 %a, float %b, float %c
212 %cond2 = select i1 %a, float %d, float %e
213 %ret = fadd float %cond1, %cond2
217 define double @cmovdouble(i1 %a, double %b, double %c) nounwind {
218 ; RV32I-LABEL: cmovdouble:
219 ; RV32I: # %bb.0: # %entry
220 ; RV32I-NEXT: addi sp, sp, -16
221 ; RV32I-NEXT: sw a3, 8(sp)
222 ; RV32I-NEXT: sw a4, 12(sp)
223 ; RV32I-NEXT: fld fa5, 8(sp)
224 ; RV32I-NEXT: sw a1, 8(sp)
225 ; RV32I-NEXT: andi a0, a0, 1
226 ; RV32I-NEXT: sw a2, 12(sp)
227 ; RV32I-NEXT: beqz a0, .LBB5_2
228 ; RV32I-NEXT: # %bb.1:
229 ; RV32I-NEXT: fld fa5, 8(sp)
230 ; RV32I-NEXT: .LBB5_2: # %entry
231 ; RV32I-NEXT: fsd fa5, 8(sp)
232 ; RV32I-NEXT: lw a0, 8(sp)
233 ; RV32I-NEXT: lw a1, 12(sp)
234 ; RV32I-NEXT: addi sp, sp, 16
237 ; RV64I-LABEL: cmovdouble:
238 ; RV64I: # %bb.0: # %entry
239 ; RV64I-NEXT: andi a0, a0, 1
240 ; RV64I-NEXT: bnez a0, .LBB5_2
241 ; RV64I-NEXT: # %bb.1: # %entry
242 ; RV64I-NEXT: fmv.d.x fa5, a2
243 ; RV64I-NEXT: fmv.x.d a0, fa5
245 ; RV64I-NEXT: .LBB5_2:
246 ; RV64I-NEXT: fmv.d.x fa5, a1
247 ; RV64I-NEXT: fmv.x.d a0, fa5
250 %cond = select i1 %a, double %b, double %c
254 ; Check that selects with dependencies on previous ones aren't incorrectly
257 define i32 @cmovccdep(i32 signext %a, i32 %b, i32 %c, i32 %d) nounwind {
258 ; RV32I-LABEL: cmovccdep:
259 ; RV32I: # %bb.0: # %entry
260 ; RV32I-NEXT: li a4, 123
261 ; RV32I-NEXT: bne a0, a4, .LBB6_3
262 ; RV32I-NEXT: # %bb.1: # %entry
263 ; RV32I-NEXT: mv a2, a1
264 ; RV32I-NEXT: bne a0, a4, .LBB6_4
265 ; RV32I-NEXT: .LBB6_2: # %entry
266 ; RV32I-NEXT: add a0, a1, a2
268 ; RV32I-NEXT: .LBB6_3: # %entry
269 ; RV32I-NEXT: mv a1, a2
270 ; RV32I-NEXT: beq a0, a4, .LBB6_2
271 ; RV32I-NEXT: .LBB6_4: # %entry
272 ; RV32I-NEXT: add a0, a1, a3
275 ; RV64I-LABEL: cmovccdep:
276 ; RV64I: # %bb.0: # %entry
277 ; RV64I-NEXT: li a4, 123
278 ; RV64I-NEXT: bne a0, a4, .LBB6_3
279 ; RV64I-NEXT: # %bb.1: # %entry
280 ; RV64I-NEXT: mv a2, a1
281 ; RV64I-NEXT: bne a0, a4, .LBB6_4
282 ; RV64I-NEXT: .LBB6_2: # %entry
283 ; RV64I-NEXT: addw a0, a1, a2
285 ; RV64I-NEXT: .LBB6_3: # %entry
286 ; RV64I-NEXT: mv a1, a2
287 ; RV64I-NEXT: beq a0, a4, .LBB6_2
288 ; RV64I-NEXT: .LBB6_4: # %entry
289 ; RV64I-NEXT: addw a0, a1, a3
292 %cmp = icmp eq i32 %a, 123
293 %cond1 = select i1 %cmp, i32 %b, i32 %c
294 %cond2 = select i1 %cmp, i32 %cond1, i32 %d
295 %ret = add i32 %cond1, %cond2
299 ; Check that selects with different conditions aren't incorrectly optimized.
301 define i32 @cmovdiffcc(i1 %a, i1 %b, i32 %c, i32 %d, i32 %e, i32 %f) nounwind {
302 ; RV32I-LABEL: cmovdiffcc:
303 ; RV32I: # %bb.0: # %entry
304 ; RV32I-NEXT: andi a0, a0, 1
305 ; RV32I-NEXT: andi a1, a1, 1
306 ; RV32I-NEXT: beqz a0, .LBB7_3
307 ; RV32I-NEXT: # %bb.1: # %entry
308 ; RV32I-NEXT: beqz a1, .LBB7_4
309 ; RV32I-NEXT: .LBB7_2: # %entry
310 ; RV32I-NEXT: add a0, a2, a4
312 ; RV32I-NEXT: .LBB7_3: # %entry
313 ; RV32I-NEXT: mv a2, a3
314 ; RV32I-NEXT: bnez a1, .LBB7_2
315 ; RV32I-NEXT: .LBB7_4: # %entry
316 ; RV32I-NEXT: add a0, a2, a5
319 ; RV64I-LABEL: cmovdiffcc:
320 ; RV64I: # %bb.0: # %entry
321 ; RV64I-NEXT: andi a0, a0, 1
322 ; RV64I-NEXT: andi a1, a1, 1
323 ; RV64I-NEXT: beqz a0, .LBB7_3
324 ; RV64I-NEXT: # %bb.1: # %entry
325 ; RV64I-NEXT: beqz a1, .LBB7_4
326 ; RV64I-NEXT: .LBB7_2: # %entry
327 ; RV64I-NEXT: addw a0, a2, a4
329 ; RV64I-NEXT: .LBB7_3: # %entry
330 ; RV64I-NEXT: mv a2, a3
331 ; RV64I-NEXT: bnez a1, .LBB7_2
332 ; RV64I-NEXT: .LBB7_4: # %entry
333 ; RV64I-NEXT: addw a0, a2, a5
336 %cond1 = select i1 %a, i32 %c, i32 %d
337 %cond2 = select i1 %b, i32 %e, i32 %f
338 %ret = add i32 %cond1, %cond2
342 define float @CascadedSelect(float noundef %a) {
343 ; RV32I-LABEL: CascadedSelect:
344 ; RV32I: # %bb.0: # %entry
345 ; RV32I-NEXT: fmv.w.x fa5, a0
346 ; RV32I-NEXT: lui a0, 260096
347 ; RV32I-NEXT: fmv.w.x fa4, a0
348 ; RV32I-NEXT: flt.s a0, fa4, fa5
349 ; RV32I-NEXT: bnez a0, .LBB8_3
350 ; RV32I-NEXT: # %bb.1: # %entry
351 ; RV32I-NEXT: fmv.w.x fa4, zero
352 ; RV32I-NEXT: flt.s a0, fa5, fa4
353 ; RV32I-NEXT: bnez a0, .LBB8_3
354 ; RV32I-NEXT: # %bb.2: # %entry
355 ; RV32I-NEXT: fmv.s fa4, fa5
356 ; RV32I-NEXT: .LBB8_3: # %entry
357 ; RV32I-NEXT: fmv.x.w a0, fa4
360 ; RV64I-LABEL: CascadedSelect:
361 ; RV64I: # %bb.0: # %entry
362 ; RV64I-NEXT: fmv.w.x fa5, a0
363 ; RV64I-NEXT: lui a0, 260096
364 ; RV64I-NEXT: fmv.w.x fa4, a0
365 ; RV64I-NEXT: flt.s a0, fa4, fa5
366 ; RV64I-NEXT: bnez a0, .LBB8_3
367 ; RV64I-NEXT: # %bb.1: # %entry
368 ; RV64I-NEXT: fmv.w.x fa4, zero
369 ; RV64I-NEXT: flt.s a0, fa5, fa4
370 ; RV64I-NEXT: bnez a0, .LBB8_3
371 ; RV64I-NEXT: # %bb.2: # %entry
372 ; RV64I-NEXT: fmv.s fa4, fa5
373 ; RV64I-NEXT: .LBB8_3: # %entry
374 ; RV64I-NEXT: fmv.x.w a0, fa4
377 %cmp = fcmp ogt float %a, 1.000000e+00
378 %cmp1 = fcmp olt float %a, 0.000000e+00
379 %.a = select i1 %cmp1, float 0.000000e+00, float %a
380 %retval.0 = select i1 %cmp, float 1.000000e+00, float %.a