xref: /llvm-project/llvm/test/CodeGen/X86/bitselect.ll (revision 96aa76aa716d577d31a2831c8d3a85ddd6b3de80)
1025952b0SSimon Pilgrim; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
2025952b0SSimon Pilgrim; RUN: llc < %s -mtriple=i686-unknown-unknown | FileCheck %s --check-prefixes=X86
3025952b0SSimon Pilgrim; RUN: llc < %s -mtriple=x86_64-unknown-unknown -mattr=-bmi | FileCheck %s --check-prefixes=X64,X64-NOBMI
4025952b0SSimon Pilgrim; RUN: llc < %s -mtriple=x86_64-unknown-unknown -mattr=+bmi | FileCheck %s --check-prefixes=X64,X64-BMI
5025952b0SSimon Pilgrim
6025952b0SSimon Pilgrim; PR46472
7025952b0SSimon Pilgrim; bitselect(a,b,m) == or(and(a,not(m)),and(b,m))
8025952b0SSimon Pilgrim; bitselect(a,b,m) == xor(and(xor(a,b),m),a)
9025952b0SSimon Pilgrim
10025952b0SSimon Pilgrimdefine i8 @bitselect_i8(i8 %a, i8 %b, i8 %m) nounwind {
11025952b0SSimon Pilgrim; X86-LABEL: bitselect_i8:
12025952b0SSimon Pilgrim; X86:       # %bb.0:
13025952b0SSimon Pilgrim; X86-NEXT:    movzbl {{[0-9]+}}(%esp), %ecx
14025952b0SSimon Pilgrim; X86-NEXT:    movzbl {{[0-9]+}}(%esp), %eax
15025952b0SSimon Pilgrim; X86-NEXT:    xorb %cl, %al
16025952b0SSimon Pilgrim; X86-NEXT:    andb {{[0-9]+}}(%esp), %al
17025952b0SSimon Pilgrim; X86-NEXT:    xorb %cl, %al
18025952b0SSimon Pilgrim; X86-NEXT:    retl
19025952b0SSimon Pilgrim;
20025952b0SSimon Pilgrim; X64-LABEL: bitselect_i8:
21025952b0SSimon Pilgrim; X64:       # %bb.0:
22025952b0SSimon Pilgrim; X64-NEXT:    andl %edx, %esi
23025952b0SSimon Pilgrim; X64-NEXT:    movl %edx, %eax
24025952b0SSimon Pilgrim; X64-NEXT:    notb %al
25025952b0SSimon Pilgrim; X64-NEXT:    andb %dil, %al
26025952b0SSimon Pilgrim; X64-NEXT:    orb %sil, %al
27025952b0SSimon Pilgrim; X64-NEXT:    retq
28025952b0SSimon Pilgrim  %not = xor i8 %m, -1
29025952b0SSimon Pilgrim  %ma = and i8 %a, %not
30025952b0SSimon Pilgrim  %mb = and i8 %b, %m
31025952b0SSimon Pilgrim  %or = or i8 %ma, %mb
32025952b0SSimon Pilgrim  ret i8 %or
33025952b0SSimon Pilgrim}
34025952b0SSimon Pilgrim
35025952b0SSimon Pilgrimdefine i16 @bitselect_i16(i16 %a, i16 %b, i16 %m) nounwind {
36025952b0SSimon Pilgrim; X86-LABEL: bitselect_i16:
37025952b0SSimon Pilgrim; X86:       # %bb.0:
38025952b0SSimon Pilgrim; X86-NEXT:    movzwl {{[0-9]+}}(%esp), %eax
39025952b0SSimon Pilgrim; X86-NEXT:    movzwl {{[0-9]+}}(%esp), %ecx
40025952b0SSimon Pilgrim; X86-NEXT:    xorw %ax, %cx
41025952b0SSimon Pilgrim; X86-NEXT:    andw {{[0-9]+}}(%esp), %cx
42025952b0SSimon Pilgrim; X86-NEXT:    xorl %ecx, %eax
43025952b0SSimon Pilgrim; X86-NEXT:    # kill: def $ax killed $ax killed $eax
44025952b0SSimon Pilgrim; X86-NEXT:    retl
45025952b0SSimon Pilgrim;
46025952b0SSimon Pilgrim; X64-NOBMI-LABEL: bitselect_i16:
47025952b0SSimon Pilgrim; X64-NOBMI:       # %bb.0:
48025952b0SSimon Pilgrim; X64-NOBMI-NEXT:    movl %edx, %eax
49025952b0SSimon Pilgrim; X64-NOBMI-NEXT:    andl %edx, %esi
50025952b0SSimon Pilgrim; X64-NOBMI-NEXT:    notl %eax
51025952b0SSimon Pilgrim; X64-NOBMI-NEXT:    andl %edi, %eax
52025952b0SSimon Pilgrim; X64-NOBMI-NEXT:    orl %esi, %eax
53025952b0SSimon Pilgrim; X64-NOBMI-NEXT:    # kill: def $ax killed $ax killed $eax
54025952b0SSimon Pilgrim; X64-NOBMI-NEXT:    retq
55025952b0SSimon Pilgrim;
56025952b0SSimon Pilgrim; X64-BMI-LABEL: bitselect_i16:
57025952b0SSimon Pilgrim; X64-BMI:       # %bb.0:
58025952b0SSimon Pilgrim; X64-BMI-NEXT:    andnl %edi, %edx, %eax
59025952b0SSimon Pilgrim; X64-BMI-NEXT:    andl %edx, %esi
60025952b0SSimon Pilgrim; X64-BMI-NEXT:    orl %esi, %eax
61025952b0SSimon Pilgrim; X64-BMI-NEXT:    # kill: def $ax killed $ax killed $eax
62025952b0SSimon Pilgrim; X64-BMI-NEXT:    retq
63025952b0SSimon Pilgrim  %not = xor i16 %m, -1
64025952b0SSimon Pilgrim  %ma = and i16 %a, %not
65025952b0SSimon Pilgrim  %mb = and i16 %b, %m
66025952b0SSimon Pilgrim  %or = or i16 %ma, %mb
67025952b0SSimon Pilgrim  ret i16 %or
68025952b0SSimon Pilgrim}
69025952b0SSimon Pilgrim
70025952b0SSimon Pilgrimdefine i32 @bitselect_i32(i32 %a, i32 %b, i32 %m) nounwind {
71025952b0SSimon Pilgrim; X86-LABEL: bitselect_i32:
72025952b0SSimon Pilgrim; X86:       # %bb.0:
73025952b0SSimon Pilgrim; X86-NEXT:    movl {{[0-9]+}}(%esp), %ecx
74025952b0SSimon Pilgrim; X86-NEXT:    movl {{[0-9]+}}(%esp), %eax
75025952b0SSimon Pilgrim; X86-NEXT:    xorl %ecx, %eax
76025952b0SSimon Pilgrim; X86-NEXT:    andl {{[0-9]+}}(%esp), %eax
77025952b0SSimon Pilgrim; X86-NEXT:    xorl %ecx, %eax
78025952b0SSimon Pilgrim; X86-NEXT:    retl
79025952b0SSimon Pilgrim;
80025952b0SSimon Pilgrim; X64-NOBMI-LABEL: bitselect_i32:
81025952b0SSimon Pilgrim; X64-NOBMI:       # %bb.0:
82025952b0SSimon Pilgrim; X64-NOBMI-NEXT:    movl %esi, %eax
83025952b0SSimon Pilgrim; X64-NOBMI-NEXT:    xorl %edi, %eax
84025952b0SSimon Pilgrim; X64-NOBMI-NEXT:    andl %edx, %eax
85025952b0SSimon Pilgrim; X64-NOBMI-NEXT:    xorl %edi, %eax
86025952b0SSimon Pilgrim; X64-NOBMI-NEXT:    retq
87025952b0SSimon Pilgrim;
88025952b0SSimon Pilgrim; X64-BMI-LABEL: bitselect_i32:
89025952b0SSimon Pilgrim; X64-BMI:       # %bb.0:
90025952b0SSimon Pilgrim; X64-BMI-NEXT:    andnl %edi, %edx, %eax
91025952b0SSimon Pilgrim; X64-BMI-NEXT:    andl %edx, %esi
92025952b0SSimon Pilgrim; X64-BMI-NEXT:    orl %esi, %eax
93025952b0SSimon Pilgrim; X64-BMI-NEXT:    retq
94025952b0SSimon Pilgrim  %not = xor i32 %m, -1
95025952b0SSimon Pilgrim  %ma = and i32 %a, %not
96025952b0SSimon Pilgrim  %mb = and i32 %b, %m
97025952b0SSimon Pilgrim  %or = or i32 %ma, %mb
98025952b0SSimon Pilgrim  ret i32 %or
99025952b0SSimon Pilgrim}
100025952b0SSimon Pilgrim
101025952b0SSimon Pilgrimdefine i64 @bitselect_i64(i64 %a, i64 %b, i64 %m) nounwind {
102025952b0SSimon Pilgrim; X86-LABEL: bitselect_i64:
103025952b0SSimon Pilgrim; X86:       # %bb.0:
104025952b0SSimon Pilgrim; X86-NEXT:    pushl %esi
105025952b0SSimon Pilgrim; X86-NEXT:    movl {{[0-9]+}}(%esp), %ecx
106025952b0SSimon Pilgrim; X86-NEXT:    movl {{[0-9]+}}(%esp), %esi
107025952b0SSimon Pilgrim; X86-NEXT:    movl {{[0-9]+}}(%esp), %eax
108025952b0SSimon Pilgrim; X86-NEXT:    xorl %ecx, %eax
109025952b0SSimon Pilgrim; X86-NEXT:    andl {{[0-9]+}}(%esp), %eax
110025952b0SSimon Pilgrim; X86-NEXT:    xorl %ecx, %eax
111025952b0SSimon Pilgrim; X86-NEXT:    movl {{[0-9]+}}(%esp), %edx
112025952b0SSimon Pilgrim; X86-NEXT:    xorl %esi, %edx
113025952b0SSimon Pilgrim; X86-NEXT:    andl {{[0-9]+}}(%esp), %edx
114025952b0SSimon Pilgrim; X86-NEXT:    xorl %esi, %edx
115025952b0SSimon Pilgrim; X86-NEXT:    popl %esi
116025952b0SSimon Pilgrim; X86-NEXT:    retl
117025952b0SSimon Pilgrim;
118025952b0SSimon Pilgrim; X64-NOBMI-LABEL: bitselect_i64:
119025952b0SSimon Pilgrim; X64-NOBMI:       # %bb.0:
120025952b0SSimon Pilgrim; X64-NOBMI-NEXT:    movq %rsi, %rax
121025952b0SSimon Pilgrim; X64-NOBMI-NEXT:    xorq %rdi, %rax
122025952b0SSimon Pilgrim; X64-NOBMI-NEXT:    andq %rdx, %rax
123025952b0SSimon Pilgrim; X64-NOBMI-NEXT:    xorq %rdi, %rax
124025952b0SSimon Pilgrim; X64-NOBMI-NEXT:    retq
125025952b0SSimon Pilgrim;
126025952b0SSimon Pilgrim; X64-BMI-LABEL: bitselect_i64:
127025952b0SSimon Pilgrim; X64-BMI:       # %bb.0:
128025952b0SSimon Pilgrim; X64-BMI-NEXT:    andnq %rdi, %rdx, %rax
129025952b0SSimon Pilgrim; X64-BMI-NEXT:    andq %rdx, %rsi
130025952b0SSimon Pilgrim; X64-BMI-NEXT:    orq %rsi, %rax
131025952b0SSimon Pilgrim; X64-BMI-NEXT:    retq
132025952b0SSimon Pilgrim  %not = xor i64 %m, -1
133025952b0SSimon Pilgrim  %ma = and i64 %a, %not
134025952b0SSimon Pilgrim  %mb = and i64 %b, %m
135025952b0SSimon Pilgrim  %or = or i64 %ma, %mb
136025952b0SSimon Pilgrim  ret i64 %or
137025952b0SSimon Pilgrim}
138025952b0SSimon Pilgrim
139025952b0SSimon Pilgrimdefine i128 @bitselect_i128(i128 %a, i128 %b, i128 %m) nounwind {
140025952b0SSimon Pilgrim; X86-LABEL: bitselect_i128:
141025952b0SSimon Pilgrim; X86:       # %bb.0:
142025952b0SSimon Pilgrim; X86-NEXT:    pushl %ebx
143025952b0SSimon Pilgrim; X86-NEXT:    pushl %edi
144025952b0SSimon Pilgrim; X86-NEXT:    pushl %esi
145025952b0SSimon Pilgrim; X86-NEXT:    movl {{[0-9]+}}(%esp), %eax
146025952b0SSimon Pilgrim; X86-NEXT:    movl {{[0-9]+}}(%esp), %esi
147025952b0SSimon Pilgrim; X86-NEXT:    movl {{[0-9]+}}(%esp), %edx
148025952b0SSimon Pilgrim; X86-NEXT:    movl {{[0-9]+}}(%esp), %edi
149025952b0SSimon Pilgrim; X86-NEXT:    movl {{[0-9]+}}(%esp), %ebx
150025952b0SSimon Pilgrim; X86-NEXT:    movl {{[0-9]+}}(%esp), %ecx
151025952b0SSimon Pilgrim; X86-NEXT:    xorl %edi, %ecx
152025952b0SSimon Pilgrim; X86-NEXT:    andl {{[0-9]+}}(%esp), %ecx
153025952b0SSimon Pilgrim; X86-NEXT:    xorl %edi, %ecx
154025952b0SSimon Pilgrim; X86-NEXT:    movl {{[0-9]+}}(%esp), %edi
155025952b0SSimon Pilgrim; X86-NEXT:    xorl %ebx, %edi
156025952b0SSimon Pilgrim; X86-NEXT:    andl {{[0-9]+}}(%esp), %edi
157025952b0SSimon Pilgrim; X86-NEXT:    xorl %ebx, %edi
158025952b0SSimon Pilgrim; X86-NEXT:    movl {{[0-9]+}}(%esp), %ebx
159025952b0SSimon Pilgrim; X86-NEXT:    xorl %esi, %ebx
160025952b0SSimon Pilgrim; X86-NEXT:    andl {{[0-9]+}}(%esp), %ebx
161025952b0SSimon Pilgrim; X86-NEXT:    xorl %esi, %ebx
162025952b0SSimon Pilgrim; X86-NEXT:    movl {{[0-9]+}}(%esp), %esi
163025952b0SSimon Pilgrim; X86-NEXT:    xorl %edx, %esi
164025952b0SSimon Pilgrim; X86-NEXT:    andl {{[0-9]+}}(%esp), %esi
165025952b0SSimon Pilgrim; X86-NEXT:    xorl %edx, %esi
166025952b0SSimon Pilgrim; X86-NEXT:    movl %esi, 12(%eax)
167025952b0SSimon Pilgrim; X86-NEXT:    movl %ebx, 8(%eax)
168025952b0SSimon Pilgrim; X86-NEXT:    movl %edi, 4(%eax)
169025952b0SSimon Pilgrim; X86-NEXT:    movl %ecx, (%eax)
170025952b0SSimon Pilgrim; X86-NEXT:    popl %esi
171025952b0SSimon Pilgrim; X86-NEXT:    popl %edi
172025952b0SSimon Pilgrim; X86-NEXT:    popl %ebx
173025952b0SSimon Pilgrim; X86-NEXT:    retl $4
174025952b0SSimon Pilgrim;
175025952b0SSimon Pilgrim; X64-NOBMI-LABEL: bitselect_i128:
176025952b0SSimon Pilgrim; X64-NOBMI:       # %bb.0:
177025952b0SSimon Pilgrim; X64-NOBMI-NEXT:    movq %rdx, %rax
178025952b0SSimon Pilgrim; X64-NOBMI-NEXT:    xorq %rdi, %rax
179025952b0SSimon Pilgrim; X64-NOBMI-NEXT:    andq %r8, %rax
180025952b0SSimon Pilgrim; X64-NOBMI-NEXT:    xorq %rdi, %rax
181025952b0SSimon Pilgrim; X64-NOBMI-NEXT:    xorq %rsi, %rcx
182025952b0SSimon Pilgrim; X64-NOBMI-NEXT:    andq %r9, %rcx
183025952b0SSimon Pilgrim; X64-NOBMI-NEXT:    xorq %rsi, %rcx
184025952b0SSimon Pilgrim; X64-NOBMI-NEXT:    movq %rcx, %rdx
185025952b0SSimon Pilgrim; X64-NOBMI-NEXT:    retq
186025952b0SSimon Pilgrim;
187025952b0SSimon Pilgrim; X64-BMI-LABEL: bitselect_i128:
188025952b0SSimon Pilgrim; X64-BMI:       # %bb.0:
189025952b0SSimon Pilgrim; X64-BMI-NEXT:    andnq %rsi, %r9, %rsi
190025952b0SSimon Pilgrim; X64-BMI-NEXT:    andnq %rdi, %r8, %rax
191025952b0SSimon Pilgrim; X64-BMI-NEXT:    andq %r9, %rcx
192025952b0SSimon Pilgrim; X64-BMI-NEXT:    orq %rcx, %rsi
193025952b0SSimon Pilgrim; X64-BMI-NEXT:    andq %r8, %rdx
194025952b0SSimon Pilgrim; X64-BMI-NEXT:    orq %rdx, %rax
195025952b0SSimon Pilgrim; X64-BMI-NEXT:    movq %rsi, %rdx
196025952b0SSimon Pilgrim; X64-BMI-NEXT:    retq
197025952b0SSimon Pilgrim  %not = xor i128 %m, -1
198025952b0SSimon Pilgrim  %ma = and i128 %a, %not
199025952b0SSimon Pilgrim  %mb = and i128 %b, %m
200025952b0SSimon Pilgrim  %or = or i128 %ma, %mb
201025952b0SSimon Pilgrim  ret i128 %or
202025952b0SSimon Pilgrim}
203*96aa76aaSSimon Pilgrim
204*96aa76aaSSimon Pilgrim;
205*96aa76aaSSimon Pilgrim; Bitselect between constants
206*96aa76aaSSimon Pilgrim;
207*96aa76aaSSimon Pilgrim
208*96aa76aaSSimon Pilgrim; bitselect(52, -6553, m)
209*96aa76aaSSimon Pilgrim; TODO: Non-BMI canonicalization is actually better.
210*96aa76aaSSimon Pilgrimdefine i32 @bitselect_constants_i32(i32 %m) nounwind {
211*96aa76aaSSimon Pilgrim; X86-LABEL: bitselect_constants_i32:
212*96aa76aaSSimon Pilgrim; X86:       # %bb.0:
213*96aa76aaSSimon Pilgrim; X86-NEXT:    movl $-6573, %eax # imm = 0xE653
214*96aa76aaSSimon Pilgrim; X86-NEXT:    andl {{[0-9]+}}(%esp), %eax
215*96aa76aaSSimon Pilgrim; X86-NEXT:    xorl $52, %eax
216*96aa76aaSSimon Pilgrim; X86-NEXT:    retl
217*96aa76aaSSimon Pilgrim;
218*96aa76aaSSimon Pilgrim; X64-NOBMI-LABEL: bitselect_constants_i32:
219*96aa76aaSSimon Pilgrim; X64-NOBMI:       # %bb.0:
220*96aa76aaSSimon Pilgrim; X64-NOBMI-NEXT:    movl %edi, %eax
221*96aa76aaSSimon Pilgrim; X64-NOBMI-NEXT:    andl $-6573, %eax # imm = 0xE653
222*96aa76aaSSimon Pilgrim; X64-NOBMI-NEXT:    xorl $52, %eax
223*96aa76aaSSimon Pilgrim; X64-NOBMI-NEXT:    retq
224*96aa76aaSSimon Pilgrim;
225*96aa76aaSSimon Pilgrim; X64-BMI-LABEL: bitselect_constants_i32:
226*96aa76aaSSimon Pilgrim; X64-BMI:       # %bb.0:
227*96aa76aaSSimon Pilgrim; X64-BMI-NEXT:    movl %edi, %eax
228*96aa76aaSSimon Pilgrim; X64-BMI-NEXT:    notl %eax
229*96aa76aaSSimon Pilgrim; X64-BMI-NEXT:    andl $52, %eax
230*96aa76aaSSimon Pilgrim; X64-BMI-NEXT:    andl $-6553, %edi # imm = 0xE667
231*96aa76aaSSimon Pilgrim; X64-BMI-NEXT:    orl %edi, %eax
232*96aa76aaSSimon Pilgrim; X64-BMI-NEXT:    retq
233*96aa76aaSSimon Pilgrim  %not = xor i32 %m, -1
234*96aa76aaSSimon Pilgrim  %ma = and i32 52, %not
235*96aa76aaSSimon Pilgrim  %mb = and i32 -6553, %m
236*96aa76aaSSimon Pilgrim  %or = or i32 %ma, %mb
237*96aa76aaSSimon Pilgrim  ret i32 %or
238*96aa76aaSSimon Pilgrim}
239