blob: 40bab00e1abca9ea112d9faa30887767bdc2bbf6 [file] [log] [blame]
Sanjay Patelaaf43042016-11-15 23:09:53 +00001; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
Sanjay Patelbab5d6c2015-09-20 15:58:00 +00002; 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; f9 and f10 should use an FP (SSE) logic instruction.
7;
8; f5, f6, f7, and f8 are less clear.
9;
10; For f5 and f6, we can save a register move by using an FP logic instruction,
Sanjay Patelaaf43042016-11-15 23:09:53 +000011; but we may need to calculate the relative costs of an SSE op vs. int op vs.
Sanjay Patelbab5d6c2015-09-20 15:58:00 +000012; scalar <-> SSE register moves.
13;
14; For f7 and f8, the SSE instructions don't take immediate operands, so if we
15; use one of those, we either have to load a constant from memory or move the
16; scalar immediate value from an integer register over to an SSE register.
17; Optimizing for size may affect that decision. Also, note that there are no
18; scalar versions of the FP logic ops, so if we want to fold a load into a
19; logic op, we have to load or splat a 16-byte vector constant.
20
21; 1 FP operand, 1 int operand, int result
22
23define i32 @f1(float %x, i32 %y) {
24; CHECK-LABEL: f1:
25; CHECK: # BB#0:
26; CHECK-NEXT: movd %xmm0, %eax
27; CHECK-NEXT: andl %edi, %eax
28; CHECK-NEXT: retq
Sanjay Patelaaf43042016-11-15 23:09:53 +000029;
Sanjay Patelbab5d6c2015-09-20 15:58:00 +000030 %bc1 = bitcast float %x to i32
31 %and = and i32 %bc1, %y
32 ret i32 %and
33}
34
35; Swap operands of the logic op.
36
37define i32 @f2(float %x, i32 %y) {
38; CHECK-LABEL: f2:
39; CHECK: # BB#0:
40; CHECK-NEXT: movd %xmm0, %eax
41; CHECK-NEXT: andl %edi, %eax
42; CHECK-NEXT: retq
Sanjay Patelaaf43042016-11-15 23:09:53 +000043;
Sanjay Patelbab5d6c2015-09-20 15:58:00 +000044 %bc1 = bitcast float %x to i32
45 %and = and i32 %y, %bc1
46 ret i32 %and
47}
48
49; 1 FP operand, 1 constant operand, int result
50
51define i32 @f3(float %x) {
52; CHECK-LABEL: f3:
53; CHECK: # BB#0:
54; CHECK-NEXT: movd %xmm0, %eax
55; CHECK-NEXT: andl $1, %eax
56; CHECK-NEXT: retq
Sanjay Patelaaf43042016-11-15 23:09:53 +000057;
Sanjay Patelbab5d6c2015-09-20 15:58:00 +000058 %bc1 = bitcast float %x to i32
59 %and = and i32 %bc1, 1
60 ret i32 %and
61}
62
63; Swap operands of the logic op.
64
65define i32 @f4(float %x) {
66; CHECK-LABEL: f4:
67; CHECK: # BB#0:
68; CHECK-NEXT: movd %xmm0, %eax
69; CHECK-NEXT: andl $2, %eax
70; CHECK-NEXT: retq
Sanjay Patelaaf43042016-11-15 23:09:53 +000071;
Sanjay Patelbab5d6c2015-09-20 15:58:00 +000072 %bc1 = bitcast float %x to i32
73 %and = and i32 2, %bc1
74 ret i32 %and
75}
76
77; 1 FP operand, 1 integer operand, FP result
78
79define float @f5(float %x, i32 %y) {
80; CHECK-LABEL: f5:
81; CHECK: # BB#0:
82; CHECK-NEXT: movd %xmm0, %eax
83; CHECK-NEXT: andl %edi, %eax
84; CHECK-NEXT: movd %eax, %xmm0
85; CHECK-NEXT: retq
Sanjay Patelaaf43042016-11-15 23:09:53 +000086;
Sanjay Patelbab5d6c2015-09-20 15:58:00 +000087 %bc1 = bitcast float %x to i32
88 %and = and i32 %bc1, %y
89 %bc2 = bitcast i32 %and to float
90 ret float %bc2
91}
92
93; Swap operands of the logic op.
94
95define float @f6(float %x, i32 %y) {
96; CHECK-LABEL: f6:
97; CHECK: # BB#0:
98; CHECK-NEXT: movd %xmm0, %eax
99; CHECK-NEXT: andl %edi, %eax
100; CHECK-NEXT: movd %eax, %xmm0
101; CHECK-NEXT: retq
Sanjay Patelaaf43042016-11-15 23:09:53 +0000102;
Sanjay Patelbab5d6c2015-09-20 15:58:00 +0000103 %bc1 = bitcast float %x to i32
104 %and = and i32 %y, %bc1
105 %bc2 = bitcast i32 %and to float
106 ret float %bc2
107}
108
109; 1 FP operand, 1 constant operand, FP result
110
111define float @f7(float %x) {
112; CHECK-LABEL: f7:
113; CHECK: # BB#0:
Sanjay Patel309c4f92015-10-27 01:28:07 +0000114; CHECK-NEXT: movss {{.*#+}} xmm1 = mem[0],zero,zero,zero
115; CHECK-NEXT: andps %xmm1, %xmm0
Sanjay Patelbab5d6c2015-09-20 15:58:00 +0000116; CHECK-NEXT: retq
Sanjay Patelaaf43042016-11-15 23:09:53 +0000117;
Sanjay Patelbab5d6c2015-09-20 15:58:00 +0000118 %bc1 = bitcast float %x to i32
119 %and = and i32 %bc1, 3
120 %bc2 = bitcast i32 %and to float
121 ret float %bc2
122}
123
124; Swap operands of the logic op.
125
126define float @f8(float %x) {
127; CHECK-LABEL: f8:
128; CHECK: # BB#0:
Sanjay Patel309c4f92015-10-27 01:28:07 +0000129; CHECK-NEXT: movss {{.*#+}} xmm1 = mem[0],zero,zero,zero
130; CHECK-NEXT: andps %xmm1, %xmm0
Sanjay Patelbab5d6c2015-09-20 15:58:00 +0000131; CHECK-NEXT: retq
Sanjay Patelaaf43042016-11-15 23:09:53 +0000132;
Sanjay Patelbab5d6c2015-09-20 15:58:00 +0000133 %bc1 = bitcast float %x to i32
134 %and = and i32 4, %bc1
135 %bc2 = bitcast i32 %and to float
136 ret float %bc2
137}
138
139; 2 FP operands, int result
140
141define i32 @f9(float %x, float %y) {
142; CHECK-LABEL: f9:
143; CHECK: # BB#0:
Sanjay Pateldf2495f2015-09-23 17:00:06 +0000144; CHECK-NEXT: andps %xmm1, %xmm0
145; CHECK-NEXT: movd %xmm0, %eax
Sanjay Patelbab5d6c2015-09-20 15:58:00 +0000146; CHECK-NEXT: retq
Sanjay Patelaaf43042016-11-15 23:09:53 +0000147;
Sanjay Patelbab5d6c2015-09-20 15:58:00 +0000148 %bc1 = bitcast float %x to i32
149 %bc2 = bitcast float %y to i32
150 %and = and i32 %bc1, %bc2
151 ret i32 %and
152}
153
154; 2 FP operands, FP result
155
156define float @f10(float %x, float %y) {
157; CHECK-LABEL: f10:
158; CHECK: # BB#0:
Sanjay Pateldf2495f2015-09-23 17:00:06 +0000159; CHECK-NEXT: andps %xmm1, %xmm0
Sanjay Patelbab5d6c2015-09-20 15:58:00 +0000160; CHECK-NEXT: retq
Sanjay Patelaaf43042016-11-15 23:09:53 +0000161;
Sanjay Patelbab5d6c2015-09-20 15:58:00 +0000162 %bc1 = bitcast float %x to i32
163 %bc2 = bitcast float %y to i32
164 %and = and i32 %bc1, %bc2
165 %bc3 = bitcast i32 %and to float
166 ret float %bc3
167}
168
169define float @or(float %x, float %y) {
170; CHECK-LABEL: or:
171; CHECK: # BB#0:
Sanjay Patelaba37552015-09-23 18:19:07 +0000172; CHECK-NEXT: orps %xmm1, %xmm0
Sanjay Patelbab5d6c2015-09-20 15:58:00 +0000173; CHECK-NEXT: retq
Sanjay Patelaaf43042016-11-15 23:09:53 +0000174;
Sanjay Patelbab5d6c2015-09-20 15:58:00 +0000175 %bc1 = bitcast float %x to i32
176 %bc2 = bitcast float %y to i32
177 %and = or i32 %bc1, %bc2
178 %bc3 = bitcast i32 %and to float
179 ret float %bc3
180}
181
182define float @xor(float %x, float %y) {
183; CHECK-LABEL: xor:
184; CHECK: # BB#0:
Sanjay Patel1a653462015-09-23 18:33:42 +0000185; CHECK-NEXT: xorps %xmm1, %xmm0
Sanjay Patelbab5d6c2015-09-20 15:58:00 +0000186; CHECK-NEXT: retq
Sanjay Patelaaf43042016-11-15 23:09:53 +0000187;
Sanjay Patelbab5d6c2015-09-20 15:58:00 +0000188 %bc1 = bitcast float %x to i32
189 %bc2 = bitcast float %y to i32
190 %and = xor i32 %bc1, %bc2
191 %bc3 = bitcast i32 %and to float
192 ret float %bc3
193}
194
Sanjay Patel28d15982015-10-26 23:52:42 +0000195define float @f7_or(float %x) {
196; CHECK-LABEL: f7_or:
197; CHECK: # BB#0:
Sanjay Patel309c4f92015-10-27 01:28:07 +0000198; CHECK-NEXT: movss {{.*#+}} xmm1 = mem[0],zero,zero,zero
199; CHECK-NEXT: orps %xmm1, %xmm0
Sanjay Patel28d15982015-10-26 23:52:42 +0000200; CHECK-NEXT: retq
Sanjay Patelaaf43042016-11-15 23:09:53 +0000201;
Sanjay Patel28d15982015-10-26 23:52:42 +0000202 %bc1 = bitcast float %x to i32
203 %and = or i32 %bc1, 3
204 %bc2 = bitcast i32 %and to float
205 ret float %bc2
206}
207
208define float @f7_xor(float %x) {
209; CHECK-LABEL: f7_xor:
210; CHECK: # BB#0:
Sanjay Patel309c4f92015-10-27 01:28:07 +0000211; CHECK-NEXT: movss {{.*#+}} xmm1 = mem[0],zero,zero,zero
212; CHECK-NEXT: xorps %xmm1, %xmm0
Sanjay Patel28d15982015-10-26 23:52:42 +0000213; CHECK-NEXT: retq
Sanjay Patelaaf43042016-11-15 23:09:53 +0000214;
Sanjay Patel28d15982015-10-26 23:52:42 +0000215 %bc1 = bitcast float %x to i32
216 %and = xor i32 %bc1, 3
217 %bc2 = bitcast i32 %and to float
218 ret float %bc2
219}
220
Sanjay Patelbab5d6c2015-09-20 15:58:00 +0000221; Make sure that doubles work too.
222
223define double @doubles(double %x, double %y) {
224; CHECK-LABEL: doubles:
225; CHECK: # BB#0:
Sanjay Pateldf2495f2015-09-23 17:00:06 +0000226; CHECK-NEXT: andpd %xmm1, %xmm0
Sanjay Patelbab5d6c2015-09-20 15:58:00 +0000227; CHECK-NEXT: retq
Sanjay Patelaaf43042016-11-15 23:09:53 +0000228;
Sanjay Patelbab5d6c2015-09-20 15:58:00 +0000229 %bc1 = bitcast double %x to i64
230 %bc2 = bitcast double %y to i64
231 %and = and i64 %bc1, %bc2
232 %bc3 = bitcast i64 %and to double
233 ret double %bc3
234}
235
Sanjay Patel28d15982015-10-26 23:52:42 +0000236define double @f7_double(double %x) {
237; CHECK-LABEL: f7_double:
238; CHECK: # BB#0:
Sanjay Patel309c4f92015-10-27 01:28:07 +0000239; CHECK-NEXT: movsd {{.*#+}} xmm1 = mem[0],zero
240; CHECK-NEXT: andpd %xmm1, %xmm0
Sanjay Patel28d15982015-10-26 23:52:42 +0000241; CHECK-NEXT: retq
Sanjay Patelaaf43042016-11-15 23:09:53 +0000242;
Sanjay Patel28d15982015-10-26 23:52:42 +0000243 %bc1 = bitcast double %x to i64
244 %and = and i64 %bc1, 3
245 %bc2 = bitcast i64 %and to double
246 ret double %bc2
247}
248
249; Grabbing the sign bit is a special case that could be handled
250; by movmskps/movmskpd, but if we're not shifting it over, then
251; a simple FP logic op is cheaper.
252
253define float @movmsk(float %x) {
254; CHECK-LABEL: movmsk:
255; CHECK: # BB#0:
Sanjay Patel309c4f92015-10-27 01:28:07 +0000256; CHECK-NEXT: movss {{.*#+}} xmm1 = mem[0],zero,zero,zero
257; CHECK-NEXT: andps %xmm1, %xmm0
Sanjay Patel28d15982015-10-26 23:52:42 +0000258; CHECK-NEXT: retq
Sanjay Patelaaf43042016-11-15 23:09:53 +0000259;
Sanjay Patel28d15982015-10-26 23:52:42 +0000260 %bc1 = bitcast float %x to i32
261 %and = and i32 %bc1, 2147483648
262 %bc2 = bitcast i32 %and to float
263 ret float %bc2
264}
265
Sanjay Patel13d57b92016-05-04 19:06:03 +0000266define double @bitcast_fabs(double %x) {
267; CHECK-LABEL: bitcast_fabs:
268; CHECK: # BB#0:
Craig Topper9bd62412016-08-09 03:06:33 +0000269; CHECK-NEXT: andps {{.*}}(%rip), %xmm0
Sanjay Patel13d57b92016-05-04 19:06:03 +0000270; CHECK-NEXT: retq
271;
272 %bc1 = bitcast double %x to i64
273 %and = and i64 %bc1, 9223372036854775807
274 %bc2 = bitcast i64 %and to double
275 ret double %bc2
276}
277
278define float @bitcast_fneg(float %x) {
279; CHECK-LABEL: bitcast_fneg:
280; CHECK: # BB#0:
Sanjay Patelb114fd62016-06-10 20:33:50 +0000281; CHECK-NEXT: xorps {{.*}}(%rip), %xmm0
Sanjay Patel13d57b92016-05-04 19:06:03 +0000282; CHECK-NEXT: retq
283;
284 %bc1 = bitcast float %x to i32
285 %xor = xor i32 %bc1, 2147483648
286 %bc2 = bitcast i32 %xor to float
287 ret float %bc2
288}
289
290define <2 x double> @bitcast_fabs_vec(<2 x double> %x) {
291; CHECK-LABEL: bitcast_fabs_vec:
292; CHECK: # BB#0:
293; CHECK-NEXT: andps {{.*}}(%rip), %xmm0
294; CHECK-NEXT: retq
295;
296 %bc1 = bitcast <2 x double> %x to <2 x i64>
297 %and = and <2 x i64> %bc1, <i64 9223372036854775807, i64 9223372036854775807>
298 %bc2 = bitcast <2 x i64> %and to <2 x double>
299 ret <2 x double> %bc2
300}
301
302define <4 x float> @bitcast_fneg_vec(<4 x float> %x) {
303; CHECK-LABEL: bitcast_fneg_vec:
304; CHECK: # BB#0:
305; CHECK-NEXT: xorps {{.*}}(%rip), %xmm0
306; CHECK-NEXT: retq
307;
308 %bc1 = bitcast <4 x float> %x to <4 x i32>
309 %xor = xor <4 x i32> %bc1, <i32 2147483648, i32 2147483648, i32 2147483648, i32 2147483648>
310 %bc2 = bitcast <4 x i32> %xor to <4 x float>
311 ret <4 x float> %bc2
312}
313