public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
* [RFC PATCH] range-op-float: Fix up op1_op2_relation of comparisons
@ 2023-04-11  8:21 Jakub Jelinek
  2023-04-11  8:59 ` Aldy Hernandez
  2023-04-11 20:58 ` Andrew MacLeod
  0 siblings, 2 replies; 7+ messages in thread
From: Jakub Jelinek @ 2023-04-11  8:21 UTC (permalink / raw)
  To: Aldy Hernandez, Andrew MacLeod; +Cc: gcc-patches

Hi!

This patch was what I've tried first before the currently committed
PR109386 fix.  Still, I think it is the right thing until we have proper
full set of VREL_* relations for NANs (though it would be really nice
if op1_op2_relation could be passed either type of the comparison
operands, or even better ranges of the two operands, such that
we could choose if inversion of say VREL_LT is VREL_GE (if !MODE_HONOR_NANS
(TYPE_MODE (type))) or rhs1/rhs2 ranges are guaranteed not to include
NANs (!known_isnan && !maybe_isnan for both), or VREL_UNGE, etc.
Anyway, the current state is that for the LE/LT/GE/GT comparisons
we pretend the inverse is like for integral comparisons, which is
true only if NANs can't appear in operands, while for UNLE/UNLT/UNGE/UNGT
we don't override op1_op2_relation (so it always yields VREL_VARYING).

Though, this patch regresses the
FAIL: gcc.dg/tree-ssa/vrp-float-6.c scan-tree-dump-times evrp "Folding predicate x_.* <= y_.* to 1" 1
test, so am not sure what to do with it.  The test has explicit
!isnan tests around it, so e.g. having the ranges passed to op1_op2_relation
would also fix it.

2023-04-11  Jakub Jelinek  <jakub@redhat.com>

	* range-op-float.cc (foperator_lt::op1_op2_relation): Return
	VREL_VARYING instead of VREL_GE.
	(foperator_le::op1_op2_relation): Return VREL_VARYING instead of
	VREL_GT.
	(foperator_gt::op1_op2_relation): Return VREL_VARYING instead of
	VREL_LE.
	(foperator_ge::op1_op2_relation): Return VREL_VARYING instead of
	VREL_LT.
	(foperator_unordered_lt::op1_op2_relation,
	foperator_unordered_le::op1_op2_relation,
	foperator_unordered_gt::op1_op2_relation,
	foperator_unordered_ge::op1_op2_relation): New.

--- gcc/range-op-float.cc.jj	2023-04-01 09:32:02.635423345 +0200
+++ gcc/range-op-float.cc	2023-04-03 10:42:54.000000000 +0200
@@ -831,7 +831,10 @@ public:
 		   relation_trio = TRIO_VARYING) const final override;
   relation_kind op1_op2_relation (const irange &lhs) const final override
   {
-    return lt_op1_op2_relation (lhs);
+    relation_kind ret = lt_op1_op2_relation (lhs);
+    if (ret == VREL_GE)
+      ret = VREL_VARYING; // Inverse of VREL_LT is VREL_UNGE.
+    return ret;
   }
   bool op1_range (frange &r, tree type,
 		  const irange &lhs, const frange &op2,
@@ -947,6 +950,10 @@ public:
 		   relation_trio rel = TRIO_VARYING) const final override;
   relation_kind op1_op2_relation (const irange &lhs) const final override
   {
+    relation_kind ret = le_op1_op2_relation (lhs);
+    if (ret == VREL_GT)
+      ret = VREL_VARYING; // Inverse of VREL_LE is VREL_UNGT.
+    return ret;
     return le_op1_op2_relation (lhs);
   }
   bool op1_range (frange &r, tree type,
@@ -1057,7 +1064,10 @@ public:
 		   relation_trio = TRIO_VARYING) const final override;
   relation_kind op1_op2_relation (const irange &lhs) const final override
   {
-    return gt_op1_op2_relation (lhs);
+    relation_kind ret = gt_op1_op2_relation (lhs);
+    if (ret == VREL_LE)
+      ret = VREL_VARYING; // Inverse of VREL_GT is VREL_UNLE.
+    return ret;
   }
   bool op1_range (frange &r, tree type,
 		  const irange &lhs, const frange &op2,
@@ -1177,7 +1187,10 @@ public:
 		   relation_trio = TRIO_VARYING) const final override;
   relation_kind op1_op2_relation (const irange &lhs) const final override
   {
-    return ge_op1_op2_relation (lhs);
+    relation_kind ret = ge_op1_op2_relation (lhs);
+    if (ret == VREL_LT)
+      ret = VREL_VARYING; // Inverse of VREL_GE is VREL_UNLT.
+    return ret;
   }
   bool op1_range (frange &r, tree type,
 		  const irange &lhs, const frange &op2,
@@ -1571,6 +1584,7 @@ class foperator_unordered_lt : public ra
   using range_operator_float::fold_range;
   using range_operator_float::op1_range;
   using range_operator_float::op2_range;
+  using range_operator_float::op1_op2_relation;
 public:
   bool fold_range (irange &r, tree type,
 		   const frange &op1, const frange &op2,
@@ -1599,6 +1613,13 @@ public:
 	return true;
       }
   }
+  relation_kind op1_op2_relation (const irange &lhs) const final override
+  {
+    relation_kind ret = lt_op1_op2_relation (lhs);
+    if (ret == VREL_LT)
+      ret = VREL_VARYING; // Should have been VREL_UNLT.
+    return ret;
+  }
   bool op1_range (frange &r, tree type,
 		  const irange &lhs,
 		  const frange &op2,
@@ -1682,6 +1703,7 @@ class foperator_unordered_le : public ra
   using range_operator_float::fold_range;
   using range_operator_float::op1_range;
   using range_operator_float::op2_range;
+  using range_operator_float::op1_op2_relation;
 public:
   bool fold_range (irange &r, tree type,
 		   const frange &op1, const frange &op2,
@@ -1710,6 +1732,13 @@ public:
 	return true;
       }
   }
+  relation_kind op1_op2_relation (const irange &lhs) const final override
+  {
+    relation_kind ret = le_op1_op2_relation (lhs);
+    if (ret == VREL_LE)
+      ret = VREL_VARYING; // Should have been VREL_UNLE.
+    return ret;
+  }
   bool op1_range (frange &r, tree type,
 		  const irange &lhs, const frange &op2,
 		  relation_trio = TRIO_VARYING) const final override;
@@ -1789,6 +1818,7 @@ class foperator_unordered_gt : public ra
   using range_operator_float::fold_range;
   using range_operator_float::op1_range;
   using range_operator_float::op2_range;
+  using range_operator_float::op1_op2_relation;
 public:
   bool fold_range (irange &r, tree type,
 		   const frange &op1, const frange &op2,
@@ -1817,6 +1847,13 @@ public:
 	return true;
       }
   }
+  relation_kind op1_op2_relation (const irange &lhs) const final override
+  {
+    relation_kind ret = gt_op1_op2_relation (lhs);
+    if (ret == VREL_GT)
+      ret = VREL_VARYING; // Should have been VREL_UNGT.
+    return ret;
+  }
   bool op1_range (frange &r, tree type,
 		  const irange &lhs, const frange &op2,
 		  relation_trio = TRIO_VARYING) const final override;
@@ -1900,6 +1937,7 @@ class foperator_unordered_ge : public ra
   using range_operator_float::fold_range;
   using range_operator_float::op1_range;
   using range_operator_float::op2_range;
+  using range_operator_float::op1_op2_relation;
 public:
   bool fold_range (irange &r, tree type,
 		   const frange &op1, const frange &op2,
@@ -1928,6 +1966,13 @@ public:
 	return true;
       }
   }
+  relation_kind op1_op2_relation (const irange &lhs) const final override
+  {
+    relation_kind ret = ge_op1_op2_relation (lhs);
+    if (ret == VREL_GE)
+      ret = VREL_VARYING; // Should have been VREL_UNGE.
+    return ret;
+  }
   bool op1_range (frange &r, tree type,
 		  const irange &lhs, const frange &op2,
 		  relation_trio = TRIO_VARYING) const final override;

	Jakub


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

* Re: [RFC PATCH] range-op-float: Fix up op1_op2_relation of comparisons
  2023-04-11  8:21 [RFC PATCH] range-op-float: Fix up op1_op2_relation of comparisons Jakub Jelinek
@ 2023-04-11  8:59 ` Aldy Hernandez
  2023-04-11 20:58 ` Andrew MacLeod
  1 sibling, 0 replies; 7+ messages in thread
From: Aldy Hernandez @ 2023-04-11  8:59 UTC (permalink / raw)
  To: Jakub Jelinek, Andrew MacLeod; +Cc: gcc-patches



On 4/11/23 10:21, Jakub Jelinek wrote:
> Hi!
> 
> This patch was what I've tried first before the currently committed
> PR109386 fix.  Still, I think it is the right thing until we have proper
> full set of VREL_* relations for NANs (though it would be really nice
> if op1_op2_relation could be passed either type of the comparison
> operands, or even better ranges of the two operands, such that
> we could choose if inversion of say VREL_LT is VREL_GE (if !MODE_HONOR_NANS
> (TYPE_MODE (type))) or rhs1/rhs2 ranges are guaranteed not to include
> NANs (!known_isnan && !maybe_isnan for both), or VREL_UNGE, etc.
> Anyway, the current state is that for the LE/LT/GE/GT comparisons
> we pretend the inverse is like for integral comparisons, which is
> true only if NANs can't appear in operands, while for UNLE/UNLT/UNGE/UNGT
> we don't override op1_op2_relation (so it always yields VREL_VARYING).
> 
> Though, this patch regresses the
> FAIL: gcc.dg/tree-ssa/vrp-float-6.c scan-tree-dump-times evrp "Folding predicate x_.* <= y_.* to 1" 1
> test, so am not sure what to do with it.  The test has explicit
> !isnan tests around it, so e.g. having the ranges passed to op1_op2_relation
> would also fix it.

I'll defer to Andrew on this, as he's the master of the relation oracle :).

Aldy

> 
> 2023-04-11  Jakub Jelinek  <jakub@redhat.com>
> 
> 	* range-op-float.cc (foperator_lt::op1_op2_relation): Return
> 	VREL_VARYING instead of VREL_GE.
> 	(foperator_le::op1_op2_relation): Return VREL_VARYING instead of
> 	VREL_GT.
> 	(foperator_gt::op1_op2_relation): Return VREL_VARYING instead of
> 	VREL_LE.
> 	(foperator_ge::op1_op2_relation): Return VREL_VARYING instead of
> 	VREL_LT.
> 	(foperator_unordered_lt::op1_op2_relation,
> 	foperator_unordered_le::op1_op2_relation,
> 	foperator_unordered_gt::op1_op2_relation,
> 	foperator_unordered_ge::op1_op2_relation): New.
> 
> --- gcc/range-op-float.cc.jj	2023-04-01 09:32:02.635423345 +0200
> +++ gcc/range-op-float.cc	2023-04-03 10:42:54.000000000 +0200
> @@ -831,7 +831,10 @@ public:
>   		   relation_trio = TRIO_VARYING) const final override;
>     relation_kind op1_op2_relation (const irange &lhs) const final override
>     {
> -    return lt_op1_op2_relation (lhs);
> +    relation_kind ret = lt_op1_op2_relation (lhs);
> +    if (ret == VREL_GE)
> +      ret = VREL_VARYING; // Inverse of VREL_LT is VREL_UNGE.
> +    return ret;
>     }
>     bool op1_range (frange &r, tree type,
>   		  const irange &lhs, const frange &op2,
> @@ -947,6 +950,10 @@ public:
>   		   relation_trio rel = TRIO_VARYING) const final override;
>     relation_kind op1_op2_relation (const irange &lhs) const final override
>     {
> +    relation_kind ret = le_op1_op2_relation (lhs);
> +    if (ret == VREL_GT)
> +      ret = VREL_VARYING; // Inverse of VREL_LE is VREL_UNGT.
> +    return ret;
>       return le_op1_op2_relation (lhs);
>     }
>     bool op1_range (frange &r, tree type,
> @@ -1057,7 +1064,10 @@ public:
>   		   relation_trio = TRIO_VARYING) const final override;
>     relation_kind op1_op2_relation (const irange &lhs) const final override
>     {
> -    return gt_op1_op2_relation (lhs);
> +    relation_kind ret = gt_op1_op2_relation (lhs);
> +    if (ret == VREL_LE)
> +      ret = VREL_VARYING; // Inverse of VREL_GT is VREL_UNLE.
> +    return ret;
>     }
>     bool op1_range (frange &r, tree type,
>   		  const irange &lhs, const frange &op2,
> @@ -1177,7 +1187,10 @@ public:
>   		   relation_trio = TRIO_VARYING) const final override;
>     relation_kind op1_op2_relation (const irange &lhs) const final override
>     {
> -    return ge_op1_op2_relation (lhs);
> +    relation_kind ret = ge_op1_op2_relation (lhs);
> +    if (ret == VREL_LT)
> +      ret = VREL_VARYING; // Inverse of VREL_GE is VREL_UNLT.
> +    return ret;
>     }
>     bool op1_range (frange &r, tree type,
>   		  const irange &lhs, const frange &op2,
> @@ -1571,6 +1584,7 @@ class foperator_unordered_lt : public ra
>     using range_operator_float::fold_range;
>     using range_operator_float::op1_range;
>     using range_operator_float::op2_range;
> +  using range_operator_float::op1_op2_relation;
>   public:
>     bool fold_range (irange &r, tree type,
>   		   const frange &op1, const frange &op2,
> @@ -1599,6 +1613,13 @@ public:
>   	return true;
>         }
>     }
> +  relation_kind op1_op2_relation (const irange &lhs) const final override
> +  {
> +    relation_kind ret = lt_op1_op2_relation (lhs);
> +    if (ret == VREL_LT)
> +      ret = VREL_VARYING; // Should have been VREL_UNLT.
> +    return ret;
> +  }
>     bool op1_range (frange &r, tree type,
>   		  const irange &lhs,
>   		  const frange &op2,
> @@ -1682,6 +1703,7 @@ class foperator_unordered_le : public ra
>     using range_operator_float::fold_range;
>     using range_operator_float::op1_range;
>     using range_operator_float::op2_range;
> +  using range_operator_float::op1_op2_relation;
>   public:
>     bool fold_range (irange &r, tree type,
>   		   const frange &op1, const frange &op2,
> @@ -1710,6 +1732,13 @@ public:
>   	return true;
>         }
>     }
> +  relation_kind op1_op2_relation (const irange &lhs) const final override
> +  {
> +    relation_kind ret = le_op1_op2_relation (lhs);
> +    if (ret == VREL_LE)
> +      ret = VREL_VARYING; // Should have been VREL_UNLE.
> +    return ret;
> +  }
>     bool op1_range (frange &r, tree type,
>   		  const irange &lhs, const frange &op2,
>   		  relation_trio = TRIO_VARYING) const final override;
> @@ -1789,6 +1818,7 @@ class foperator_unordered_gt : public ra
>     using range_operator_float::fold_range;
>     using range_operator_float::op1_range;
>     using range_operator_float::op2_range;
> +  using range_operator_float::op1_op2_relation;
>   public:
>     bool fold_range (irange &r, tree type,
>   		   const frange &op1, const frange &op2,
> @@ -1817,6 +1847,13 @@ public:
>   	return true;
>         }
>     }
> +  relation_kind op1_op2_relation (const irange &lhs) const final override
> +  {
> +    relation_kind ret = gt_op1_op2_relation (lhs);
> +    if (ret == VREL_GT)
> +      ret = VREL_VARYING; // Should have been VREL_UNGT.
> +    return ret;
> +  }
>     bool op1_range (frange &r, tree type,
>   		  const irange &lhs, const frange &op2,
>   		  relation_trio = TRIO_VARYING) const final override;
> @@ -1900,6 +1937,7 @@ class foperator_unordered_ge : public ra
>     using range_operator_float::fold_range;
>     using range_operator_float::op1_range;
>     using range_operator_float::op2_range;
> +  using range_operator_float::op1_op2_relation;
>   public:
>     bool fold_range (irange &r, tree type,
>   		   const frange &op1, const frange &op2,
> @@ -1928,6 +1966,13 @@ public:
>   	return true;
>         }
>     }
> +  relation_kind op1_op2_relation (const irange &lhs) const final override
> +  {
> +    relation_kind ret = ge_op1_op2_relation (lhs);
> +    if (ret == VREL_GE)
> +      ret = VREL_VARYING; // Should have been VREL_UNGE.
> +    return ret;
> +  }
>     bool op1_range (frange &r, tree type,
>   		  const irange &lhs, const frange &op2,
>   		  relation_trio = TRIO_VARYING) const final override;
> 
> 	Jakub
> 


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

* Re: [RFC PATCH] range-op-float: Fix up op1_op2_relation of comparisons
  2023-04-11  8:21 [RFC PATCH] range-op-float: Fix up op1_op2_relation of comparisons Jakub Jelinek
  2023-04-11  8:59 ` Aldy Hernandez
@ 2023-04-11 20:58 ` Andrew MacLeod
  2023-04-12 10:33   ` Jakub Jelinek
  1 sibling, 1 reply; 7+ messages in thread
From: Andrew MacLeod @ 2023-04-11 20:58 UTC (permalink / raw)
  To: Jakub Jelinek, Aldy Hernandez; +Cc: gcc-patches

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


On 4/11/23 04:21, Jakub Jelinek wrote:
> Hi!
>
> This patch was what I've tried first before the currently committed
> PR109386 fix.  Still, I think it is the right thing until we have proper
> full set of VREL_* relations for NANs (though it would be really nice
> if op1_op2_relation could be passed either type of the comparison
> operands, or even better ranges of the two operands, such that
> we could choose if inversion of say VREL_LT is VREL_GE (if !MODE_HONOR_NANS
> (TYPE_MODE (type))) or rhs1/rhs2 ranges are guaranteed not to include
> NANs (!known_isnan && !maybe_isnan for both), or VREL_UNGE, etc.
> Anyway, the current state is that for the LE/LT/GE/GT comparisons
> we pretend the inverse is like for integral comparisons, which is
> true only if NANs can't appear in operands, while for UNLE/UNLT/UNGE/UNGT
> we don't override op1_op2_relation (so it always yields VREL_VARYING).
>
> Though, this patch regresses the
> FAIL: gcc.dg/tree-ssa/vrp-float-6.c scan-tree-dump-times evrp "Folding predicate x_.* <= y_.* to 1" 1
> test, so am not sure what to do with it.  The test has explicit
> !isnan tests around it, so e.g. having the ranges passed to op1_op2_relation
> would also fix it.


I see no reason op1_op2_relation can't have ranges provided to it for 
op1 and op2.  There was no need originally.  There are times when we 
don't have a range handy and we want the simple answer, but if the 
ranges are available, we could utilize them.

Attached is a patch which added op1 and op2 ranges to the routine.  GORI 
will utilize and pass on real ranges (which I think is the core part you 
want), but the consumers in fold_using_range at this point will simply 
pass in varying.  There are 2 consumers in fold_using_range.. one is a 
combiner for logicals, and the other is for export outgoing relations 
that are not on the branch condition.  The combiner could use real 
ranges, but until I fix dispatch up it is very awkward to get them.  The 
export one simply doesn't have them without going to an calculating 
them.. which would probably be expensive..

Regardless, you can at least try your enhancement using real ranges and 
see if this works for you.

This bootstraps and has no regressions, and is fine by me if you want to 
use it.,

Andrew


[-- Attachment #2: rel.patch --]
[-- Type: text/x-patch, Size: 14578 bytes --]

commit 3715234f2cba21f2b9ec6c609b6f058d1d8af500
Author: Andrew MacLeod <amacleod@redhat.com>
Date:   Tue Apr 11 12:25:49 2023 -0400

    Add op1 and op2 ranges to op1_op2_relation.
    
            * gimple-range-fold.cc (fold_using_range::relation_fold_and_or):
            Provide VARYING for op1 and op2 when calling op1_op2_relation.
            (fur_source::register_outgoing_edges): Ditto.
            * gimple-range-gori.cc (gori_compute::compute_operand1_range):
            Pass op1 and op2 ranges to op1_op2_relation.
            (gori_compute::compute_operand2_range): Ditto.
            * range-op-float.cc (*::op1_op2_relation): Adjust params.
            * range-op.cc (*::op1_op2_relation): Adjust params.
            * range-op.h (*::op1_op2_relation): Adjust params.

diff --git a/gcc/gimple-range-fold.cc b/gcc/gimple-range-fold.cc
index e81f6b3699e..3170b1e71a1 100644
--- a/gcc/gimple-range-fold.cc
+++ b/gcc/gimple-range-fold.cc
@@ -1051,9 +1051,11 @@ fold_using_range::relation_fold_and_or (irange& lhs_range, gimple *s,
     return;
 
   int_range<2> bool_one (boolean_true_node, boolean_true_node);
+  Value_Range op (TREE_TYPE (ssa1));
+  op.set_varying (TREE_TYPE (ssa1));
 
-  relation_kind relation1 = handler1.op1_op2_relation (bool_one);
-  relation_kind relation2 = handler2.op1_op2_relation (bool_one);
+  relation_kind relation1 = handler1.op1_op2_relation (bool_one, op, op);
+  relation_kind relation2 = handler2.op1_op2_relation (bool_one, op, op);
   if (relation1 == VREL_VARYING || relation2 == VREL_VARYING)
     return;
 
@@ -1125,15 +1127,17 @@ fur_source::register_outgoing_edges (gcond *s, irange &lhs_range, edge e0, edge
   tree ssa2 = gimple_range_ssa_p (handler.operand2 ());
   if (ssa1 && ssa2)
     {
+      Value_Range op (TREE_TYPE (ssa1));
+      op.set_varying (TREE_TYPE (ssa1));
       if (e0)
 	{
-	  relation_kind relation = handler.op1_op2_relation (e0_range);
+	  relation_kind relation = handler.op1_op2_relation (e0_range, op, op);
 	  if (relation != VREL_VARYING)
 	    register_relation (e0, relation, ssa1, ssa2);
 	}
       if (e1)
 	{
-	  relation_kind relation = handler.op1_op2_relation (e1_range);
+	  relation_kind relation = handler.op1_op2_relation (e1_range, op, op);
 	  if (relation != VREL_VARYING)
 	    register_relation (e1, relation, ssa1, ssa2);
 	}
@@ -1160,17 +1164,19 @@ fur_source::register_outgoing_edges (gcond *s, irange &lhs_range, edge e0, edge
       Value_Range r (TREE_TYPE (name));
       if (ssa1 && ssa2)
 	{
+	  Value_Range op (TREE_TYPE (ssa1));
+	  op.set_varying (TREE_TYPE (ssa1));
 	  if (e0 && gori ()->outgoing_edge_range_p (r, e0, name, *m_query)
 	      && r.singleton_p ())
 	    {
-	      relation_kind relation = handler.op1_op2_relation (r);
+	      relation_kind relation = handler.op1_op2_relation (r, op, op);
 	      if (relation != VREL_VARYING)
 		register_relation (e0, relation, ssa1, ssa2);
 	    }
 	  if (e1 && gori ()->outgoing_edge_range_p (r, e1, name, *m_query)
 	      && r.singleton_p ())
 	    {
-	      relation_kind relation = handler.op1_op2_relation (r);
+	      relation_kind relation = handler.op1_op2_relation (r, op, op);
 	      if (relation != VREL_VARYING)
 		register_relation (e1, relation, ssa1, ssa2);
 	    }
diff --git a/gcc/gimple-range-gori.cc b/gcc/gimple-range-gori.cc
index d77e1f51ac2..a488c230f6c 100644
--- a/gcc/gimple-range-gori.cc
+++ b/gcc/gimple-range-gori.cc
@@ -1105,7 +1105,8 @@ gori_compute::compute_operand1_range (vrange &r,
       // This allows multiple relations to be processed in compound logicals.
       if (gimple_range_ssa_p (op1) && gimple_range_ssa_p (op2))
 	{
-	  relation_kind k = handler.op1_op2_relation (lhs);
+	  relation_kind k = handler.op1_op2_relation (lhs, op1_range,
+						      op2_range);
 	  if (k != VREL_VARYING)
 	    {
 	      op_op = k;
@@ -1210,7 +1211,7 @@ gori_compute::compute_operand2_range (vrange &r,
   // This allows multiple relations to be processed in compound logicals.
   if (gimple_range_ssa_p (op1) && gimple_range_ssa_p (op2))
     {
-      relation_kind k = handler.op1_op2_relation (lhs);
+      relation_kind k = handler.op1_op2_relation (lhs, op1_range, op2_range);
       if (k != VREL_VARYING)
 	{
 	  op_op = k;
diff --git a/gcc/range-op-float.cc b/gcc/range-op-float.cc
index e0e91bad44d..72de8f2a856 100644
--- a/gcc/range-op-float.cc
+++ b/gcc/range-op-float.cc
@@ -233,13 +233,17 @@ range_operator_float::lhs_op2_relation (const frange &lhs ATTRIBUTE_UNUSED,
 }
 
 relation_kind
-range_operator_float::op1_op2_relation (const irange &lhs ATTRIBUTE_UNUSED) const
+range_operator_float::op1_op2_relation (const irange &lhs ATTRIBUTE_UNUSED,
+					const frange &op1 ATTRIBUTE_UNUSED,
+					const frange &op2 ATTRIBUTE_UNUSED) const
 {
   return VREL_VARYING;
 }
 
 relation_kind
-range_operator_float::op1_op2_relation (const frange &lhs ATTRIBUTE_UNUSED) const
+range_operator_float::op1_op2_relation (const frange &lhs ATTRIBUTE_UNUSED,
+					const frange &op1 ATTRIBUTE_UNUSED,
+					const frange &op2 ATTRIBUTE_UNUSED) const
 {
   return VREL_VARYING;
 }
@@ -578,7 +582,8 @@ public:
   bool fold_range (irange &r, tree type,
 		   const frange &op1, const frange &op2,
 		   relation_trio = TRIO_VARYING) const final override;
-  relation_kind op1_op2_relation (const irange &lhs) const final override
+  relation_kind op1_op2_relation (const irange &lhs, const frange &,
+				  const frange &) const final override
   {
     return equal_op1_op2_relation (lhs);
   }
@@ -706,7 +711,8 @@ public:
   bool fold_range (irange &r, tree type,
 		   const frange &op1, const frange &op2,
 		   relation_trio rel = TRIO_VARYING) const final override;
-  relation_kind op1_op2_relation (const irange &lhs) const final override
+  relation_kind op1_op2_relation (const irange &lhs, const frange &,
+				  const frange &) const final override
   {
     return not_equal_op1_op2_relation (lhs);
   }
@@ -829,7 +835,8 @@ public:
   bool fold_range (irange &r, tree type,
 		   const frange &op1, const frange &op2,
 		   relation_trio = TRIO_VARYING) const final override;
-  relation_kind op1_op2_relation (const irange &lhs) const final override
+  relation_kind op1_op2_relation (const irange &lhs, const frange &,
+				  const frange &) const final override
   {
     return lt_op1_op2_relation (lhs);
   }
@@ -945,7 +952,8 @@ public:
   bool fold_range (irange &r, tree type,
 		   const frange &op1, const frange &op2,
 		   relation_trio rel = TRIO_VARYING) const final override;
-  relation_kind op1_op2_relation (const irange &lhs) const final override
+  relation_kind op1_op2_relation (const irange &lhs, const frange &,
+				  const frange &) const final override
   {
     return le_op1_op2_relation (lhs);
   }
@@ -1055,7 +1063,8 @@ public:
   bool fold_range (irange &r, tree type,
 		   const frange &op1, const frange &op2,
 		   relation_trio = TRIO_VARYING) const final override;
-  relation_kind op1_op2_relation (const irange &lhs) const final override
+  relation_kind op1_op2_relation (const irange &lhs, const frange &,
+				  const frange &) const final override
   {
     return gt_op1_op2_relation (lhs);
   }
@@ -1175,7 +1184,8 @@ public:
   bool fold_range (irange &r, tree type,
 		   const frange &op1, const frange &op2,
 		   relation_trio = TRIO_VARYING) const final override;
-  relation_kind op1_op2_relation (const irange &lhs) const final override
+  relation_kind op1_op2_relation (const irange &lhs, const frange &,
+				  const frange &) const final override
   {
     return ge_op1_op2_relation (lhs);
   }
diff --git a/gcc/range-op.cc b/gcc/range-op.cc
index f90e78dcfbc..876747110a9 100644
--- a/gcc/range-op.cc
+++ b/gcc/range-op.cc
@@ -368,11 +368,14 @@ range_operator::lhs_op2_relation (const irange &lhs ATTRIBUTE_UNUSED,
 }
 
 relation_kind
-range_operator::op1_op2_relation (const irange &lhs ATTRIBUTE_UNUSED) const
+range_operator::op1_op2_relation (const irange &lhs ATTRIBUTE_UNUSED,
+				  const irange &op1 ATTRIBUTE_UNUSED,
+				  const irange &op2 ATTRIBUTE_UNUSED) const
 {
   return VREL_VARYING;
 }
 
+
 // Default is no relation affects the LHS.
 
 bool
@@ -565,7 +568,9 @@ public:
 			  const irange &lhs,
 			  const irange &val,
 			  relation_trio = TRIO_VARYING) const;
-  virtual relation_kind op1_op2_relation (const irange &lhs) const;
+  virtual relation_kind op1_op2_relation (const irange &lhs,
+					  const irange &,
+					  const irange &) const;
 } op_equal;
 
 // Check if the LHS range indicates a relation between OP1 and OP2.
@@ -587,7 +592,8 @@ equal_op1_op2_relation (const irange &lhs)
 }
 
 relation_kind
-operator_equal::op1_op2_relation (const irange &lhs) const
+operator_equal::op1_op2_relation (const irange &lhs, const irange &,
+				  const irange &) const
 {
   return equal_op1_op2_relation (lhs);
 }
@@ -685,7 +691,8 @@ public:
 			  const irange &lhs,
 			  const irange &op1,
 			  relation_trio = TRIO_VARYING) const;
-  virtual relation_kind op1_op2_relation (const irange &lhs) const;
+  virtual relation_kind op1_op2_relation (const irange &lhs, const irange &,
+					  const irange &) const;
 } op_not_equal;
 
 // Check if the LHS range indicates a relation between OP1 and OP2.
@@ -707,7 +714,8 @@ not_equal_op1_op2_relation (const irange &lhs)
 }
 
 relation_kind
-operator_not_equal::op1_op2_relation (const irange &lhs) const
+operator_not_equal::op1_op2_relation (const irange &lhs, const irange &,
+				      const irange &) const
 {
   return not_equal_op1_op2_relation (lhs);
 }
@@ -865,7 +873,8 @@ public:
 			  const irange &lhs,
 			  const irange &op1,
 			  relation_trio = TRIO_VARYING) const;
-  virtual relation_kind op1_op2_relation (const irange &lhs) const;
+  virtual relation_kind op1_op2_relation (const irange &lhs, const irange &,
+					  const irange &) const;
 } op_lt;
 
 // Check if the LHS range indicates a relation between OP1 and OP2.
@@ -887,7 +896,8 @@ lt_op1_op2_relation (const irange &lhs)
 }
 
 relation_kind
-operator_lt::op1_op2_relation (const irange &lhs) const
+operator_lt::op1_op2_relation (const irange &lhs, const irange &,
+			       const irange &) const
 {
   return lt_op1_op2_relation (lhs);
 }
@@ -985,7 +995,8 @@ public:
 			  const irange &lhs,
 			  const irange &op1,
 			  relation_trio = TRIO_VARYING) const;
-  virtual relation_kind op1_op2_relation (const irange &lhs) const;
+  virtual relation_kind op1_op2_relation (const irange &lhs, const irange &,
+					  const irange &) const;
 } op_le;
 
 // Check if the LHS range indicates a relation between OP1 and OP2.
@@ -1007,7 +1018,8 @@ le_op1_op2_relation (const irange &lhs)
 }
 
 relation_kind
-operator_le::op1_op2_relation (const irange &lhs) const
+operator_le::op1_op2_relation (const irange &lhs, const irange &,
+			       const irange &) const
 {
   return le_op1_op2_relation (lhs);
 }
@@ -1102,7 +1114,8 @@ public:
 			  const irange &lhs,
 			  const irange &op1,
 			  relation_trio = TRIO_VARYING) const;
-  virtual relation_kind op1_op2_relation (const irange &lhs) const;
+  virtual relation_kind op1_op2_relation (const irange &lhs, const irange &,
+					  const irange &) const;
 } op_gt;
 
 // Check if the LHS range indicates a relation between OP1 and OP2.
@@ -1124,7 +1137,8 @@ gt_op1_op2_relation (const irange &lhs)
 }
 
 relation_kind
-operator_gt::op1_op2_relation (const irange &lhs) const
+operator_gt::op1_op2_relation (const irange &lhs, const irange &,
+			       const irange &) const
 {
   return gt_op1_op2_relation (lhs);
 }
@@ -1218,7 +1232,8 @@ public:
 			  const irange &lhs,
 			  const irange &op1,
 			  relation_trio = TRIO_VARYING) const;
-  virtual relation_kind op1_op2_relation (const irange &lhs) const;
+  virtual relation_kind op1_op2_relation (const irange &lhs, const irange &,
+					  const irange &) const;
 } op_ge;
 
 // Check if the LHS range indicates a relation between OP1 and OP2.
@@ -1240,7 +1255,8 @@ ge_op1_op2_relation (const irange &lhs)
 }
 
 relation_kind
-operator_ge::op1_op2_relation (const irange &lhs) const
+operator_ge::op1_op2_relation (const irange &lhs, const irange &,
+			       const irange &) const
 {
   return ge_op1_op2_relation (lhs);
 }
@@ -4845,14 +4861,21 @@ range_op_handler::lhs_op2_relation (const vrange &lhs,
 }
 
 relation_kind
-range_op_handler::op1_op2_relation (const vrange &lhs) const
+range_op_handler::op1_op2_relation (const vrange &lhs, const vrange &op1,
+				    const vrange &op2) const
 {
   gcc_checking_assert (m_valid);
   if (m_int)
-    return m_int->op1_op2_relation (as_a <irange> (lhs));
+    return m_int->op1_op2_relation (as_a <irange> (lhs),
+				    as_a <irange> (op1),
+				    as_a <irange> (op2));
   if (is_a <irange> (lhs))
-    return m_float->op1_op2_relation (as_a <irange> (lhs));
-  return m_float->op1_op2_relation (as_a <frange> (lhs));
+    return m_float->op1_op2_relation (as_a <irange> (lhs),
+				      as_a <frange> (op1),
+				      as_a <frange> (op2));
+  return m_float->op1_op2_relation (as_a <frange> (lhs),
+				    as_a <frange> (op1),
+				    as_a <frange> (op2));
 }
 
 // Cast the range in R to TYPE.
diff --git a/gcc/range-op.h b/gcc/range-op.h
index 03ef6b98542..310302b4ec9 100644
--- a/gcc/range-op.h
+++ b/gcc/range-op.h
@@ -89,7 +89,9 @@ public:
 					  const irange &op1,
 					  const irange &op2,
 					  relation_kind = VREL_VARYING) const;
-  virtual relation_kind op1_op2_relation (const irange &lhs) const;
+  virtual relation_kind op1_op2_relation (const irange &lhs,
+					  const irange &op1,
+					  const irange &op2) const;
 protected:
   // Perform an integral operation between 2 sub-ranges and return it.
   virtual void wi_fold (irange &r, tree type,
@@ -178,8 +180,12 @@ public:
 					  const frange &op1,
 					  const frange &op2,
 					  relation_kind = VREL_VARYING) const;
-  virtual relation_kind op1_op2_relation (const irange &lhs) const;
-  virtual relation_kind op1_op2_relation (const frange &lhs) const;
+  virtual relation_kind op1_op2_relation (const irange &lhs,
+					  const frange &op1,
+					  const frange &op2) const;
+  virtual relation_kind op1_op2_relation (const frange &lhs,
+					  const frange &op1,
+					  const frange &op2) const;
 };
 
 class range_op_handler
@@ -209,7 +215,8 @@ public:
 				  const vrange &op1,
 				  const vrange &op2,
 				  relation_kind = VREL_VARYING) const;
-  relation_kind op1_op2_relation (const vrange &lhs) const;
+  relation_kind op1_op2_relation (const vrange &lhs, const vrange &op1,
+				  const vrange &op2) const;
 protected:
   void set_op_handler (enum tree_code code, tree type);
   bool m_valid;

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

* Re: [RFC PATCH] range-op-float: Fix up op1_op2_relation of comparisons
  2023-04-11 20:58 ` Andrew MacLeod
@ 2023-04-12 10:33   ` Jakub Jelinek
  2023-04-12 14:21     ` Jakub Jelinek
  0 siblings, 1 reply; 7+ messages in thread
From: Jakub Jelinek @ 2023-04-12 10:33 UTC (permalink / raw)
  To: Andrew MacLeod; +Cc: Aldy Hernandez, gcc-patches

On Tue, Apr 11, 2023 at 04:58:19PM -0400, Andrew MacLeod wrote:
> This bootstraps and has no regressions, and is fine by me if you want to use
> it.

Thanks, looks nice.
My incremental patch on top of that would then be below.

Though,
FAIL: gcc.dg/tree-ssa/vrp-float-6.c scan-tree-dump-times evrp "Folding predicate x_.* <= y_.* to 1" 1
still FAILs with those 2 patches together.
Shall we just xfail it for now and find some solution for GCC 14?

2023-04-12  Jakub Jelinek  <jakub@redhat.com>

	* range-op-float.cc (foperator_lt::op1_op2_relation): Return
	VREL_VARYING instead of VREL_GE if HONOR_NANS and op1 or op2 could be
	NANs.
	(foperator_le::op1_op2_relation): Similarly return VREL_VARYING
	instead of VREL_GT.
	(foperator_gt::op1_op2_relation): Similarly return VREL_VARYING
	instead of VREL_LE.
	(foperator_ge::op1_op2_relation): Similarly return VREL_VARYING
	instead of VREL_LT.
	(foperator_unordered_lt::op1_op2_relation,
	foperator_unordered_le::op1_op2_relation,
	foperator_unordered_gt::op1_op2_relation,
	foperator_unordered_ge::op1_op2_relation): New.

--- gcc/range-op-float.cc.jj	2023-04-12 12:17:44.784962757 +0200
+++ gcc/range-op-float.cc	2023-04-12 12:26:11.740657502 +0200
@@ -835,10 +835,18 @@ public:
   bool fold_range (irange &r, tree type,
 		   const frange &op1, const frange &op2,
 		   relation_trio = TRIO_VARYING) const final override;
-  relation_kind op1_op2_relation (const irange &lhs, const frange &,
-				  const frange &) const final override
+  relation_kind op1_op2_relation (const irange &lhs, const frange &op1,
+				  const frange &op2) const final override
   {
-    return lt_op1_op2_relation (lhs);
+    relation_kind ret = lt_op1_op2_relation (lhs);
+    if (ret == VREL_GE
+	&& HONOR_NANS (op1.type ())
+	&& (op1.known_isnan ()
+	    || op1.maybe_isnan ()
+	    || op2.known_isnan ()
+	    || op2.maybe_isnan ()))
+      ret = VREL_VARYING; // Inverse of VREL_LT is VREL_UNGE with NAN ops.
+    return ret;
   }
   bool op1_range (frange &r, tree type,
 		  const irange &lhs, const frange &op2,
@@ -952,9 +960,18 @@ public:
   bool fold_range (irange &r, tree type,
 		   const frange &op1, const frange &op2,
 		   relation_trio rel = TRIO_VARYING) const final override;
-  relation_kind op1_op2_relation (const irange &lhs, const frange &,
-				  const frange &) const final override
+  relation_kind op1_op2_relation (const irange &lhs, const frange &op1,
+				  const frange &op2) const final override
   {
+    relation_kind ret = le_op1_op2_relation (lhs);
+    if (ret == VREL_GT
+	&& HONOR_NANS (op1.type ())
+	&& (op1.known_isnan ()
+	    || op1.maybe_isnan ()
+	    || op2.known_isnan ()
+	    || op2.maybe_isnan ()))
+      ret = VREL_VARYING; // Inverse of VREL_LE is VREL_UNGT with NAN ops.
+    return ret;
     return le_op1_op2_relation (lhs);
   }
   bool op1_range (frange &r, tree type,
@@ -1063,10 +1080,18 @@ public:
   bool fold_range (irange &r, tree type,
 		   const frange &op1, const frange &op2,
 		   relation_trio = TRIO_VARYING) const final override;
-  relation_kind op1_op2_relation (const irange &lhs, const frange &,
-				  const frange &) const final override
+  relation_kind op1_op2_relation (const irange &lhs, const frange &op1,
+				  const frange &op2) const final override
   {
-    return gt_op1_op2_relation (lhs);
+    relation_kind ret = gt_op1_op2_relation (lhs);
+    if (ret == VREL_LE
+	&& HONOR_NANS (op1.type ())
+	&& (op1.known_isnan ()
+	    || op1.maybe_isnan ()
+	    || op2.known_isnan ()
+	    || op2.maybe_isnan ()))
+      ret = VREL_VARYING; // Inverse of VREL_GT is VREL_UNLE with NAN ops.
+    return ret;
   }
   bool op1_range (frange &r, tree type,
 		  const irange &lhs, const frange &op2,
@@ -1184,10 +1209,18 @@ public:
   bool fold_range (irange &r, tree type,
 		   const frange &op1, const frange &op2,
 		   relation_trio = TRIO_VARYING) const final override;
-  relation_kind op1_op2_relation (const irange &lhs, const frange &,
-				  const frange &) const final override
+  relation_kind op1_op2_relation (const irange &lhs, const frange &op1,
+				  const frange &op2) const final override
   {
-    return ge_op1_op2_relation (lhs);
+    relation_kind ret = ge_op1_op2_relation (lhs);
+    if (ret == VREL_LT
+	&& HONOR_NANS (op1.type ())
+	&& (op1.known_isnan ()
+	    || op1.maybe_isnan ()
+	    || op2.known_isnan ()
+	    || op2.maybe_isnan ()))
+      ret = VREL_VARYING; // Inverse of VREL_GE is VREL_UNLT with NAN ops.
+    return ret;
   }
   bool op1_range (frange &r, tree type,
 		  const irange &lhs, const frange &op2,
@@ -1581,6 +1614,7 @@ class foperator_unordered_lt : public ra
   using range_operator_float::fold_range;
   using range_operator_float::op1_range;
   using range_operator_float::op2_range;
+  using range_operator_float::op1_op2_relation;
 public:
   bool fold_range (irange &r, tree type,
 		   const frange &op1, const frange &op2,
@@ -1609,6 +1643,19 @@ public:
 	return true;
       }
   }
+  relation_kind op1_op2_relation (const irange &lhs, const frange &op1,
+				  const frange &op2) const final override
+  {
+    relation_kind ret = lt_op1_op2_relation (lhs);
+    if (ret == VREL_LT
+	&& HONOR_NANS (op1.type ())
+	&& (op1.known_isnan ()
+	    || op1.maybe_isnan ()
+	    || op2.known_isnan ()
+	    || op2.maybe_isnan ()))
+      ret = VREL_VARYING; // Should have been VREL_UNLT with NAN ops.
+    return ret;
+  }
   bool op1_range (frange &r, tree type,
 		  const irange &lhs,
 		  const frange &op2,
@@ -1692,6 +1739,7 @@ class foperator_unordered_le : public ra
   using range_operator_float::fold_range;
   using range_operator_float::op1_range;
   using range_operator_float::op2_range;
+  using range_operator_float::op1_op2_relation;
 public:
   bool fold_range (irange &r, tree type,
 		   const frange &op1, const frange &op2,
@@ -1720,6 +1768,19 @@ public:
 	return true;
       }
   }
+  relation_kind op1_op2_relation (const irange &lhs, const frange &op1,
+				  const frange &op2) const final override
+  {
+    relation_kind ret = le_op1_op2_relation (lhs);
+    if (ret == VREL_LE
+	&& HONOR_NANS (op1.type ())
+	&& (op1.known_isnan ()
+	    || op1.maybe_isnan ()
+	    || op2.known_isnan ()
+	    || op2.maybe_isnan ()))
+      ret = VREL_VARYING; // Should have been VREL_UNLE with NAN ops.
+    return ret;
+  }
   bool op1_range (frange &r, tree type,
 		  const irange &lhs, const frange &op2,
 		  relation_trio = TRIO_VARYING) const final override;
@@ -1799,6 +1860,7 @@ class foperator_unordered_gt : public ra
   using range_operator_float::fold_range;
   using range_operator_float::op1_range;
   using range_operator_float::op2_range;
+  using range_operator_float::op1_op2_relation;
 public:
   bool fold_range (irange &r, tree type,
 		   const frange &op1, const frange &op2,
@@ -1827,6 +1889,19 @@ public:
 	return true;
       }
   }
+  relation_kind op1_op2_relation (const irange &lhs, const frange &op1,
+				  const frange &op2) const final override
+  {
+    relation_kind ret = gt_op1_op2_relation (lhs);
+    if (ret == VREL_GT
+	&& HONOR_NANS (op1.type ())
+	&& (op1.known_isnan ()
+	    || op1.maybe_isnan ()
+	    || op2.known_isnan ()
+	    || op2.maybe_isnan ()))
+      ret = VREL_VARYING; // Should have been VREL_UNGT with NAN ops.
+    return ret;
+  }
   bool op1_range (frange &r, tree type,
 		  const irange &lhs, const frange &op2,
 		  relation_trio = TRIO_VARYING) const final override;
@@ -1910,6 +1985,7 @@ class foperator_unordered_ge : public ra
   using range_operator_float::fold_range;
   using range_operator_float::op1_range;
   using range_operator_float::op2_range;
+  using range_operator_float::op1_op2_relation;
 public:
   bool fold_range (irange &r, tree type,
 		   const frange &op1, const frange &op2,
@@ -1938,6 +2014,19 @@ public:
 	return true;
       }
   }
+  relation_kind op1_op2_relation (const irange &lhs, const frange &op1,
+				  const frange &op2) const final override
+  {
+    relation_kind ret = ge_op1_op2_relation (lhs);
+    if (ret == VREL_GE
+	&& HONOR_NANS (op1.type ())
+	&& (op1.known_isnan ()
+	    || op1.maybe_isnan ()
+	    || op2.known_isnan ()
+	    || op2.maybe_isnan ()))
+      ret = VREL_VARYING; // Should have been VREL_UNGE with NAN ops.
+    return ret;
+  }
   bool op1_range (frange &r, tree type,
 		  const irange &lhs, const frange &op2,
 		  relation_trio = TRIO_VARYING) const final override;


	Jakub


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

* Re: [RFC PATCH] range-op-float: Fix up op1_op2_relation of comparisons
  2023-04-12 10:33   ` Jakub Jelinek
@ 2023-04-12 14:21     ` Jakub Jelinek
  2023-04-12 16:35       ` Bernhard Reutner-Fischer
  0 siblings, 1 reply; 7+ messages in thread
From: Jakub Jelinek @ 2023-04-12 14:21 UTC (permalink / raw)
  To: Andrew MacLeod, Aldy Hernandez, gcc-patches

On Wed, Apr 12, 2023 at 12:33:39PM +0200, Jakub Jelinek via Gcc-patches wrote:
> On Tue, Apr 11, 2023 at 04:58:19PM -0400, Andrew MacLeod wrote:
> > This bootstraps and has no regressions, and is fine by me if you want to use
> > it.
> 
> Thanks, looks nice.
> My incremental patch on top of that would then be below.
> 
> Though,
> FAIL: gcc.dg/tree-ssa/vrp-float-6.c scan-tree-dump-times evrp "Folding predicate x_.* <= y_.* to 1" 1
> still FAILs with those 2 patches together.
> Shall we just xfail it for now and find some solution for GCC 14?

Except that testing of this patch on top of your patch has shown
+FAIL: gfortran.dg/maxlocval_4.f90   -O3 -fomit-frame-pointer -funroll-loops -fpeel-loops -ftracer -finline-functions  (internal compiler error: in type, at value-range.h:1157)
+FAIL: gfortran.dg/maxlocval_4.f90   -O3 -fomit-frame-pointer -funroll-loops -fpeel-loops -ftracer -finline-functions  (test for excess errors)
+UNRESOLVED: gfortran.dg/maxlocval_4.f90   -O3 -fomit-frame-pointer -funroll-loops -fpeel-loops -ftracer -finline-functions  compilation failed to produce executable
+FAIL: gfortran.dg/maxlocval_4.f90   -O3 -g  (internal compiler error: in type, at value-range.h:1157)
+FAIL: gfortran.dg/maxlocval_4.f90   -O3 -g  (test for excess errors)
+UNRESOLVED: gfortran.dg/maxlocval_4.f90   -O3 -g  compilation failed to produce executable
+FAIL: gfortran.dg/minlocval_1.f90   -Os  (internal compiler error: in type, at value-range.h:1157)
+FAIL: gfortran.dg/minlocval_1.f90   -Os  (test for excess errors)
+UNRESOLVED: gfortran.dg/minlocval_1.f90   -Os  compilation failed to produce executable
+FAIL: gfortran.dg/minlocval_4.f90   -O3 -fomit-frame-pointer -funroll-loops -fpeel-loops -ftracer -finline-functions  (internal compiler error: in type, at value-range.h:1157)
+FAIL: gfortran.dg/minlocval_4.f90   -O3 -fomit-frame-pointer -funroll-loops -fpeel-loops -ftracer -finline-functions  (test for excess errors)
+UNRESOLVED: gfortran.dg/minlocval_4.f90   -O3 -fomit-frame-pointer -funroll-loops -fpeel-loops -ftracer -finline-functions  compilation failed to produce executable
+FAIL: gfortran.dg/minlocval_4.f90   -O3 -g  (internal compiler error: in type, at value-range.h:1157)
+FAIL: gfortran.dg/minlocval_4.f90   -O3 -g  (test for excess errors)
+UNRESOLVED: gfortran.dg/minlocval_4.f90   -O3 -g  compilation failed to produce executable
+FAIL: gfortran.dg/pr104466.f90   -O  (internal compiler error: in type, at value-range.h:1157)
+FAIL: gfortran.dg/pr104466.f90   -O  (test for excess errors)
+FAIL: gfortran.dg/pr79315.f90   -O  (internal compiler error: in type, at value-range.h:1157)
+FAIL: gfortran.dg/pr79315.f90   -O  (test for excess errors)
+FAIL: gfortran.dg/pr81175.f   -O  (internal compiler error: in type, at value-range.h:1157)
+FAIL: gfortran.dg/pr81175.f   -O  (test for excess errors)
+FAIL: gfortran.dg/graphite/id-11.f   -O  (internal compiler error: in type, at value-range.h:1157)
+FAIL: gfortran.dg/graphite/id-11.f   -O  (test for excess errors)
regressions, missed the fact that frange::type ICEs on undefined_p values.
Seems the HONOR_NANS case was there just as a bad attempt to speed the test
up, we can just test known_isnan || maybe_isnan on both operands and that is
it.
With this version all those tests pass again:

2023-04-12  Jakub Jelinek  <jakub@redhat.com>

	* range-op-float.cc (foperator_lt::op1_op2_relation): Return
	VREL_VARYING instead of VREL_GE if op1 or op2 could be NANs.
	(foperator_le::op1_op2_relation): Similarly return VREL_VARYING
	instead of VREL_GT.
	(foperator_gt::op1_op2_relation): Similarly return VREL_VARYING
	instead of VREL_LE.
	(foperator_ge::op1_op2_relation): Similarly return VREL_VARYING
	instead of VREL_LT.
	(foperator_unordered_lt::op1_op2_relation,
	foperator_unordered_le::op1_op2_relation,
	foperator_unordered_gt::op1_op2_relation,
	foperator_unordered_ge::op1_op2_relation): New.

--- gcc/range-op-float.cc.jj	2023-04-12 12:17:44.784962757 +0200
+++ gcc/range-op-float.cc	2023-04-12 16:07:54.948759355 +0200
@@ -835,10 +835,17 @@ public:
   bool fold_range (irange &r, tree type,
 		   const frange &op1, const frange &op2,
 		   relation_trio = TRIO_VARYING) const final override;
-  relation_kind op1_op2_relation (const irange &lhs, const frange &,
-				  const frange &) const final override
+  relation_kind op1_op2_relation (const irange &lhs, const frange &op1,
+				  const frange &op2) const final override
   {
-    return lt_op1_op2_relation (lhs);
+    relation_kind ret = lt_op1_op2_relation (lhs);
+    if (ret == VREL_GE
+	&& (op1.known_isnan ()
+	    || op1.maybe_isnan ()
+	    || op2.known_isnan ()
+	    || op2.maybe_isnan ()))
+      ret = VREL_VARYING; // Inverse of VREL_LT is VREL_UNGE with NAN ops.
+    return ret;
   }
   bool op1_range (frange &r, tree type,
 		  const irange &lhs, const frange &op2,
@@ -952,9 +959,17 @@ public:
   bool fold_range (irange &r, tree type,
 		   const frange &op1, const frange &op2,
 		   relation_trio rel = TRIO_VARYING) const final override;
-  relation_kind op1_op2_relation (const irange &lhs, const frange &,
-				  const frange &) const final override
+  relation_kind op1_op2_relation (const irange &lhs, const frange &op1,
+				  const frange &op2) const final override
   {
+    relation_kind ret = le_op1_op2_relation (lhs);
+    if (ret == VREL_GT
+	&& (op1.known_isnan ()
+	    || op1.maybe_isnan ()
+	    || op2.known_isnan ()
+	    || op2.maybe_isnan ()))
+      ret = VREL_VARYING; // Inverse of VREL_LE is VREL_UNGT with NAN ops.
+    return ret;
     return le_op1_op2_relation (lhs);
   }
   bool op1_range (frange &r, tree type,
@@ -1063,10 +1078,17 @@ public:
   bool fold_range (irange &r, tree type,
 		   const frange &op1, const frange &op2,
 		   relation_trio = TRIO_VARYING) const final override;
-  relation_kind op1_op2_relation (const irange &lhs, const frange &,
-				  const frange &) const final override
+  relation_kind op1_op2_relation (const irange &lhs, const frange &op1,
+				  const frange &op2) const final override
   {
-    return gt_op1_op2_relation (lhs);
+    relation_kind ret = gt_op1_op2_relation (lhs);
+    if (ret == VREL_LE
+	&& (op1.known_isnan ()
+	    || op1.maybe_isnan ()
+	    || op2.known_isnan ()
+	    || op2.maybe_isnan ()))
+      ret = VREL_VARYING; // Inverse of VREL_GT is VREL_UNLE with NAN ops.
+    return ret;
   }
   bool op1_range (frange &r, tree type,
 		  const irange &lhs, const frange &op2,
@@ -1184,10 +1206,17 @@ public:
   bool fold_range (irange &r, tree type,
 		   const frange &op1, const frange &op2,
 		   relation_trio = TRIO_VARYING) const final override;
-  relation_kind op1_op2_relation (const irange &lhs, const frange &,
-				  const frange &) const final override
+  relation_kind op1_op2_relation (const irange &lhs, const frange &op1,
+				  const frange &op2) const final override
   {
-    return ge_op1_op2_relation (lhs);
+    relation_kind ret = ge_op1_op2_relation (lhs);
+    if (ret == VREL_LT
+	&& (op1.known_isnan ()
+	    || op1.maybe_isnan ()
+	    || op2.known_isnan ()
+	    || op2.maybe_isnan ()))
+      ret = VREL_VARYING; // Inverse of VREL_GE is VREL_UNLT with NAN ops.
+    return ret;
   }
   bool op1_range (frange &r, tree type,
 		  const irange &lhs, const frange &op2,
@@ -1581,6 +1610,7 @@ class foperator_unordered_lt : public ra
   using range_operator_float::fold_range;
   using range_operator_float::op1_range;
   using range_operator_float::op2_range;
+  using range_operator_float::op1_op2_relation;
 public:
   bool fold_range (irange &r, tree type,
 		   const frange &op1, const frange &op2,
@@ -1609,6 +1639,18 @@ public:
 	return true;
       }
   }
+  relation_kind op1_op2_relation (const irange &lhs, const frange &op1,
+				  const frange &op2) const final override
+  {
+    relation_kind ret = lt_op1_op2_relation (lhs);
+    if (ret == VREL_LT
+	&& (op1.known_isnan ()
+	    || op1.maybe_isnan ()
+	    || op2.known_isnan ()
+	    || op2.maybe_isnan ()))
+      ret = VREL_VARYING; // Should have been VREL_UNLT with NAN ops.
+    return ret;
+  }
   bool op1_range (frange &r, tree type,
 		  const irange &lhs,
 		  const frange &op2,
@@ -1692,6 +1734,7 @@ class foperator_unordered_le : public ra
   using range_operator_float::fold_range;
   using range_operator_float::op1_range;
   using range_operator_float::op2_range;
+  using range_operator_float::op1_op2_relation;
 public:
   bool fold_range (irange &r, tree type,
 		   const frange &op1, const frange &op2,
@@ -1720,6 +1763,18 @@ public:
 	return true;
       }
   }
+  relation_kind op1_op2_relation (const irange &lhs, const frange &op1,
+				  const frange &op2) const final override
+  {
+    relation_kind ret = le_op1_op2_relation (lhs);
+    if (ret == VREL_LE
+	&& (op1.known_isnan ()
+	    || op1.maybe_isnan ()
+	    || op2.known_isnan ()
+	    || op2.maybe_isnan ()))
+      ret = VREL_VARYING; // Should have been VREL_UNLE with NAN ops.
+    return ret;
+  }
   bool op1_range (frange &r, tree type,
 		  const irange &lhs, const frange &op2,
 		  relation_trio = TRIO_VARYING) const final override;
@@ -1799,6 +1854,7 @@ class foperator_unordered_gt : public ra
   using range_operator_float::fold_range;
   using range_operator_float::op1_range;
   using range_operator_float::op2_range;
+  using range_operator_float::op1_op2_relation;
 public:
   bool fold_range (irange &r, tree type,
 		   const frange &op1, const frange &op2,
@@ -1827,6 +1883,18 @@ public:
 	return true;
       }
   }
+  relation_kind op1_op2_relation (const irange &lhs, const frange &op1,
+				  const frange &op2) const final override
+  {
+    relation_kind ret = gt_op1_op2_relation (lhs);
+    if (ret == VREL_GT
+	&& (op1.known_isnan ()
+	    || op1.maybe_isnan ()
+	    || op2.known_isnan ()
+	    || op2.maybe_isnan ()))
+      ret = VREL_VARYING; // Should have been VREL_UNGT with NAN ops.
+    return ret;
+  }
   bool op1_range (frange &r, tree type,
 		  const irange &lhs, const frange &op2,
 		  relation_trio = TRIO_VARYING) const final override;
@@ -1910,6 +1978,7 @@ class foperator_unordered_ge : public ra
   using range_operator_float::fold_range;
   using range_operator_float::op1_range;
   using range_operator_float::op2_range;
+  using range_operator_float::op1_op2_relation;
 public:
   bool fold_range (irange &r, tree type,
 		   const frange &op1, const frange &op2,
@@ -1938,6 +2007,18 @@ public:
 	return true;
       }
   }
+  relation_kind op1_op2_relation (const irange &lhs, const frange &op1,
+				  const frange &op2) const final override
+  {
+    relation_kind ret = ge_op1_op2_relation (lhs);
+    if (ret == VREL_GE
+	&& (op1.known_isnan ()
+	    || op1.maybe_isnan ()
+	    || op2.known_isnan ()
+	    || op2.maybe_isnan ()))
+      ret = VREL_VARYING; // Should have been VREL_UNGE with NAN ops.
+    return ret;
+  }
   bool op1_range (frange &r, tree type,
 		  const irange &lhs, const frange &op2,
 		  relation_trio = TRIO_VARYING) const final override;


	Jakub


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

* Re: [RFC PATCH] range-op-float: Fix up op1_op2_relation of comparisons
  2023-04-12 14:21     ` Jakub Jelinek
@ 2023-04-12 16:35       ` Bernhard Reutner-Fischer
  2023-04-12 16:40         ` Jakub Jelinek
  0 siblings, 1 reply; 7+ messages in thread
From: Bernhard Reutner-Fischer @ 2023-04-12 16:35 UTC (permalink / raw)
  To: Jakub Jelinek, Jakub Jelinek via Gcc-patches, Andrew MacLeod,
	Aldy Hernandez, gcc-patches

On 12 April 2023 16:21:24 CEST, Jakub Jelinek via Gcc-patches <gcc-patches@gcc.gnu.org> wrote:

>--- gcc/range-op-float.cc.jj	2023-04-12 12:17:44.784962757 +0200
>+++ gcc/range-op-float.cc	2023-04-12 16:07:54.948759355 +0200
>@@ -835,10 +835,17 @@ public:
>   bool fold_range (irange &r, tree type,
> 		   const frange &op1, const frange &op2,
> 		   relation_trio = TRIO_VARYING) const final override;
>-  relation_kind op1_op2_relation (const irange &lhs, const frange &,
>-				  const frange &) const final override
>+  relation_kind op1_op2_relation (const irange &lhs, const frange &op1,
>+				  const frange &op2) const final override
>   {
>-    return lt_op1_op2_relation (lhs);
>+    relation_kind ret = lt_op1_op2_relation (lhs);
>+    if (ret == VREL_GE
>+	&& (op1.known_isnan ()
>+	    || op1.maybe_isnan ()
>+	    || op2.known_isnan ()
>+	    || op2.maybe_isnan ()))
>+      ret = VREL_VARYING; // Inverse of VREL_LT is VREL_UNGE with NAN ops.
>+    return ret;
>   }
>   bool op1_range (frange &r, tree type,
> 		  const irange &lhs, const frange &op2,
>@@ -952,9 +959,17 @@ public:
>   bool fold_range (irange &r, tree type,
> 		   const frange &op1, const frange &op2,
> 		   relation_trio rel = TRIO_VARYING) const final override;
>-  relation_kind op1_op2_relation (const irange &lhs, const frange &,
>-				  const frange &) const final override
>+  relation_kind op1_op2_relation (const irange &lhs, const frange &op1,
>+				  const frange &op2) const final override
>   {
>+    relation_kind ret = le_op1_op2_relation (lhs);
>+    if (ret == VREL_GT
>+	&& (op1.known_isnan ()
>+	    || op1.maybe_isnan ()
>+	    || op2.known_isnan ()
>+	    || op2.maybe_isnan ()))
>+      ret = VREL_VARYING; // Inverse of VREL_LE is VREL_UNGT with NAN ops.
>+    return ret;
>     return le_op1_op2_relation (lhs);

I think you forgot to delete the above return.

thanks,

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

* Re: [RFC PATCH] range-op-float: Fix up op1_op2_relation of comparisons
  2023-04-12 16:35       ` Bernhard Reutner-Fischer
@ 2023-04-12 16:40         ` Jakub Jelinek
  0 siblings, 0 replies; 7+ messages in thread
From: Jakub Jelinek @ 2023-04-12 16:40 UTC (permalink / raw)
  To: Bernhard Reutner-Fischer
  Cc: Jakub Jelinek via Gcc-patches, Andrew MacLeod, Aldy Hernandez

On Wed, Apr 12, 2023 at 06:35:29PM +0200, Bernhard Reutner-Fischer wrote:
> >+    relation_kind ret = le_op1_op2_relation (lhs);
> >+    if (ret == VREL_GT
> >+	&& (op1.known_isnan ()
> >+	    || op1.maybe_isnan ()
> >+	    || op2.known_isnan ()
> >+	    || op2.maybe_isnan ()))
> >+      ret = VREL_VARYING; // Inverse of VREL_LE is VREL_UNGT with NAN ops.
> >+    return ret;
> >     return le_op1_op2_relation (lhs);
> 
> I think you forgot to delete the above return.

Thanks, adjusted in my copy.

	Jakub


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

end of thread, other threads:[~2023-04-12 16:40 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2023-04-11  8:21 [RFC PATCH] range-op-float: Fix up op1_op2_relation of comparisons Jakub Jelinek
2023-04-11  8:59 ` Aldy Hernandez
2023-04-11 20:58 ` Andrew MacLeod
2023-04-12 10:33   ` Jakub Jelinek
2023-04-12 14:21     ` Jakub Jelinek
2023-04-12 16:35       ` Bernhard Reutner-Fischer
2023-04-12 16:40         ` Jakub Jelinek

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