1 /* PR ipa/80732 */
2 /* { dg-do run } */
3 /* { dg-options "-ldl -fPIC -rdynamic -O3 -g -pie" } */
4 /* { dg-require-ifunc "" } */
5 /* { dg-require-effective-target fma4 } */
6 /* { dg-require-effective-target fpic } */
7 /* { dg-require-effective-target pie } */
8 
9 #include "fma4-check.h"
10 
11 #include <dlfcn.h>
12 
13 __attribute__((target_clones("default","fma"),noinline,optimize("fast-math")))
f1(double a,double b,double c)14 double f1(double a, double b, double c)
15 {
16     return a * b + c;
17 }
18 
k1(double a,double b,double c,void ** p)19 double k1(double a, double b, double c, void **p)
20 {
21     *p = f1;
22     return f1(a, b, c);
23 }
24 
25 __attribute__((target("fma"),optimize("fast-math")))
f2_fma(double a,double b,double c)26 static double f2_fma(double a, double b, double c)
27 {
28     return a * b + c;
29 }
30 
31 __attribute__((optimize("fast-math")))
f2_default(double a,double b,double c)32 static double f2_default(double a, double b, double c)
33 {
34     return a * b + c;
35 }
36 
__typeof__(f2_fma)37 static __typeof__ (f2_fma)* f2_resolve(void)
38 {
39     __builtin_cpu_init ();
40     if (__builtin_cpu_supports("fma"))
41         return f2_fma;
42     else
43         return f2_default;
44 }
45 
46 double f2(double a, double b, double c) __attribute__((ifunc("f2_resolve")));
47 
k2(double a,double b,double c,void ** p)48 double k2(double a, double b, double c, void **p)
49 {
50     *p = f2;
51     return f2(a, b, c);
52 }
53 
54 double (*initializer) (double, double, double) = { &f1 };
55 
56 static void
fma4_test(void)57 fma4_test (void)
58 {
59     char buffer[256];
60     const char *expectation = "4.93038e-32, 4.93038e-32, 4.93038e-32";
61 
62     volatile double a = 1.0000000000000002;
63     volatile double b = -0.9999999999999998;
64     volatile double c = 1.0;
65 
66     void *hdl = dlopen(0, RTLD_NOW);
67 
68     double (*pf1)(double, double, double) = dlsym(hdl, "f1");
69     double (*pk1)(double, double, double, void**) = dlsym(hdl, "k1");
70     double (*_pf1)(double, double, double);
71 
72     double v1_1 = pf1(a, b, c);
73     double v1_2 = pk1(a, b, c, (void**)&_pf1);
74     double v1_3 = _pf1(a, b, c);
75     __builtin_sprintf (buffer, "%g, %g, %g", v1_1, v1_2, v1_3);
76     if (__builtin_strcmp (buffer, expectation) != 0)
77       __builtin_abort ();
78 
79     double (*pf2)(double, double, double) = dlsym(hdl, "f2");
80     double (*pk2)(double, double, double, void**) = dlsym(hdl, "k2");
81     double (*_pf2)(double, double, double);
82 
83     double v2_1 = pf2(a, b, c);
84     double v2_2 = pk2(a, b, c, (void**)&_pf2);
85     double v2_3 = _pf2(a, b, c);
86     __builtin_sprintf(buffer, "%g, %g, %g", v2_1, v2_2, v2_3);
87     if (__builtin_strcmp (buffer, expectation) != 0)
88       __builtin_abort ();
89 
90     __builtin_sprintf(buffer, "%g, %g, %g", initializer (a, b, c), v2_2, v2_3);
91     if (__builtin_strcmp (buffer, expectation) != 0)
92       __builtin_abort ();
93 }
94