Re: [RFC PATCH] range-op-float: Fix up op1_op2_relation of comparisons

2023-04-12 Thread Jakub Jelinek via Gcc-patches
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



Re: [RFC PATCH] range-op-float: Fix up op1_op2_relation of comparisons

2023-04-12 Thread Bernhard Reutner-Fischer via Gcc-patches
On 12 April 2023 16:21:24 CEST, Jakub Jelinek via Gcc-patches 
 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 , tree type,
>  const frange , const frange ,
>  relation_trio = TRIO_VARYING) const final override;
>-  relation_kind op1_op2_relation (const irange , const frange &,
>-const frange &) const final override
>+  relation_kind op1_op2_relation (const irange , const frange ,
>+const frange ) 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 , tree type,
> const irange , const frange ,
>@@ -952,9 +959,17 @@ public:
>   bool fold_range (irange , tree type,
>  const frange , const frange ,
>  relation_trio rel = TRIO_VARYING) const final override;
>-  relation_kind op1_op2_relation (const irange , const frange &,
>-const frange &) const final override
>+  relation_kind op1_op2_relation (const irange , const frange ,
>+const frange ) 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,


Re: [RFC PATCH] range-op-float: Fix up op1_op2_relation of comparisons

2023-04-12 Thread Jakub Jelinek via 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  

* 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.jj2023-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 , tree type,
   const frange , const frange ,
   relation_trio = TRIO_VARYING) const final override;
-  relation_kind op1_op2_relation (const irange , const frange &,
- const frange &) const final override
+  relation_kind op1_op2_relation (const irange , const frange ,
+ const frange ) 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 , tree type,
  

Re: [RFC PATCH] range-op-float: Fix up op1_op2_relation of comparisons

2023-04-12 Thread Jakub Jelinek via 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  

* 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.jj2023-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 , tree type,
   const frange , const frange ,
   relation_trio = TRIO_VARYING) const final override;
-  relation_kind op1_op2_relation (const irange , const frange &,
- const frange &) const final override
+  relation_kind op1_op2_relation (const irange , const frange ,
+ const frange ) 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 , tree type,
  const irange , const frange ,
@@ -952,9 +960,18 @@ public:
   bool fold_range (irange , tree type,
   const frange , const frange ,
   relation_trio rel = TRIO_VARYING) const final override;
-  relation_kind op1_op2_relation (const irange , const frange &,
- const frange &) const final override
+  relation_kind op1_op2_relation (const irange , const frange ,
+ const frange ) 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 , tree type,
@@ -1063,10 +1080,18 @@ public:
   bool fold_range (irange , tree type,
   const frange , const frange ,
   relation_trio = TRIO_VARYING) const final override;
-  relation_kind op1_op2_relation (const irange , const frange &,
- const frange &) const final override
+  relation_kind op1_op2_relation (const irange , const frange ,
+ const frange ) 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 , tree type,
  const irange , const frange ,
@@ -1184,10 +1209,18 @@ public:
   bool fold_range (irange , tree type,
   const frange , const frange ,
   relation_trio = TRIO_VARYING) const final override;
-  relation_kind op1_op2_relation (const irange , const frange &,
- const frange &) const final override
+  relation_kind op1_op2_relation (const irange , const frange ,
+ const frange ) 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 , tree type,
  const irange , const frange ,
@@ 

Re: [RFC PATCH] range-op-float: Fix up op1_op2_relation of comparisons

2023-04-11 Thread Andrew MacLeod via Gcc-patches


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

commit 3715234f2cba21f2b9ec6c609b6f058d1d8af500
Author: Andrew MacLeod 
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 _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 _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 

Re: [RFC PATCH] range-op-float: Fix up op1_op2_relation of comparisons

2023-04-11 Thread Aldy Hernandez via 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  

* 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.jj2023-04-01 09:32:02.635423345 +0200
+++ gcc/range-op-float.cc   2023-04-03 10:42:54.0 +0200
@@ -831,7 +831,10 @@ public:
   relation_trio = TRIO_VARYING) const final override;
relation_kind op1_op2_relation (const irange ) 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 , tree type,
  const irange , const frange ,
@@ -947,6 +950,10 @@ public:
   relation_trio rel = TRIO_VARYING) const final override;
relation_kind op1_op2_relation (const irange ) 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 , tree type,
@@ -1057,7 +1064,10 @@ public:
   relation_trio = TRIO_VARYING) const final override;
relation_kind op1_op2_relation (const irange ) 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 , tree type,
  const irange , const frange ,
@@ -1177,7 +1187,10 @@ public:
   relation_trio = TRIO_VARYING) const final override;
relation_kind op1_op2_relation (const irange ) 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 , tree type,
  const irange , const frange ,
@@ -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 , tree type,
   const frange , const frange ,
@@ -1599,6 +1613,13 @@ public:
return true;
}
}
+  relation_kind op1_op2_relation (const irange ) 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 , tree type,
  const irange ,
  const frange ,
@@ -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 , tree type,
   const frange , const frange ,
@@ -1710,6 +1732,13 @@ public:
return true;

[RFC PATCH] range-op-float: Fix up op1_op2_relation of comparisons

2023-04-11 Thread Jakub Jelinek via 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  

* 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.jj2023-04-01 09:32:02.635423345 +0200
+++ gcc/range-op-float.cc   2023-04-03 10:42:54.0 +0200
@@ -831,7 +831,10 @@ public:
   relation_trio = TRIO_VARYING) const final override;
   relation_kind op1_op2_relation (const irange ) 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 , tree type,
  const irange , const frange ,
@@ -947,6 +950,10 @@ public:
   relation_trio rel = TRIO_VARYING) const final override;
   relation_kind op1_op2_relation (const irange ) 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 , tree type,
@@ -1057,7 +1064,10 @@ public:
   relation_trio = TRIO_VARYING) const final override;
   relation_kind op1_op2_relation (const irange ) 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 , tree type,
  const irange , const frange ,
@@ -1177,7 +1187,10 @@ public:
   relation_trio = TRIO_VARYING) const final override;
   relation_kind op1_op2_relation (const irange ) 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 , tree type,
  const irange , const frange ,
@@ -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 , tree type,
   const frange , const frange ,
@@ -1599,6 +1613,13 @@ public:
return true;
   }
   }
+  relation_kind op1_op2_relation (const irange ) 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 , tree type,
  const irange ,
  const frange ,
@@ -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 , tree type,
   const frange , const frange ,
@@ -1710,6 +1732,13 @@ public:
return true;
   }
   }
+  relation_kind op1_op2_relation (const irange ) const final override
+  {
+relation_kind ret = le_op1_op2_relation (lhs);
+if (ret == VREL_LE)
+