1; RUN: llc -verify-machineinstrs < %s -mtriple=powerpc64-unknown-linux-gnu -mcpu=pwr7 -mattr=-vsx | FileCheck %s
2
3target datalayout = "E-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-f128:128:128-v128:128:128-n32:64"
4target triple = "powerpc64-unknown-linux-gnu"
5
6declare double @llvm.sqrt.f64(double)
7declare float @llvm.sqrt.f32(float)
8declare <4 x float> @llvm.sqrt.v4f32(<4 x float>)
9
10define double @foo_fmf(double %a, double %b) nounwind {
11; CHECK: @foo_fmf
12; CHECK: frsqrte
13; CHECK: fmul
14; CHECK-NEXT: fmadd
15; CHECK-NEXT: fmul
16; CHECK-NEXT: fmul
17; CHECK-NEXT: fmul
18; CHECK-NEXT: fmadd
19; CHECK-NEXT: fmul
20; CHECK-NEXT: fmul
21; CHECK-NEXT: fmul
22; CHECK: blr
23  %x = call fast double @llvm.sqrt.f64(double %b)
24  %r = fdiv fast double %a, %x
25  ret double %r
26}
27
28define double @foo_safe(double %a, double %b) nounwind {
29; CHECK: @foo_safe
30; CHECK: fsqrt
31; CHECK: fdiv
32; CHECK: blr
33  %x = call double @llvm.sqrt.f64(double %b)
34  %r = fdiv double %a, %x
35  ret double %r
36}
37
38define double @no_estimate_refinement_f64(double %a, double %b) #0 {
39; CHECK-LABEL: @no_estimate_refinement_f64
40; CHECK: frsqrte
41; CHECK-NOT: fmadd
42; CHECK: fmul
43; CHECK-NOT: fmadd
44; CHECK: blr
45  %x = call fast double @llvm.sqrt.f64(double %b)
46  %r = fdiv fast double %a, %x
47  ret double %r
48}
49
50define double @foof_fmf(double %a, float %b) nounwind {
51; CHECK: @foof_fmf
52; CHECK-DAG: frsqrtes
53; CHECK: fmuls
54; CHECK-NEXT: fmadds
55; CHECK-NEXT: fmuls
56; CHECK-NEXT: fmuls
57; CHECK-NEXT: fmul
58; CHECK-NEXT: blr
59  %x = call fast float @llvm.sqrt.f32(float %b)
60  %y = fpext float %x to double
61  %r = fdiv fast double %a, %y
62  ret double %r
63}
64
65define double @foof_safe(double %a, float %b) nounwind {
66; CHECK: @foof_safe
67; CHECK: fsqrts
68; CHECK: fdiv
69; CHECK: blr
70  %x = call float @llvm.sqrt.f32(float %b)
71  %y = fpext float %x to double
72  %r = fdiv double %a, %y
73  ret double %r
74}
75
76define float @food_fmf(float %a, double %b) nounwind {
77; CHECK: @food_fmf
78; CHECK-DAG: frsqrte
79; CHECK: fmul
80; CHECK-NEXT: fmadd
81; CHECK-NEXT: fmul
82; CHECK-NEXT: fmul
83; CHECK-NEXT: fmul
84; CHECK-NEXT: fmadd
85; CHECK-NEXT: fmul
86; CHECK-NEXT: fmul
87; CHECK-NEXT: frsp
88; CHECK-NEXT: fmuls
89; CHECK-NEXT: blr
90  %x = call fast double @llvm.sqrt.f64(double %b)
91  %y = fptrunc double %x to float
92  %r = fdiv fast float %a, %y
93  ret float %r
94}
95
96define float @food_safe(float %a, double %b) nounwind {
97; CHECK: @food_safe
98; CHECK: fsqrt
99; CHECK: fdivs
100; CHECK: blr
101  %x = call double @llvm.sqrt.f64(double %b)
102  %y = fptrunc double %x to float
103  %r = fdiv float %a, %y
104  ret float %r
105}
106
107define float @goo_fmf(float %a, float %b) nounwind {
108; CHECK: @goo_fmf
109; CHECK-DAG: frsqrtes
110; CHECK: fmuls
111; CHECK-NEXT: fmadds
112; CHECK-NEXT: fmuls
113; CHECK-NEXT: fmuls
114; CHECK-NEXT: fmuls
115; CHECK-NEXT: blr
116  %x = call fast float @llvm.sqrt.f32(float %b)
117  %r = fdiv fast float %a, %x
118  ret float %r
119}
120
121define float @goo_safe(float %a, float %b) nounwind {
122; CHECK: @goo_safe
123; CHECK: fsqrts
124; CHECK: fdivs
125; CHECK: blr
126  %x = call float @llvm.sqrt.f32(float %b)
127  %r = fdiv float %a, %x
128  ret float %r
129}
130
131define float @no_estimate_refinement_f32(float %a, float %b) #0 {
132; CHECK-LABEL: @no_estimate_refinement_f32
133; CHECK: frsqrtes
134; CHECK-NOT: fmadds
135; CHECK: fmuls
136; CHECK-NOT: fmadds
137; CHECK: blr
138  %x = call fast float @llvm.sqrt.f32(float %b)
139  %r = fdiv fast float %a, %x
140  ret float %r
141}
142
143; Recognize that this is rsqrt(a) * rcp(b) * c,
144; not 1 / ( 1 / sqrt(a)) * rcp(b) * c.
145define float @rsqrt_fmul_fmf(float %a, float %b, float %c) {
146; CHECK: @rsqrt_fmul_fmf
147; CHECK-DAG: frsqrtes
148; CHECK-DAG: fres
149; CHECK-DAG: fnmsubs
150; CHECK-DAG: fmuls
151; CHECK-DAG: fmadds
152; CHECK-DAG: fmadds
153; CHECK: fmuls
154; CHECK-NEXT: fmuls
155; CHECK-NEXT: fmuls
156; CHECK-NEXT: blr
157  %x = call fast float @llvm.sqrt.f32(float %a)
158  %y = fmul fast float %x, %b
159  %z = fdiv fast float %c, %y
160  ret float %z
161}
162
163; Recognize that this is rsqrt(a) * rcp(b) * c,
164; not 1 / ( 1 / sqrt(a)) * rcp(b) * c.
165define float @rsqrt_fmul_safe(float %a, float %b, float %c) {
166; CHECK: @rsqrt_fmul_safe
167; CHECK: fsqrts
168; CHECK: fmuls
169; CHECK: fdivs
170; CHECK: blr
171  %x = call float @llvm.sqrt.f32(float %a)
172  %y = fmul float %x, %b
173  %z = fdiv float %c, %y
174  ret float %z
175}
176
177define <4 x float> @hoo_fmf(<4 x float> %a, <4 x float> %b) nounwind {
178; CHECK: @hoo_fmf
179; CHECK: vrsqrtefp
180  %x = call fast <4 x float> @llvm.sqrt.v4f32(<4 x float> %b)
181  %r = fdiv fast <4 x float> %a, %x
182  ret <4 x float> %r
183}
184
185define <4 x float> @hoo_safe(<4 x float> %a, <4 x float> %b) nounwind {
186; CHECK: @hoo_safe
187; CHECK-NOT: vrsqrtefp
188; CHECK: blr
189  %x = call <4 x float> @llvm.sqrt.v4f32(<4 x float> %b)
190  %r = fdiv <4 x float> %a, %x
191  ret <4 x float> %r
192}
193
194define double @foo2_fmf(double %a, double %b) nounwind {
195; CHECK: @foo2_fmf
196; CHECK-DAG: fre
197; CHECK-DAG: fnmsub
198; CHECK: fmadd
199; CHECK-NEXT: fnmsub
200; CHECK-NEXT: fmadd
201; CHECK-NEXT: fmul
202; CHECK-NEXT: blr
203  %r = fdiv fast double %a, %b
204  ret double %r
205}
206
207define double @foo2_safe(double %a, double %b) nounwind {
208; CHECK: @foo2_safe
209; CHECK: fdiv
210; CHECK: blr
211  %r = fdiv double %a, %b
212  ret double %r
213}
214
215define float @goo2_fmf(float %a, float %b) nounwind {
216; CHECK: @goo2_fmf
217; CHECK-DAG: fres
218; CHECK-DAG: fnmsubs
219; CHECK: fmadds
220; CHECK-NEXT: fmuls
221; CHECK-NEXT: blr
222  %r = fdiv fast float %a, %b
223  ret float %r
224}
225
226define float @goo2_safe(float %a, float %b) nounwind {
227; CHECK: @goo2_safe
228; CHECK: fdivs
229; CHECK: blr
230  %r = fdiv float %a, %b
231  ret float %r
232}
233
234define <4 x float> @hoo2_fmf(<4 x float> %a, <4 x float> %b) nounwind {
235; CHECK: @hoo2_fmf
236; CHECK: vrefp
237  %r = fdiv fast <4 x float> %a, %b
238  ret <4 x float> %r
239}
240
241define <4 x float> @hoo2_safe(<4 x float> %a, <4 x float> %b) nounwind {
242; CHECK: @hoo2_safe
243; CHECK-NOT: vrefp
244; CHECK: blr
245  %r = fdiv <4 x float> %a, %b
246  ret <4 x float> %r
247}
248
249define double @foo3_fmf(double %a) nounwind {
250; CHECK: @foo3_fmf
251; CHECK: fcmpu
252; CHECK-DAG: frsqrte
253; CHECK: fmul
254; CHECK-NEXT: fmadd
255; CHECK-NEXT: fmul
256; CHECK-NEXT: fmul
257; CHECK-NEXT: fmul
258; CHECK-NEXT: fmadd
259; CHECK-NEXT: fmul
260; CHECK-NEXT: fmul
261; CHECK: blr
262  %r = call fast double @llvm.sqrt.f64(double %a)
263  ret double %r
264}
265
266define double @foo3_safe(double %a) nounwind {
267; CHECK: @foo3_safe
268; CHECK: fsqrt
269; CHECK: blr
270  %r = call double @llvm.sqrt.f64(double %a)
271  ret double %r
272}
273
274define float @goo3_fmf(float %a) nounwind {
275; CHECK: @goo3_fmf
276; CHECK: fcmpu
277; CHECK-DAG: frsqrtes
278; CHECK: fmuls
279; CHECK-NEXT: fmadds
280; CHECK-NEXT: fmuls
281; CHECK-NEXT: fmuls
282; CHECK: blr
283  %r = call fast float @llvm.sqrt.f32(float %a)
284  ret float %r
285}
286
287define float @goo3_safe(float %a) nounwind {
288; CHECK: @goo3_safe
289; CHECK: fsqrts
290; CHECK: blr
291  %r = call float @llvm.sqrt.f32(float %a)
292  ret float %r
293}
294
295define <4 x float> @hoo3_fmf(<4 x float> %a) nounwind {
296; CHECK: @hoo3_fmf
297; CHECK: vrsqrtefp
298; CHECK-DAG: vcmpeqfp
299  %r = call fast <4 x float> @llvm.sqrt.v4f32(<4 x float> %a)
300  ret <4 x float> %r
301}
302
303define <4 x float> @hoo3_safe(<4 x float> %a) nounwind {
304; CHECK: @hoo3_safe
305; CHECK-NOT: vrsqrtefp
306; CHECK: blr
307  %r = call <4 x float> @llvm.sqrt.v4f32(<4 x float> %a)
308  ret <4 x float> %r
309}
310
311attributes #0 = { nounwind "reciprocal-estimates"="sqrtf:0,sqrtd:0" }
312