OSDN Git Service

Daily bump.
[pf3gnuchains/gcc-fork.git] / gcc / ira.c
index de7f5b6..41a2928 100644 (file)
--- a/gcc/ira.c
+++ b/gcc/ira.c
@@ -1,5 +1,5 @@
 /* Integrated Register Allocator (IRA) entry point.
-   Copyright (C) 2006, 2007, 2008, 2009, 2010, 2011
+   Copyright (C) 2006, 2007, 2008, 2009, 2010, 2011, 2012
    Free Software Foundation, Inc.
    Contributed by Vladimir Makarov <vmakarov@redhat.com>.
 
@@ -383,6 +383,7 @@ along with GCC; see the file COPYING3.  If not see
 #include "integrate.h"
 #include "ggc.h"
 #include "ira-int.h"
+#include "dce.h"
 
 
 struct target_ira default_target_ira;
@@ -405,11 +406,12 @@ int ira_spilled_reg_stack_slots_num;
    stack slots used in current function so far.  */
 struct ira_spilled_reg_stack_slot *ira_spilled_reg_stack_slots;
 
-/* Correspondingly overall cost of the allocation, cost of the
-   allocnos assigned to hard-registers, cost of the allocnos assigned
-   to memory, cost of loads, stores and register move insns generated
-   for pseudo-register live range splitting (see ira-emit.c).  */
-int ira_overall_cost;
+/* Correspondingly overall cost of the allocation, overall cost before
+   reload, cost of the allocnos assigned to hard-registers, cost of
+   the allocnos assigned to memory, cost of loads, stores and register
+   move insns generated for pseudo-register live range splitting (see
+   ira-emit.c).  */
+int ira_overall_cost, overall_cost_before;
 int ira_reg_cost, ira_mem_cost;
 int ira_load_cost, ira_store_cost, ira_shuffle_cost;
 int ira_move_loops_num, ira_additional_jumps_num;
@@ -583,11 +585,11 @@ setup_class_subset_and_memory_move_costs (void)
            ira_max_memory_move_cost[mode][cl][0]
              = ira_memory_move_cost[mode][cl][0]
              = memory_move_cost ((enum machine_mode) mode,
-                                 (enum reg_class) cl, false);
+                                 (reg_class_t) cl, false);
            ira_max_memory_move_cost[mode][cl][1]
              = ira_memory_move_cost[mode][cl][1]
              = memory_move_cost ((enum machine_mode) mode,
-                                 (enum reg_class) cl, true);
+                                 (reg_class_t) cl, true);
            /* Costs for NO_REGS are used in cost calculation on the
               1st pass when the preferred register classes are not
               known yet.  In this case we take the best scenario.  */
@@ -716,7 +718,7 @@ ira_print_disposition (FILE *f)
        if ((bb = ALLOCNO_LOOP_TREE_NODE (a)->bb) != NULL)
          fprintf (f, "b%-3d", bb->index);
        else
-         fprintf (f, "l%-3d", ALLOCNO_LOOP_TREE_NODE (a)->loop->num);
+         fprintf (f, "l%-3d", ALLOCNO_LOOP_TREE_NODE (a)->loop_num);
        if (ALLOCNO_HARD_REGNO (a) >= 0)
          fprintf (f, " %3d", ALLOCNO_HARD_REGNO (a));
        else
@@ -799,27 +801,35 @@ setup_pressure_classes (void)
     {
       if (ira_available_class_regs[cl] == 0)
        continue;
-      /* Check that the moves between any hard registers of the
-        current class are not more expensive for a legal mode than
-        load/store of the hard registers of the current class.  Such
-        class is a potential candidate to be a register pressure
-        class.  */
-      for (m = 0; m < NUM_MACHINE_MODES; m++)
+      if (ira_available_class_regs[cl] != 1
+         /* A register class without subclasses may contain a few
+            hard registers and movement between them is costly
+            (e.g. SPARC FPCC registers).  We still should consider it
+            as a candidate for a pressure class.  */
+         && alloc_reg_class_subclasses[cl][0] != LIM_REG_CLASSES)
        {
-         COPY_HARD_REG_SET (temp_hard_regset, reg_class_contents[cl]);
-         AND_COMPL_HARD_REG_SET (temp_hard_regset, no_unit_alloc_regs);
-         AND_COMPL_HARD_REG_SET (temp_hard_regset,
-                                 ira_prohibited_class_mode_regs[cl][m]);
-         if (hard_reg_set_empty_p (temp_hard_regset))
+         /* Check that the moves between any hard registers of the
+            current class are not more expensive for a legal mode
+            than load/store of the hard registers of the current
+            class.  Such class is a potential candidate to be a
+            register pressure class.  */
+         for (m = 0; m < NUM_MACHINE_MODES; m++)
+           {
+             COPY_HARD_REG_SET (temp_hard_regset, reg_class_contents[cl]);
+             AND_COMPL_HARD_REG_SET (temp_hard_regset, no_unit_alloc_regs);
+             AND_COMPL_HARD_REG_SET (temp_hard_regset,
+                                     ira_prohibited_class_mode_regs[cl][m]);
+             if (hard_reg_set_empty_p (temp_hard_regset))
+               continue;
+             ira_init_register_move_cost_if_necessary ((enum machine_mode) m);
+             cost = ira_register_move_cost[m][cl][cl];
+             if (cost <= ira_max_memory_move_cost[m][cl][1]
+                 || cost <= ira_max_memory_move_cost[m][cl][0])
+               break;
+           }
+         if (m >= NUM_MACHINE_MODES)
            continue;
-         ira_init_register_move_cost_if_necessary ((enum machine_mode) m);
-         cost = ira_register_move_cost[m][cl][cl];
-         if (cost <= ira_max_memory_move_cost[m][cl][1]
-             || cost <= ira_max_memory_move_cost[m][cl][0])
-           break;
        }
-      if (m >= NUM_MACHINE_MODES)
-       continue;
       curr = 0;
       insert_p = true;
       COPY_HARD_REG_SET (temp_hard_regset, reg_class_contents[cl]);
@@ -848,6 +858,8 @@ setup_pressure_classes (void)
              && (! hard_reg_set_equal_p (temp_hard_regset2, temp_hard_regset)
                  || cl == (int) GENERAL_REGS))
            continue;
+         if (hard_reg_set_equal_p (temp_hard_regset2, temp_hard_regset))
+           insert_p = false;
          pressure_classes[curr++] = (enum reg_class) cl2;
        }
       /* If the current candidate is a subset of a so far added
@@ -858,23 +870,44 @@ setup_pressure_classes (void)
       n = curr;
     }
 #ifdef ENABLE_IRA_CHECKING
-  /* Check pressure classes correctness: here we check that hard
-     registers from all register pressure classes contains all hard
-     registers available for the allocation.  */
-  CLEAR_HARD_REG_SET (temp_hard_regset);
-  CLEAR_HARD_REG_SET (temp_hard_regset2);
-  for (cl = 0; cl <= LIM_REG_CLASSES; cl++)
-    {
-      for (i = 0; i < n; i++)
-       if ((int) pressure_classes[i] == cl)
-         break;
-      IOR_HARD_REG_SET (temp_hard_regset2, reg_class_contents[cl]);
-      if (i >= n)
-       IOR_HARD_REG_SET (temp_hard_regset, reg_class_contents[cl]);
-    }
-  AND_COMPL_HARD_REG_SET (temp_hard_regset, no_unit_alloc_regs);
-  AND_COMPL_HARD_REG_SET (temp_hard_regset2, no_unit_alloc_regs);
-  ira_assert (hard_reg_set_subset_p (temp_hard_regset2, temp_hard_regset));
+  {
+    HARD_REG_SET ignore_hard_regs;
+
+    /* Check pressure classes correctness: here we check that hard
+       registers from all register pressure classes contains all hard
+       registers available for the allocation.  */
+    CLEAR_HARD_REG_SET (temp_hard_regset);
+    CLEAR_HARD_REG_SET (temp_hard_regset2);
+    COPY_HARD_REG_SET (ignore_hard_regs, no_unit_alloc_regs);
+    for (cl = 0; cl < LIM_REG_CLASSES; cl++)
+      {
+       /* For some targets (like MIPS with MD_REGS), there are some
+          classes with hard registers available for allocation but
+          not able to hold value of any mode.  */
+       for (m = 0; m < NUM_MACHINE_MODES; m++)
+         if (contains_reg_of_mode[cl][m])
+           break;
+       if (m >= NUM_MACHINE_MODES)
+         {
+           IOR_HARD_REG_SET (ignore_hard_regs, reg_class_contents[cl]);
+           continue;
+         }
+       for (i = 0; i < n; i++)
+         if ((int) pressure_classes[i] == cl)
+           break;
+       IOR_HARD_REG_SET (temp_hard_regset2, reg_class_contents[cl]);
+       if (i < n)
+         IOR_HARD_REG_SET (temp_hard_regset, reg_class_contents[cl]);
+      }
+    for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
+      /* Some targets (like SPARC with ICC reg) have alocatable regs
+        for which no reg class is defined.  */
+      if (REGNO_REG_CLASS (i) == NO_REGS)
+       SET_HARD_REG_BIT (ignore_hard_regs, i);
+    AND_COMPL_HARD_REG_SET (temp_hard_regset, ignore_hard_regs);
+    AND_COMPL_HARD_REG_SET (temp_hard_regset2, ignore_hard_regs);
+    ira_assert (hard_reg_set_subset_p (temp_hard_regset2, temp_hard_regset));
+  }
 #endif
   ira_pressure_classes_num = 0;
   for (i = 0; i < n; i++)
@@ -923,7 +956,7 @@ setup_allocno_and_important_classes (void)
   /* Collect classes which contain unique sets of allocatable hard
      registers.  Prefer GENERAL_REGS to other classes containing the
      same set of hard registers.  */
-  for (i = 0; i <= LIM_REG_CLASSES; i++)
+  for (i = 0; i < LIM_REG_CLASSES; i++)
     {
       COPY_HARD_REG_SET (temp_hard_regset, reg_class_contents[i]);
       AND_COMPL_HARD_REG_SET (temp_hard_regset, no_unit_alloc_regs);
@@ -1371,7 +1404,7 @@ setup_reg_class_nregs (void)
       for (cl = 0; cl < N_REG_CLASSES; cl++)
        ira_reg_class_max_nregs[cl][m]
          = ira_reg_class_min_nregs[cl][m]
-         = CLASS_MAX_NREGS ((enum reg_class) cl, (enum machine_mode) m);
+         = targetm.class_max_nregs ((reg_class_t) cl, (enum machine_mode) m);
       for (cl = 0; cl < N_REG_CLASSES; cl++)
        for (i = 0;
             (cl2 = alloc_reg_class_subclasses[cl][i]) != LIM_REG_CLASSES;
@@ -1422,6 +1455,12 @@ clarify_prohibited_class_mode_regs (void)
          if (TEST_HARD_REG_BIT (ira_prohibited_class_mode_regs[cl][j], hard_regno))
            continue;
          nregs = hard_regno_nregs[hard_regno][j];
+          if (hard_regno + nregs > FIRST_PSEUDO_REGISTER)
+            {
+              SET_HARD_REG_BIT (ira_prohibited_class_mode_regs[cl][j],
+                                hard_regno);
+               continue;
+            }
          pclass = ira_pressure_class_translate[REGNO_REG_CLASS (hard_regno)];
          for (nregs-- ;nregs >= 0; nregs--)
            if (((enum reg_class) pclass
@@ -1463,6 +1502,10 @@ ira_init_register_move_cost (enum machine_mode mode)
          sizeof (move_table) * N_REG_CLASSES);
   for (cl1 = 0; cl1 < N_REG_CLASSES; cl1++)
     {
+      /* Some subclasses are to small to have enough registers to hold
+        a value of MODE.  Just ignore them.  */
+      if (ira_reg_class_max_nregs[cl1][mode] > ira_available_class_regs[cl1])
+       continue;
       COPY_HARD_REG_SET (temp_hard_regset, reg_class_contents[cl1]);
       AND_COMPL_HARD_REG_SET (temp_hard_regset, no_unit_alloc_regs);
       if (hard_reg_set_empty_p (temp_hard_regset))
@@ -1556,16 +1599,11 @@ free_register_move_costs (void)
 
   for (mode = 0; mode < MAX_MACHINE_MODE; mode++)
     {
-      if (ira_max_register_move_cost[mode] != NULL)
-       free (ira_max_register_move_cost[mode]);
-      if (ira_may_move_in_cost[mode] != NULL)
-       free (ira_may_move_in_cost[mode]);
-      if (ira_may_move_out_cost[mode] != NULL)
-       free (ira_may_move_out_cost[mode]);
-      if (ira_max_may_move_in_cost[mode] != NULL)
-       free (ira_max_may_move_in_cost[mode]);
-      if (ira_max_may_move_out_cost[mode] != NULL)
-       free (ira_max_may_move_out_cost[mode]);
+      free (ira_max_register_move_cost[mode]);
+      free (ira_may_move_in_cost[mode]);
+      free (ira_may_move_out_cost[mode]);
+      free (ira_max_may_move_in_cost[mode]);
+      free (ira_max_may_move_out_cost[mode]);
       ira_register_move_cost[mode] = NULL;
       ira_max_register_move_cost[mode] = NULL;
       ira_may_move_in_cost[mode] = NULL;
@@ -1724,16 +1762,10 @@ compute_regs_asm_clobbered (void)
              {
                df_ref def = *def_rec;
                unsigned int dregno = DF_REF_REGNO (def);
-               if (dregno < FIRST_PSEUDO_REGISTER)
-                 {
-                   unsigned int i;
-                   enum machine_mode mode = GET_MODE (DF_REF_REAL_REG (def));
-                   unsigned int end = dregno
-                     + hard_regno_nregs[dregno][mode] - 1;
-
-                   for (i = dregno; i <= end; ++i)
-                     SET_HARD_REG_BIT(crtl->asm_clobbers, i);
-                 }
+               if (HARD_REGISTER_NUM_P (dregno))
+                 add_to_hard_reg_set (&crtl->asm_clobbers,
+                                      GET_MODE (DF_REF_REAL_REG (def)),
+                                      dregno);
              }
        }
     }
@@ -1836,15 +1868,15 @@ rtx *ira_reg_equiv_const;
 static void
 find_reg_equiv_invariant_const (void)
 {
-  int i;
+  unsigned int i;
   bool invariant_p;
   rtx list, insn, note, constant, x;
 
-  for (i = FIRST_PSEUDO_REGISTER; i < reg_equiv_init_size; i++)
+  for (i = FIRST_PSEUDO_REGISTER; i < VEC_length (reg_equivs_t, reg_equivs); i++)
     {
       constant = NULL_RTX;
       invariant_p = false;
-      for (list = reg_equiv_init[i]; list != NULL_RTX; list = XEXP (list, 1))
+      for (list = reg_equiv_init (i); list != NULL_RTX; list = XEXP (list, 1))
        {
          insn = XEXP (list, 0);
          note = find_reg_note (insn, REG_EQUIV, NULL_RTX);
@@ -1926,8 +1958,8 @@ setup_reg_renumber (void)
                                      reg_class_contents[pclass]);
            }
          if (ALLOCNO_CALLS_CROSSED_NUM (a) != 0
-             && ! ira_hard_reg_not_in_set_p (hard_regno, ALLOCNO_MODE (a),
-                                             call_used_reg_set))
+             && ira_hard_reg_set_intersection_p (hard_regno, ALLOCNO_MODE (a),
+                                                 call_used_reg_set))
            {
              ira_assert (!optimize || flag_caller_saves
                          || regno >= ira_reg_equiv_len
@@ -1965,10 +1997,10 @@ setup_allocno_assignment_flags (void)
                                || ALLOCNO_EMIT_DATA (a)->mem_optimized_dest_p
                                || (ALLOCNO_MEMORY_COST (a)
                                    - ALLOCNO_CLASS_COST (a)) < 0);
-      ira_assert (hard_regno < 0
-                 || ! ira_hard_reg_not_in_set_p (hard_regno, ALLOCNO_MODE (a),
-                                                 reg_class_contents
-                                                 [ALLOCNO_CLASS (a)]));
+      ira_assert
+       (hard_regno < 0
+        || ira_hard_reg_in_set_p (hard_regno, ALLOCNO_MODE (a),
+                                  reg_class_contents[ALLOCNO_CLASS (a)]));
     }
 }
 
@@ -1986,9 +2018,9 @@ calculate_allocation_cost (void)
     {
       hard_regno = ALLOCNO_HARD_REGNO (a);
       ira_assert (hard_regno < 0
-                 || ! ira_hard_reg_not_in_set_p
-                      (hard_regno, ALLOCNO_MODE (a),
-                       reg_class_contents[ALLOCNO_CLASS (a)]));
+                 || (ira_hard_reg_in_set_p
+                     (hard_regno, ALLOCNO_MODE (a),
+                      reg_class_contents[ALLOCNO_CLASS (a)])));
       if (hard_regno < 0)
        {
          cost = ALLOCNO_MEMORY_COST (a);
@@ -2057,7 +2089,7 @@ check_allocation (void)
          int this_regno = hard_regno;
          if (n > 1)
            {
-             if (WORDS_BIG_ENDIAN)
+             if (REG_WORDS_BIG_ENDIAN)
                this_regno += n - i - 1;
              else
                this_regno += i;
@@ -2076,7 +2108,7 @@ check_allocation (void)
              if (ALLOCNO_NUM_OBJECTS (conflict_a) > 1
                  && conflict_nregs == ALLOCNO_NUM_OBJECTS (conflict_a))
                {
-                 if (WORDS_BIG_ENDIAN)
+                 if (REG_WORDS_BIG_ENDIAN)
                    conflict_hard_regno += (ALLOCNO_NUM_OBJECTS (conflict_a)
                                            - OBJECT_SUBWORD (conflict_obj) - 1);
                  else
@@ -2104,17 +2136,18 @@ check_allocation (void)
 static void
 fix_reg_equiv_init (void)
 {
-  int max_regno = max_reg_num ();
-  int i, new_regno;
+  unsigned int max_regno = max_reg_num ();
+  int i, new_regno, max;
   rtx x, prev, next, insn, set;
 
-  if (reg_equiv_init_size < max_regno)
+  if (VEC_length (reg_equivs_t, reg_equivs) < max_regno)
     {
-      reg_equiv_init = GGC_RESIZEVEC (rtx, reg_equiv_init, max_regno);
-      while (reg_equiv_init_size < max_regno)
-       reg_equiv_init[reg_equiv_init_size++] = NULL_RTX;
-      for (i = FIRST_PSEUDO_REGISTER; i < reg_equiv_init_size; i++)
-       for (prev = NULL_RTX, x = reg_equiv_init[i]; x != NULL_RTX; x = next)
+      max = VEC_length (reg_equivs_t, reg_equivs);
+      grow_reg_equivs ();
+      for (i = FIRST_PSEUDO_REGISTER; i < max; i++)
+       for (prev = NULL_RTX, x = reg_equiv_init (i);
+            x != NULL_RTX;
+            x = next)
          {
            next = XEXP (x, 1);
            insn = XEXP (x, 0);
@@ -2136,11 +2169,11 @@ fix_reg_equiv_init (void)
            else
              {
                if (prev == NULL_RTX)
-                 reg_equiv_init[i] = next;
+                 reg_equiv_init (i) = next;
                else
                  XEXP (prev, 1) = next;
-               XEXP (x, 1) = reg_equiv_init[new_regno];
-               reg_equiv_init[new_regno] = x;
+               XEXP (x, 1) = reg_equiv_init (new_regno);
+               reg_equiv_init (new_regno) = x;
              }
          }
     }
@@ -2302,7 +2335,7 @@ validate_equiv_mem_from_store (rtx dest, const_rtx set ATTRIBUTE_UNUSED,
   if ((REG_P (dest)
        && reg_overlap_mentioned_p (dest, equiv_mem))
       || (MEM_P (dest)
-         && true_dependence (dest, VOIDmode, equiv_mem, rtx_varies_p)))
+         && true_dependence (dest, VOIDmode, equiv_mem)))
     equiv_mem_modified = 1;
 }
 
@@ -2556,7 +2589,7 @@ memref_referenced_p (rtx memref, rtx x)
                                      reg_equiv[REGNO (x)].replacement));
 
     case MEM:
-      if (true_dependence (memref, VOIDmode, x, rtx_varies_p))
+      if (true_dependence (memref, VOIDmode, x))
        return 1;
       break;
 
@@ -2645,7 +2678,7 @@ no_equiv (rtx reg, const_rtx store ATTRIBUTE_UNUSED,
      should keep their initialization insns.  */
   if (reg_equiv[regno].is_arg_equivalence)
     return;
-  reg_equiv_init[regno] = NULL_RTX;
+  reg_equiv_init (regno) = NULL_RTX;
   for (; list; list =  XEXP (list, 1))
     {
       rtx insn = XEXP (list, 0);
@@ -2697,8 +2730,7 @@ update_equiv_regs (void)
   recorded_label_ref = 0;
 
   reg_equiv = XCNEWVEC (struct equivalence, max_regno);
-  reg_equiv_init = ggc_alloc_cleared_vec_rtx (max_regno);
-  reg_equiv_init_size = max_regno;
+  grow_reg_equivs ();
 
   init_alias_analysis ();
 
@@ -2763,8 +2795,8 @@ update_equiv_regs (void)
 
              /* Record for reload that this is an equivalencing insn.  */
              if (rtx_equal_p (src, XEXP (note, 0)))
-               reg_equiv_init[regno]
-                 = gen_rtx_INSN_LIST (VOIDmode, insn, reg_equiv_init[regno]);
+               reg_equiv_init (regno)
+                 = gen_rtx_INSN_LIST (VOIDmode, insn, reg_equiv_init (regno));
 
              /* Continue normally in case this is a candidate for
                 replacements.  */
@@ -2864,8 +2896,8 @@ update_equiv_regs (void)
              /* If we haven't done so, record for reload that this is an
                 equivalencing insn.  */
              if (!reg_equiv[regno].is_arg_equivalence)
-               reg_equiv_init[regno]
-                 = gen_rtx_INSN_LIST (VOIDmode, insn, reg_equiv_init[regno]);
+               reg_equiv_init (regno)
+                 = gen_rtx_INSN_LIST (VOIDmode, insn, reg_equiv_init (regno));
 
              /* Record whether or not we created a REG_EQUIV note for a LABEL_REF.
                 We might end up substituting the LABEL_REF for uses of the
@@ -2965,7 +2997,7 @@ update_equiv_regs (void)
            {
              /* This insn makes the equivalence, not the one initializing
                 the register.  */
-             reg_equiv_init[regno]
+             reg_equiv_init (regno)
                = gen_rtx_INSN_LIST (VOIDmode, insn, NULL_RTX);
              df_notes_rescan (init_insn);
            }
@@ -3068,7 +3100,7 @@ update_equiv_regs (void)
                      reg_equiv[regno].init_insns
                        = XEXP (reg_equiv[regno].init_insns, 1);
 
-                     reg_equiv_init[regno] = NULL_RTX;
+                     reg_equiv_init (regno) = NULL_RTX;
                      bitmap_set_bit (cleared_regs, regno);
                    }
                  /* Move the initialization of the register to just before
@@ -3101,7 +3133,7 @@ update_equiv_regs (void)
                      if (insn == BB_HEAD (bb))
                        BB_HEAD (bb) = PREV_INSN (insn);
 
-                     reg_equiv_init[regno]
+                     reg_equiv_init (regno)
                        = gen_rtx_INSN_LIST (VOIDmode, new_insn, NULL_RTX);
                      bitmap_set_bit (cleared_regs, regno);
                    }
@@ -3467,8 +3499,7 @@ build_insn_chain (void)
     }
 
   for (i = 0; i < (unsigned int) max_regno; i++)
-    if (live_subregs[i])
-      free (live_subregs[i]);
+    free (live_subregs[i]);
 
   reload_insn_chain = c;
   *p = NULL;
@@ -3481,19 +3512,8 @@ build_insn_chain (void)
   if (dump_file)
     print_insn_chains (dump_file);
 }
-\f
-/* Allocate memory for reg_equiv_memory_loc.  */
-static void
-init_reg_equiv_memory_loc (void)
-{
-  max_regno = max_reg_num ();
 
-  /* And the reg_equiv_memory_loc array.  */
-  VEC_safe_grow (rtx, gc, reg_equiv_memory_loc_vec, max_regno);
-  memset (VEC_address (rtx, reg_equiv_memory_loc_vec), 0,
-         sizeof (rtx) * max_regno);
-  reg_equiv_memory_loc = VEC_address (rtx, reg_equiv_memory_loc_vec);
-}
+\f
 
 /* All natural loops.  */
 struct loops ira_loops;
@@ -3502,18 +3522,17 @@ struct loops ira_loops;
    mode or when the conflict table is too big.  */
 bool ira_conflicts_p;
 
+/* Saved between IRA and reload.  */
+static int saved_flag_ira_share_spill_slots;
+
 /* This is the main entry of IRA.  */
 static void
 ira (FILE *f)
 {
-  int overall_cost_before, allocated_reg_info_size;
+  int allocated_reg_info_size;
   bool loops_p;
   int max_regno_before_ira, ira_max_point_before_emit;
   int rebuild_p;
-  int saved_flag_ira_share_spill_slots;
-  basic_block bb;
-
-  timevar_push (TV_IRA);
 
   if (flag_caller_saves)
     init_caller_save ();
@@ -3595,17 +3614,16 @@ ira (FILE *f)
   ira_move_loops_num = ira_additional_jumps_num = 0;
 
   ira_assert (current_loops == NULL);
-  flow_loops_find (&ira_loops);
-  record_loop_exits ();
-  current_loops = &ira_loops;
-
-  init_reg_equiv_memory_loc ();
+  if (flag_ira_region == IRA_REGION_ALL || flag_ira_region == IRA_REGION_MIXED)
+    {
+      flow_loops_find (&ira_loops);
+      record_loop_exits ();
+      current_loops = &ira_loops;
+    }
 
   if (internal_flag_ira_verbose > 0 && ira_dump_file != NULL)
     fprintf (ira_dump_file, "Building IRA IR\n");
-  loops_p = ira_build (optimize
-                      && (flag_ira_region == IRA_REGION_ALL
-                          || flag_ira_region == IRA_REGION_MIXED));
+  loops_p = ira_build ();
 
   ira_assert (ira_conflicts_p || !loops_p);
 
@@ -3670,8 +3688,6 @@ ira (FILE *f)
   if (delete_trivially_dead_insns (get_insns (), max_reg_num ()))
     df_analyze ();
 
-  init_reg_equiv_memory_loc ();
-
   if (max_regno != max_regno_before_ira)
     {
       regstat_free_n_sets_and_refs ();
@@ -3680,10 +3696,10 @@ ira (FILE *f)
       regstat_compute_ri ();
     }
 
-  allocate_initial_values (reg_equiv_memory_loc);
-
   overall_cost_before = ira_overall_cost;
-  if (ira_conflicts_p)
+  if (! ira_conflicts_p)
+    grow_reg_equivs ();
+  else
     {
       fix_reg_equiv_init ();
 
@@ -3699,16 +3715,22 @@ ira (FILE *f)
       memset (ira_spilled_reg_stack_slots, 0,
              max_regno * sizeof (struct ira_spilled_reg_stack_slot));
     }
+  allocate_initial_values (reg_equivs);
+}
 
-  timevar_pop (TV_IRA);
+static void
+do_reload (void)
+{
+  basic_block bb;
+  bool need_dce;
+
+  if (flag_ira_verbose < 10)
+    ira_dump_file = dump_file;
 
-  timevar_push (TV_RELOAD);
   df_set_flags (DF_NO_INSN_RESCAN);
   build_insn_chain ();
 
-  reload_completed = !reload (get_insns (), ira_conflicts_p);
-
-  timevar_pop (TV_RELOAD);
+  need_dce = reload (get_insns (), ira_conflicts_p);
 
   timevar_push (TV_IRA);
 
@@ -3717,7 +3739,6 @@ ira (FILE *f)
       ira_free (ira_spilled_reg_stack_slots);
 
       ira_finish_assign ();
-
     }
   if (internal_flag_ira_verbose > 0 && ira_dump_file != NULL
       && overall_cost_before != ira_overall_cost)
@@ -3726,8 +3747,11 @@ ira (FILE *f)
 
   flag_ira_share_spill_slots = saved_flag_ira_share_spill_slots;
 
-  flow_loops_free (&ira_loops);
-  free_dominance_info (CDI_DOMINATORS);
+  if (current_loops != NULL)
+    {
+      flow_loops_free (&ira_loops);
+      free_dominance_info (CDI_DOMINATORS);
+    }
   FOR_ALL_BB (bb)
     bb->loop_father = NULL;
   current_loops = NULL;
@@ -3749,7 +3773,7 @@ ira (FILE *f)
 #endif
 
   /* The code after the reload has changed so much that at this point
-     we might as well just rescan everything.  Not that
+     we might as well just rescan everything.  Note that
      df_rescan_all_insns is not going to help here because it does not
      touch the artificial uses and defs.  */
   df_finish_pass (true);
@@ -3761,17 +3785,12 @@ ira (FILE *f)
   if (optimize)
     df_analyze ();
 
+  if (need_dce && optimize)
+    run_fast_dce ();
+
   timevar_pop (TV_IRA);
 }
-
 \f
-
-static bool
-gate_ira (void)
-{
-  return true;
-}
-
 /* Run the integrated register allocator.  */
 static unsigned int
 rest_of_handle_ira (void)
@@ -3785,17 +3804,42 @@ struct rtl_opt_pass pass_ira =
  {
   RTL_PASS,
   "ira",                                /* name */
-  gate_ira,                             /* gate */
+  NULL,                                 /* gate */
   rest_of_handle_ira,                  /* execute */
   NULL,                                 /* sub */
   NULL,                                 /* next */
   0,                                    /* static_pass_number */
-  TV_NONE,                             /* tv_id */
+  TV_IRA,                              /* tv_id */
+  0,                                    /* properties_required */
+  0,                                    /* properties_provided */
+  0,                                    /* properties_destroyed */
+  0,                                    /* todo_flags_start */
+  TODO_dump_func                        /* todo_flags_finish */
+ }
+};
+
+static unsigned int
+rest_of_handle_reload (void)
+{
+  do_reload ();
+  return 0;
+}
+
+struct rtl_opt_pass pass_reload =
+{
+ {
+  RTL_PASS,
+  "reload",                             /* name */
+  NULL,                                 /* gate */
+  rest_of_handle_reload,               /* execute */
+  NULL,                                 /* sub */
+  NULL,                                 /* next */
+  0,                                    /* static_pass_number */
+  TV_RELOAD,                           /* tv_id */
   0,                                    /* properties_required */
   0,                                    /* properties_provided */
   0,                                    /* properties_destroyed */
   0,                                    /* todo_flags_start */
-  TODO_dump_func |
-  TODO_ggc_collect                      /* todo_flags_finish */
+  TODO_dump_func | TODO_ggc_collect     /* todo_flags_finish */
  }
 };