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)
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.