Hello. I have made this patch strictly considering the following points Joseph mentioned in his initial email :
> * The narrowing functions, e.g. fadd, faddl, daddl, are a bit different > from most other built-in math.h functions because the return type is > different from the argument types. You could start by adding them to > builtins.def similarly to roundeven (with new macros to handle adding such > functions for relevant pairs of _FloatN, _FloatNx types). These functions > could be folded for constant arguments only if the result is exact, or if > -fno-rounding-math -fno-trapping-math (and -fno-math-errno if the result > involves overflow / underflow). I am trying to come up with testcases which would work around -fno-rounding-math -fno-trapping-math and -fno-math-errno while considering inexact and overlfow/underflow cases. I will try them as soon as possible and send another patch with them and after regression testing. Apart from that, am I missing something in this patch? Thanks, Tejas On Wed, 31 Jul 2019 at 12:06, Tejas Joshi <tejasjoshi9...@gmail.com> wrote: > > Hello. > > > fold_const_fadd), for example I am not sure what the return values are > > supposed to mean, and add a run-time testcase(s) and I'd say you are > > done for now > > I modeled real_fadd function on a similar function, real_nextafter > which would take three arguments. Just as overflow and underflow > conditions are handled there, I thought similarly if exact/inexact and > overflow/underflow conditions would be handled by fold_const_fadd for > real_fadd. As these conditions are still need to be addressed (so > current function is prototypish), is real_nextafter a good model to > refer? > > > I am not sure I understand your question, you have used real_convert in > > real_fadd and it seems to be doing exactly that? As you know I am not > > Looking at different comments where real_convert is used, I guessed it > formats GCC's floating point format to a target format rather than > converting to return type. Its still unclear to me but its good if it > does convert to return type like it seems. I am working on these > conditions now and will try to come up with testcases. > > Thanks, > Tejas > > > On Mon, 29 Jul 2019 at 22:47, Martin Jambor <mjam...@suse.cz> wrote: > > > > Hi, > > > > On Sat, Jul 27 2019, Tejas Joshi wrote: > > > Hello. > > > > > >>> You'll need something different from CASE_MATHFN - these are a different > > >>> kind of functions that need handling in a different way, because they > > >>> are > > >>> parametrized over certain *pairs* of types, rather than over a single > > >>> type. > > >> first phase, please just directly test for in the code for > > >> CFN_BUILT_IN_FADD, CFN_BUILT_IN_FADDL, CFN_BUILT_IN_DADDL and process > > >> those here to get a prototype working. When you add support for more > > > > > > Thanks for the inputs. I have used CFN_BUILT_IN_FADD, etc in this > > > following patch and function is getting folded. > > > > good. Please add comments to functions which miss them (real_fadd and > > fold_const_fadd), for example I am not sure what the return values are > > supposed to mean, and add a run-time testcase(s) and I'd say you are > > done for now - after you implement fsub, fmul and fdiv(?) you might want > > to re-structure some common bits to make the code prettier. > > > > > My question is that how the addition and narrowing should be performed > > > (is it ok to use do_add for addition?). > > > > I don't see a reason why it would not be. > > > > > As functions in real.c does > > > not operate on any specific precision, just defining the return type > > > as float would do the trick? Or do I need to make trailing > > > out-of-precision bits zero? If yes, having functions like > > > double_to_float would then be useful or such functions already exist > > > to do the conversion? > > > > I am not sure I understand your question, you have used real_convert in > > real_fadd and it seems to be doing exactly that? As you know I am not > > too familiar with this area of gcc but reading the code suggests that > > and a simple debugging session seems to confirm that (some unimportant > > gdb output omitted): > > > > ---------------------------------------------------------------------- > > $ ~/gcc/gsoc/inst/bin/gcc -Ofast -S fadd-fold.c -wrapper gdb,--args > > GNU gdb (GDB; openSUSE Tumbleweed) 8.3 > > Copyright (C) 2019 Free Software Foundation, Inc. > > License GPLv3+: GNU GPL version 3 or later > > <http://gnu.org/licenses/gpl.html> > > > > (gdb) b real_fadd > > Breakpoint 1 at 0x108215b: file /home/mjambor/gcc/gsoc/src/gcc/real.c, line > > 5100. > > (gdb) r > > Starting program: > > /home/mjambor/gcc/gsoc/inst/lib/gcc/x86_64-pc-linux-gnu/10.0.0/cc1 -quiet > > fadd-fold.c -quiet -dumpbase fadd-fold.c -mtune=generic -march=x86-64 > > -auxbase fadd-fold -Ofast -o fadd-fold.s > > > > Breakpoint 1, real_fadd (r=0x7fffffffc580, fmt=..., x=0x7ffff7800060, > > y=0x7ffff7800080) > > at /home/mjambor/gcc/gsoc/src/gcc/real.c:5100 > > 5100 do_add (r, x, y, 0); > > (gdb) n > > 5101 if (fmt) > > (gdb) p *r > > $1 = {cl = 1, decimal = 0, sign = 0, signalling = 0, canonical = 0, uexp = > > 5, sig = {0, 0, > > 10549231767152649216}} > > (gdb) p/x r->sig[2] > > $2 = 0x9266666666666400 > > (gdb) n > > 5102 real_convert (r, fmt, r); > > (gdb) > > 5103 return false; > > (gdb) p/x r->sig[2] > > $3 = 0x9266660000000000 > > ---------------------------------------------------------------------- > > > > Thanks, > > > > Martin > > > >
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 *);