1; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
2; RUN: llc < %s -mtriple=x86_64-unknown-unknown -mattr=+sse2 | FileCheck %s --check-prefix=CHECK --check-prefix=SSE
3; RUN: llc < %s -mtriple=x86_64-unknown-unknown -mattr=+avx  | FileCheck %s --check-prefix=CHECK --check-prefix=AVX
4
5; If the target's divss/divps instructions are substantially
6; slower than rcpss/rcpps with a Newton-Raphson refinement,
7; we should generate the estimate sequence.
8
9; See PR21385 ( http://llvm.org/bugs/show_bug.cgi?id=21385 )
10; for details about the accuracy, speed, and implementation
11; differences of x86 reciprocal estimates.
12
13define float @f32_no_estimate(float %x) #0 {
14; SSE-LABEL: f32_no_estimate:
15; SSE:       # BB#0:
16; SSE-NEXT:    movss {{.*#+}} xmm1 = mem[0],zero,zero,zero
17; SSE-NEXT:    divss %xmm0, %xmm1
18; SSE-NEXT:    movaps %xmm1, %xmm0
19; SSE-NEXT:    retq
20;
21; AVX-LABEL: f32_no_estimate:
22; AVX:       # BB#0:
23; AVX-NEXT:    vmovss {{.*#+}} xmm1 = mem[0],zero,zero,zero
24; AVX-NEXT:    vdivss %xmm0, %xmm1, %xmm0
25; AVX-NEXT:    retq
26  %div = fdiv fast float 1.0, %x
27  ret float %div
28}
29
30define float @f32_one_step(float %x) #1 {
31; SSE-LABEL: f32_one_step:
32; SSE:       # BB#0:
33; SSE-NEXT:    rcpss %xmm0, %xmm2
34; SSE-NEXT:    mulss %xmm2, %xmm0
35; SSE-NEXT:    movss {{.*#+}} xmm1 = mem[0],zero,zero,zero
36; SSE-NEXT:    subss %xmm0, %xmm1
37; SSE-NEXT:    mulss %xmm2, %xmm1
38; SSE-NEXT:    addss %xmm2, %xmm1
39; SSE-NEXT:    movaps %xmm1, %xmm0
40; SSE-NEXT:    retq
41;
42; AVX-LABEL: f32_one_step:
43; AVX:       # BB#0:
44; AVX-NEXT:    vrcpss %xmm0, %xmm0, %xmm1
45; AVX-NEXT:    vmulss %xmm1, %xmm0, %xmm0
46; AVX-NEXT:    vmovss {{.*#+}} xmm2 = mem[0],zero,zero,zero
47; AVX-NEXT:    vsubss %xmm0, %xmm2, %xmm0
48; AVX-NEXT:    vmulss %xmm0, %xmm1, %xmm0
49; AVX-NEXT:    vaddss %xmm0, %xmm1, %xmm0
50; AVX-NEXT:    retq
51  %div = fdiv fast float 1.0, %x
52  ret float %div
53}
54
55define float @f32_two_step(float %x) #2 {
56; SSE-LABEL: f32_two_step:
57; SSE:       # BB#0:
58; SSE-NEXT:    rcpss %xmm0, %xmm2
59; SSE-NEXT:    movaps %xmm0, %xmm3
60; SSE-NEXT:    mulss %xmm2, %xmm3
61; SSE-NEXT:    movss {{.*#+}} xmm1 = mem[0],zero,zero,zero
62; SSE-NEXT:    movaps %xmm1, %xmm4
63; SSE-NEXT:    subss %xmm3, %xmm4
64; SSE-NEXT:    mulss %xmm2, %xmm4
65; SSE-NEXT:    addss %xmm2, %xmm4
66; SSE-NEXT:    mulss %xmm4, %xmm0
67; SSE-NEXT:    subss %xmm0, %xmm1
68; SSE-NEXT:    mulss %xmm4, %xmm1
69; SSE-NEXT:    addss %xmm4, %xmm1
70; SSE-NEXT:    movaps %xmm1, %xmm0
71; SSE-NEXT:    retq
72;
73; AVX-LABEL: f32_two_step:
74; AVX:       # BB#0:
75; AVX-NEXT:    vrcpss %xmm0, %xmm0, %xmm1
76; AVX-NEXT:    vmulss %xmm1, %xmm0, %xmm2
77; AVX-NEXT:    vmovss {{.*#+}} xmm3 = mem[0],zero,zero,zero
78; AVX-NEXT:    vsubss %xmm2, %xmm3, %xmm2
79; AVX-NEXT:    vmulss %xmm2, %xmm1, %xmm2
80; AVX-NEXT:    vaddss %xmm2, %xmm1, %xmm1
81; AVX-NEXT:    vmulss %xmm1, %xmm0, %xmm0
82; AVX-NEXT:    vsubss %xmm0, %xmm3, %xmm0
83; AVX-NEXT:    vmulss %xmm0, %xmm1, %xmm0
84; AVX-NEXT:    vaddss %xmm0, %xmm1, %xmm0
85; AVX-NEXT:    retq
86  %div = fdiv fast float 1.0, %x
87  ret float %div
88}
89
90define <4 x float> @v4f32_no_estimate(<4 x float> %x) #0 {
91; SSE-LABEL: v4f32_no_estimate:
92; SSE:       # BB#0:
93; SSE-NEXT:    movaps {{.*#+}} xmm1 = [1.000000e+00,1.000000e+00,1.000000e+00,1.000000e+00]
94; SSE-NEXT:    divps %xmm0, %xmm1
95; SSE-NEXT:    movaps %xmm1, %xmm0
96; SSE-NEXT:    retq
97;
98; AVX-LABEL: v4f32_no_estimate:
99; AVX:       # BB#0:
100; AVX-NEXT:    vmovaps {{.*#+}} xmm1 = [1.000000e+00,1.000000e+00,1.000000e+00,1.000000e+00]
101; AVX-NEXT:    vdivps %xmm0, %xmm1, %xmm0
102; AVX-NEXT:    retq
103  %div = fdiv fast <4 x float> <float 1.0, float 1.0, float 1.0, float 1.0>, %x
104  ret <4 x float> %div
105}
106
107define <4 x float> @v4f32_one_step(<4 x float> %x) #1 {
108; SSE-LABEL: v4f32_one_step:
109; SSE:       # BB#0:
110; SSE-NEXT:    rcpps %xmm0, %xmm2
111; SSE-NEXT:    mulps %xmm2, %xmm0
112; SSE-NEXT:    movaps {{.*#+}} xmm1 = [1.000000e+00,1.000000e+00,1.000000e+00,1.000000e+00]
113; SSE-NEXT:    subps %xmm0, %xmm1
114; SSE-NEXT:    mulps %xmm2, %xmm1
115; SSE-NEXT:    addps %xmm2, %xmm1
116; SSE-NEXT:    movaps %xmm1, %xmm0
117; SSE-NEXT:    retq
118;
119; AVX-LABEL: v4f32_one_step:
120; AVX:       # BB#0:
121; AVX-NEXT:    vrcpps %xmm0, %xmm1
122; AVX-NEXT:    vmulps %xmm1, %xmm0, %xmm0
123; AVX-NEXT:    vmovaps {{.*#+}} xmm2 = [1.000000e+00,1.000000e+00,1.000000e+00,1.000000e+00]
124; AVX-NEXT:    vsubps %xmm0, %xmm2, %xmm0
125; AVX-NEXT:    vmulps %xmm0, %xmm1, %xmm0
126; AVX-NEXT:    vaddps %xmm0, %xmm1, %xmm0
127; AVX-NEXT:    retq
128  %div = fdiv fast <4 x float> <float 1.0, float 1.0, float 1.0, float 1.0>, %x
129  ret <4 x float> %div
130}
131
132define <4 x float> @v4f32_two_step(<4 x float> %x) #2 {
133; SSE-LABEL: v4f32_two_step:
134; SSE:       # BB#0:
135; SSE-NEXT:    rcpps %xmm0, %xmm2
136; SSE-NEXT:    movaps %xmm0, %xmm3
137; SSE-NEXT:    mulps %xmm2, %xmm3
138; SSE-NEXT:    movaps {{.*#+}} xmm1 = [1.000000e+00,1.000000e+00,1.000000e+00,1.000000e+00]
139; SSE-NEXT:    movaps %xmm1, %xmm4
140; SSE-NEXT:    subps %xmm3, %xmm4
141; SSE-NEXT:    mulps %xmm2, %xmm4
142; SSE-NEXT:    addps %xmm2, %xmm4
143; SSE-NEXT:    mulps %xmm4, %xmm0
144; SSE-NEXT:    subps %xmm0, %xmm1
145; SSE-NEXT:    mulps %xmm4, %xmm1
146; SSE-NEXT:    addps %xmm4, %xmm1
147; SSE-NEXT:    movaps %xmm1, %xmm0
148; SSE-NEXT:    retq
149;
150; AVX-LABEL: v4f32_two_step:
151; AVX:       # BB#0:
152; AVX-NEXT:    vrcpps %xmm0, %xmm1
153; AVX-NEXT:    vmulps %xmm1, %xmm0, %xmm2
154; AVX-NEXT:    vmovaps {{.*#+}} xmm3 = [1.000000e+00,1.000000e+00,1.000000e+00,1.000000e+00]
155; AVX-NEXT:    vsubps %xmm2, %xmm3, %xmm2
156; AVX-NEXT:    vmulps %xmm2, %xmm1, %xmm2
157; AVX-NEXT:    vaddps %xmm2, %xmm1, %xmm1
158; AVX-NEXT:    vmulps %xmm1, %xmm0, %xmm0
159; AVX-NEXT:    vsubps %xmm0, %xmm3, %xmm0
160; AVX-NEXT:    vmulps %xmm0, %xmm1, %xmm0
161; AVX-NEXT:    vaddps %xmm0, %xmm1, %xmm0
162; AVX-NEXT:    retq
163  %div = fdiv fast <4 x float> <float 1.0, float 1.0, float 1.0, float 1.0>, %x
164  ret <4 x float> %div
165}
166
167define <8 x float> @v8f32_no_estimate(<8 x float> %x) #0 {
168; SSE-LABEL: v8f32_no_estimate:
169; SSE:       # BB#0:
170; SSE-NEXT:    movaps {{.*#+}} xmm2 = [1.000000e+00,1.000000e+00,1.000000e+00,1.000000e+00]
171; SSE-NEXT:    movaps %xmm2, %xmm3
172; SSE-NEXT:    divps %xmm0, %xmm3
173; SSE-NEXT:    divps %xmm1, %xmm2
174; SSE-NEXT:    movaps %xmm3, %xmm0
175; SSE-NEXT:    movaps %xmm2, %xmm1
176; SSE-NEXT:    retq
177;
178; AVX-LABEL: v8f32_no_estimate:
179; AVX:       # BB#0:
180; AVX-NEXT:    vmovaps {{.*#+}} ymm1 = [1.000000e+00,1.000000e+00,1.000000e+00,1.000000e+00,1.000000e+00,1.000000e+00,1.000000e+00,1.000000e+00]
181; AVX-NEXT:    vdivps %ymm0, %ymm1, %ymm0
182; AVX-NEXT:    retq
183  %div = fdiv fast <8 x float> <float 1.0, float 1.0, float 1.0, float 1.0, float 1.0, float 1.0, float 1.0, float 1.0>, %x
184  ret <8 x float> %div
185}
186
187define <8 x float> @v8f32_one_step(<8 x float> %x) #1 {
188; SSE-LABEL: v8f32_one_step:
189; SSE:       # BB#0:
190; SSE-NEXT:    rcpps %xmm0, %xmm4
191; SSE-NEXT:    mulps %xmm4, %xmm0
192; SSE-NEXT:    movaps {{.*#+}} xmm2 = [1.000000e+00,1.000000e+00,1.000000e+00,1.000000e+00]
193; SSE-NEXT:    movaps %xmm2, %xmm3
194; SSE-NEXT:    subps %xmm0, %xmm3
195; SSE-NEXT:    mulps %xmm4, %xmm3
196; SSE-NEXT:    addps %xmm4, %xmm3
197; SSE-NEXT:    rcpps %xmm1, %xmm0
198; SSE-NEXT:    mulps %xmm0, %xmm1
199; SSE-NEXT:    subps %xmm1, %xmm2
200; SSE-NEXT:    mulps %xmm0, %xmm2
201; SSE-NEXT:    addps %xmm0, %xmm2
202; SSE-NEXT:    movaps %xmm3, %xmm0
203; SSE-NEXT:    movaps %xmm2, %xmm1
204; SSE-NEXT:    retq
205;
206; AVX-LABEL: v8f32_one_step:
207; AVX:       # BB#0:
208; AVX-NEXT:    vrcpps %ymm0, %ymm1
209; AVX-NEXT:    vmulps %ymm1, %ymm0, %ymm0
210; AVX-NEXT:    vmovaps {{.*#+}} ymm2 = [1.000000e+00,1.000000e+00,1.000000e+00,1.000000e+00,1.000000e+00,1.000000e+00,1.000000e+00,1.000000e+00]
211; AVX-NEXT:    vsubps %ymm0, %ymm2, %ymm0
212; AVX-NEXT:    vmulps %ymm0, %ymm1, %ymm0
213; AVX-NEXT:    vaddps %ymm0, %ymm1, %ymm0
214; AVX-NEXT:    retq
215  %div = fdiv fast <8 x float> <float 1.0, float 1.0, float 1.0, float 1.0, float 1.0, float 1.0, float 1.0, float 1.0>, %x
216  ret <8 x float> %div
217}
218
219define <8 x float> @v8f32_two_step(<8 x float> %x) #2 {
220; SSE-LABEL: v8f32_two_step:
221; SSE:       # BB#0:
222; SSE-NEXT:    movaps %xmm1, %xmm2
223; SSE-NEXT:    rcpps %xmm0, %xmm3
224; SSE-NEXT:    movaps %xmm0, %xmm4
225; SSE-NEXT:    mulps %xmm3, %xmm4
226; SSE-NEXT:    movaps {{.*#+}} xmm1 = [1.000000e+00,1.000000e+00,1.000000e+00,1.000000e+00]
227; SSE-NEXT:    movaps %xmm1, %xmm5
228; SSE-NEXT:    subps %xmm4, %xmm5
229; SSE-NEXT:    mulps %xmm3, %xmm5
230; SSE-NEXT:    addps %xmm3, %xmm5
231; SSE-NEXT:    mulps %xmm5, %xmm0
232; SSE-NEXT:    movaps %xmm1, %xmm3
233; SSE-NEXT:    subps %xmm0, %xmm3
234; SSE-NEXT:    mulps %xmm5, %xmm3
235; SSE-NEXT:    addps %xmm5, %xmm3
236; SSE-NEXT:    rcpps %xmm2, %xmm0
237; SSE-NEXT:    movaps %xmm2, %xmm4
238; SSE-NEXT:    mulps %xmm0, %xmm4
239; SSE-NEXT:    movaps %xmm1, %xmm5
240; SSE-NEXT:    subps %xmm4, %xmm5
241; SSE-NEXT:    mulps %xmm0, %xmm5
242; SSE-NEXT:    addps %xmm0, %xmm5
243; SSE-NEXT:    mulps %xmm5, %xmm2
244; SSE-NEXT:    subps %xmm2, %xmm1
245; SSE-NEXT:    mulps %xmm5, %xmm1
246; SSE-NEXT:    addps %xmm5, %xmm1
247; SSE-NEXT:    movaps %xmm3, %xmm0
248; SSE-NEXT:    retq
249;
250; AVX-LABEL: v8f32_two_step:
251; AVX:       # BB#0:
252; AVX-NEXT:    vrcpps %ymm0, %ymm1
253; AVX-NEXT:    vmulps %ymm1, %ymm0, %ymm2
254; AVX-NEXT:    vmovaps {{.*#+}} ymm3 = [1.000000e+00,1.000000e+00,1.000000e+00,1.000000e+00,1.000000e+00,1.000000e+00,1.000000e+00,1.000000e+00]
255; AVX-NEXT:    vsubps %ymm2, %ymm3, %ymm2
256; AVX-NEXT:    vmulps %ymm2, %ymm1, %ymm2
257; AVX-NEXT:    vaddps %ymm2, %ymm1, %ymm1
258; AVX-NEXT:    vmulps %ymm1, %ymm0, %ymm0
259; AVX-NEXT:    vsubps %ymm0, %ymm3, %ymm0
260; AVX-NEXT:    vmulps %ymm0, %ymm1, %ymm0
261; AVX-NEXT:    vaddps %ymm0, %ymm1, %ymm0
262; AVX-NEXT:    retq
263  %div = fdiv fast <8 x float> <float 1.0, float 1.0, float 1.0, float 1.0, float 1.0, float 1.0, float 1.0, float 1.0>, %x
264  ret <8 x float> %div
265}
266
267attributes #0 = { "unsafe-fp-math"="true" "reciprocal-estimates"="!divf,!vec-divf" }
268attributes #1 = { "unsafe-fp-math"="true" "reciprocal-estimates"="divf,vec-divf" }
269attributes #2 = { "unsafe-fp-math"="true" "reciprocal-estimates"="divf:2,vec-divf:2" }
270
271