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.

Reply via email to