xref: /llvm-project/llvm/test/CodeGen/RISCV/select-optimize-multiple.ll (revision 2d550d19b321837aac647ec9e8c5b6f26f682b17)
1; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
2; RUN: llc -mtriple=riscv32 -mattr=+d -verify-machineinstrs < %s \
3; RUN:   | FileCheck %s -check-prefix=RV32I
4; RUN: llc -mtriple=riscv64 -mattr=+d -verify-machineinstrs < %s \
5; RUN:   | FileCheck %s -check-prefix=RV64I
6
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.
10
11define i64 @cmovcc64(i32 signext %a, i64 %b, i64 %c) nounwind {
12; RV32I-LABEL: cmovcc64:
13; RV32I:       # %bb.0: # %entry
14; RV32I-NEXT:    addi a5, zero, 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
22; RV32I-NEXT:    ret
23;
24; RV64I-LABEL: cmovcc64:
25; RV64I:       # %bb.0: # %entry
26; RV64I-NEXT:    addi a3, zero, 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
32; RV64I-NEXT:    ret
33entry:
34  %cmp = icmp eq i32 %a, 123
35  %cond = select i1 %cmp, i64 %b, i64 %c
36  ret i64 %cond
37}
38
39define 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:    beqz a1, .LBB1_2
45; RV32I-NEXT:  # %bb.1: # %entry
46; RV32I-NEXT:    addi a1, a4, 4
47; RV32I-NEXT:    addi a2, a4, 8
48; RV32I-NEXT:    addi a5, a4, 12
49; RV32I-NEXT:    mv a3, a4
50; RV32I-NEXT:    j .LBB1_3
51; RV32I-NEXT:  .LBB1_2:
52; RV32I-NEXT:    addi a1, a3, 4
53; RV32I-NEXT:    addi a2, a3, 8
54; RV32I-NEXT:    addi a5, a3, 12
55; RV32I-NEXT:  .LBB1_3: # %entry
56; RV32I-NEXT:    lw a4, 0(a5)
57; RV32I-NEXT:    sw a4, 12(a0)
58; RV32I-NEXT:    lw a2, 0(a2)
59; RV32I-NEXT:    sw a2, 8(a0)
60; RV32I-NEXT:    lw a1, 0(a1)
61; RV32I-NEXT:    sw a1, 4(a0)
62; RV32I-NEXT:    lw a1, 0(a3)
63; RV32I-NEXT:    sw a1, 0(a0)
64; RV32I-NEXT:    ret
65;
66; RV64I-LABEL: cmovcc128:
67; RV64I:       # %bb.0: # %entry
68; RV64I-NEXT:    addi a5, zero, 123
69; RV64I-NEXT:    beq a0, a5, .LBB1_2
70; RV64I-NEXT:  # %bb.1: # %entry
71; RV64I-NEXT:    mv a1, a3
72; RV64I-NEXT:    mv a2, a4
73; RV64I-NEXT:  .LBB1_2: # %entry
74; RV64I-NEXT:    mv a0, a1
75; RV64I-NEXT:    mv a1, a2
76; RV64I-NEXT:    ret
77entry:
78  %cmp = icmp eq i64 %a, 123
79  %cond = select i1 %cmp, i128 %b, i128 %c
80  ret i128 %cond
81}
82
83define i64 @cmov64(i1 %a, i64 %b, i64 %c) nounwind {
84; RV32I-LABEL: cmov64:
85; RV32I:       # %bb.0: # %entry
86; RV32I-NEXT:    andi a0, a0, 1
87; RV32I-NEXT:    bnez a0, .LBB2_2
88; RV32I-NEXT:  # %bb.1: # %entry
89; RV32I-NEXT:    mv a1, a3
90; RV32I-NEXT:    mv a2, a4
91; RV32I-NEXT:  .LBB2_2: # %entry
92; RV32I-NEXT:    mv a0, a1
93; RV32I-NEXT:    mv a1, a2
94; RV32I-NEXT:    ret
95;
96; RV64I-LABEL: cmov64:
97; RV64I:       # %bb.0: # %entry
98; RV64I-NEXT:    andi a0, a0, 1
99; RV64I-NEXT:    bnez a0, .LBB2_2
100; RV64I-NEXT:  # %bb.1: # %entry
101; RV64I-NEXT:    mv a1, a2
102; RV64I-NEXT:  .LBB2_2: # %entry
103; RV64I-NEXT:    mv a0, a1
104; RV64I-NEXT:    ret
105entry:
106  %cond = select i1 %a, i64 %b, i64 %c
107  ret i64 %cond
108}
109
110define i128 @cmov128(i1 %a, i128 %b, i128 %c) nounwind {
111; RV32I-LABEL: cmov128:
112; RV32I:       # %bb.0: # %entry
113; RV32I-NEXT:    andi a1, a1, 1
114; RV32I-NEXT:    bnez a1, .LBB3_2
115; RV32I-NEXT:  # %bb.1: # %entry
116; RV32I-NEXT:    addi a1, a3, 4
117; RV32I-NEXT:    addi a4, a3, 8
118; RV32I-NEXT:    addi a5, a3, 12
119; RV32I-NEXT:    mv a2, a3
120; RV32I-NEXT:    j .LBB3_3
121; RV32I-NEXT:  .LBB3_2:
122; RV32I-NEXT:    addi a1, a2, 4
123; RV32I-NEXT:    addi a4, a2, 8
124; RV32I-NEXT:    addi a5, a2, 12
125; RV32I-NEXT:  .LBB3_3: # %entry
126; RV32I-NEXT:    lw a3, 0(a5)
127; RV32I-NEXT:    sw a3, 12(a0)
128; RV32I-NEXT:    lw a3, 0(a4)
129; RV32I-NEXT:    sw a3, 8(a0)
130; RV32I-NEXT:    lw a1, 0(a1)
131; RV32I-NEXT:    sw a1, 4(a0)
132; RV32I-NEXT:    lw a1, 0(a2)
133; RV32I-NEXT:    sw a1, 0(a0)
134; RV32I-NEXT:    ret
135;
136; RV64I-LABEL: cmov128:
137; RV64I:       # %bb.0: # %entry
138; RV64I-NEXT:    andi a0, a0, 1
139; RV64I-NEXT:    bnez a0, .LBB3_2
140; RV64I-NEXT:  # %bb.1: # %entry
141; RV64I-NEXT:    mv a1, a3
142; RV64I-NEXT:    mv a2, a4
143; RV64I-NEXT:  .LBB3_2: # %entry
144; RV64I-NEXT:    mv a0, a1
145; RV64I-NEXT:    mv a1, a2
146; RV64I-NEXT:    ret
147entry:
148  %cond = select i1 %a, i128 %b, i128 %c
149  ret i128 %cond
150}
151
152define float @cmovfloat(i1 %a, float %b, float %c, float %d, float %e) nounwind {
153; RV32I-LABEL: cmovfloat:
154; RV32I:       # %bb.0: # %entry
155; RV32I-NEXT:    andi a0, a0, 1
156; RV32I-NEXT:    bnez a0, .LBB4_2
157; RV32I-NEXT:  # %bb.1: # %entry
158; RV32I-NEXT:    fmv.w.x ft0, a4
159; RV32I-NEXT:    fmv.w.x ft1, a2
160; RV32I-NEXT:    j .LBB4_3
161; RV32I-NEXT:  .LBB4_2:
162; RV32I-NEXT:    fmv.w.x ft0, a3
163; RV32I-NEXT:    fmv.w.x ft1, a1
164; RV32I-NEXT:  .LBB4_3: # %entry
165; RV32I-NEXT:    fadd.s ft0, ft1, ft0
166; RV32I-NEXT:    fmv.x.w a0, ft0
167; RV32I-NEXT:    ret
168;
169; RV64I-LABEL: cmovfloat:
170; RV64I:       # %bb.0: # %entry
171; RV64I-NEXT:    andi a0, a0, 1
172; RV64I-NEXT:    bnez a0, .LBB4_2
173; RV64I-NEXT:  # %bb.1: # %entry
174; RV64I-NEXT:    fmv.w.x ft0, a4
175; RV64I-NEXT:    fmv.w.x ft1, a2
176; RV64I-NEXT:    j .LBB4_3
177; RV64I-NEXT:  .LBB4_2:
178; RV64I-NEXT:    fmv.w.x ft0, a3
179; RV64I-NEXT:    fmv.w.x ft1, a1
180; RV64I-NEXT:  .LBB4_3: # %entry
181; RV64I-NEXT:    fadd.s ft0, ft1, ft0
182; RV64I-NEXT:    fmv.x.w a0, ft0
183; RV64I-NEXT:    ret
184entry:
185  %cond1 = select i1 %a, float %b, float %c
186  %cond2 = select i1 %a, float %d, float %e
187  %ret = fadd float %cond1, %cond2
188  ret float %ret
189}
190
191define double @cmovdouble(i1 %a, double %b, double %c) nounwind {
192; RV32I-LABEL: cmovdouble:
193; RV32I:       # %bb.0: # %entry
194; RV32I-NEXT:    addi sp, sp, -16
195; RV32I-NEXT:    sw a3, 8(sp)
196; RV32I-NEXT:    sw a4, 12(sp)
197; RV32I-NEXT:    fld ft0, 8(sp)
198; RV32I-NEXT:    sw a1, 8(sp)
199; RV32I-NEXT:    sw a2, 12(sp)
200; RV32I-NEXT:    fld ft1, 8(sp)
201; RV32I-NEXT:    andi a0, a0, 1
202; RV32I-NEXT:    bnez a0, .LBB5_2
203; RV32I-NEXT:  # %bb.1: # %entry
204; RV32I-NEXT:    fmv.d ft1, ft0
205; RV32I-NEXT:  .LBB5_2: # %entry
206; RV32I-NEXT:    fsd ft1, 8(sp)
207; RV32I-NEXT:    lw a0, 8(sp)
208; RV32I-NEXT:    lw a1, 12(sp)
209; RV32I-NEXT:    addi sp, sp, 16
210; RV32I-NEXT:    ret
211;
212; RV64I-LABEL: cmovdouble:
213; RV64I:       # %bb.0: # %entry
214; RV64I-NEXT:    andi a0, a0, 1
215; RV64I-NEXT:    bnez a0, .LBB5_2
216; RV64I-NEXT:  # %bb.1: # %entry
217; RV64I-NEXT:    fmv.d.x ft0, a2
218; RV64I-NEXT:    fmv.x.d a0, ft0
219; RV64I-NEXT:    ret
220; RV64I-NEXT:  .LBB5_2:
221; RV64I-NEXT:    fmv.d.x ft0, a1
222; RV64I-NEXT:    fmv.x.d a0, ft0
223; RV64I-NEXT:    ret
224entry:
225  %cond = select i1 %a, double %b, double %c
226  ret double %cond
227}
228
229; Check that selects with dependencies on previous ones aren't incorrectly
230; optimized.
231
232define i32 @cmovccdep(i32 signext %a, i32 %b, i32 %c, i32 %d) nounwind {
233; RV32I-LABEL: cmovccdep:
234; RV32I:       # %bb.0: # %entry
235; RV32I-NEXT:    addi a4, zero, 123
236; RV32I-NEXT:    bne a0, a4, .LBB6_3
237; RV32I-NEXT:  # %bb.1: # %entry
238; RV32I-NEXT:    mv a2, a1
239; RV32I-NEXT:    bne a0, a4, .LBB6_4
240; RV32I-NEXT:  .LBB6_2: # %entry
241; RV32I-NEXT:    add a0, a1, a2
242; RV32I-NEXT:    ret
243; RV32I-NEXT:  .LBB6_3: # %entry
244; RV32I-NEXT:    mv a1, a2
245; RV32I-NEXT:    mv a2, a1
246; RV32I-NEXT:    beq a0, a4, .LBB6_2
247; RV32I-NEXT:  .LBB6_4: # %entry
248; RV32I-NEXT:    mv a2, a3
249; RV32I-NEXT:    add a0, a1, a2
250; RV32I-NEXT:    ret
251;
252; RV64I-LABEL: cmovccdep:
253; RV64I:       # %bb.0: # %entry
254; RV64I-NEXT:    addi a4, zero, 123
255; RV64I-NEXT:    bne a0, a4, .LBB6_3
256; RV64I-NEXT:  # %bb.1: # %entry
257; RV64I-NEXT:    mv a2, a1
258; RV64I-NEXT:    bne a0, a4, .LBB6_4
259; RV64I-NEXT:  .LBB6_2: # %entry
260; RV64I-NEXT:    addw a0, a1, a2
261; RV64I-NEXT:    ret
262; RV64I-NEXT:  .LBB6_3: # %entry
263; RV64I-NEXT:    mv a1, a2
264; RV64I-NEXT:    mv a2, a1
265; RV64I-NEXT:    beq a0, a4, .LBB6_2
266; RV64I-NEXT:  .LBB6_4: # %entry
267; RV64I-NEXT:    mv a2, a3
268; RV64I-NEXT:    addw a0, a1, a2
269; RV64I-NEXT:    ret
270entry:
271  %cmp = icmp eq i32 %a, 123
272  %cond1 = select i1 %cmp, i32 %b, i32 %c
273  %cond2 = select i1 %cmp, i32 %cond1, i32 %d
274  %ret = add i32 %cond1, %cond2
275  ret i32 %ret
276}
277
278; Check that selects with different conditions aren't incorrectly optimized.
279
280define i32 @cmovdiffcc(i1 %a, i1 %b, i32 %c, i32 %d, i32 %e, i32 %f) nounwind {
281; RV32I-LABEL: cmovdiffcc:
282; RV32I:       # %bb.0: # %entry
283; RV32I-NEXT:    andi a1, a1, 1
284; RV32I-NEXT:    beqz a1, .LBB7_3
285; RV32I-NEXT:  # %bb.1: # %entry
286; RV32I-NEXT:    andi a0, a0, 1
287; RV32I-NEXT:    beqz a0, .LBB7_4
288; RV32I-NEXT:  .LBB7_2: # %entry
289; RV32I-NEXT:    add a0, a2, a4
290; RV32I-NEXT:    ret
291; RV32I-NEXT:  .LBB7_3: # %entry
292; RV32I-NEXT:    mv a4, a5
293; RV32I-NEXT:    andi a0, a0, 1
294; RV32I-NEXT:    bnez a0, .LBB7_2
295; RV32I-NEXT:  .LBB7_4: # %entry
296; RV32I-NEXT:    mv a2, a3
297; RV32I-NEXT:    add a0, a2, a4
298; RV32I-NEXT:    ret
299;
300; RV64I-LABEL: cmovdiffcc:
301; RV64I:       # %bb.0: # %entry
302; RV64I-NEXT:    andi a1, a1, 1
303; RV64I-NEXT:    beqz a1, .LBB7_3
304; RV64I-NEXT:  # %bb.1: # %entry
305; RV64I-NEXT:    andi a0, a0, 1
306; RV64I-NEXT:    beqz a0, .LBB7_4
307; RV64I-NEXT:  .LBB7_2: # %entry
308; RV64I-NEXT:    addw a0, a2, a4
309; RV64I-NEXT:    ret
310; RV64I-NEXT:  .LBB7_3: # %entry
311; RV64I-NEXT:    mv a4, a5
312; RV64I-NEXT:    andi a0, a0, 1
313; RV64I-NEXT:    bnez a0, .LBB7_2
314; RV64I-NEXT:  .LBB7_4: # %entry
315; RV64I-NEXT:    mv a2, a3
316; RV64I-NEXT:    addw a0, a2, a4
317; RV64I-NEXT:    ret
318entry:
319  %cond1 = select i1 %a, i32 %c, i32 %d
320  %cond2 = select i1 %b, i32 %e, i32 %f
321  %ret = add i32 %cond1, %cond2
322  ret i32 %ret
323}
324