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.