RE: [PATCH] aarch64: accept x8-x15 in aarch64_general_reg
Tamar Christina <[email protected]>
| Newsgroups | gmane.comp.gcc.patches |
|---|---|
| Message-ID | <GVXPR08MB10405510AE988A49DFE423DF6FFDC2@GVXPR08MB10405.eurprd08.prod.outlook.com> |
> -----Original Message----- > From: [email protected] <[email protected]> > Sent: 12 August 2026 10:42 > To: [email protected] > Cc: Tamar Christina <[email protected]>; Wilco Dijkstra > <[email protected]>; Alex Coplan <[email protected]>; > [email protected]; Alice Carlotti <[email protected]>; > Kyrylo Tkachov <[email protected]> > Subject: [PATCH] aarch64: accept x8-x15 in aarch64_general_reg > > From: Kyrylo Tkachov <[email protected]> > > 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]> > --- > gcc/config/aarch64/predicates.md | 9 ++- > .../gcc.dg/rtl/aarch64/subs_general_reg.c | 70 +++++++++++++++++++ > 2 files changed, 77 insertions(+), 2 deletions(-) > create mode 100644 gcc/testsuite/gcc.dg/rtl/aarch64/subs_general_reg.c > > diff --git a/gcc/config/aarch64/predicates.md > b/gcc/config/aarch64/predicates.md > index e2911a0bccd..eff83c0231f 100644 > --- a/gcc/config/aarch64/predicates.md > +++ b/gcc/config/aarch64/predicates.md > @@ -36,10 +36,15 @@ > (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) > + && HARD_REGISTER_P (op) > + && GP_REGNUM_P (REGNO (op))"))) Looks sensible to me, but isn't the HARD_REGISTER_P redundant? GP_REGNUM_P already specifically checks for a reg numbers belong to the hard register range? So I think we can drop that. But LGTM. Thanks, Tamr > > ;; 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 00000000000..26d07a4233c > --- /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} } } */ > -- > 2.50.1 (Apple Git-155)