http://gcc.gnu.org/bugzilla/show_bug.cgi?id=46315
--- Comment #4 from Richard Guenther <rguenth at gcc dot gnu.org> 2010-11-12 14:56:54 UTC --- loop-header copying is where things start to be different. In the end the asm doesn't make much sense: parse_ranged.clone.0: .LFB2: .cfi_startproc leaq 2(%rdi), %rdx movq %rdi, %rax ... leal (%rdx,%rdx,4), %edx movb $2, %al leal (%rcx,%rdx,2), %edx .L2: testq %rax, %rax je .L7 cmpl $60, %edx movl $0, %edx cmovge %rdx, %rax ret so we might end up returning literal 2. Reduced testcase: static char const * parse_ranged (char const *s, int digits) { int n = 0; char const *lim = s + digits; while (s < lim) { unsigned d = *s++ - '0'; if (9 < d) return 0; n = 10 * n + d; } return s && 0 <= n && n <= 59 ? s : 0; } extern void abort (void); int main() { const char *s = "10092240"; s = parse_ranged (s, 2); s = parse_ranged (s, 2); s = parse_ranged (s, 2); s = parse_ranged (s, 2); if (!s || *s != '\0') abort(); return 0; }