This is the mail archive of the
gcc@gcc.gnu.org
mailing list for the GCC project.
Re: [GSoC-19] Implementing narrowing functions like fadd
- From: Tejas Joshi <tejasjoshi9673 at gmail dot com>
- To: gcc at gcc dot gnu dot org
- Cc: Martin Jambor <mjambor at suse dot cz>, hubicka at ucw dot cz, joseph at codesourcery dot com
- Date: Tue, 6 Aug 2019 21:16:14 +0530
- Subject: Re: [GSoC-19] Implementing narrowing functions like fadd
- References: <CACMrGjDsV4WZXK8FnTjiZRpgJMxbw7OCQGPBQtdObsKaJmedTQ@mail.gmail.com> <CACMrGjBKUv4T+LLrk5-ruMabt4d972HaCRANLbPTZ95_hXyW1A@mail.gmail.com> <CACMrGjDKCkGSzofy1=XoeOts8UvehAjx4_2biT8JShxTj=8RAQ@mail.gmail.com> <mpt36jenk70.fsf@arm.com> <CACMrGjDh7tAz=UMqjcEUmNHmbwWN+F_4PTFR5hNjzV8K6jGAgA@mail.gmail.com> <ri68ssk1znm.fsf@suse.cz> <CACMrGjBfT9kznDM+vS18KiAFektS=c9X8es4Z-WY81TYMwqDzA@mail.gmail.com> <ri6lfwgzro7.fsf@suse.cz> <CACMrGjAcu2fKtr2r=upL0Nk3Xd+gPcFa7gX53oj341_gNvWdLA@mail.gmail.com> <CACMrGjD5c8o3s2ruqk-EQ4VC7ir7tCVH=mX-xnADQ_d7AKjYPg@mail.gmail.com>
Hello.
I have come up with the testcases for fadd variants and the following
patch comes with them. Again, the patch follows the points mentioned
above and if good to go, I will post it to the gcc-patches. The patch
bootstraps and survives regression tests.
Thanks,
Tejas
On Fri, 2 Aug 2019 at 16:10, Tejas Joshi <tejasjoshi9673@gmail.com> wrote:
>
> 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 <tejasjoshi9673@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 <mjambor@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 *);
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;
+}