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