summaryrefslogtreecommitdiff
path: root/gcc/testsuite/gcc.target/i386/pr80732.c
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/testsuite/gcc.target/i386/pr80732.c')
-rw-r--r--gcc/testsuite/gcc.target/i386/pr80732.c93
1 files changed, 93 insertions, 0 deletions
diff --git a/gcc/testsuite/gcc.target/i386/pr80732.c b/gcc/testsuite/gcc.target/i386/pr80732.c
new file mode 100644
index 00000000000..e1207298239
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr80732.c
@@ -0,0 +1,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 void *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 ();
+}