fix rtl/23560

Eric Botcazou ebotcazou@libertysurf.fr
Fri Aug 11 17:25:00 GMT 2006


Hi Richard,

> Yet another rtl strength reduction bug.
>
> This time, ivopts transforms the loop and creates an unsigned counter
> that runs from -7u to +7u.  Odd, but certainly legal.  In the middle,
> there's a conditional that's transformed from (i == 8 || i == 9) to
> (ivtmp <= 1).  Also fine.
>
> Well, rtl-loop comes along and tries to eliminate the ivtmp biv with
> a giv that's a pointer value.  Except after the transformation to the
> giv, the LEU comparison is incorrect.

I've run into another variant (PR rtl-optimization/28386): ivtmp runs from 
-127u to 127u and the test is ivtmp <= 127u:

  unsigned int ivtmp.34;
  int D.1323;
  char D.1324;
  int j;
  char a;

<bb 0>:
  a = g;
  j = 0;
  ivtmp.34 = 0ffffff81;

<L3>:;
  if (ivtmp.34 <= 127) goto <L4>; else goto <L5>;

<L4>:;
  D.1323 = (int) ivtmp.34;
  D.1324 = s[D.1323][0];
  a = (char) (int) D.1324;
  j = j + 1;

<L5>:;
  ivtmp.34 = ivtmp.34 + 1;
  if (ivtmp.34 != 128) goto <L3>; else goto <L12>;

> Solved by not allowing this transformation unless the biv can be shown
> to not wrap.

That matches the comment in the code:

      /* Unless we're dealing with an equality comparison, if we can't
	 determine that the original biv doesn't wrap, then we must not
	 apply the transformation.  */
      /* ??? Actually, what we must do is verify that the transformed
	 giv doesn't wrap.  But the general case of this transformation
	 was disabled long ago due to wrapping problems, and there's no
	 point reviving it this close to end-of-life for loop.c.  The
	 only case still enabled is known (via the check on add_val) to
	 be pointer arithmetic, which in theory never overflows for
	 valid programs.  */

But that doesn't match the code:

    case COMPARE:
    case EQ:  case NE:
    case GT:  case GE:  case GTU:  case GEU:
    case LT:  case LE:  case LTU:  case LEU:
      /* See if either argument is the biv.  */
      if (XEXP (x, 0) == reg)
	arg = XEXP (x, 1), arg_operand = 1;
      else if (XEXP (x, 1) == reg)
	arg = XEXP (x, 0), arg_operand = 0;
      else
	break;

      if (code != EQ && code != NE
	  && biased_biv_may_wrap_p (loop, bl, INTVAL (arg)))
	return 0;

The code tests that the biased biv doesn't wrap, which is true in my case so 
the biv is wrongly eliminated to a non-wrapping pointer giv.

I think this illustrates that the bias doesn't play any role in the matter: a 
biv that wraps cannot be eliminated if it is subject to any comparisons other 
than equality or inequality because the wrapping threshold cannot be shifted.

What do you think?  Thanks in advance.

-- 
Eric Botcazou



More information about the Gcc-patches mailing list