public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
* [COMMITTED] Move TRUE case first in range-op.cc.
@ 2022-10-11 13:51 Aldy Hernandez
  2022-10-11 13:51 ` [COMMITTED] Share common ordered comparison code with UN*_EXPR Aldy Hernandez
                   ` (2 more replies)
  0 siblings, 3 replies; 5+ messages in thread
From: Aldy Hernandez @ 2022-10-11 13:51 UTC (permalink / raw)
  To: GCC patches; +Cc: Andrew MacLeod, Aldy Hernandez

It's incredibly annoying that some of the BRS_TRUE cases come after
BRS_FALSE, if only because we're not consistent.  Having random
ordering increases the changes of thinkos when adapting the irange
code to floats.

gcc/ChangeLog:

	* range-op.cc (operator_equal::op1_range): Move BRS_TRUE case up.
	(operator_lt::op2_range): Same.
	(operator_le::op2_range): Same.
	(operator_gt::op2_range): Same.
	(operator_ge::op2_range): Same.
---
 gcc/range-op.cc | 42 +++++++++++++++++++++---------------------
 1 file changed, 21 insertions(+), 21 deletions(-)

diff --git a/gcc/range-op.cc b/gcc/range-op.cc
index df0735cb42a..4d5a033dfa5 100644
--- a/gcc/range-op.cc
+++ b/gcc/range-op.cc
@@ -531,6 +531,11 @@ operator_equal::op1_range (irange &r, tree type,
 {
   switch (get_bool_state (r, lhs, type))
     {
+    case BRS_TRUE:
+      // If it's true, the result is the same as OP2.
+      r = op2;
+      break;
+
     case BRS_FALSE:
       // If the result is false, the only time we know anything is
       // if OP2 is a constant.
@@ -543,11 +548,6 @@ operator_equal::op1_range (irange &r, tree type,
 	r.set_varying (type);
       break;
 
-    case BRS_TRUE:
-      // If it's true, the result is the same as OP2.
-      r = op2;
-      break;
-
     default:
       break;
     }
@@ -841,14 +841,14 @@ operator_lt::op2_range (irange &r, tree type,
 {
   switch (get_bool_state (r, lhs, type))
     {
-    case BRS_FALSE:
-      build_le (r, type, op1.upper_bound ());
-      break;
-
     case BRS_TRUE:
       build_gt (r, type, op1.lower_bound ());
       break;
 
+    case BRS_FALSE:
+      build_le (r, type, op1.upper_bound ());
+      break;
+
     default:
       break;
     }
@@ -952,14 +952,14 @@ operator_le::op2_range (irange &r, tree type,
 {
   switch (get_bool_state (r, lhs, type))
     {
-    case BRS_FALSE:
-      build_lt (r, type, op1.upper_bound ());
-      break;
-
     case BRS_TRUE:
       build_ge (r, type, op1.lower_bound ());
       break;
 
+    case BRS_FALSE:
+      build_lt (r, type, op1.upper_bound ());
+      break;
+
     default:
       break;
     }
@@ -1062,14 +1062,14 @@ operator_gt::op2_range (irange &r, tree type,
 {
   switch (get_bool_state (r, lhs, type))
     {
-    case BRS_FALSE:
-      build_ge (r, type, op1.lower_bound ());
-      break;
-
     case BRS_TRUE:
       build_lt (r, type, op1.upper_bound ());
       break;
 
+    case BRS_FALSE:
+      build_ge (r, type, op1.lower_bound ());
+      break;
+
     default:
       break;
     }
@@ -1173,14 +1173,14 @@ operator_ge::op2_range (irange &r, tree type,
 {
   switch (get_bool_state (r, lhs, type))
     {
-    case BRS_FALSE:
-      build_gt (r, type, op1.lower_bound ());
-      break;
-
     case BRS_TRUE:
       build_le (r, type, op1.upper_bound ());
       break;
 
+    case BRS_FALSE:
+      build_gt (r, type, op1.lower_bound ());
+      break;
+
     default:
       break;
     }
-- 
2.37.3


^ permalink raw reply	[flat|nested] 5+ messages in thread

* [COMMITTED] Share common ordered comparison code with UN*_EXPR.
  2022-10-11 13:51 [COMMITTED] Move TRUE case first in range-op.cc Aldy Hernandez
@ 2022-10-11 13:51 ` Aldy Hernandez
  2022-10-11 13:51 ` [COMMITTED] Implement op1_range operators for unordered comparisons Aldy Hernandez
  2022-10-11 13:51 ` [COMMITTED] Implement ABS_EXPR operator for frange Aldy Hernandez
  2 siblings, 0 replies; 5+ messages in thread
From: Aldy Hernandez @ 2022-10-11 13:51 UTC (permalink / raw)
  To: GCC patches; +Cc: Andrew MacLeod, Aldy Hernandez

Most unordered comparisons can use the result from the ordered
version, if the operands are known not to be NAN or if the result is
true.

gcc/ChangeLog:

	* range-op-float.cc (class foperator_unordered_lt): New.
	(class foperator_relop_unknown): Remove
	(class foperator_unordered_le): New.
	(class foperator_unordered_gt): New.
	(class foperator_unordered_ge): New.
	(class foperator_unordered_equal): New.
	(floating_op_table::floating_op_table): Replace all UN_EXPR
	entries with their appropriate fop_unordered_* counterpart.
---
 gcc/range-op-float.cc | 140 ++++++++++++++++++++++++++++++++++++++----
 1 file changed, 128 insertions(+), 12 deletions(-)

diff --git a/gcc/range-op-float.cc b/gcc/range-op-float.cc
index 3cf117d8931..8dd4bcc70c0 100644
--- a/gcc/range-op-float.cc
+++ b/gcc/range-op-float.cc
@@ -1132,24 +1132,140 @@ foperator_ordered::op1_range (frange &r, tree type,
   return true;
 }
 
-// Placeholder for unimplemented relational operators.
+class foperator_unordered_lt : public range_operator_float
+{
+  using range_operator_float::fold_range;
+public:
+  bool fold_range (irange &r, tree type,
+		   const frange &op1, const frange &op2,
+		   relation_kind rel) const final override
+  {
+    if (op1.known_isnan () || op2.known_isnan ())
+      {
+	r = range_true (type);
+	return true;
+      }
+    if (!fop_lt.fold_range (r, type, op1, op2, rel))
+      return false;
+    // The result is the same as the ordered version when the
+    // comparison is true or when the operands cannot be NANs.
+    if (finite_operands_p (op1, op2) || r == range_true (type))
+      return true;
+    else
+      {
+	r = range_true_and_false (type);
+	return true;
+      }
+  }
+} fop_unordered_lt;
 
-class foperator_relop_unknown : public range_operator_float
+class foperator_unordered_le : public range_operator_float
 {
   using range_operator_float::fold_range;
+public:
+  bool fold_range (irange &r, tree type,
+		   const frange &op1, const frange &op2,
+		   relation_kind rel) const final override
+  {
+    if (op1.known_isnan () || op2.known_isnan ())
+      {
+	r = range_true (type);
+	return true;
+      }
+    if (!fop_le.fold_range (r, type, op1, op2, rel))
+      return false;
+    // The result is the same as the ordered version when the
+    // comparison is true or when the operands cannot be NANs.
+    if (finite_operands_p (op1, op2) || r == range_true (type))
+      return true;
+    else
+      {
+	r = range_true_and_false (type);
+	return true;
+      }
+  }
+} fop_unordered_le;
 
+class foperator_unordered_gt : public range_operator_float
+{
+  using range_operator_float::fold_range;
 public:
   bool fold_range (irange &r, tree type,
 		   const frange &op1, const frange &op2,
-		   relation_kind) const final override
+		   relation_kind rel) const final override
   {
     if (op1.known_isnan () || op2.known_isnan ())
-      r = range_true (type);
+      {
+	r = range_true (type);
+	return true;
+      }
+    if (!fop_gt.fold_range (r, type, op1, op2, rel))
+      return false;
+    // The result is the same as the ordered version when the
+    // comparison is true or when the operands cannot be NANs.
+    if (finite_operands_p (op1, op2) || r == range_true (type))
+      return true;
     else
-      r.set_varying (type);
-    return true;
+      {
+	r = range_true_and_false (type);
+	return true;
+      }
+  }
+} fop_unordered_gt;
+
+class foperator_unordered_ge : public range_operator_float
+{
+  using range_operator_float::fold_range;
+public:
+  bool fold_range (irange &r, tree type,
+		   const frange &op1, const frange &op2,
+		   relation_kind rel) const final override
+  {
+    if (op1.known_isnan () || op2.known_isnan ())
+      {
+	r = range_true (type);
+	return true;
+      }
+    if (!fop_ge.fold_range (r, type, op1, op2, rel))
+      return false;
+    // The result is the same as the ordered version when the
+    // comparison is true or when the operands cannot be NANs.
+    if (finite_operands_p (op1, op2) || r == range_true (type))
+      return true;
+    else
+      {
+	r = range_true_and_false (type);
+	return true;
+      }
+  }
+} fop_unordered_ge;
+
+class foperator_unordered_equal : public range_operator_float
+{
+  using range_operator_float::fold_range;
+public:
+  bool fold_range (irange &r, tree type,
+		   const frange &op1, const frange &op2,
+		   relation_kind rel) const final override
+  {
+    if (op1.known_isnan () || op2.known_isnan ())
+      {
+	r = range_true (type);
+	return true;
+      }
+    if (!fop_equal.fold_range (r, type, op1, op2, rel))
+      return false;
+    // The result is the same as the ordered version when the
+    // comparison is true or when the operands cannot be NANs.
+    if (finite_operands_p (op1, op2) || r == range_true (type))
+      return true;
+    else
+      {
+	r = range_true_and_false (type);
+	return true;
+      }
   }
-} fop_unordered_relop_unknown;
+} fop_unordered_equal;
 
 
 // Instantiate a range_op_table for floating point operations.
@@ -1174,11 +1290,11 @@ floating_op_table::floating_op_table ()
   set (LE_EXPR, fop_le);
   set (GT_EXPR, fop_gt);
   set (GE_EXPR, fop_ge);
-  set (UNLE_EXPR, fop_unordered_relop_unknown);
-  set (UNLT_EXPR, fop_unordered_relop_unknown);
-  set (UNGE_EXPR, fop_unordered_relop_unknown);
-  set (UNGT_EXPR, fop_unordered_relop_unknown);
-  set (UNEQ_EXPR, fop_unordered_relop_unknown);
+  set (UNLE_EXPR, fop_unordered_le);
+  set (UNLT_EXPR, fop_unordered_lt);
+  set (UNGE_EXPR, fop_unordered_ge);
+  set (UNGT_EXPR, fop_unordered_gt);
+  set (UNEQ_EXPR, fop_unordered_equal);
   set (ORDERED_EXPR, fop_ordered);
   set (UNORDERED_EXPR, fop_unordered);
 }
-- 
2.37.3


^ permalink raw reply	[flat|nested] 5+ messages in thread

* [COMMITTED] Implement op1_range operators for unordered comparisons.
  2022-10-11 13:51 [COMMITTED] Move TRUE case first in range-op.cc Aldy Hernandez
  2022-10-11 13:51 ` [COMMITTED] Share common ordered comparison code with UN*_EXPR Aldy Hernandez
@ 2022-10-11 13:51 ` Aldy Hernandez
  2022-10-11 13:57   ` Aldy Hernandez
  2022-10-11 13:51 ` [COMMITTED] Implement ABS_EXPR operator for frange Aldy Hernandez
  2 siblings, 1 reply; 5+ messages in thread
From: Aldy Hernandez @ 2022-10-11 13:51 UTC (permalink / raw)
  To: GCC patches; +Cc: Andrew MacLeod, Aldy Hernandez

gcc/ChangeLog:

	* range-op-float.cc (foperator_unordered_le::op1_range): New.
	(foperator_unordered_le::op2_range): New.
	(foperator_unordered_gt::op1_range): New.
	(foperator_unordered_gt::op2_range): New.
	(foperator_unordered_ge::op1_range): New.
	(foperator_unordered_ge::op2_range): New.
	(foperator_unordered_equal::op1_range): New.
---
 gcc/range-op-float.cc | 205 ++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 205 insertions(+)

diff --git a/gcc/range-op-float.cc b/gcc/range-op-float.cc
index 8dd4bcc70c0..ef51b7538e3 100644
--- a/gcc/range-op-float.cc
+++ b/gcc/range-op-float.cc
@@ -1162,6 +1162,8 @@ public:
 class foperator_unordered_le : public range_operator_float
 {
   using range_operator_float::fold_range;
+  using range_operator_float::op1_range;
+  using range_operator_float::op2_range;
 public:
   bool fold_range (irange &r, tree type,
 		   const frange &op1, const frange &op2,
@@ -1184,11 +1186,65 @@ public:
 	return true;
       }
   }
+  bool op1_range (frange &r, tree type,
+		  const irange &lhs, const frange &op2,
+		  relation_kind rel) const final override;
+  bool op2_range (frange &r, tree type,
+		  const irange &lhs, const frange &op1,
+		  relation_kind rel) const final override;
 } fop_unordered_le;
 
+bool
+foperator_unordered_le::op1_range (frange &r, tree type,
+				   const irange &lhs, const frange &op2,
+				   relation_kind) const
+{
+  switch (get_bool_state (r, lhs, type))
+    {
+    case BRS_TRUE:
+      build_le (r, type, op2);
+      break;
+
+    case BRS_FALSE:
+      build_gt (r, type, op2);
+      r.clear_nan ();
+      break;
+
+    default:
+      break;
+    }
+  return true;
+}
+
+bool
+foperator_unordered_le::op2_range (frange &r,
+				   tree type,
+				   const irange &lhs,
+				   const frange &op1,
+				   relation_kind) const
+{
+  switch (get_bool_state (r, lhs, type))
+    {
+    case BRS_TRUE:
+      build_ge (r, type, op1);
+      break;
+
+    case BRS_FALSE:
+      build_lt (r, type, op1);
+      r.clear_nan ();
+      break;
+
+    default:
+      break;
+    }
+  return true;
+}
+
 class foperator_unordered_gt : public range_operator_float
 {
   using range_operator_float::fold_range;
+  using range_operator_float::op1_range;
+  using range_operator_float::op2_range;
 public:
   bool fold_range (irange &r, tree type,
 		   const frange &op1, const frange &op2,
@@ -1211,11 +1267,67 @@ public:
 	return true;
       }
   }
+  bool op1_range (frange &r, tree type,
+		  const irange &lhs, const frange &op2,
+		  relation_kind rel) const final override;
+  bool op2_range (frange &r, tree type,
+		  const irange &lhs, const frange &op1,
+		  relation_kind rel) const final override;
 } fop_unordered_gt;
 
+bool
+foperator_unordered_gt::op1_range (frange &r,
+			 tree type,
+			 const irange &lhs,
+			 const frange &op2,
+			 relation_kind) const
+{
+  switch (get_bool_state (r, lhs, type))
+    {
+    case BRS_TRUE:
+      build_gt (r, type, op2);
+      break;
+
+    case BRS_FALSE:
+      build_le (r, type, op2);
+      r.clear_nan ();
+      break;
+
+    default:
+      break;
+    }
+  return true;
+}
+
+bool
+foperator_unordered_gt::op2_range (frange &r,
+				   tree type,
+				   const irange &lhs,
+				   const frange &op1,
+				   relation_kind) const
+{
+  switch (get_bool_state (r, lhs, type))
+    {
+    case BRS_TRUE:
+      build_lt (r, type, op1);
+      break;
+
+    case BRS_FALSE:
+      build_ge (r, type, op1);
+      r.clear_nan ();
+      break;
+
+    default:
+      break;
+    }
+  return true;
+}
+
 class foperator_unordered_ge : public range_operator_float
 {
   using range_operator_float::fold_range;
+  using range_operator_float::op1_range;
+  using range_operator_float::op2_range;
 public:
   bool fold_range (irange &r, tree type,
 		   const frange &op1, const frange &op2,
@@ -1238,11 +1350,66 @@ public:
 	return true;
       }
   }
+  bool op1_range (frange &r, tree type,
+		  const irange &lhs, const frange &op2,
+		  relation_kind rel) const final override;
+  bool op2_range (frange &r, tree type,
+		  const irange &lhs, const frange &op1,
+		  relation_kind rel) const final override;
 } fop_unordered_ge;
 
+bool
+foperator_unordered_ge::op1_range (frange &r,
+				   tree type,
+				   const irange &lhs,
+				   const frange &op2,
+				   relation_kind) const
+{
+  switch (get_bool_state (r, lhs, type))
+    {
+    case BRS_TRUE:
+      build_ge (r, type, op2);
+      break;
+
+    case BRS_FALSE:
+      build_lt (r, type, op2);
+      r.clear_nan ();
+      break;
+
+    default:
+      break;
+    }
+  return true;
+}
+
+bool
+foperator_unordered_ge::op2_range (frange &r, tree type,
+				   const irange &lhs,
+				   const frange &op1,
+				   relation_kind) const
+{
+  switch (get_bool_state (r, lhs, type))
+    {
+    case BRS_TRUE:
+      build_le (r, type, op1);
+      break;
+
+    case BRS_FALSE:
+      build_gt (r, type, op1);
+      r.clear_nan ();
+      break;
+
+    default:
+      break;
+    }
+  return true;
+}
+
 class foperator_unordered_equal : public range_operator_float
 {
   using range_operator_float::fold_range;
+  using range_operator_float::op1_range;
+  using range_operator_float::op2_range;
 public:
   bool fold_range (irange &r, tree type,
 		   const frange &op1, const frange &op2,
@@ -1265,8 +1432,46 @@ public:
 	return true;
       }
   }
+  bool op1_range (frange &r, tree type,
+		  const irange &lhs, const frange &op2,
+		  relation_kind rel) const final override;
+  bool op2_range (frange &r, tree type,
+		  const irange &lhs, const frange &op1,
+		  relation_kind rel) const final override
+  {
+    return op1_range (r, type, lhs, op1, rel);
+  }
 } fop_unordered_equal;
 
+bool
+foperator_unordered_equal::op1_range (frange &r, tree type,
+				      const irange &lhs,
+				      const frange &op2,
+				      relation_kind) const
+{
+  switch (get_bool_state (r, lhs, type))
+    {
+    case BRS_TRUE:
+      // If it's true, the result is the same as OP2 plus a NAN.
+      r = op2;
+      // Add both zeros if there's the possibility of zero equality.
+      frange_add_zeros (r, type);
+      // Add the posibility of a NAN.
+      r.update_nan ();
+      break;
+
+    case BRS_FALSE:
+      // The false side indictates !NAN and not equal.  We can at least
+      // represent !NAN.
+      r.set_varying (type);
+      r.clear_nan ();
+      break;
+
+    default:
+      break;
+    }
+  return true;
+}
 
 // Instantiate a range_op_table for floating point operations.
 static floating_op_table global_floating_table;
-- 
2.37.3


^ permalink raw reply	[flat|nested] 5+ messages in thread

* [COMMITTED] Implement ABS_EXPR operator for frange.
  2022-10-11 13:51 [COMMITTED] Move TRUE case first in range-op.cc Aldy Hernandez
  2022-10-11 13:51 ` [COMMITTED] Share common ordered comparison code with UN*_EXPR Aldy Hernandez
  2022-10-11 13:51 ` [COMMITTED] Implement op1_range operators for unordered comparisons Aldy Hernandez
@ 2022-10-11 13:51 ` Aldy Hernandez
  2 siblings, 0 replies; 5+ messages in thread
From: Aldy Hernandez @ 2022-10-11 13:51 UTC (permalink / raw)
  To: GCC patches; +Cc: Andrew MacLeod, Aldy Hernandez

Implementing ABS_EXPR allows us to fold certain __builtin_inf calls
since they are expanded into calls to involving ABS_EXPR.

This is an adaptation of the integer version.

gcc/ChangeLog:

	* range-op-float.cc (class foperator_abs): New.
	(floating_op_table::floating_op_table): Add ABS_EXPR entry.

gcc/testsuite/ChangeLog:

	* gcc.dg/tree-ssa/vrp-float-abs-1.c: New test.
---
 gcc/range-op-float.cc                         | 91 +++++++++++++++++++
 .../gcc.dg/tree-ssa/vrp-float-abs-1.c         | 17 ++++
 2 files changed, 108 insertions(+)
 create mode 100644 gcc/testsuite/gcc.dg/tree-ssa/vrp-float-abs-1.c

diff --git a/gcc/range-op-float.cc b/gcc/range-op-float.cc
index ef51b7538e3..283eb134c78 100644
--- a/gcc/range-op-float.cc
+++ b/gcc/range-op-float.cc
@@ -1132,6 +1132,95 @@ foperator_ordered::op1_range (frange &r, tree type,
   return true;
 }
 
+class foperator_abs : public range_operator_float
+{
+  using range_operator_float::fold_range;
+  using range_operator_float::op1_range;
+public:
+  bool fold_range (frange &r, tree type,
+		   const frange &op1, const frange &,
+		   relation_kind) const final override;
+  bool op1_range (frange &r, tree type,
+		  const frange &lhs, const frange &op2,
+		  relation_kind rel) const final override;
+} fop_abs;
+
+bool
+foperator_abs::fold_range (frange &r, tree type,
+			   const frange &op1, const frange &op2,
+			   relation_kind) const
+{
+  if (empty_range_varying (r, type, op1, op2))
+    return true;
+  if (op1.known_isnan ())
+    {
+      r.set_nan (type, /*sign=*/false);
+      return true;
+    }
+
+  const REAL_VALUE_TYPE lh_lb = op1.lower_bound ();
+  const REAL_VALUE_TYPE lh_ub = op1.upper_bound ();
+  // Handle the easy case where everything is positive.
+  if (real_compare (GE_EXPR, &lh_lb, &dconst0)
+      && !real_iszero (&lh_lb, /*sign=*/true)
+      && !op1.maybe_isnan (/*sign=*/true))
+    {
+      r = op1;
+      return true;
+    }
+
+  REAL_VALUE_TYPE min = real_value_abs (&lh_lb);
+  REAL_VALUE_TYPE max = real_value_abs (&lh_ub);
+  // If the range contains zero then we know that the minimum value in the
+  // range will be zero.
+  if (real_compare (LE_EXPR, &lh_lb, &dconst0)
+      && real_compare (GE_EXPR, &lh_ub, &dconst0))
+    {
+      if (real_compare (GT_EXPR, &min, &max))
+	max = min;
+      min = dconst0;
+    }
+  else
+    {
+      // If the range was reversed, swap MIN and MAX.
+      if (real_compare (GT_EXPR, &min, &max))
+	std::swap (min, max);
+    }
+
+  r.set (type, min, max);
+  if (op1.maybe_isnan ())
+    r.update_nan (/*sign=*/false);
+  else
+    r.clear_nan ();
+  return true;
+}
+
+bool
+foperator_abs::op1_range (frange &r, tree type,
+			  const frange &lhs, const frange &op2,
+			  relation_kind) const
+{
+  if (empty_range_varying (r, type, lhs, op2))
+    return true;
+  if (lhs.known_isnan ())
+    {
+      r.set_nan (type);
+      return true;
+    }
+
+  // Start with the positives because negatives are an impossible result.
+  frange positives (type, dconst0, frange_val_max (type));
+  positives.update_nan (/*sign=*/false);
+  positives.intersect (lhs);
+  r = positives;
+  // Then add the negative of each pair:
+  // ABS(op1) = [5,20] would yield op1 => [-20,-5][5,20].
+  r.union_ (frange (type,
+		    real_value_negate (&positives.upper_bound ()),
+		    real_value_negate (&positives.lower_bound ())));
+  return true;
+}
+
 class foperator_unordered_lt : public range_operator_float
 {
   using range_operator_float::fold_range;
@@ -1502,6 +1591,8 @@ floating_op_table::floating_op_table ()
   set (UNEQ_EXPR, fop_unordered_equal);
   set (ORDERED_EXPR, fop_ordered);
   set (UNORDERED_EXPR, fop_unordered);
+
+  set (ABS_EXPR, fop_abs);
 }
 
 // Return a pointer to the range_operator_float instance, if there is
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/vrp-float-abs-1.c b/gcc/testsuite/gcc.dg/tree-ssa/vrp-float-abs-1.c
new file mode 100644
index 00000000000..4b7b75833e0
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/vrp-float-abs-1.c
@@ -0,0 +1,17 @@
+// { dg-do compile }
+// { dg-options "-O2 -fno-thread-jumps -fdump-tree-evrp" }
+
+void link_error ();
+
+void
+foo (double x, double y)
+{
+  if (x > y && __builtin_signbit (y) == 0)
+    {
+      // y == +INF is impossible.
+      if (__builtin_isinf (y))
+        link_error ();
+    }
+}
+
+// { dg-final { scan-tree-dump-not "link_error" "evrp" } }
-- 
2.37.3


^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [COMMITTED] Implement op1_range operators for unordered comparisons.
  2022-10-11 13:51 ` [COMMITTED] Implement op1_range operators for unordered comparisons Aldy Hernandez
@ 2022-10-11 13:57   ` Aldy Hernandez
  0 siblings, 0 replies; 5+ messages in thread
From: Aldy Hernandez @ 2022-10-11 13:57 UTC (permalink / raw)
  To: GCC patches; +Cc: Andrew MacLeod

I forgot to mention.  These were lifted from the integer counterparts.
Most of the code is the same, as the build_{cond} code in the frange
version will add the appropriate NAN (unless -ffinite-math-only), and
all we have to do is clear it on the false edge.

Aldy

On Tue, Oct 11, 2022 at 3:51 PM Aldy Hernandez <aldyh@redhat.com> wrote:
>
> gcc/ChangeLog:
>
>         * range-op-float.cc (foperator_unordered_le::op1_range): New.
>         (foperator_unordered_le::op2_range): New.
>         (foperator_unordered_gt::op1_range): New.
>         (foperator_unordered_gt::op2_range): New.
>         (foperator_unordered_ge::op1_range): New.
>         (foperator_unordered_ge::op2_range): New.
>         (foperator_unordered_equal::op1_range): New.
> ---
>  gcc/range-op-float.cc | 205 ++++++++++++++++++++++++++++++++++++++++++
>  1 file changed, 205 insertions(+)
>
> diff --git a/gcc/range-op-float.cc b/gcc/range-op-float.cc
> index 8dd4bcc70c0..ef51b7538e3 100644
> --- a/gcc/range-op-float.cc
> +++ b/gcc/range-op-float.cc
> @@ -1162,6 +1162,8 @@ public:
>  class foperator_unordered_le : public range_operator_float
>  {
>    using range_operator_float::fold_range;
> +  using range_operator_float::op1_range;
> +  using range_operator_float::op2_range;
>  public:
>    bool fold_range (irange &r, tree type,
>                    const frange &op1, const frange &op2,
> @@ -1184,11 +1186,65 @@ public:
>         return true;
>        }
>    }
> +  bool op1_range (frange &r, tree type,
> +                 const irange &lhs, const frange &op2,
> +                 relation_kind rel) const final override;
> +  bool op2_range (frange &r, tree type,
> +                 const irange &lhs, const frange &op1,
> +                 relation_kind rel) const final override;
>  } fop_unordered_le;
>
> +bool
> +foperator_unordered_le::op1_range (frange &r, tree type,
> +                                  const irange &lhs, const frange &op2,
> +                                  relation_kind) const
> +{
> +  switch (get_bool_state (r, lhs, type))
> +    {
> +    case BRS_TRUE:
> +      build_le (r, type, op2);
> +      break;
> +
> +    case BRS_FALSE:
> +      build_gt (r, type, op2);
> +      r.clear_nan ();
> +      break;
> +
> +    default:
> +      break;
> +    }
> +  return true;
> +}
> +
> +bool
> +foperator_unordered_le::op2_range (frange &r,
> +                                  tree type,
> +                                  const irange &lhs,
> +                                  const frange &op1,
> +                                  relation_kind) const
> +{
> +  switch (get_bool_state (r, lhs, type))
> +    {
> +    case BRS_TRUE:
> +      build_ge (r, type, op1);
> +      break;
> +
> +    case BRS_FALSE:
> +      build_lt (r, type, op1);
> +      r.clear_nan ();
> +      break;
> +
> +    default:
> +      break;
> +    }
> +  return true;
> +}
> +
>  class foperator_unordered_gt : public range_operator_float
>  {
>    using range_operator_float::fold_range;
> +  using range_operator_float::op1_range;
> +  using range_operator_float::op2_range;
>  public:
>    bool fold_range (irange &r, tree type,
>                    const frange &op1, const frange &op2,
> @@ -1211,11 +1267,67 @@ public:
>         return true;
>        }
>    }
> +  bool op1_range (frange &r, tree type,
> +                 const irange &lhs, const frange &op2,
> +                 relation_kind rel) const final override;
> +  bool op2_range (frange &r, tree type,
> +                 const irange &lhs, const frange &op1,
> +                 relation_kind rel) const final override;
>  } fop_unordered_gt;
>
> +bool
> +foperator_unordered_gt::op1_range (frange &r,
> +                        tree type,
> +                        const irange &lhs,
> +                        const frange &op2,
> +                        relation_kind) const
> +{
> +  switch (get_bool_state (r, lhs, type))
> +    {
> +    case BRS_TRUE:
> +      build_gt (r, type, op2);
> +      break;
> +
> +    case BRS_FALSE:
> +      build_le (r, type, op2);
> +      r.clear_nan ();
> +      break;
> +
> +    default:
> +      break;
> +    }
> +  return true;
> +}
> +
> +bool
> +foperator_unordered_gt::op2_range (frange &r,
> +                                  tree type,
> +                                  const irange &lhs,
> +                                  const frange &op1,
> +                                  relation_kind) const
> +{
> +  switch (get_bool_state (r, lhs, type))
> +    {
> +    case BRS_TRUE:
> +      build_lt (r, type, op1);
> +      break;
> +
> +    case BRS_FALSE:
> +      build_ge (r, type, op1);
> +      r.clear_nan ();
> +      break;
> +
> +    default:
> +      break;
> +    }
> +  return true;
> +}
> +
>  class foperator_unordered_ge : public range_operator_float
>  {
>    using range_operator_float::fold_range;
> +  using range_operator_float::op1_range;
> +  using range_operator_float::op2_range;
>  public:
>    bool fold_range (irange &r, tree type,
>                    const frange &op1, const frange &op2,
> @@ -1238,11 +1350,66 @@ public:
>         return true;
>        }
>    }
> +  bool op1_range (frange &r, tree type,
> +                 const irange &lhs, const frange &op2,
> +                 relation_kind rel) const final override;
> +  bool op2_range (frange &r, tree type,
> +                 const irange &lhs, const frange &op1,
> +                 relation_kind rel) const final override;
>  } fop_unordered_ge;
>
> +bool
> +foperator_unordered_ge::op1_range (frange &r,
> +                                  tree type,
> +                                  const irange &lhs,
> +                                  const frange &op2,
> +                                  relation_kind) const
> +{
> +  switch (get_bool_state (r, lhs, type))
> +    {
> +    case BRS_TRUE:
> +      build_ge (r, type, op2);
> +      break;
> +
> +    case BRS_FALSE:
> +      build_lt (r, type, op2);
> +      r.clear_nan ();
> +      break;
> +
> +    default:
> +      break;
> +    }
> +  return true;
> +}
> +
> +bool
> +foperator_unordered_ge::op2_range (frange &r, tree type,
> +                                  const irange &lhs,
> +                                  const frange &op1,
> +                                  relation_kind) const
> +{
> +  switch (get_bool_state (r, lhs, type))
> +    {
> +    case BRS_TRUE:
> +      build_le (r, type, op1);
> +      break;
> +
> +    case BRS_FALSE:
> +      build_gt (r, type, op1);
> +      r.clear_nan ();
> +      break;
> +
> +    default:
> +      break;
> +    }
> +  return true;
> +}
> +
>  class foperator_unordered_equal : public range_operator_float
>  {
>    using range_operator_float::fold_range;
> +  using range_operator_float::op1_range;
> +  using range_operator_float::op2_range;
>  public:
>    bool fold_range (irange &r, tree type,
>                    const frange &op1, const frange &op2,
> @@ -1265,8 +1432,46 @@ public:
>         return true;
>        }
>    }
> +  bool op1_range (frange &r, tree type,
> +                 const irange &lhs, const frange &op2,
> +                 relation_kind rel) const final override;
> +  bool op2_range (frange &r, tree type,
> +                 const irange &lhs, const frange &op1,
> +                 relation_kind rel) const final override
> +  {
> +    return op1_range (r, type, lhs, op1, rel);
> +  }
>  } fop_unordered_equal;
>
> +bool
> +foperator_unordered_equal::op1_range (frange &r, tree type,
> +                                     const irange &lhs,
> +                                     const frange &op2,
> +                                     relation_kind) const
> +{
> +  switch (get_bool_state (r, lhs, type))
> +    {
> +    case BRS_TRUE:
> +      // If it's true, the result is the same as OP2 plus a NAN.
> +      r = op2;
> +      // Add both zeros if there's the possibility of zero equality.
> +      frange_add_zeros (r, type);
> +      // Add the posibility of a NAN.
> +      r.update_nan ();
> +      break;
> +
> +    case BRS_FALSE:
> +      // The false side indictates !NAN and not equal.  We can at least
> +      // represent !NAN.
> +      r.set_varying (type);
> +      r.clear_nan ();
> +      break;
> +
> +    default:
> +      break;
> +    }
> +  return true;
> +}
>
>  // Instantiate a range_op_table for floating point operations.
>  static floating_op_table global_floating_table;
> --
> 2.37.3
>


^ permalink raw reply	[flat|nested] 5+ messages in thread

end of thread, other threads:[~2022-10-11 13:57 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-10-11 13:51 [COMMITTED] Move TRUE case first in range-op.cc Aldy Hernandez
2022-10-11 13:51 ` [COMMITTED] Share common ordered comparison code with UN*_EXPR Aldy Hernandez
2022-10-11 13:51 ` [COMMITTED] Implement op1_range operators for unordered comparisons Aldy Hernandez
2022-10-11 13:57   ` Aldy Hernandez
2022-10-11 13:51 ` [COMMITTED] Implement ABS_EXPR operator for frange Aldy Hernandez

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).