https://gcc.gnu.org/bugzilla/show_bug.cgi?id=121908
--- Comment #2 from Anton Blanchard <anton at ozlabs dot org> ---
I was looking at this loop because it's the reason LLVM on RISC-V outperforms
gcc on cpu2017 557.xz_r. An example:
uint32_t f(const uint8_t *pb, const uint8_t *cur, uint32_t len, uint32_t
len_limit)
{
while (++len != len_limit)
if (pb[len] != cur[len])
break;
return len;
}
What's interesting is that LLVM uses a strlen/strcpy style vector expansion,
checking for a page crossing and explicitly vectorizing it with a "bytecmp"
expansion:
addiw a5, a2, 1
bltu a3, a5, .LBB0_7
zext.w a6, a3
add.uw t0, a5, a0
add.uw a7, a5, a1
add a4, a0, a6
add t1, a1, a6
xor t0, t0, a4
xor a4, a7, t1
or a4, t0, a4
srli a4, a4, 12 <--- page crossing check
bnez a4, .LBB0_7
zext.w a2, a5
.LBB0_3:
sub a4, a6, a2
vsetvli a5, a4, e8, m2, ta, ma
add a4, a0, a2
vle8.v v8, (a4)
add a4, a1, a2
vle8.v v10, (a4)
vmsne.vv v12, v8, v10
vfirst.m a4, v12
srli a7, a4, 63
czero.nez t0, a4, a7
czero.eqz a4, a5, a7
or a7, a4, t0
sext.w a4, a7
bne a4, a5, .LBB0_6
add a2, a2, a5
bne a2, a6, .LBB0_3
mv a0, a3
ret
.LBB0_6:
addw a0, a7, a2
ret
I disabled this vectorization with -mllvm
-disable-loop-idiom-vectorize-bytecmp, and performance on our RISC-V CPU
(Ascalon) dropped 9.5%. I tried it also on Zen4 and it dropped 11%. Seems to be
worth it.