OSDN Git Service

* sh.c (calc_live_regs): If the return address pointer is live,
authoramylaar <amylaar@138bc75d-0d04-0410-961f-82ee72b054a4>
Thu, 7 Aug 2003 22:40:07 +0000 (22:40 +0000)
committeramylaar <amylaar@138bc75d-0d04-0410-961f-82ee72b054a4>
Thu, 7 Aug 2003 22:40:07 +0000 (22:40 +0000)
force pr live.
(sh5_schedule_saves): Exclude PR_MEDIA_REG from being a temp register
for saves / restores.
(sh_expand_epilogue): If sh_media_register_for_return returns a
register number, flag the instructions that restores PR_MEDIA_REG
as possibly dead.
Remove dead update of offset.
(sh_get_pr_initial_val): Use UNSPEC_RA if we don't know yet if
we can use the result of get_hard_reg_initial_val.
* sh.md (UNSPEC_RA): New constant.
(movsi_i_lowpart+1): Changed into a define_insn_and_split, named:
(load_ra).  Handle UNSPEC_RA.
(sibcall_media): Use PR_MEDIA_REG.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@70234 138bc75d-0d04-0410-961f-82ee72b054a4

gcc/ChangeLog
gcc/config/sh/sh.c
gcc/config/sh/sh.md

index 9568cca..4eb8d9c 100644 (file)
@@ -1,5 +1,20 @@
 2003-08-07  J"orn Rennecke <joern.rennecke@superh.com>
 
+       * sh.c (calc_live_regs): If the return address pointer is live,
+       force pr live.
+       (sh5_schedule_saves): Exclude PR_MEDIA_REG from being a temp register
+       for saves / restores.
+       (sh_expand_epilogue): If sh_media_register_for_return returns a
+       register number, flag the instructions that restores PR_MEDIA_REG
+       as possibly dead.
+       Remove dead update of offset.
+       (sh_get_pr_initial_val): Use UNSPEC_RA if we don't know yet if
+       we can use the result of get_hard_reg_initial_val.
+       * sh.md (UNSPEC_RA): New constant.
+       (movsi_i_lowpart+1): Changed into a define_insn_and_split, named:
+       (load_ra).  Handle UNSPEC_RA.
+       (sibcall_media): Use PR_MEDIA_REG.
+
        * sh.h (CALL_USED_REGISTERS): Include PR_REG and PR_MEDIA_REG.
        * sh.c (calc_live_regs): Use sh_pr_n_sets to determine if pr
        needs saving on SHmedia.
index d64d919..d1b203b 100644 (file)
@@ -4848,6 +4848,8 @@ calc_live_regs (live_regs_mask)
      the initial value can become the PR_MEDIA_REG hard register, as seen for
      execute/20010122-1.c:test9.  */
   if (TARGET_SHMEDIA)
+    /* ??? this function is called from initial_elimination_offset, hence we
+       can't use the result of sh_media_register_for_return here.  */
     pr_live = sh_pr_n_sets ();
   else
     {
@@ -4856,6 +4858,10 @@ calc_live_regs (live_regs_mask)
                 ? (GET_CODE (pr_initial) != REG
                    || REGNO (pr_initial) != (PR_REG))
                 : regs_ever_live[PR_REG]);
+      /* For Shcompact, if not optimizing, we end up with a memory reference
+        using the return address pointer for __builtin_return_address even
+        though there is no actual need to put the PR register on the stack.  */
+      pr_live |= regs_ever_live[RETURN_ADDRESS_POINTER_REGNUM];
     }
   /* Force PR to be live if the prologue has to call the SHmedia
      argument decoder or register saver.  */
@@ -5027,7 +5033,7 @@ sh5_schedule_saves (HARD_REG_SET *live_regs_mask, save_schedule *schedule,
 
   if (! current_function_interrupt)
     for (i = FIRST_GENERAL_REG; tmpx < MAX_TEMPS && i <= LAST_GENERAL_REG; i++)
-      if (call_used_regs[i] && ! fixed_regs[i]
+      if (call_used_regs[i] && ! fixed_regs[i] && i != PR_MEDIA_REG
          && ! FUNCTION_ARG_REGNO_P (i)
          && i != FIRST_RET_REG
          && ! (current_function_needs_context && i == STATIC_CHAIN_REGNUM)
@@ -5169,6 +5175,9 @@ sh_expand_prologue ()
          rtx insn = emit_move_insn (gen_rtx_REG (DImode, tr),
                                     gen_rtx_REG (DImode, PR_MEDIA_REG));
 
+         /* ??? We should suppress saving pr when we don't need it, but this
+            is tricky because of builtin_return_address.  */
+
          /* If this function only exits with sibcalls, this copy
             will be flagged as dead.  */
          REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_MAYBE_DEAD,
@@ -5552,7 +5561,7 @@ sh_expand_epilogue ()
       save_schedule schedule;
       save_entry *entry;
       int *tmp_pnt;
-      
+
       entry = sh5_schedule_saves (&live_regs_mask, &schedule, d_rounding);
       offset_base = -entry[1].offset + d_rounding;
       tmp_pnt = schedule.temps;
@@ -5660,8 +5669,11 @@ sh_expand_epilogue ()
            }
 
          insn = emit_move_insn (reg_rtx, mem_rtx);
-
-         offset += GET_MODE_SIZE (mode);
+         if (reg == PR_MEDIA_REG && sh_media_register_for_return () >= 0)
+           /* This is dead, unless we return with a sibcall.  */
+           REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_MAYBE_DEAD,
+                                                 const0_rtx,
+                                                 REG_NOTES (insn));
        }
 
       if (entry->offset + offset_base != d + d_rounding)
@@ -8835,17 +8847,29 @@ scavenge_reg (HARD_REG_SET *s)
 rtx
 sh_get_pr_initial_val (void)
 {
+  rtx val;
+
   /* ??? Unfortunately, get_hard_reg_initial_val doesn't always work for the
      PR register on SHcompact, because it might be clobbered by the prologue.
-     We don't know if that's the case before rtl generation is finished.  */
+     We check first if that is known to be the case.  */
   if (TARGET_SHCOMPACT
-      && (rtx_equal_function_value_matters
-         || (current_function_args_info.call_cookie
-              & ~ CALL_COOKIE_RET_TRAMP (1))
+      && ((current_function_args_info.call_cookie
+          & ~ CALL_COOKIE_RET_TRAMP (1))
          || current_function_has_nonlocal_label))
     return gen_rtx_MEM (SImode, return_address_pointer_rtx);
-  return
-    get_hard_reg_initial_val (Pmode, TARGET_SHMEDIA ? PR_MEDIA_REG : PR_REG);
+
+  /* If we haven't finished rtl generation, there might be a nonlocal label
+     that we haven't seen yet.
+     ??? get_hard_reg_initial_val fails if it is called while no_new_pseudos
+     is set, unless it has been called before for the same register.  And even
+     then, we end in trouble if we didn't use the register in the same
+     basic block before.  So call get_hard_reg_initial_val now and wrap it
+     in an unspec if we might need to replace it.  */
+  val
+    = get_hard_reg_initial_val (Pmode, TARGET_SHMEDIA ? PR_MEDIA_REG : PR_REG);
+  if (TARGET_SHCOMPACT && rtx_equal_function_value_matters)
+    return gen_rtx_UNSPEC (SImode, gen_rtvec (1, val), UNSPEC_RA);
+  return val;
 }
 
 #include "gt-sh.h"
index d4dd5d1..2c8462f 100644 (file)
   (UNSPEC_DTPOFF       23)
   (UNSPEC_GOTTPOFF     24)
   (UNSPEC_TPOFF                25)
+  (UNSPEC_RA           26)
 
   ;; These are used with unspec_volatile.
   (UNSPECV_BLOCKAGE    0)
        fake    %1,%0"
   [(set_attr "type" "pcload,move,load,move,prget,move,store,pcload")])
 
-(define_split
+(define_insn_and_split "load_ra"
   [(set (match_operand:SI 0 "general_movdst_operand" "")
-       (mem:SI (reg:SI RAP_REG)))]
-  "TARGET_SHCOMPACT
-   && ! rtx_equal_function_value_matters
-   && ! ((current_function_args_info.call_cookie
-         & ~ CALL_COOKIE_RET_TRAMP (1))
-        || current_function_has_nonlocal_label)"
+       (unspec:SI [(match_operand 1 "register_operand" "")] UNSPEC_RA))]
+  "TARGET_SHCOMPACT"
+  "#"
+  "&& ! rtx_equal_function_value_matters"
   [(set (match_dup 0) (match_dup 1))]
-  "operands[1] = sh_get_pr_initial_val ();")
+  "
+{
+  if (current_function_has_nonlocal_label)
+    operands[1] = gen_rtx_MEM (SImode, return_address_pointer_rtx);
+}")
 
 (define_insn "*movsi_media"
   [(set (match_operand:SI 0 "general_movdst_operand"
 (define_insn "sibcall_media"
   [(call (mem:DI (match_operand:DI 0 "target_reg_operand" "k"))
         (match_operand 1 "" ""))
+   (use (reg:SI PR_MEDIA_REG))
    (return)]
   "TARGET_SHMEDIA"
   "blink       %0, r63"