types for VR_VARYING
diff mbox series

Message ID a2dfa084-4335-4576-f85a-a6dfd460cb15@redhat.com
State New
Headers show
Series
  • types for VR_VARYING
Related show

Commit Message

Aldy Hernandez Aug. 12, 2019, 6:43 p.m. UTC
This is a fresh re-post of:

https://gcc.gnu.org/ml/gcc-patches/2019-07/msg00006.html

Andrew gave me some feedback a week ago, and I obviously don't remember 
what it was because I was about to leave on PTO.  However, I do remember 
I addressed his concerns before getting drunk on rum in tropical islands.

This patch adds MIN/MAX values for VR_VARYING.  As was discussed 
earlier, we are only changing VR_VARYING, not VR_UNDEFINED as was the 
original plan.

As I mentioned earlier, I am tired of re-doing ChangeLogs, so I'll whip 
up the changelog when the review starts.

Tested on x86-64 Linux.

OK?

Aldy

Comments

Jeff Law Aug. 12, 2019, 11:46 p.m. UTC | #1
On 8/12/19 12:43 PM, Aldy Hernandez wrote:
> This is a fresh re-post of:
> 
> https://gcc.gnu.org/ml/gcc-patches/2019-07/msg00006.html
> 
> Andrew gave me some feedback a week ago, and I obviously don't remember
> what it was because I was about to leave on PTO.  However, I do remember
> I addressed his concerns before getting drunk on rum in tropical islands.
FWIW found a great coffee infused rum while in Kauai last week.  I'm not
a coffee fan, but it was wonderful.  The one bottle we brought back
isn't going to last until Cauldron and I don't think I can get a special
order filled before I leave :(

Their more traditional rums were good as well.  Koloa Rum.  See if you
can get it locally :-)


> 
> This patch adds MIN/MAX values for VR_VARYING.  As was discussed
> earlier, we are only changing VR_VARYING, not VR_UNDEFINED as was the
> original plan.
> 
> As I mentioned earlier, I am tired of re-doing ChangeLogs, so I'll whip
> up the changelog when the review starts.
ACK.



> @@ -150,12 +166,11 @@ vr_values::set_defs_to_varying (gimple *stmt)
>    ssa_op_iter i;
>    tree def;
>    FOR_EACH_SSA_TREE_OPERAND (def, stmt, i, SSA_OP_DEF)
> -    {
> -      value_range *vr = get_value_range (def);
> -      /* Avoid writing to vr_const_varying get_value_range may return.  */
> -      if (!vr->varying_p ())
> -	vr->set_varying ();
> -    }
> +    if (value_range_base::supports_type_p (TREE_TYPE (def)))
> +      {
> +	value_range *vr = get_value_range (def);
> +	vr->set_varying (TREE_TYPE (def));
> +      }
>  }
Is the supports_type_p stuff there to placate the calls from ipa-cp?  I
can live with it in the short term, but it really feels like there
should be something in the ipa-cp client that avoids this silliness.


>  
>  /* Update the value range and equivalence set for variable VAR to

> @@ -1920,7 +1935,7 @@ vr_values::dump_all_value_ranges (FILE *file)
>  vr_values::vr_values () : vrp_value_range_pool ("Tree VRP value ranges")
>  {
>    values_propagated = false;
> -  num_vr_values = num_ssa_names;
> +  num_vr_values = num_ssa_names + num_ssa_names / 10;
>    vr_value = XCNEWVEC (value_range *, num_vr_values);
>    vr_phi_edge_counts = XCNEWVEC (int, num_ssa_names);
>    bitmap_obstack_initialize (&vrp_equiv_obstack);
My recollection was someone (Richi) proposed 2X for the initial
allocation which should ensure that in all but the most pathological
cases that we never trigger a reallocation.  In terms of "wasted" space,
it shouldn't matter in practice.

So if you could check the old thread and verify that Richi recommended
the 2X initial allocation and if so, make that minor update.

Jeff
Aldy Hernandez Aug. 14, 2019, 12:39 a.m. UTC | #2
On 8/12/19 7:46 PM, Jeff Law wrote:
> On 8/12/19 12:43 PM, Aldy Hernandez wrote:
>> This is a fresh re-post of:
>>
>> https://gcc.gnu.org/ml/gcc-patches/2019-07/msg00006.html
>>
>> Andrew gave me some feedback a week ago, and I obviously don't remember
>> what it was because I was about to leave on PTO.  However, I do remember
>> I addressed his concerns before getting drunk on rum in tropical islands.
> FWIW found a great coffee infused rum while in Kauai last week.  I'm not
> a coffee fan, but it was wonderful.  The one bottle we brought back
> isn't going to last until Cauldron and I don't think I can get a special
> order filled before I leave :(

You must bring some to Cauldron before we believe you. :)

> 
> Their more traditional rums were good as well.  Koloa Rum.  See if you
> can get it locally :-)
> 
> 
>>
>> This patch adds MIN/MAX values for VR_VARYING.  As was discussed
>> earlier, we are only changing VR_VARYING, not VR_UNDEFINED as was the
>> original plan.
>>
>> As I mentioned earlier, I am tired of re-doing ChangeLogs, so I'll whip
>> up the changelog when the review starts.
> ACK.

ChangeLog entries included in attached patch.

> 
> 
> 
>> @@ -150,12 +166,11 @@ vr_values::set_defs_to_varying (gimple *stmt)
>>     ssa_op_iter i;
>>     tree def;
>>     FOR_EACH_SSA_TREE_OPERAND (def, stmt, i, SSA_OP_DEF)
>> -    {
>> -      value_range *vr = get_value_range (def);
>> -      /* Avoid writing to vr_const_varying get_value_range may return.  */
>> -      if (!vr->varying_p ())
>> -	vr->set_varying ();
>> -    }
>> +    if (value_range_base::supports_type_p (TREE_TYPE (def)))
>> +      {
>> +	value_range *vr = get_value_range (def);
>> +	vr->set_varying (TREE_TYPE (def));
>> +      }
>>   }
> Is the supports_type_p stuff there to placate the calls from ipa-cp?  I
> can live with it in the short term, but it really feels like there
> should be something in the ipa-cp client that avoids this silliness.

I am not happy with this either, but there are various places where 
statements that are !stmt_interesting_for_vrp() are still setting a 
range of VARYING, which is then being ignored at a later time.

For example, vrp_initialize:

	  if (!stmt_interesting_for_vrp (phi))
	    {
	      tree lhs = PHI_RESULT (phi);
	      set_def_to_varying (lhs);
	      prop_set_simulate_again (phi, false);
	    }

Also in evrp_range_analyzer::record_ranges_from_stmt(), where we if the 
statement is interesting for VRP but extract_range_from_stmt() does not 
produce a useful range, we also set a varying for a range we will never 
use.  Similarly for a statement that is not interesting in this hunk.

Then there is vrp_prop::visit_stmt() where we also set VARYING for types 
that VRP will never handle:

       case IFN_ADD_OVERFLOW:
       case IFN_SUB_OVERFLOW:
       case IFN_MUL_OVERFLOW:
       case IFN_ATOMIC_COMPARE_EXCHANGE:
	/* These internal calls return _Complex integer type,
	   which VRP does not track, but the immediate uses
	   thereof might be interesting.  */
	if (lhs && TREE_CODE (lhs) == SSA_NAME)
	  {
	    imm_use_iterator iter;
	    use_operand_p use_p;
	    enum ssa_prop_result res = SSA_PROP_VARYING;

	    set_def_to_varying (lhs);

I've adjusted the patch so that set_def_to_varying will set the range to 
VR_UNDEFINED if !supports_type_p.  This is a fail safe, as we can't 
really do anything with a nonsensical range.  I just don't want to leave 
the range in an indeterminate state.

> 
> 
>>   
>>   /* Update the value range and equivalence set for variable VAR to
> 
>> @@ -1920,7 +1935,7 @@ vr_values::dump_all_value_ranges (FILE *file)
>>   vr_values::vr_values () : vrp_value_range_pool ("Tree VRP value ranges")
>>   {
>>     values_propagated = false;
>> -  num_vr_values = num_ssa_names;
>> +  num_vr_values = num_ssa_names + num_ssa_names / 10;
>>     vr_value = XCNEWVEC (value_range *, num_vr_values);
>>     vr_phi_edge_counts = XCNEWVEC (int, num_ssa_names);
>>     bitmap_obstack_initialize (&vrp_equiv_obstack);
> My recollection was someone (Richi) proposed 2X for the initial
> allocation which should ensure that in all but the most pathological
> cases that we never trigger a reallocation.  In terms of "wasted" space,
> it shouldn't matter in practice.
> 
> So if you could check the old thread and verify that Richi recommended
> the 2X initial allocation and if so, make that minor update.

Yes, it was 2X.

I noticed that Richi made some changes to the lattice handling for 
VARYING while the discussion was on-going.  I missed these, and had 
failed to adapt the patch for it.  I would appreciate a final review of 
the attached patch, especially the vr-values.c changes, which I have 
modified to play nice with current trunk.

I also noticed that Andrew's patch was setting num_vr_values to 
num_ssa_names + num_ssa_names / 10.  I think he meant num_vr_values + 
num_vr_values / 10.  Please verify the current incantation makes sense.

Tested on x86-64 Linux.

OK for trunk?

Aldy
Andrew MacLeod Aug. 14, 2019, 1:50 p.m. UTC | #3
On 8/13/19 8:39 PM, Aldy Hernandez wrote:
>
>
> Yes, it was 2X.
>
> I noticed that Richi made some changes to the lattice handling for 
> VARYING while the discussion was on-going.  I missed these, and had 
> failed to adapt the patch for it.  I would appreciate a final review 
> of the attached patch, especially the vr-values.c changes, which I 
> have modified to play nice with current trunk.
>
> I also noticed that Andrew's patch was setting num_vr_values to 
> num_ssa_names + num_ssa_names / 10.  I think he meant num_vr_values + 
> num_vr_values / 10.  Please verify the current incantation makes sense.
>
no, I meant num_ssa_names.  We are resizing the vector because 
num_vr_values is out of date (and smaller than num_ssa_names is now), so 
we need to resize the vector to be at least the number of ssa-names... 
and I added 10% just in case we arent done adding new ones.


if num_vr_values is 100, and we've added 200 ssa-names, num_ssa_names 
would now be 300.   if you resize based on num_vr_values, you could 
still go off the end of the vector.


Andrew
Aldy Hernandez Aug. 14, 2019, 2:15 p.m. UTC | #4
On 8/14/19 9:50 AM, Andrew MacLeod wrote:
> On 8/13/19 8:39 PM, Aldy Hernandez wrote:
>>
>>
>> Yes, it was 2X.
>>
>> I noticed that Richi made some changes to the lattice handling for 
>> VARYING while the discussion was on-going.  I missed these, and had 
>> failed to adapt the patch for it.  I would appreciate a final review 
>> of the attached patch, especially the vr-values.c changes, which I 
>> have modified to play nice with current trunk.
>>
>> I also noticed that Andrew's patch was setting num_vr_values to 
>> num_ssa_names + num_ssa_names / 10.  I think he meant num_vr_values + 
>> num_vr_values / 10.  Please verify the current incantation makes sense.
>>
> no, I meant num_ssa_names.  We are resizing the vector because 
> num_vr_values is out of date (and smaller than num_ssa_names is now), so 
> we need to resize the vector to be at least the number of ssa-names... 
> and I added 10% just in case we arent done adding new ones.
> 
> 
> if num_vr_values is 100, and we've added 200 ssa-names, num_ssa_names 
> would now be 300.   if you resize based on num_vr_values, you could 
> still go off the end of the vector.

OK, I've changed the resize to allocate 2X as well.  So now we'll have:

+      unsigned int old_sz = num_vr_values;
+      num_vr_values = num_ssa_names * 2;
+      vr_value = XRESIZEVEC (value_range *, vr_value, num_vr_values);
etc

And the original allocation will also be 2X.

Aldy
Jeff Law Aug. 14, 2019, 4:59 p.m. UTC | #5
On 8/14/19 8:15 AM, Aldy Hernandez wrote:
> 
> 
> On 8/14/19 9:50 AM, Andrew MacLeod wrote:
>> On 8/13/19 8:39 PM, Aldy Hernandez wrote:
>>>
>>>
>>> Yes, it was 2X.
>>>
>>> I noticed that Richi made some changes to the lattice handling for
>>> VARYING while the discussion was on-going.  I missed these, and had
>>> failed to adapt the patch for it.  I would appreciate a final review
>>> of the attached patch, especially the vr-values.c changes, which I
>>> have modified to play nice with current trunk.
>>>
>>> I also noticed that Andrew's patch was setting num_vr_values to
>>> num_ssa_names + num_ssa_names / 10.  I think he meant num_vr_values +
>>> num_vr_values / 10.  Please verify the current incantation makes sense.
>>>
>> no, I meant num_ssa_names.  We are resizing the vector because
>> num_vr_values is out of date (and smaller than num_ssa_names is now),
>> so we need to resize the vector to be at least the number of
>> ssa-names... and I added 10% just in case we arent done adding new ones.
>>
>>
>> if num_vr_values is 100, and we've added 200 ssa-names, num_ssa_names
>> would now be 300.   if you resize based on num_vr_values, you could
>> still go off the end of the vector.
> 
> OK, I've changed the resize to allocate 2X as well.  So now we'll have:
> 
> +      unsigned int old_sz = num_vr_values;
> +      num_vr_values = num_ssa_names * 2;
> +      vr_value = XRESIZEVEC (value_range *, vr_value, num_vr_values);
> etc
> 
> And the original allocation will also be 2X.
I don't think we want the resize to be 2X, we've tried to get away from
those kinds of growth patterns.  The 10% from Andrew's patch seems like
a better choice for the resize.

jeff
Jeff Law Aug. 14, 2019, 5:37 p.m. UTC | #6
On 8/13/19 6:39 PM, Aldy Hernandez wrote:
> 
> 
> On 8/12/19 7:46 PM, Jeff Law wrote:
>> On 8/12/19 12:43 PM, Aldy Hernandez wrote:
>>> This is a fresh re-post of:
>>>
>>> https://gcc.gnu.org/ml/gcc-patches/2019-07/msg00006.html
>>>
>>> Andrew gave me some feedback a week ago, and I obviously don't remember
>>> what it was because I was about to leave on PTO.  However, I do remember
>>> I addressed his concerns before getting drunk on rum in tropical islands.
>>>
>> FWIW found a great coffee infused rum while in Kauai last week.  I'm not
>> a coffee fan, but it was wonderful.  The one bottle we brought back
>> isn't going to last until Cauldron and I don't think I can get a special
>> order filled before I leave :(
> 
> You must bring some to Cauldron before we believe you. :)
That's the problem.  The nearest place I can get it is in Vegas and
there's no distributor in Montreal.   I can special order it in our
state run stores, but it won't be here in time.

Of course, I don't mind if you don't believe me.  More for me in that
case...


>> Is the supports_type_p stuff there to placate the calls from ipa-cp?  I
>> can live with it in the short term, but it really feels like there
>> should be something in the ipa-cp client that avoids this silliness.
> 
> I am not happy with this either, but there are various places where
> statements that are !stmt_interesting_for_vrp() are still setting a
> range of VARYING, which is then being ignored at a later time.
> 
> For example, vrp_initialize:
> 
>       if (!stmt_interesting_for_vrp (phi))
>         {
>           tree lhs = PHI_RESULT (phi);
>           set_def_to_varying (lhs);
>           prop_set_simulate_again (phi, false);
>         }
> 
> Also in evrp_range_analyzer::record_ranges_from_stmt(), where we if the
> statement is interesting for VRP but extract_range_from_stmt() does not
> produce a useful range, we also set a varying for a range we will never
> use.  Similarly for a statement that is not interesting in this hunk.
Ugh.  One could perhaps argue that setting any kind of range in these
circumstances is silly.   But I suspect it's necessary due to the
optimistic handling of VR_UNDEFINED in value_range_base::union_helper.
It's all coming back to me now...


> 
> Then there is vrp_prop::visit_stmt() where we also set VARYING for types
> that VRP will never handle:
> 
>       case IFN_ADD_OVERFLOW:
>       case IFN_SUB_OVERFLOW:
>       case IFN_MUL_OVERFLOW:
>       case IFN_ATOMIC_COMPARE_EXCHANGE:
>     /* These internal calls return _Complex integer type,
>        which VRP does not track, but the immediate uses
>        thereof might be interesting.  */
>     if (lhs && TREE_CODE (lhs) == SSA_NAME)
>       {
>         imm_use_iterator iter;
>         use_operand_p use_p;
>         enum ssa_prop_result res = SSA_PROP_VARYING;
> 
>         set_def_to_varying (lhs);
> 
> I've adjusted the patch so that set_def_to_varying will set the range to
> VR_UNDEFINED if !supports_type_p.  This is a fail safe, as we can't
> really do anything with a nonsensical range.  I just don't want to leave
> the range in an indeterminate state.
> 
I think VR_UNDEFINED is unsafe due to value_range_base::union_helper.
And that's a more general than this patch.  VR_UNDEFINED is _not_ a safe
range to set something to if we can't handle it.  We have to use VR_VARYING.

Why?  See the beginning of value_range_base::union_helper:

   /* VR0 has the resulting range if VR1 is undefined or VR0 is varying.  */
   if (vr1->undefined_p ()
       || vr0->varying_p ())
     return *vr0;

   /* VR1 has the resulting range if VR0 is undefined or VR1 is varying.  */
   if (vr0->undefined_p ()
       || vr1->varying_p ())
     return *vr1;
This can get called for something like

  a = <cond> ? name1 : name2;

If name1 was set to VR_UNDEFINED thinking that VR_UNDEFINED was a safe
value for something we can't handle, then we'll incorrectly return the
range for name2.

VR_UNDEFINED can only be used for the ranges of objects we haven't
processed.  If we can't produce a range for an object because the
statement is something we don't handle or just doesn't produce anythign
useful, then the right result is VR_VARYING.

This may be worth commenting at the definition site for VR_*.

> 
> I also noticed that Andrew's patch was setting num_vr_values to
> num_ssa_names + num_ssa_names / 10.  I think he meant num_vr_values +
> num_vr_values / 10.  Please verify the current incantation makes sense.
Going to assume this will be adjusted per the other messages in this thread.


> diff --git a/gcc/tree-ssa-threadedge.c b/gcc/tree-ssa-threadedge.c
> index 39ea22f0554..663dd6e2398 100644
> --- a/gcc/tree-ssa-threadedge.c
> +++ b/gcc/tree-ssa-threadedge.c
> @@ -182,8 +182,10 @@ record_temporary_equivalences_from_phis (edge e,
>  	    new_vr->deep_copy (vr_values->get_value_range (src));
>  	  else if (TREE_CODE (src) == INTEGER_CST)
>  	    new_vr->set (src);
> +	  else if (value_range_base::supports_type_p (TREE_TYPE (src)))
> +	    new_vr->set_varying (TREE_TYPE (src));
>  	  else
> -	    new_vr->set_varying ();
> +	    new_vr->set_undefined ();
So I think this can cause problems.  VR_VARYING seems like the right
state here.


> +
> +  if (!value_range_base::supports_type_p (TREE_TYPE (var)))
> +    {
> +      vr->set_undefined ();
> +      return vr;
Probably better as VR_VARYING here too.

> +	{
> +	  /* If we have an unsupported type (structs, void, etc), there
> +	     is nothing we'll be able to do with this entry.
> +	     Initialize it to UNDEFINED as a sanity measure, just in
> +	     case.  */
> +	  vr->set_undefined ();
Here too.

Jeff
Aldy Hernandez Aug. 15, 2019, 10:39 a.m. UTC | #7
On 8/14/19 1:37 PM, Jeff Law wrote:
> On 8/13/19 6:39 PM, Aldy Hernandez wrote:
>>
>>
>> On 8/12/19 7:46 PM, Jeff Law wrote:
>>> On 8/12/19 12:43 PM, Aldy Hernandez wrote:
>>>> This is a fresh re-post of:
>>>>
>>>> https://gcc.gnu.org/ml/gcc-patches/2019-07/msg00006.html
>>>>
>>>> Andrew gave me some feedback a week ago, and I obviously don't remember
>>>> what it was because I was about to leave on PTO.  However, I do remember
>>>> I addressed his concerns before getting drunk on rum in tropical islands.
>>>>
>>> FWIW found a great coffee infused rum while in Kauai last week.  I'm not
>>> a coffee fan, but it was wonderful.  The one bottle we brought back
>>> isn't going to last until Cauldron and I don't think I can get a special
>>> order filled before I leave :(
>>
>> You must bring some to Cauldron before we believe you. :)
> That's the problem.  The nearest place I can get it is in Vegas and
> there's no distributor in Montreal.   I can special order it in our
> state run stores, but it won't be here in time.
> 
> Of course, I don't mind if you don't believe me.  More for me in that
> case...
> 
> 
>>> Is the supports_type_p stuff there to placate the calls from ipa-cp?  I
>>> can live with it in the short term, but it really feels like there
>>> should be something in the ipa-cp client that avoids this silliness.
>>
>> I am not happy with this either, but there are various places where
>> statements that are !stmt_interesting_for_vrp() are still setting a
>> range of VARYING, which is then being ignored at a later time.
>>
>> For example, vrp_initialize:
>>
>>        if (!stmt_interesting_for_vrp (phi))
>>          {
>>            tree lhs = PHI_RESULT (phi);
>>            set_def_to_varying (lhs);
>>            prop_set_simulate_again (phi, false);
>>          }
>>
>> Also in evrp_range_analyzer::record_ranges_from_stmt(), where we if the
>> statement is interesting for VRP but extract_range_from_stmt() does not
>> produce a useful range, we also set a varying for a range we will never
>> use.  Similarly for a statement that is not interesting in this hunk.
> Ugh.  One could perhaps argue that setting any kind of range in these
> circumstances is silly.   But I suspect it's necessary due to the
> optimistic handling of VR_UNDEFINED in value_range_base::union_helper.
> It's all coming back to me now...
> 
> 
>>
>> Then there is vrp_prop::visit_stmt() where we also set VARYING for types
>> that VRP will never handle:
>>
>>        case IFN_ADD_OVERFLOW:
>>        case IFN_SUB_OVERFLOW:
>>        case IFN_MUL_OVERFLOW:
>>        case IFN_ATOMIC_COMPARE_EXCHANGE:
>>      /* These internal calls return _Complex integer type,
>>         which VRP does not track, but the immediate uses
>>         thereof might be interesting.  */
>>      if (lhs && TREE_CODE (lhs) == SSA_NAME)
>>        {
>>          imm_use_iterator iter;
>>          use_operand_p use_p;
>>          enum ssa_prop_result res = SSA_PROP_VARYING;
>>
>>          set_def_to_varying (lhs);
>>
>> I've adjusted the patch so that set_def_to_varying will set the range to
>> VR_UNDEFINED if !supports_type_p.  This is a fail safe, as we can't
>> really do anything with a nonsensical range.  I just don't want to leave
>> the range in an indeterminate state.
>>
> I think VR_UNDEFINED is unsafe due to value_range_base::union_helper.
> And that's a more general than this patch.  VR_UNDEFINED is _not_ a safe
> range to set something to if we can't handle it.  We have to use VR_VARYING.
> 
> Why?  See the beginning of value_range_base::union_helper:
> 
>     /* VR0 has the resulting range if VR1 is undefined or VR0 is varying.  */
>     if (vr1->undefined_p ()
>         || vr0->varying_p ())
>       return *vr0;
> 
>     /* VR1 has the resulting range if VR0 is undefined or VR1 is varying.  */
>     if (vr0->undefined_p ()
>         || vr1->varying_p ())
>       return *vr1;
> This can get called for something like
> 
>    a = <cond> ? name1 : name2;
> 
> If name1 was set to VR_UNDEFINED thinking that VR_UNDEFINED was a safe
> value for something we can't handle, then we'll incorrectly return the
> range for name2.

I think that if name1 was !supports_type_p, we will have never called 
union/intersect.  We will have bailed at some point earlier.  However, I 
do see your point about being consistent.

> 
> VR_UNDEFINED can only be used for the ranges of objects we haven't
> processed.  If we can't produce a range for an object because the
> statement is something we don't handle or just doesn't produce anythign
> useful, then the right result is VR_VARYING.
> 
> This may be worth commenting at the definition site for VR_*.
> 
>>
>> I also noticed that Andrew's patch was setting num_vr_values to
>> num_ssa_names + num_ssa_names / 10.  I think he meant num_vr_values +
>> num_vr_values / 10.  Please verify the current incantation makes sense.
> Going to assume this will be adjusted per the other messages in this thread.

Done.

> 
> 
>> diff --git a/gcc/tree-ssa-threadedge.c b/gcc/tree-ssa-threadedge.c
>> index 39ea22f0554..663dd6e2398 100644
>> --- a/gcc/tree-ssa-threadedge.c
>> +++ b/gcc/tree-ssa-threadedge.c
>> @@ -182,8 +182,10 @@ record_temporary_equivalences_from_phis (edge e,
>>   	    new_vr->deep_copy (vr_values->get_value_range (src));
>>   	  else if (TREE_CODE (src) == INTEGER_CST)
>>   	    new_vr->set (src);
>> +	  else if (value_range_base::supports_type_p (TREE_TYPE (src)))
>> +	    new_vr->set_varying (TREE_TYPE (src));
>>   	  else
>> -	    new_vr->set_varying ();
>> +	    new_vr->set_undefined ();
> So I think this can cause problems.  VR_VARYING seems like the right
> state here.
> 
> 
>> +
>> +  if (!value_range_base::supports_type_p (TREE_TYPE (var)))
>> +    {
>> +      vr->set_undefined ();
>> +      return vr;
> Probably better as VR_VARYING here too.
> 
>> +	{
>> +	  /* If we have an unsupported type (structs, void, etc), there
>> +	     is nothing we'll be able to do with this entry.
>> +	     Initialize it to UNDEFINED as a sanity measure, just in
>> +	     case.  */
>> +	  vr->set_undefined ();
> Here too.

Hmmm, the problem with setting VR_VARYING for unsupported types is that 
we have no min/max to use.  Even though min/max will not be used in any 
calculation, it's nice to have it set so type() will work consistently. 
May I suggest this generic approach while we disassociate the lattice 
and ranges from value_range_base (or remove vrp altogether :))?

void
value_range_base::set_varying (tree type)
{
   m_kind = VR_VARYING;
   if (supports_type_p (type))
     {
       m_min = vrp_val_min (type, true);
       m_max = vrp_val_max (type, true);
     }
   else
     {
       /* We can't do anything range-wise with these types.  Build
	 something for which type() will work as a temporary measure
	 until lattices and value_range_base are disassociated.  */
       m_min = m_max = build1 (NOP_EXPR, type, void_type_node);
     }
}

This way, no changes happen throughout the code, varying remains 
varying, type() works everywhere, and we don't have to dig into all 
value_range users to skip unsupported types.

This should work, as no one is going to call min() / max() on an 
unsupported type, since they're just being used for the lattice.

Aldy
Richard Biener Aug. 15, 2019, 11:23 a.m. UTC | #8
On Thu, Aug 15, 2019 at 12:40 PM Aldy Hernandez <aldyh@redhat.com> wrote:
>
> On 8/14/19 1:37 PM, Jeff Law wrote:
> > On 8/13/19 6:39 PM, Aldy Hernandez wrote:
> >>
> >>
> >> On 8/12/19 7:46 PM, Jeff Law wrote:
> >>> On 8/12/19 12:43 PM, Aldy Hernandez wrote:
> >>>> This is a fresh re-post of:
> >>>>
> >>>> https://gcc.gnu.org/ml/gcc-patches/2019-07/msg00006.html
> >>>>
> >>>> Andrew gave me some feedback a week ago, and I obviously don't remember
> >>>> what it was because I was about to leave on PTO.  However, I do remember
> >>>> I addressed his concerns before getting drunk on rum in tropical islands.
> >>>>
> >>> FWIW found a great coffee infused rum while in Kauai last week.  I'm not
> >>> a coffee fan, but it was wonderful.  The one bottle we brought back
> >>> isn't going to last until Cauldron and I don't think I can get a special
> >>> order filled before I leave :(
> >>
> >> You must bring some to Cauldron before we believe you. :)
> > That's the problem.  The nearest place I can get it is in Vegas and
> > there's no distributor in Montreal.   I can special order it in our
> > state run stores, but it won't be here in time.
> >
> > Of course, I don't mind if you don't believe me.  More for me in that
> > case...
> >
> >
> >>> Is the supports_type_p stuff there to placate the calls from ipa-cp?  I
> >>> can live with it in the short term, but it really feels like there
> >>> should be something in the ipa-cp client that avoids this silliness.
> >>
> >> I am not happy with this either, but there are various places where
> >> statements that are !stmt_interesting_for_vrp() are still setting a
> >> range of VARYING, which is then being ignored at a later time.
> >>
> >> For example, vrp_initialize:
> >>
> >>        if (!stmt_interesting_for_vrp (phi))
> >>          {
> >>            tree lhs = PHI_RESULT (phi);
> >>            set_def_to_varying (lhs);
> >>            prop_set_simulate_again (phi, false);
> >>          }
> >>
> >> Also in evrp_range_analyzer::record_ranges_from_stmt(), where we if the
> >> statement is interesting for VRP but extract_range_from_stmt() does not
> >> produce a useful range, we also set a varying for a range we will never
> >> use.  Similarly for a statement that is not interesting in this hunk.
> > Ugh.  One could perhaps argue that setting any kind of range in these
> > circumstances is silly.   But I suspect it's necessary due to the
> > optimistic handling of VR_UNDEFINED in value_range_base::union_helper.
> > It's all coming back to me now...
> >
> >
> >>
> >> Then there is vrp_prop::visit_stmt() where we also set VARYING for types
> >> that VRP will never handle:
> >>
> >>        case IFN_ADD_OVERFLOW:
> >>        case IFN_SUB_OVERFLOW:
> >>        case IFN_MUL_OVERFLOW:
> >>        case IFN_ATOMIC_COMPARE_EXCHANGE:
> >>      /* These internal calls return _Complex integer type,
> >>         which VRP does not track, but the immediate uses
> >>         thereof might be interesting.  */
> >>      if (lhs && TREE_CODE (lhs) == SSA_NAME)
> >>        {
> >>          imm_use_iterator iter;
> >>          use_operand_p use_p;
> >>          enum ssa_prop_result res = SSA_PROP_VARYING;
> >>
> >>          set_def_to_varying (lhs);
> >>
> >> I've adjusted the patch so that set_def_to_varying will set the range to
> >> VR_UNDEFINED if !supports_type_p.  This is a fail safe, as we can't
> >> really do anything with a nonsensical range.  I just don't want to leave
> >> the range in an indeterminate state.
> >>
> > I think VR_UNDEFINED is unsafe due to value_range_base::union_helper.
> > And that's a more general than this patch.  VR_UNDEFINED is _not_ a safe
> > range to set something to if we can't handle it.  We have to use VR_VARYING.
> >
> > Why?  See the beginning of value_range_base::union_helper:
> >
> >     /* VR0 has the resulting range if VR1 is undefined or VR0 is varying.  */
> >     if (vr1->undefined_p ()
> >         || vr0->varying_p ())
> >       return *vr0;
> >
> >     /* VR1 has the resulting range if VR0 is undefined or VR1 is varying.  */
> >     if (vr0->undefined_p ()
> >         || vr1->varying_p ())
> >       return *vr1;
> > This can get called for something like
> >
> >    a = <cond> ? name1 : name2;
> >
> > If name1 was set to VR_UNDEFINED thinking that VR_UNDEFINED was a safe
> > value for something we can't handle, then we'll incorrectly return the
> > range for name2.
>
> I think that if name1 was !supports_type_p, we will have never called
> union/intersect.  We will have bailed at some point earlier.  However, I
> do see your point about being consistent.
>
> >
> > VR_UNDEFINED can only be used for the ranges of objects we haven't
> > processed.  If we can't produce a range for an object because the
> > statement is something we don't handle or just doesn't produce anythign
> > useful, then the right result is VR_VARYING.
> >
> > This may be worth commenting at the definition site for VR_*.
> >
> >>
> >> I also noticed that Andrew's patch was setting num_vr_values to
> >> num_ssa_names + num_ssa_names / 10.  I think he meant num_vr_values +
> >> num_vr_values / 10.  Please verify the current incantation makes sense.
> > Going to assume this will be adjusted per the other messages in this thread.
>
> Done.
>
> >
> >
> >> diff --git a/gcc/tree-ssa-threadedge.c b/gcc/tree-ssa-threadedge.c
> >> index 39ea22f0554..663dd6e2398 100644
> >> --- a/gcc/tree-ssa-threadedge.c
> >> +++ b/gcc/tree-ssa-threadedge.c
> >> @@ -182,8 +182,10 @@ record_temporary_equivalences_from_phis (edge e,
> >>          new_vr->deep_copy (vr_values->get_value_range (src));
> >>        else if (TREE_CODE (src) == INTEGER_CST)
> >>          new_vr->set (src);
> >> +      else if (value_range_base::supports_type_p (TREE_TYPE (src)))
> >> +        new_vr->set_varying (TREE_TYPE (src));
> >>        else
> >> -        new_vr->set_varying ();
> >> +        new_vr->set_undefined ();
> > So I think this can cause problems.  VR_VARYING seems like the right
> > state here.
> >
> >
> >> +
> >> +  if (!value_range_base::supports_type_p (TREE_TYPE (var)))
> >> +    {
> >> +      vr->set_undefined ();
> >> +      return vr;
> > Probably better as VR_VARYING here too.
> >
> >> +    {
> >> +      /* If we have an unsupported type (structs, void, etc), there
> >> +         is nothing we'll be able to do with this entry.
> >> +         Initialize it to UNDEFINED as a sanity measure, just in
> >> +         case.  */
> >> +      vr->set_undefined ();
> > Here too.
>
> Hmmm, the problem with setting VR_VARYING for unsupported types is that
> we have no min/max to use.  Even though min/max will not be used in any
> calculation, it's nice to have it set so type() will work consistently.
> May I suggest this generic approach while we disassociate the lattice
> and ranges from value_range_base (or remove vrp altogether :))?
>
> void
> value_range_base::set_varying (tree type)
> {
>    m_kind = VR_VARYING;
>    if (supports_type_p (type))
>      {
>        m_min = vrp_val_min (type, true);
>        m_max = vrp_val_max (type, true);
>      }
>    else
>      {
>        /* We can't do anything range-wise with these types.  Build
>          something for which type() will work as a temporary measure
>          until lattices and value_range_base are disassociated.  */
>        m_min = m_max = build1 (NOP_EXPR, type, void_type_node);
>      }
> }
>
> This way, no changes happen throughout the code, varying remains
> varying, type() works everywhere, and we don't have to dig into all
> value_range users to skip unsupported types.
>
> This should work, as no one is going to call min() / max() on an
> unsupported type, since they're just being used for the lattice.

Then use error_mark_node or NULL_TREE?!

Sorry, couldn't resist to chime in when seeing the NOP_EXPR build.

Last time.  Promised.  I'm resisting to comment on the supports_type_p
abdomination.

Richard.

> Aldy
Aldy Hernandez Aug. 15, 2019, 1:03 p.m. UTC | #9
On 8/15/19 7:23 AM, Richard Biener wrote:
> On Thu, Aug 15, 2019 at 12:40 PM Aldy Hernandez <aldyh@redhat.com> wrote:
>>
>> On 8/14/19 1:37 PM, Jeff Law wrote:
>>> On 8/13/19 6:39 PM, Aldy Hernandez wrote:
>>>>
>>>>
>>>> On 8/12/19 7:46 PM, Jeff Law wrote:
>>>>> On 8/12/19 12:43 PM, Aldy Hernandez wrote:
>>>>>> This is a fresh re-post of:
>>>>>>
>>>>>> https://gcc.gnu.org/ml/gcc-patches/2019-07/msg00006.html
>>>>>>
>>>>>> Andrew gave me some feedback a week ago, and I obviously don't remember
>>>>>> what it was because I was about to leave on PTO.  However, I do remember
>>>>>> I addressed his concerns before getting drunk on rum in tropical islands.
>>>>>>
>>>>> FWIW found a great coffee infused rum while in Kauai last week.  I'm not
>>>>> a coffee fan, but it was wonderful.  The one bottle we brought back
>>>>> isn't going to last until Cauldron and I don't think I can get a special
>>>>> order filled before I leave :(
>>>>
>>>> You must bring some to Cauldron before we believe you. :)
>>> That's the problem.  The nearest place I can get it is in Vegas and
>>> there's no distributor in Montreal.   I can special order it in our
>>> state run stores, but it won't be here in time.
>>>
>>> Of course, I don't mind if you don't believe me.  More for me in that
>>> case...
>>>
>>>
>>>>> Is the supports_type_p stuff there to placate the calls from ipa-cp?  I
>>>>> can live with it in the short term, but it really feels like there
>>>>> should be something in the ipa-cp client that avoids this silliness.
>>>>
>>>> I am not happy with this either, but there are various places where
>>>> statements that are !stmt_interesting_for_vrp() are still setting a
>>>> range of VARYING, which is then being ignored at a later time.
>>>>
>>>> For example, vrp_initialize:
>>>>
>>>>         if (!stmt_interesting_for_vrp (phi))
>>>>           {
>>>>             tree lhs = PHI_RESULT (phi);
>>>>             set_def_to_varying (lhs);
>>>>             prop_set_simulate_again (phi, false);
>>>>           }
>>>>
>>>> Also in evrp_range_analyzer::record_ranges_from_stmt(), where we if the
>>>> statement is interesting for VRP but extract_range_from_stmt() does not
>>>> produce a useful range, we also set a varying for a range we will never
>>>> use.  Similarly for a statement that is not interesting in this hunk.
>>> Ugh.  One could perhaps argue that setting any kind of range in these
>>> circumstances is silly.   But I suspect it's necessary due to the
>>> optimistic handling of VR_UNDEFINED in value_range_base::union_helper.
>>> It's all coming back to me now...
>>>
>>>
>>>>
>>>> Then there is vrp_prop::visit_stmt() where we also set VARYING for types
>>>> that VRP will never handle:
>>>>
>>>>         case IFN_ADD_OVERFLOW:
>>>>         case IFN_SUB_OVERFLOW:
>>>>         case IFN_MUL_OVERFLOW:
>>>>         case IFN_ATOMIC_COMPARE_EXCHANGE:
>>>>       /* These internal calls return _Complex integer type,
>>>>          which VRP does not track, but the immediate uses
>>>>          thereof might be interesting.  */
>>>>       if (lhs && TREE_CODE (lhs) == SSA_NAME)
>>>>         {
>>>>           imm_use_iterator iter;
>>>>           use_operand_p use_p;
>>>>           enum ssa_prop_result res = SSA_PROP_VARYING;
>>>>
>>>>           set_def_to_varying (lhs);
>>>>
>>>> I've adjusted the patch so that set_def_to_varying will set the range to
>>>> VR_UNDEFINED if !supports_type_p.  This is a fail safe, as we can't
>>>> really do anything with a nonsensical range.  I just don't want to leave
>>>> the range in an indeterminate state.
>>>>
>>> I think VR_UNDEFINED is unsafe due to value_range_base::union_helper.
>>> And that's a more general than this patch.  VR_UNDEFINED is _not_ a safe
>>> range to set something to if we can't handle it.  We have to use VR_VARYING.
>>>
>>> Why?  See the beginning of value_range_base::union_helper:
>>>
>>>      /* VR0 has the resulting range if VR1 is undefined or VR0 is varying.  */
>>>      if (vr1->undefined_p ()
>>>          || vr0->varying_p ())
>>>        return *vr0;
>>>
>>>      /* VR1 has the resulting range if VR0 is undefined or VR1 is varying.  */
>>>      if (vr0->undefined_p ()
>>>          || vr1->varying_p ())
>>>        return *vr1;
>>> This can get called for something like
>>>
>>>     a = <cond> ? name1 : name2;
>>>
>>> If name1 was set to VR_UNDEFINED thinking that VR_UNDEFINED was a safe
>>> value for something we can't handle, then we'll incorrectly return the
>>> range for name2.
>>
>> I think that if name1 was !supports_type_p, we will have never called
>> union/intersect.  We will have bailed at some point earlier.  However, I
>> do see your point about being consistent.
>>
>>>
>>> VR_UNDEFINED can only be used for the ranges of objects we haven't
>>> processed.  If we can't produce a range for an object because the
>>> statement is something we don't handle or just doesn't produce anythign
>>> useful, then the right result is VR_VARYING.
>>>
>>> This may be worth commenting at the definition site for VR_*.
>>>
>>>>
>>>> I also noticed that Andrew's patch was setting num_vr_values to
>>>> num_ssa_names + num_ssa_names / 10.  I think he meant num_vr_values +
>>>> num_vr_values / 10.  Please verify the current incantation makes sense.
>>> Going to assume this will be adjusted per the other messages in this thread.
>>
>> Done.
>>
>>>
>>>
>>>> diff --git a/gcc/tree-ssa-threadedge.c b/gcc/tree-ssa-threadedge.c
>>>> index 39ea22f0554..663dd6e2398 100644
>>>> --- a/gcc/tree-ssa-threadedge.c
>>>> +++ b/gcc/tree-ssa-threadedge.c
>>>> @@ -182,8 +182,10 @@ record_temporary_equivalences_from_phis (edge e,
>>>>           new_vr->deep_copy (vr_values->get_value_range (src));
>>>>         else if (TREE_CODE (src) == INTEGER_CST)
>>>>           new_vr->set (src);
>>>> +      else if (value_range_base::supports_type_p (TREE_TYPE (src)))
>>>> +        new_vr->set_varying (TREE_TYPE (src));
>>>>         else
>>>> -        new_vr->set_varying ();
>>>> +        new_vr->set_undefined ();
>>> So I think this can cause problems.  VR_VARYING seems like the right
>>> state here.
>>>
>>>
>>>> +
>>>> +  if (!value_range_base::supports_type_p (TREE_TYPE (var)))
>>>> +    {
>>>> +      vr->set_undefined ();
>>>> +      return vr;
>>> Probably better as VR_VARYING here too.
>>>
>>>> +    {
>>>> +      /* If we have an unsupported type (structs, void, etc), there
>>>> +         is nothing we'll be able to do with this entry.
>>>> +         Initialize it to UNDEFINED as a sanity measure, just in
>>>> +         case.  */
>>>> +      vr->set_undefined ();
>>> Here too.
>>
>> Hmmm, the problem with setting VR_VARYING for unsupported types is that
>> we have no min/max to use.  Even though min/max will not be used in any
>> calculation, it's nice to have it set so type() will work consistently.
>> May I suggest this generic approach while we disassociate the lattice
>> and ranges from value_range_base (or remove vrp altogether :))?
>>
>> void
>> value_range_base::set_varying (tree type)
>> {
>>     m_kind = VR_VARYING;
>>     if (supports_type_p (type))
>>       {
>>         m_min = vrp_val_min (type, true);
>>         m_max = vrp_val_max (type, true);
>>       }
>>     else
>>       {
>>         /* We can't do anything range-wise with these types.  Build
>>           something for which type() will work as a temporary measure
>>           until lattices and value_range_base are disassociated.  */
>>         m_min = m_max = build1 (NOP_EXPR, type, void_type_node);
>>       }
>> }
>>
>> This way, no changes happen throughout the code, varying remains
>> varying, type() works everywhere, and we don't have to dig into all
>> value_range users to skip unsupported types.
>>
>> This should work, as no one is going to call min() / max() on an
>> unsupported type, since they're just being used for the lattice.
> 
> Then use error_mark_node or NULL_TREE?!

I was using something for which type() could work, to always be 
consistent.  But perhaps no one should be asking a type() for something 
we don't support range-wise ??.

I would prefer not to use NULL_TREE, so the assertion/checking routines 
can always expect something and not have to special case anything. 
Error_mark_node would work, if no one ever asks for type().

Thanks for your feedback.
Aldy

> 
> Sorry, couldn't resist to chime in when seeing the NOP_EXPR build.
> 
> Last time.  Promised.  I'm resisting to comment on the supports_type_p
> abdomination.
> 
> Richard.
> 
>> Aldy
Aldy Hernandez Aug. 15, 2019, 4:06 p.m. UTC | #10
On 8/15/19 7:23 AM, Richard Biener wrote:
> On Thu, Aug 15, 2019 at 12:40 PM Aldy Hernandez <aldyh@redhat.com> wrote:
>>
>> On 8/14/19 1:37 PM, Jeff Law wrote:
>>> On 8/13/19 6:39 PM, Aldy Hernandez wrote:
>>>>
>>>>
>>>> On 8/12/19 7:46 PM, Jeff Law wrote:
>>>>> On 8/12/19 12:43 PM, Aldy Hernandez wrote:
>>>>>> This is a fresh re-post of:
>>>>>>
>>>>>> https://gcc.gnu.org/ml/gcc-patches/2019-07/msg00006.html
>>>>>>
>>>>>> Andrew gave me some feedback a week ago, and I obviously don't remember
>>>>>> what it was because I was about to leave on PTO.  However, I do remember
>>>>>> I addressed his concerns before getting drunk on rum in tropical islands.
>>>>>>
>>>>> FWIW found a great coffee infused rum while in Kauai last week.  I'm not
>>>>> a coffee fan, but it was wonderful.  The one bottle we brought back
>>>>> isn't going to last until Cauldron and I don't think I can get a special
>>>>> order filled before I leave :(
>>>>
>>>> You must bring some to Cauldron before we believe you. :)
>>> That's the problem.  The nearest place I can get it is in Vegas and
>>> there's no distributor in Montreal.   I can special order it in our
>>> state run stores, but it won't be here in time.
>>>
>>> Of course, I don't mind if you don't believe me.  More for me in that
>>> case...
>>>
>>>
>>>>> Is the supports_type_p stuff there to placate the calls from ipa-cp?  I
>>>>> can live with it in the short term, but it really feels like there
>>>>> should be something in the ipa-cp client that avoids this silliness.
>>>>
>>>> I am not happy with this either, but there are various places where
>>>> statements that are !stmt_interesting_for_vrp() are still setting a
>>>> range of VARYING, which is then being ignored at a later time.
>>>>
>>>> For example, vrp_initialize:
>>>>
>>>>         if (!stmt_interesting_for_vrp (phi))
>>>>           {
>>>>             tree lhs = PHI_RESULT (phi);
>>>>             set_def_to_varying (lhs);
>>>>             prop_set_simulate_again (phi, false);
>>>>           }
>>>>
>>>> Also in evrp_range_analyzer::record_ranges_from_stmt(), where we if the
>>>> statement is interesting for VRP but extract_range_from_stmt() does not
>>>> produce a useful range, we also set a varying for a range we will never
>>>> use.  Similarly for a statement that is not interesting in this hunk.
>>> Ugh.  One could perhaps argue that setting any kind of range in these
>>> circumstances is silly.   But I suspect it's necessary due to the
>>> optimistic handling of VR_UNDEFINED in value_range_base::union_helper.
>>> It's all coming back to me now...
>>>
>>>
>>>>
>>>> Then there is vrp_prop::visit_stmt() where we also set VARYING for types
>>>> that VRP will never handle:
>>>>
>>>>         case IFN_ADD_OVERFLOW:
>>>>         case IFN_SUB_OVERFLOW:
>>>>         case IFN_MUL_OVERFLOW:
>>>>         case IFN_ATOMIC_COMPARE_EXCHANGE:
>>>>       /* These internal calls return _Complex integer type,
>>>>          which VRP does not track, but the immediate uses
>>>>          thereof might be interesting.  */
>>>>       if (lhs && TREE_CODE (lhs) == SSA_NAME)
>>>>         {
>>>>           imm_use_iterator iter;
>>>>           use_operand_p use_p;
>>>>           enum ssa_prop_result res = SSA_PROP_VARYING;
>>>>
>>>>           set_def_to_varying (lhs);
>>>>
>>>> I've adjusted the patch so that set_def_to_varying will set the range to
>>>> VR_UNDEFINED if !supports_type_p.  This is a fail safe, as we can't
>>>> really do anything with a nonsensical range.  I just don't want to leave
>>>> the range in an indeterminate state.
>>>>
>>> I think VR_UNDEFINED is unsafe due to value_range_base::union_helper.
>>> And that's a more general than this patch.  VR_UNDEFINED is _not_ a safe
>>> range to set something to if we can't handle it.  We have to use VR_VARYING.
>>>
>>> Why?  See the beginning of value_range_base::union_helper:
>>>
>>>      /* VR0 has the resulting range if VR1 is undefined or VR0 is varying.  */
>>>      if (vr1->undefined_p ()
>>>          || vr0->varying_p ())
>>>        return *vr0;
>>>
>>>      /* VR1 has the resulting range if VR0 is undefined or VR1 is varying.  */
>>>      if (vr0->undefined_p ()
>>>          || vr1->varying_p ())
>>>        return *vr1;
>>> This can get called for something like
>>>
>>>     a = <cond> ? name1 : name2;
>>>
>>> If name1 was set to VR_UNDEFINED thinking that VR_UNDEFINED was a safe
>>> value for something we can't handle, then we'll incorrectly return the
>>> range for name2.
>>
>> I think that if name1 was !supports_type_p, we will have never called
>> union/intersect.  We will have bailed at some point earlier.  However, I
>> do see your point about being consistent.
>>
>>>
>>> VR_UNDEFINED can only be used for the ranges of objects we haven't
>>> processed.  If we can't produce a range for an object because the
>>> statement is something we don't handle or just doesn't produce anythign
>>> useful, then the right result is VR_VARYING.
>>>
>>> This may be worth commenting at the definition site for VR_*.
>>>
>>>>
>>>> I also noticed that Andrew's patch was setting num_vr_values to
>>>> num_ssa_names + num_ssa_names / 10.  I think he meant num_vr_values +
>>>> num_vr_values / 10.  Please verify the current incantation makes sense.
>>> Going to assume this will be adjusted per the other messages in this thread.
>>
>> Done.
>>
>>>
>>>
>>>> diff --git a/gcc/tree-ssa-threadedge.c b/gcc/tree-ssa-threadedge.c
>>>> index 39ea22f0554..663dd6e2398 100644
>>>> --- a/gcc/tree-ssa-threadedge.c
>>>> +++ b/gcc/tree-ssa-threadedge.c
>>>> @@ -182,8 +182,10 @@ record_temporary_equivalences_from_phis (edge e,
>>>>           new_vr->deep_copy (vr_values->get_value_range (src));
>>>>         else if (TREE_CODE (src) == INTEGER_CST)
>>>>           new_vr->set (src);
>>>> +      else if (value_range_base::supports_type_p (TREE_TYPE (src)))
>>>> +        new_vr->set_varying (TREE_TYPE (src));
>>>>         else
>>>> -        new_vr->set_varying ();
>>>> +        new_vr->set_undefined ();
>>> So I think this can cause problems.  VR_VARYING seems like the right
>>> state here.
>>>
>>>
>>>> +
>>>> +  if (!value_range_base::supports_type_p (TREE_TYPE (var)))
>>>> +    {
>>>> +      vr->set_undefined ();
>>>> +      return vr;
>>> Probably better as VR_VARYING here too.
>>>
>>>> +    {
>>>> +      /* If we have an unsupported type (structs, void, etc), there
>>>> +         is nothing we'll be able to do with this entry.
>>>> +         Initialize it to UNDEFINED as a sanity measure, just in
>>>> +         case.  */
>>>> +      vr->set_undefined ();
>>> Here too.
>>
>> Hmmm, the problem with setting VR_VARYING for unsupported types is that
>> we have no min/max to use.  Even though min/max will not be used in any
>> calculation, it's nice to have it set so type() will work consistently.
>> May I suggest this generic approach while we disassociate the lattice
>> and ranges from value_range_base (or remove vrp altogether :))?
>>
>> void
>> value_range_base::set_varying (tree type)
>> {
>>     m_kind = VR_VARYING;
>>     if (supports_type_p (type))
>>       {
>>         m_min = vrp_val_min (type, true);
>>         m_max = vrp_val_max (type, true);
>>       }
>>     else
>>       {
>>         /* We can't do anything range-wise with these types.  Build
>>           something for which type() will work as a temporary measure
>>           until lattices and value_range_base are disassociated.  */
>>         m_min = m_max = build1 (NOP_EXPR, type, void_type_node);
>>       }
>> }
>>
>> This way, no changes happen throughout the code, varying remains
>> varying, type() works everywhere, and we don't have to dig into all
>> value_range users to skip unsupported types.
>>
>> This should work, as no one is going to call min() / max() on an
>> unsupported type, since they're just being used for the lattice.
> 
> Then use error_mark_node or NULL_TREE?!

I tested with error_mark_node.  It seems no one is calling type() on 
these unsupported types, so perhaps error_mark_node is fine, and signals 
that we don't support these types if anyone tries to do anything funny 
with them.  I've adjusted the patch.

Thanks.
Aldy
Aldy Hernandez Aug. 16, 2019, 6:57 a.m. UTC | #11
On 8/15/19 12:06 PM, Aldy Hernandez wrote:
> 
> 
> On 8/15/19 7:23 AM, Richard Biener wrote:
>> On Thu, Aug 15, 2019 at 12:40 PM Aldy Hernandez <aldyh@redhat.com> wrote:
>>>
>>> On 8/14/19 1:37 PM, Jeff Law wrote:
>>>> On 8/13/19 6:39 PM, Aldy Hernandez wrote:
>>>>>
>>>>>
>>>>> On 8/12/19 7:46 PM, Jeff Law wrote:
>>>>>> On 8/12/19 12:43 PM, Aldy Hernandez wrote:
>>>>>>> This is a fresh re-post of:
>>>>>>>
>>>>>>> https://gcc.gnu.org/ml/gcc-patches/2019-07/msg00006.html
>>>>>>>
>>>>>>> Andrew gave me some feedback a week ago, and I obviously don't 
>>>>>>> remember
>>>>>>> what it was because I was about to leave on PTO.  However, I do 
>>>>>>> remember
>>>>>>> I addressed his concerns before getting drunk on rum in tropical 
>>>>>>> islands.
>>>>>>>
>>>>>> FWIW found a great coffee infused rum while in Kauai last week.  
>>>>>> I'm not
>>>>>> a coffee fan, but it was wonderful.  The one bottle we brought back
>>>>>> isn't going to last until Cauldron and I don't think I can get a 
>>>>>> special
>>>>>> order filled before I leave :(
>>>>>
>>>>> You must bring some to Cauldron before we believe you. :)
>>>> That's the problem.  The nearest place I can get it is in Vegas and
>>>> there's no distributor in Montreal.   I can special order it in our
>>>> state run stores, but it won't be here in time.
>>>>
>>>> Of course, I don't mind if you don't believe me.  More for me in that
>>>> case...
>>>>
>>>>
>>>>>> Is the supports_type_p stuff there to placate the calls from 
>>>>>> ipa-cp?  I
>>>>>> can live with it in the short term, but it really feels like there
>>>>>> should be something in the ipa-cp client that avoids this silliness.
>>>>>
>>>>> I am not happy with this either, but there are various places where
>>>>> statements that are !stmt_interesting_for_vrp() are still setting a
>>>>> range of VARYING, which is then being ignored at a later time.
>>>>>
>>>>> For example, vrp_initialize:
>>>>>
>>>>>         if (!stmt_interesting_for_vrp (phi))
>>>>>           {
>>>>>             tree lhs = PHI_RESULT (phi);
>>>>>             set_def_to_varying (lhs);
>>>>>             prop_set_simulate_again (phi, false);
>>>>>           }
>>>>>
>>>>> Also in evrp_range_analyzer::record_ranges_from_stmt(), where we if 
>>>>> the
>>>>> statement is interesting for VRP but extract_range_from_stmt() does 
>>>>> not
>>>>> produce a useful range, we also set a varying for a range we will 
>>>>> never
>>>>> use.  Similarly for a statement that is not interesting in this hunk.
>>>> Ugh.  One could perhaps argue that setting any kind of range in these
>>>> circumstances is silly.   But I suspect it's necessary due to the
>>>> optimistic handling of VR_UNDEFINED in value_range_base::union_helper.
>>>> It's all coming back to me now...
>>>>
>>>>
>>>>>
>>>>> Then there is vrp_prop::visit_stmt() where we also set VARYING for 
>>>>> types
>>>>> that VRP will never handle:
>>>>>
>>>>>         case IFN_ADD_OVERFLOW:
>>>>>         case IFN_SUB_OVERFLOW:
>>>>>         case IFN_MUL_OVERFLOW:
>>>>>         case IFN_ATOMIC_COMPARE_EXCHANGE:
>>>>>       /* These internal calls return _Complex integer type,
>>>>>          which VRP does not track, but the immediate uses
>>>>>          thereof might be interesting.  */
>>>>>       if (lhs && TREE_CODE (lhs) == SSA_NAME)
>>>>>         {
>>>>>           imm_use_iterator iter;
>>>>>           use_operand_p use_p;
>>>>>           enum ssa_prop_result res = SSA_PROP_VARYING;
>>>>>
>>>>>           set_def_to_varying (lhs);
>>>>>
>>>>> I've adjusted the patch so that set_def_to_varying will set the 
>>>>> range to
>>>>> VR_UNDEFINED if !supports_type_p.  This is a fail safe, as we can't
>>>>> really do anything with a nonsensical range.  I just don't want to 
>>>>> leave
>>>>> the range in an indeterminate state.
>>>>>
>>>> I think VR_UNDEFINED is unsafe due to value_range_base::union_helper.
>>>> And that's a more general than this patch.  VR_UNDEFINED is _not_ a 
>>>> safe
>>>> range to set something to if we can't handle it.  We have to use 
>>>> VR_VARYING.
>>>>
>>>> Why?  See the beginning of value_range_base::union_helper:
>>>>
>>>>      /* VR0 has the resulting range if VR1 is undefined or VR0 is 
>>>> varying.  */
>>>>      if (vr1->undefined_p ()
>>>>          || vr0->varying_p ())
>>>>        return *vr0;
>>>>
>>>>      /* VR1 has the resulting range if VR0 is undefined or VR1 is 
>>>> varying.  */
>>>>      if (vr0->undefined_p ()
>>>>          || vr1->varying_p ())
>>>>        return *vr1;
>>>> This can get called for something like
>>>>
>>>>     a = <cond> ? name1 : name2;
>>>>
>>>> If name1 was set to VR_UNDEFINED thinking that VR_UNDEFINED was a safe
>>>> value for something we can't handle, then we'll incorrectly return the
>>>> range for name2.
>>>
>>> I think that if name1 was !supports_type_p, we will have never called
>>> union/intersect.  We will have bailed at some point earlier.  However, I
>>> do see your point about being consistent.
>>>
>>>>
>>>> VR_UNDEFINED can only be used for the ranges of objects we haven't
>>>> processed.  If we can't produce a range for an object because the
>>>> statement is something we don't handle or just doesn't produce anythign
>>>> useful, then the right result is VR_VARYING.
>>>>
>>>> This may be worth commenting at the definition site for VR_*.
>>>>
>>>>>
>>>>> I also noticed that Andrew's patch was setting num_vr_values to
>>>>> num_ssa_names + num_ssa_names / 10.  I think he meant num_vr_values +
>>>>> num_vr_values / 10.  Please verify the current incantation makes 
>>>>> sense.
>>>> Going to assume this will be adjusted per the other messages in this 
>>>> thread.
>>>
>>> Done.
>>>
>>>>
>>>>
>>>>> diff --git a/gcc/tree-ssa-threadedge.c b/gcc/tree-ssa-threadedge.c
>>>>> index 39ea22f0554..663dd6e2398 100644
>>>>> --- a/gcc/tree-ssa-threadedge.c
>>>>> +++ b/gcc/tree-ssa-threadedge.c
>>>>> @@ -182,8 +182,10 @@ record_temporary_equivalences_from_phis (edge e,
>>>>>           new_vr->deep_copy (vr_values->get_value_range (src));
>>>>>         else if (TREE_CODE (src) == INTEGER_CST)
>>>>>           new_vr->set (src);
>>>>> +      else if (value_range_base::supports_type_p (TREE_TYPE (src)))
>>>>> +        new_vr->set_varying (TREE_TYPE (src));
>>>>>         else
>>>>> -        new_vr->set_varying ();
>>>>> +        new_vr->set_undefined ();
>>>> So I think this can cause problems.  VR_VARYING seems like the right
>>>> state here.
>>>>
>>>>
>>>>> +
>>>>> +  if (!value_range_base::supports_type_p (TREE_TYPE (var)))
>>>>> +    {
>>>>> +      vr->set_undefined ();
>>>>> +      return vr;
>>>> Probably better as VR_VARYING here too.
>>>>
>>>>> +    {
>>>>> +      /* If we have an unsupported type (structs, void, etc), there
>>>>> +         is nothing we'll be able to do with this entry.
>>>>> +         Initialize it to UNDEFINED as a sanity measure, just in
>>>>> +         case.  */
>>>>> +      vr->set_undefined ();
>>>> Here too.
>>>
>>> Hmmm, the problem with setting VR_VARYING for unsupported types is that
>>> we have no min/max to use.  Even though min/max will not be used in any
>>> calculation, it's nice to have it set so type() will work consistently.
>>> May I suggest this generic approach while we disassociate the lattice
>>> and ranges from value_range_base (or remove vrp altogether :))?
>>>
>>> void
>>> value_range_base::set_varying (tree type)
>>> {
>>>     m_kind = VR_VARYING;
>>>     if (supports_type_p (type))
>>>       {
>>>         m_min = vrp_val_min (type, true);
>>>         m_max = vrp_val_max (type, true);
>>>       }
>>>     else
>>>       {
>>>         /* We can't do anything range-wise with these types.  Build
>>>           something for which type() will work as a temporary measure
>>>           until lattices and value_range_base are disassociated.  */
>>>         m_min = m_max = build1 (NOP_EXPR, type, void_type_node);
>>>       }
>>> }
>>>
>>> This way, no changes happen throughout the code, varying remains
>>> varying, type() works everywhere, and we don't have to dig into all
>>> value_range users to skip unsupported types.
>>>
>>> This should work, as no one is going to call min() / max() on an
>>> unsupported type, since they're just being used for the lattice.
>>
>> Then use error_mark_node or NULL_TREE?!
> 
> I tested with error_mark_node.  It seems no one is calling type() on 
> these unsupported types, so perhaps error_mark_node is fine, and signals 
> that we don't support these types if anyone tries to do anything funny 
> with them.  I've adjusted the patch.

Committed to trunk.

Aldy
Jeff Law Aug. 16, 2019, 3:58 p.m. UTC | #12
On 8/15/19 10:06 AM, Aldy Hernandez wrote:
> 
> 
> On 8/15/19 7:23 AM, Richard Biener wrote:
>> On Thu, Aug 15, 2019 at 12:40 PM Aldy Hernandez <aldyh@redhat.com> wrote:
>>>
>>> On 8/14/19 1:37 PM, Jeff Law wrote:
>>>> On 8/13/19 6:39 PM, Aldy Hernandez wrote:
>>>>>
>>>>>
>>>>> On 8/12/19 7:46 PM, Jeff Law wrote:
>>>>>> On 8/12/19 12:43 PM, Aldy Hernandez wrote:
>>>>>>> This is a fresh re-post of:
>>>>>>>
>>>>>>> https://gcc.gnu.org/ml/gcc-patches/2019-07/msg00006.html
>>>>>>>
>>>>>>> Andrew gave me some feedback a week ago, and I obviously don't
>>>>>>> remember
>>>>>>> what it was because I was about to leave on PTO.  However, I do
>>>>>>> remember
>>>>>>> I addressed his concerns before getting drunk on rum in tropical
>>>>>>> islands.
>>>>>>>
>>>>>> FWIW found a great coffee infused rum while in Kauai last week. 
>>>>>> I'm not
>>>>>> a coffee fan, but it was wonderful.  The one bottle we brought back
>>>>>> isn't going to last until Cauldron and I don't think I can get a
>>>>>> special
>>>>>> order filled before I leave :(
>>>>>
>>>>> You must bring some to Cauldron before we believe you. :)
>>>> That's the problem.  The nearest place I can get it is in Vegas and
>>>> there's no distributor in Montreal.   I can special order it in our
>>>> state run stores, but it won't be here in time.
>>>>
>>>> Of course, I don't mind if you don't believe me.  More for me in that
>>>> case...
>>>>
>>>>
>>>>>> Is the supports_type_p stuff there to placate the calls from
>>>>>> ipa-cp?  I
>>>>>> can live with it in the short term, but it really feels like there
>>>>>> should be something in the ipa-cp client that avoids this silliness.
>>>>>
>>>>> I am not happy with this either, but there are various places where
>>>>> statements that are !stmt_interesting_for_vrp() are still setting a
>>>>> range of VARYING, which is then being ignored at a later time.
>>>>>
>>>>> For example, vrp_initialize:
>>>>>
>>>>>         if (!stmt_interesting_for_vrp (phi))
>>>>>           {
>>>>>             tree lhs = PHI_RESULT (phi);
>>>>>             set_def_to_varying (lhs);
>>>>>             prop_set_simulate_again (phi, false);
>>>>>           }
>>>>>
>>>>> Also in evrp_range_analyzer::record_ranges_from_stmt(), where we if
>>>>> the
>>>>> statement is interesting for VRP but extract_range_from_stmt() does
>>>>> not
>>>>> produce a useful range, we also set a varying for a range we will
>>>>> never
>>>>> use.  Similarly for a statement that is not interesting in this hunk.
>>>> Ugh.  One could perhaps argue that setting any kind of range in these
>>>> circumstances is silly.   But I suspect it's necessary due to the
>>>> optimistic handling of VR_UNDEFINED in value_range_base::union_helper.
>>>> It's all coming back to me now...
>>>>
>>>>
>>>>>
>>>>> Then there is vrp_prop::visit_stmt() where we also set VARYING for
>>>>> types
>>>>> that VRP will never handle:
>>>>>
>>>>>         case IFN_ADD_OVERFLOW:
>>>>>         case IFN_SUB_OVERFLOW:
>>>>>         case IFN_MUL_OVERFLOW:
>>>>>         case IFN_ATOMIC_COMPARE_EXCHANGE:
>>>>>       /* These internal calls return _Complex integer type,
>>>>>          which VRP does not track, but the immediate uses
>>>>>          thereof might be interesting.  */
>>>>>       if (lhs && TREE_CODE (lhs) == SSA_NAME)
>>>>>         {
>>>>>           imm_use_iterator iter;
>>>>>           use_operand_p use_p;
>>>>>           enum ssa_prop_result res = SSA_PROP_VARYING;
>>>>>
>>>>>           set_def_to_varying (lhs);
>>>>>
>>>>> I've adjusted the patch so that set_def_to_varying will set the
>>>>> range to
>>>>> VR_UNDEFINED if !supports_type_p.  This is a fail safe, as we can't
>>>>> really do anything with a nonsensical range.  I just don't want to
>>>>> leave
>>>>> the range in an indeterminate state.
>>>>>
>>>> I think VR_UNDEFINED is unsafe due to value_range_base::union_helper.
>>>> And that's a more general than this patch.  VR_UNDEFINED is _not_ a
>>>> safe
>>>> range to set something to if we can't handle it.  We have to use
>>>> VR_VARYING.
>>>>
>>>> Why?  See the beginning of value_range_base::union_helper:
>>>>
>>>>      /* VR0 has the resulting range if VR1 is undefined or VR0 is
>>>> varying.  */
>>>>      if (vr1->undefined_p ()
>>>>          || vr0->varying_p ())
>>>>        return *vr0;
>>>>
>>>>      /* VR1 has the resulting range if VR0 is undefined or VR1 is
>>>> varying.  */
>>>>      if (vr0->undefined_p ()
>>>>          || vr1->varying_p ())
>>>>        return *vr1;
>>>> This can get called for something like
>>>>
>>>>     a = <cond> ? name1 : name2;
>>>>
>>>> If name1 was set to VR_UNDEFINED thinking that VR_UNDEFINED was a safe
>>>> value for something we can't handle, then we'll incorrectly return the
>>>> range for name2.
>>>
>>> I think that if name1 was !supports_type_p, we will have never called
>>> union/intersect.  We will have bailed at some point earlier.  However, I
>>> do see your point about being consistent.
>>>
>>>>
>>>> VR_UNDEFINED can only be used for the ranges of objects we haven't
>>>> processed.  If we can't produce a range for an object because the
>>>> statement is something we don't handle or just doesn't produce anythign
>>>> useful, then the right result is VR_VARYING.
>>>>
>>>> This may be worth commenting at the definition site for VR_*.
>>>>
>>>>>
>>>>> I also noticed that Andrew's patch was setting num_vr_values to
>>>>> num_ssa_names + num_ssa_names / 10.  I think he meant num_vr_values +
>>>>> num_vr_values / 10.  Please verify the current incantation makes
>>>>> sense.
>>>> Going to assume this will be adjusted per the other messages in this
>>>> thread.
>>>
>>> Done.
>>>
>>>>
>>>>
>>>>> diff --git a/gcc/tree-ssa-threadedge.c b/gcc/tree-ssa-threadedge.c
>>>>> index 39ea22f0554..663dd6e2398 100644
>>>>> --- a/gcc/tree-ssa-threadedge.c
>>>>> +++ b/gcc/tree-ssa-threadedge.c
>>>>> @@ -182,8 +182,10 @@ record_temporary_equivalences_from_phis (edge e,
>>>>>           new_vr->deep_copy (vr_values->get_value_range (src));
>>>>>         else if (TREE_CODE (src) == INTEGER_CST)
>>>>>           new_vr->set (src);
>>>>> +      else if (value_range_base::supports_type_p (TREE_TYPE (src)))
>>>>> +        new_vr->set_varying (TREE_TYPE (src));
>>>>>         else
>>>>> -        new_vr->set_varying ();
>>>>> +        new_vr->set_undefined ();
>>>> So I think this can cause problems.  VR_VARYING seems like the right
>>>> state here.
>>>>
>>>>
>>>>> +
>>>>> +  if (!value_range_base::supports_type_p (TREE_TYPE (var)))
>>>>> +    {
>>>>> +      vr->set_undefined ();
>>>>> +      return vr;
>>>> Probably better as VR_VARYING here too.
>>>>
>>>>> +    {
>>>>> +      /* If we have an unsupported type (structs, void, etc), there
>>>>> +         is nothing we'll be able to do with this entry.
>>>>> +         Initialize it to UNDEFINED as a sanity measure, just in
>>>>> +         case.  */
>>>>> +      vr->set_undefined ();
>>>> Here too.
>>>
>>> Hmmm, the problem with setting VR_VARYING for unsupported types is that
>>> we have no min/max to use.  Even though min/max will not be used in any
>>> calculation, it's nice to have it set so type() will work consistently.
>>> May I suggest this generic approach while we disassociate the lattice
>>> and ranges from value_range_base (or remove vrp altogether :))?
>>>
>>> void
>>> value_range_base::set_varying (tree type)
>>> {
>>>     m_kind = VR_VARYING;
>>>     if (supports_type_p (type))
>>>       {
>>>         m_min = vrp_val_min (type, true);
>>>         m_max = vrp_val_max (type, true);
>>>       }
>>>     else
>>>       {
>>>         /* We can't do anything range-wise with these types.  Build
>>>           something for which type() will work as a temporary measure
>>>           until lattices and value_range_base are disassociated.  */
>>>         m_min = m_max = build1 (NOP_EXPR, type, void_type_node);
>>>       }
>>> }
>>>
>>> This way, no changes happen throughout the code, varying remains
>>> varying, type() works everywhere, and we don't have to dig into all
>>> value_range users to skip unsupported types.
>>>
>>> This should work, as no one is going to call min() / max() on an
>>> unsupported type, since they're just being used for the lattice.
>>
>> Then use error_mark_node or NULL_TREE?!
> 
> I tested with error_mark_node.  It seems no one is calling type() on
> these unsupported types, so perhaps error_mark_node is fine, and signals
> that we don't support these types if anyone tries to do anything funny
> with them.  I've adjusted the patch.
I like error_mark_node.  It makes it pretty clear that something has
gone horribly wrong as opposed to something perhaps being uninitialized.

jeff
Martin Sebor Aug. 23, 2019, 8:27 p.m. UTC | #13
On 8/15/19 10:06 AM, Aldy Hernandez wrote:
> 

Hey Aldy,

After enabling EVRP for the strlen pass (as part of the sprintf
integration) I get a SEGV in the return statement in the function
below.  Backing out this change gets rid of the ICE and lets my
tests pass, but I have no idea what the root cause of the SEGV
might be.  The only mildly suspicious thing is the assertion in
the function:

@@ -355,9 +369,7 @@ value_range_base::singleton_p (tree *result) const
  tree
  value_range_base::type () const
  {
-  /* Types are only valid for VR_RANGE and VR_ANTI_RANGE, which are
-     known to have non-zero min/max.  */
-  gcc_assert (min ());
+  gcc_assert (m_min || undefined_p ());
    return TREE_TYPE (min ());
  }

*this looks like so:

   (gdb) p *this
   $55 = {m_kind = VR_UNDEFINED, m_min = 0x0, m_max = 0x0}

so the assertion passes but the dererefence in TREE_TYPE fails.

The test case is trivial:

   void g (const char *a, const char *b)
   {
     if (__builtin_memcmp (a, b, 8))
       __builtin_abort ();
   }

The ICE happens when updating the range for the second statement
below:

   _1 = __builtin_memcmp (a_3(D), b_4(D), 8);
   _1 = (int) _8;

Any ideas?

Martin


during GIMPLE pass: strlen
u.c: In function ‘g’:
u.c:1:6: internal compiler error: Segmentation fault
     1 | void g (const char *a, const char *b)
       |      ^
0x11c4d08 crash_signal
	/src/gcc/svn/gcc/toplev.c:326
0x815519 contains_struct_check(tree_node*, tree_node_structure_enum, 
char const*, int, char const*)
	/src/gcc/svn/gcc/tree.h:3376
0x15e9391 value_range_base::type() const
	/src/gcc/svn/gcc/tree-vrp.c:373
0x16bdad6 vr_values::update_value_range(tree_node const*, value_range*)
	/src/gcc/svn/gcc/vr-values.c:237
0x200f9a9 evrp_range_analyzer::record_ranges_from_stmt(gimple*, bool)
	/src/gcc/svn/gcc/gimple-ssa-evrp-analyze.c:325
0x14c9062 strlen_dom_walker::before_dom_children(basic_block_def*)
	/src/gcc/svn/gcc/tree-ssa-strlen.c:4800
0x1fbdf8a dom_walker::walk(basic_block_def*)
	/src/gcc/svn/gcc/domwalk.c:309
0x14c9362 printf_strlen_execute
	/src/gcc/svn/gcc/tree-ssa-strlen.c:4866
0x14c95f8 execute
	/src/gcc/svn/gcc/tree-ssa-strlen.c:4968
Please submit a full bug report,
Aldy Hernandez Aug. 24, 2019, 10:55 a.m. UTC | #14
On 8/23/19 4:27 PM, Martin Sebor wrote:
> On 8/15/19 10:06 AM, Aldy Hernandez wrote:
>>
> 
> Hey Aldy,
> 
> After enabling EVRP for the strlen pass (as part of the sprintf
> integration) I get a SEGV in the return statement in the function
> below.  Backing out this change gets rid of the ICE and lets my
> tests pass, but I have no idea what the root cause of the SEGV
> might be.  The only mildly suspicious thing is the assertion in
> the function:
> 
> @@ -355,9 +369,7 @@ value_range_base::singleton_p (tree *result) const
>   tree
>   value_range_base::type () const
>   {
> -  /* Types are only valid for VR_RANGE and VR_ANTI_RANGE, which are
> -     known to have non-zero min/max.  */
> -  gcc_assert (min ());
> +  gcc_assert (m_min || undefined_p ());
>     return TREE_TYPE (min ());
>   }

type() should really be:

tree
value_range_base::type () const
{
   gcc_assert (m_min);
   return TREE_TYPE (min ());
}

I should post a patch to fix this.  However, UNDEF should never have a 
type, so the assert will fail anyhow.

The code asking for the type of an UNDEF is wrong.

> 
> *this looks like so:
> 
>    (gdb) p *this
>    $55 = {m_kind = VR_UNDEFINED, m_min = 0x0, m_max = 0x0}
> 
> so the assertion passes but the dererefence in TREE_TYPE fails.
> 
> The test case is trivial:
> 
>    void g (const char *a, const char *b)
>    {
>      if (__builtin_memcmp (a, b, 8))
>        __builtin_abort ();
>    }
> 
> The ICE happens when updating the range for the second statement
> below:
> 
>    _1 = __builtin_memcmp (a_3(D), b_4(D), 8);
>    _1 = (int) _8;
> 
> Any ideas?
> 
> Martin
> 
> 
> during GIMPLE pass: strlen
> u.c: In function ‘g’:
> u.c:1:6: internal compiler error: Segmentation fault
>      1 | void g (const char *a, const char *b)
>        |      ^
> 0x11c4d08 crash_signal
>      /src/gcc/svn/gcc/toplev.c:326
> 0x815519 contains_struct_check(tree_node*, tree_node_structure_enum, 
> char const*, int, char const*)
>      /src/gcc/svn/gcc/tree.h:3376
> 0x15e9391 value_range_base::type() const
>      /src/gcc/svn/gcc/tree-vrp.c:373
> 0x16bdad6 vr_values::update_value_range(tree_node const*, value_range*)
>      /src/gcc/svn/gcc/vr-values.c:237

According to your backtrace, it looks like the call to type comes from here:

       /* Do not allow transitions up the lattice.  The following
          is slightly more awkward than just new_vr->type < old_vr->type
          because VR_RANGE and VR_ANTI_RANGE need to be considered
          the same.  We may not have is_new when transitioning to
          UNDEFINED.  If old_vr->type is VARYING, we shouldn't be
          called, if we are anyway, keep it VARYING.  */
       if (old_vr->varying_p ())
         {
           new_vr->set_varying (new_vr->type ());
           is_new = false;
         }

So new_vr is UNDEFINED and we're asking for it's type.  That should 
probably be:

new_vr->set_varying (TREE_TYPE (var));

Would you mind testing the attached patch?

If it passes, feel free to commit it as obvious.

Thanks for catching this.

Aldy
Martin Sebor Aug. 24, 2019, 7:02 p.m. UTC | #15
On 8/24/19 4:55 AM, Aldy Hernandez wrote:
> 
> 
> On 8/23/19 4:27 PM, Martin Sebor wrote:
>> On 8/15/19 10:06 AM, Aldy Hernandez wrote:
>>>
>>
>> Hey Aldy,
>>
>> After enabling EVRP for the strlen pass (as part of the sprintf
>> integration) I get a SEGV in the return statement in the function
>> below.  Backing out this change gets rid of the ICE and lets my
>> tests pass, but I have no idea what the root cause of the SEGV
>> might be.  The only mildly suspicious thing is the assertion in
>> the function:
>>
>> @@ -355,9 +369,7 @@ value_range_base::singleton_p (tree *result) const
>>   tree
>>   value_range_base::type () const
>>   {
>> -  /* Types are only valid for VR_RANGE and VR_ANTI_RANGE, which are
>> -     known to have non-zero min/max.  */
>> -  gcc_assert (min ());
>> +  gcc_assert (m_min || undefined_p ());
>>     return TREE_TYPE (min ());
>>   }
> 
> type() should really be:
> 
> tree
> value_range_base::type () const
> {
>    gcc_assert (m_min);
>    return TREE_TYPE (min ());
> }
> 
> I should post a patch to fix this.  However, UNDEF should never have a 
> type, so the assert will fail anyhow.
> 
> The code asking for the type of an UNDEF is wrong.
> 
>>
>> *this looks like so:
>>
>>    (gdb) p *this
>>    $55 = {m_kind = VR_UNDEFINED, m_min = 0x0, m_max = 0x0}
>>
>> so the assertion passes but the dererefence in TREE_TYPE fails.
>>
>> The test case is trivial:
>>
>>    void g (const char *a, const char *b)
>>    {
>>      if (__builtin_memcmp (a, b, 8))
>>        __builtin_abort ();
>>    }
>>
>> The ICE happens when updating the range for the second statement
>> below:
>>
>>    _1 = __builtin_memcmp (a_3(D), b_4(D), 8);
>>    _1 = (int) _8;
>>
>> Any ideas?
>>
>> Martin
>>
>>
>> during GIMPLE pass: strlen
>> u.c: In function ‘g’:
>> u.c:1:6: internal compiler error: Segmentation fault
>>      1 | void g (const char *a, const char *b)
>>        |      ^
>> 0x11c4d08 crash_signal
>>      /src/gcc/svn/gcc/toplev.c:326
>> 0x815519 contains_struct_check(tree_node*, tree_node_structure_enum, 
>> char const*, int, char const*)
>>      /src/gcc/svn/gcc/tree.h:3376
>> 0x15e9391 value_range_base::type() const
>>      /src/gcc/svn/gcc/tree-vrp.c:373
>> 0x16bdad6 vr_values::update_value_range(tree_node const*, value_range*)
>>      /src/gcc/svn/gcc/vr-values.c:237
> 
> According to your backtrace, it looks like the call to type comes from 
> here:
> 
>        /* Do not allow transitions up the lattice.  The following
>           is slightly more awkward than just new_vr->type < old_vr->type
>           because VR_RANGE and VR_ANTI_RANGE need to be considered
>           the same.  We may not have is_new when transitioning to
>           UNDEFINED.  If old_vr->type is VARYING, we shouldn't be
>           called, if we are anyway, keep it VARYING.  */
>        if (old_vr->varying_p ())
>          {
>            new_vr->set_varying (new_vr->type ());
>            is_new = false;
>          }
> 
> So new_vr is UNDEFINED and we're asking for it's type.  That should 
> probably be:
> 
> new_vr->set_varying (TREE_TYPE (var));
> 
> Would you mind testing the attached patch?
> 
> If it passes, feel free to commit it as obvious.
> 
> Thanks for catching this.

Thanks for the quick fix!  It cleared up the ICE for me.

Martin

Patch
diff mbox series

commit dad943a48ff2fccc203bf11839b7e3016e44dfe1
Author: Aldy Hernandez <aldyh@redhat.com>
Date:   Mon Jul 22 10:04:43 2019 +0200

    Add type to VR_VARYING.

diff --git a/gcc/gimple-ssa-evrp-analyze.c b/gcc/gimple-ssa-evrp-analyze.c
index 4c68af847e1..0184703a13c 100644
--- a/gcc/gimple-ssa-evrp-analyze.c
+++ b/gcc/gimple-ssa-evrp-analyze.c
@@ -251,13 +251,18 @@  evrp_range_analyzer::record_ranges_from_phis (basic_block bb)
       if (virtual_operand_p (lhs))
 	continue;
 
+      /* Skips floats and other things we can't represent in a
+	 range.  */
+      if (!value_range_base::supports_type_p (TREE_TYPE (lhs)))
+	continue;
+
       value_range vr_result;
       bool interesting = stmt_interesting_for_vrp (phi);
       if (!has_unvisited_preds && interesting)
 	vr_values->extract_range_from_phi_node (phi, &vr_result);
       else
 	{
-	  vr_result.set_varying ();
+	  vr_result.set_varying (TREE_TYPE (lhs));
 	  /* When we have an unvisited executable predecessor we can't
 	     use PHI arg ranges which may be still UNDEFINED but have
 	     to use VARYING for them.  But we can still resort to
diff --git a/gcc/ipa-cp.c b/gcc/ipa-cp.c
index 69c00a9c5a5..859ad3fbaf5 100644
--- a/gcc/ipa-cp.c
+++ b/gcc/ipa-cp.c
@@ -977,7 +977,12 @@  ipcp_vr_lattice::set_to_bottom ()
 {
   if (m_vr.varying_p ())
     return false;
-  m_vr.set_varying ();
+  /* ?? We create all sorts of VARYING ranges for floats, structures,
+     and other types which we cannot handle as ranges.  We should
+     probably avoid handling them throughout the pass, but it's easier
+     to create a sensible VARYING here and let the lattice
+     propagate.  */
+  m_vr.set_varying (integer_type_node);
   return true;
 }
 
diff --git a/gcc/tree-ssa-threadedge.c b/gcc/tree-ssa-threadedge.c
index 785227df690..43bca63da09 100644
--- a/gcc/tree-ssa-threadedge.c
+++ b/gcc/tree-ssa-threadedge.c
@@ -182,8 +182,10 @@  record_temporary_equivalences_from_phis (edge e,
 	    new_vr->deep_copy (vr_values->get_value_range (src));
 	  else if (TREE_CODE (src) == INTEGER_CST)
 	    new_vr->set (src);
+	  else if (value_range_base::supports_type_p (TREE_TYPE (src)))
+	    new_vr->set_varying (TREE_TYPE (src));
 	  else
-	    new_vr->set_varying ();
+	    new_vr->set_undefined ();
 
 	  /* This is a temporary range for DST, so push it.  */
 	  evrp_range_analyzer->push_value_range (dst, new_vr);
diff --git a/gcc/tree-ssanames.c b/gcc/tree-ssanames.c
index 8b80bce8945..3911db9c26e 100644
--- a/gcc/tree-ssanames.c
+++ b/gcc/tree-ssanames.c
@@ -440,14 +440,16 @@  get_range_info (const_tree name, value_range_base &vr)
   wide_int wmin, wmax;
   enum value_range_kind kind = get_range_info (name, &wmin, &wmax);
 
-  if (kind == VR_VARYING || kind == VR_UNDEFINED)
-    min = max = NULL;
+  if (kind == VR_VARYING)
+    vr.set_varying (TREE_TYPE (name));
+  else if (kind == VR_UNDEFINED)
+    vr.set_undefined ();
   else
     {
       min = wide_int_to_tree (TREE_TYPE (name), wmin);
       max = wide_int_to_tree (TREE_TYPE (name), wmax);
+      vr.set (kind, min, max);
     }
-  vr.set (kind, min, max);
   return kind;
 }
 
diff --git a/gcc/tree-vrp.c b/gcc/tree-vrp.c
index de2f39d8487..e215b032f78 100644
--- a/gcc/tree-vrp.c
+++ b/gcc/tree-vrp.c
@@ -186,9 +186,11 @@  value_range_base::check ()
 	break;
       }
     case VR_UNDEFINED:
-    case VR_VARYING:
       gcc_assert (!min () && !max ());
       break;
+    case VR_VARYING:
+      gcc_assert (m_min && m_max);
+      break;
     default:
       gcc_unreachable ();
     }
@@ -214,6 +216,10 @@  value_range::check ()
 bool
 value_range_base::equal_p (const value_range_base &other) const
 {
+  /* Ignore types for undefined.  All undefines are equal.  */
+  if (undefined_p ())
+    return m_kind == other.m_kind;
+
   return (m_kind == other.m_kind
 	  && vrp_operand_equal_p (m_min, other.m_min)
 	  && vrp_operand_equal_p (m_max, other.m_max));
@@ -269,16 +275,19 @@  value_range::set_undefined ()
 }
 
 void
-value_range_base::set_varying ()
+value_range_base::set_varying (tree type)
 {
+  gcc_assert (supports_type_p (type));
   m_kind = VR_VARYING;
-  m_min = m_max = NULL;
+  m_min = vrp_val_min (type, true);
+  m_max = vrp_val_max (type, true);
 }
 
 void
-value_range::set_varying ()
+value_range::set_varying (tree type)
 {
-  set (VR_VARYING, NULL, NULL, NULL);
+  value_range_base::set_varying (type);
+  equiv_clear ();
 }
 
 /* Return TRUE if it is possible that range contains VAL.  */
@@ -355,9 +364,7 @@  value_range_base::singleton_p (tree *result) const
 tree
 value_range_base::type () const
 {
-  /* Types are only valid for VR_RANGE and VR_ANTI_RANGE, which are
-     known to have non-zero min/max.  */
-  gcc_assert (min ());
+  gcc_assert (m_min || undefined_p ());
   return TREE_TYPE (min ());
 }
 
@@ -395,11 +402,20 @@  value_range_base::dump (FILE *file) const
       fprintf (file, "]");
     }
   else if (varying_p ())
-    fprintf (file, "VARYING");
+    {
+      print_generic_expr (file, type ());
+      fprintf (file, " VARYING");
+    }
   else
     gcc_unreachable ();
 }
 
+void
+value_range_base::dump () const
+{
+  dump (stderr);
+}
+
 void
 value_range::dump (FILE *file) const
 {
@@ -423,6 +439,12 @@  value_range::dump (FILE *file) const
     }
 }
 
+void
+value_range::dump () const
+{
+  dump (stderr);
+}
+
 void
 dump_value_range (FILE *file, const value_range *vr)
 {
@@ -658,7 +680,10 @@  value_range_base::set (enum value_range_kind kind, tree min, tree max)
     }
   else if (kind == VR_VARYING)
     {
-      set_varying ();
+      gcc_assert (TREE_TYPE (min) == TREE_TYPE (max));
+      gcc_assert (vrp_val_min (TREE_TYPE (min), true));
+      gcc_assert (vrp_val_max (TREE_TYPE (max), true));
+      set_varying (TREE_TYPE (min));
       return;
     }
 
@@ -683,7 +708,7 @@  value_range_base::set (enum value_range_kind kind, tree min, tree max)
 	 for VR_ANTI_RANGE empty range, so drop to varying as well.  */
       if (TYPE_PRECISION (TREE_TYPE (min)) == 1)
 	{
-	  set_varying ();
+	  set_varying (TREE_TYPE (min));
 	  return;
 	}
 
@@ -697,7 +722,7 @@  value_range_base::set (enum value_range_kind kind, tree min, tree max)
 	 to varying in this case.  */
       if (tree_int_cst_lt (max, min))
 	{
-	  set_varying ();
+	  set_varying (TREE_TYPE (min));
 	  return;
 	}
 
@@ -720,7 +745,7 @@  value_range_base::set (enum value_range_kind kind, tree min, tree max)
 	{
 	  /* We cannot deal with empty ranges, drop to varying.
 	     ???  This could be VR_UNDEFINED instead.  */
-	  set_varying ();
+	  set_varying (type);
 	  return;
 	}
       else if (TYPE_PRECISION (TREE_TYPE (min)) == 1
@@ -767,7 +792,7 @@  value_range_base::set (enum value_range_kind kind, tree min, tree max)
       && wi::eq_p (wi::to_wide (max), wi::max_value (prec, sign)))
     {
       if (kind == VR_RANGE)
-	set_varying ();
+	set_varying (type);
       else if (kind == VR_ANTI_RANGE)
 	set_undefined ();
       else
@@ -1292,7 +1317,7 @@  extract_range_from_multiplicative_op (value_range_base *vr,
 	      || code == LSHIFT_EXPR);
   if (!range_int_cst_p (vr1))
     {
-      vr->set_varying ();
+      vr->set_varying (type);
       return;
     }
 
@@ -1327,7 +1352,7 @@  extract_range_from_multiplicative_op (value_range_base *vr,
     vr->set (VR_RANGE, wide_int_to_tree (type, res_lb),
 	     wide_int_to_tree (type, res_ub));
   else
-    vr->set_varying ();
+    vr->set_varying (type);
 }
 
 /* If BOUND will include a symbolic bound, adjust it accordingly,
@@ -1536,7 +1561,7 @@  extract_range_from_binary_expr (value_range_base *vr,
   if (!INTEGRAL_TYPE_P (expr_type)
       && !POINTER_TYPE_P (expr_type))
     {
-      vr->set_varying ();
+      vr->set_varying (expr_type);
       return;
     }
 
@@ -1560,7 +1585,7 @@  extract_range_from_binary_expr (value_range_base *vr,
       && code != BIT_IOR_EXPR
       && code != BIT_XOR_EXPR)
     {
-      vr->set_varying ();
+      vr->set_varying (expr_type);
       return;
     }
 
@@ -1575,9 +1600,9 @@  extract_range_from_binary_expr (value_range_base *vr,
      have UNDEFINED result for all or some value-ranges of the not UNDEFINED
      operand.  */
   else if (vr0.undefined_p ())
-    vr0.set_varying ();
+    vr0.set_varying (expr_type);
   else if (vr1.undefined_p ())
-    vr1.set_varying ();
+    vr1.set_varying (expr_type);
 
   /* We get imprecise results from ranges_from_anti_range when
      code is EXACT_DIV_EXPR.  We could mask out bits in the resulting
@@ -1649,7 +1674,7 @@  extract_range_from_binary_expr (value_range_base *vr,
 	  || vr0.symbolic_p ()
 	  || vr1.symbolic_p ()))
     {
-      vr->set_varying ();
+      vr->set_varying (expr_type);
       return;
     }
 
@@ -1667,7 +1692,7 @@  extract_range_from_binary_expr (value_range_base *vr,
 	  else if (vr0.zero_p () && vr1.zero_p ())
 	    vr->set_zero (expr_type);
 	  else
-	    vr->set_varying ();
+	    vr->set_varying (expr_type);
 	}
       else if (code == POINTER_PLUS_EXPR)
 	{
@@ -1696,7 +1721,7 @@  extract_range_from_binary_expr (value_range_base *vr,
 	  else if (vr0.zero_p () && vr1.zero_p ())
 	    vr->set_zero (expr_type);
 	  else
-	    vr->set_varying ();
+	    vr->set_varying (expr_type);
 	}
       else if (code == BIT_AND_EXPR)
 	{
@@ -1707,10 +1732,10 @@  extract_range_from_binary_expr (value_range_base *vr,
 	  else if (vr0.zero_p () || vr1.zero_p ())
 	    vr->set_zero (expr_type);
 	  else
-	    vr->set_varying ();
+	    vr->set_varying (expr_type);
 	}
       else
-	vr->set_varying ();
+	vr->set_varying (expr_type);
 
       return;
     }
@@ -1788,7 +1813,7 @@  extract_range_from_binary_expr (value_range_base *vr,
 	  if (((bool)min_ovf && sym_min_op0 != sym_min_op1)
 	      || ((bool)max_ovf && sym_max_op0 != sym_max_op1))
 	    {
-	      vr->set_varying ();
+	      vr->set_varying (expr_type);
 	      return;
 	    }
 
@@ -1799,7 +1824,7 @@  extract_range_from_binary_expr (value_range_base *vr,
 					 wmin, wmax, min_ovf, max_ovf);
 	  if (type == VR_VARYING)
 	    {
-	      vr->set_varying ();
+	      vr->set_varying (expr_type);
 	      return;
 	    }
 
@@ -1825,7 +1850,7 @@  extract_range_from_binary_expr (value_range_base *vr,
 	     a single range or anti-range as the above is
 		 [-INF+1, +INF(OVF)] intersected with ~[5, 5]
 	     but one could use a scheme similar to equivalences for this. */
-	  vr->set_varying ();
+	  vr->set_varying (expr_type);
 	  return;
 	}
     }
@@ -1842,7 +1867,7 @@  extract_range_from_binary_expr (value_range_base *vr,
 	vr->set (VR_RANGE, wide_int_to_tree (expr_type, wmin),
 		 wide_int_to_tree (expr_type, wmax));
       else
-	vr->set_varying ();
+	vr->set_varying (expr_type);
       return;
     }
   else if (code == MULT_EXPR)
@@ -1850,7 +1875,7 @@  extract_range_from_binary_expr (value_range_base *vr,
       if (!range_int_cst_p (&vr0)
 	  || !range_int_cst_p (&vr1))
 	{
-	  vr->set_varying ();
+	  vr->set_varying (expr_type);
 	  return;
 	}
       extract_range_from_multiplicative_op (vr, code, &vr0, &vr1, expr_type);
@@ -1890,7 +1915,7 @@  extract_range_from_binary_expr (value_range_base *vr,
 		}
 	    }
 	}
-      vr->set_varying ();
+      vr->set_varying (expr_type);
       return;
     }
   else if (code == TRUNC_DIV_EXPR
@@ -1927,7 +1952,7 @@  extract_range_from_binary_expr (value_range_base *vr,
 			       TYPE_OVERFLOW_UNDEFINED (expr_type),
 			       extra_range_p, extra_min, extra_max))
 	{
-	  vr->set_varying ();
+	  vr->set_varying (expr_type);
 	  return;
 	}
       vr->set (VR_RANGE, wide_int_to_tree (expr_type, wmin),
@@ -1986,7 +2011,7 @@  extract_range_from_binary_expr (value_range_base *vr,
 	      vr->set (VR_RANGE, min, max);
 	    }
 	  else
-	    vr->set_varying ();
+	    vr->set_varying (expr_type);
 	  return;
 	}
       else if (code == BIT_IOR_EXPR)
@@ -2004,7 +2029,7 @@  extract_range_from_binary_expr (value_range_base *vr,
 	      vr->set (VR_RANGE, min, max);
 	    }
 	  else
-	    vr->set_varying ();
+	    vr->set_varying (expr_type);
 	  return;
 	}
       else if (code == BIT_XOR_EXPR)
@@ -2020,7 +2045,7 @@  extract_range_from_binary_expr (value_range_base *vr,
 	      vr->set (VR_RANGE, min, max);
 	    }
 	  else
-	    vr->set_varying ();
+	    vr->set_varying (expr_type);
 	  return;
 	}
     }
@@ -2034,7 +2059,7 @@  extract_range_from_binary_expr (value_range_base *vr,
       || max == NULL_TREE
       || TREE_OVERFLOW_P (max))
     {
-      vr->set_varying ();
+      vr->set_varying (expr_type);
       return;
     }
 
@@ -2043,7 +2068,7 @@  extract_range_from_binary_expr (value_range_base *vr,
      Note that we do accept [-INF, -INF] and [+INF, +INF].  */
   if (vrp_val_is_min (min) && vrp_val_is_max (max))
     {
-      vr->set_varying ();
+      vr->set_varying (expr_type);
       return;
     }
 
@@ -2053,7 +2078,7 @@  extract_range_from_binary_expr (value_range_base *vr,
       /* If the new range has its limits swapped around (MIN > MAX),
 	 then the operation caused one of them to wrap around, mark
 	 the new range VARYING.  */
-      vr->set_varying ();
+      vr->set_varying (expr_type);
     }
   else
     vr->set (type, min, max);
@@ -2079,7 +2104,7 @@  extract_range_from_unary_expr (value_range_base *vr,
       || !(INTEGRAL_TYPE_P (type)
 	   || POINTER_TYPE_P (type)))
     {
-      vr->set_varying ();
+      vr->set_varying (type);
       return;
     }
 
@@ -2151,7 +2176,7 @@  extract_range_from_unary_expr (value_range_base *vr,
 	  else if (vr0.zero_p ())
 	    vr->set_zero (type);
 	  else
-	    vr->set_varying ();
+	    vr->set_varying (type);
 	  return;
 	}
 
@@ -2185,7 +2210,7 @@  extract_range_from_unary_expr (value_range_base *vr,
 	  vr->set (VR_RANGE, min, max);
 	}
       else
-	vr->set_varying ();
+	vr->set_varying (outer_type);
       return;
     }
   else if (code == ABS_EXPR)
@@ -2198,7 +2223,7 @@  extract_range_from_unary_expr (value_range_base *vr,
 	vr->set (VR_RANGE, wide_int_to_tree (type, wmin),
 		 wide_int_to_tree (type, wmax));
       else
-	vr->set_varying ();
+	vr->set_varying (type);
       return;
     }
   else if (code == ABSU_EXPR)
@@ -2214,7 +2239,7 @@  extract_range_from_unary_expr (value_range_base *vr,
     }
 
   /* For unhandled operations fall back to varying.  */
-  vr->set_varying ();
+  vr->set_varying (type);
   return;
 }
 
@@ -5210,7 +5235,8 @@  vrp_prop::vrp_initialize ()
 	  if (!stmt_interesting_for_vrp (phi))
 	    {
 	      tree lhs = PHI_RESULT (phi);
-	      get_value_range (lhs)->set_varying ();
+	      if (value_range_base::supports_type_p (TREE_TYPE (lhs)))
+		get_value_range (lhs)->set_varying (TREE_TYPE (lhs));
 	      prop_set_simulate_again (phi, false);
 	    }
 	  else
@@ -5405,7 +5431,8 @@  vrp_prop::visit_stmt (gimple *stmt, edge *taken_edge_p, tree *output_p)
 	    use_operand_p use_p;
 	    enum ssa_prop_result res = SSA_PROP_VARYING;
 
-	    get_value_range (lhs)->set_varying ();
+	    if (value_range_base::supports_type_p (TREE_TYPE (lhs)))
+	      get_value_range (lhs)->set_varying (TREE_TYPE (lhs));
 
 	    FOR_EACH_IMM_USE_FAST (use_p, iter, lhs)
 	      {
@@ -6090,7 +6117,12 @@  value_range_base::intersect_helper (const value_range_base *vr0,
      VR_RANGE can still be a VR_RANGE.  Work on a temporary so we can
      fall back to vr0 when this turns things to varying.  */
   value_range_base tem;
-  tem.set (vr0type, vr0min, vr0max);
+  if (vr0type == VR_UNDEFINED)
+    tem.set_undefined ();
+  else if (vr0type == VR_VARYING)
+    tem.set_varying (vr0->type ());
+  else
+    tem.set (vr0type, vr0min, vr0max);
   /* If that failed, use the saved original VR0.  */
   if (tem.varying_p ())
     return *vr0;
@@ -6195,7 +6227,12 @@  value_range_base::union_helper (const value_range_base *vr0,
 
   /* Work on a temporary so we can still use vr0 when union returns varying.  */
   value_range_base tem;
-  tem.set (vr0type, vr0min, vr0max);
+  if (vr0type == VR_UNDEFINED)
+    tem.set_undefined ();
+  else if (vr0type == VR_VARYING)
+    tem.set_varying (vr0->type ());
+  else
+    tem.set (vr0type, vr0min, vr0max);
 
   /* Failed to find an efficient meet.  Before giving up and setting
      the result to VARYING, see if we can at least derive a useful
@@ -6292,7 +6329,7 @@  value_range_base::normalize_symbolics () const
   if (min_symbolic && max_symbolic)
     {
       value_range_base var;
-      var.set_varying ();
+      var.set_varying (ttype);
       return var;
     }
   if (kind () == VR_RANGE)
@@ -6313,7 +6350,7 @@  value_range_base::normalize_symbolics () const
 	  return value_range_base (VR_RANGE, n, vrp_val_max (ttype));
 	}
       value_range_base var;
-      var.set_varying ();
+      var.set_varying (ttype);
       return var;
     }
   // ~[NUM, SYM] -> [-MIN, NUM - 1]
@@ -6323,7 +6360,7 @@  value_range_base::normalize_symbolics () const
       return value_range_base (VR_RANGE, vrp_val_min (ttype), n);
     }
   value_range_base var;
-  var.set_varying ();
+  var.set_varying (ttype);
   return var;
 }
 
@@ -7000,7 +7037,7 @@  determine_value_range_1 (value_range_base *vr, tree expr)
 	vr->set (kind, wide_int_to_tree (TREE_TYPE (expr), min),
 		 wide_int_to_tree (TREE_TYPE (expr), max));
       else
-	vr->set_varying ();
+	vr->set_varying (TREE_TYPE (expr));
     }
 }
 
diff --git a/gcc/tree-vrp.h b/gcc/tree-vrp.h
index b5830851fcb..c879a8c6df8 100644
--- a/gcc/tree-vrp.h
+++ b/gcc/tree-vrp.h
@@ -58,7 +58,7 @@  public:
   bool constant_p () const;
   bool undefined_p () const;
   bool varying_p () const;
-  void set_varying ();
+  void set_varying (tree type);
   void set_undefined ();
 
   void union_ (const value_range_base *);
@@ -75,7 +75,9 @@  public:
   bool nonzero_p () const;
   bool singleton_p (tree *result = NULL) const;
   void dump (FILE *) const;
+  void dump () const;
 
+  static bool supports_type_p (tree);
   value_range_base normalize_symbolics () const;
 
 protected:
@@ -135,7 +137,7 @@  class GTY((user)) value_range : public value_range_base
 
   /* Types of value ranges.  */
   void set_undefined ();
-  void set_varying ();
+  void set_varying (tree);
 
   /* Equivalence bitmap methods.  */
   bitmap equiv () const;
@@ -145,6 +147,7 @@  class GTY((user)) value_range : public value_range_base
   /* Misc methods.  */
   void deep_copy (const value_range *);
   void dump (FILE *) const;
+  void dump () const;
 
  private:
   /* Deep-copies bitmap argument.  */
@@ -254,6 +257,17 @@  struct assert_info
   tree expr;
 };
 
+// Return true if TYPE is a valid type for value_range to operate on.
+// Otherwise return FALSE.
+
+inline bool
+value_range_base::supports_type_p (tree type)
+{
+  if (type && (INTEGRAL_TYPE_P (type) || POINTER_TYPE_P (type)))
+    return type;
+  return NULL;
+}
+
 extern void register_edge_assert_for (tree, edge, enum tree_code,
 				      tree, tree, vec<assert_info> &);
 extern bool stmt_interesting_for_vrp (gimple *);
diff --git a/gcc/vr-values.c b/gcc/vr-values.c
index 10789bdd64e..e2829ae985f 100644
--- a/gcc/vr-values.c
+++ b/gcc/vr-values.c
@@ -64,7 +64,7 @@  static inline void
 set_value_range_to_truthvalue (value_range *vr, tree type)
 {
   if (TYPE_PRECISION (type) == 1)
-    vr->set_varying ();
+    vr->set_varying (type);
   else
     vr->update (VR_RANGE, build_int_cst (type, 0), build_int_cst (type, 1));
 }
@@ -78,7 +78,6 @@  set_value_range_to_truthvalue (value_range *vr, tree type)
 value_range *
 vr_values::get_value_range (const_tree var)
 {
-  static const value_range vr_const_varying (VR_VARYING, NULL, NULL);
   value_range *vr;
   tree sym;
   unsigned ver = SSA_NAME_VERSION (var);
@@ -91,18 +90,35 @@  vr_values::get_value_range (const_tree var)
      We should get here at most from the substitute-and-fold stage which
      will never try to change values.  */
   if (ver >= num_vr_values)
-    return CONST_CAST (value_range *, &vr_const_varying);
+    {
+      unsigned int old_sz = num_vr_values;
+      num_vr_values = num_ssa_names + num_ssa_names / 10;
+      vr_value = XRESIZEVEC (value_range *, vr_value, num_vr_values);
+      for ( ; old_sz < num_vr_values; old_sz++)
+        vr_value [old_sz] = NULL;
+    }
 
   vr = vr_value[ver];
   if (vr)
     return vr;
 
-  /* After propagation finished do not allocate new value-ranges.  */
-  if (values_propagated)
-    return CONST_CAST (value_range *, &vr_const_varying);
 
   /* Create a default value range.  */
   vr_value[ver] = vr = vrp_value_range_pool.allocate ();
+
+  if (!value_range_base::supports_type_p (TREE_TYPE (var)))
+    {
+      vr->set_undefined ();
+      return vr;
+    }
+
+  /* After propagation finished return varying.  */
+  if (values_propagated)
+    {
+      vr->set_varying (TREE_TYPE (var));
+      return vr;
+    }
+
   vr->set_undefined ();
 
   /* If VAR is a default definition of a parameter, the variable can
@@ -126,10 +142,10 @@  vr_values::get_value_range (const_tree var)
 	    {
 	      get_range_info (var, *vr);
 	      if (vr->undefined_p ())
-		vr->set_varying ();
+		vr->set_varying (TREE_TYPE (sym));
 	    }
 	  else
-	    vr->set_varying ();
+	    vr->set_varying (TREE_TYPE (sym));
 	}
       else if (TREE_CODE (sym) == RESULT_DECL
 	       && DECL_BY_REFERENCE (sym))
@@ -150,12 +166,11 @@  vr_values::set_defs_to_varying (gimple *stmt)
   ssa_op_iter i;
   tree def;
   FOR_EACH_SSA_TREE_OPERAND (def, stmt, i, SSA_OP_DEF)
-    {
-      value_range *vr = get_value_range (def);
-      /* Avoid writing to vr_const_varying get_value_range may return.  */
-      if (!vr->varying_p ())
-	vr->set_varying ();
-    }
+    if (value_range_base::supports_type_p (TREE_TYPE (def)))
+      {
+	value_range *vr = get_value_range (def);
+	vr->set_varying (TREE_TYPE (def));
+      }
 }
 
 /* Update the value range and equivalence set for variable VAR to
@@ -198,13 +213,13 @@  vr_values::update_value_range (const_tree var, value_range *new_vr)
 	 called, if we are anyway, keep it VARYING.  */
       if (old_vr->varying_p ())
 	{
-	  new_vr->set_varying ();
+	  new_vr->set_varying (new_vr->type ());
 	  is_new = false;
 	}
       else if (new_vr->undefined_p ())
 	{
-	  old_vr->set_varying ();
-	  new_vr->set_varying ();
+	  old_vr->set_varying (TREE_TYPE (var));
+	  new_vr->set_varying (TREE_TYPE (var));
 	  return true;
 	}
       else
@@ -435,7 +450,7 @@  vr_values::extract_range_for_var_from_comparison_expr (tree var,
   if ((POINTER_TYPE_P (type) && cond_code != NE_EXPR && cond_code != EQ_EXPR)
       || limit == var)
     {
-      vr_p->set_varying ();
+      vr_p->set_varying (type);
       return;
     }
 
@@ -595,7 +610,7 @@  vr_values::extract_range_for_var_from_comparison_expr (tree var,
 	 all should be optimized away above us.  */
       if (cond_code == LT_EXPR
 	  && compare_values (max, min) == 0)
-	vr_p->set_varying ();
+	vr_p->set_varying (TREE_TYPE (min));
       else
 	{
 	  /* For LT_EXPR, we create the range [MIN, MAX - 1].  */
@@ -635,7 +650,7 @@  vr_values::extract_range_for_var_from_comparison_expr (tree var,
 	 all should be optimized away above us.  */
       if (cond_code == GT_EXPR
 	  && compare_values (min, max) == 0)
-	vr_p->set_varying ();
+	vr_p->set_varying (TREE_TYPE (min));
       else
 	{
 	  /* For GT_EXPR, we create the range [MIN + 1, MAX].  */
@@ -743,14 +758,14 @@  vr_values::extract_range_from_binary_expr (value_range *vr,
   else if (is_gimple_min_invariant (op0))
     vr0.set (op0);
   else
-    vr0.set_varying ();
+    vr0.set_varying (TREE_TYPE (op0));
 
   if (TREE_CODE (op1) == SSA_NAME)
     vr1 = *(get_value_range (op1));
   else if (is_gimple_min_invariant (op1))
     vr1.set (op1);
   else
-    vr1.set_varying ();
+    vr1.set_varying (TREE_TYPE (op1));
 
   /* If one argument is varying, we can sometimes still deduce a
      range for the output: any + [3, +INF] is in [MIN+3, +INF].  */
@@ -891,7 +906,7 @@  vr_values::extract_range_from_unary_expr (value_range *vr, enum tree_code code,
   else if (is_gimple_min_invariant (op0))
     vr0.set (op0);
   else
-    vr0.set_varying ();
+    vr0.set_varying (type);
 
   ::extract_range_from_unary_expr (vr, code, type, &vr0, TREE_TYPE (op0));
 }
@@ -913,7 +928,7 @@  vr_values::extract_range_from_cond_expr (value_range *vr, gassign *stmt)
   else if (is_gimple_min_invariant (op0))
     tem0.set (op0);
   else
-    tem0.set_varying ();
+    tem0.set_varying (TREE_TYPE (op0));
 
   tree op1 = gimple_assign_rhs3 (stmt);
   value_range tem1;
@@ -923,7 +938,7 @@  vr_values::extract_range_from_cond_expr (value_range *vr, gassign *stmt)
   else if (is_gimple_min_invariant (op1))
     tem1.set (op1);
   else
-    tem1.set_varying ();
+    tem1.set_varying (TREE_TYPE (op1));
 
   /* The resulting value range is the union of the operand ranges */
   vr->deep_copy (vr0);
@@ -975,14 +990,14 @@  vr_values::check_for_binary_op_overflow (enum tree_code subcode, tree type,
   else if (TREE_CODE (op0) == INTEGER_CST)
     vr0.set (op0);
   else
-    vr0.set_varying ();
+    vr0.set_varying (TREE_TYPE (op0));
 
   if (TREE_CODE (op1) == SSA_NAME)
     vr1 = *get_value_range (op1);
   else if (TREE_CODE (op1) == INTEGER_CST)
     vr1.set (op1);
   else
-    vr1.set_varying ();
+    vr1.set_varying (TREE_TYPE (op1));
 
   tree vr0min = vr0.min (), vr0max = vr0.max ();
   tree vr1min = vr1.min (), vr1max = vr1.max ();
@@ -1310,7 +1325,7 @@  vr_values::extract_range_basic (value_range *vr, gimple *stmt)
 	  if (vr->kind () == VR_RANGE
 	      && (vr->min () == vr->max ()
 		  || operand_equal_p (vr->min (), vr->max (), 0)))
-	    vr->set_varying ();
+	    vr->set_varying (vr->type ());
 	  return;
 	}
     }
@@ -1366,7 +1381,7 @@  vr_values::extract_range_basic (value_range *vr, gimple *stmt)
 			vr->set (build_int_cst (type, ovf));
 		      else if (TYPE_PRECISION (type) == 1
 			       && !TYPE_UNSIGNED (type))
-			vr->set_varying ();
+			vr->set_varying (type);
 		      else
 			vr->set (VR_RANGE, build_int_cst (type, 0),
 				 build_int_cst (type, 1));
@@ -1411,7 +1426,7 @@  vr_values::extract_range_basic (value_range *vr, gimple *stmt)
       vr->equiv_clear ();
     }
   else
-    vr->set_varying ();
+    vr->set_varying (type);
 }
 
 
@@ -1447,7 +1462,7 @@  vr_values::extract_range_from_assignment (value_range *vr, gassign *stmt)
 	   && is_gimple_min_invariant (gimple_assign_rhs1 (stmt)))
     vr->set (gimple_assign_rhs1 (stmt));
   else
-    vr->set_varying ();
+    vr->set_varying (TREE_TYPE (gimple_assign_lhs (stmt)));
 
   if (vr->varying_p ())
     extract_range_basic (vr, stmt);
@@ -1920,7 +1935,7 @@  vr_values::dump_all_value_ranges (FILE *file)
 vr_values::vr_values () : vrp_value_range_pool ("Tree VRP value ranges")
 {
   values_propagated = false;
-  num_vr_values = num_ssa_names;
+  num_vr_values = num_ssa_names + num_ssa_names / 10;
   vr_value = XCNEWVEC (value_range *, num_vr_values);
   vr_phi_edge_counts = XCNEWVEC (int, num_ssa_names);
   bitmap_obstack_initialize (&vrp_equiv_obstack);
@@ -2856,7 +2871,7 @@  vr_values::extract_range_from_phi_node (gphi *phi, value_range *vr_result)
 		      vr_arg_tem.set (vr_arg_->kind (), vr_arg_->min (),
 				      vr_arg_->max (), NULL);
 		      if (vr_arg_tem.symbolic_p ())
-			vr_arg_tem.set_varying ();
+			vr_arg_tem.set_varying (TREE_TYPE (arg));
 		    }
 		  else
 		    vr_arg = vr_arg_;
@@ -2978,7 +2993,7 @@  vr_values::extract_range_from_phi_node (gphi *phi, value_range *vr_result)
   goto update_range;
 
 varying:
-  vr_result->set_varying ();
+  vr_result->set_varying (TREE_TYPE (lhs));
 
 scev_check:
   /* If this is a loop PHI node SCEV may known more about its value-range.
@@ -2999,7 +3014,7 @@  infinite_check:
 	   || compare_values (vr_result->min (), vr_result->max ()) > 0))
     ;
   else
-    vr_result->set_varying ();
+    vr_result->set_varying (TREE_TYPE (lhs));
 
   /* If the new range is different than the previous value, keep
      iterating.  */