------- 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