public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
From: Aldy Hernandez <aldyh@redhat.com>
To: Jakub Jelinek <jakub@redhat.com>
Cc: Joseph Myers <joseph@codesourcery.com>,
	GCC patches <gcc-patches@gcc.gnu.org>,
	 Andrew MacLeod <amacleod@redhat.com>
Subject: Re: [PATCH] [range-ops] Implement sqrt.
Date: Thu, 17 Nov 2022 17:40:59 +0100	[thread overview]
Message-ID: <CAGm3qMUURJJWRpCt42Ne7r_+EWqxB2fghdhSjR9EuLAJzUfp=w@mail.gmail.com> (raw)
In-Reply-To: <Y3VI+Jn294KcUInD@tucnak>

[-- Attachment #1: Type: text/plain, Size: 4460 bytes --]

To go along with whatever magic we're gonna tack along to the
range-ops sqrt implementation, here is another revision addressing the
VARYING issue you pointed out.

A few things...

Instead of going through trees, I decided to call do_mpfr_arg1
directly.  Let's not go the wide int <-> tree rat hole in this one.

The function do_mpfr_arg1 bails on +INF, so I had to handle it manually.

There's a regression in gfortran.dg/ieee/ieee_6.f90, which I'm not
sure how to handle.  We are failing because we are calculating
sqrt(-1) and expecting certain IEEE flags set.  These flags aren't
set, presumably because we folded sqrt(-1) into a NAN directly:

    // All negatives.
    if (real_compare (LT_EXPR, &lh_ub, &dconst0))
      {
    real_nan (&lb, "", 0, TYPE_MODE (type));
    ub = lb;
    maybe_nan = true;
    return;
      }

The failing part of the test is:

  if (.not. (all(flags .eqv. [.false.,.false.,.true.,.true.,.false.]) &
             .or. all(flags .eqv. [.false.,.false.,.true.,.true.,.true.]) &
             .or. all(flags .eqv. [.false.,.false.,.true.,.false.,.false.]) &
             .or. all(flags .eqv.
[.false.,.false.,.true.,.false.,.true.]))) STOP 5

But we are generating F F F F F.  Google has informed me that that 3rd
flag is IEEE_INVALID.

So... is the optimization wrong?  Are we not allowed to substitute
that NAN if we know it's gonna happen?  Should we also allow F F F F F
in the test?  Or something else?

Thanks.
Aldy

On Wed, Nov 16, 2022 at 9:33 PM Jakub Jelinek <jakub@redhat.com> wrote:
>
> On Mon, Nov 14, 2022 at 09:55:29PM +0000, Joseph Myers wrote:
> > On Sun, 13 Nov 2022, Jakub Jelinek via Gcc-patches wrote:
> >
> > > So, I wonder if we don't need to add a target hook where targets will be
> > > able to provide upper bound on error for floating point functions for
> > > different floating point modes and some way to signal unknown accuracy/can't
> > > be trusted, in which case we would give up or return just the range for
> > > VARYING.
> >
> > Note that the figures given in the glibc manual are purely empirical
> > (largest errors observed for inputs in the glibc testsuite on a system
> > that was then used to update the libm-test-ulps files); they don't
> > constitute any kind of guarantee about either the current implementation
> > or the API, nor are they formally verified, nor do they come from
> > exhaustive testing (though worst cases from exhaustive testing for float
> > may have been added to the glibc testsuite in some cases).  (I think the
> > only functions known to give huge errors for some inputs, outside of any
> > IBM long double issues, are the Bessel functions and cpow functions.  But
> > even if other functions don't have huge errors, and some
> > architecture-specific implementations might have issues, there are
> > certainly some cases where errors can exceed the 9ulp threshold on what
> > the libm tests will accept in libm-test-ulps files, which are thus
> > considered glibc bugs.  (That's 9ulp from the correctly rounded value,
> > computed in ulp of that value.  For IBM long double it's 16ulp instead,
> > treating the format as having a fixed 106 bits of precision.  Both figures
> > are empirical ones chosen based on what bounds sufficed for most libm
> > functions some years ago; ideally, with better implementations of some
> > functions we could probably bring those numbers down.))
>
> I know I can't get guarantees without formal proofs and even ulps from
> reported errors are better than randomized testing.
> But I think at least for non-glibc we want to be able to get a rough idea
> of the usual error range in ulps.
>
> This is what I came up with so far (link with
> gcc -o ulp-tester{,.c} -O2 -lmpfr -lm
> ), it still doesn't verify that functions are always within the mathematical
> range of results ([-0.0, Inf] for sqrt, [-1.0, 1.0] for sin/cos etc.), guess
> that would be useful and verify the program actually does what is intended.
> One can supply just one argument (number of tests, first 46 aren't really
> random) or two, in the latter case the second should be upward, downward or
> towardzero to use non-default rounding mode.
> The idea is that we'd collect ballpark estimates for roundtonearest and
> then estimates for the other 3 rounding modes, the former would be used
> without -frounding-math, max over all 4 rounding modes for -frounding-math
> as gcc will compute using mpfr always in round to nearest.
>
>         Jakub

[-- Attachment #2: 0001-range-ops-Implement-sqrt.patch --]
[-- Type: text/x-patch, Size: 4584 bytes --]

From 759bcd4b4b6f70fcec045b24fb6874aaca989549 Mon Sep 17 00:00:00 2001
From: Aldy Hernandez <aldyh@redhat.com>
Date: Sun, 13 Nov 2022 18:39:59 +0100
Subject: [PATCH] [range-ops] Implement sqrt.

gcc/ChangeLog:

	* fold-const-call.cc (do_mpfr_arg1): Remove static.
	* gimple-range-op.cc (class cfn_sqrt): New.
	(gimple_range_op_handler::maybe_builtin_call): Add sqrt case.
	* realmpfr.h (do_mpfr_arg1): Add extern.

gcc/testsuite/ChangeLog:

	* gcc.dg/tree-ssa/vrp124.c: New test.
---
 gcc/fold-const-call.cc                 |  2 +-
 gcc/gimple-range-op.cc                 | 56 ++++++++++++++++++++++++++
 gcc/realmpfr.h                         |  4 ++
 gcc/testsuite/gcc.dg/tree-ssa/vrp124.c | 16 ++++++++
 4 files changed, 77 insertions(+), 1 deletion(-)
 create mode 100644 gcc/testsuite/gcc.dg/tree-ssa/vrp124.c

diff --git a/gcc/fold-const-call.cc b/gcc/fold-const-call.cc
index 8ceed8f02f9..5c6b852acdc 100644
--- a/gcc/fold-const-call.cc
+++ b/gcc/fold-const-call.cc
@@ -118,7 +118,7 @@ do_mpfr_ckconv (real_value *result, mpfr_srcptr m, bool inexact,
    in format FORMAT, given that FUNC is the MPFR implementation of f.
    Return true on success.  */
 
-static bool
+bool
 do_mpfr_arg1 (real_value *result,
 	      int (*func) (mpfr_ptr, mpfr_srcptr, mpfr_rnd_t),
 	      const real_value *arg, const real_format *format)
diff --git a/gcc/gimple-range-op.cc b/gcc/gimple-range-op.cc
index 7764166d5fb..f1f2f098305 100644
--- a/gcc/gimple-range-op.cc
+++ b/gcc/gimple-range-op.cc
@@ -43,6 +43,8 @@ along with GCC; see the file COPYING3.  If not see
 #include "range.h"
 #include "value-query.h"
 #include "gimple-range.h"
+#include "fold-const-call.h"
+#include "realmpfr.h"
 
 // Given stmt S, fill VEC, up to VEC_SIZE elements, with relevant ssa-names
 // on the statement.  For efficiency, it is an error to not pass in enough
@@ -301,6 +303,54 @@ public:
   }
 } op_cfn_constant_p;
 
+// Implement range operator for SQRT.
+class cfn_sqrt : public range_operator_float
+{
+  using range_operator_float::fold_range;
+private:
+  void rv_fold (REAL_VALUE_TYPE &lb, REAL_VALUE_TYPE &ub, bool &maybe_nan,
+		tree type,
+		const REAL_VALUE_TYPE &lh_lb,
+		const REAL_VALUE_TYPE &lh_ub,
+		const REAL_VALUE_TYPE &,
+		const REAL_VALUE_TYPE &,
+		relation_kind) const final override
+  {
+    // All negatives.
+    if (real_compare (LT_EXPR, &lh_ub, &dconst0))
+      {
+	real_nan (&lb, "", 0, TYPE_MODE (type));
+	ub = lb;
+	maybe_nan = true;
+	return;
+      }
+    const real_format *format = REAL_MODE_FORMAT (TYPE_MODE (type));
+    // All positives.
+    if (real_compare (GE_EXPR, &lh_lb, &dconst0))
+      {
+	// ?? Handle +INF manually since do_mpfr_arg1 does not.
+	if (real_isinf (&lh_lb, 0))
+	  lb = lh_lb;
+	else if (!do_mpfr_arg1 (&lb, mpfr_sqrt, &lh_lb, format))
+	  {
+	    lb = dconst0;
+	    lb.sign = 1;
+	  }
+	maybe_nan = false;
+      }
+    // Both positives and negatives.
+    else
+      {
+	// Range is [-0.0, sqrt(lh_ub)] +-NAN.
+	lb = dconst0;
+	lb.sign = 1;
+	maybe_nan = true;
+      }
+    if (!do_mpfr_arg1 (&ub, mpfr_sqrt, &lh_ub, format))
+      ub = dconstinf;
+  }
+} fop_cfn_sqrt;
+
 // Implement range operator for CFN_BUILT_IN_SIGNBIT.
 class cfn_signbit : public range_operator_float
 {
@@ -907,6 +957,12 @@ gimple_range_op_handler::maybe_builtin_call ()
       m_int = &op_cfn_parity;
       break;
 
+    CASE_CFN_SQRT_ALL:
+      m_valid = true;
+      m_op1 = gimple_call_arg (call, 0);
+      m_float = &fop_cfn_sqrt;
+      break;
+
     default:
       break;
     }
diff --git a/gcc/realmpfr.h b/gcc/realmpfr.h
index edc08385fe8..807dd2308d2 100644
--- a/gcc/realmpfr.h
+++ b/gcc/realmpfr.h
@@ -32,4 +32,8 @@ extern void real_from_mpfr (REAL_VALUE_TYPE *, mpfr_srcptr,
 			    const real_format *, mpfr_rnd_t);
 extern void mpfr_from_real (mpfr_ptr, const REAL_VALUE_TYPE *, mpfr_rnd_t);
 
+extern bool do_mpfr_arg1 (real_value *result,
+			  int (*func) (mpfr_ptr, mpfr_srcptr, mpfr_rnd_t),
+			  const real_value *arg, const real_format *format);
+
 #endif /* ! GCC_REALGMP_H */
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/vrp124.c b/gcc/testsuite/gcc.dg/tree-ssa/vrp124.c
new file mode 100644
index 00000000000..ef72d660153
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/vrp124.c
@@ -0,0 +1,16 @@
+// { dg-do compile }
+// { dg-options "-O2 -fdump-tree-evrp -fdisable-tree-ethread" }
+
+void link_error ();
+
+void foo (float f)
+{
+  float z = __builtin_sqrt (f);
+  if (!__builtin_isnan (z))
+    {
+      if (z < 0.0)
+	link_error ();
+    }
+}
+
+// { dg-final { scan-tree-dump-not "link_error" "evrp" } }
-- 
2.38.1


  reply	other threads:[~2022-11-17 16:41 UTC|newest]

Thread overview: 21+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2022-11-13 20:05 Aldy Hernandez
2022-11-13 20:39 ` Jakub Jelinek
2022-11-14  7:45   ` Aldy Hernandez
2022-11-14 14:30     ` Jeff Law
2022-11-14 14:35       ` Jakub Jelinek
2022-11-14 14:48         ` Jeff Law
2022-11-14 15:01         ` Aldy Hernandez
2022-11-14 21:55   ` Joseph Myers
2022-11-16 20:32     ` Jakub Jelinek
2022-11-17 16:40       ` Aldy Hernandez [this message]
2022-11-17 16:48         ` Aldy Hernandez
2022-11-17 17:42           ` Aldy Hernandez
2022-11-17 18:59         ` Joseph Myers
2022-11-17 19:37           ` Jakub Jelinek
2022-11-17 20:43             ` Joseph Myers
2022-11-18  8:39             ` Richard Biener
2022-11-18 10:37               ` Aldy Hernandez
2022-11-18 10:44                 ` Jakub Jelinek
2022-11-18 11:20                   ` Aldy Hernandez
2022-11-18 11:57                     ` Aldy Hernandez
2022-11-18 12:14                   ` Richard Biener

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to='CAGm3qMUURJJWRpCt42Ne7r_+EWqxB2fghdhSjR9EuLAJzUfp=w@mail.gmail.com' \
    --to=aldyh@redhat.com \
    --cc=amacleod@redhat.com \
    --cc=gcc-patches@gcc.gnu.org \
    --cc=jakub@redhat.com \
    --cc=joseph@codesourcery.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).