------- Comment #2 from kazu at gcc dot gnu dot org 2006-05-20 04:57 ------- The whole problem is reduced to the combiner doing wrong simplification of XOR. Here are some details.
Consider: extern void abort (void) __attribute__ ((noreturn)); extern void exit (int) __attribute__ ((noreturn)); static int __attribute__((noinline)) foo (int a, int b) { int c = a ^ b; if (c == a) abort (); } int main (void) { foo (0, 1); exit (0); } Note that c == a <==> a ^ b == a <==> b == 0 So foo aborts if and only if b == 0. In the above testcase, b gets 1, so foo shouldn't abort, but it does. The combiner tries to combine the following two insns. (I'm omitting clobbers for brevity.) (set (reg:SI 61) (xor:SI (reg/v:SI 60 [ b ]) (reg/v:SI 59 [ a ]))) (set (reg:CCZ 17 flags) (compare:CCZ (reg:SI 61) (reg/v:SI 59 [ a ]))) The combiner produces (set (reg:CCZ 17 flags) (compare:CCZ (reg/v:SI 59 [ a ]) (const_int 0 [0x0]))) Note that this is wrong. What matters is whether b is 0 or not. Once the problem is reduced to this level, -march=pentium4 is no longer needed. Is is just that with -march=pentium4, "k % 2" is expanded using XOR. -- http://gcc.gnu.org/bugzilla/show_bug.cgi?id=27671