From: chrbr Date: Thu, 21 Jun 2007 08:58:53 +0000 (+0000) Subject: svn ci -m "introduce bank[0,1] registers and fix rte delay slot scheduling" X-Git-Url: http://git.sourceforge.jp/view?p=pf3gnuchains%2Fgcc-fork.git;a=commitdiff_plain;h=2f8b8488b9b73fff97e73aa6607797cf59ca423b svn ci -m "introduce bank[0,1] registers and fix rte delay slot scheduling" 2007-06-21 Christian Bruel * config/sh/sh-protos.h (sh_loads_bankedreg_p): Declare. * config/sh/sh.c (sh_loads_bankedreg_p): New function. (push_regs): Changed saving order or banked registers. (sh_expand_epilogue): Likewise. * config/sh/sh.h (BANKED_REGISTER_P): New macro. (FIRST_BANKED_REG): Likewise. (LAST_BANKED_REG): Likewise. * config/sh/sh.md (banked) New attribute. (in_delay_slot): Check banked attribute. 2007-06-21 Christian Bruel * gcc.dg/attr-isr.c: Test delay slot content. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@125914 138bc75d-0d04-0410-961f-82ee72b054a4 --- diff --git a/gcc/ChangeLog b/gcc/ChangeLog index aaf940e5b55..212090b9773 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,15 @@ +2007-06-21 Christian Bruel + + * config/sh/sh-protos.h (sh_loads_bankedreg_p): Declare. + * config/sh/sh.c (sh_loads_bankedreg_p): New function. + (push_regs): Changed saving order or banked registers. + (sh_expand_epilogue): Likewise. + * config/sh/sh.h (BANKED_REGISTER_P): New macro. + (FIRST_BANKED_REG): Likewise. + (LAST_BANKED_REG): Likewise. + * config/sh/sh.md (banked) New attribute. + (in_delay_slot): Check banked attribute. + 2007-06-20 Sebastian Pop PR tree-optimization/32075 diff --git a/gcc/config/sh/sh-protos.h b/gcc/config/sh/sh-protos.h index e142b1cee68..b3c9387c284 100644 --- a/gcc/config/sh/sh-protos.h +++ b/gcc/config/sh/sh-protos.h @@ -168,6 +168,7 @@ extern rtx replace_n_hard_rtx (rtx, rtx *, int , int); extern int shmedia_cleanup_truncate (rtx *, void *); extern int sh_contains_memref_p (rtx); +extern int sh_loads_bankedreg_p (rtx); extern rtx shmedia_prepare_call_address (rtx fnaddr, int is_sibcall); struct secondary_reload_info; extern enum reg_class sh_secondary_reload (bool, rtx, enum reg_class, diff --git a/gcc/config/sh/sh.c b/gcc/config/sh/sh.c index 60520f7871c..0541256679f 100644 --- a/gcc/config/sh/sh.c +++ b/gcc/config/sh/sh.c @@ -5723,13 +5723,13 @@ pop (int rn) static void push_regs (HARD_REG_SET *mask, int interrupt_handler) { - int i; + int i = interrupt_handler ? LAST_BANKED_REG + 1 : 0; int skip_fpscr = 0; /* Push PR last; this gives better latencies after the prologue, and candidates for the return delay slot when there are no general registers pushed. */ - for (i = 0; i < FIRST_PSEUDO_REGISTER; i++) + for (; i < FIRST_PSEUDO_REGISTER; i++) { /* If this is an interrupt handler, and the SZ bit varies, and we have to push any floating point register, we need @@ -5749,6 +5749,13 @@ push_regs (HARD_REG_SET *mask, int interrupt_handler) && TEST_HARD_REG_BIT (*mask, i)) push (i); } + + /* Push banked registers last to improve delay slot opportunities. */ + if (interrupt_handler) + for (i = FIRST_BANKED_REG; i <= LAST_BANKED_REG; i++) + if (TEST_HARD_REG_BIT (*mask, i)) + push (i); + if (TEST_HARD_REG_BIT (*mask, PR_REG)) push (PR_REG); } @@ -6675,6 +6682,8 @@ sh_expand_epilogue (bool sibcall_p) } else /* ! TARGET_SH5 */ { + int last_reg; + save_size = 0; if (TEST_HARD_REG_BIT (live_regs_mask, PR_REG)) { @@ -6682,7 +6691,21 @@ sh_expand_epilogue (bool sibcall_p) emit_insn (gen_blockage ()); pop (PR_REG); } - for (i = 0; i < FIRST_PSEUDO_REGISTER; i++) + + /* Banked registers are poped first to avoid being scheduled in the + delay slot. RTE switches banks before the ds instruction. */ + if (current_function_interrupt) + { + for (i = FIRST_BANKED_REG; i <= LAST_BANKED_REG; i++) + if (TEST_HARD_REG_BIT (live_regs_mask, i)) + pop (LAST_BANKED_REG - i); + + last_reg = FIRST_PSEUDO_REGISTER - LAST_BANKED_REG - 1; + } + else + last_reg = FIRST_PSEUDO_REGISTER; + + for (i = 0; i < last_reg; i++) { int j = (FIRST_PSEUDO_REGISTER - 1) - i; @@ -6692,9 +6715,9 @@ sh_expand_epilogue (bool sibcall_p) fpscr_deferred = 1; else if (j != PR_REG && TEST_HARD_REG_BIT (live_regs_mask, j)) pop (j); + if (j == FIRST_FP_REG && fpscr_deferred) pop (FPSCR_REG); - } } if (target_flags != save_flags && ! current_function_interrupt) @@ -10839,6 +10862,20 @@ sh_contains_memref_p (rtx insn) return for_each_rtx (&PATTERN (insn), &sh_contains_memref_p_1, NULL); } +/* Return nonzero iff INSN loads a banked register. */ +int +sh_loads_bankedreg_p (rtx insn) +{ + if (GET_CODE (PATTERN (insn)) == SET) + { + rtx op = SET_DEST (PATTERN(insn)); + if (REG_P (op) && BANKED_REGISTER_P (REGNO (op))) + return 1; + } + + return 0; +} + /* FNADDR is the MEM expression from a call expander. Return an address to use in an SHmedia insn pattern. */ rtx diff --git a/gcc/config/sh/sh.h b/gcc/config/sh/sh.h index 91a56119c63..4fe0de8885f 100644 --- a/gcc/config/sh/sh.h +++ b/gcc/config/sh/sh.h @@ -1033,6 +1033,16 @@ extern char sh_additional_register_names[ADDREGNAMES_SIZE] \ #define FIRST_TARGET_REG TR0_REG #define LAST_TARGET_REG (FIRST_TARGET_REG + (TARGET_SHMEDIA ? 7 : -1)) +/* Registers that can be accessed through bank0 or bank1 depending on sr.md. */ + +#define FIRST_BANKED_REG R0_REG +#define LAST_BANKED_REG R7_REG + +#define BANKED_REGISTER_P(REGNO) \ + IN_RANGE ((REGNO), \ + (unsigned HOST_WIDE_INT) FIRST_BANKED_REG, \ + (unsigned HOST_WIDE_INT) LAST_BANKED_REG) + #define GENERAL_REGISTER_P(REGNO) \ IN_RANGE ((REGNO), \ (unsigned HOST_WIDE_INT) FIRST_GENERAL_REG, \ diff --git a/gcc/config/sh/sh.md b/gcc/config/sh/sh.md index e85470eae74..be6294f4fda 100644 --- a/gcc/config/sh/sh.md +++ b/gcc/config/sh/sh.md @@ -463,6 +463,12 @@ (define_attr "needs_delay_slot" "yes,no" (const_string "no")) +(define_attr "banked" "yes,no" + (cond [(eq (symbol_ref "sh_loads_bankedreg_p (insn)") + (const_int 1)) + (const_string "yes")] + (const_string "no"))) + ;; ??? This should be (nil) instead of (const_int 0) (define_attr "hit_stack" "yes,no" (cond [(eq (symbol_ref "find_regno_note (insn, REG_INC, SP_REG)") @@ -541,8 +547,9 @@ (eq_attr "type" "!pload,prset")) (and (eq_attr "interrupt_function" "yes") (ior - (ne (symbol_ref "TARGET_SH3") (const_int 0)) - (eq_attr "hit_stack" "no"))))) (nil) (nil)]) + (eq (symbol_ref "TARGET_SH3") (const_int 0)) + (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. diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index caf24ed56be..f38fda0ee91 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,7 @@ +2007-06-21 Christian Bruel + + * gcc.dg/attr-isr.c: Test delay slot content. + 2007-06-20 Jerry DeLisle PR fortran/32361 diff --git a/gcc/testsuite/gcc.dg/attr-isr.c b/gcc/testsuite/gcc.dg/attr-isr.c index 113ac21d43c..8292fe9e7bf 100644 --- a/gcc/testsuite/gcc.dg/attr-isr.c +++ b/gcc/testsuite/gcc.dg/attr-isr.c @@ -16,3 +16,4 @@ void /* { dg-final { scan-assembler-times "\[^f\]r\[0-9\]\[ \t\]*," 8 } } */ /* { dg-final { scan-assembler-not "\[^f\]r1\[0-3\]" } } */ /* { dg-final { scan-assembler-times "macl" 2} } */ +/* { dg-final { scan-assembler-not "rte.*\n.*r15\[+\],r\[0-7\]\n" } } */