xref: /llvm-project/llvm/test/CodeGen/ARM/select_const.ll (revision ab08bb8da9484f1603641b4e9a5133df41498533)
1; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
2; RUN: llc < %s -mtriple=arm-eabi-unknown-unknown | FileCheck %s
3
4; Select of constants: control flow / conditional moves can always be replaced by logic+math (but may not be worth it?).
5; Test the zeroext/signext variants of each pattern to see if that makes a difference.
6
7; select Cond, 0, 1 --> zext (!Cond)
8
9define i32 @select_0_or_1(i1 %cond) {
10; CHECK-LABEL: select_0_or_1:
11; CHECK:       @ BB#0:
12; CHECK-NEXT:    mov r1, #1
13; CHECK-NEXT:    bic r0, r1, r0
14; CHECK-NEXT:    mov pc, lr
15  %sel = select i1 %cond, i32 0, i32 1
16  ret i32 %sel
17}
18
19define i32 @select_0_or_1_zeroext(i1 zeroext %cond) {
20; CHECK-LABEL: select_0_or_1_zeroext:
21; CHECK:       @ BB#0:
22; CHECK-NEXT:    eor r0, r0, #1
23; CHECK-NEXT:    mov pc, lr
24  %sel = select i1 %cond, i32 0, i32 1
25  ret i32 %sel
26}
27
28define i32 @select_0_or_1_signext(i1 signext %cond) {
29; CHECK-LABEL: select_0_or_1_signext:
30; CHECK:       @ BB#0:
31; CHECK-NEXT:    mov r1, #1
32; CHECK-NEXT:    bic r0, r1, r0
33; CHECK-NEXT:    mov pc, lr
34  %sel = select i1 %cond, i32 0, i32 1
35  ret i32 %sel
36}
37
38; select Cond, 1, 0 --> zext (Cond)
39
40define i32 @select_1_or_0(i1 %cond) {
41; CHECK-LABEL: select_1_or_0:
42; CHECK:       @ BB#0:
43; CHECK-NEXT:    and r0, r0, #1
44; CHECK-NEXT:    mov pc, lr
45  %sel = select i1 %cond, i32 1, i32 0
46  ret i32 %sel
47}
48
49define i32 @select_1_or_0_zeroext(i1 zeroext %cond) {
50; CHECK-LABEL: select_1_or_0_zeroext:
51; CHECK:       @ BB#0:
52; CHECK-NEXT:    mov pc, lr
53  %sel = select i1 %cond, i32 1, i32 0
54  ret i32 %sel
55}
56
57define i32 @select_1_or_0_signext(i1 signext %cond) {
58; CHECK-LABEL: select_1_or_0_signext:
59; CHECK:       @ BB#0:
60; CHECK-NEXT:    and r0, r0, #1
61; CHECK-NEXT:    mov pc, lr
62  %sel = select i1 %cond, i32 1, i32 0
63  ret i32 %sel
64}
65
66; select Cond, 0, -1 --> sext (!Cond)
67
68define i32 @select_0_or_neg1(i1 %cond) {
69; CHECK-LABEL: select_0_or_neg1:
70; CHECK:       @ BB#0:
71; CHECK-NEXT:    mov r1, #1
72; CHECK-NEXT:    bic r0, r1, r0
73; CHECK-NEXT:    rsb r0, r0, #0
74; CHECK-NEXT:    mov pc, lr
75  %sel = select i1 %cond, i32 0, i32 -1
76  ret i32 %sel
77}
78
79define i32 @select_0_or_neg1_zeroext(i1 zeroext %cond) {
80; CHECK-LABEL: select_0_or_neg1_zeroext:
81; CHECK:       @ BB#0:
82; CHECK-NEXT:    eor r0, r0, #1
83; CHECK-NEXT:    rsb r0, r0, #0
84; CHECK-NEXT:    mov pc, lr
85  %sel = select i1 %cond, i32 0, i32 -1
86  ret i32 %sel
87}
88
89define i32 @select_0_or_neg1_signext(i1 signext %cond) {
90; CHECK-LABEL: select_0_or_neg1_signext:
91; CHECK:       @ BB#0:
92; CHECK-NEXT:    mvn r0, r0
93; CHECK-NEXT:    mov pc, lr
94  %sel = select i1 %cond, i32 0, i32 -1
95  ret i32 %sel
96}
97
98define i32 @select_0_or_neg1_alt(i1 %cond) {
99; CHECK-LABEL: select_0_or_neg1_alt:
100; CHECK:       @ BB#0:
101; CHECK-NEXT:    mov r1, #1
102; CHECK-NEXT:    bic r0, r1, r0
103; CHECK-NEXT:    rsb r0, r0, #0
104; CHECK-NEXT:    mov pc, lr
105  %z = zext i1 %cond to i32
106  %add = add i32 %z, -1
107  ret i32 %add
108}
109
110define i32 @select_0_or_neg1_alt_zeroext(i1 zeroext %cond) {
111; CHECK-LABEL: select_0_or_neg1_alt_zeroext:
112; CHECK:       @ BB#0:
113; CHECK-NEXT:    eor r0, r0, #1
114; CHECK-NEXT:    rsb r0, r0, #0
115; CHECK-NEXT:    mov pc, lr
116  %z = zext i1 %cond to i32
117  %add = add i32 %z, -1
118  ret i32 %add
119}
120
121define i32 @select_0_or_neg1_alt_signext(i1 signext %cond) {
122; CHECK-LABEL: select_0_or_neg1_alt_signext:
123; CHECK:       @ BB#0:
124; CHECK-NEXT:    mvn r0, r0
125; CHECK-NEXT:    mov pc, lr
126  %z = zext i1 %cond to i32
127  %add = add i32 %z, -1
128  ret i32 %add
129}
130
131; select Cond, -1, 0 --> sext (Cond)
132
133define i32 @select_neg1_or_0(i1 %cond) {
134; CHECK-LABEL: select_neg1_or_0:
135; CHECK:       @ BB#0:
136; CHECK-NEXT:    and r0, r0, #1
137; CHECK-NEXT:    rsb r0, r0, #0
138; CHECK-NEXT:    mov pc, lr
139  %sel = select i1 %cond, i32 -1, i32 0
140  ret i32 %sel
141}
142
143define i32 @select_neg1_or_0_zeroext(i1 zeroext %cond) {
144; CHECK-LABEL: select_neg1_or_0_zeroext:
145; CHECK:       @ BB#0:
146; CHECK-NEXT:    rsb r0, r0, #0
147; CHECK-NEXT:    mov pc, lr
148  %sel = select i1 %cond, i32 -1, i32 0
149  ret i32 %sel
150}
151
152define i32 @select_neg1_or_0_signext(i1 signext %cond) {
153; CHECK-LABEL: select_neg1_or_0_signext:
154; CHECK:       @ BB#0:
155; CHECK-NEXT:    mov pc, lr
156  %sel = select i1 %cond, i32 -1, i32 0
157  ret i32 %sel
158}
159
160; select Cond, C+1, C --> add (zext Cond), C
161
162define i32 @select_Cplus1_C(i1 %cond) {
163; CHECK-LABEL: select_Cplus1_C:
164; CHECK:       @ BB#0:
165; CHECK-NEXT:    mov r1, #41
166; CHECK-NEXT:    tst r0, #1
167; CHECK-NEXT:    movne r1, #42
168; CHECK-NEXT:    mov r0, r1
169; CHECK-NEXT:    mov pc, lr
170  %sel = select i1 %cond, i32 42, i32 41
171  ret i32 %sel
172}
173
174define i32 @select_Cplus1_C_zeroext(i1 zeroext %cond) {
175; CHECK-LABEL: select_Cplus1_C_zeroext:
176; CHECK:       @ BB#0:
177; CHECK-NEXT:    mov r1, #41
178; CHECK-NEXT:    cmp r0, #0
179; CHECK-NEXT:    movne r1, #42
180; CHECK-NEXT:    mov r0, r1
181; CHECK-NEXT:    mov pc, lr
182  %sel = select i1 %cond, i32 42, i32 41
183  ret i32 %sel
184}
185
186define i32 @select_Cplus1_C_signext(i1 signext %cond) {
187; CHECK-LABEL: select_Cplus1_C_signext:
188; CHECK:       @ BB#0:
189; CHECK-NEXT:    mov r1, #41
190; CHECK-NEXT:    tst r0, #1
191; CHECK-NEXT:    movne r1, #42
192; CHECK-NEXT:    mov r0, r1
193; CHECK-NEXT:    mov pc, lr
194  %sel = select i1 %cond, i32 42, i32 41
195  ret i32 %sel
196}
197
198; select Cond, C, C+1 --> add (sext Cond), C
199
200define i32 @select_C_Cplus1(i1 %cond) {
201; CHECK-LABEL: select_C_Cplus1:
202; CHECK:       @ BB#0:
203; CHECK-NEXT:    mov r1, #42
204; CHECK-NEXT:    tst r0, #1
205; CHECK-NEXT:    movne r1, #41
206; CHECK-NEXT:    mov r0, r1
207; CHECK-NEXT:    mov pc, lr
208  %sel = select i1 %cond, i32 41, i32 42
209  ret i32 %sel
210}
211
212define i32 @select_C_Cplus1_zeroext(i1 zeroext %cond) {
213; CHECK-LABEL: select_C_Cplus1_zeroext:
214; CHECK:       @ BB#0:
215; CHECK-NEXT:    mov r1, #42
216; CHECK-NEXT:    cmp r0, #0
217; CHECK-NEXT:    movne r1, #41
218; CHECK-NEXT:    mov r0, r1
219; CHECK-NEXT:    mov pc, lr
220  %sel = select i1 %cond, i32 41, i32 42
221  ret i32 %sel
222}
223
224define i32 @select_C_Cplus1_signext(i1 signext %cond) {
225; CHECK-LABEL: select_C_Cplus1_signext:
226; CHECK:       @ BB#0:
227; CHECK-NEXT:    mov r1, #42
228; CHECK-NEXT:    tst r0, #1
229; CHECK-NEXT:    movne r1, #41
230; CHECK-NEXT:    mov r0, r1
231; CHECK-NEXT:    mov pc, lr
232  %sel = select i1 %cond, i32 41, i32 42
233  ret i32 %sel
234}
235
236; In general, select of 2 constants could be:
237; select Cond, C1, C2 --> add (mul (zext Cond), C1-C2), C2 --> add (and (sext Cond), C1-C2), C2
238
239define i32 @select_C1_C2(i1 %cond) {
240; CHECK-LABEL: select_C1_C2:
241; CHECK:       @ BB#0:
242; CHECK-NEXT:    mov r1, #165
243; CHECK-NEXT:    tst r0, #1
244; CHECK-NEXT:    orr r1, r1, #256
245; CHECK-NEXT:    moveq r1, #42
246; CHECK-NEXT:    mov r0, r1
247; CHECK-NEXT:    mov pc, lr
248  %sel = select i1 %cond, i32 421, i32 42
249  ret i32 %sel
250}
251
252define i32 @select_C1_C2_zeroext(i1 zeroext %cond) {
253; CHECK-LABEL: select_C1_C2_zeroext:
254; CHECK:       @ BB#0:
255; CHECK-NEXT:    mov r1, #165
256; CHECK-NEXT:    cmp r0, #0
257; CHECK-NEXT:    orr r1, r1, #256
258; CHECK-NEXT:    moveq r1, #42
259; CHECK-NEXT:    mov r0, r1
260; CHECK-NEXT:    mov pc, lr
261  %sel = select i1 %cond, i32 421, i32 42
262  ret i32 %sel
263}
264
265define i32 @select_C1_C2_signext(i1 signext %cond) {
266; CHECK-LABEL: select_C1_C2_signext:
267; CHECK:       @ BB#0:
268; CHECK-NEXT:    mov r1, #165
269; CHECK-NEXT:    tst r0, #1
270; CHECK-NEXT:    orr r1, r1, #256
271; CHECK-NEXT:    moveq r1, #42
272; CHECK-NEXT:    mov r0, r1
273; CHECK-NEXT:    mov pc, lr
274  %sel = select i1 %cond, i32 421, i32 42
275  ret i32 %sel
276}
277
278