[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} } } */