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
next prev parent 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).