http://gcc.gnu.org/bugzilla/show_bug.cgi?id=49942
--- Comment #5 from jphartmann at gmail dot com <jphartmann at gmail dot com> 2011-08-02 09:59:44 UTC --- Because the unoptimised code has a je at that place. And putting anything after the assignment generates correct code. And debug code after the loop shows that it falls through where it shouldn't. Maybe it will help to show the actual C rather than what comes out of the preprocessor, but this is the one that works. Remove the assignment to dummy and it fails: for (i = 0; NUMD - FUZZ > i; i++) { int diff = (0xff & op0->digits[i]) - (0xff & op1->digits[i]); DDDEBUG("i %d op %c op1 %c diff %d\n", i, op0->digits[i], op1->digits[i], diff); dummy = diff; /* cures a gcc bug */ if (diff) return '-' == op0->sign ? (0 < diff ? -1 : 1) : (0 > diff ? -1 : 1); } DDEBUG("Fell through. %s vs %s\n", op0->digits, op1->digits); The DDDEBUG is discarded by the preprocessor. FUZZ is 0 and NUMD is 9 in the case at hand. In the case at hand the leading digits are different; that may have a bearing since it looks like some of the loop is unrolled.