public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
From: Aldy Hernandez <aldyh@redhat.com>
To: Jeff Law <jeffreyalaw@gmail.com>
Cc: Andrew MacLeod <amacleod@redhat.com>,
	Roger Sayle <roger@nextmovesoftware.com>,
	 Richard Biener <richard.guenther@gmail.com>,
	GCC Patches <gcc-patches@gcc.gnu.org>
Subject: Re: [PATCH] Ignore (possible) signed zeros in operands of FP comparisons.
Date: Mon, 21 Mar 2022 16:56:15 +0100	[thread overview]
Message-ID: <CAGm3qMV4pujGhLNYBdPOt2GdpQ9yz_Tnjd77KfSeX1KrskGmmg@mail.gmail.com> (raw)
In-Reply-To: <CAGm3qMU8RBAgyQO1Q9-8ZRSpuzhOdzhJBmX40hXFBVVO8FhroQ@mail.gmail.com>

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

On Fri, Mar 18, 2022 at 7:33 PM Aldy Hernandez <aldyh@redhat.com> wrote:

> > >>>>> Consider the following interesting example:
> > >>>>>
> > >>>>> int foo(int x, double y) {
> > >>>>>      return (x * 0.0) < y;
> > >>>>> }
> > >>>>>
> > >>>>> Although we know that x (when converted to double) can't be NaN or
> > >>>>> Inf, we still worry that for negative values of x that (x * 0.0) may
> > >>>>> be -0.0 and so perform the multiplication at run-time. But in this
> > >>>>> case, the result of the comparison (-0.0 < y) will be exactly the
> > >>>>> same
> > >>>>> as (+0.0 < y) for any y, hence the above may be safely constant
> > >>>>> folded to "0.0 <
> > >>>> y"
> > >>>>> avoiding the multiplication at run-time.

Ok, once the "frange" infrastructure is in place, it's actually
trivial.  See attached patch and tests.  We can do everything with
small range-op entries and evrp / ranger will handle everything else.

Roger, I believe this is what you described:

+// { dg-do compile }
+// { dg-options "-O2 -fno-tree-forwprop -fno-thread-jumps
-fdump-tree-evrp -fdump-tree-optimized" }
+
+extern void link_error ();
+
+int foo(int x, double y)
+{
+      return (x * 0.0) < y;
+}
+
+// The multiply should be gone by *vrp time.
+// { dg-final { scan-tree-dump-not " \\* " "evrp" } }
+
+// Ultimately, there sound be no references to "x".
+// { dg-final { scan-tree-dump-not "x_" "optimized" } }

With the attached patch (and pending patches), we keep track that a
cast from int to float is guaranteed to not be NaN, which allows us to
fold x*0.0 into 0.0, and DCE to remove x altogether.  Also, as the
other tests show, we are able to resolve __builtin_isnan's for the
operations implemented.  It should be straightforward for someone with
floating point foo to extend this to all operations.

Aldy

[-- Attachment #2: 0011-frange-Implement-NAN-aware-stubs-for-FLOAT_EXPR-UNOR.patch --]
[-- Type: text/x-patch, Size: 5082 bytes --]

From 2a6218e97782f63dfe9836e6024fbb28c8cbb803 Mon Sep 17 00:00:00 2001
From: Aldy Hernandez <aldyh@redhat.com>
Date: Mon, 21 Mar 2022 16:26:40 +0100
Subject: [PATCH] [frange] Implement NAN aware stubs for FLOAT_EXPR,
 UNORDERED_EXPR, and MULT_EXPR.

---
 gcc/range-op-float.cc                        | 90 ++++++++++++++++++++
 gcc/testsuite/gcc.dg/tree-ssa/vrp-float-01.c | 14 +++
 gcc/testsuite/gcc.dg/tree-ssa/vrp-float-02.c | 14 +++
 gcc/testsuite/gcc.dg/tree-ssa/vrp-float-03.c | 15 ++++
 4 files changed, 133 insertions(+)
 create mode 100644 gcc/testsuite/gcc.dg/tree-ssa/vrp-float-01.c
 create mode 100644 gcc/testsuite/gcc.dg/tree-ssa/vrp-float-02.c
 create mode 100644 gcc/testsuite/gcc.dg/tree-ssa/vrp-float-03.c

diff --git a/gcc/range-op-float.cc b/gcc/range-op-float.cc
index 988a3938959..52aaa01ab0f 100644
--- a/gcc/range-op-float.cc
+++ b/gcc/range-op-float.cc
@@ -922,6 +922,93 @@ foperator_cst::fold_range (frange &r, tree type ATTRIBUTE_UNUSED,
   return true;
 }
 
+class foperator_cast : public range_operator
+{
+  using range_operator::fold_range;
+public:
+  virtual bool fold_range (frange &r, tree type,
+			   const irange &inner,
+			   const frange &outer,
+			   relation_kind rel = VREL_NONE) const override;
+} fop_convert;
+
+bool
+foperator_cast::fold_range (frange &r, tree type,
+			    const irange &inner,
+			    const frange &outer,
+			    relation_kind) const
+{
+  if (empty_range_varying (r, type, inner, outer))
+    return true;
+
+  r.set_varying (type);
+
+  // Some flags can be cleared when converting from ints.
+  r.clear_prop (FRANGE_PROP_NAN);
+
+  return true;
+}
+
+class foperator_unordered : public range_operator
+{
+  using range_operator::fold_range;
+public:
+  virtual bool fold_range (irange &r, tree type,
+			   const frange &lh,
+			   const frange &rh,
+			   relation_kind rel = VREL_NONE) const override;
+} fop_unordered;
+
+bool
+foperator_unordered::fold_range (irange &r, tree type,
+				 const frange &lh,
+				 const frange &rh,
+				 relation_kind) const
+{
+  if (empty_range_varying (r, type, lh, rh))
+    return true;
+
+  // Return FALSE if both operands are !NaN.
+  if (!lh.get_prop (FRANGE_PROP_NAN) && !rh.get_prop (FRANGE_PROP_NAN))
+    {
+      r = range_false (type);
+      return true;
+    }
+
+  return false;
+}
+
+class foperator_mult : public range_operator
+{
+  using range_operator::fold_range;
+public:
+  virtual bool fold_range (frange &r, tree type,
+			   const frange &lh,
+			   const frange &rh,
+			   relation_kind rel = VREL_NONE) const override;
+} fop_mult;
+
+bool
+foperator_mult::fold_range (frange &r, tree type,
+			    const frange &lh,
+			    const frange &rh,
+			    relation_kind) const
+{
+  if (empty_range_varying (r, type, lh, rh))
+    return true;
+
+  // When x is !Nan, x * 0.0 = 0.0
+  if (rh.zero_p ()
+      && !rh.get_prop (FRANGE_PROP_NAN)
+      && !lh.get_prop (FRANGE_PROP_NAN))
+    {
+      r.set_zero (type);
+      return true;
+    }
+
+  return false;
+}
+
 class floating_table : public range_op_table
 {
 public:
@@ -944,6 +1031,9 @@ floating_table::floating_table ()
   set (PAREN_EXPR, fop_identity);
   set (OBJ_TYPE_REF, fop_identity);
   set (REAL_CST, fop_real_cst);
+  set (FLOAT_EXPR, fop_convert);
+  set (UNORDERED_EXPR, fop_unordered);
+  set (MULT_EXPR, fop_mult);
 }
 
 #if CHECKING_P
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/vrp-float-01.c b/gcc/testsuite/gcc.dg/tree-ssa/vrp-float-01.c
new file mode 100644
index 00000000000..92af87091a8
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/vrp-float-01.c
@@ -0,0 +1,14 @@
+// { dg-do compile }
+// { dg-options "-O2 -fno-tree-forwprop -fno-tree-ccp -fno-tree-fre -fdump-tree-evrp" }
+
+extern void link_error ();
+
+void
+foo ()
+{
+  float z = 0.0;
+  if (__builtin_isnan (z))
+    link_error ();
+}
+
+// { dg-final { scan-tree-dump-not "link_error" "evrp" } }
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/vrp-float-02.c b/gcc/testsuite/gcc.dg/tree-ssa/vrp-float-02.c
new file mode 100644
index 00000000000..d38ea523bea
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/vrp-float-02.c
@@ -0,0 +1,14 @@
+// { dg-do compile }
+// { dg-options "-O2 -fno-tree-forwprop -fno-thread-jumps -fdump-tree-evrp" }
+
+extern void link_error ();
+
+void
+foo (int i)
+{
+  float z = i;
+  if (__builtin_isnan (z))
+    link_error ();
+}
+
+// { dg-final { scan-tree-dump-not "link_error" "evrp" } }
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/vrp-float-03.c b/gcc/testsuite/gcc.dg/tree-ssa/vrp-float-03.c
new file mode 100644
index 00000000000..6c26a295f94
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/vrp-float-03.c
@@ -0,0 +1,15 @@
+// { dg-do compile }
+// { dg-options "-O2 -fno-tree-forwprop -fno-thread-jumps -fdump-tree-evrp -fdump-tree-optimized" }
+
+extern void link_error ();
+
+int foo(int x, double y) 
+{
+      return (x * 0.0) < y;
+}
+
+// The multiply should be gone by *vrp time.
+// { dg-final { scan-tree-dump-not " \\* " "evrp" } }
+
+// Ultimately, there sound be no references to "x".
+// { dg-final { scan-tree-dump-not "x_" "optimized" } }
-- 
2.35.1


  reply	other threads:[~2022-03-21 15:56 UTC|newest]

Thread overview: 15+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2022-03-14 19:25 Roger Sayle
2022-03-15  7:29 ` Richard Biener
2022-03-15  8:03   ` Roger Sayle
2022-03-15 10:50     ` Richard Biener
2022-03-17 23:27     ` Jeff Law
2022-03-18  2:12       ` Andrew MacLeod
2022-03-18  7:43       ` Roger Sayle
2022-03-18 13:07         ` Andrew MacLeod
2022-03-18 18:07           ` Aldy Hernandez
2022-03-18 13:16       ` Andrew MacLeod
2022-03-18 16:01         ` Jeff Law
2022-03-18 18:33           ` Aldy Hernandez
2022-03-21 15:56             ` Aldy Hernandez [this message]
2022-03-26 18:52               ` Roger Sayle
2022-03-16  9:44   ` Richard Sandiford

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=CAGm3qMV4pujGhLNYBdPOt2GdpQ9yz_Tnjd77KfSeX1KrskGmmg@mail.gmail.com \
    --to=aldyh@redhat.com \
    --cc=amacleod@redhat.com \
    --cc=gcc-patches@gcc.gnu.org \
    --cc=jeffreyalaw@gmail.com \
    --cc=richard.guenther@gmail.com \
    --cc=roger@nextmovesoftware.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).