aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMatthew Malcomson <matthew.malcomson@arm.com>2019-02-22 16:35:22 +0000
committerMatthew Malcomson <matmal01@gcc.gnu.org>2019-02-22 16:35:22 +0000
commit341fca1b4982c93a7c6cce90b0e0f84f92a35146 (patch)
tree034169e57790c6f7a247df657e043b654516c585
parent3c2a70cb1414b10ab3d52286087398cd03a70413 (diff)
downloadgcc-341fca1b4982c93a7c6cce90b0e0f84f92a35146.zip
gcc-341fca1b4982c93a7c6cce90b0e0f84f92a35146.tar.gz
gcc-341fca1b4982c93a7c6cce90b0e0f84f92a35146.tar.bz2
Handle stack pointer with SUBS/ADDS instructions.
In general the stack pointer was not handled for many SUBS/ADDS patterns in aarch64.md. Both the "extended register" and "immediate" forms allow the stack pointer to be used as the source register, while no form allows the stack pointer for the destination register. The define_insn patterns generating ADDS/SUBS did not allow the stack pointer for any operand, while the define_peephole2 patterns that generated RTX to be matched by these patterns allowed the stack pointer for any operand. The patterns are fixed by adding the 'k' constraint for the first source operand to all define_insns that generate the ADDS/SUBS "extended register" and "immediate" forms (but not the "shifted register" form). In peephole optimizations, constraint strings are ignored (see "(gccint) C Constraint Interface" info node in the documentation), so the decision to act or not is based solely on the predicate and condition. This patch introduces a new predicate "aarch64_general_reg" to be used in define_peephole2 patterns where only GENERAL_REGS registers are acceptable and uses that predicate in the peepholes that generate patterns for ADDS/SUBS. Full bootstrap and regtest done on aarch64-none-linux-gnu. Regression tests done on aarch64-none-linux-gnu and aarch64-none-elf cross compiler. OK for trunk? gcc/ChangeLog: 2019-02-22 Matthew Malcomson <matthew.malcomson@arm.com> PR target/89324 * config/aarch64/aarch64.md: Use aarch64_general_reg predicate on destination register in peepholes generating patterns for ADDS/SUBS. (add<mode>3_compare0, *addsi3_compare0_uxtw, add<mode>3_compareC, add<mode>3_compareV_imm, add<mode>3_compareV, *adds_<optab><ALLX:mode>_<GPI:mode>, *subs_<optab><ALLX:mode>_<GPI:mode>, *adds_<optab><ALLX:mode>_shift_<GPI:mode>, *subs_<optab><ALLX:mode>_shift_<GPI:mode>, *adds_<optab><mode>_multp2, *subs_<optab><mode>_multp2, *sub<mode>3_compare0, *subsi3_compare0_uxtw, sub<mode>3_compare1): Allow stack pointer for source register. * config/aarch64/predicates.md (aarch64_general_reg): New predicate. gcc/testsuite/ChangeLog: 2019-02-22 Matthew Malcomson <matthew.malcomson@arm.com> PR target/89324 * gcc.dg/rtl/aarch64/subs_adds_sp.c: New test. * gfortran.fortran-torture/compile/pr89324.f90: New test. From-SVN: r269122
-rw-r--r--gcc/ChangeLog17
-rw-r--r--gcc/config/aarch64/aarch64.md38
-rw-r--r--gcc/config/aarch64/predicates.md4
-rw-r--r--gcc/testsuite/ChangeLog6
-rw-r--r--gcc/testsuite/gcc.dg/rtl/aarch64/subs_adds_sp.c153
-rw-r--r--gcc/testsuite/gfortran.fortran-torture/compile/pr89324.f9015
6 files changed, 214 insertions, 19 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 42ed0dc..8b283d5 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,20 @@
+2019-02-22 Matthew Malcomson <matthew.malcomson@arm.com>
+
+ PR target/89324
+ * config/aarch64/aarch64.md: Use aarch64_general_reg predicate on
+ destination register in peepholes generating patterns for ADDS/SUBS.
+ (add<mode>3_compare0,
+ *addsi3_compare0_uxtw, add<mode>3_compareC,
+ add<mode>3_compareV_imm, add<mode>3_compareV,
+ *adds_<optab><ALLX:mode>_<GPI:mode>,
+ *subs_<optab><ALLX:mode>_<GPI:mode>,
+ *adds_<optab><ALLX:mode>_shift_<GPI:mode>,
+ *subs_<optab><ALLX:mode>_shift_<GPI:mode>,
+ *adds_<optab><mode>_multp2, *subs_<optab><mode>_multp2,
+ *sub<mode>3_compare0, *subsi3_compare0_uxtw,
+ sub<mode>3_compare1): Allow stack pointer for source register.
+ * config/aarch64/predicates.md (aarch64_general_reg): New predicate.
+
2019-02-22 Martin Sebor <msebor@redhat.com>
PR c/89425
diff --git a/gcc/config/aarch64/aarch64.md b/gcc/config/aarch64/aarch64.md
index b7f6fe0..b7cd9fc 100644
--- a/gcc/config/aarch64/aarch64.md
+++ b/gcc/config/aarch64/aarch64.md
@@ -1985,7 +1985,7 @@
(define_insn "add<mode>3_compare0"
[(set (reg:CC_NZ CC_REGNUM)
(compare:CC_NZ
- (plus:GPI (match_operand:GPI 1 "register_operand" "%r,r,r")
+ (plus:GPI (match_operand:GPI 1 "register_operand" "%rk,rk,rk")
(match_operand:GPI 2 "aarch64_plus_operand" "r,I,J"))
(const_int 0)))
(set (match_operand:GPI 0 "register_operand" "=r,r,r")
@@ -2002,7 +2002,7 @@
(define_insn "*addsi3_compare0_uxtw"
[(set (reg:CC_NZ CC_REGNUM)
(compare:CC_NZ
- (plus:SI (match_operand:SI 1 "register_operand" "%r,r,r")
+ (plus:SI (match_operand:SI 1 "register_operand" "%rk,rk,rk")
(match_operand:SI 2 "aarch64_plus_operand" "r,I,J"))
(const_int 0)))
(set (match_operand:DI 0 "register_operand" "=r,r,r")
@@ -2034,7 +2034,7 @@
[(set (reg:CC_C CC_REGNUM)
(compare:CC_C
(plus:GPI
- (match_operand:GPI 1 "register_operand" "r,r,r")
+ (match_operand:GPI 1 "register_operand" "rk,rk,rk")
(match_operand:GPI 2 "aarch64_plus_operand" "r,I,J"))
(match_dup 1)))
(set (match_operand:GPI 0 "register_operand" "=r,r,r")
@@ -2081,7 +2081,7 @@
(compare:CC_V
(plus:<DWI>
(sign_extend:<DWI>
- (match_operand:GPI 1 "register_operand" "r,r"))
+ (match_operand:GPI 1 "register_operand" "rk,rk"))
(match_operand:GPI 2 "aarch64_plus_immediate" "I,J"))
(sign_extend:<DWI>
(plus:GPI (match_dup 1) (match_dup 2)))))
@@ -2098,7 +2098,7 @@
[(set (reg:CC_V CC_REGNUM)
(compare:CC_V
(plus:<DWI>
- (sign_extend:<DWI> (match_operand:GPI 1 "register_operand" "r"))
+ (sign_extend:<DWI> (match_operand:GPI 1 "register_operand" "rk"))
(sign_extend:<DWI> (match_operand:GPI 2 "register_operand" "r")))
(sign_extend:<DWI> (plus:GPI (match_dup 1) (match_dup 2)))))
(set (match_operand:GPI 0 "register_operand" "=r")
@@ -2177,7 +2177,7 @@
(compare:CC_NZ
(plus:GPI
(ANY_EXTEND:GPI (match_operand:ALLX 1 "register_operand" "r"))
- (match_operand:GPI 2 "register_operand" "r"))
+ (match_operand:GPI 2 "register_operand" "rk"))
(const_int 0)))
(set (match_operand:GPI 0 "register_operand" "=r")
(plus:GPI (ANY_EXTEND:GPI (match_dup 1)) (match_dup 2)))]
@@ -2189,7 +2189,7 @@
(define_insn "*subs_<optab><ALLX:mode>_<GPI:mode>"
[(set (reg:CC_NZ CC_REGNUM)
(compare:CC_NZ
- (minus:GPI (match_operand:GPI 1 "register_operand" "r")
+ (minus:GPI (match_operand:GPI 1 "register_operand" "rk")
(ANY_EXTEND:GPI
(match_operand:ALLX 2 "register_operand" "r")))
(const_int 0)))
@@ -2207,7 +2207,7 @@
(ANY_EXTEND:GPI
(match_operand:ALLX 1 "register_operand" "r"))
(match_operand 2 "aarch64_imm3" "Ui3"))
- (match_operand:GPI 3 "register_operand" "r"))
+ (match_operand:GPI 3 "register_operand" "rk"))
(const_int 0)))
(set (match_operand:GPI 0 "register_operand" "=rk")
(plus:GPI (ashift:GPI (ANY_EXTEND:GPI (match_dup 1))
@@ -2221,7 +2221,7 @@
(define_insn "*subs_<optab><ALLX:mode>_shift_<GPI:mode>"
[(set (reg:CC_NZ CC_REGNUM)
(compare:CC_NZ
- (minus:GPI (match_operand:GPI 1 "register_operand" "r")
+ (minus:GPI (match_operand:GPI 1 "register_operand" "rk")
(ashift:GPI
(ANY_EXTEND:GPI
(match_operand:ALLX 2 "register_operand" "r"))
@@ -2244,7 +2244,7 @@
(match_operand 2 "aarch64_pwr_imm3" "Up3"))
(match_operand 3 "const_int_operand" "n")
(const_int 0))
- (match_operand:GPI 4 "register_operand" "r"))
+ (match_operand:GPI 4 "register_operand" "rk"))
(const_int 0)))
(set (match_operand:GPI 0 "register_operand" "=r")
(plus:GPI (ANY_EXTRACT:GPI (mult:GPI (match_dup 1) (match_dup 2))
@@ -2259,7 +2259,7 @@
(define_insn "*subs_<optab><mode>_multp2"
[(set (reg:CC_NZ CC_REGNUM)
(compare:CC_NZ
- (minus:GPI (match_operand:GPI 4 "register_operand" "r")
+ (minus:GPI (match_operand:GPI 4 "register_operand" "rk")
(ANY_EXTRACT:GPI
(mult:GPI (match_operand:GPI 1 "register_operand" "r")
(match_operand 2 "aarch64_pwr_imm3" "Up3"))
@@ -2923,7 +2923,7 @@
(define_insn "*sub<mode>3_compare0"
[(set (reg:CC_NZ CC_REGNUM)
- (compare:CC_NZ (minus:GPI (match_operand:GPI 1 "register_operand" "r")
+ (compare:CC_NZ (minus:GPI (match_operand:GPI 1 "register_operand" "rk")
(match_operand:GPI 2 "register_operand" "r"))
(const_int 0)))
(set (match_operand:GPI 0 "register_operand" "=r")
@@ -2936,7 +2936,7 @@
;; zero_extend version of above
(define_insn "*subsi3_compare0_uxtw"
[(set (reg:CC_NZ CC_REGNUM)
- (compare:CC_NZ (minus:SI (match_operand:SI 1 "register_operand" "r")
+ (compare:CC_NZ (minus:SI (match_operand:SI 1 "register_operand" "rk")
(match_operand:SI 2 "register_operand" "r"))
(const_int 0)))
(set (match_operand:DI 0 "register_operand" "=r")
@@ -2949,7 +2949,7 @@
(define_insn "sub<mode>3_compare1_imm"
[(set (reg:CC CC_REGNUM)
(compare:CC
- (match_operand:GPI 1 "aarch64_reg_or_zero" "rZ,rZ")
+ (match_operand:GPI 1 "aarch64_reg_or_zero" "rkZ,rkZ")
(match_operand:GPI 2 "aarch64_plus_immediate" "I,J")))
(set (match_operand:GPI 0 "register_operand" "=r,r")
(plus:GPI
@@ -2965,7 +2965,7 @@
(define_insn "sub<mode>3_compare1"
[(set (reg:CC CC_REGNUM)
(compare:CC
- (match_operand:GPI 1 "aarch64_reg_or_zero" "rZ")
+ (match_operand:GPI 1 "aarch64_reg_or_zero" "rkZ")
(match_operand:GPI 2 "aarch64_reg_or_zero" "rZ")))
(set (match_operand:GPI 0 "register_operand" "=r")
(minus:GPI (match_dup 1) (match_dup 2)))]
@@ -2975,7 +2975,7 @@
)
(define_peephole2
- [(set (match_operand:GPI 0 "register_operand")
+ [(set (match_operand:GPI 0 "aarch64_general_reg")
(minus:GPI (match_operand:GPI 1 "aarch64_reg_or_zero")
(match_operand:GPI 2 "aarch64_reg_or_zero")))
(set (reg:CC CC_REGNUM)
@@ -3000,7 +3000,7 @@
(compare:CC
(match_operand:GPI 1 "aarch64_reg_or_zero")
(match_operand:GPI 2 "aarch64_reg_or_zero")))
- (set (match_operand:GPI 0 "register_operand")
+ (set (match_operand:GPI 0 "aarch64_general_reg")
(minus:GPI (match_dup 1)
(match_dup 2)))]
""
@@ -3013,7 +3013,7 @@
)
(define_peephole2
- [(set (match_operand:GPI 0 "register_operand")
+ [(set (match_operand:GPI 0 "aarch64_general_reg")
(plus:GPI (match_operand:GPI 1 "register_operand")
(match_operand:GPI 2 "aarch64_plus_immediate")))
(set (reg:CC CC_REGNUM)
@@ -3038,7 +3038,7 @@
(compare:CC
(match_operand:GPI 1 "register_operand")
(match_operand:GPI 3 "const_int_operand")))
- (set (match_operand:GPI 0 "register_operand")
+ (set (match_operand:GPI 0 "aarch64_general_reg")
(plus:GPI (match_dup 1)
(match_operand:GPI 2 "aarch64_plus_immediate")))]
"INTVAL (operands[3]) == -INTVAL (operands[2])"
diff --git a/gcc/config/aarch64/predicates.md b/gcc/config/aarch64/predicates.md
index b8e6d23..8e1b784 100644
--- a/gcc/config/aarch64/predicates.md
+++ b/gcc/config/aarch64/predicates.md
@@ -30,6 +30,10 @@
(ior (match_code "symbol_ref")
(match_operand 0 "register_operand")))
+(define_predicate "aarch64_general_reg"
+ (and (match_operand 0 "register_operand")
+ (match_test "REGNO_REG_CLASS (REGNO (op)) == GENERAL_REGS")))
+
;; Return true if OP a (const_int 0) operand.
(define_predicate "const0_operand"
(and (match_code "const_int")
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 8c8f4a5..555dc4a 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,9 @@
+2019-02-22 Matthew Malcomson <matthew.malcomson@arm.com>
+
+ PR target/89324
+ * gcc.dg/rtl/aarch64/subs_adds_sp.c: New test.
+ * gfortran.fortran-torture/compile/pr89324.f90: New test.
+
2019-02-22 Martin Sebor <msebor@redhat.com>
PR c/89425
diff --git a/gcc/testsuite/gcc.dg/rtl/aarch64/subs_adds_sp.c b/gcc/testsuite/gcc.dg/rtl/aarch64/subs_adds_sp.c
new file mode 100644
index 0000000..f537771
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/rtl/aarch64/subs_adds_sp.c
@@ -0,0 +1,153 @@
+/* { dg-do compile { target aarch64-*-* } } */
+/* { dg-options "-O2" } */
+/*
+ Tests are:
+ Patterns allow subs/adds with a stack pointer source.
+ define_peephole2's don't generate patterns for subs/adds with a stack
+ pointer destination.
+ */
+
+/* These functions used to ICE due to using the stack pointer as a source
+ register. */
+
+int __RTL (startwith ("final"))
+adds ()
+{
+(function "adds"
+ (insn-chain
+ (block 2
+ (edge-from entry (flags "FALLTHRU"))
+ (cnote 3 [bb 2] NOTE_INSN_BASIC_BLOCK)
+ (cinsn 101 (parallel [
+ (set (reg:CC cc)
+ (compare:CC (reg/f:DI sp)
+ (const_int -3)))
+ (set (reg/f:DI x19)
+ (plus:DI (reg/f:DI sp)
+ (const_int 3)))
+ ]))
+ ;; Extra insn to avoid the above being deleted by DCE.
+ (cinsn 10 (use (reg/i:SI x19)))
+ (cinsn 11 (use (reg/i:SI sp)))
+ (edge-to exit (flags "FALLTHRU"))
+ ) ;; block 2
+ ) ;; insn-chain
+) ;; function "main"
+}
+
+int __RTL (startwith ("final"))
+subs ()
+{
+(function "subs"
+ (insn-chain
+ (block 2
+ (edge-from entry (flags "FALLTHRU"))
+ (cnote 3 [bb 2] NOTE_INSN_BASIC_BLOCK)
+ (cinsn 101 (parallel [
+ (set (reg:CC cc)
+ (compare:CC (reg/f:DI sp)
+ (const_int 3)))
+ (set (reg/f:DI x19)
+ (plus:DI (reg/f:DI sp)
+ (const_int -3)))
+ ]))
+ ;; Extra insn to avoid the above being deleted by DCE.
+ (cinsn 10 (use (reg/i:SI x19)))
+ (cinsn 11 (use (reg/i:SI sp)))
+ (edge-to exit (flags "FALLTHRU"))
+ ) ;; block 2
+ ) ;; insn-chain
+) ;; function "main"
+}
+
+/* These functions used to trigger peepholes generating invalid SUBS patterns
+ that used the stack pointer for the destination register. */
+
+int __RTL (startwith ("peephole2")) sub3_compare1_peephole_1 ()
+{
+(function "sub3_compare1_peephole_1"
+ (insn-chain
+ (block 2
+ (edge-from entry (flags "FALLTHRU"))
+ (cnote 3 [bb 2] NOTE_INSN_BASIC_BLOCK)
+ (cinsn 89 (set (reg:DI sp)
+ (minus:DI (reg:DI x2) (reg:DI x5))))
+ (cinsn 90 (set (reg:CC cc)
+ (compare:CC (reg:DI x2) (reg:DI x5))))
+ ;; Extra insn to avoid the above being deleted by DCE.
+ (cinsn 12 (use (reg/i:DI cc)))
+ (cinsn 11 (use (reg/i:DI sp)))
+ (edge-to exit (flags "FALLTHRU"))
+ ) ;; block 2
+ ) ;; insn-chain
+) ;; function "main"
+}
+
+int __RTL (startwith ("peephole2")) sub3_compare1_peephole_2 ()
+{
+(function "sub3_compare1_peephole_2"
+ (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 sp)
+ (minus:DI (reg:DI x2) (reg:DI x5))))
+ ;; Extra insn to avoid the above being deleted by DCE.
+ (cinsn 12 (use (reg/i:DI cc)))
+ (cinsn 11 (use (reg/i:DI sp)))
+ (edge-to exit (flags "FALLTHRU"))
+ ) ;; block 2
+ ) ;; insn-chain
+) ;; function "main"
+}
+
+int __RTL (startwith ("peephole2")) sub3_compare1_imm_peephole_1 ()
+{
+(function "sub3_compare1_imm_peephole_1"
+ (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 sp)
+ (minus:DI (reg:DI x2) (reg:DI x5))))
+ ;; Extra insn to avoid the above being deleted by DCE.
+ (cinsn 12 (use (reg/i:DI cc)))
+ (cinsn 11 (use (reg/i:DI sp)))
+ (edge-to exit (flags "FALLTHRU"))
+ ) ;; block 2
+ ) ;; insn-chain
+) ;; function "main"
+}
+
+int __RTL (startwith ("peephole2")) sub3_compare1_imm_peephole_2 ()
+{
+(function "sub3_compare1_imm_peephole_1"
+ (insn-chain
+ (block 2
+ (edge-from entry (flags "FALLTHRU"))
+ (cnote 3 [bb 2] NOTE_INSN_BASIC_BLOCK)
+ (cinsn 89 (set (reg:DI sp)
+ (minus:DI (reg:DI x2) (reg:DI x5))))
+ (cinsn 90 (set (reg:CC cc)
+ (compare:CC (reg:DI x2) (reg:DI x5))))
+ ;; Extra insn to avoid the above being deleted by DCE.
+ (cinsn 12 (use (reg/i:DI cc)))
+ (cinsn 11 (use (reg/i:DI sp)))
+ (edge-to exit (flags "FALLTHRU"))
+ ) ;; block 2
+ ) ;; insn-chain
+) ;; function "main"
+}
+
+/* Verify that the adds and subs functions generated their respective
+ instructions, and that none of the other functions generated either since
+ they are setting the stack pointer. */
+/* { dg-final { scan-assembler-times {adds\tx[0-9]+, sp} 1 } } */
+/* { dg-final { scan-assembler-not {adds\tsp} } } */
+/* { dg-final { scan-assembler-times {subs\tx[0-9]+, sp} 1 } } */
+/* { dg-final { scan-assembler-not {subs\tsp} } } */
+
diff --git a/gcc/testsuite/gfortran.fortran-torture/compile/pr89324.f90 b/gcc/testsuite/gfortran.fortran-torture/compile/pr89324.f90
new file mode 100644
index 0000000..014b655
--- /dev/null
+++ b/gcc/testsuite/gfortran.fortran-torture/compile/pr89324.f90
@@ -0,0 +1,15 @@
+module a
+contains
+ pure function myotherlen()
+ myotherlen = 99
+ end
+ subroutine b
+ characterx
+ block
+ character(myotherlen()) c
+ c = "abc"
+ x = c
+ end block
+
+ end
+end