https://gcc.gnu.org/g:9a8f57d7713b4816a77144c5ef121989d9fd4a09
commit r17-5644-g9a8f57d7713b4816a77144c5ef121989d9fd4a09 Author: Jeff Law <[email protected]> Date: Tue Oct 27 09:29:12 2026 -0600 [RISC-V] Fix miscellaneous bugs found by LLM review in RISC-V port Here's the next batch of things caught by LLM review of the RISC-V port. Interestingly enough when I wiped memory and had it re-review bitmanip.md, it did find one new thing, similarly for zicond.md. So first, in the zero extension from HI expander. If we're extending from a promoted subreg, we can instead just generate a trivial move (which likely gets optimized away). That's fine and good. But we failed to check that the inner object's mode matches the destination mode for the extension. It's easy enough to check the modes. While I've never seen this happen in practice, better to be safe than trigger an obscure ICE one day. In bitmanip.md we have a pattern which was not conditional on TARGET_64BIT, but which extensively uses DI modes. With only slight work we can make it functional on rv32 as well (X mode and adjust hardcoded 63 to be BITS_PER_WORD - 1. In zicond.md there's an explicit subreg in the output pattern. We just want the lowpart, and if the operand was already a subreg, we'd end up with nested subregs, which is verboten. So we just construct a fresh operand with gen_lowpart and use that instead. Bootstrapped & regression tested on the c920 and k3 and regression tested on riscv32-elf and riscv64-elf. gcc/ * config/riscv/bitmanip.md (a >= 0 ? b : 0 splitter): Generalize for rv32. * config/riscv/zicond.md (conditional shift splitter): Use subreg_lowpart rather than explicit subregs. * config/riscv/riscv.md (zero_extendhi<GPR:mode>2): When optimizing extension of promoted subreg, make sure inner mode matches final destination's mode. Diff: --- gcc/config/riscv/bitmanip.md | 15 ++++++++------- gcc/config/riscv/riscv.md | 3 ++- gcc/config/riscv/zicond.md | 5 +++-- 3 files changed, 13 insertions(+), 10 deletions(-) diff --git a/gcc/config/riscv/bitmanip.md b/gcc/config/riscv/bitmanip.md index f3207a72180c..b3550d9a0d07 100644 --- a/gcc/config/riscv/bitmanip.md +++ b/gcc/config/riscv/bitmanip.md @@ -310,14 +310,15 @@ ;; bit of extra help for combine (i.e., the below split), we end up emitting ;; not/srai/and instead of combining the not into an andn. (define_split - [(set (match_operand:DI 0 "register_operand") - (and:DI (neg:DI (ge:DI (match_operand:DI 1 "register_operand") - (const_int 0))) - (match_operand:DI 2 "register_operand"))) - (clobber (match_operand:DI 3 "register_operand"))] + [(set (match_operand:X 0 "register_operand") + (and:X (neg:X (ge:X (match_operand:DI 1 "register_operand") + (const_int 0))) + (match_operand:X 2 "register_operand"))) + (clobber (match_operand:X 3 "register_operand"))] "TARGET_ZBB || TARGET_ZBKB" - [(set (match_dup 3) (ashiftrt:DI (match_dup 1) (const_int 63))) - (set (match_dup 0) (and:DI (not:DI (match_dup 3)) (match_dup 2)))]) + [(set (match_dup 3) (ashiftrt:X (match_dup 1) (match_dup 4))) + (set (match_dup 0) (and:X (not:X (match_dup 3)) (match_dup 2)))] + { operands[4] = GEN_INT (BITS_PER_WORD - 1); }) (define_insn "*xor_not<mode>" [(set (match_operand:X 0 "register_operand" "=r") diff --git a/gcc/config/riscv/riscv.md b/gcc/config/riscv/riscv.md index 24a9d5fbfd86..76a566520ff5 100644 --- a/gcc/config/riscv/riscv.md +++ b/gcc/config/riscv/riscv.md @@ -1903,7 +1903,8 @@ /* If the source is a suitably extended subreg, then this is just a simple move. */ if (SUBREG_P (operands[1]) && SUBREG_PROMOTED_VAR_P (operands[1]) - && SUBREG_PROMOTED_UNSIGNED_P (operands[1])) + && SUBREG_PROMOTED_UNSIGNED_P (operands[1]) + && GET_MODE (SUBREG_REG (operands[1])) == <GPR:MODE>mode) { emit_insn (gen_mov<GPR:mode> (operands[0], SUBREG_REG (operands[1]))); DONE; diff --git a/gcc/config/riscv/zicond.md b/gcc/config/riscv/zicond.md index a6275f6637f5..b07aec8feb24 100644 --- a/gcc/config/riscv/zicond.md +++ b/gcc/config/riscv/zicond.md @@ -335,8 +335,9 @@ [(set (match_dup 4) (if_then_else:X (ne:X (match_dup 1) (const_int 0)) (match_dup 3) (const_int 0))) - (set (match_dup 0) (any_shift_rotate:X (match_dup 2) (subreg:QI (match_dup 4) 0)))] - "operands[3] = gen_lowpart (word_mode, operands[3]);") + (set (match_dup 0) (any_shift_rotate:X (match_dup 2) (match_dup 5)))] + "operands[3] = gen_lowpart (word_mode, operands[3]); + operands[5] = gen_lowpart (QImode, operands[4]);") ;; AND is special as the czero doesn't produce the neutral operand. It ;; would be a natural 4->3 split, but combine doesn't support that, so
