Re: [PATCH] Fix some EVRP stupidness

2018-10-23 Thread Aldy Hernandez
Thanks!

On Tue, Oct 23, 2018, 13:37 Richard Biener  wrote:

> On Tue, 23 Oct 2018, Richard Biener wrote:
>
> > On Tue, 23 Oct 2018, Aldy Hernandez wrote:
> >
> > >
> > > > +   if (tem.kind () == old_vr->kind ()
> > > > +   && tem.min () == old_vr->min ()
> > > > +   && tem.max () == old_vr->max ())
> > > > + continue;
> > >
> > > I think it would be cleaner to use tem.ignore_equivs_equal_p
> (*old_vr). The
> > > goal was to use == when the equivalence bitmap should be taken into
> account,
> > > or ignore_equivs_equal_p() otherwise.
> >
> > Ah, didn't know of that function (and yes, I wanted to ignore equivs).
> >
> > Will try to remember together with the dump thing David noticed.
>
> Like the following.
>
> Bootstrapped / tested on x86_64-unknown-linux-gnu, applied.
>
> Richard.
>
> 2018-10-23  Richard Biener  
>
> * tree-vrp.c (add_assert_info): Guard dump_printf with
> dump_enabled_p.
> * gimple-ssa-evrp-analyze.c
> (evrp_range_analyzer::record_ranges_from_incoming_edge):
> Use value_range::ignore_equivs_equal_p.
>
> Index: gcc/tree-vrp.c
> ===
> --- gcc/tree-vrp.c  (revision 265420)
> +++ gcc/tree-vrp.c  (working copy)
> @@ -2299,9 +2299,10 @@ add_assert_info (vec 
>info.val = val;
>info.expr = expr;
>asserts.safe_push (info);
> -  dump_printf (MSG_NOTE | MSG_PRIORITY_INTERNALS,
> -  "Adding assert for %T from %T %s %T\n",
> -  name, expr, op_symbol_code (comp_code), val);
> +  if (dump_enabled_p ())
> +dump_printf (MSG_NOTE | MSG_PRIORITY_INTERNALS,
> +"Adding assert for %T from %T %s %T\n",
> +name, expr, op_symbol_code (comp_code), val);
>  }
>
>  /* If NAME doesn't have an ASSERT_EXPR registered for asserting
> Index: gcc/gimple-ssa-evrp-analyze.c
> ===
> --- gcc/gimple-ssa-evrp-analyze.c   (revision 265420)
> +++ gcc/gimple-ssa-evrp-analyze.c   (working copy)
> @@ -209,9 +209,7 @@ evrp_range_analyzer::record_ranges_from_
>   value_range *old_vr = get_value_range (vrs[i].first);
>   value_range tem (old_vr->kind (), old_vr->min (),
> old_vr->max ());
>   tem.intersect (vrs[i].second);
> - if (tem.kind () == old_vr->kind ()
> - && tem.min () == old_vr->min ()
> - && tem.max () == old_vr->max ())
> + if (tem.ignore_equivs_equal_p (*old_vr))
> continue;
>   push_value_range (vrs[i].first, vrs[i].second);
>   if (is_fallthru
>


Re: [PATCH] Fix some EVRP stupidness

2018-10-23 Thread Richard Biener
On Tue, 23 Oct 2018, Richard Biener wrote:

> On Tue, 23 Oct 2018, Aldy Hernandez wrote:
> 
> > 
> > > +   if (tem.kind () == old_vr->kind ()
> > > +   && tem.min () == old_vr->min ()
> > > +   && tem.max () == old_vr->max ())
> > > + continue;
> > 
> > I think it would be cleaner to use tem.ignore_equivs_equal_p (*old_vr). The
> > goal was to use == when the equivalence bitmap should be taken into account,
> > or ignore_equivs_equal_p() otherwise.
> 
> Ah, didn't know of that function (and yes, I wanted to ignore equivs).
> 
> Will try to remember together with the dump thing David noticed.

Like the following.

Bootstrapped / tested on x86_64-unknown-linux-gnu, applied.

Richard.

2018-10-23  Richard Biener  

* tree-vrp.c (add_assert_info): Guard dump_printf with
dump_enabled_p.
* gimple-ssa-evrp-analyze.c
(evrp_range_analyzer::record_ranges_from_incoming_edge):
Use value_range::ignore_equivs_equal_p.

Index: gcc/tree-vrp.c
===
--- gcc/tree-vrp.c  (revision 265420)
+++ gcc/tree-vrp.c  (working copy)
@@ -2299,9 +2299,10 @@ add_assert_info (vec 
   info.val = val;
   info.expr = expr;
   asserts.safe_push (info);
-  dump_printf (MSG_NOTE | MSG_PRIORITY_INTERNALS,
-  "Adding assert for %T from %T %s %T\n",
-  name, expr, op_symbol_code (comp_code), val);
+  if (dump_enabled_p ())
+dump_printf (MSG_NOTE | MSG_PRIORITY_INTERNALS,
+"Adding assert for %T from %T %s %T\n",
+name, expr, op_symbol_code (comp_code), val);
 }
 
 /* If NAME doesn't have an ASSERT_EXPR registered for asserting
Index: gcc/gimple-ssa-evrp-analyze.c
===
--- gcc/gimple-ssa-evrp-analyze.c   (revision 265420)
+++ gcc/gimple-ssa-evrp-analyze.c   (working copy)
@@ -209,9 +209,7 @@ evrp_range_analyzer::record_ranges_from_
  value_range *old_vr = get_value_range (vrs[i].first);
  value_range tem (old_vr->kind (), old_vr->min (), old_vr->max ());
  tem.intersect (vrs[i].second);
- if (tem.kind () == old_vr->kind ()
- && tem.min () == old_vr->min ()
- && tem.max () == old_vr->max ())
+ if (tem.ignore_equivs_equal_p (*old_vr))
continue;
  push_value_range (vrs[i].first, vrs[i].second);
  if (is_fallthru


Re: [PATCH] Fix some EVRP stupidness

2018-10-23 Thread Richard Biener
On Tue, 23 Oct 2018, Aldy Hernandez wrote:

> 
> > + if (tem.kind () == old_vr->kind ()
> > + && tem.min () == old_vr->min ()
> > + && tem.max () == old_vr->max ())
> > +   continue;
> 
> I think it would be cleaner to use tem.ignore_equivs_equal_p (*old_vr). The
> goal was to use == when the equivalence bitmap should be taken into account,
> or ignore_equivs_equal_p() otherwise.

Ah, didn't know of that function (and yes, I wanted to ignore equivs).

Will try to remember together with the dump thing David noticed.

Richard.

> (Unless you really really don't want to compare the extremes with
> vrp_operand_equal_p.)
> 
> Aldy


Re: [PATCH] Fix some EVRP stupidness

2018-10-23 Thread Aldy Hernandez




+ if (tem.kind () == old_vr->kind ()
+ && tem.min () == old_vr->min ()
+ && tem.max () == old_vr->max ())
+   continue;


I think it would be cleaner to use tem.ignore_equivs_equal_p (*old_vr). 
The goal was to use == when the equivalence bitmap should be taken into 
account, or ignore_equivs_equal_p() otherwise.


(Unless you really really don't want to compare the extremes with 
vrp_operand_equal_p.)


Aldy


Re: [PATCH] Fix some EVRP stupidness

2018-10-22 Thread Richard Biener
On Mon, 22 Oct 2018, David Malcolm wrote:

> On Mon, 2018-10-22 at 15:56 +0200, Richard Biener wrote:
> [...snip...]
> 
> > This is what I finally applied for the original patch after fixing
> > the above issue.
> > 
> > Bootstrapped and tested on x86_64-unknown-linux-gnu, applied.
> > 
> > Richard.
> > 
> > 2018-10-22  Richard Biener  
> > 
> > * gimple-ssa-evrp-analyze.c
> > (evrp_range_analyzer::record_ranges_from_incoming_edge): Be
> > smarter about what ranges to use.
> > * tree-vrp.c (add_assert_info): Dump here.
> > (register_edge_assert_for_2): Instead of here at multiple but
> > not all places.
> [...snip...]
>  
> > Index: gcc/tree-vrp.c
> > ===
> > --- gcc/tree-vrp.c  (revision 265381)
> > +++ gcc/tree-vrp.c  (working copy)
> > @@ -2299,6 +2299,9 @@ add_assert_info (vec 
> >info.val = val;
> >info.expr = expr;
> >asserts.safe_push (info);
> > +  dump_printf (MSG_NOTE | MSG_PRIORITY_INTERNALS,
> > +  "Adding assert for %T from %T %s %T\n",
> > +  name, expr, op_symbol_code (comp_code), val);
> >  }
> 
> I think this dump_printf call needs to be wrapped in:
>   if (dump_enabled_p ())
> since otherwise it does non-trivial work, which is then discarded for
> the common case where dumping is disabled.
> 
> Alternatively, should dump_printf and dump_printf_loc test have an
> early-reject internally for that?

Oh, I thought it had one - at least the "old" implementation
did nothing expensive so if (dump_enabled_p ()) was just used
to guard multiple printf stmts, avoiding multiple no-op calls.

Did you check that all existing dump_* calls are wrapped inside
a dump_enabled_p () region?  If so I can properly guard the above.
Otherwise I think we should restore previous expectation?

Richard.

> 
> >  /* If NAME doesn't have an ASSERT_EXPR registered for asserting
> > @@ -2698,16 +2701,6 @@ register_edge_assert_for_2 (tree name, e
> >   tmp = build1 (NOP_EXPR, TREE_TYPE (name), name3);
> >   if (cst2 != NULL_TREE)
> > tmp = build2 (PLUS_EXPR, TREE_TYPE (name), tmp, cst2);
> > -
> > - if (dump_file)
> > -   {
> > - fprintf (dump_file, "Adding assert for ");
> > - print_generic_expr (dump_file, name3);
> > - fprintf (dump_file, " from ");
> > - print_generic_expr (dump_file, tmp);
> > - fprintf (dump_file, "\n");
> > -   }
> > -
> >   add_assert_info (asserts, name3, tmp, comp_code, val);
> > }
> [...snip...]
> 
> 

-- 
Richard Biener 
SUSE LINUX GmbH, GF: Felix Imendoerffer, Jane Smithard, Graham Norton, HRB 
21284 (AG Nuernberg)


Re: [PATCH] Fix some EVRP stupidness

2018-10-22 Thread David Malcolm
On Mon, 2018-10-22 at 15:56 +0200, Richard Biener wrote:
[...snip...]

> This is what I finally applied for the original patch after fixing
> the above issue.
> 
> Bootstrapped and tested on x86_64-unknown-linux-gnu, applied.
> 
> Richard.
> 
> 2018-10-22  Richard Biener  
> 
>   * gimple-ssa-evrp-analyze.c
>   (evrp_range_analyzer::record_ranges_from_incoming_edge): Be
>   smarter about what ranges to use.
>   * tree-vrp.c (add_assert_info): Dump here.
>   (register_edge_assert_for_2): Instead of here at multiple but
>   not all places.
[...snip...]
 
> Index: gcc/tree-vrp.c
> ===
> --- gcc/tree-vrp.c(revision 265381)
> +++ gcc/tree-vrp.c(working copy)
> @@ -2299,6 +2299,9 @@ add_assert_info (vec 
>info.val = val;
>info.expr = expr;
>asserts.safe_push (info);
> +  dump_printf (MSG_NOTE | MSG_PRIORITY_INTERNALS,
> +"Adding assert for %T from %T %s %T\n",
> +name, expr, op_symbol_code (comp_code), val);
>  }

I think this dump_printf call needs to be wrapped in:
  if (dump_enabled_p ())
since otherwise it does non-trivial work, which is then discarded for
the common case where dumping is disabled.

Alternatively, should dump_printf and dump_printf_loc test have an
early-reject internally for that?


>  /* If NAME doesn't have an ASSERT_EXPR registered for asserting
> @@ -2698,16 +2701,6 @@ register_edge_assert_for_2 (tree name, e
> tmp = build1 (NOP_EXPR, TREE_TYPE (name), name3);
> if (cst2 != NULL_TREE)
>   tmp = build2 (PLUS_EXPR, TREE_TYPE (name), tmp, cst2);
> -
> -   if (dump_file)
> - {
> -   fprintf (dump_file, "Adding assert for ");
> -   print_generic_expr (dump_file, name3);
> -   fprintf (dump_file, " from ");
> -   print_generic_expr (dump_file, tmp);
> -   fprintf (dump_file, "\n");
> - }
> -
> add_assert_info (asserts, name3, tmp, comp_code, val);
>   }
[...snip...]


Re: [PATCH] Fix some EVRP stupidness

2018-10-22 Thread Richard Biener
On Thu, 18 Oct 2018, Richard Biener wrote:

> On October 18, 2018 5:42:56 PM GMT+02:00, Aldy Hernandez  
> wrote:
> >
> >
> >On 10/18/18 8:11 AM, Richard Biener wrote:
> >> On Thu, 18 Oct 2018, Richard Biener wrote:
> >> 
> >>>
> >>> At some point we decided to not simply intersect all ranges we get
> >>> via register_edge_assert_for.  Instead we simply register them
> >>> in-order.  That causes things like replacing [64, +INF] with ~[0,
> >0].
> >>>
> >>> The following patch avoids replacing a range with a larger one
> >>> as obvious improvement.
> >>>
> >>> Compared to assert_expr based VRP we lack the ability to put down
> >>> actual assert_exprs and thus multiple SSA names with ranges we
> >>> could link via equivalences.  In the end we need sth similar,
> >>> for example by keeping a stack of active ranges for each SSA name.
> >>>
> >>> Bootstrapped and tested on x86_64-unknown-linux-gnu, applied to
> >trunk.
> >> 
> >> Actually not.  Needed to update to the new value_range class and
> >after
> >> that (and its introduction of ->check()) we now ICE during bootstrap
> >> with
> >> 
> >> during GIMPLE pass: evrp
> >> /space/rguenther/src/svn/trunk/libgcc/config/libbid/bid128_div.c: In
> >> function ‘get_BID128’:
> >>
> >/space/rguenther/src/svn/trunk/libgcc/config/libbid/bid128_div.c:1851:1:
> >> internal compiler error: in check, at tree-vrp.c:155
> >>   1851 | }
> >>| ^
> >> 0xf3a8b5 value_range::check()
> >>  /space/rguenther/src/svn/trunk/gcc/tree-vrp.c:155
> >> 0xf42424 value_range::value_range(value_range_kind, tree_node*,
> >> tree_node*, bitmap_head*)
> >>  /space/rguenther/src/svn/trunk/gcc/tree-vrp.c:110
> >> 0xf42424 set_value_range_with_overflow
> >>  /space/rguenther/src/svn/trunk/gcc/tree-vrp.c:1422
> >> 0xf42424 extract_range_from_binary_expr_1(value_range*, tree_code,
> >> tree_node*, value_range const*, value_range const*)
> >>  /space/rguenther/src/svn/trunk/gcc/tree-vrp.c:1679
> >> 
> >> for a PLUS_EXPR of [12254, expon_43] and [-1, -1] yielding
> >> (temporarily!) [12254, -1] before supposed to be adjusted by the
> >> symbolic bound:
> >> 
> >>/* Adjust the range for possible overflow.  */
> >>set_value_range_with_overflow (*vr, expr_type,
> >>   wmin, wmax, min_ovf,
> >max_ovf);
> >> ^^^ ICE
> >>if (vr->varying_p ())
> >>  return;
> >> 
> >>/* Build the symbolic bounds if needed.  */
> >>min = vr->min ();
> >>max = vr->max ();
> >>adjust_symbolic_bound (min, code, expr_type,
> >>   sym_min_op0, sym_min_op1,
> >>   neg_min_op0, neg_min_op1);
> >>adjust_symbolic_bound (max, code, expr_type,
> >>   sym_max_op0, sym_max_op1,
> >>   neg_max_op0, neg_max_op1);
> >>type = vr->kind ();
> >> 
> >> I think the refactoring that was applied here is simply not suitable
> >> because *vr is _not_ necessarily a valid range before the symbolic
> >> bounds have been adjusted.  A fix would be sth like the following
> >> which I am going to test now.
> >
> >Sounds reasonable.
> 
> Doesn't work and miscompiles all over the place. 
> 
> >Is this PR87640?  Because the testcase there is also crashing while 
> >creating the range right before adjusting the symbolics.
> 
> Might be. 
> 
> I'll poke some more tomorrow unless you beat me to it. 

This is what I finally applied for the original patch after fixing
the above issue.

Bootstrapped and tested on x86_64-unknown-linux-gnu, applied.

Richard.

2018-10-22  Richard Biener  

* gimple-ssa-evrp-analyze.c
(evrp_range_analyzer::record_ranges_from_incoming_edge): Be
smarter about what ranges to use.
* tree-vrp.c (add_assert_info): Dump here.
(register_edge_assert_for_2): Instead of here at multiple but
not all places.

* gcc.dg/tree-ssa/evrp12.c: New testcase.
* gcc.dg/predict-6.c: Adjust.
* gcc.dg/tree-ssa/vrp33.c: Disable EVRP.
* gcc.dg/tree-ssa/vrp02.c: Likewise.
* gcc.dg/tree-ssa/cunroll-9.c: Likewise.

Index: gcc/gimple-ssa-evrp-analyze.c
===
--- gcc/gimple-ssa-evrp-analyze.c   (revision 265381)
+++ gcc/gimple-ssa-evrp-analyze.c   (working copy)
@@ -203,6 +203,16 @@ evrp_range_analyzer::record_ranges_from_
 ordering issues that can lead to worse ranges.  */
  for (unsigned i = 0; i < vrs.length (); ++i)
{
+ /* But make sure we do not weaken ranges like when
+getting first [64, +INF] and then ~[0, 0] from
+conditions like (s & 0x3cc0) == 0).  */
+ value_range *old_vr = get_value_range (vrs[i].first);
+ value_range tem (old_vr->kind (), old_vr->min (), old_vr->max ());
+ 

Re: [PATCH] Fix some EVRP stupidness

2018-10-18 Thread Richard Biener
On October 18, 2018 5:42:56 PM GMT+02:00, Aldy Hernandez  
wrote:
>
>
>On 10/18/18 8:11 AM, Richard Biener wrote:
>> On Thu, 18 Oct 2018, Richard Biener wrote:
>> 
>>>
>>> At some point we decided to not simply intersect all ranges we get
>>> via register_edge_assert_for.  Instead we simply register them
>>> in-order.  That causes things like replacing [64, +INF] with ~[0,
>0].
>>>
>>> The following patch avoids replacing a range with a larger one
>>> as obvious improvement.
>>>
>>> Compared to assert_expr based VRP we lack the ability to put down
>>> actual assert_exprs and thus multiple SSA names with ranges we
>>> could link via equivalences.  In the end we need sth similar,
>>> for example by keeping a stack of active ranges for each SSA name.
>>>
>>> Bootstrapped and tested on x86_64-unknown-linux-gnu, applied to
>trunk.
>> 
>> Actually not.  Needed to update to the new value_range class and
>after
>> that (and its introduction of ->check()) we now ICE during bootstrap
>> with
>> 
>> during GIMPLE pass: evrp
>> /space/rguenther/src/svn/trunk/libgcc/config/libbid/bid128_div.c: In
>> function ‘get_BID128’:
>>
>/space/rguenther/src/svn/trunk/libgcc/config/libbid/bid128_div.c:1851:1:
>> internal compiler error: in check, at tree-vrp.c:155
>>   1851 | }
>>| ^
>> 0xf3a8b5 value_range::check()
>>  /space/rguenther/src/svn/trunk/gcc/tree-vrp.c:155
>> 0xf42424 value_range::value_range(value_range_kind, tree_node*,
>> tree_node*, bitmap_head*)
>>  /space/rguenther/src/svn/trunk/gcc/tree-vrp.c:110
>> 0xf42424 set_value_range_with_overflow
>>  /space/rguenther/src/svn/trunk/gcc/tree-vrp.c:1422
>> 0xf42424 extract_range_from_binary_expr_1(value_range*, tree_code,
>> tree_node*, value_range const*, value_range const*)
>>  /space/rguenther/src/svn/trunk/gcc/tree-vrp.c:1679
>> 
>> for a PLUS_EXPR of [12254, expon_43] and [-1, -1] yielding
>> (temporarily!) [12254, -1] before supposed to be adjusted by the
>> symbolic bound:
>> 
>>/* Adjust the range for possible overflow.  */
>>set_value_range_with_overflow (*vr, expr_type,
>>   wmin, wmax, min_ovf,
>max_ovf);
>> ^^^ ICE
>>if (vr->varying_p ())
>>  return;
>> 
>>/* Build the symbolic bounds if needed.  */
>>min = vr->min ();
>>max = vr->max ();
>>adjust_symbolic_bound (min, code, expr_type,
>>   sym_min_op0, sym_min_op1,
>>   neg_min_op0, neg_min_op1);
>>adjust_symbolic_bound (max, code, expr_type,
>>   sym_max_op0, sym_max_op1,
>>   neg_max_op0, neg_max_op1);
>>type = vr->kind ();
>> 
>> I think the refactoring that was applied here is simply not suitable
>> because *vr is _not_ necessarily a valid range before the symbolic
>> bounds have been adjusted.  A fix would be sth like the following
>> which I am going to test now.
>
>Sounds reasonable.

Doesn't work and miscompiles all over the place. 

>Is this PR87640?  Because the testcase there is also crashing while 
>creating the range right before adjusting the symbolics.

Might be. 

I'll poke some more tomorrow unless you beat me to it. 

Richard. 

>Thanks for looking at this.
>Aldy



Re: [PATCH] Fix some EVRP stupidness

2018-10-18 Thread Aldy Hernandez




On 10/18/18 8:11 AM, Richard Biener wrote:

On Thu, 18 Oct 2018, Richard Biener wrote:



At some point we decided to not simply intersect all ranges we get
via register_edge_assert_for.  Instead we simply register them
in-order.  That causes things like replacing [64, +INF] with ~[0, 0].

The following patch avoids replacing a range with a larger one
as obvious improvement.

Compared to assert_expr based VRP we lack the ability to put down
actual assert_exprs and thus multiple SSA names with ranges we
could link via equivalences.  In the end we need sth similar,
for example by keeping a stack of active ranges for each SSA name.

Bootstrapped and tested on x86_64-unknown-linux-gnu, applied to trunk.


Actually not.  Needed to update to the new value_range class and after
that (and its introduction of ->check()) we now ICE during bootstrap
with

during GIMPLE pass: evrp
/space/rguenther/src/svn/trunk/libgcc/config/libbid/bid128_div.c: In
function ‘get_BID128’:
/space/rguenther/src/svn/trunk/libgcc/config/libbid/bid128_div.c:1851:1:
internal compiler error: in check, at tree-vrp.c:155
  1851 | }
   | ^
0xf3a8b5 value_range::check()
 /space/rguenther/src/svn/trunk/gcc/tree-vrp.c:155
0xf42424 value_range::value_range(value_range_kind, tree_node*,
tree_node*, bitmap_head*)
 /space/rguenther/src/svn/trunk/gcc/tree-vrp.c:110
0xf42424 set_value_range_with_overflow
 /space/rguenther/src/svn/trunk/gcc/tree-vrp.c:1422
0xf42424 extract_range_from_binary_expr_1(value_range*, tree_code,
tree_node*, value_range const*, value_range const*)
 /space/rguenther/src/svn/trunk/gcc/tree-vrp.c:1679

for a PLUS_EXPR of [12254, expon_43] and [-1, -1] yielding
(temporarily!) [12254, -1] before supposed to be adjusted by the
symbolic bound:

   /* Adjust the range for possible overflow.  */
   set_value_range_with_overflow (*vr, expr_type,
  wmin, wmax, min_ovf, max_ovf);
^^^ ICE
   if (vr->varying_p ())
 return;

   /* Build the symbolic bounds if needed.  */
   min = vr->min ();
   max = vr->max ();
   adjust_symbolic_bound (min, code, expr_type,
  sym_min_op0, sym_min_op1,
  neg_min_op0, neg_min_op1);
   adjust_symbolic_bound (max, code, expr_type,
  sym_max_op0, sym_max_op1,
  neg_max_op0, neg_max_op1);
   type = vr->kind ();

I think the refactoring that was applied here is simply not suitable
because *vr is _not_ necessarily a valid range before the symbolic
bounds have been adjusted.  A fix would be sth like the following
which I am going to test now.


Sounds reasonable.

Is this PR87640?  Because the testcase there is also crashing while 
creating the range right before adjusting the symbolics.


Thanks for looking at this.
Aldy


Re: [PATCH] Fix some EVRP stupidness

2018-10-18 Thread Richard Biener
On Thu, 18 Oct 2018, Richard Biener wrote:

> 
> At some point we decided to not simply intersect all ranges we get
> via register_edge_assert_for.  Instead we simply register them
> in-order.  That causes things like replacing [64, +INF] with ~[0, 0].
> 
> The following patch avoids replacing a range with a larger one
> as obvious improvement.
> 
> Compared to assert_expr based VRP we lack the ability to put down
> actual assert_exprs and thus multiple SSA names with ranges we
> could link via equivalences.  In the end we need sth similar,
> for example by keeping a stack of active ranges for each SSA name.
> 
> Bootstrapped and tested on x86_64-unknown-linux-gnu, applied to trunk.

Actually not.  Needed to update to the new value_range class and after
that (and its introduction of ->check()) we now ICE during bootstrap
with

during GIMPLE pass: evrp
/space/rguenther/src/svn/trunk/libgcc/config/libbid/bid128_div.c: In 
function ‘get_BID128’:
/space/rguenther/src/svn/trunk/libgcc/config/libbid/bid128_div.c:1851:1: 
internal compiler error: in check, at tree-vrp.c:155
 1851 | }
  | ^
0xf3a8b5 value_range::check()
/space/rguenther/src/svn/trunk/gcc/tree-vrp.c:155
0xf42424 value_range::value_range(value_range_kind, tree_node*, 
tree_node*, bitmap_head*)
/space/rguenther/src/svn/trunk/gcc/tree-vrp.c:110
0xf42424 set_value_range_with_overflow
/space/rguenther/src/svn/trunk/gcc/tree-vrp.c:1422
0xf42424 extract_range_from_binary_expr_1(value_range*, tree_code, 
tree_node*, value_range const*, value_range const*)
/space/rguenther/src/svn/trunk/gcc/tree-vrp.c:1679

for a PLUS_EXPR of [12254, expon_43] and [-1, -1] yielding
(temporarily!) [12254, -1] before supposed to be adjusted by the
symbolic bound:

  /* Adjust the range for possible overflow.  */
  set_value_range_with_overflow (*vr, expr_type,
 wmin, wmax, min_ovf, max_ovf);
^^^ ICE
  if (vr->varying_p ())
return;

  /* Build the symbolic bounds if needed.  */
  min = vr->min ();
  max = vr->max ();
  adjust_symbolic_bound (min, code, expr_type,
 sym_min_op0, sym_min_op1,
 neg_min_op0, neg_min_op1);
  adjust_symbolic_bound (max, code, expr_type,
 sym_max_op0, sym_max_op1,
 neg_max_op0, neg_max_op1);
  type = vr->kind ();

I think the refactoring that was applied here is simply not suitable
because *vr is _not_ necessarily a valid range before the symbolic
bounds have been adjusted.  A fix would be sth like the following
which I am going to test now.

Richard.

diff --git a/gcc/tree-vrp.c b/gcc/tree-vrp.c
index 40d40e5e2fe..c5748a43246 100644
--- a/gcc/tree-vrp.c
+++ b/gcc/tree-vrp.c
@@ -1328,7 +1328,7 @@ combine_bound (enum tree_code code, wide_int , 
wi::overflow_type ,
underflow.  +1 indicates overflow.  0 indicates neither.  */
 
 static void
-set_value_range_with_overflow (value_range ,
+set_value_range_with_overflow (value_range_kind , tree , tree 
,
   tree type,
   const wide_int , const wide_int ,
   wi::overflow_type min_ovf,
@@ -1341,7 +1341,7 @@ set_value_range_with_overflow (value_range ,
  range covers all values.  */
   if (prec == 1 && wi::lt_p (wmax, wmin, sgn))
 {
-  set_value_range_to_varying ();
+  kind = VR_VARYING;
   return;
 }
 
@@ -1357,13 +1357,15 @@ set_value_range_with_overflow (value_range ,
 the entire range.  We have a similar check at the end of
 extract_range_from_binary_expr_1.  */
  if (wi::gt_p (tmin, tmax, sgn))
-   vr.set_varying ();
+   kind = VR_VARYING;
  else
-   /* No overflow or both overflow or underflow.  The
-  range kind stays VR_RANGE.  */
-   vr = value_range (VR_RANGE,
- wide_int_to_tree (type, tmin),
- wide_int_to_tree (type, tmax));
+   {
+ kind = VR_RANGE;
+ /* No overflow or both overflow or underflow.  The
+range kind stays VR_RANGE.  */
+ min = wide_int_to_tree (type, tmin);
+ max = wide_int_to_tree (type, tmax);
+   }
  return;
}
   else if ((min_ovf == wi::OVF_UNDERFLOW && max_ovf == wi::OVF_NONE)
@@ -1384,18 +1386,18 @@ set_value_range_with_overflow (value_range ,
 types values.  */
  if (covers || wi::cmp (tmin, tmax, sgn) > 0)
{
- set_value_range_to_varying ();
+ kind = VR_VARYING;
  return;
}
- vr = value_range (VR_ANTI_RANGE,
-   wide_int_to_tree (type, tmin),
-   wide_int_to_tree (type, tmax));
+ kind = VR_ANTI_RANGE;
+