This is the mail archive of the gcc@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: [GSoC-19] Implementing narrowing functions like fadd


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;
+} 

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]