diff mbox series

[frange] Remove special casing from unordered operators.

Message ID 20230920151234.1015328-1-aldyh@redhat.com
State New
Headers show
Series [frange] Remove special casing from unordered operators. | expand

Commit Message

Aldy Hernandez Sept. 20, 2023, 3:12 p.m. UTC
In coming up with testcases for the unordered folders, I realized that
we were already handling them correctly, even in the absence of my
work in this area lately.

All of the unordered fold_range() methods try to fold with the ordered
variants first, and if they return TRUE, we are guaranteed to be able
to fold, even in the presence of NANs.  For example:

if (x_5 >= y_8)
  if (x_5 __UNLE y_8)

On the true side of the first conditional we know that either x_5 < y_8
or that one or more operands is a NAN.  Since UNLE_EXPR returns true
for precisely this scenario, we can fold as true.

This is handled in the fold_range() methods as follows:

    if (!range_op_handler (LE_EXPR).fold_range (r, type, op1_no_nan,
						op2_no_nan, trio))
      return false;
    // The result is the same as the ordered version when the
    // comparison is true or when the operands cannot be NANs.
    if (!maybe_isnan (op1, op2) || r == range_true (type))
      return true;

This code has been there since the last release, and makes the special
casing I am deleting obsolete.  I have added tests to make sure we
keep track of this behavior.

I will commit this pending tests.

gcc/ChangeLog:

	* range-op-float.cc (foperator_unordered_ge::fold_range): Remove
	special casing.
	(foperator_unordered_gt::fold_range): Same.
	(foperator_unordered_lt::fold_range): Same.
	(foperator_unordered_le::fold_range): Same.

gcc/testsuite/ChangeLog:

	* gcc.dg/tree-ssa/vrp-float-relations-5.c: New test.
	* gcc.dg/tree-ssa/vrp-float-relations-6.c: New test.
---
 gcc/range-op-float.cc                         | 20 ++-----
 .../gcc.dg/tree-ssa/vrp-float-relations-5.c   | 54 +++++++++++++++++++
 .../gcc.dg/tree-ssa/vrp-float-relations-6.c   | 54 +++++++++++++++++++
 3 files changed, 112 insertions(+), 16 deletions(-)
 create mode 100644 gcc/testsuite/gcc.dg/tree-ssa/vrp-float-relations-5.c
 create mode 100644 gcc/testsuite/gcc.dg/tree-ssa/vrp-float-relations-6.c

Comments

Aldy Hernandez Sept. 20, 2023, 7:13 p.m. UTC | #1
On 9/20/23 11:12, Aldy Hernandez wrote:
> In coming up with testcases for the unordered folders, I realized that
> we were already handling them correctly, even in the absence of my
> work in this area lately.
> 
> All of the unordered fold_range() methods try to fold with the ordered
> variants first, and if they return TRUE, we are guaranteed to be able
> to fold, even in the presence of NANs.  For example:
> 
> if (x_5 >= y_8)
>    if (x_5 __UNLE y_8)
> 
> On the true side of the first conditional we know that either x_5 < y_8
> or that one or more operands is a NAN.  Since UNLE_EXPR returns true
> for precisely this scenario, we can fold as true.

Ugh, that should've been the false edge of the first conditional, thus:

if (x_5 >= y_8)
   {
   }
else
   {
     // Relation at this point is: x_5 < y_8
     // or either x_5 or y_8 is a NAN.
     if (x_5 __UNLE y_8)
       link_error();
   }

The second conditional is foldable because LT U NAN is a subset of 
__UNLE (which is LE U NAN).

The patch still stands though :).

Aldy
diff mbox series

Patch

diff --git a/gcc/range-op-float.cc b/gcc/range-op-float.cc
index 399deee5d8a..0951bd385a9 100644
--- a/gcc/range-op-float.cc
+++ b/gcc/range-op-float.cc
@@ -1644,10 +1644,7 @@  public:
 		   const frange &op1, const frange &op2,
 		   relation_trio trio = TRIO_VARYING) const final override
   {
-    relation_kind rel = trio.op1_op2 ();
-
-    if (op1.known_isnan () || op2.known_isnan ()
-	|| rel == VREL_LT)
+    if (op1.known_isnan () || op2.known_isnan ())
       {
 	r = range_true (type);
 	return true;
@@ -1759,10 +1756,7 @@  public:
 		   const frange &op1, const frange &op2,
 		   relation_trio trio = TRIO_VARYING) const final override
   {
-    relation_kind rel = trio.op1_op2 ();
-
-    if (op1.known_isnan () || op2.known_isnan ()
-	|| rel == VREL_LE)
+    if (op1.known_isnan () || op2.known_isnan ())
       {
 	r = range_true (type);
 	return true;
@@ -1870,10 +1864,7 @@  public:
 		   const frange &op1, const frange &op2,
 		   relation_trio trio = TRIO_VARYING) const final override
   {
-    relation_kind rel = trio.op1_op2 ();
-
-    if (op1.known_isnan () || op2.known_isnan ()
-	|| rel == VREL_GT)
+    if (op1.known_isnan () || op2.known_isnan ())
       {
 	r = range_true (type);
 	return true;
@@ -1985,10 +1976,7 @@  public:
 		   const frange &op1, const frange &op2,
 		   relation_trio trio = TRIO_VARYING) const final override
   {
-    relation_kind rel = trio.op1_op2 ();
-
-    if (op1.known_isnan () || op2.known_isnan ()
-	|| rel == VREL_GE)
+    if (op1.known_isnan () || op2.known_isnan ())
       {
 	r = range_true (type);
 	return true;
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/vrp-float-relations-5.c b/gcc/testsuite/gcc.dg/tree-ssa/vrp-float-relations-5.c
new file mode 100644
index 00000000000..2bd06c6fbf7
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/vrp-float-relations-5.c
@@ -0,0 +1,54 @@ 
+// { dg-do compile }
+// { dg-options "-O2 -fgimple -fdump-tree-evrp" }
+
+void link_error();
+
+void __GIMPLE (ssa,startwith("evrp"))
+foo1 (float x, float y)
+{
+  __BB(2):
+  if (x_4(D) <= y_5(D))
+    goto __BB5;
+  else
+    goto __BB3;
+
+  __BB(3):
+  // Relation at this point is VREL_GT.
+  if (x_4(D) __UNGE y_5(D))
+    goto __BB5;
+  else
+    goto __BB4;
+
+  __BB(4):
+  link_error ();
+  goto __BB5;
+
+  __BB(5):
+  return;
+}
+
+void __GIMPLE (ssa,startwith("evrp"))
+foo2 (float x, float y)
+{
+  __BB(2):
+  if (x_4(D) <= y_5(D))
+    goto __BB5;
+  else
+    goto __BB3;
+
+  __BB(3):
+  // Relation at this point is VREL_GT.
+  if (x_4(D) __UNGT y_5(D))
+    goto __BB5;
+  else
+    goto __BB4;
+
+  __BB(4):
+  link_error ();
+  goto __BB5;
+
+  __BB(5):
+  return;
+}
+
+// { dg-final { scan-tree-dump-not "link_error" "evrp" } }
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/vrp-float-relations-6.c b/gcc/testsuite/gcc.dg/tree-ssa/vrp-float-relations-6.c
new file mode 100644
index 00000000000..a75ae5d64ff
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/vrp-float-relations-6.c
@@ -0,0 +1,54 @@ 
+// { dg-do compile }
+// { dg-options "-O2 -fgimple -fdump-tree-evrp" }
+
+void link_error();
+
+void __GIMPLE (ssa,startwith("evrp"))
+foo1 (float x, float y)
+{
+  __BB(2):
+  if (x_4(D) >= y_5(D))
+    goto __BB5;
+  else
+    goto __BB3;
+
+  __BB(3):
+  // Relation at this point is VREL_LT.
+  if (x_4(D) __UNLT y_5(D))
+    goto __BB5;
+  else
+    goto __BB4;
+
+  __BB(4):
+  link_error ();
+  goto __BB5;
+
+  __BB(5):
+  return;
+}
+
+void __GIMPLE (ssa,startwith("evrp"))
+foo2 (float x, float y)
+{
+  __BB(2):
+  if (x_4(D) >= y_5(D))
+    goto __BB5;
+  else
+    goto __BB3;
+
+  __BB(3):
+  // Relation at this point is VREL_LT.
+  if (x_4(D) __UNLE y_5(D))
+    goto __BB5;
+  else
+    goto __BB4;
+
+  __BB(4):
+  link_error ();
+  goto __BB5;
+
+  __BB(5):
+  return;
+}
+
+// { dg-final { scan-tree-dump-not "link_error" "evrp" } }