xref: /llvm-project/llvm/test/CodeGen/X86/selectcc-to-shiftand.ll (revision d96529af3c362c53ef2e8c883a9e571fb3626927)
1; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
2; RUN: llc -mtriple=x86_64-unknown-linux-gnu -mattr=-bmi < %s | FileCheck %s --check-prefixes=ANY,CHECK-NOBMI
3; RUN: llc -mtriple=x86_64-unknown-linux-gnu -mattr=+bmi < %s | FileCheck %s --check-prefixes=ANY,CHECK-BMI
4
5; Compare if negative and select of constants where one constant is zero.
6
7define i32 @neg_sel_constants(i32 %a) {
8; ANY-LABEL: neg_sel_constants:
9; ANY:       # %bb.0:
10; ANY-NEXT:    movl %edi, %eax
11; ANY-NEXT:    sarl $31, %eax
12; ANY-NEXT:    andl $5, %eax
13; ANY-NEXT:    retq
14  %tmp.1 = icmp slt i32 %a, 0
15  %retval = select i1 %tmp.1, i32 5, i32 0
16  ret i32 %retval
17}
18
19; Compare if negative and select of constants where one constant is zero and the other is a single bit.
20
21define i32 @neg_sel_special_constant(i32 %a) {
22; ANY-LABEL: neg_sel_special_constant:
23; ANY:       # %bb.0:
24; ANY-NEXT:    movl %edi, %eax
25; ANY-NEXT:    shrl $22, %eax
26; ANY-NEXT:    andl $512, %eax # imm = 0x200
27; ANY-NEXT:    retq
28  %tmp.1 = icmp slt i32 %a, 0
29  %retval = select i1 %tmp.1, i32 512, i32 0
30  ret i32 %retval
31}
32
33; Compare if negative and select variable or zero.
34
35define i32 @neg_sel_variable_and_zero(i32 %a, i32 %b) {
36; ANY-LABEL: neg_sel_variable_and_zero:
37; ANY:       # %bb.0:
38; ANY-NEXT:    movl %edi, %eax
39; ANY-NEXT:    sarl $31, %eax
40; ANY-NEXT:    andl %esi, %eax
41; ANY-NEXT:    retq
42  %tmp.1 = icmp slt i32 %a, 0
43  %retval = select i1 %tmp.1, i32 %b, i32 0
44  ret i32 %retval
45}
46
47; Compare if not positive and select the same variable as being compared: smin(a, 0).
48
49define i32 @not_pos_sel_same_variable(i32 %a) {
50; ANY-LABEL: not_pos_sel_same_variable:
51; ANY:       # %bb.0:
52; ANY-NEXT:    movl %edi, %eax
53; ANY-NEXT:    sarl $31, %eax
54; ANY-NEXT:    andl %edi, %eax
55; ANY-NEXT:    retq
56  %tmp = icmp slt i32 %a, 1
57  %min = select i1 %tmp, i32 %a, i32 0
58  ret i32 %min
59}
60
61; Flipping the comparison condition can be handled by getting the bitwise not of the sign mask.
62
63; Compare if positive and select of constants where one constant is zero.
64
65define i32 @pos_sel_constants(i32 %a) {
66; ANY-LABEL: pos_sel_constants:
67; ANY:       # %bb.0:
68; ANY-NEXT:    # kill: def $edi killed $edi def $rdi
69; ANY-NEXT:    notl %edi
70; ANY-NEXT:    shrl $31, %edi
71; ANY-NEXT:    leal (%rdi,%rdi,4), %eax
72; ANY-NEXT:    retq
73  %tmp.1 = icmp sgt i32 %a, -1
74  %retval = select i1 %tmp.1, i32 5, i32 0
75  ret i32 %retval
76}
77
78; Compare if positive and select of constants where one constant is zero and the other is a single bit.
79
80define i32 @pos_sel_special_constant(i32 %a) {
81; ANY-LABEL: pos_sel_special_constant:
82; ANY:       # %bb.0:
83; ANY-NEXT:    movl %edi, %eax
84; ANY-NEXT:    notl %eax
85; ANY-NEXT:    shrl $22, %eax
86; ANY-NEXT:    andl $512, %eax # imm = 0x200
87; ANY-NEXT:    retq
88  %tmp.1 = icmp sgt i32 %a, -1
89  %retval = select i1 %tmp.1, i32 512, i32 0
90  ret i32 %retval
91}
92
93; Compare if positive and select variable or zero.
94
95define i32 @pos_sel_variable_and_zero(i32 %a, i32 %b) {
96; CHECK-NOBMI-LABEL: pos_sel_variable_and_zero:
97; CHECK-NOBMI:       # %bb.0:
98; CHECK-NOBMI-NEXT:    xorl %eax, %eax
99; CHECK-NOBMI-NEXT:    testl %edi, %edi
100; CHECK-NOBMI-NEXT:    cmovnsl %esi, %eax
101; CHECK-NOBMI-NEXT:    retq
102;
103; CHECK-BMI-LABEL: pos_sel_variable_and_zero:
104; CHECK-BMI:       # %bb.0:
105; CHECK-BMI-NEXT:    sarl $31, %edi
106; CHECK-BMI-NEXT:    andnl %esi, %edi, %eax
107; CHECK-BMI-NEXT:    retq
108  %tmp.1 = icmp sgt i32 %a, -1
109  %retval = select i1 %tmp.1, i32 %b, i32 0
110  ret i32 %retval
111}
112
113; Compare if not negative or zero and select the same variable as being compared: smax(a, 0).
114
115define i32 @not_neg_sel_same_variable(i32 %a) {
116; CHECK-NOBMI-LABEL: not_neg_sel_same_variable:
117; CHECK-NOBMI:       # %bb.0:
118; CHECK-NOBMI-NEXT:    xorl %eax, %eax
119; CHECK-NOBMI-NEXT:    testl %edi, %edi
120; CHECK-NOBMI-NEXT:    cmovnsl %edi, %eax
121; CHECK-NOBMI-NEXT:    retq
122;
123; CHECK-BMI-LABEL: not_neg_sel_same_variable:
124; CHECK-BMI:       # %bb.0:
125; CHECK-BMI-NEXT:    movl %edi, %eax
126; CHECK-BMI-NEXT:    sarl $31, %eax
127; CHECK-BMI-NEXT:    andnl %edi, %eax, %eax
128; CHECK-BMI-NEXT:    retq
129  %tmp = icmp sgt i32 %a, 0
130  %min = select i1 %tmp, i32 %a, i32 0
131  ret i32 %min
132}
133
134; https://llvm.org/bugs/show_bug.cgi?id=31175
135
136; ret = (x-y) > 0 ? x-y : 0
137define i32 @PR31175(i32 %x, i32 %y) {
138; CHECK-NOBMI-LABEL: PR31175:
139; CHECK-NOBMI:       # %bb.0:
140; CHECK-NOBMI-NEXT:    xorl %eax, %eax
141; CHECK-NOBMI-NEXT:    subl %esi, %edi
142; CHECK-NOBMI-NEXT:    cmovnsl %edi, %eax
143; CHECK-NOBMI-NEXT:    retq
144;
145; CHECK-BMI-LABEL: PR31175:
146; CHECK-BMI:       # %bb.0:
147; CHECK-BMI-NEXT:    subl %esi, %edi
148; CHECK-BMI-NEXT:    movl %edi, %eax
149; CHECK-BMI-NEXT:    sarl $31, %eax
150; CHECK-BMI-NEXT:    andnl %edi, %eax, %eax
151; CHECK-BMI-NEXT:    retq
152  %sub = sub nsw i32 %x, %y
153  %cmp = icmp sgt i32 %sub, 0
154  %sel = select i1 %cmp, i32 %sub, i32 0
155  ret i32 %sel
156}
157
158define i8 @sel_shift_bool_i8(i1 %t) {
159; ANY-LABEL: sel_shift_bool_i8:
160; ANY:       # %bb.0:
161; ANY-NEXT:    movl %edi, %eax
162; ANY-NEXT:    shlb $7, %al
163; ANY-NEXT:    # kill: def $al killed $al killed $eax
164; ANY-NEXT:    retq
165  %shl = select i1 %t, i8 128, i8 0
166  ret i8 %shl
167}
168
169define i16 @sel_shift_bool_i16(i1 %t) {
170; ANY-LABEL: sel_shift_bool_i16:
171; ANY:       # %bb.0:
172; ANY-NEXT:    movl %edi, %eax
173; ANY-NEXT:    andl $1, %eax
174; ANY-NEXT:    shll $7, %eax
175; ANY-NEXT:    # kill: def $ax killed $ax killed $eax
176; ANY-NEXT:    retq
177  %shl = select i1 %t, i16 128, i16 0
178  ret i16 %shl
179}
180
181define i32 @sel_shift_bool_i32(i1 %t) {
182; ANY-LABEL: sel_shift_bool_i32:
183; ANY:       # %bb.0:
184; ANY-NEXT:    movl %edi, %eax
185; ANY-NEXT:    andl $1, %eax
186; ANY-NEXT:    shll $6, %eax
187; ANY-NEXT:    retq
188  %shl = select i1 %t, i32 64, i32 0
189  ret i32 %shl
190}
191
192define i64 @sel_shift_bool_i64(i1 %t) {
193; ANY-LABEL: sel_shift_bool_i64:
194; ANY:       # %bb.0:
195; ANY-NEXT:    movl %edi, %eax
196; ANY-NEXT:    andl $1, %eax
197; ANY-NEXT:    shll $16, %eax
198; ANY-NEXT:    retq
199  %shl = select i1 %t, i64 65536, i64 0
200  ret i64 %shl
201}
202
203define <16 x i8> @sel_shift_bool_v16i8(<16 x i1> %t) {
204; ANY-LABEL: sel_shift_bool_v16i8:
205; ANY:       # %bb.0:
206; ANY-NEXT:    psllw $7, %xmm0
207; ANY-NEXT:    pand {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm0
208; ANY-NEXT:    retq
209  %shl = select <16 x i1> %t, <16 x i8> <i8 128, i8 128, i8 128, i8 128, i8 128, i8 128, i8 128, i8 128, i8 128, i8 128, i8 128, i8 128, i8 128, i8 128, i8 128, i8 128>, <16 x i8> zeroinitializer
210  ret <16 x i8> %shl
211}
212
213define <8 x i16> @sel_shift_bool_v8i16(<8 x i1> %t) {
214; ANY-LABEL: sel_shift_bool_v8i16:
215; ANY:       # %bb.0:
216; ANY-NEXT:    psllw $7, %xmm0
217; ANY-NEXT:    pand {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm0
218; ANY-NEXT:    retq
219  %shl= select <8 x i1> %t, <8 x i16> <i16 128, i16 128, i16 128, i16 128, i16 128, i16 128, i16 128, i16 128>, <8 x i16> zeroinitializer
220  ret <8 x i16> %shl
221}
222
223define <4 x i32> @sel_shift_bool_v4i32(<4 x i1> %t) {
224; ANY-LABEL: sel_shift_bool_v4i32:
225; ANY:       # %bb.0:
226; ANY-NEXT:    pslld $6, %xmm0
227; ANY-NEXT:    pand {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm0
228; ANY-NEXT:    retq
229  %shl = select <4 x i1> %t, <4 x i32> <i32 64, i32 64, i32 64, i32 64>, <4 x i32> zeroinitializer
230  ret <4 x i32> %shl
231}
232
233define <2 x i64> @sel_shift_bool_v2i64(<2 x i1> %t) {
234; ANY-LABEL: sel_shift_bool_v2i64:
235; ANY:       # %bb.0:
236; ANY-NEXT:    psllq $16, %xmm0
237; ANY-NEXT:    pand {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm0
238; ANY-NEXT:    retq
239  %shl = select <2 x i1> %t, <2 x i64> <i64 65536, i64 65536>, <2 x i64> zeroinitializer
240  ret <2 x i64> %shl
241}
242