https://gcc.gnu.org/bugzilla/show_bug.cgi?id=21150
--- Comment #7 from Denis Vlasenko <vda.linux at googlemail dot com> ---
Fixed at least in 4.7.2, maybe earlier. With -m32 -fomit-frame-pointer -O2:
a: movzbl v+45, %eax
xorb v+36, %al
xorb v, %al
xorb v+54, %al
xorb v+63, %al
xorb v+9, %al
xorb v+18, %al
xorb v+27, %al
ret
b: movzbl v+18, %eax
xorb v+9, %al
xorb v, %al
xorb v+27, %al
xorb v+36, %al
xorb v+45, %al
xorb v+54, %al
xorb v+63, %al
ret
c: movzbl v+9, %eax
xorb v, %al
xorb v+18, %al
xorb v+27, %al
xorb v+36, %al
xorb v+45, %al
xorb v+54, %al
xorb v+63, %al
ret
d: movzbl v+18, %eax
xorb v+9, %al
xorb v, %al
xorb v+27, %al
xorb v+36, %al
xorb v+45, %al
xorb v+54, %al
xorb v+63, %al
ret
With same but -Os, my only complaint is that word-sized XORs are needlessly
adding partial register update stalls:
d: movb v+18, %al
xorb v+9, %al
xorl v, %eax
xorb v+27, %al
xorl v+36, %eax
xorb v+45, %al
xorb v+54, %al
xorb v+63, %al
ret
but overall it looks much better. Feel free to close this BZ.