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