1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2; RUN: llc -mtriple=x86_64-unknown-unknown -mattr=sse2 < %s | FileCheck %s
3
4; PR22428: https://llvm.org/bugs/show_bug.cgi?id=22428
5; f1, f2, f3, and f4 should use an integer logic instruction.
6; f5, f6, f9, and f10 should use an FP (SSE) logic instruction.
7;
8; f7 and f8 are less clear.
9;
10; For f7 and f8, the SSE instructions don't take immediate operands, so if we
11; use one of those, we either have to load a constant from memory or move the
12; scalar immediate value from an integer register over to an SSE register.
13; Optimizing for size may affect that decision. Also, note that there are no
14; scalar versions of the FP logic ops, so if we want to fold a load into a
15; logic op, we have to load or splat a 16-byte vector constant.
16
17; 1 FP operand, 1 int operand, int result
18
19define i32 @f1(float %x, i32 %y) {
20; CHECK-LABEL: f1:
21; CHECK:       # BB#0:
22; CHECK-NEXT:    movd %xmm0, %eax
23; CHECK-NEXT:    andl %edi, %eax
24; CHECK-NEXT:    retq
25;
26  %bc1 = bitcast float %x to i32
27  %and = and i32 %bc1, %y
28  ret i32 %and
29}
30
31; Swap operands of the logic op.
32
33define i32 @f2(float %x, i32 %y) {
34; CHECK-LABEL: f2:
35; CHECK:       # BB#0:
36; CHECK-NEXT:    movd %xmm0, %eax
37; CHECK-NEXT:    andl %edi, %eax
38; CHECK-NEXT:    retq
39;
40  %bc1 = bitcast float %x to i32
41  %and = and i32 %y, %bc1
42  ret i32 %and
43}
44
45; 1 FP operand, 1 constant operand, int result
46
47define i32 @f3(float %x) {
48; CHECK-LABEL: f3:
49; CHECK:       # BB#0:
50; CHECK-NEXT:    movd %xmm0, %eax
51; CHECK-NEXT:    andl $1, %eax
52; CHECK-NEXT:    retq
53;
54  %bc1 = bitcast float %x to i32
55  %and = and i32 %bc1, 1
56  ret i32 %and
57}
58
59; Swap operands of the logic op.
60
61define i32 @f4(float %x) {
62; CHECK-LABEL: f4:
63; CHECK:       # BB#0:
64; CHECK-NEXT:    movd %xmm0, %eax
65; CHECK-NEXT:    andl $2, %eax
66; CHECK-NEXT:    retq
67;
68  %bc1 = bitcast float %x to i32
69  %and = and i32 2, %bc1
70  ret i32 %and
71}
72
73; 1 FP operand, 1 integer operand, FP result
74
75define float @f5(float %x, i32 %y) {
76; CHECK-LABEL: f5:
77; CHECK:       # BB#0:
78; CHECK-NEXT:    movd %edi, %xmm1
79; CHECK-NEXT:    pand %xmm1, %xmm0
80; CHECK-NEXT:    retq
81;
82  %bc1 = bitcast float %x to i32
83  %and = and i32 %bc1, %y
84  %bc2 = bitcast i32 %and to float
85  ret float %bc2
86}
87
88; Swap operands of the logic op.
89
90define float @f6(float %x, i32 %y) {
91; CHECK-LABEL: f6:
92; CHECK:       # BB#0:
93; CHECK-NEXT:    movd %edi, %xmm1
94; CHECK-NEXT:    pand %xmm1, %xmm0
95; CHECK-NEXT:    retq
96;
97  %bc1 = bitcast float %x to i32
98  %and = and i32 %y, %bc1
99  %bc2 = bitcast i32 %and to float
100  ret float %bc2
101}
102
103; 1 FP operand, 1 constant operand, FP result
104
105define float @f7(float %x) {
106; CHECK-LABEL: f7:
107; CHECK:       # BB#0:
108; CHECK-NEXT:    movss {{.*#+}} xmm1 = mem[0],zero,zero,zero
109; CHECK-NEXT:    andps %xmm1, %xmm0
110; CHECK-NEXT:    retq
111;
112  %bc1 = bitcast float %x to i32
113  %and = and i32 %bc1, 3
114  %bc2 = bitcast i32 %and to float
115  ret float %bc2
116}
117
118; Swap operands of the logic op.
119
120define float @f8(float %x) {
121; CHECK-LABEL: f8:
122; CHECK:       # BB#0:
123; CHECK-NEXT:    movss {{.*#+}} xmm1 = mem[0],zero,zero,zero
124; CHECK-NEXT:    andps %xmm1, %xmm0
125; CHECK-NEXT:    retq
126;
127  %bc1 = bitcast float %x to i32
128  %and = and i32 4, %bc1
129  %bc2 = bitcast i32 %and to float
130  ret float %bc2
131}
132
133; 2 FP operands, int result
134
135define i32 @f9(float %x, float %y) {
136; CHECK-LABEL: f9:
137; CHECK:       # BB#0:
138; CHECK-NEXT:    pand %xmm1, %xmm0
139; CHECK-NEXT:    movd %xmm0, %eax
140; CHECK-NEXT:    retq
141;
142  %bc1 = bitcast float %x to i32
143  %bc2 = bitcast float %y to i32
144  %and = and i32 %bc1, %bc2
145  ret i32 %and
146}
147
148; 2 FP operands, FP result
149
150define float @f10(float %x, float %y) {
151; CHECK-LABEL: f10:
152; CHECK:       # BB#0:
153; CHECK-NEXT:    andps %xmm1, %xmm0
154; CHECK-NEXT:    retq
155;
156  %bc1 = bitcast float %x to i32
157  %bc2 = bitcast float %y to i32
158  %and = and i32 %bc1, %bc2
159  %bc3 = bitcast i32 %and to float
160  ret float %bc3
161}
162
163define float @or(float %x, float %y) {
164; CHECK-LABEL: or:
165; CHECK:       # BB#0:
166; CHECK-NEXT:    orps %xmm1, %xmm0
167; CHECK-NEXT:    retq
168;
169  %bc1 = bitcast float %x to i32
170  %bc2 = bitcast float %y to i32
171  %and = or i32 %bc1, %bc2
172  %bc3 = bitcast i32 %and to float
173  ret float %bc3
174}
175
176define float @xor(float %x, float %y) {
177; CHECK-LABEL: xor:
178; CHECK:       # BB#0:
179; CHECK-NEXT:    xorps %xmm1, %xmm0
180; CHECK-NEXT:    retq
181;
182  %bc1 = bitcast float %x to i32
183  %bc2 = bitcast float %y to i32
184  %and = xor i32 %bc1, %bc2
185  %bc3 = bitcast i32 %and to float
186  ret float %bc3
187}
188
189define float @f7_or(float %x) {
190; CHECK-LABEL: f7_or:
191; CHECK:       # BB#0:
192; CHECK-NEXT:    movss {{.*#+}} xmm1 = mem[0],zero,zero,zero
193; CHECK-NEXT:    orps %xmm1, %xmm0
194; CHECK-NEXT:    retq
195;
196  %bc1 = bitcast float %x to i32
197  %and = or i32 %bc1, 3
198  %bc2 = bitcast i32 %and to float
199  ret float %bc2
200}
201
202define float @f7_xor(float %x) {
203; CHECK-LABEL: f7_xor:
204; CHECK:       # BB#0:
205; CHECK-NEXT:    movss {{.*#+}} xmm1 = mem[0],zero,zero,zero
206; CHECK-NEXT:    xorps %xmm1, %xmm0
207; CHECK-NEXT:    retq
208;
209  %bc1 = bitcast float %x to i32
210  %and = xor i32 %bc1, 3
211  %bc2 = bitcast i32 %and to float
212  ret float %bc2
213}
214
215; Make sure that doubles work too.
216
217define double @doubles(double %x, double %y) {
218; CHECK-LABEL: doubles:
219; CHECK:       # BB#0:
220; CHECK-NEXT:    andps %xmm1, %xmm0
221; CHECK-NEXT:    retq
222;
223  %bc1 = bitcast double %x to i64
224  %bc2 = bitcast double %y to i64
225  %and = and i64 %bc1, %bc2
226  %bc3 = bitcast i64 %and to double
227  ret double %bc3
228}
229
230define double @f7_double(double %x) {
231; CHECK-LABEL: f7_double:
232; CHECK:       # BB#0:
233; CHECK-NEXT:    movsd {{.*#+}} xmm1 = mem[0],zero
234; CHECK-NEXT:    andpd %xmm1, %xmm0
235; CHECK-NEXT:    retq
236;
237  %bc1 = bitcast double %x to i64
238  %and = and i64 %bc1, 3
239  %bc2 = bitcast i64 %and to double
240  ret double %bc2
241}
242
243; Grabbing the sign bit is a special case that could be handled
244; by movmskps/movmskpd, but if we're not shifting it over, then
245; a simple FP logic op is cheaper.
246
247define float @movmsk(float %x) {
248; CHECK-LABEL: movmsk:
249; CHECK:       # BB#0:
250; CHECK-NEXT:    movss {{.*#+}} xmm1 = mem[0],zero,zero,zero
251; CHECK-NEXT:    andps %xmm1, %xmm0
252; CHECK-NEXT:    retq
253;
254  %bc1 = bitcast float %x to i32
255  %and = and i32 %bc1, 2147483648
256  %bc2 = bitcast i32 %and to float
257  ret float %bc2
258}
259
260define double @bitcast_fabs(double %x) {
261; CHECK-LABEL: bitcast_fabs:
262; CHECK:       # BB#0:
263; CHECK-NEXT:    andps {{.*}}(%rip), %xmm0
264; CHECK-NEXT:    retq
265;
266  %bc1 = bitcast double %x to i64
267  %and = and i64 %bc1, 9223372036854775807
268  %bc2 = bitcast i64 %and to double
269  ret double %bc2
270}
271
272define float @bitcast_fneg(float %x) {
273; CHECK-LABEL: bitcast_fneg:
274; CHECK:       # BB#0:
275; CHECK-NEXT:    xorps {{.*}}(%rip), %xmm0
276; CHECK-NEXT:    retq
277;
278  %bc1 = bitcast float %x to i32
279  %xor = xor i32 %bc1, 2147483648
280  %bc2 = bitcast i32 %xor to float
281  ret float %bc2
282}
283
284define <2 x double> @bitcast_fabs_vec(<2 x double> %x) {
285; CHECK-LABEL: bitcast_fabs_vec:
286; CHECK:       # BB#0:
287; CHECK-NEXT:    andps {{.*}}(%rip), %xmm0
288; CHECK-NEXT:    retq
289;
290  %bc1 = bitcast <2 x double> %x to <2 x i64>
291  %and = and <2 x i64> %bc1, <i64 9223372036854775807, i64 9223372036854775807>
292  %bc2 = bitcast <2 x i64> %and to <2 x double>
293  ret <2 x double> %bc2
294}
295
296define <4 x float> @bitcast_fneg_vec(<4 x float> %x) {
297; CHECK-LABEL: bitcast_fneg_vec:
298; CHECK:       # BB#0:
299; CHECK-NEXT:    xorps {{.*}}(%rip), %xmm0
300; CHECK-NEXT:    retq
301;
302  %bc1 = bitcast <4 x float> %x to <4 x i32>
303  %xor = xor <4 x i32> %bc1, <i32 2147483648, i32 2147483648, i32 2147483648, i32 2147483648>
304  %bc2 = bitcast <4 x i32> %xor to <4 x float>
305  ret <4 x float> %bc2
306}
307
308