On 9/11/26 4:19 PM, Michiel Derhaeg wrote:
From: Loeka Rogge <[email protected]>

The clmul-based reversed crc expansion multiplies by the reflected
polynomial shifted left by one.  For a 32-bit crc on rv32 that operand
is 33 bits wide and does not fit in a register, so rv32 fell back to the
table based expansion.

clmulr produces bits 2*xlen-2:xlen-1 of the carry-less product, which is
what clmulh produces from an operand that is already shifted left by one:

   clmulh (a, ref_poly << 1) = (a * ref_poly)[62:31] = clmulr (a, ref_poly)

so the shift can be dropped and the unshifted 32-bit reflected polynomial
handed to clmulr instead.

The Linux kernel uses the same identity in crc32_le_zbc(),
arch/riscv/lib/crc32.c (since moved to lib/crc/riscv/):

        /* We don't have a "clmulrh" insn, so use clmul + slli instead. */
        asm volatile (".option push\n"
                      ".option arch,+zbc\n"
                      "clmul       %0, %1, %2\n"
                      "slli        %0, %0, 1\n"
                      "xor %0, %0, %1\n"
                      "clmulr      %0, %0, %3\n"
                      ".option pop\n"
                      : "=&r" (crc)
                      : "r" (s), "r" (poly_qt), "r" (poly) :);

__builtin_rev_crc32_data32 (crc, data, 0x04C11DB7) on rv32_zbc now
generates:

        li      a5,305479680
        addi    t0,a5,1791
        li      a4,-150925312
        xor     t1,a0,t0
        addi    t2,a4,1601
        clmul   a1,t1,t2
        li      a0,-306675712
        addi    a2,a0,800
        clmulr  a0,a1,a2

Regtested for rv32gc and rv64gc.

gcc/ChangeLog:

        * config/riscv/bitmanip.md (crc_rev<ANYI1:mode><ANYI:mode>4):
        Use the clmul expansion for a word-sized crc on rv32 with Zbc.
        * config/riscv/riscv.cc (expand_reversed_crc_using_clmul): Use
        clmulr with the unshifted reflected polynomial when the crc is
        word-sized.
        (riscv_optab_supported_p): Allow crc_rev for a word-sized result
        on rv32 with Zbc when optimizing for size.

gcc/testsuite/ChangeLog:

        * gcc.target/riscv/crc-builtin-zbc32.c: Add reversed crc32 tests.
This looks good, but it seems like it ought to also work for TARGET_64BIT.  So I'm puzzled why things are conditional on !TARGET_64BIT?

jeff

Reply via email to