From 3d131ceb7f5c3a5d68d9deacfe375dc7dddfb3db Mon Sep 17 00:00:00 2001 From: Richard Sandiford Date: Thu, 12 Jul 2018 13:01:33 +0000 Subject: Add IFN_COND_FMA functions This patch adds conditional equivalents of the IFN_FMA built-in functions. Most of it is just a mechanical extension of the binary stuff. 2018-07-12 Richard Sandiford gcc/ * doc/md.texi (cond_fma, cond_fms, cond_fnma, cond_fnms): Document. * optabs.def (cond_fma_optab, cond_fms_optab, cond_fnma_optab) (cond_fnms_optab): New optabs. * internal-fn.def (COND_FMA, COND_FMS, COND_FNMA, COND_FNMS): New internal functions. (FMA): Use DEF_INTERNAL_FLT_FN rather than DEF_INTERNAL_FLT_FLOATN_FN. * internal-fn.h (get_conditional_internal_fn): Declare. (get_unconditional_internal_fn): Likewise. * internal-fn.c (cond_ternary_direct): New macro. (expand_cond_ternary_optab_fn): Likewise. (direct_cond_ternary_optab_supported_p): Likewise. (FOR_EACH_COND_FN_PAIR): Likewise. (get_conditional_internal_fn): New function. (get_unconditional_internal_fn): Likewise. * gimple-match.h (gimple_match_op::MAX_NUM_OPS): Bump to 5. (gimple_match_op::gimple_match_op): Add a new overload for 5 operands. (gimple_match_op::set_op): Likewise. (gimple_resimplify5): Declare. * genmatch.c (decision_tree::gen): Generate simplifications for 5 operands. * gimple-match-head.c (gimple_simplify): Define an overload for 5 operands. Handle calls with 5 arguments in the top-level overload. (convert_conditional_op): Handle conversions from unconditional internal functions to conditional ones. (gimple_resimplify5): New function. (build_call_internal): Pass a fifth operand. (maybe_push_res_to_seq): Likewise. (try_conditional_simplification): Try converting conditional internal functions to unconditional internal functions. Handle 3-operand unconditional forms. * match.pd (UNCOND_TERNARY, COND_TERNARY): Operator lists. Define ternary equivalents of the current rules for binary conditional internal functions. * config/aarch64/aarch64.c (aarch64_preferred_else_value): Handle ternary operations. * config/aarch64/iterators.md (UNSPEC_COND_FMLA, UNSPEC_COND_FMLS) (UNSPEC_COND_FNMLA, UNSPEC_COND_FNMLS): New unspecs. (optab): Handle them. (SVE_COND_FP_TERNARY): New int iterator. (sve_fmla_op, sve_fmad_op): New int attributes. * config/aarch64/aarch64-sve.md (cond_) (*cond__2, *cond__any): New SVE_COND_FP_TERNARY patterns. gcc/testsuite/ * gcc.dg/vect/vect-cond-arith-3.c: New test. * gcc.target/aarch64/sve/vcond_13.c: Likewise. * gcc.target/aarch64/sve/vcond_13_run.c: Likewise. * gcc.target/aarch64/sve/vcond_14.c: Likewise. * gcc.target/aarch64/sve/vcond_14_run.c: Likewise. * gcc.target/aarch64/sve/vcond_15.c: Likewise. * gcc.target/aarch64/sve/vcond_15_run.c: Likewise. * gcc.target/aarch64/sve/vcond_16.c: Likewise. * gcc.target/aarch64/sve/vcond_16_run.c: Likewise. git-svn-id: https://gcc.gnu.org/svn/gcc/trunk@262587 138bc75d-0d04-0410-961f-82ee72b054a4 --- gcc/testsuite/gcc.target/aarch64/sve/vcond_13.c | 58 ++++++++++++++++++++++ .../gcc.target/aarch64/sve/vcond_13_run.c | 37 ++++++++++++++ gcc/testsuite/gcc.target/aarch64/sve/vcond_14.c | 58 ++++++++++++++++++++++ .../gcc.target/aarch64/sve/vcond_14_run.c | 37 ++++++++++++++ gcc/testsuite/gcc.target/aarch64/sve/vcond_15.c | 58 ++++++++++++++++++++++ .../gcc.target/aarch64/sve/vcond_15_run.c | 37 ++++++++++++++ gcc/testsuite/gcc.target/aarch64/sve/vcond_16.c | 58 ++++++++++++++++++++++ .../gcc.target/aarch64/sve/vcond_16_run.c | 37 ++++++++++++++ 8 files changed, 380 insertions(+) create mode 100644 gcc/testsuite/gcc.target/aarch64/sve/vcond_13.c create mode 100644 gcc/testsuite/gcc.target/aarch64/sve/vcond_13_run.c create mode 100644 gcc/testsuite/gcc.target/aarch64/sve/vcond_14.c create mode 100644 gcc/testsuite/gcc.target/aarch64/sve/vcond_14_run.c create mode 100644 gcc/testsuite/gcc.target/aarch64/sve/vcond_15.c create mode 100644 gcc/testsuite/gcc.target/aarch64/sve/vcond_15_run.c create mode 100644 gcc/testsuite/gcc.target/aarch64/sve/vcond_16.c create mode 100644 gcc/testsuite/gcc.target/aarch64/sve/vcond_16_run.c (limited to 'gcc/testsuite/gcc.target/aarch64/sve') diff --git a/gcc/testsuite/gcc.target/aarch64/sve/vcond_13.c b/gcc/testsuite/gcc.target/aarch64/sve/vcond_13.c new file mode 100644 index 00000000000..3c3aa00f674 --- /dev/null +++ b/gcc/testsuite/gcc.target/aarch64/sve/vcond_13.c @@ -0,0 +1,58 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -ftree-vectorize" } */ + +#define N 119 + +#define DEF_LOOP(INV, TYPE, CMPTYPE, SUFFIX) \ + void __attribute__ ((noipa)) \ + f_##INV##_##SUFFIX (TYPE *restrict a, TYPE *restrict b, \ + TYPE *restrict c, TYPE *restrict d, \ + CMPTYPE *restrict cond) \ + { \ + for (int i = 0; i < N; ++i) \ + { \ + TYPE mb = (INV & 1 ? -b[i] : b[i]); \ + TYPE mc = c[i]; \ + TYPE md = (INV & 2 ? -d[i] : d[i]); \ + TYPE fma = __builtin_fma##SUFFIX (mb, mc, md); \ + TYPE truev = (INV & 4 ? -fma : fma); \ + a[i] = cond[i] < 10 ? truev : b[i]; \ + } \ + } + +#define FOR_EACH_TYPE(T, INV) \ + T (INV, _Float16, short, f16) \ + T (INV, float, float, f32) \ + T (INV, double, double, f64) + +#define FOR_EACH_INV(T) \ + FOR_EACH_TYPE (T, 0) \ + FOR_EACH_TYPE (T, 1) \ + FOR_EACH_TYPE (T, 2) \ + FOR_EACH_TYPE (T, 3) \ + FOR_EACH_TYPE (T, 4) \ + FOR_EACH_TYPE (T, 5) \ + FOR_EACH_TYPE (T, 6) \ + FOR_EACH_TYPE (T, 7) + +FOR_EACH_INV (DEF_LOOP) + +/* { dg-final { scan-assembler-not {\tsel\t} } } */ +/* { dg-final { scan-assembler-not {\tmovprfx\t} } } */ +/* { dg-final { scan-assembler-not {\tmov\tz[0-9]+\.., z[0-9]+} } } */ + +/* { dg-final { scan-assembler-times {\tfmad\tz[0-9]+\.h,} 2 } } */ +/* { dg-final { scan-assembler-times {\tfmad\tz[0-9]+\.s,} 2 } } */ +/* { dg-final { scan-assembler-times {\tfmad\tz[0-9]+\.d,} 2 } } */ + +/* { dg-final { scan-assembler-times {\tfmsb\tz[0-9]+\.h,} 2 } } */ +/* { dg-final { scan-assembler-times {\tfmsb\tz[0-9]+\.s,} 2 } } */ +/* { dg-final { scan-assembler-times {\tfmsb\tz[0-9]+\.d,} 2 } } */ + +/* { dg-final { scan-assembler-times {\tfnmad\tz[0-9]+\.h,} 2 } } */ +/* { dg-final { scan-assembler-times {\tfnmad\tz[0-9]+\.s,} 2 } } */ +/* { dg-final { scan-assembler-times {\tfnmad\tz[0-9]+\.d,} 2 } } */ + +/* { dg-final { scan-assembler-times {\tfnmsb\tz[0-9]+\.h,} 2 } } */ +/* { dg-final { scan-assembler-times {\tfnmsb\tz[0-9]+\.s,} 2 } } */ +/* { dg-final { scan-assembler-times {\tfnmsb\tz[0-9]+\.d,} 2 } } */ diff --git a/gcc/testsuite/gcc.target/aarch64/sve/vcond_13_run.c b/gcc/testsuite/gcc.target/aarch64/sve/vcond_13_run.c new file mode 100644 index 00000000000..f0f8385babc --- /dev/null +++ b/gcc/testsuite/gcc.target/aarch64/sve/vcond_13_run.c @@ -0,0 +1,37 @@ +/* { dg-do run { target aarch64_sve_hw } } */ +/* { dg-options "-O2 -ftree-vectorize" } */ + +#include "vcond_13.c" + +#define TEST_LOOP(INV, TYPE, CMPTYPE, SUFFIX) \ + { \ + TYPE a[N], b[N], c[N], d[N]; \ + CMPTYPE cond[N]; \ + for (int i = 0; i < N; ++i) \ + { \ + b[i] = i % 15; \ + c[i] = i % 9 + 11; \ + d[i] = i % 13 + 14; \ + cond[i] = i % 17; \ + asm volatile ("" ::: "memory"); \ + } \ + f_##INV##_##SUFFIX (a, b, c, d, cond); \ + for (int i = 0; i < N; ++i) \ + { \ + double mb = (INV & 1 ? -b[i] : b[i]); \ + double mc = c[i]; \ + double md = (INV & 2 ? -d[i] : d[i]); \ + double fma = __builtin_fma (mb, mc, md); \ + double truev = (INV & 4 ? -fma : fma); \ + if (a[i] != (i % 17 < 10 ? truev : b[i])) \ + __builtin_abort (); \ + asm volatile ("" ::: "memory"); \ + } \ + } + +int +main (void) +{ + FOR_EACH_INV (TEST_LOOP) + return 0; +} diff --git a/gcc/testsuite/gcc.target/aarch64/sve/vcond_14.c b/gcc/testsuite/gcc.target/aarch64/sve/vcond_14.c new file mode 100644 index 00000000000..1144461dec0 --- /dev/null +++ b/gcc/testsuite/gcc.target/aarch64/sve/vcond_14.c @@ -0,0 +1,58 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -ftree-vectorize" } */ + +#define N 119 + +#define DEF_LOOP(INV, TYPE, CMPTYPE, SUFFIX) \ + void __attribute__ ((noipa)) \ + f_##INV##_##SUFFIX (TYPE *restrict a, TYPE *restrict b, \ + TYPE *restrict c, TYPE *restrict d, \ + CMPTYPE *restrict cond) \ + { \ + for (int i = 0; i < N; ++i) \ + { \ + TYPE mb = (INV & 1 ? -b[i] : b[i]); \ + TYPE mc = c[i]; \ + TYPE md = (INV & 2 ? -d[i] : d[i]); \ + TYPE fma = __builtin_fma##SUFFIX (mb, mc, md); \ + TYPE truev = (INV & 4 ? -fma : fma); \ + a[i] = cond[i] < 10 ? truev : c[i]; \ + } \ + } + +#define FOR_EACH_TYPE(T, INV) \ + T (INV, _Float16, short, f16) \ + T (INV, float, float, f32) \ + T (INV, double, double, f64) + +#define FOR_EACH_INV(T) \ + FOR_EACH_TYPE (T, 0) \ + FOR_EACH_TYPE (T, 1) \ + FOR_EACH_TYPE (T, 2) \ + FOR_EACH_TYPE (T, 3) \ + FOR_EACH_TYPE (T, 4) \ + FOR_EACH_TYPE (T, 5) \ + FOR_EACH_TYPE (T, 6) \ + FOR_EACH_TYPE (T, 7) + +FOR_EACH_INV (DEF_LOOP) + +/* { dg-final { scan-assembler-not {\tsel\t} } } */ +/* { dg-final { scan-assembler-not {\tmovprfx\t} } } */ +/* { dg-final { scan-assembler-not {\tmov\tz[0-9]+\.., z[0-9]+} } } */ + +/* { dg-final { scan-assembler-times {\tfmad\tz[0-9]+\.h,} 2 } } */ +/* { dg-final { scan-assembler-times {\tfmad\tz[0-9]+\.s,} 2 } } */ +/* { dg-final { scan-assembler-times {\tfmad\tz[0-9]+\.d,} 2 } } */ + +/* { dg-final { scan-assembler-times {\tfmsb\tz[0-9]+\.h,} 2 } } */ +/* { dg-final { scan-assembler-times {\tfmsb\tz[0-9]+\.s,} 2 } } */ +/* { dg-final { scan-assembler-times {\tfmsb\tz[0-9]+\.d,} 2 } } */ + +/* { dg-final { scan-assembler-times {\tfnmad\tz[0-9]+\.h,} 2 } } */ +/* { dg-final { scan-assembler-times {\tfnmad\tz[0-9]+\.s,} 2 } } */ +/* { dg-final { scan-assembler-times {\tfnmad\tz[0-9]+\.d,} 2 } } */ + +/* { dg-final { scan-assembler-times {\tfnmsb\tz[0-9]+\.h,} 2 } } */ +/* { dg-final { scan-assembler-times {\tfnmsb\tz[0-9]+\.s,} 2 } } */ +/* { dg-final { scan-assembler-times {\tfnmsb\tz[0-9]+\.d,} 2 } } */ diff --git a/gcc/testsuite/gcc.target/aarch64/sve/vcond_14_run.c b/gcc/testsuite/gcc.target/aarch64/sve/vcond_14_run.c new file mode 100644 index 00000000000..090f35be315 --- /dev/null +++ b/gcc/testsuite/gcc.target/aarch64/sve/vcond_14_run.c @@ -0,0 +1,37 @@ +/* { dg-do run { target aarch64_sve_hw } } */ +/* { dg-options "-O2 -ftree-vectorize" } */ + +#include "vcond_14.c" + +#define TEST_LOOP(INV, TYPE, CMPTYPE, SUFFIX) \ + { \ + TYPE a[N], b[N], c[N], d[N]; \ + CMPTYPE cond[N]; \ + for (int i = 0; i < N; ++i) \ + { \ + b[i] = i % 15; \ + c[i] = i % 9 + 11; \ + d[i] = i % 13 + 14; \ + cond[i] = i % 17; \ + asm volatile ("" ::: "memory"); \ + } \ + f_##INV##_##SUFFIX (a, b, c, d, cond); \ + for (int i = 0; i < N; ++i) \ + { \ + double mb = (INV & 1 ? -b[i] : b[i]); \ + double mc = c[i]; \ + double md = (INV & 2 ? -d[i] : d[i]); \ + double fma = __builtin_fma (mb, mc, md); \ + double truev = (INV & 4 ? -fma : fma); \ + if (a[i] != (i % 17 < 10 ? truev : c[i])) \ + __builtin_abort (); \ + asm volatile ("" ::: "memory"); \ + } \ + } + +int +main (void) +{ + FOR_EACH_INV (TEST_LOOP) + return 0; +} diff --git a/gcc/testsuite/gcc.target/aarch64/sve/vcond_15.c b/gcc/testsuite/gcc.target/aarch64/sve/vcond_15.c new file mode 100644 index 00000000000..4967074072c --- /dev/null +++ b/gcc/testsuite/gcc.target/aarch64/sve/vcond_15.c @@ -0,0 +1,58 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -ftree-vectorize" } */ + +#define N 119 + +#define DEF_LOOP(INV, TYPE, CMPTYPE, SUFFIX) \ + void __attribute__ ((noipa)) \ + f_##INV##_##SUFFIX (TYPE *restrict a, TYPE *restrict b, \ + TYPE *restrict c, TYPE *restrict d, \ + CMPTYPE *restrict cond) \ + { \ + for (int i = 0; i < N; ++i) \ + { \ + TYPE mb = (INV & 1 ? -b[i] : b[i]); \ + TYPE mc = c[i]; \ + TYPE md = (INV & 2 ? -d[i] : d[i]); \ + TYPE fma = __builtin_fma##SUFFIX (mb, mc, md); \ + TYPE truev = (INV & 4 ? -fma : fma); \ + a[i] = cond[i] < 10 ? truev : d[i]; \ + } \ + } + +#define FOR_EACH_TYPE(T, INV) \ + T (INV, _Float16, short, f16) \ + T (INV, float, float, f32) \ + T (INV, double, double, f64) + +#define FOR_EACH_INV(T) \ + FOR_EACH_TYPE (T, 0) \ + FOR_EACH_TYPE (T, 1) \ + FOR_EACH_TYPE (T, 2) \ + FOR_EACH_TYPE (T, 3) \ + FOR_EACH_TYPE (T, 4) \ + FOR_EACH_TYPE (T, 5) \ + FOR_EACH_TYPE (T, 6) \ + FOR_EACH_TYPE (T, 7) + +FOR_EACH_INV (DEF_LOOP) + +/* { dg-final { scan-assembler-not {\tsel\t} } } */ +/* { dg-final { scan-assembler-not {\tmovprfx\t} } } */ +/* { dg-final { scan-assembler-not {\tmov\tz[0-9]+\.., z[0-9]+} } } */ + +/* { dg-final { scan-assembler-times {\tfmla\tz[0-9]+\.h,} 2 } } */ +/* { dg-final { scan-assembler-times {\tfmla\tz[0-9]+\.s,} 2 } } */ +/* { dg-final { scan-assembler-times {\tfmla\tz[0-9]+\.d,} 2 } } */ + +/* { dg-final { scan-assembler-times {\tfmls\tz[0-9]+\.h,} 2 } } */ +/* { dg-final { scan-assembler-times {\tfmls\tz[0-9]+\.s,} 2 } } */ +/* { dg-final { scan-assembler-times {\tfmls\tz[0-9]+\.d,} 2 } } */ + +/* { dg-final { scan-assembler-times {\tfnmla\tz[0-9]+\.h,} 2 } } */ +/* { dg-final { scan-assembler-times {\tfnmla\tz[0-9]+\.s,} 2 } } */ +/* { dg-final { scan-assembler-times {\tfnmla\tz[0-9]+\.d,} 2 } } */ + +/* { dg-final { scan-assembler-times {\tfnmls\tz[0-9]+\.h,} 2 } } */ +/* { dg-final { scan-assembler-times {\tfnmls\tz[0-9]+\.s,} 2 } } */ +/* { dg-final { scan-assembler-times {\tfnmls\tz[0-9]+\.d,} 2 } } */ diff --git a/gcc/testsuite/gcc.target/aarch64/sve/vcond_15_run.c b/gcc/testsuite/gcc.target/aarch64/sve/vcond_15_run.c new file mode 100644 index 00000000000..b08d4d8ebfb --- /dev/null +++ b/gcc/testsuite/gcc.target/aarch64/sve/vcond_15_run.c @@ -0,0 +1,37 @@ +/* { dg-do run { target aarch64_sve_hw } } */ +/* { dg-options "-O2 -ftree-vectorize" } */ + +#include "vcond_15.c" + +#define TEST_LOOP(INV, TYPE, CMPTYPE, SUFFIX) \ + { \ + TYPE a[N], b[N], c[N], d[N]; \ + CMPTYPE cond[N]; \ + for (int i = 0; i < N; ++i) \ + { \ + b[i] = i % 15; \ + c[i] = i % 9 + 11; \ + d[i] = i % 13 + 14; \ + cond[i] = i % 17; \ + asm volatile ("" ::: "memory"); \ + } \ + f_##INV##_##SUFFIX (a, b, c, d, cond); \ + for (int i = 0; i < N; ++i) \ + { \ + double mb = (INV & 1 ? -b[i] : b[i]); \ + double mc = c[i]; \ + double md = (INV & 2 ? -d[i] : d[i]); \ + double fma = __builtin_fma (mb, mc, md); \ + double truev = (INV & 4 ? -fma : fma); \ + if (a[i] != (i % 17 < 10 ? truev : d[i])) \ + __builtin_abort (); \ + asm volatile ("" ::: "memory"); \ + } \ + } + +int +main (void) +{ + FOR_EACH_INV (TEST_LOOP) + return 0; +} diff --git a/gcc/testsuite/gcc.target/aarch64/sve/vcond_16.c b/gcc/testsuite/gcc.target/aarch64/sve/vcond_16.c new file mode 100644 index 00000000000..7fa98716830 --- /dev/null +++ b/gcc/testsuite/gcc.target/aarch64/sve/vcond_16.c @@ -0,0 +1,58 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -ftree-vectorize" } */ + +#define N 119 + +#define DEF_LOOP(INV, TYPE, CMPTYPE, SUFFIX) \ + void __attribute__ ((noipa)) \ + f_##INV##_##SUFFIX (TYPE *restrict a, TYPE *restrict b, \ + TYPE *restrict c, TYPE *restrict d, \ + CMPTYPE *restrict cond) \ + { \ + for (int i = 0; i < N; ++i) \ + { \ + TYPE mb = (INV & 1 ? -b[i] : b[i]); \ + TYPE mc = c[i]; \ + TYPE md = (INV & 2 ? -d[i] : d[i]); \ + TYPE fma = __builtin_fma##SUFFIX (mb, mc, md); \ + TYPE truev = (INV & 4 ? -fma : fma); \ + a[i] = cond[i] < 10 ? truev : 10; \ + } \ + } + +#define FOR_EACH_TYPE(T, INV) \ + T (INV, _Float16, short, f16) \ + T (INV, float, float, f32) \ + T (INV, double, double, f64) + +#define FOR_EACH_INV(T) \ + FOR_EACH_TYPE (T, 0) \ + FOR_EACH_TYPE (T, 1) \ + FOR_EACH_TYPE (T, 2) \ + FOR_EACH_TYPE (T, 3) \ + FOR_EACH_TYPE (T, 4) \ + FOR_EACH_TYPE (T, 5) \ + FOR_EACH_TYPE (T, 6) \ + FOR_EACH_TYPE (T, 7) + +FOR_EACH_INV (DEF_LOOP) + +/* { dg-final { scan-assembler-times {\tsel\t} 24 } } */ +/* { dg-final { scan-assembler-not {\tmovprfx\t} } } */ +/* { dg-final { scan-assembler-not {\tmov\tz[0-9]+\.., z[0-9]+} } } */ + +/* { dg-final { scan-assembler-times {\tfmla\tz[0-9]+\.h,} 2 } } */ +/* { dg-final { scan-assembler-times {\tfmla\tz[0-9]+\.s,} 2 } } */ +/* { dg-final { scan-assembler-times {\tfmla\tz[0-9]+\.d,} 2 } } */ + +/* { dg-final { scan-assembler-times {\tfmls\tz[0-9]+\.h,} 2 } } */ +/* { dg-final { scan-assembler-times {\tfmls\tz[0-9]+\.s,} 2 } } */ +/* { dg-final { scan-assembler-times {\tfmls\tz[0-9]+\.d,} 2 } } */ + +/* { dg-final { scan-assembler-times {\tfnmla\tz[0-9]+\.h,} 2 } } */ +/* { dg-final { scan-assembler-times {\tfnmla\tz[0-9]+\.s,} 2 } } */ +/* { dg-final { scan-assembler-times {\tfnmla\tz[0-9]+\.d,} 2 } } */ + +/* { dg-final { scan-assembler-times {\tfnmls\tz[0-9]+\.h,} 2 } } */ +/* { dg-final { scan-assembler-times {\tfnmls\tz[0-9]+\.s,} 2 } } */ +/* { dg-final { scan-assembler-times {\tfnmls\tz[0-9]+\.d,} 2 } } */ diff --git a/gcc/testsuite/gcc.target/aarch64/sve/vcond_16_run.c b/gcc/testsuite/gcc.target/aarch64/sve/vcond_16_run.c new file mode 100644 index 00000000000..d4e5afd4d57 --- /dev/null +++ b/gcc/testsuite/gcc.target/aarch64/sve/vcond_16_run.c @@ -0,0 +1,37 @@ +/* { dg-do run { target aarch64_sve_hw } } */ +/* { dg-options "-O2 -ftree-vectorize" } */ + +#include "vcond_16.c" + +#define TEST_LOOP(INV, TYPE, CMPTYPE, SUFFIX) \ + { \ + TYPE a[N], b[N], c[N], d[N]; \ + CMPTYPE cond[N]; \ + for (int i = 0; i < N; ++i) \ + { \ + b[i] = i % 15; \ + c[i] = i % 9 + 11; \ + d[i] = i % 13 + 14; \ + cond[i] = i % 17; \ + asm volatile ("" ::: "memory"); \ + } \ + f_##INV##_##SUFFIX (a, b, c, d, cond); \ + for (int i = 0; i < N; ++i) \ + { \ + double mb = (INV & 1 ? -b[i] : b[i]); \ + double mc = c[i]; \ + double md = (INV & 2 ? -d[i] : d[i]); \ + double fma = __builtin_fma (mb, mc, md); \ + double truev = (INV & 4 ? -fma : fma); \ + if (a[i] != (i % 17 < 10 ? truev : 10)) \ + __builtin_abort (); \ + asm volatile ("" ::: "memory"); \ + } \ + } + +int +main (void) +{ + FOR_EACH_INV (TEST_LOOP) + return 0; +} -- cgit v1.2.3