https://gcc.gnu.org/g:4af99f0796e6bb65d4413f9d73e0f792722dd3b2

commit r17-5278-g4af99f0796e6bb65d4413f9d73e0f792722dd3b2
Author: Jeff Law <[email protected]>
Date:   Sat Oct 17 10:55:19 2026 -0600

    [RISC-V] Fix LLM identified bugs in RISC-V bitmanip.md file
    
    So as I mentioned at Cauldron I think we can and should be proactively 
looking
    at our machine descriptions with LLMs for bugs. This patch addresses four
    issues caught by an LLM checker on RISC-V's bitmanip.md.
    
    First we have a a simply broken pattern.  The pattern incorrectly uses 
sext_hwi
    (operand, 32) > 0 to see if it's safe to treat a constant as if it's been
    extended from 32 to 64 bits.  But it'll fails miserably if the constant has 
any
    bits in 32..63 already set, it essentially wipes them out when they may be
    relevant to the min/max comparison.  I spent an absurd amount of time 
trying to
    get a C testcase that would trigger.  I did finally get one to trigger using
    RTL, but it triggers an ICE later when mated with a driver to send
    problematical constants into the key function.
    
    Given the pattern has been problematical before, the original introduction 
said
    it was supposed to be a short-term fix and my inability to trigger with C 
code,
    I'm just going to remove the pattern.
    
    Next we have a clobber operand in "X" mode in a splitter.  The other 
operands
    are GPR.  In the split-rtl we use that as as scratch and can end up with
    mismatched modes.  Changing it to GPR is the right thing to do.
    
    Next we have a pattern that I'm sure shouldn't match anything.  It's 
condition
    is TARGET_64BIT so the mode of its AND operation is DI.  Yet the AND has 
two SI
    operands.  Opps.  This one looks familiar to me, so probably something I
    introduced.
    
    Last, there's a pattern which generates RTL designed to match a Zbs bit
    extraction, but the splitter was not conditional on Zbs.  This isn't 
generally
    causing problems because combine will ignore the splitter if it generates 
RTL
    that doesn't match.  But we might as well do the right thing and add the
    TARGET_ZBS condition.
    
    Regression tested on riscv32-elf and riscv64-elf.  Pushing to the trunk.
    
    Assisted-by: LLM (reviewing bitmanip.md for bugs, attempts to generate 
testcase
    for first problem)
    
    Jeff
    
    ps.  There are other problems in this file, but these were easy to knock 
out.
    
            * config/riscv/bitmanip.md (minmax splitter): Remove broken pattern.
            (*bextdi_position_ze_masked): Likewise.
            (polarity reversed mask splitter): Clobber GPR, not X mode register.
            (splitter to generate bext): Make conditional on TARGET_ZBS.

Diff:
---
 gcc/config/riscv/bitmanip.md | 46 ++------------------------------------------
 1 file changed, 2 insertions(+), 44 deletions(-)

diff --git a/gcc/config/riscv/bitmanip.md b/gcc/config/riscv/bitmanip.md
index af4718332446..af728c54835b 100644
--- a/gcc/config/riscv/bitmanip.md
+++ b/gcc/config/riscv/bitmanip.md
@@ -648,36 +648,6 @@
   "<bitmanip_minmax_cmp_insn>\t%0,%1,%z2"
   [(set_attr "type" "<bitmanip_minmax_cmp_insn>")])
 
-;; Optimize the common case of a SImode min/max against a constant
-;; that is safe both for sign- and zero-extension.
-(define_split
-  [(set (match_operand:DI 0 "register_operand")
-       (sign_extend:DI
-         (subreg:SI
-           (bitmanip_minmax:DI (zero_extend:DI
-                                 (match_operand:SI 1 "register_operand"))
-                               (match_operand:DI 2 "immediate_operand")) 0)))
-   (clobber (match_operand:DI 3 "register_operand"))
-   (clobber (match_operand:DI 4 "register_operand"))]
-  "TARGET_64BIT && TARGET_ZBB && sext_hwi (INTVAL (operands[2]), 32) >= 0"
-  [(set (match_dup 0) (<uminmax_optab>:DI (match_dup 4) (match_dup 3)))]
-  "
-{
-  /* Load the constant into a register.  */
-  emit_move_insn (operands[3], operands[2]);
-
-  /* If operands[1] is a sign extended SUBREG, then we can use it
-     directly.  Otherwise extend it into another temporary.  */
-  if (SUBREG_P (operands[1])
-      && SUBREG_PROMOTED_VAR_P (operands[1])
-      && SUBREG_PROMOTED_SIGNED_P (operands[1]))
-    operands[4] = SUBREG_REG (operands[1]);
-  else
-    emit_move_insn (operands[4], gen_rtx_SIGN_EXTEND (DImode, operands[1]));
-
-  /* The minmax is actually emitted from the split pattern.  */
-}")
-
 ;; ZBS extension.
 
 (define_insn "*<bit_optab><mode>"
@@ -1177,7 +1147,7 @@
                                           (const_int 1)
                                           (match_operand 2))
                        (const_int 0))))
-   (clobber (match_operand:X 3 "register_operand"))]
+   (clobber (match_operand:GPR 3 "register_operand"))]
   "TARGET_ZBS"
   [(set (match_dup 3) (zero_extract:GPR (match_dup 1) (const_int 1) (match_dup 
2)))
    (set (match_dup 0) (plus:GPR (match_dup 3) (const_int -1)))])
@@ -1502,18 +1472,6 @@
   "bext\t%0,%1,%2"
   [(set_attr "type" "bitmanip")])
 
-;; Same as above, but without the extraneous zero_extend.
-(define_insn "*bextdi_position_ze_masked"
-  [(set (match_operand:X 0 "register_operand" "=r")
-       (zero_extract:X
-         (match_operand:X 1 "register_operand" "r")
-         (const_int 1)
-         (and:X (match_operand:SI 2 "register_operand" "r")
-                (match_operand:SI 3 "bitpos_mask_operand" "n"))))]
-  "TARGET_64BIT && TARGET_ZBS"
-  "bext\t%0,%1,%2"
-  [(set_attr "type" "bitmanip")])
-
 ;; This has shown up in testing.  In particular we end up with an
 ;; immediate input.  We can load that into a register and target
 ;; one of the above bext patterns.
@@ -1523,7 +1481,7 @@
                           (match_operand:QI 2 "register_operand"))
               (const_int 1)))
    (clobber (match_operand:X 3 "register_operand"))]
-  ""
+  "TARGET_ZBS"
   [(set (match_dup 3) (match_dup 1))
    (set (match_dup 0) (zero_extract:X (match_dup 3)
                                      (const_int 1)

Reply via email to