1 ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
2 ; RUN: llc -mtriple=riscv64 -mattr=+c -verify-machineinstrs < %s \
3 ; RUN: | FileCheck -check-prefix=NOCMOV %s
4 ; RUN: llc -mtriple=riscv64 -mattr=+conditional-cmv-fusion,+c -verify-machineinstrs < %s \
5 ; RUN: | FileCheck -check-prefixes=CMOV,CMOV-NOZICOND %s
6 ; RUN: llc -mtriple=riscv64 -mattr=+conditional-cmv-fusion,+c,+zicond -verify-machineinstrs < %s \
7 ; RUN: | FileCheck -check-prefixes=CMOV,CMOV-ZICOND %s
8 ; RUN: llc -mtriple=riscv64 -mattr=+short-forward-branch-opt -verify-machineinstrs < %s \
9 ; RUN: | FileCheck -check-prefixes=SHORT_FORWARD,SFB-NOZICOND %s
10 ; RUN: llc -mtriple=riscv64 -mattr=+short-forward-branch-opt,+c -verify-machineinstrs < %s \
11 ; RUN: | FileCheck -check-prefixes=SHORT_FORWARD,SFB-NOZICOND %s
12 ; RUN: llc -mtriple=riscv64 -mattr=+short-forward-branch-opt,+zicond -verify-machineinstrs < %s \
13 ; RUN: | FileCheck -check-prefixes=SHORT_FORWARD,SFB-ZICOND %s
15 ; The conditional move optimization in sifive-p450 requires that only a
16 ; single c.mv instruction appears in the branch shadow.
18 ; The sifive-7-series can predicate an xor.
20 define signext i32 @test1(i32 signext %x, i32 signext %y, i32 signext %z) {
21 ; NOCMOV-LABEL: test1:
23 ; NOCMOV-NEXT: snez a2, a2
24 ; NOCMOV-NEXT: addi a2, a2, -1
25 ; NOCMOV-NEXT: and a1, a1, a2
26 ; NOCMOV-NEXT: xor a0, a0, a1
31 ; CMOV-NEXT: xor a1, a1, a0
32 ; CMOV-NEXT: bnez a2, .LBB0_2
34 ; CMOV-NEXT: mv a0, a1
38 ; SHORT_FORWARD-LABEL: test1:
39 ; SHORT_FORWARD: # %bb.0:
40 ; SHORT_FORWARD-NEXT: bnez a2, .LBB0_2
41 ; SHORT_FORWARD-NEXT: # %bb.1:
42 ; SHORT_FORWARD-NEXT: xor a0, a0, a1
43 ; SHORT_FORWARD-NEXT: .LBB0_2:
44 ; SHORT_FORWARD-NEXT: ret
45 %c = icmp eq i32 %z, 0
47 %b = select i1 %c, i32 %a, i32 %x
51 define signext i32 @test2(i32 signext %x, i32 signext %y, i32 signext %z) {
52 ; NOCMOV-LABEL: test2:
54 ; NOCMOV-NEXT: seqz a2, a2
55 ; NOCMOV-NEXT: addi a2, a2, -1
56 ; NOCMOV-NEXT: and a1, a1, a2
57 ; NOCMOV-NEXT: xor a0, a0, a1
62 ; CMOV-NEXT: xor a1, a1, a0
63 ; CMOV-NEXT: beqz a2, .LBB1_2
65 ; CMOV-NEXT: mv a0, a1
69 ; SHORT_FORWARD-LABEL: test2:
70 ; SHORT_FORWARD: # %bb.0:
71 ; SHORT_FORWARD-NEXT: beqz a2, .LBB1_2
72 ; SHORT_FORWARD-NEXT: # %bb.1:
73 ; SHORT_FORWARD-NEXT: xor a0, a0, a1
74 ; SHORT_FORWARD-NEXT: .LBB1_2:
75 ; SHORT_FORWARD-NEXT: ret
76 %c = icmp eq i32 %z, 0
78 %b = select i1 %c, i32 %x, i32 %a
82 ; Make sure we don't share the same basic block for two selects with the same
84 define signext i32 @test3(i32 signext %v, i32 signext %w, i32 signext %x, i32 signext %y, i32 signext %z) {
85 ; NOCMOV-LABEL: test3:
87 ; NOCMOV-NEXT: seqz a4, a4
88 ; NOCMOV-NEXT: addi a4, a4, -1
89 ; NOCMOV-NEXT: and a1, a1, a4
90 ; NOCMOV-NEXT: xor a0, a0, a1
91 ; NOCMOV-NEXT: and a3, a3, a4
92 ; NOCMOV-NEXT: xor a2, a2, a3
93 ; NOCMOV-NEXT: addw a0, a0, a2
98 ; CMOV-NEXT: xor a1, a1, a0
99 ; CMOV-NEXT: bnez a4, .LBB2_2
100 ; CMOV-NEXT: # %bb.1:
101 ; CMOV-NEXT: mv a1, a0
102 ; CMOV-NEXT: .LBB2_2:
103 ; CMOV-NEXT: xor a0, a2, a3
104 ; CMOV-NEXT: bnez a4, .LBB2_4
105 ; CMOV-NEXT: # %bb.3:
106 ; CMOV-NEXT: mv a0, a2
107 ; CMOV-NEXT: .LBB2_4:
108 ; CMOV-NEXT: addw a0, a0, a1
111 ; SHORT_FORWARD-LABEL: test3:
112 ; SHORT_FORWARD: # %bb.0:
113 ; SHORT_FORWARD-NEXT: beqz a4, .LBB2_2
114 ; SHORT_FORWARD-NEXT: # %bb.1:
115 ; SHORT_FORWARD-NEXT: xor a0, a0, a1
116 ; SHORT_FORWARD-NEXT: .LBB2_2:
117 ; SHORT_FORWARD-NEXT: beqz a4, .LBB2_4
118 ; SHORT_FORWARD-NEXT: # %bb.3:
119 ; SHORT_FORWARD-NEXT: xor a2, a2, a3
120 ; SHORT_FORWARD-NEXT: .LBB2_4:
121 ; SHORT_FORWARD-NEXT: addw a0, a0, a2
122 ; SHORT_FORWARD-NEXT: ret
123 %c = icmp eq i32 %z, 0
125 %b = select i1 %c, i32 %v, i32 %a
127 %e = select i1 %c, i32 %x, i32 %d
132 define signext i32 @test4(i32 signext %x, i32 signext %y, i32 signext %z) {
133 ; NOCMOV-LABEL: test4:
135 ; NOCMOV-NEXT: snez a0, a2
136 ; NOCMOV-NEXT: addi a0, a0, -1
137 ; NOCMOV-NEXT: andi a0, a0, 3
140 ; CMOV-NOZICOND-LABEL: test4:
141 ; CMOV-NOZICOND: # %bb.0:
142 ; CMOV-NOZICOND-NEXT: li a1, 0
143 ; CMOV-NOZICOND-NEXT: li a0, 3
144 ; CMOV-NOZICOND-NEXT: beqz a2, .LBB3_2
145 ; CMOV-NOZICOND-NEXT: # %bb.1:
146 ; CMOV-NOZICOND-NEXT: mv a0, a1
147 ; CMOV-NOZICOND-NEXT: .LBB3_2:
148 ; CMOV-NOZICOND-NEXT: ret
150 ; CMOV-ZICOND-LABEL: test4:
151 ; CMOV-ZICOND: # %bb.0:
152 ; CMOV-ZICOND-NEXT: li a0, 3
153 ; CMOV-ZICOND-NEXT: czero.nez a0, a0, a2
154 ; CMOV-ZICOND-NEXT: ret
156 ; SFB-NOZICOND-LABEL: test4:
157 ; SFB-NOZICOND: # %bb.0:
158 ; SFB-NOZICOND-NEXT: li a0, 3
159 ; SFB-NOZICOND-NEXT: beqz a2, .LBB3_2
160 ; SFB-NOZICOND-NEXT: # %bb.1:
161 ; SFB-NOZICOND-NEXT: li a0, 0
162 ; SFB-NOZICOND-NEXT: .LBB3_2:
163 ; SFB-NOZICOND-NEXT: ret
165 ; SFB-ZICOND-LABEL: test4:
166 ; SFB-ZICOND: # %bb.0:
167 ; SFB-ZICOND-NEXT: li a0, 3
168 ; SFB-ZICOND-NEXT: czero.nez a0, a0, a2
169 ; SFB-ZICOND-NEXT: ret
170 %c = icmp eq i32 %z, 0
171 %a = select i1 %c, i32 3, i32 0
175 define i16 @select_xor_1(i16 %A, i8 %cond) {
176 ; NOCMOV-LABEL: select_xor_1:
177 ; NOCMOV: # %bb.0: # %entry
178 ; NOCMOV-NEXT: slli a1, a1, 63
179 ; NOCMOV-NEXT: srai a1, a1, 63
180 ; NOCMOV-NEXT: andi a1, a1, 43
181 ; NOCMOV-NEXT: xor a0, a0, a1
184 ; CMOV-LABEL: select_xor_1:
185 ; CMOV: # %bb.0: # %entry
186 ; CMOV-NEXT: andi a1, a1, 1
187 ; CMOV-NEXT: xori a2, a0, 43
188 ; CMOV-NEXT: beqz a1, .LBB4_2
189 ; CMOV-NEXT: # %bb.1: # %entry
190 ; CMOV-NEXT: mv a0, a2
191 ; CMOV-NEXT: .LBB4_2: # %entry
194 ; SHORT_FORWARD-LABEL: select_xor_1:
195 ; SHORT_FORWARD: # %bb.0: # %entry
196 ; SHORT_FORWARD-NEXT: andi a1, a1, 1
197 ; SHORT_FORWARD-NEXT: beqz a1, .LBB4_2
198 ; SHORT_FORWARD-NEXT: # %bb.1: # %entry
199 ; SHORT_FORWARD-NEXT: xori a0, a0, 43
200 ; SHORT_FORWARD-NEXT: .LBB4_2: # %entry
201 ; SHORT_FORWARD-NEXT: ret
203 %and = and i8 %cond, 1
204 %cmp10 = icmp eq i8 %and, 0
206 %1 = select i1 %cmp10, i16 %A, i16 %0
210 ; Equivalent to above, but with icmp ne (and %cond, 1), 1 instead of
211 ; icmp eq (and %cond, 1), 0
212 define i16 @select_xor_1b(i16 %A, i8 %cond) {
213 ; NOCMOV-LABEL: select_xor_1b:
214 ; NOCMOV: # %bb.0: # %entry
215 ; NOCMOV-NEXT: slli a1, a1, 63
216 ; NOCMOV-NEXT: srai a1, a1, 63
217 ; NOCMOV-NEXT: andi a1, a1, 43
218 ; NOCMOV-NEXT: xor a0, a0, a1
221 ; CMOV-LABEL: select_xor_1b:
222 ; CMOV: # %bb.0: # %entry
223 ; CMOV-NEXT: andi a1, a1, 1
224 ; CMOV-NEXT: xori a2, a0, 43
225 ; CMOV-NEXT: beqz a1, .LBB5_2
226 ; CMOV-NEXT: # %bb.1: # %entry
227 ; CMOV-NEXT: mv a0, a2
228 ; CMOV-NEXT: .LBB5_2: # %entry
231 ; SHORT_FORWARD-LABEL: select_xor_1b:
232 ; SHORT_FORWARD: # %bb.0: # %entry
233 ; SHORT_FORWARD-NEXT: andi a1, a1, 1
234 ; SHORT_FORWARD-NEXT: beqz a1, .LBB5_2
235 ; SHORT_FORWARD-NEXT: # %bb.1: # %entry
236 ; SHORT_FORWARD-NEXT: xori a0, a0, 43
237 ; SHORT_FORWARD-NEXT: .LBB5_2: # %entry
238 ; SHORT_FORWARD-NEXT: ret
240 %and = and i8 %cond, 1
241 %cmp10 = icmp ne i8 %and, 1
243 %1 = select i1 %cmp10, i16 %A, i16 %0
247 define i32 @select_xor_2(i32 %A, i32 %B, i8 %cond) {
248 ; NOCMOV-LABEL: select_xor_2:
249 ; NOCMOV: # %bb.0: # %entry
250 ; NOCMOV-NEXT: slli a2, a2, 63
251 ; NOCMOV-NEXT: srai a2, a2, 63
252 ; NOCMOV-NEXT: and a1, a1, a2
253 ; NOCMOV-NEXT: xor a0, a0, a1
256 ; CMOV-LABEL: select_xor_2:
257 ; CMOV: # %bb.0: # %entry
258 ; CMOV-NEXT: andi a2, a2, 1
259 ; CMOV-NEXT: xor a1, a1, a0
260 ; CMOV-NEXT: beqz a2, .LBB6_2
261 ; CMOV-NEXT: # %bb.1: # %entry
262 ; CMOV-NEXT: mv a0, a1
263 ; CMOV-NEXT: .LBB6_2: # %entry
266 ; SFB-ZICOND-LABEL: select_xor_2:
267 ; SFB-ZICOND: # %bb.0: # %entry
268 ; SFB-ZICOND-NEXT: andi a2, a2, 1
269 ; SFB-ZICOND-NEXT: beqz a2, .LBB6_2
270 ; SFB-ZICOND-NEXT: # %bb.1: # %entry
271 ; SFB-ZICOND-NEXT: xor a0, a1, a0
272 ; SFB-ZICOND-NEXT: .LBB6_2: # %entry
273 ; SFB-ZICOND-NEXT: ret
275 %and = and i8 %cond, 1
276 %cmp10 = icmp eq i8 %and, 0
278 %1 = select i1 %cmp10, i32 %A, i32 %0
282 ; Equivalent to above, but with icmp ne (and %cond, 1), 1 instead of
283 ; icmp eq (and %cond, 1), 0
284 define i32 @select_xor_2b(i32 %A, i32 %B, i8 %cond) {
285 ; NOCMOV-LABEL: select_xor_2b:
286 ; NOCMOV: # %bb.0: # %entry
287 ; NOCMOV-NEXT: slli a2, a2, 63
288 ; NOCMOV-NEXT: srai a2, a2, 63
289 ; NOCMOV-NEXT: and a1, a1, a2
290 ; NOCMOV-NEXT: xor a0, a0, a1
293 ; CMOV-LABEL: select_xor_2b:
294 ; CMOV: # %bb.0: # %entry
295 ; CMOV-NEXT: andi a2, a2, 1
296 ; CMOV-NEXT: xor a1, a1, a0
297 ; CMOV-NEXT: beqz a2, .LBB7_2
298 ; CMOV-NEXT: # %bb.1: # %entry
299 ; CMOV-NEXT: mv a0, a1
300 ; CMOV-NEXT: .LBB7_2: # %entry
303 ; SFB-ZICOND-LABEL: select_xor_2b:
304 ; SFB-ZICOND: # %bb.0: # %entry
305 ; SFB-ZICOND-NEXT: andi a2, a2, 1
306 ; SFB-ZICOND-NEXT: beqz a2, .LBB7_2
307 ; SFB-ZICOND-NEXT: # %bb.1: # %entry
308 ; SFB-ZICOND-NEXT: xor a0, a1, a0
309 ; SFB-ZICOND-NEXT: .LBB7_2: # %entry
310 ; SFB-ZICOND-NEXT: ret
312 %and = and i8 %cond, 1
313 %cmp10 = icmp ne i8 %and, 1
315 %1 = select i1 %cmp10, i32 %A, i32 %0
319 define i32 @select_or(i32 %A, i32 %B, i8 %cond) {
320 ; NOCMOV-LABEL: select_or:
321 ; NOCMOV: # %bb.0: # %entry
322 ; NOCMOV-NEXT: slli a2, a2, 63
323 ; NOCMOV-NEXT: srai a2, a2, 63
324 ; NOCMOV-NEXT: and a1, a1, a2
325 ; NOCMOV-NEXT: or a0, a0, a1
328 ; CMOV-LABEL: select_or:
329 ; CMOV: # %bb.0: # %entry
330 ; CMOV-NEXT: andi a2, a2, 1
331 ; CMOV-NEXT: or a1, a1, a0
332 ; CMOV-NEXT: beqz a2, .LBB8_2
333 ; CMOV-NEXT: # %bb.1: # %entry
334 ; CMOV-NEXT: mv a0, a1
335 ; CMOV-NEXT: .LBB8_2: # %entry
338 ; SFB-ZICOND-LABEL: select_or:
339 ; SFB-ZICOND: # %bb.0: # %entry
340 ; SFB-ZICOND-NEXT: andi a2, a2, 1
341 ; SFB-ZICOND-NEXT: beqz a2, .LBB8_2
342 ; SFB-ZICOND-NEXT: # %bb.1: # %entry
343 ; SFB-ZICOND-NEXT: or a0, a1, a0
344 ; SFB-ZICOND-NEXT: .LBB8_2: # %entry
345 ; SFB-ZICOND-NEXT: ret
347 %and = and i8 %cond, 1
348 %cmp10 = icmp eq i8 %and, 0
350 %1 = select i1 %cmp10, i32 %A, i32 %0
354 ; Equivalent to above, but with icmp ne (and %cond, 1), 1 instead of
355 ; icmp eq (and %cond, 1), 0
356 define i32 @select_or_b(i32 %A, i32 %B, i8 %cond) {
357 ; NOCMOV-LABEL: select_or_b:
358 ; NOCMOV: # %bb.0: # %entry
359 ; NOCMOV-NEXT: slli a2, a2, 63
360 ; NOCMOV-NEXT: srai a2, a2, 63
361 ; NOCMOV-NEXT: and a1, a1, a2
362 ; NOCMOV-NEXT: or a0, a0, a1
365 ; CMOV-LABEL: select_or_b:
366 ; CMOV: # %bb.0: # %entry
367 ; CMOV-NEXT: andi a2, a2, 1
368 ; CMOV-NEXT: or a1, a1, a0
369 ; CMOV-NEXT: beqz a2, .LBB9_2
370 ; CMOV-NEXT: # %bb.1: # %entry
371 ; CMOV-NEXT: mv a0, a1
372 ; CMOV-NEXT: .LBB9_2: # %entry
375 ; SFB-ZICOND-LABEL: select_or_b:
376 ; SFB-ZICOND: # %bb.0: # %entry
377 ; SFB-ZICOND-NEXT: andi a2, a2, 1
378 ; SFB-ZICOND-NEXT: beqz a2, .LBB9_2
379 ; SFB-ZICOND-NEXT: # %bb.1: # %entry
380 ; SFB-ZICOND-NEXT: or a0, a1, a0
381 ; SFB-ZICOND-NEXT: .LBB9_2: # %entry
382 ; SFB-ZICOND-NEXT: ret
384 %and = and i8 %cond, 1
385 %cmp10 = icmp ne i8 %and, 1
387 %1 = select i1 %cmp10, i32 %A, i32 %0
391 define i32 @select_or_1(i32 %A, i32 %B, i32 %cond) {
392 ; NOCMOV-LABEL: select_or_1:
393 ; NOCMOV: # %bb.0: # %entry
394 ; NOCMOV-NEXT: slli a2, a2, 63
395 ; NOCMOV-NEXT: srai a2, a2, 63
396 ; NOCMOV-NEXT: and a1, a1, a2
397 ; NOCMOV-NEXT: or a0, a0, a1
400 ; CMOV-LABEL: select_or_1:
401 ; CMOV: # %bb.0: # %entry
402 ; CMOV-NEXT: andi a2, a2, 1
403 ; CMOV-NEXT: or a1, a1, a0
404 ; CMOV-NEXT: beqz a2, .LBB10_2
405 ; CMOV-NEXT: # %bb.1: # %entry
406 ; CMOV-NEXT: mv a0, a1
407 ; CMOV-NEXT: .LBB10_2: # %entry
410 ; SFB-ZICOND-LABEL: select_or_1:
411 ; SFB-ZICOND: # %bb.0: # %entry
412 ; SFB-ZICOND-NEXT: andi a2, a2, 1
413 ; SFB-ZICOND-NEXT: beqz a2, .LBB10_2
414 ; SFB-ZICOND-NEXT: # %bb.1: # %entry
415 ; SFB-ZICOND-NEXT: or a0, a1, a0
416 ; SFB-ZICOND-NEXT: .LBB10_2: # %entry
417 ; SFB-ZICOND-NEXT: ret
419 %and = and i32 %cond, 1
420 %cmp10 = icmp eq i32 %and, 0
422 %1 = select i1 %cmp10, i32 %A, i32 %0
426 ; Equivalent to above, but with icmp ne (and %cond, 1), 1 instead of
427 ; icmp eq (and %cond, 1), 0
428 define i32 @select_or_1b(i32 %A, i32 %B, i32 %cond) {
429 ; NOCMOV-LABEL: select_or_1b:
430 ; NOCMOV: # %bb.0: # %entry
431 ; NOCMOV-NEXT: slli a2, a2, 63
432 ; NOCMOV-NEXT: srai a2, a2, 63
433 ; NOCMOV-NEXT: and a1, a1, a2
434 ; NOCMOV-NEXT: or a0, a0, a1
437 ; CMOV-LABEL: select_or_1b:
438 ; CMOV: # %bb.0: # %entry
439 ; CMOV-NEXT: andi a2, a2, 1
440 ; CMOV-NEXT: or a1, a1, a0
441 ; CMOV-NEXT: beqz a2, .LBB11_2
442 ; CMOV-NEXT: # %bb.1: # %entry
443 ; CMOV-NEXT: mv a0, a1
444 ; CMOV-NEXT: .LBB11_2: # %entry
447 ; SFB-ZICOND-LABEL: select_or_1b:
448 ; SFB-ZICOND: # %bb.0: # %entry
449 ; SFB-ZICOND-NEXT: andi a2, a2, 1
450 ; SFB-ZICOND-NEXT: beqz a2, .LBB11_2
451 ; SFB-ZICOND-NEXT: # %bb.1: # %entry
452 ; SFB-ZICOND-NEXT: or a0, a1, a0
453 ; SFB-ZICOND-NEXT: .LBB11_2: # %entry
454 ; SFB-ZICOND-NEXT: ret
456 %and = and i32 %cond, 1
457 %cmp10 = icmp ne i32 %and, 1
459 %1 = select i1 %cmp10, i32 %A, i32 %0