]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
backport: re PR rtl-optimization/41619 (ICE in insert_save (caller-save.c) for SPEC...
authorEric Botcazou <ebotcazou@adacore.com>
Thu, 26 May 2011 12:43:06 +0000 (12:43 +0000)
committerEric Botcazou <ebotcazou@gcc.gnu.org>
Thu, 26 May 2011 12:43:06 +0000 (12:43 +0000)
Backport from mainline
2011-01-21  Jeff Law  <law@redhat.com>

PR rtl-optimization/41619
* caller-save.c (setup_save_areas): Break out code to determine
which hard regs are live across calls by examining the reload chains
so that it is always used.
Eliminate code which checked REG_N_CALLS_CROSSED.

From-SVN: r174278

gcc/ChangeLog
gcc/caller-save.c

index 4a9b077940529e174566e70e31545c65b69d6c63..6ec4e5e952cc3606e99f518e6b671a348951b095 100644 (file)
@@ -1,3 +1,14 @@
+2011-05-26  Eric Botcazou  <ebotcazou@adacore.com>
+
+       Backport from mainline
+       2011-01-21  Jeff Law  <law@redhat.com>
+
+       PR rtl-optimization/41619
+       * caller-save.c (setup_save_areas): Break out code to determine
+       which hard regs are live across calls by examining the reload chains
+       so that it is always used.
+       Eliminate code which checked REG_N_CALLS_CROSSED.
+
 2011-05-25  Uros Bizjak  <ubizjak@gmail.com>
 
        PR target/49133
index 17fa028cb400ad565ae4d4188b94d4737a9baf9c..4d252d7495bbe7bcc23259b2241d638d17d7d1b0 100644 (file)
@@ -439,101 +439,93 @@ saved_hard_reg_compare_func (const void *v1p, const void *v2p)
 void
 setup_save_areas (void)
 {
-  int i, j, k;
-  unsigned int r;
+  int i, j, k, freq;
   HARD_REG_SET hard_regs_used;
+  struct saved_hard_reg *saved_reg;
+  rtx insn;
+  struct insn_chain *chain, *next;
+  unsigned int regno;
+  HARD_REG_SET hard_regs_to_save, used_regs, this_insn_sets;
+  reg_set_iterator rsi;
 
-  /* Allocate space in the save area for the largest multi-register
-     pseudos first, then work backwards to single register
-     pseudos.  */
-
-  /* Find and record all call-used hard-registers in this function.  */
   CLEAR_HARD_REG_SET (hard_regs_used);
-  for (i = FIRST_PSEUDO_REGISTER; i < max_regno; i++)
-    if (reg_renumber[i] >= 0 && REG_N_CALLS_CROSSED (i) > 0)
-      {
-       unsigned int regno = reg_renumber[i];
-       unsigned int endregno
-         = end_hard_regno (GET_MODE (regno_reg_rtx[i]), regno);
-       for (r = regno; r < endregno; r++)
-         if (call_used_regs[r])
-           SET_HARD_REG_BIT (hard_regs_used, r);
-      }
 
-  if (optimize && flag_ira_share_save_slots)
+  /* Find every CALL_INSN and record which hard regs are live across the
+     call into HARD_REG_MAP and HARD_REGS_USED.  */
+  initiate_saved_hard_regs ();
+  /* Create hard reg saved regs.  */
+  for (chain = reload_insn_chain; chain != 0; chain = next)
     {
-      rtx insn, slot;
-      struct insn_chain *chain, *next;
-      char *saved_reg_conflicts;
-      unsigned int regno;
-      int next_k, freq;
-      struct saved_hard_reg *saved_reg, *saved_reg2, *saved_reg3;
-      int call_saved_regs_num;
-      struct saved_hard_reg *call_saved_regs[FIRST_PSEUDO_REGISTER];
-      HARD_REG_SET hard_regs_to_save, used_regs, this_insn_sets;
-      reg_set_iterator rsi;
-      int best_slot_num;
-      int prev_save_slots_num;
-      rtx prev_save_slots[FIRST_PSEUDO_REGISTER];
-
-      initiate_saved_hard_regs ();
-      /* Create hard reg saved regs.  */
-      for (chain = reload_insn_chain; chain != 0; chain = next)
+      insn = chain->insn;
+      next = chain->next;
+      if (!CALL_P (insn)
+         || find_reg_note (insn, REG_NORETURN, NULL))
+       continue;
+      freq = REG_FREQ_FROM_BB (BLOCK_FOR_INSN (insn));
+      REG_SET_TO_HARD_REG_SET (hard_regs_to_save,
+                              &chain->live_throughout);
+      COPY_HARD_REG_SET (used_regs, call_used_reg_set);
+
+      /* Record all registers set in this call insn.  These don't
+        need to be saved.  N.B. the call insn might set a subreg
+        of a multi-hard-reg pseudo; then the pseudo is considered
+        live during the call, but the subreg that is set
+        isn't.  */
+      CLEAR_HARD_REG_SET (this_insn_sets);
+      note_stores (PATTERN (insn), mark_set_regs, &this_insn_sets);
+      /* Sibcalls are considered to set the return value.  */
+      if (SIBLING_CALL_P (insn) && crtl->return_rtx)
+       mark_set_regs (crtl->return_rtx, NULL_RTX, &this_insn_sets);
+
+      AND_COMPL_HARD_REG_SET (used_regs, call_fixed_reg_set);
+      AND_COMPL_HARD_REG_SET (used_regs, this_insn_sets);
+      AND_HARD_REG_SET (hard_regs_to_save, used_regs);
+      for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
+       if (TEST_HARD_REG_BIT (hard_regs_to_save, regno))
+         {
+           if (hard_reg_map[regno] != NULL)
+             hard_reg_map[regno]->call_freq += freq;
+           else
+             saved_reg = new_saved_hard_reg (regno, freq);
+           SET_HARD_REG_BIT (hard_regs_used, regno);
+         }
+      /* Look through all live pseudos, mark their hard registers.  */
+      EXECUTE_IF_SET_IN_REG_SET
+       (&chain->live_throughout, FIRST_PSEUDO_REGISTER, regno, rsi)
        {
-         insn = chain->insn;
-         next = chain->next;
-         if (!CALL_P (insn)
-             || find_reg_note (insn, REG_NORETURN, NULL))
-           continue;
-         freq = REG_FREQ_FROM_BB (BLOCK_FOR_INSN (insn));
-         REG_SET_TO_HARD_REG_SET (hard_regs_to_save,
-                                  &chain->live_throughout);
-         COPY_HARD_REG_SET (used_regs, call_used_reg_set);
+         int r = reg_renumber[regno];
+         int bound;
 
-         /* Record all registers set in this call insn.  These don't
-            need to be saved.  N.B. the call insn might set a subreg
-            of a multi-hard-reg pseudo; then the pseudo is considered
-            live during the call, but the subreg that is set
-            isn't.  */
-         CLEAR_HARD_REG_SET (this_insn_sets);
-         note_stores (PATTERN (insn), mark_set_regs, &this_insn_sets);
-         /* Sibcalls are considered to set the return value.  */
-         if (SIBLING_CALL_P (insn) && crtl->return_rtx)
-           mark_set_regs (crtl->return_rtx, NULL_RTX, &this_insn_sets);
+         if (r < 0)
+           continue;
 
-         AND_COMPL_HARD_REG_SET (used_regs, call_fixed_reg_set);
-         AND_COMPL_HARD_REG_SET (used_regs, this_insn_sets);
-         AND_HARD_REG_SET (hard_regs_to_save, used_regs);
-         for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
-           if (TEST_HARD_REG_BIT (hard_regs_to_save, regno))
+         bound = r + hard_regno_nregs[r][PSEUDO_REGNO_MODE (regno)];
+         for (; r < bound; r++)
+           if (TEST_HARD_REG_BIT (used_regs, r))
              {
-               if (hard_reg_map[regno] != NULL)
-                 hard_reg_map[regno]->call_freq += freq;
+               if (hard_reg_map[r] != NULL)
+                 hard_reg_map[r]->call_freq += freq;
                else
-                 saved_reg = new_saved_hard_reg (regno, freq);
+                 saved_reg = new_saved_hard_reg (r, freq);
+                SET_HARD_REG_BIT (hard_regs_to_save, r);
+                SET_HARD_REG_BIT (hard_regs_used, r);
              }
-         /* Look through all live pseudos, mark their hard registers.  */
-         EXECUTE_IF_SET_IN_REG_SET
-           (&chain->live_throughout, FIRST_PSEUDO_REGISTER, regno, rsi)
-           {
-             int r = reg_renumber[regno];
-             int bound;
+       }
+    }
 
-             if (r < 0)
-               continue;
+  /* If requested, figure out which hard regs can share save slots.  */
+  if (optimize && flag_ira_share_save_slots)
+    {
+      rtx slot;
+      char *saved_reg_conflicts;
+      int next_k;
+      struct saved_hard_reg *saved_reg2, *saved_reg3;
+      int call_saved_regs_num;
+      struct saved_hard_reg *call_saved_regs[FIRST_PSEUDO_REGISTER];
+      int best_slot_num;
+      int prev_save_slots_num;
+      rtx prev_save_slots[FIRST_PSEUDO_REGISTER];
 
-             bound = r + hard_regno_nregs[r][PSEUDO_REGNO_MODE (regno)];
-             for (; r < bound; r++)
-               if (TEST_HARD_REG_BIT (used_regs, r))
-                 {
-                   if (hard_reg_map[r] != NULL)
-                     hard_reg_map[r]->call_freq += freq;
-                   else
-                     saved_reg = new_saved_hard_reg (r, freq);
-                   SET_HARD_REG_BIT (hard_regs_to_save, r);
-                 }
-           }
-       }
       /* Find saved hard register conflicts.  */
       saved_reg_conflicts = (char *) xmalloc (saved_regs_num * saved_regs_num);
       memset (saved_reg_conflicts, 0, saved_regs_num * saved_regs_num);
@@ -691,8 +683,10 @@ setup_save_areas (void)
     }
   else
     {
-      /* Now run through all the call-used hard-registers and allocate
-        space for them in the caller-save area.  Try to allocate space
+      /* We are not sharing slots. 
+
+        Run through all the call-used hard-registers and allocate
+        space for each in the caller-save area.  Try to allocate space
         in a manner which allows multi-register saves/restores to be done.  */
 
       for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)