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))")))
;; 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)