This is the mail archive of the gcc-bugs@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[Bug ada/26348] [4.2 Regression] ICE compiling a-textio.adb at -O1 -ftree-vrp



------- Comment #8 from law at redhat dot com  2006-02-19 00:16 -------
Subject: Re:  [4.2 Regression] ICE compiling a-textio.adb at
        -O1 -ftree-vrp

On Sat, 2006-02-18 at 17:02 +0000, pinskia at gcc dot gnu dot org wrote:
> 
> ------- Comment #5 from pinskia at gcc dot gnu dot org  2006-02-18 17:02 -------
> Saw it too.
Ignore my last post about an initial theory.  It looks like 
some code, somewhere is goofing up types in a very unpleasant
way.  If I had to point a finger, I'd have to guess it's
somewhere in the Ada front-end and an Ada person is going to have
to look at this.  It's highly unlikely with my total lack of
knowledge about the Ada front-end that have any chance of fixing
it.

Our little odyssey starts with visiting this PHI node:

[ The first visit is uninteresting, ignore it.  I'm starting my
  analysis with the second visit. ]

lastD.2483_148 = PHI <lastD.2483_60(28), lastD.2483_15(14)>;

Only the edge from block #14 is executable, so the result of the
PHI will be equivalent to the current range for last_15.  The
range we record is [0, 0x7fffffff].

We then proceed to the uses of last_148.  One of which is:

lastD.2483_86 = lastD.2483_148 + 1;


Now for the first "oddity".  If we look at the underlying type
for last we have a type "natural___XDLU_0__2147483647".  What's
interesting about it is that it has a 32bit type precision, but
the min/max values only specify 31 bits.  ie, the min/max values
are 0, 0x7fffffff.

So anyway, we proceed to add the current range for last_148
[0, 0x7fffffff] to the constant 1.    This results in
[1, 0x80000000].  Second oddity.  This is clearly outside the
type's min/max values, but because the value is inside the
type's precision, no overflow is signaled and no bits are
zero'd out.

We then encounter this statement:

lastD.2483_60 = lastD.2483_86;

So we copy the current range for last_86 to last_60.  [1, 0x80000000]
which I'll note again is outside the min/max values associated with
last's type.

We now return to the PHI node:

lastD.2483_148 = PHI <lastD.2483_60(28), lastD.2483_15(14)>;

We still only have one edge (from block #14) marked executable,
so nothing interesting happens yet.

We then visit the PHI node a 4th time.  This time both edges are
marked as executable.  So we're going to have to meet the ranges
for last_60 [0x1, 0x80000000] and last_15 [0x0, 0x7fffffff].

Now with the range for last_60 being outside the type's min/max values
I don't think we can meaningfully merge these ranges.  We've clearly
gone off the reservation already, but just for fun let's see what 
happens.

The min value is computed as 0x0, which is exactly what we would
expect.  Nothing fun or interesting here.

What's fun is meeting the max values of 0x8000000 and 0x7fffffff.
vrp_meet returns 0x80000000 as the meet value.  OK, that's plausible,
I don't think vrp_meet tries to clamp values at min/max for the type.

We then fallinto this hunk of code:


3995      if (lhs_vr->type == VR_RANGE && vr_result.type == VR_RANGE)
3996        {
3997          if (!POINTER_TYPE_P (TREE_TYPE (lhs)))
3998            {
3999              int cmp_min = compare_values (lhs_vr->min,
vr_result.min);
4000              int cmp_max = compare_values (lhs_vr->max,
vr_result.max);
4001
4002              /* If the new minimum is smaller or larger than the
previous
4003                 one, go all the way to -INF.  In the first case, to
avoid
4004                 iterating millions of times to reach -INF, and in
the
(gdb) 
4005                 other case to avoid infinite bouncing between
different
4006                 minimums.  */
4007              if (cmp_min > 0 || cmp_min < 0)
4008                vr_result.min = TYPE_MIN_VALUE (TREE_TYPE
(vr_result.min));
4009
4010              /* Similarly, if the new maximum is smaller or larger
than
4011                 the previous one, go all the way to +INF.  */
4012              if (cmp_max < 0 || cmp_max > 0)
4013                vr_result.max = TYPE_MAX_VALUE (TREE_TYPE
(vr_result.max));
4014
(gdb) 
4015              /* If we ended up with a (-INF, +INF) range, set it to
4016                 VARYING.  */
4017              if (vr_result.min == TYPE_MIN_VALUE (TREE_TYPE
(vr_result.min))
4018                  && vr_result.max == TYPE_MAX_VALUE (TREE_TYPE
(vr_result.max)))
4019                goto varying;

lhs_vr->max is 0x7fffffff and vr_result->max is 0x80000000, so cmp_max
is -1.  Which indicates we should set a new maximum to be the maximum
for the type.  The maximum for the type is 0x7fffffff.  But just as
important, this ends up changing the underlying type for vr_result.max,
instead of being "natural___XDLU_0__2147483647" it's a more generic
integer type.  Ugh!  Now we go to update the range for the result
using update_value_range.  We determine the range is new, even though
the underlying values are unchanged because we're using pointer 
equality for all our tests (this is bad).

So we consider the PHI node's result as being new, so we re-simulate
the uses of the PHI result and we end up ping-ponging back and
forth betwen 0x7fffffff and 0x80000000 as its upper value due to
the type inconsistencies.  And and because of the pointer equality
tests in update_value_range we keep thinking we've got a new range
for the result of the PHI every time.  Net result is an infinite loop.

So what needs to be fixed.

First, the inconsistency between the type's precision in its min/max
values needs to be fixed.  Most likely this is an Ada FE problem.

Second, for a given integer type (such as natural___XDLU_0_2147483647,
the type for the nodes in TYPE_MIN_VALUE and TYPE_MAX_VALUE really
should be a natural___XDLU_0_2147483647.  ie, the type of an integer
constant should be the same as the type of its min/max values. 
Otherwise we're a lot more likely to ping pong because the
anti-ping-pong tests use pointer equality to check and see if
a range's type, min or max values have changed.    When an integer
type's min/max values are of a different type, we can think that
a value changed when in fact it did not change at all.

Again, both of these are issues an Ada maintainer is going to
need to look at in depth.

Jeff


-- 


http://gcc.gnu.org/bugzilla/show_bug.cgi?id=26348


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]