Bug 108647 - [13 Regression] ICE in upper_bound, at value-range.h:950 with -O3 since r13-2974-g67166c9ec35d58ef
Summary: [13 Regression] ICE in upper_bound, at value-range.h:950 with -O3 since r13-2...
Status: RESOLVED FIXED
Alias: None
Product: gcc
Classification: Unclassified
Component: tree-optimization (show other bugs)
Version: 13.0
: P1 normal
Target Milestone: 13.0
Assignee: Jakub Jelinek
URL:
Keywords: ice-on-valid-code
Depends on:
Blocks: yarpgen
  Show dependency treegraph
 
Reported: 2023-02-02 21:21 UTC by Vsevolod Livinskii
Modified: 2023-02-04 07:26 UTC (History)
8 users (show)

See Also:
Host:
Target:
Build:
Known to work:
Known to fail:
Last reconfirmed: 2023-02-03 00:00:00


Attachments
frange changes (1.16 KB, patch)
2023-02-03 16:31 UTC, Aldy Hernandez
Details | Diff
gcc13-pr108647.patch (1.19 KB, patch)
2023-02-03 16:33 UTC, Jakub Jelinek
Details | Diff

Note You need to log in before you can comment on or make changes to this bug.
Description Vsevolod Livinskii 2023-02-02 21:21:09 UTC
Link to the Compiler Explorer: https://godbolt.org/z/PMGTPGPab

Reproducer:
bool a;
int b, c;
inline const bool &d(bool &e, const bool &f) { return f < e ? f : e; }
void g(char e, bool f[], bool h[], bool p4[]) {
  for (;;)
    if (p4)
      for (char j = 0; j < 6; j += (f[0] & c ? p4[0] : int(0 >= e))
                                       ? 0
                                       : d(p4[0], p4[0] > h[0]) + 1) {
        a = 0;
        b = 0;
      }
}

Error:
>$ g++ -O3 -c func.cpp
during GIMPLE pass: thread
func.cpp: In function 'void g(char, bool*, bool*, bool*)':
func.cpp:4:6: internal compiler error: in upper_bound, at value-range.h:950
    4 | void g(char e, bool f[], bool h[], bool p4[]) {
      |      ^
0x995922 irange::upper_bound() const
	/testing/gcc/gcc_src_master/gcc/value-range.h:950
0x9961f0 irange::upper_bound() const
	/testing/gcc/gcc_src_master/gcc/tree.h:3653
0x9961f0 operator_lt::op2_range(irange&, tree_node*, irange const&, irange const&, relation_trio) const
	/testing/gcc/gcc_src_master/gcc/range-op.cc:952
0x20cc69f gori_compute::refine_using_relation(tree_node*, vrange&, tree_node*, vrange&, fur_source&, relation_kind_t)
	/testing/gcc/gcc_src_master/gcc/gimple-range-gori.cc:1034
0x20ce404 gori_compute::compute_operand1_range(vrange&, gimple_range_op_handler&, vrange const&, tree_node*, fur_source&, value_relation*)
	/testing/gcc/gcc_src_master/gcc/gimple-range-gori.cc:1092
0x20cd0e5 gori_compute::compute_operand_range(vrange&, gimple*, vrange const&, tree_node*, fur_source&, value_relation*)
	/testing/gcc/gcc_src_master/gcc/gimple-range-gori.cc:700
0x20d0ad8 gori_compute::outgoing_edge_range_p(vrange&, edge_def*, tree_node*, range_query&)
	/testing/gcc/gcc_src_master/gcc/gimple-range-gori.cc:1358
0x141362d path_range_query::compute_ranges_in_block(basic_block_def*)
	/testing/gcc/gcc_src_master/gcc/gimple-range-path.cc:454
0x1413d3a path_range_query::compute_ranges(bitmap_head const*)
	/testing/gcc/gcc_src_master/gcc/gimple-range-path.cc:622
0x149cd3a back_threader::find_taken_edge_cond(vec<basic_block_def*, va_heap, vl_ptr> const&, gcond*)
	/testing/gcc/gcc_src_master/gcc/tree-ssa-threadbackward.cc:324
0x149cf33 back_threader::maybe_register_path(back_threader_profitability&)
	/testing/gcc/gcc_src_master/gcc/tree-ssa-threadbackward.cc:248
0x149d2d0 back_threader::find_paths_to_names(basic_block_def*, bitmap_head*, unsigned int, back_threader_profitability&)
	/testing/gcc/gcc_src_master/gcc/tree-ssa-threadbackward.cc:371
0x149d789 back_threader::find_paths_to_names(basic_block_def*, bitmap_head*, unsigned int, back_threader_profitability&)
	/testing/gcc/gcc_src_master/gcc/tree-ssa-threadbackward.cc:479
0x149d789 back_threader::find_paths_to_names(basic_block_def*, bitmap_head*, unsigned int, back_threader_profitability&)
	/testing/gcc/gcc_src_master/gcc/tree-ssa-threadbackward.cc:479
0x149d789 back_threader::find_paths_to_names(basic_block_def*, bitmap_head*, unsigned int, back_threader_profitability&)
	/testing/gcc/gcc_src_master/gcc/tree-ssa-threadbackward.cc:479
0x149d789 back_threader::find_paths_to_names(basic_block_def*, bitmap_head*, unsigned int, back_threader_profitability&)
	/testing/gcc/gcc_src_master/gcc/tree-ssa-threadbackward.cc:479
0x149e258 back_threader::maybe_thread_block(basic_block_def*)
	/testing/gcc/gcc_src_master/gcc/tree-ssa-threadbackward.cc:551
0x149e321 back_threader::thread_blocks()
	/testing/gcc/gcc_src_master/gcc/tree-ssa-threadbackward.cc:975
0x149e398 execute
	/testing/gcc/gcc_src_master/gcc/tree-ssa-threadbackward.cc:1077

gcc version 13.0.1 20230201 (a2c848c92c3f13c2dd9bd92d22beb44c1ff848b4)
Comment 1 Richard Biener 2023-02-03 08:04:16 UTC
Confirmed.  We have VR_UNDEFINED as other_op in

#4  0x00000000030c3df4 in gori_compute::refine_using_relation (this=0x490b310, 
    op1=<ssa_name 0x7ffff643c360 42>, op1_range=..., 
    op2=<ssa_name 0x7ffff643c678 53>, op2_range=..., src=..., k=VREL_LT)
    at /home/rguenther/src/trunk/gcc/gimple-range-gori.cc:1034
1034          if (!op_handler.op2_range (new_result, type,
(gdb) l
1029          src.get_operand (other_op, def_op1);
1030
1031          // Using op1_range as the LHS, and relation REL, evaluate op2.
1032          tree type = TREE_TYPE (def_op2);
1033          Value_Range new_result (type);
1034          if (!op_handler.op2_range (new_result, type,
1035                                     op1_def_p ? op1_range : op2_range,
1036                                     other_op, relation_trio::lhs_op2 (k)))

must be a quite recent regression.
Comment 2 Martin Liška 2023-02-03 09:21:19 UTC
Started with r13-2974-g67166c9ec35d58ef.
Comment 3 Jakub Jelinek 2023-02-03 09:29:40 UTC
The ICE is when operator_lt::op2_range does:
976	    case BRS_FALSE:
977	      build_le (r, type, op1.upper_bound ());
978	      break;

lhs is
[irange] bool [0, 0] NONZERO 0x0
and rhs is
[irange] UNDEFINED
which is why op1.upper_bound () ICEs - it has no pairs.
I wonder if operator_lt::op?_range and other operators shouldn't start with
relop_early_resolve or at least empty_range_varying or something similar to deal with
op?.undefined_p ().
Comment 4 Jakub Jelinek 2023-02-03 09:54:20 UTC
Perhaps just adding if (op2.undefined_p ()) return false; above most of the
switch (get_bool_state (r, lhs, type)) lines (in methods that refer to op2; and similarly for op1) for the comparison operators.
Comment 5 Aldy Hernandez 2023-02-03 12:46:32 UTC
> Perhaps just adding if (op2.undefined_p ()) return false; above most of the
> switch (get_bool_state (r, lhs, type)) lines (in methods that refer to op2;
> and similarly for op1) for the comparison operators.

This feels like the right approach.  We also do something similar in some of the binary operators.  For example, plus/minus_expr do:

  if (lhs.undefined_p ())
    return false;

For this testcase we have:

[0,0] = UNDEFINED < op2

I don't think we can determine anything for op2 in this situation, so the right thing would be to return false, which amounts to returning VARYING.

The binary operators would also have to handle operators of undefined, but those seem to all have gates on singleton_p() or go through the fold_range() routine for the inverse operation, so they'd be handled correctly.

So yeah, it looks like just handling the op[12]_range operators above the get_bool_state would do the trick.

Hmmm, it seems like there are 2 operators that have possible problematic handling of op2.undefined_p():

1. operator_cast::op1_range (irange &r, tree type,

   The assert looks at the op2 type.  That will ICE with an UNDEFINED.

   The truncating_cast_p path will also look at op2's type blindly.

2. operator_bitwise_xor::op1_range

  Imagine: [0,0] = x ^ UNDEFINED

  op1_range won't ICE, but it will do:

	case BRS_FALSE:
	  r = op2;

  I don't think we know anything about x in this case.  Though if, op2 is UNDEFINED, I guess it
  wouldn't hurt to assume op1 is also UNDEFINED.

   Also earlier in the function, for:

     UNDEFINED = x ^ op2

   will return x = UNDEFINED for any op2.  

So at least #1 would also have to be handled because it could ICE.

Also, range-op-float.cc needs the same treatment prior all the get_bool_state calls.

As you mention, another alternative would be to always call empty_range_varying, as we're doing for abs::op[12]_range:

  if (empty_range_varying (r, type, lhs, op2))
    return true;

Thoughts?  Andrew?

Hmmm, I wonder why we haven't tripped over this scenario in past releases (LHS being defined, but op2 being UNDEFINED).
Comment 6 Andrew Macleod 2023-02-03 14:54:51 UTC
This is the first release that we process relations in GORI.  Up until recently it was fairly ad-hoc what got passed in as a relation trio to the op?_range routines.  A couple of days ago I fleshed it out fully.  I am surprised that isn't what caused this.

Anyway, the reason its tripping:

  if (_42 != 0)
    goto <bb 10>; [50.00%]
  else
    goto <bb 6>; [50.00%]

bb6:
  _27 = *h_29(D);
  _53 = _27 < _42;
  if (_42 > _53)

we start by trying to evaluate the outgoing edge for _42 on the true side:
[1,1] = (_42 > _53)
The problem is we have determined that _42 is bool [0, 0] at this point.
Knowing _42 is [0, 0], the definition of _53 can never be true, so it is also bool [0,0]

in order for _53 to be [0,0] AND _42 to be [0,0], the bool value for _27 is nonsensical..    and thus its being calculated as undefined.

This branch is eventually going to be removed since it can never be taken, but that hasnt happened at this point yet.

we could fix it at the call site, but you do point out that the opX_range routines are not gracefully dealing with undefined values.

We probably should audit them all to make sure we handled undefined gracefully before accessing a bound.
Comment 7 Jakub Jelinek 2023-02-03 15:11:20 UTC
So
--- gcc/range-op.cc.jj	2023-02-03 10:51:40.699003658 +0100
+++ gcc/range-op.cc	2023-02-03 16:04:39.264159294 +0100
@@ -642,7 +642,8 @@ operator_equal::op1_range (irange &r, tr
     case BRS_FALSE:
       // If the result is false, the only time we know anything is
       // if OP2 is a constant.
-      if (wi::eq_p (op2.lower_bound(), op2.upper_bound()))
+      if (!op2.undefined_p ()
+	  && wi::eq_p (op2.lower_bound(), op2.upper_bound()))
 	{
 	  r = op2;
 	  r.invert ();
@@ -755,7 +756,8 @@ operator_not_equal::op1_range (irange &r
     case BRS_TRUE:
       // If the result is true, the only time we know anything is if
       // OP2 is a constant.
-      if (wi::eq_p (op2.lower_bound(), op2.upper_bound()))
+      if (!op2.undefined_p ()
+	  && wi::eq_p (op2.lower_bound(), op2.upper_bound()))
 	{
 	  r = op2;
 	  r.invert ();
@@ -920,6 +922,9 @@ operator_lt::op1_range (irange &r, tree
 			const irange &op2,
 			relation_trio) const
 {
+  if (op2.undefined_p ())
+    return false;
+
   switch (get_bool_state (r, lhs, type))
     {
     case BRS_TRUE:
@@ -942,6 +947,9 @@ operator_lt::op2_range (irange &r, tree
 			const irange &op1,
 			relation_trio) const
 {
+  if (op1.undefined_p ())
+    return false;
+
   switch (get_bool_state (r, lhs, type))
     {
     case BRS_TRUE:
@@ -1031,6 +1039,9 @@ operator_le::op1_range (irange &r, tree
 			const irange &op2,
 			relation_trio) const
 {
+  if (op2.undefined_p ())
+    return false;
+
   switch (get_bool_state (r, lhs, type))
     {
     case BRS_TRUE:
@@ -1053,6 +1064,9 @@ operator_le::op2_range (irange &r, tree
 			const irange &op1,
 			relation_trio) const
 {
+  if (op1.undefined_p ())
+    return false;
+
   switch (get_bool_state (r, lhs, type))
     {
     case BRS_TRUE:
@@ -1141,6 +1155,9 @@ operator_gt::op1_range (irange &r, tree
 			const irange &lhs, const irange &op2,
 			relation_trio) const
 {
+  if (op2.undefined_p ())
+    return false;
+
   switch (get_bool_state (r, lhs, type))
     {
     case BRS_TRUE:
@@ -1163,6 +1180,9 @@ operator_gt::op2_range (irange &r, tree
 			const irange &op1,
 			relation_trio) const
 {
+  if (op1.undefined_p ())
+    return false;
+
   switch (get_bool_state (r, lhs, type))
     {
     case BRS_TRUE:
@@ -1252,6 +1272,9 @@ operator_ge::op1_range (irange &r, tree
 			const irange &op2,
 			relation_trio) const
 {
+  if (op2.undefined_p ())
+    return false;
+
   switch (get_bool_state (r, lhs, type))
     {
     case BRS_TRUE:
@@ -1274,6 +1297,9 @@ operator_ge::op2_range (irange &r, tree
 			const irange &op1,
 			relation_trio) const
 {
+  if (op1.undefined_p ())
+    return false;
+
   switch (get_bool_state (r, lhs, type))
     {
     case BRS_TRUE:
then plus testcase?
Comment 8 Jakub Jelinek 2023-02-03 15:15:00 UTC
Unfortunately that would mean for the non-equality cases that if lhs.undefined_p () we don't return undefined but false (aka VARYING).
Another option is to add those if (op?.undefined_p ()) return false; to both case BRS_TRUE: and case BRS_FALSE:.
Comment 9 Andrew Macleod 2023-02-03 15:20:50 UTC
(In reply to Jakub Jelinek from comment #8)
> Unfortunately that would mean for the non-equality cases that if
> lhs.undefined_p () we don't return undefined but false (aka VARYING).
> Another option is to add those if (op?.undefined_p ()) return false; to both
> case BRS_TRUE: and case BRS_FALSE:.

Well, if the LHS is undefined, (or even one of the operands) we are typically in dead code or edge anyway.. I'm not sure it really matters?

An alternate question as well is why is the threader even looking at this impossible path. It should know that the branch can never be true
Comment 10 Jakub Jelinek 2023-02-03 15:23:14 UTC
(In reply to Andrew Macleod from comment #9)
> (In reply to Jakub Jelinek from comment #8)
> > Unfortunately that would mean for the non-equality cases that if
> > lhs.undefined_p () we don't return undefined but false (aka VARYING).
> > Another option is to add those if (op?.undefined_p ()) return false; to both
> > case BRS_TRUE: and case BRS_FALSE:.
> 
> Well, if the LHS is undefined, (or even one of the operands) we are
> typically in dead code or edge anyway.. I'm not sure it really matters?

Ok, I'll test the patch then.

> An alternate question as well is why is the threader even looking at this
> impossible path. It should know that the branch can never be true

I think range-op shouldn't assume nothing will call it with UNDEFINED ranges.
Comment 11 Andrew Macleod 2023-02-03 15:28:18 UTC
(In reply to Jakub Jelinek from comment #10)
> (In reply to Andrew Macleod from comment #9)
> > (In reply to Jakub Jelinek from comment #8)
> > > Unfortunately that would mean for the non-equality cases that if
> > > lhs.undefined_p () we don't return undefined but false (aka VARYING).
> > > Another option is to add those if (op?.undefined_p ()) return false; to both
> > > case BRS_TRUE: and case BRS_FALSE:.
> > 
> > Well, if the LHS is undefined, (or even one of the operands) we are
> > typically in dead code or edge anyway.. I'm not sure it really matters?
> 
> Ok, I'll test the patch then.
> 
> > An alternate question as well is why is the threader even looking at this
> > impossible path. It should know that the branch can never be true
> 
> I think range-op shouldn't assume nothing will call it with UNDEFINED ranges.

Oh I wasn't suggesting otherwise,we should be bulletproof.  Just wondering why the threader is spending any time evaluating ranges on a path it should know is impossible.
Comment 12 Aldy Hernandez 2023-02-03 16:16:15 UTC
(In reply to Jakub Jelinek from comment #7)
> So
> --- gcc/range-op.cc.jj	2023-02-03 10:51:40.699003658 +0100
> +++ gcc/range-op.cc	2023-02-03 16:04:39.264159294 +0100
> @@ -642,7 +642,8 @@ operator_equal::op1_range (irange &r, tr
>      case BRS_FALSE:
>        // If the result is false, the only time we know anything is
>        // if OP2 is a constant.
> -      if (wi::eq_p (op2.lower_bound(), op2.upper_bound()))
> +      if (!op2.undefined_p ()
> +	  && wi::eq_p (op2.lower_bound(), op2.upper_bound()))
>  	{
>  	  r = op2;
>  	  r.invert ();
> @@ -755,7 +756,8 @@ operator_not_equal::op1_range (irange &r
>      case BRS_TRUE:
>        // If the result is true, the only time we know anything is if
>        // OP2 is a constant.
> -      if (wi::eq_p (op2.lower_bound(), op2.upper_bound()))
> +      if (!op2.undefined_p ()
> +	  && wi::eq_p (op2.lower_bound(), op2.upper_bound()))
>  	{
>  	  r = op2;
>  	  r.invert ();
> @@ -920,6 +922,9 @@ operator_lt::op1_range (irange &r, tree
>  			const irange &op2,
>  			relation_trio) const
>  {
> +  if (op2.undefined_p ())
> +    return false;
> +
>    switch (get_bool_state (r, lhs, type))
>      {
>      case BRS_TRUE:
> @@ -942,6 +947,9 @@ operator_lt::op2_range (irange &r, tree
>  			const irange &op1,
>  			relation_trio) const
>  {
> +  if (op1.undefined_p ())
> +    return false;
> +
>    switch (get_bool_state (r, lhs, type))
>      {
>      case BRS_TRUE:
> @@ -1031,6 +1039,9 @@ operator_le::op1_range (irange &r, tree
>  			const irange &op2,
>  			relation_trio) const
>  {
> +  if (op2.undefined_p ())
> +    return false;
> +
>    switch (get_bool_state (r, lhs, type))
>      {
>      case BRS_TRUE:
> @@ -1053,6 +1064,9 @@ operator_le::op2_range (irange &r, tree
>  			const irange &op1,
>  			relation_trio) const
>  {
> +  if (op1.undefined_p ())
> +    return false;
> +
>    switch (get_bool_state (r, lhs, type))
>      {
>      case BRS_TRUE:
> @@ -1141,6 +1155,9 @@ operator_gt::op1_range (irange &r, tree
>  			const irange &lhs, const irange &op2,
>  			relation_trio) const
>  {
> +  if (op2.undefined_p ())
> +    return false;
> +
>    switch (get_bool_state (r, lhs, type))
>      {
>      case BRS_TRUE:
> @@ -1163,6 +1180,9 @@ operator_gt::op2_range (irange &r, tree
>  			const irange &op1,
>  			relation_trio) const
>  {
> +  if (op1.undefined_p ())
> +    return false;
> +
>    switch (get_bool_state (r, lhs, type))
>      {
>      case BRS_TRUE:
> @@ -1252,6 +1272,9 @@ operator_ge::op1_range (irange &r, tree
>  			const irange &op2,
>  			relation_trio) const
>  {
> +  if (op2.undefined_p ())
> +    return false;
> +
>    switch (get_bool_state (r, lhs, type))
>      {
>      case BRS_TRUE:
> @@ -1274,6 +1297,9 @@ operator_ge::op2_range (irange &r, tree
>  			const irange &op1,
>  			relation_trio) const
>  {
> +  if (op1.undefined_p ())
> +    return false;
> +
>    switch (get_bool_state (r, lhs, type))
>      {
>      case BRS_TRUE:
> then plus testcase?

Looks good to me.

Do you mind adding this bit to your testing?

diff --git a/gcc/range-op.cc b/gcc/range-op.cc
index 136b709385c..fdc0a6c05fd 100644
--- a/gcc/range-op.cc
+++ b/gcc/range-op.cc
@@ -2678,7 +2678,6 @@ operator_cast::op1_range (irange &r, tree type,
   if (lhs.undefined_p ())
     return false;
   tree lhs_type = lhs.type ();
-  gcc_checking_assert (types_compatible_p (op2.type(), type));
 
   // If we are calculating a pointer, shortcut to what we really care about.
   if (POINTER_TYPE_P (type))
@@ -2705,6 +2704,8 @@ operator_cast::op1_range (irange &r, tree type,
       return true;
     }
 
+  if (op2.undefined_p ())
+    return false;
   if (truncating_cast_p (op2, lhs))
     {
       if (lhs.varying_p ())

This catches the cast operator which will ICE in truncating_cast_p when op2 is undefined.

I've removed the checking assert since any number of operations further down will ICE if the types don't match.
Comment 13 Aldy Hernandez 2023-02-03 16:31:36 UTC
Created attachment 54404 [details]
frange changes

These are the analogous changes to range-op-float.cc.

Patch in testing.
Comment 14 Jakub Jelinek 2023-02-03 16:33:13 UTC
Created attachment 54405 [details]
gcc13-pr108647.patch

Here is what I'm about to test momentarily, though I must say I don't understand those operator_cast changes at all.  I thought casts are unary operators and so I don't understand what kind of range would be op2 in that case.
Comment 15 Aldy Hernandez 2023-02-03 16:35:23 UTC
(In reply to Jakub Jelinek from comment #14)
> Created attachment 54405 [details]
> gcc13-pr108647.patch
> 
> Here is what I'm about to test momentarily, though I must say I don't
> understand those operator_cast changes at all.  I thought casts are unary
> operators and so I don't understand what kind of range would be op2 in that
> case.

Oh poop, sorry.  Unary operators always have the resulting type passed as VARYING in op2.  It would never be undefined.  Sorry for the noise; you can disregard the cast changes.
Comment 16 GCC Commits 2023-02-03 20:31:06 UTC
The master branch has been updated by Aldy Hernandez <aldyh@gcc.gnu.org>:

https://gcc.gnu.org/g:10bd26d6efe88a8cf03a6a325351bc470a910cab

commit r13-5695-g10bd26d6efe88a8cf03a6a325351bc470a910cab
Author: Aldy Hernandez <aldyh@redhat.com>
Date:   Fri Feb 3 17:28:52 2023 +0100

    range-ops: Handle undefined ranges in frange op[12]_range [PR108647]
    
    This patch gracefully handles undefined operand ranges for the floating
    point op[12]_range operators.  This is very low risk, as we would have
    ICEd otherwise.
    
    We don't have a testcase that ICEs for floating point ranges, but it's
    only a matter of time.  Besides, this dovetails nicely with the integer
    versions Jakub is testing.
    
    gcc/ChangeLog:
    
            PR tree-optimization/108647
            * range-op-float.cc (foperator_lt::op1_range): Handle undefined ranges.
            (foperator_lt::op2_range): Same.
            (foperator_le::op1_range): Same.
            (foperator_le::op2_range): Same.
            (foperator_gt::op1_range): Same.
            (foperator_gt::op2_range): Same.
            (foperator_ge::op1_range): Same.
            (foperator_ge::op2_range): Same.
            (foperator_unordered_lt::op1_range): Same.
            (foperator_unordered_lt::op2_range): Same.
            (foperator_unordered_le::op1_range): Same.
            (foperator_unordered_le::op2_range): Same.
            (foperator_unordered_gt::op1_range): Same.
            (foperator_unordered_gt::op2_range): Same.
            (foperator_unordered_ge::op1_range): Same.
            (foperator_unordered_ge::op2_range): Same.
Comment 17 GCC Commits 2023-02-03 20:39:57 UTC
The master branch has been updated by Jakub Jelinek <jakub@gcc.gnu.org>:

https://gcc.gnu.org/g:e753080ab8abd4021381699bc7e857f5b4a083c4

commit r13-5698-ge753080ab8abd4021381699bc7e857f5b4a083c4
Author: Jakub Jelinek <jakub@redhat.com>
Date:   Fri Feb 3 21:39:16 2023 +0100

    range-op: Handle op?.undefined_p () in op[12]_range of comparisons [PR108647]
    
    As mentioned in the PR, we ICE because lhs is singleton [0, 0]
    or [1, 1] but op2 (or in other cases op1) is undefined and op?.*_bound ()
    ICEs on those because there are no pairs for UNDEFINED.
    
    The following patch makes us set r to varying or return false in those
    cases.
    
    2023-02-03  Jakub Jelinek  <jakub@redhat.com>
    
            PR tree-optimization/108647
            * range-op.cc (operator_equal::op1_range,
            operator_not_equal::op1_range): Don't test op2 bound
            equality if op2.undefined_p (), instead set_varying.
            (operator_lt::op1_range, operator_le::op1_range,
            operator_gt::op1_range, operator_ge::op1_range): Return false if
            op2.undefined_p ().
            (operator_lt::op2_range, operator_le::op2_range,
            operator_gt::op2_range, operator_ge::op2_range): Return false if
            op1.undefined_p ().
    
            * g++.dg/torture/pr108647.C: New test.
Comment 18 Jakub Jelinek 2023-02-03 20:43:11 UTC
Should be fixed now.
Comment 19 Khem Raj 2023-02-04 01:35:58 UTC
This is now resulting in build error in harfbuzz on aarch64 which did not happen before, the testcase is here

https://uclibc.org/~kraj/hb-aat-layout.cc.i

Compile cmd used is

/mnt/b/cross/aarch64-linux-musl/tools/bin/aarch64-linux-musl-g++ --sysroot=/mnt/b/yoe/master/build/tmp/work/cortexa72-yoe-linux/harfbuzz/6.0.0-r0/recipe-sysroot -fstack-protector-strong -O2 -D_FORTIFY_SOURCE=2 -Wformat -Wformat-security -Werror=format-security -Isrc/libharfbuzz.so.0.60600.0.p -Isrc -I../harfbuzz-6.0.0/src -I. -I../harfbuzz-6.0.0 -fdiagnostics-color=always -D_FILE_OFFSET_BITS=64 -Wall -Winvalid-pch -std=c++11 -fno-rtti -fno-exceptions -fno-rtti -fno-threadsafe-statics -fvisibility-inlines-hidden -DHAVE_CONFIG_H -O2 -pipe -g -feliminate-unused-debug-types -fmacro-prefix-map=/mnt/b/yoe/master/build/tmp/work/cortexa72-yoe-linux/harfbuzz/6.0.0-r0/harfbuzz-6.0.0=/usr/src/debug/harfbuzz/6.0.0-r0 -fdebug-prefix-map=/mnt/b/yoe/master/build/tmp/work/cortexa72-yoe-linux/harfbuzz/6.0.0-r0/harfbuzz-6.0.0=/usr/src/debug/harfbuzz/6.0.0-r0 -fmacro-prefix-map=/mnt/b/yoe/master/build/tmp/work/cortexa72-yoe-linux/harfbuzz/6.0.0-r0/build=/usr/src/debug/harfbuzz/6.0.0-r0 -fdebug-prefix-map=/mnt/b/yoe/master/build/tmp/work/cortexa72-yoe-linux/harfbuzz/6.0.0-r0/build=/usr/src/debug/harfbuzz/6.0.0-r0 -fdebug-prefix-map=/mnt/b/yoe/master/build/tmp/work/cortexa72-yoe-linux/harfbuzz/6.0.0-r0/recipe-sysroot= -fmacro-prefix-map=/mnt/b/yoe/master/build/tmp/work/cortexa72-yoe-linux/harfbuzz/6.0.0-r0/recipe-sysroot= -fdebug-prefix-map=/mnt/b/yoe/master/build/tmp/work/cortexa72-yoe-linux/harfbuzz/6.0.0-r0/recipe-sysroot-native= -fvisibility-inlines-hidden -fPIC -pthread -Wno-non-virtual-dtor -MD -MQ src/libharfbuzz.so.0.60600.0.p/hb-aat-layout.cc.o -MF src/libharfbuzz.so.0.60600.0.p/hb-aat-layout.cc.o.d -o src/libharfbuzz.so.0.60600.0.p/hb-aat-layout.cc.o -c ../harfbuzz-6.0.0/src/hb-aat-layout.cc
Comment 20 Jakub Jelinek 2023-02-04 04:28:50 UTC
How could these changes result in
../harfbuzz-6.0.0/src/hb-map.hh:295:5: error: no match for ‘operator|’ (operand types are ‘hb_filter_iter_t<hb_array_t<hb_hashmap_t<unsigned int, unsigned int, true>::item_t>, bool (hb_hashmap_t<unsigned int, unsigned int, true>::item_t::*)() const, const<unnamed struct>&, 0>’ and ‘hb_reduce_t<hb_hashmap_t<unsigned int, unsigned int, true>::hash() const::<lambda(uint32_t, const hb_hashmap_t<unsigned int, unsigned int, true>::item_t&)>, unsigned int>’)
errors?  I can see that with a cross-compiler, so VRP miscompiling the C++ FE is not an option.
Comment 21 Jakub Jelinek 2023-02-04 05:25:24 UTC
Seems it is r13-5684-g59e0376f607805ef9b67fd7b0a4a3084ab3571a5 aka PR107461 change.  So, please file a separate bugreport, it has nothing to do with this PR.
Comment 22 Khem Raj 2023-02-04 07:26:47 UTC
(In reply to Jakub Jelinek from comment #20)
> How could these changes result in
> ../harfbuzz-6.0.0/src/hb-map.hh:295:5: error: no match for ‘operator|’
> (operand types are ‘hb_filter_iter_t<hb_array_t<hb_hashmap_t<unsigned int,
> unsigned int, true>::item_t>, bool (hb_hashmap_t<unsigned int, unsigned int,
> true>::item_t::*)() const, const<unnamed struct>&, 0>’ and
> ‘hb_reduce_t<hb_hashmap_t<unsigned int, unsigned int, true>::hash()
> const::<lambda(uint32_t, const hb_hashmap_t<unsigned int, unsigned int,
> true>::item_t&)>, unsigned int>’)
> errors?  I can see that with a cross-compiler, so VRP miscompiling the C++
> FE is not an option.

argh my bad, filled in wrong tab. Sorry about this.