• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2; RUN: opt < %s -instcombine -S | FileCheck %s
3
4target 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-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64-S128"
5target triple = "x86_64-unknown-linux-gnu"
6
7; Check for and against shrinkage when using the
8; unsafe-fp-math function attribute on a math lib
9; function. This optimization may be overridden by
10; the -enable-double-float-shrink option.
11; PR17850: http://llvm.org/bugs/show_bug.cgi?id=17850
12
13define float @acos_test1(float %f)   {
14; CHECK-LABEL: @acos_test1(
15; CHECK-NEXT:    [[ACOSF:%.*]] = call fast float @acosf(float [[F:%.*]])
16; CHECK-NEXT:    ret float [[ACOSF]]
17;
18  %conv = fpext float %f to double
19  %call = call fast double @acos(double %conv)
20  %conv1 = fptrunc double %call to float
21  ret float %conv1
22}
23
24define double @acos_test2(float %f)   {
25; CHECK-LABEL: @acos_test2(
26; CHECK-NEXT:    [[CONV:%.*]] = fpext float [[F:%.*]] to double
27; CHECK-NEXT:    [[CALL:%.*]] = call fast double @acos(double [[CONV]])
28; CHECK-NEXT:    ret double [[CALL]]
29;
30  %conv = fpext float %f to double
31  %call = call fast double @acos(double %conv)
32  ret double %call
33}
34
35define float @acosh_test1(float %f)   {
36; CHECK-LABEL: @acosh_test1(
37; CHECK-NEXT:    [[ACOSHF:%.*]] = call fast float @acoshf(float [[F:%.*]])
38; CHECK-NEXT:    ret float [[ACOSHF]]
39;
40  %conv = fpext float %f to double
41  %call = call fast double @acosh(double %conv)
42  %conv1 = fptrunc double %call to float
43  ret float %conv1
44}
45
46define double @acosh_test2(float %f)   {
47; CHECK-LABEL: @acosh_test2(
48; CHECK-NEXT:    [[CONV:%.*]] = fpext float [[F:%.*]] to double
49; CHECK-NEXT:    [[CALL:%.*]] = call fast double @acosh(double [[CONV]])
50; CHECK-NEXT:    ret double [[CALL]]
51;
52  %conv = fpext float %f to double
53  %call = call fast double @acosh(double %conv)
54  ret double %call
55}
56
57define float @asin_test1(float %f)   {
58; CHECK-LABEL: @asin_test1(
59; CHECK-NEXT:    [[ASINF:%.*]] = call fast float @asinf(float [[F:%.*]])
60; CHECK-NEXT:    ret float [[ASINF]]
61;
62  %conv = fpext float %f to double
63  %call = call fast double @asin(double %conv)
64  %conv1 = fptrunc double %call to float
65  ret float %conv1
66}
67
68define double @asin_test2(float %f)   {
69; CHECK-LABEL: @asin_test2(
70; CHECK-NEXT:    [[CONV:%.*]] = fpext float [[F:%.*]] to double
71; CHECK-NEXT:    [[CALL:%.*]] = call fast double @asin(double [[CONV]])
72; CHECK-NEXT:    ret double [[CALL]]
73;
74  %conv = fpext float %f to double
75  %call = call fast double @asin(double %conv)
76  ret double %call
77}
78
79define float @asinh_test1(float %f)   {
80; CHECK-LABEL: @asinh_test1(
81; CHECK-NEXT:    [[ASINHF:%.*]] = call fast float @asinhf(float [[F:%.*]])
82; CHECK-NEXT:    ret float [[ASINHF]]
83;
84  %conv = fpext float %f to double
85  %call = call fast double @asinh(double %conv)
86  %conv1 = fptrunc double %call to float
87  ret float %conv1
88}
89
90define double @asinh_test2(float %f)   {
91; CHECK-LABEL: @asinh_test2(
92; CHECK-NEXT:    [[CONV:%.*]] = fpext float [[F:%.*]] to double
93; CHECK-NEXT:    [[CALL:%.*]] = call fast double @asinh(double [[CONV]])
94; CHECK-NEXT:    ret double [[CALL]]
95;
96  %conv = fpext float %f to double
97  %call = call fast double @asinh(double %conv)
98  ret double %call
99}
100
101define float @atan_test1(float %f)   {
102; CHECK-LABEL: @atan_test1(
103; CHECK-NEXT:    [[ATANF:%.*]] = call fast float @atanf(float [[F:%.*]])
104; CHECK-NEXT:    ret float [[ATANF]]
105;
106  %conv = fpext float %f to double
107  %call = call fast double @atan(double %conv)
108  %conv1 = fptrunc double %call to float
109  ret float %conv1
110}
111
112define double @atan_test2(float %f)   {
113; CHECK-LABEL: @atan_test2(
114; CHECK-NEXT:    [[CONV:%.*]] = fpext float [[F:%.*]] to double
115; CHECK-NEXT:    [[CALL:%.*]] = call fast double @atan(double [[CONV]])
116; CHECK-NEXT:    ret double [[CALL]]
117;
118  %conv = fpext float %f to double
119  %call = call fast double @atan(double %conv)
120  ret double %call
121}
122
123define float @atanh_test1(float %f)   {
124; CHECK-LABEL: @atanh_test1(
125; CHECK-NEXT:    [[ATANHF:%.*]] = call fast float @atanhf(float [[F:%.*]])
126; CHECK-NEXT:    ret float [[ATANHF]]
127;
128  %conv = fpext float %f to double
129  %call = call fast double @atanh(double %conv)
130  %conv1 = fptrunc double %call to float
131  ret float %conv1
132}
133
134define double @atanh_test2(float %f)   {
135; CHECK-LABEL: @atanh_test2(
136; CHECK-NEXT:    [[CONV:%.*]] = fpext float [[F:%.*]] to double
137; CHECK-NEXT:    [[CALL:%.*]] = call fast double @atanh(double [[CONV]])
138; CHECK-NEXT:    ret double [[CALL]]
139;
140  %conv = fpext float %f to double
141  %call = call fast double @atanh(double %conv)
142  ret double %call
143}
144
145define float @cbrt_test1(float %f)   {
146; CHECK-LABEL: @cbrt_test1(
147; CHECK-NEXT:    [[CBRTF:%.*]] = call fast float @cbrtf(float [[F:%.*]])
148; CHECK-NEXT:    ret float [[CBRTF]]
149;
150  %conv = fpext float %f to double
151  %call = call fast double @cbrt(double %conv)
152  %conv1 = fptrunc double %call to float
153  ret float %conv1
154}
155
156define double @cbrt_test2(float %f)   {
157; CHECK-LABEL: @cbrt_test2(
158; CHECK-NEXT:    [[CONV:%.*]] = fpext float [[F:%.*]] to double
159; CHECK-NEXT:    [[CALL:%.*]] = call fast double @cbrt(double [[CONV]])
160; CHECK-NEXT:    ret double [[CALL]]
161;
162  %conv = fpext float %f to double
163  %call = call fast  double @cbrt(double %conv)
164  ret double %call
165}
166
167define float @exp_test1(float %f)   {
168; CHECK-LABEL: @exp_test1(
169; CHECK-NEXT:    [[EXPF:%.*]] = call fast float @expf(float [[F:%.*]])
170; CHECK-NEXT:    ret float [[EXPF]]
171;
172  %conv = fpext float %f to double
173  %call = call fast double @exp(double %conv)
174  %conv1 = fptrunc double %call to float
175  ret float %conv1
176}
177
178define double @exp_test2(float %f)   {
179; CHECK-LABEL: @exp_test2(
180; CHECK-NEXT:    [[CONV:%.*]] = fpext float [[F:%.*]] to double
181; CHECK-NEXT:    [[CALL:%.*]] = call fast double @exp(double [[CONV]])
182; CHECK-NEXT:    ret double [[CALL]]
183;
184  %conv = fpext float %f to double
185  %call = call fast double @exp(double %conv)
186  ret double %call
187}
188
189define float @expm1_test1(float %f)   {
190; CHECK-LABEL: @expm1_test1(
191; CHECK-NEXT:    [[EXPM1F:%.*]] = call fast float @expm1f(float [[F:%.*]])
192; CHECK-NEXT:    ret float [[EXPM1F]]
193;
194  %conv = fpext float %f to double
195  %call = call fast double @expm1(double %conv)
196  %conv1 = fptrunc double %call to float
197  ret float %conv1
198}
199
200define double @expm1_test2(float %f)   {
201; CHECK-LABEL: @expm1_test2(
202; CHECK-NEXT:    [[CONV:%.*]] = fpext float [[F:%.*]] to double
203; CHECK-NEXT:    [[CALL:%.*]] = call fast double @expm1(double [[CONV]])
204; CHECK-NEXT:    ret double [[CALL]]
205;
206  %conv = fpext float %f to double
207  %call = call fast double @expm1(double %conv)
208  ret double %call
209}
210
211; exp10f() doesn't exist for this triple, so it doesn't shrink.
212
213define float @exp10_test1(float %f)   {
214; CHECK-LABEL: @exp10_test1(
215; CHECK-NEXT:    [[CONV:%.*]] = fpext float [[F:%.*]] to double
216; CHECK-NEXT:    [[CALL:%.*]] = call fast double @exp10(double [[CONV]])
217; CHECK-NEXT:    [[CONV1:%.*]] = fptrunc double [[CALL]] to float
218; CHECK-NEXT:    ret float [[CONV1]]
219;
220  %conv = fpext float %f to double
221  %call = call fast double @exp10(double %conv)
222  %conv1 = fptrunc double %call to float
223  ret float %conv1
224}
225
226define double @exp10_test2(float %f)   {
227; CHECK-LABEL: @exp10_test2(
228; CHECK-NEXT:    [[CONV:%.*]] = fpext float [[F:%.*]] to double
229; CHECK-NEXT:    [[CALL:%.*]] = call fast double @exp10(double [[CONV]])
230; CHECK-NEXT:    ret double [[CALL]]
231;
232  %conv = fpext float %f to double
233  %call = call fast double @exp10(double %conv)
234  ret double %call
235}
236
237define float @log_test1(float %f)   {
238; CHECK-LABEL: @log_test1(
239; CHECK-NEXT:    [[LOGF:%.*]] = call fast float @logf(float [[F:%.*]])
240; CHECK-NEXT:    ret float [[LOGF]]
241;
242  %conv = fpext float %f to double
243  %call = call fast double @log(double %conv)
244  %conv1 = fptrunc double %call to float
245  ret float %conv1
246}
247
248define double @log_test2(float %f)   {
249; CHECK-LABEL: @log_test2(
250; CHECK-NEXT:    [[CONV:%.*]] = fpext float [[F:%.*]] to double
251; CHECK-NEXT:    [[CALL:%.*]] = call fast double @log(double [[CONV]])
252; CHECK-NEXT:    ret double [[CALL]]
253;
254  %conv = fpext float %f to double
255  %call = call fast double @log(double %conv)
256  ret double %call
257}
258
259define float @log10_test1(float %f)   {
260; CHECK-LABEL: @log10_test1(
261; CHECK-NEXT:    [[LOG10F:%.*]] = call fast float @log10f(float [[F:%.*]])
262; CHECK-NEXT:    ret float [[LOG10F]]
263;
264  %conv = fpext float %f to double
265  %call = call fast double @log10(double %conv)
266  %conv1 = fptrunc double %call to float
267  ret float %conv1
268}
269
270define double @log10_test2(float %f) {
271; CHECK-LABEL: @log10_test2(
272; CHECK-NEXT:    [[CONV:%.*]] = fpext float [[F:%.*]] to double
273; CHECK-NEXT:    [[CALL:%.*]] = call fast double @log10(double [[CONV]])
274; CHECK-NEXT:    ret double [[CALL]]
275;
276  %conv = fpext float %f to double
277  %call = call fast double @log10(double %conv)
278  ret double %call
279}
280
281define float @log1p_test1(float %f)   {
282; CHECK-LABEL: @log1p_test1(
283; CHECK-NEXT:    [[LOG1PF:%.*]] = call fast float @log1pf(float [[F:%.*]])
284; CHECK-NEXT:    ret float [[LOG1PF]]
285;
286  %conv = fpext float %f to double
287  %call = call fast double @log1p(double %conv)
288  %conv1 = fptrunc double %call to float
289  ret float %conv1
290}
291
292define double @log1p_test2(float %f)   {
293; CHECK-LABEL: @log1p_test2(
294; CHECK-NEXT:    [[CONV:%.*]] = fpext float [[F:%.*]] to double
295; CHECK-NEXT:    [[CALL:%.*]] = call fast double @log1p(double [[CONV]])
296; CHECK-NEXT:    ret double [[CALL]]
297;
298  %conv = fpext float %f to double
299  %call = call fast double @log1p(double %conv)
300  ret double %call
301}
302
303define float @log2_test1(float %f)   {
304; CHECK-LABEL: @log2_test1(
305; CHECK-NEXT:    [[LOG2F:%.*]] = call fast float @log2f(float [[F:%.*]])
306; CHECK-NEXT:    ret float [[LOG2F]]
307;
308  %conv = fpext float %f to double
309  %call = call fast double @log2(double %conv)
310  %conv1 = fptrunc double %call to float
311  ret float %conv1
312}
313
314define double @log2_test2(float %f)   {
315; CHECK-LABEL: @log2_test2(
316; CHECK-NEXT:    [[CONV:%.*]] = fpext float [[F:%.*]] to double
317; CHECK-NEXT:    [[CALL:%.*]] = call fast double @log2(double [[CONV]])
318; CHECK-NEXT:    ret double [[CALL]]
319;
320  %conv = fpext float %f to double
321  %call = call fast double @log2(double %conv)
322  ret double %call
323}
324
325define float @logb_test1(float %f)   {
326; CHECK-LABEL: @logb_test1(
327; CHECK-NEXT:    [[LOGBF:%.*]] = call fast float @logbf(float [[F:%.*]])
328; CHECK-NEXT:    ret float [[LOGBF]]
329;
330  %conv = fpext float %f to double
331  %call = call fast double @logb(double %conv)
332  %conv1 = fptrunc double %call to float
333  ret float %conv1
334}
335
336define double @logb_test2(float %f)   {
337; CHECK-LABEL: @logb_test2(
338; CHECK-NEXT:    [[CONV:%.*]] = fpext float [[F:%.*]] to double
339; CHECK-NEXT:    [[CALL:%.*]] = call fast double @logb(double [[CONV]])
340; CHECK-NEXT:    ret double [[CALL]]
341;
342  %conv = fpext float %f to double
343  %call = call fast double @logb(double %conv)
344  ret double %call
345}
346
347; FIXME: Miscompile - we dropped the 2nd argument!
348
349define float @pow_test1(float %f, float %g)   {
350; CHECK-LABEL: @pow_test1(
351; CHECK-NEXT:    [[POWF:%.*]] = call fast float @powf(float [[F:%.*]])
352; CHECK-NEXT:    ret float [[POWF]]
353;
354  %df = fpext float %f to double
355  %dg = fpext float %g to double
356  %call = call fast double @pow(double %df, double %dg)
357  %fr = fptrunc double %call to float
358  ret float %fr
359}
360
361; TODO: This should shrink?
362
363define double @pow_test2(float %f, float %g) {
364; CHECK-LABEL: @pow_test2(
365; CHECK-NEXT:    [[DF:%.*]] = fpext float [[F:%.*]] to double
366; CHECK-NEXT:    [[DG:%.*]] = fpext float [[G:%.*]] to double
367; CHECK-NEXT:    [[CALL:%.*]] = call fast double @pow(double [[DF]], double [[DG]])
368; CHECK-NEXT:    ret double [[CALL]]
369;
370  %df = fpext float %f to double
371  %dg = fpext float %g to double
372  %call = call fast double @pow(double %df, double %dg)
373  ret double %call
374}
375
376define float @sin_test1(float %f)   {
377; CHECK-LABEL: @sin_test1(
378; CHECK-NEXT:    [[SINF:%.*]] = call fast float @sinf(float [[F:%.*]])
379; CHECK-NEXT:    ret float [[SINF]]
380;
381  %conv = fpext float %f to double
382  %call = call fast double @sin(double %conv)
383  %conv1 = fptrunc double %call to float
384  ret float %conv1
385}
386
387define double @sin_test2(float %f) {
388; CHECK-LABEL: @sin_test2(
389; CHECK-NEXT:    [[CONV:%.*]] = fpext float [[F:%.*]] to double
390; CHECK-NEXT:    [[CALL:%.*]] = call fast double @sin(double [[CONV]])
391; CHECK-NEXT:    ret double [[CALL]]
392;
393  %conv = fpext float %f to double
394  %call = call fast double @sin(double %conv)
395  ret double %call
396}
397
398define float @sqrt_test1(float %f) {
399; CHECK-LABEL: @sqrt_test1(
400; CHECK-NEXT:    [[SQRTF:%.*]] = call float @sqrtf(float [[F:%.*]])
401; CHECK-NEXT:    ret float [[SQRTF]]
402;
403  %conv = fpext float %f to double
404  %call = call double @sqrt(double %conv)
405  %conv1 = fptrunc double %call to float
406  ret float %conv1
407}
408
409define double @sqrt_test2(float %f) {
410; CHECK-LABEL: @sqrt_test2(
411; CHECK-NEXT:    [[CONV:%.*]] = fpext float [[F:%.*]] to double
412; CHECK-NEXT:    [[CALL:%.*]] = call double @sqrt(double [[CONV]])
413; CHECK-NEXT:    ret double [[CALL]]
414;
415  %conv = fpext float %f to double
416  %call = call double @sqrt(double %conv)
417  ret double %call
418}
419
420define float @sqrt_int_test1(float %f) {
421; CHECK-LABEL: @sqrt_int_test1(
422; CHECK-NEXT:    [[TMP1:%.*]] = call float @llvm.sqrt.f32(float [[F:%.*]])
423; CHECK-NEXT:    ret float [[TMP1]]
424;
425  %conv = fpext float %f to double
426  %call = call double @llvm.sqrt.f64(double %conv)
427  %conv1 = fptrunc double %call to float
428  ret float %conv1
429}
430
431define double @sqrt_int_test2(float %f) {
432; CHECK-LABEL: @sqrt_int_test2(
433; CHECK-NEXT:    [[CONV:%.*]] = fpext float [[F:%.*]] to double
434; CHECK-NEXT:    [[CALL:%.*]] = call double @llvm.sqrt.f64(double [[CONV]])
435; CHECK-NEXT:    ret double [[CALL]]
436;
437  %conv = fpext float %f to double
438  %call = call double @llvm.sqrt.f64(double %conv)
439  ret double %call
440}
441
442define float @tan_test1(float %f) {
443; CHECK-LABEL: @tan_test1(
444; CHECK-NEXT:    [[TANF:%.*]] = call fast float @tanf(float [[F:%.*]])
445; CHECK-NEXT:    ret float [[TANF]]
446;
447  %conv = fpext float %f to double
448  %call = call fast double @tan(double %conv)
449  %conv1 = fptrunc double %call to float
450  ret float %conv1
451}
452
453define double @tan_test2(float %f) {
454; CHECK-LABEL: @tan_test2(
455; CHECK-NEXT:    [[CONV:%.*]] = fpext float [[F:%.*]] to double
456; CHECK-NEXT:    [[CALL:%.*]] = call fast double @tan(double [[CONV]])
457; CHECK-NEXT:    ret double [[CALL]]
458;
459  %conv = fpext float %f to double
460  %call = call fast double @tan(double %conv)
461  ret double %call
462}
463define float @tanh_test1(float %f) {
464; CHECK-LABEL: @tanh_test1(
465; CHECK-NEXT:    [[TANHF:%.*]] = call fast float @tanhf(float [[F:%.*]])
466; CHECK-NEXT:    ret float [[TANHF]]
467;
468  %conv = fpext float %f to double
469  %call = call fast double @tanh(double %conv)
470  %conv1 = fptrunc double %call to float
471  ret float %conv1
472}
473
474define double @tanh_test2(float %f) {
475; CHECK-LABEL: @tanh_test2(
476; CHECK-NEXT:    [[CONV:%.*]] = fpext float [[F:%.*]] to double
477; CHECK-NEXT:    [[CALL:%.*]] = call fast double @tanh(double [[CONV]])
478; CHECK-NEXT:    ret double [[CALL]]
479;
480  %conv = fpext float %f to double
481  %call = call fast double @tanh(double %conv)
482  ret double %call
483}
484
485; 'arcp' on an fmax() is meaningless. This test just proves that
486; flags are propagated for shrunken *binary* double FP calls.
487define float @max1(float %a, float %b) {
488; CHECK-LABEL: @max1(
489; CHECK-NEXT:    [[FMAXF:%.*]] = call arcp float @fmaxf(float [[A:%.*]], float [[B:%.*]])
490; CHECK-NEXT:    ret float [[FMAXF]]
491;
492  %c = fpext float %a to double
493  %d = fpext float %b to double
494  %e = call arcp double @fmax(double %c, double %d)
495  %f = fptrunc double %e to float
496  ret float %f
497}
498
499; A function can have a name that matches a common libcall,
500; but with the wrong type(s). Let it be.
501
502define float @fake_fmin(float %a, float %b) {
503; CHECK-LABEL: @fake_fmin(
504; CHECK-NEXT:    [[C:%.*]] = fpext float [[A:%.*]] to fp128
505; CHECK-NEXT:    [[D:%.*]] = fpext float [[B:%.*]] to fp128
506; CHECK-NEXT:    [[E:%.*]] = call fp128 @fmin(fp128 [[C]], fp128 [[D]])
507; CHECK-NEXT:    [[F:%.*]] = fptrunc fp128 [[E]] to float
508; CHECK-NEXT:    ret float [[F]]
509;
510  %c = fpext float %a to fp128
511  %d = fpext float %b to fp128
512  %e = call fp128 @fmin(fp128 %c, fp128 %d)
513  %f = fptrunc fp128 %e to float
514  ret float %f
515}
516
517declare fp128 @fmin(fp128, fp128) ; This is not the 'fmin' you're looking for.
518
519declare double @fmax(double, double)
520
521declare double @tanh(double)
522declare double @tan(double)
523
524; sqrt is a special case: the shrinking optimization
525; is valid even without unsafe-fp-math.
526declare double @sqrt(double)
527declare double @llvm.sqrt.f64(double)
528
529declare double @sin(double)
530declare double @pow(double, double)
531declare double @log2(double)
532declare double @log1p(double)
533declare double @log10(double)
534declare double @log(double)
535declare double @logb(double)
536declare double @exp10(double)
537declare double @expm1(double)
538declare double @exp(double)
539declare double @cbrt(double)
540declare double @atanh(double)
541declare double @atan(double)
542declare double @acos(double)
543declare double @acosh(double)
544declare double @asin(double)
545declare double @asinh(double)
546
547