https://gcc.gnu.org/bugzilla/show_bug.cgi?id=89112
--- Comment #3 from acsawdey at gcc dot gnu.org --- It appears that gcc decided to split the bdnzt generated by the memcmp expansion because the destination was out of range, and produced this: bdz $+12 beq 0,$+8 b $+8;b .L939 bne 0,.L937 ; --> to setb code So after the second iteration the bdz should branch to the bne which branches to a setb if there was a difference or falls through and does an overlapping compare to get the last 4 bytes of the 36 being compared. But the disassembly when I look at things in gdb has an extra branch in there which messes things up: 0x0000000010008b90 <constant+33360>: bdz 0x10008b9c <constant+33372> 0x0000000010008b94 <constant+33364>: beq 0x10008b9c <constant+33372> 0x0000000010008b98 <constant+33368>: b 0x10008ba0 <constant+33376> 0x0000000010008b9c <constant+33372>: b 0x10000b8c <constant+588> 0x0000000010008ba0 <constant+33376>: bne 0x10000bac <constant+620> So now the bdz branches to a branch to b8c which is back to the top of the loop to compare another 16 bytes which is of course wrong. It's possible this all happened because I didn't generate labels in the splitter, so multiple conditional branches had to be split because they were out of range.