Hi. This patch includes fadd variants implementation for folding. The patch bootstraps and survives regression tests on x86_64-linux-gnu.
Thanks, Tejas gcc/ChangeLog: 2019-08-08 Tejas Joshi <tejasjoshi9...@gmail.com> * builtin-types.def: New function type variable arguments. * builtins.def: New function definitions for fadd variants. * fold-const-call.c (fold_const_fadd): New function for folding fadd variants. (fold_const_call): Add new cases for fadd variants. * real.c (real_fadd): New function. Performs addition of two numbers and returns result in narrowed down type. * real.h: New function declaration for real_fadd. gcc/testsuite/ChangeLog: 2019-08-08 Tejas Joshi <tejasjoshi9...@gmail.com> * testsuite/gcc.dg/builtin-fadd-1.c: New test. * testsuite/gcc.dg/builtin-fadd-2.c: New test.
diff --git a/gcc/builtin-types.def b/gcc/builtin-types.def index e5c9e063c48..6bc552fa71a 100644 --- a/gcc/builtin-types.def +++ b/gcc/builtin-types.def @@ -387,8 +387,14 @@ DEF_FUNCTION_TYPE_2 (BT_FN_VOID_UINT_PTR, BT_VOID, BT_UINT, BT_PTR) DEF_FUNCTION_TYPE_2 (BT_FN_FLOAT_FLOAT_FLOAT, BT_FLOAT, BT_FLOAT, BT_FLOAT) +DEF_FUNCTION_TYPE_2 (BT_FN_FLOAT_DOUBLE_DOUBLE, + BT_FLOAT, BT_DOUBLE, BT_DOUBLE) +DEF_FUNCTION_TYPE_2 (BT_FN_FLOAT_LONGDOUBLE_LONGDOUBLE, + BT_FLOAT, BT_LONGDOUBLE, BT_LONGDOUBLE) DEF_FUNCTION_TYPE_2 (BT_FN_DOUBLE_DOUBLE_DOUBLE, BT_DOUBLE, BT_DOUBLE, BT_DOUBLE) +DEF_FUNCTION_TYPE_2 (BT_FN_DOUBLE_LONGDOUBLE_LONGDOUBLE, + BT_DOUBLE, BT_LONGDOUBLE, BT_LONGDOUBLE) DEF_FUNCTION_TYPE_2 (BT_FN_LONGDOUBLE_LONGDOUBLE_LONGDOUBLE, BT_LONGDOUBLE, BT_LONGDOUBLE, BT_LONGDOUBLE) DEF_FUNCTION_TYPE_2 (BT_FN_FLOAT16_FLOAT16_FLOAT16, diff --git a/gcc/builtins.def b/gcc/builtins.def index 8bb7027aac7..2df616c477e 100644 --- a/gcc/builtins.def +++ b/gcc/builtins.def @@ -355,6 +355,9 @@ DEF_EXT_LIB_FLOATN_NX_BUILTINS (BUILT_IN_FABS, "fabs", FABS_TYPE, ATTR_CONST_NOT DEF_GCC_BUILTIN (BUILT_IN_FABSD32, "fabsd32", BT_FN_DFLOAT32_DFLOAT32, ATTR_CONST_NOTHROW_LEAF_LIST) DEF_GCC_BUILTIN (BUILT_IN_FABSD64, "fabsd64", BT_FN_DFLOAT64_DFLOAT64, ATTR_CONST_NOTHROW_LEAF_LIST) DEF_GCC_BUILTIN (BUILT_IN_FABSD128, "fabsd128", BT_FN_DFLOAT128_DFLOAT128, ATTR_CONST_NOTHROW_LEAF_LIST) +DEF_EXT_LIB_BUILTIN (BUILT_IN_FADD, "fadd", BT_FN_FLOAT_DOUBLE_DOUBLE, ATTR_CONST_NOTHROW_LEAF_LIST) +DEF_EXT_LIB_BUILTIN (BUILT_IN_FADDL, "faddl", BT_FN_FLOAT_LONGDOUBLE_LONGDOUBLE, ATTR_CONST_NOTHROW_LEAF_LIST) +DEF_EXT_LIB_BUILTIN (BUILT_IN_DADDL, "daddl", BT_FN_DOUBLE_LONGDOUBLE_LONGDOUBLE, ATTR_CONST_NOTHROW_LEAF_LIST) DEF_C99_BUILTIN (BUILT_IN_FDIM, "fdim", BT_FN_DOUBLE_DOUBLE_DOUBLE, ATTR_MATHFN_FPROUNDING_ERRNO) DEF_C99_BUILTIN (BUILT_IN_FDIMF, "fdimf", BT_FN_FLOAT_FLOAT_FLOAT, ATTR_MATHFN_FPROUNDING_ERRNO) DEF_C99_BUILTIN (BUILT_IN_FDIML, "fdiml", BT_FN_LONGDOUBLE_LONGDOUBLE_LONGDOUBLE, ATTR_MATHFN_FPROUNDING_ERRNO) diff --git a/gcc/fold-const-call.c b/gcc/fold-const-call.c index d9b546e6803..f895c89de96 100644 --- a/gcc/fold-const-call.c +++ b/gcc/fold-const-call.c @@ -570,6 +570,32 @@ fold_const_nextafter (real_value *result, const real_value *arg0, return true; } +/* Try to evaluate: + + *RESULT = fadd (*ARG0, *ARG1) + + in format FORMAT. Return true on success. */ + +static bool +fold_const_fadd (real_value *result, const real_value *arg0, + const real_value *arg1, const real_format *format) +{ + if (REAL_VALUE_ISSIGNALING_NAN (*arg0) + || REAL_VALUE_ISSIGNALING_NAN (*arg1)) + return false; + + if (real_fadd (result, format, arg0, arg1) + && !flag_errno_math) + return false; + + if (!exact_real_truncate (format, result) + && !(flag_rounding_math && flag_trapping_math)) + return false; + + real_convert (result, format, result); + return true; +} + /* Try to evaluate: *RESULT = ldexp (*ARG0, ARG1) @@ -1644,6 +1670,25 @@ fold_const_call (combined_fn fn, tree type, tree arg0, tree arg1) case CFN_FOLD_LEFT_PLUS: return fold_const_fold_left (type, arg0, arg1, PLUS_EXPR); + case CFN_BUILT_IN_FADD: + case CFN_BUILT_IN_FADDL: + case CFN_BUILT_IN_DADDL: + { + if (real_cst_p (arg0) + && real_cst_p (arg1)) + { + machine_mode arg0_mode = TYPE_MODE (TREE_TYPE (arg0)); + gcc_checking_assert (SCALAR_FLOAT_MODE_P (arg0_mode)); + REAL_VALUE_TYPE result; + machine_mode mode = TYPE_MODE (type); + if (fold_const_fadd (&result, TREE_REAL_CST_PTR (arg0), + TREE_REAL_CST_PTR (arg1), + REAL_MODE_FORMAT (mode))) + return build_real (type, result); + } + } + return NULL_TREE; + default: return fold_const_call_1 (fn, type, arg0, arg1); } diff --git a/gcc/real.c b/gcc/real.c index ab71430709f..280e434e897 100644 --- a/gcc/real.c +++ b/gcc/real.c @@ -5093,6 +5093,30 @@ real_roundeven (REAL_VALUE_TYPE *r, format_helper fmt, real_round (r, fmt, x); } +/* Perform addition of X and Y and place the result in R to narrowed + down type. Return TRUE if result involves overflow/underflow. */ + +bool +real_fadd (REAL_VALUE_TYPE *r, format_helper fmt, + const REAL_VALUE_TYPE *x, const REAL_VALUE_TYPE *y) +{ + do_add (r, x, y, 0); + + /* Overflow/underflow check. */ + if (REAL_EXP (r) > fmt->emax) + { + get_inf (r, r->sign); + return true; + } + if (REAL_EXP (r) < fmt->emin) + { + get_zero (r, r->sign); + return true; + } + + return false; +} + /* Set the sign of R to the sign of X. */ void diff --git a/gcc/real.h b/gcc/real.h index 76889bff0ea..f9d388f491b 100644 --- a/gcc/real.h +++ b/gcc/real.h @@ -510,6 +510,10 @@ extern void real_round (REAL_VALUE_TYPE *, format_helper, extern void real_roundeven (REAL_VALUE_TYPE *, format_helper, const REAL_VALUE_TYPE *); +/* Narrowing type standard math operations functions. */ +extern bool real_fadd (REAL_VALUE_TYPE *, format_helper, + const REAL_VALUE_TYPE *, const REAL_VALUE_TYPE *); + /* Set the sign of R to the sign of X. */ extern void real_copysign (REAL_VALUE_TYPE *, const REAL_VALUE_TYPE *); diff --git a/gcc/testsuite/gcc.dg/builtin-fadd-1.c b/gcc/testsuite/gcc.dg/builtin-fadd-1.c new file mode 100644 index 00000000000..958d5a019d7 --- /dev/null +++ b/gcc/testsuite/gcc.dg/builtin-fadd-1.c @@ -0,0 +1,31 @@ +/* { dg-do run } */ +/* { dg-options "-O2" } */ + +#define TEST(FN, VAL1, VAL2, RESULT) \ + if (__builtin_##FN (VAL1, VAL2) != RESULT) __builtin_abort (); + +int +main (void) +{ + TEST(fadd, 0, 0, 0.0F); + TEST(fadd, 1, -1, 0.0F); + TEST(fadd, -1, -1.5, -2.5F); + TEST(fadd, 1.4, 1.6, 3.0F); + TEST(fadd, 2.5, 1.5, 4.0F); + TEST(fadd, __FLT_MAX__, __FLT_MAX__/2, 3*__FLT_MAX__/2); + + TEST(faddl, 0.0L, 0.0L, 0.0F); + TEST(faddl, 1.0L, -1.0L, 0.0F); + TEST(faddl, -1.0L, -1.5L, -2.5F); + TEST(faddl, 1.4L, 1.6L, 3.0F); + TEST(faddl, 2.5L, 1.5L, 4.0F); + TEST(faddl, __FLT_MAX__, __FLT_MAX__/2, 3*__FLT_MAX__/2); + + TEST(daddl, 0L, 0L, 0.0); + TEST(daddl, 1L, -1L, 0.0); + TEST(daddl, -1L, -1.5L, -2.5); + TEST(daddl, 1.4L, 1.6L, 3.0); + TEST(daddl, 2.5L, 1.5L, 4.0); + TEST(daddl, __DBL_MAX__, __DBL_MAX__/2, 3*__DBL_MAX__/2); + return 0; +} diff --git a/gcc/testsuite/gcc.dg/builtin-fadd-2.c b/gcc/testsuite/gcc.dg/builtin-fadd-2.c new file mode 100644 index 00000000000..76c81ae0470 --- /dev/null +++ b/gcc/testsuite/gcc.dg/builtin-fadd-2.c @@ -0,0 +1,38 @@ +/* { dg-do run } */ +/* { dg-options "-O2 -frounding-math" } */ + +#define TEST(FN, VAL1, VAL2, RESULT) \ + if (__builtin_##FN (VAL1, VAL2) != RESULT) __builtin_abort (); + +int +main (void) +{ + TEST(fadd, 1, 1.1, 2.1F); + TEST(fadd, 3, 4.2, 7.2F); + TEST(fadd, 2, 4.3, 6.3F); + TEST(fadd, -2, -2.4, -4.4F); + TEST(fadd, -3, -3.6, -6.6F); + TEST(fadd, -5.3, -5.4, -10.7F); + TEST(fadd, 8, 0.8, 8.8F); + TEST(fadd, 0.5, 0.4, 0.9F); + + TEST(faddl, 1.0L, 1.1L, 2.1F); + TEST(faddl, 3.0L, 4.2L, 7.2F); + TEST(faddl, 2.0L, 4.3L, 6.3F); + TEST(faddl, -2.0L, -2.4L, -4.4F); + TEST(faddl, -3.0L, -3.6L, -6.6F); + TEST(faddl, -5.3L, -5.4L, -10.7F); + TEST(faddl, 8.0L, 0.8L, 8.8F); + TEST(faddl, 0.5L, 0.4L, 0.9F); + + TEST(daddl, 1.0L, 1.1L, 2.1); + TEST(daddl, 3.0L, 4.2L, 7.2); + TEST(daddl, 2.0L, 4.3L, 6.3); + TEST(daddl, -2.0L, -2.4L, -4.4); + TEST(daddl, -3.0L, -3.6L, -6.6); + TEST(daddl, -5.3L, -5.4L, -10.7); + TEST(daddl, 8.0L, 0.8L, 8.8); + TEST(daddl, 0.5L, 0.4L, 0.9); + + return 0; +}