------- Comment #3 from reza dot yazdani at amd dot com  2010-03-04 18:37 
-------
I reduced the test to:
--------------------------
extern void abort (void);

__attribute__ ((noinline)) int
foo (int *zzz, unsigned int kk)
{
  int a, b, d;

  a = b = 0;
  for (d = 0; d < 1000; d++)
    {
      if (kk != 0)
        b = *zzz;
    }

  return b;
}

int
main (void)
{
  if (foo (0, 0) != 0)
    abort();
  return 0;
}
---------------------------
gcc tries to move an invariant unsigned test out of the loop. The following
three guarded loops are generated in the function "insert_guard(..)" in the
file "clast.c".

if (T_7 <= -1) {
  for (scat_1=0;scat_1<=999;scat_1++) {
    S3(scat_1) ;
    S4(scat_1) ;
    S5(scat_1) ;
  }
}
if (T_7 >= 1) {
  for (scat_1=0;scat_1<=999;scat_1++) {
    S3(scat_1) ;
    S4(scat_1) ;
    S5(scat_1) ;
  }
}
if (T_7 == 0) {
  for (scat_1=0;scat_1<=999;scat_1++) {
    S3(scat_1) ;
    S5(scat_1) ;
  }
}
S7() ;
$49 = void

kk is an "unsigned int" in the test program in the guard expression (kk != 0).
The T_7 represents kk in the above expressions. As kk is unsigned T_7 <= -1 is
always true and the dereference of the pointer (*zzz) is executed
unconditionally which causes the seg. fault. If the type of kk is changed to
signed, the correct code is generated.

I think, as unsigned expressions are bounded from one side, there must be a
constrain in insert_guard(..) that if the guard is unsigned, only the last two
cases should be generated.


-- 

reza dot yazdani at amd dot com changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
                 CC|                            |reza dot yazdani at amd dot
                   |                            |com


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

Reply via email to