------- Additional Comments From sebastian dot pop at cri dot ensmp dot fr  
2005-07-27 09:01 -------
Subject: Re:  [4.1 Regression] wrong code for casts and scev

dberlin at dberlin dot org wrote:
> > A sequence of unsigned char 1, 2, ..., 255 has to be converted to
> > signed char that would wrap with -fwrapv: 1, 2, ..., 127, -128, ...
> > So here is a patch that keeps the cast if the sequence wraps. 
> 
> You mean keep the cast at all, or keep it in the evolution describing
> the number of iterations in the loop.
> 

Sorry for not being clear.  When chrec_convert fails, it simply
returns fold_convert (type, chrec), and because the folder does not
know about the chrecs at all it just returns a convert_expr 
(outer_type) {(inner_type)x, +, (inner_type)y}.

> If you mean keep it in the number of iterations of the loop, that seems
> wrong:
> 
> 
> Let's look at the case again
> void abort(void);
> 
> static inline void
> foo (signed char a)
> {
>   int b = a - 0x7F;
>   if (b > 1)
>     abort();
> }
> 
> int main()
> {
>   unsigned char b;
>   for(b = 0;b <0xFF;b++)
>    foo (b);
> }
> 
> Note that foo doesn't *actually* change the value of the passed in parameter.
> The loop still iterates 0xFF times.
> 
> Why is the cast affecting the number of iterations in the loop at all?
> We should still calculate the number of iterations to be 255 in any case.
> 

Once inlined, you have a loop with two exits: the first is the natural
exit after 255 iterations, the second is a jump outside the loop to a
bb that contains the abort function.  

If we have an evolution {(signed char) 0, +, (signed char) 1} - 127
can be folded to {(schar) -127, +, (schar) 1}, and the loop exit
guarded by the "if (b > 1)" becomes true for iteration 128.

So, there are two exits: the first one exits after 255 iterations the
second one exits after 128, and niter takes the minimum between these
two estimations, that is 128.

Now the failing step is that it is not possible to convert the
unsigned sequence {0, +, 1} that stands for 0, 1, ..., 255, into the
signed sequence {0, +, 1} that stands for 0, 1, ..., 127.  Here, a
part of the sequence has been lost in the translation.  

The solution here is to keep the cast around the first sequence:
(schar) {(uchar)0, +, (uchar)1}.  This is always safe with both
wrapping and non-wrapping semantics.

> also,
> 
> in *all* of the vectorizer testcases, number_of_iterations_in_loop should be 
> determined to be "n", an int.
> 
> The code in those cases provably doesn't wrap (signed integer arithmetic 
> doesn't wrap without -fwrapv), 
> So why do we think it should wrap, when it's not casted at all?
> 

The scev_probably_wraps_p analyzer is still too weak for infering that
the sequences used by the vectorizer don't wrap.

Let's take the example from vect-77.c

  D.2035_21 = offD.2023_11 + iD.2026_30;
  D.2036_22 = (long unsigned intD.4) D.2035_21;
  D.2037_23 = D.2036_22 * 4;
  D.2038_24 = (aintD.2020 *) D.2037_23;
  D.2039_25 = ibD.2022_16 + D.2038_24;

because you have this cast to unsigned and then the multiplication by
4 and an unknown initial value off_11, even if you know that the main
index i_30 doesn't wrap, you still can chose an offset large enough
for making D.2037_23 wrap.  So we need some extra information about
the range of offset if we want to convert the scev of D.2035_21.

For the moment this is the point where the analyzer fails to properly
convert the scev, and produces:

(set_scalar_evolution 
  (scalar = D.2036_22)
  (scalar_evolution = (long unsigned int) {off_11, +, 1}_1))

Is it possible to assume that a variable converted to a pointer type
does not wrap? As in: D.2038_24 = (aintD.2020 *) D.2037_23;



-- 


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

Reply via email to