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

Reply via email to