On 9/9/26 3:00 AM, Sun Yuechi wrote:
addi+and keeps a 32 bit object sign extended on rv64, bclr does not:
clearing bit 31 leaves 0xffffffff00000000, so the loop
(m = x; m; m &= m - 1) never terminates.
A sext.w would fix that, but ctzw+bclr+sext.w is no shorter than
ctzw+addiw+and and one instruction deeper, so leave the 32 bit case
alone.
Wrong code since r16-3984-g4f01f39d021; it hangs rte_softrss() in DPDK
built with -march=rva23u64.
gcc/
* config/riscv/riscv-bclr-lowest-set-bit.cc
(pass_bclr_lowest_set_bit::execute): Skip a decrement wrapped in
a SIGN_EXTEND.
gcc/testsuite/
* gcc.target/riscv/bclr-lowest-set-bit-1.c: Expect addi+and for
the unsigned int cases on rv64.
* gcc.target/riscv/bclr-lowest-set-bit-2.c: New test.
Signed-off-by: Sun Yuechi <[email protected]>
---
v2: skip the SIGN_EXTEND case instead of extending the result, and
update bclr-lowest-set-bit-1.c for rv64.
Regtested on riscv64-linux-gnu (16.1.0 tree), no regressions.
So I was looking at this in more detail today. The more I look at it,
the more I think that supporting the form with addiw just isn't going to
work.
You've already show the code as-is is buggy. But the explicit sign
extension approach doesn't work either. The key is we have to preserve
the semantics of that DI mode AND.
Consider the value 0x1234567880000001. The result of the original
sequence with that input value is 0x1234567880000000. With the trailing
sign extension it would be 0xffffffff80000000. Clearly not right.
As much as I don't want to lose the optimization in the case where we
have the addiw form, I don't see a good way to preserve semantics
without doing more nonzero bit testing. Too bad, this does show up in
deepsjeng IIRC.
Jeff