I have gcc-4.1 configured with ../gcc-4.1.0/configure --prefix=/usr --libexecdir=/usr/lib --enable-shared --enable-threads=posix --enable-__cxa_atexit --enable-c99 --enable-long-long --enable-clocale=gnu --enable-languages=c,c++ --disable-multilib --disable-libstdcxx-pch The following test generates the checksum of a dummy sun disk label. cat > test.c << "EOF" #include <stddef.h> #include <stdio.h> #include <string.h> #include <stdlib.h> typedef unsigned short __be16; typedef unsigned int __be32; struct sun_disklabel { unsigned char info[128]; /* Informative text string */ unsigned char spare0[14]; struct sun_info { unsigned char spare1; unsigned char id; unsigned char spare2; unsigned char flags; } infos[8]; unsigned char spare[246]; /* Boot information etc. */ __be16 rspeed; /* Disk rotational speed */ __be16 pcylcount; /* Physical cylinder count */ __be16 sparecyl; /* extra sects per cylinder */ unsigned char spare2[4]; /* More magic... */ __be16 ilfact; /* Interleave factor */ __be16 ncyl; /* Data cylinder count */ __be16 nacyl; /* Alt. cylinder count */ __be16 ntrks; /* Tracks per cylinder */ __be16 nsect; /* Sectors per track */ unsigned char spare3[4]; /* Even more magic... */ struct sun_partition { __be32 start_cylinder; __be32 num_sectors; } partitions[8]; __be16 magic; /* Magic number */ __be16 csum; /* Label xor'd checksum */ }; int main(void) { struct sun_disklabel label; __be16 csum, *ush; memset(&label, 0xff, sizeof(label)); ush = ((__be16 *) (&label + 1)) - 1; for (csum = 0; ush >= ((__be16 *) &label); ) csum ^= *ush--; printf("Test checksum is %x\n", csum); exit(0); } EOF When this test is compiled with 'gcc test.c' or 'gcc -Os test.c' the checksum is 0. The checksum is supposed to be 0. When the test is compiled with 'gcc -O2 test.c' the checksum is 0xffff. The same goes for -O1 and -O3. Compiling with -Wall doesn't ouput any warnings. The last known version to work is gcc-4.0.2. As far as I know the problem is in this loop: for (csum = 0; ush >= ((__be16 *) &label); ) The problem also exists if the loop is changed to this: while (ush >= ((__be16 *) &label))
Created attachment 11276 [details] The test case source
Created attachment 11277 [details] The .i file from gcc -O2 test.c
Created attachment 11278 [details] The .i file from gcc -Os test.c
ush = ((__be16 *) (&label + 1)) - 1; That is undefined code (at least with strict aliasing turned on). But that should not have an effect at -O1.
Confirmed. Number of iteration analysis concludes the loop ush_4 = label.23_3 + 510B; if (label.23_3 <= ush_4) goto <L6>; else goto <L2>; <L6>:; # ush_16 = PHI <ush_10(3), ush_4(1)>; # csum_14 = PHI <csum_9(3), 0(1)>; <L0>:; # VUSE <label_12>; D.2866_8 = *ush_16; csum_9 = D.2866_8 ^ csum_14; ush_10 = ush_16 - 2B; if (label.23_3 <= ush_10) goto <L8>; else goto <L9>; <L8>:; goto <bb 2> (<L0>); runs once: (.t75.ivcanon) (set_nb_iterations_in_loop = 1B)) Loop 1 iterates 0B times. Unrolled loop 1 completely. and the loop is gone. I guess its some signedness problem again: (add_to_evolution (loop_nb = 1) (chrec_before = ush_4) (to_add = 2B) (res = {ush_4, +, -2B}_1)) (evolution_function = {ush_4, +, -2B}_1)) (set_scalar_evolution (scalar = ush_16) (scalar_evolution = {ush_4, +, -2B}_1)) ) (analyze_scalar_evolution (loop_nb = 1) (scalar = 2B) (get_scalar_evolution (scalar = 2B) (scalar_evolution = 2B)) ) (set_scalar_evolution (scalar = ush_10) (scalar_evolution = {ush_4 - 2B, +, -2B}_1)) )
This is a dup of PR26763, which is fixed for 4.1.1. *** This bug has been marked as a duplicate of 26763 ***