[gcc r17-3218] aarch64: accept x8-x15 in aarch64_general_reg

Kyrylo Tkachov via Gcc-cvs <[email protected]>
Newsgroups gmane.comp.gcc.cvs
Message-ID <[email protected]>
https://gcc.gnu.org/g:81b7d7b827252fd93694812ccc751059b2c0d8e4

commit r17-3218-g81b7d7b827252fd93694812ccc751059b2c0d8e4
Author: Kyrylo Tkachov <[email protected]>
Date:   Mon Aug 10 01:15:59 2026 -0700

    aarch64: accept x8-x15 in aarch64_general_reg
    
    The peephole2 patterns that fuse a comparison and a subtraction into SUBS
    require their destination to satisfy aarch64_general_reg.  That predicate
    compares REGNO_REG_CLASS against GENERAL_REGS, but REGNO_REG_CLASS returns
    the smallest class holding the register, and since the SME2 support added
    W8_W11_REGS and W12_W15_REGS it does not return GENERAL_REGS for x8-x15.
    The peepholes therefore stop firing whenever the register allocator puts
    the difference in one of those eight registers:
    
      (set (reg:CC cc) (compare:CC (reg:DI x2) (reg:DI x5)))
      (set (reg:DI x9) (minus:DI (reg:DI x2) (reg:DI x5)))
    
      -     cmp     x2, x5
      +     subs    x9, x2, x5
    
    Test the register number instead.  The stack pointer is still rejected,
    which is what the predicate was added for.
    Bootstrapped and tested on aarch64-none-linux-gnu.
    Ok for trunk?
    Thanks,
    Kyrill
    
    gcc/ChangeLog:
    
            * config/aarch64/predicates.md (aarch64_general_reg): Test the
            register number rather than REGNO_REG_CLASS, which reports the
            W8_W11_REGS and W12_W15_REGS subclasses for x8-x15.
    
    gcc/testsuite/ChangeLog:
    
            * gcc.dg/rtl/aarch64/subs_general_reg.c: New test.
    
    Signed-off-by: Kyrylo Tkachov <[email protected]>

Diff:
---
 gcc/config/aarch64/predicates.md                   |  8 ++-
 .../gcc.dg/rtl/aarch64/subs_general_reg.c          | 70 ++++++++++++++++++++++
 2 files changed, 76 insertions(+), 2 deletions(-)

diff --git a/gcc/config/aarch64/predicates.md b/gcc/config/aarch64/predicates.md
index e2911a0bccdb..9d2613a9aeef 100644
--- a/gcc/config/aarch64/predicates.md
+++ b/gcc/config/aarch64/predicates.md
@@ -36,10 +36,14 @@
   (ior (match_code "symbol_ref")
        (match_operand 0 "register_operand")))
 
+;; True if OP is an allocated general register, i.e. x0-x30 but not the
+;; stack pointer.  REGNO_REG_CLASS returns the smallest class holding the
+;; register, and x8-x15 belong to the W8_W11_REGS and W12_W15_REGS
+;; subclasses, so it cannot be compared against GENERAL_REGS here.
 (define_predicate "aarch64_general_reg"
   (and (match_operand 0 "register_operand")
-       (match_test "REGNO_REG_CLASS (REGNO (op)) == STUB_REGS
-		    || REGNO_REG_CLASS (REGNO (op)) == GENERAL_REGS")))
+       (match_test "REG_P (op)
+		    && GP_REGNUM_P (REGNO (op))")))
 
 ;; Return true if OP a (const_int 0) operand.
 (define_predicate "const0_operand"
diff --git a/gcc/testsuite/gcc.dg/rtl/aarch64/subs_general_reg.c b/gcc/testsuite/gcc.dg/rtl/aarch64/subs_general_reg.c
new file mode 100644
index 000000000000..26d07a4233c6
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/rtl/aarch64/subs_general_reg.c
@@ -0,0 +1,70 @@
+/* { dg-do compile { target aarch64-*-* } } */
+/* { dg-options "-O2" } */
+
+/* The peephole2 patterns that build SUBS require the destination to satisfy
+   aarch64_general_reg.  Every allocatable general register must satisfy it,
+   including x8-x15, which REGNO_REG_CLASS reports as the W8_W11_REGS and
+   W12_W15_REGS subclasses rather than as GENERAL_REGS.  */
+
+int __RTL (startwith ("peephole2")) sub_compare_x2 ()
+{
+(function "sub_compare_x2"
+  (insn-chain
+    (block 2
+      (edge-from entry (flags "FALLTHRU"))
+      (cnote 3 [bb 2] NOTE_INSN_BASIC_BLOCK)
+      (cinsn 90 (set (reg:CC cc)
+		 (compare:CC (reg:DI x2) (reg:DI x5))))
+      (cinsn 89 (set (reg:DI x2)
+		 (minus:DI (reg:DI x2) (reg:DI x5))))
+      ;; Extra insns to avoid the above being deleted by DCE.
+      (cinsn 12 (use (reg/i:DI cc)))
+      (cinsn 11 (use (reg/i:DI x2)))
+      (edge-to exit (flags "FALLTHRU"))
+    ) ;; block 2
+  ) ;; insn-chain
+) ;; function "sub_compare_x2"
+}
+
+int __RTL (startwith ("peephole2")) sub_compare_x9 ()
+{
+(function "sub_compare_x9"
+  (insn-chain
+    (block 2
+      (edge-from entry (flags "FALLTHRU"))
+      (cnote 3 [bb 2] NOTE_INSN_BASIC_BLOCK)
+      (cinsn 90 (set (reg:CC cc)
+		 (compare:CC (reg:DI x2) (reg:DI x5))))
+      (cinsn 89 (set (reg:DI x9)
+		 (minus:DI (reg:DI x2) (reg:DI x5))))
+      ;; Extra insns to avoid the above being deleted by DCE.
+      (cinsn 12 (use (reg/i:DI cc)))
+      (cinsn 11 (use (reg/i:DI x9)))
+      (edge-to exit (flags "FALLTHRU"))
+    ) ;; block 2
+  ) ;; insn-chain
+) ;; function "sub_compare_x9"
+}
+
+int __RTL (startwith ("peephole2")) sub_compare_x13 ()
+{
+(function "sub_compare_x13"
+  (insn-chain
+    (block 2
+      (edge-from entry (flags "FALLTHRU"))
+      (cnote 3 [bb 2] NOTE_INSN_BASIC_BLOCK)
+      (cinsn 90 (set (reg:CC cc)
+		 (compare:CC (reg:DI x2) (reg:DI x5))))
+      (cinsn 89 (set (reg:DI x13)
+		 (minus:DI (reg:DI x2) (reg:DI x5))))
+      ;; Extra insns to avoid the above being deleted by DCE.
+      (cinsn 12 (use (reg/i:DI cc)))
+      (cinsn 11 (use (reg/i:DI x13)))
+      (edge-to exit (flags "FALLTHRU"))
+    ) ;; block 2
+  ) ;; insn-chain
+) ;; function "sub_compare_x13"
+}
+
+/* { dg-final { scan-assembler-times {subs\tx[0-9]+, x2, x5} 3 } } */
+/* { dg-final { scan-assembler-not {\tcmp\t} } } */
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.