This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[SH] PR 54602
- From: Oleg Endo <oleg dot endo at t-online dot de>
- To: gcc-patches <gcc-patches at gcc dot gnu dot org>
- Date: Fri, 12 Oct 2012 11:00:13 +0200
- Subject: [SH] PR 54602
Hello,
This fixes the issue of PR 54602 as proposed in the PR.
Tested on rev 192200 with
make -k check RUNTESTFLAGS="--target_board=sh-sim
\{-m2/-ml,-m2/-mb,-m2a/-mb,-m4/-ml,-m4/-mb,-m4a/-ml,-m4a/-mb}"
and no new failures.
OK?
Cheers,
Oleg
gcc/ChangeLog:
PR target/54602
* config/sh/sh.md: Correct define_delay for return insns.
(*movsi_pop): Delete.
testsuite/ChangeLog:
PR target/54602
* gcc.target/sh/pr54602-1.c: New.
* gcc.target/sh/pr54602-2.c: New.
* gcc.target/sh/pr54602-3.c: New.
* gcc.target/sh/pr54602-4.c: New.
Index: gcc/testsuite/gcc.target/sh/pr54602-1.c
===================================================================
--- gcc/testsuite/gcc.target/sh/pr54602-1.c (revision 0)
+++ gcc/testsuite/gcc.target/sh/pr54602-1.c (revision 0)
@@ -0,0 +1,15 @@
+/* Verify that the delay slot is stuffed with register pop insns for normal
+ (i.e. not interrupt handler) function returns. If everything goes as
+ expected we won't see any nop insns. */
+/* { dg-do compile { target "sh*-*-*" } } */
+/* { dg-options "-O1" } */
+/* { dg-skip-if "" { "sh*-*-*" } { "-m5*"} { "" } } */
+/* { dg-final { scan-assembler-not "nop" } } */
+
+int test00 (int a, int b);
+
+int
+test01 (int a, int b, int c, int d)
+{
+ return test00 (a, b) + c;
+}
Index: gcc/testsuite/gcc.target/sh/pr54602-3.c
===================================================================
--- gcc/testsuite/gcc.target/sh/pr54602-3.c (revision 0)
+++ gcc/testsuite/gcc.target/sh/pr54602-3.c (revision 0)
@@ -0,0 +1,12 @@
+/* Verify that the rte delay slot is not stuffed with register pop insns
+ which touch the banked registers r0..r7 on SH3* and SH4* targets. */
+/* { dg-do compile { target "sh*-*-*" } } */
+/* { dg-options "-O1" } */
+/* { dg-skip-if "" { "sh*-*-*" } { "*" } { "-m3*" "-m4*" } } */
+/* { dg-final { scan-assembler-times "nop" 1 } } */
+
+int __attribute__ ((interrupt_handler))
+test00 (int a, int b, int c, int d)
+{
+ return a + b;
+}
Index: gcc/testsuite/gcc.target/sh/pr54602-2.c
===================================================================
--- gcc/testsuite/gcc.target/sh/pr54602-2.c (revision 0)
+++ gcc/testsuite/gcc.target/sh/pr54602-2.c (revision 0)
@@ -0,0 +1,15 @@
+/* Verify that the delay slot is not stuffed with register pop insns for
+ interrupt handler function returns on SH1* and SH2* targets, where the
+ rte insn uses the stack pointer. */
+/* { dg-do compile { target "sh*-*-*" } } */
+/* { dg-options "-O1" } */
+/* { dg-skip-if "" { "sh*-*-*" } { "*" } { "-m1*" "-m2*" } } */
+/* { dg-final { scan-assembler-times "nop" 1 } } */
+
+int test00 (int a, int b);
+
+int __attribute__ ((interrupt_handler))
+test01 (int a, int b, int c, int d)
+{
+ return test00 (a, b) + c;
+}
Index: gcc/testsuite/gcc.target/sh/pr54602-4.c
===================================================================
--- gcc/testsuite/gcc.target/sh/pr54602-4.c (revision 0)
+++ gcc/testsuite/gcc.target/sh/pr54602-4.c (revision 0)
@@ -0,0 +1,15 @@
+/* Verify that the delay slot is stuffed with register pop insns on SH3* and
+ SH4* targets, where the stack pointer is not used by the rte insn. If
+ everything works out, we won't see a nop insn. */
+/* { dg-do compile { target "sh*-*-*" } } */
+/* { dg-options "-O1" } */
+/* { dg-skip-if "" { "sh*-*-*" } { "*" } { "-m3*" "-m4*" } } */
+/* { dg-final { scan-assembler-not "nop" } } */
+
+int test00 (int a, int b);
+
+int __attribute__ ((interrupt_handler))
+test01 (int a, int b, int c, int d)
+{
+ return test00 (a, b) + c;
+}
Index: gcc/config/sh/sh.md
===================================================================
--- gcc/config/sh/sh.md (revision 192200)
+++ gcc/config/sh/sh.md (working copy)
@@ -541,22 +541,22 @@
(eq_attr "needs_delay_slot" "yes")
[(eq_attr "in_delay_slot" "yes") (nil) (nil)])
-;; On the SH and SH2, the rte instruction reads the return pc from the stack,
-;; and thus we can't put a pop instruction in its delay slot.
-;; On the SH3 and SH4, the rte instruction does not use the stack, so a pop
-;; instruction can go in the delay slot.
;; Since a normal return (rts) implicitly uses the PR register,
;; we can't allow PR register loads in an rts delay slot.
+;; On the SH1* and SH2*, the rte instruction reads the return pc from the
+;; stack, and thus we can't put a pop instruction in its delay slot.
+;; On the SH3* and SH4*, the rte instruction does not use the stack, so a
+;; pop instruction can go in the delay slot, unless it references a banked
+;; register (the register bank is switched by rte).
(define_delay
(eq_attr "type" "return")
[(and (eq_attr "in_delay_slot" "yes")
(ior (and (eq_attr "interrupt_function" "no")
(eq_attr "type" "!pload,prset"))
(and (eq_attr "interrupt_function" "yes")
- (ior
- (not (match_test "TARGET_SH3"))
- (eq_attr "hit_stack" "no")
- (eq_attr "banked" "no"))))) (nil) (nil)])
+ (ior (match_test "TARGET_SH3") (eq_attr "hit_stack" "no"))
+ (eq_attr "banked" "no"))))
+ (nil) (nil)])
;; Since a call implicitly uses the PR register, we can't allow
;; a PR register store in a jsr delay slot.
@@ -6186,21 +6186,6 @@
emit_insn (gen_ashlsi3 (operands[5], operands[0], operands[2]));
})
-;; Define additional pop for SH1 and SH2 so it does not get
-;; placed in the delay slot.
-(define_insn "*movsi_pop"
- [(set (match_operand:SI 0 "register_operand" "=r,x,l")
- (match_operand:SI 1 "sh_no_delay_pop_operand" ">,>,>"))]
- "(TARGET_SH1 || TARGET_SH2E || TARGET_SH2A)
- && ! TARGET_SH3"
- "@
- mov.l %1,%0
- lds.l %1,%0
- lds.l %1,%0"
- [(set_attr "type" "load_si,mem_mac,pload")
- (set_attr "length" "2,2,2")
- (set_attr "in_delay_slot" "no,no,no")])
-
;; t/r must come after r/r, lest reload will try to reload stuff like
;; (set (subreg:SI (mem:QI (plus:SI (reg:SI SP_REG) (const_int 12)) 0) 0)
;; (made from (set (subreg:SI (reg:QI ###) 0) ) into T.