re PR target/65697 (__atomic memory barriers not strong enough for __sync builtins)
[gcc.git] / gcc / ira.c
index 71f64dbb8f286ed486620971c2dd4342ff7cee3e..92d5eb11ed7c71ce682145db958805610f5319ab 100644 (file)
--- a/gcc/ira.c
+++ b/gcc/ira.c
@@ -1,5 +1,5 @@
 /* Integrated Register Allocator (IRA) entry point.
-   Copyright (C) 2006-2014 Free Software Foundation, Inc.
+   Copyright (C) 2006-2015 Free Software Foundation, Inc.
    Contributed by Vladimir Makarov <vmakarov@redhat.com>.
 
 This file is part of GCC.
@@ -153,7 +153,7 @@ along with GCC; see the file COPYING3.  If not see
          calculates its initial (non-accumulated) cost of memory and
          each hard-register of its allocno class (file ira-cost.c).
 
-       * IRA creates live ranges of each allocno, calulates register
+       * IRA creates live ranges of each allocno, calculates register
          pressure for each pressure class in each region, sets up
          conflict hard registers for each allocno and info about calls
          the allocno lives through (file ira-lives.c).
@@ -245,7 +245,7 @@ along with GCC; see the file COPYING3.  If not see
          hard-register for allocnos conflicting with given allocno.
 
        * Chaitin-Briggs coloring assigns as many pseudos as possible
-         to hard registers.  After coloringh we try to improve
+         to hard registers.  After coloring we try to improve
          allocation with cost point of view.  We improve the
          allocation by spilling some allocnos and assigning the freed
          hard registers to other allocnos if it decreases the overall
@@ -307,7 +307,7 @@ along with GCC; see the file COPYING3.  If not see
        rebuilding would be, but is much faster.
 
      o After IR flattening, IRA tries to assign hard registers to all
-       spilled allocnos.  This is impelemented by a simple and fast
+       spilled allocnos.  This is implemented by a simple and fast
        priority coloring algorithm (see function
        ira_reassign_conflict_allocnos::ira-color.c).  Here new allocnos
        created during the code change pass can be assigned to hard
@@ -328,7 +328,7 @@ along with GCC; see the file COPYING3.  If not see
          in places where the pseudo-register lives.
 
    IRA uses a lot of data representing the target processors.  These
-   data are initilized in file ira.c.
+   data are initialized in file ira.c.
 
    If function has no loops (or the loops are ignored when
    -fira-algorithm=CB is used), we have classic Chaitin-Briggs
@@ -368,16 +368,33 @@ along with GCC; see the file COPYING3.  If not see
 #include "coretypes.h"
 #include "tm.h"
 #include "regs.h"
+#include "alias.h"
+#include "symtab.h"
 #include "tree.h"
+#include "hard-reg-set.h"
 #include "rtl.h"
 #include "tm_p.h"
 #include "target.h"
 #include "flags.h"
 #include "obstack.h"
 #include "bitmap.h"
-#include "hard-reg-set.h"
+#include "predict.h"
+#include "function.h"
+#include "dominance.h"
+#include "cfg.h"
+#include "cfgrtl.h"
+#include "cfgbuild.h"
+#include "cfgcleanup.h"
 #include "basic-block.h"
 #include "df.h"
+#include "insn-config.h"
+#include "expmed.h"
+#include "dojump.h"
+#include "explow.h"
+#include "calls.h"
+#include "emit-rtl.h"
+#include "varasm.h"
+#include "stmt.h"
 #include "expr.h"
 #include "recog.h"
 #include "params.h"
@@ -386,12 +403,12 @@ along with GCC; see the file COPYING3.  If not see
 #include "except.h"
 #include "reload.h"
 #include "diagnostic-core.h"
-#include "function.h"
-#include "ggc.h"
 #include "ira-int.h"
 #include "lra.h"
 #include "dce.h"
 #include "dbgcnt.h"
+#include "rtl-iter.h"
+#include "shrink-wrap.h"
 
 struct target_ira default_target_ira;
 struct target_ira_int default_target_ira_int;
@@ -418,9 +435,9 @@ struct ira_spilled_reg_stack_slot *ira_spilled_reg_stack_slots;
    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;
+int64_t ira_overall_cost, overall_cost_before;
+int64_t ira_reg_cost, ira_mem_cost;
+int64_t ira_load_cost, ira_store_cost, ira_shuffle_cost;
 int ira_move_loops_num, ira_additional_jumps_num;
 
 /* All registers that can be eliminated.  */
@@ -580,11 +597,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,
+             = memory_move_cost ((machine_mode) mode,
                                  (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,
+             = memory_move_cost ((machine_mode) mode,
                                  (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
@@ -817,7 +834,7 @@ setup_pressure_classes (void)
                                      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);
+             ira_init_register_move_cost_if_necessary ((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])
@@ -896,7 +913,7 @@ setup_pressure_classes (void)
          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
+      /* Some targets (like SPARC with ICC reg) have allocatable regs
         for which no reg class is defined.  */
       if (REGNO_REG_CLASS (i) == NO_REGS)
        SET_HARD_REG_BIT (ignore_hard_regs, i);
@@ -941,7 +958,7 @@ setup_uniform_class_p (void)
          for (m = 0; m < NUM_MACHINE_MODES; m++)
            if (contains_reg_of_mode[cl][m] && contains_reg_of_mode[cl2][m])
              {
-               ira_init_register_move_cost_if_necessary ((enum machine_mode) m);
+               ira_init_register_move_cost_if_necessary ((machine_mode) m);
                if (ira_register_move_cost[m][cl][cl]
                    != ira_register_move_cost[m][cl2][cl2])
                  break;
@@ -957,7 +974,7 @@ setup_uniform_class_p (void)
 /* Set up IRA_ALLOCNO_CLASSES, IRA_ALLOCNO_CLASSES_NUM,
    IRA_IMPORTANT_CLASSES, and IRA_IMPORTANT_CLASSES_NUM.
 
-   Target may have many subtargets and not all target hard regiters can
+   Target may have many subtargets and not all target hard registers can
    be used for allocation, e.g. x86 port in 32-bit mode can not use
    hard registers introduced in x86-64 like r8-r15).  Some classes
    might have the same allocatable hard registers, e.g.  INDEX_REGS
@@ -1017,7 +1034,7 @@ setup_allocno_and_important_classes (void)
   classes[n] = LIM_REG_CLASSES;
 
   /* Set up classes which can be used for allocnos as classes
-     conatining non-empty unique sets of allocatable hard
+     containing non-empty unique sets of allocatable hard
      registers.  */
   ira_allocno_classes_num = 0;
   for (i = 0; (cl = classes[i]) != LIM_REG_CLASSES; i++)
@@ -1076,7 +1093,7 @@ setup_allocno_and_important_classes (void)
    containing a given class.  If allocatable hard register set of a
    given class is not a subset of any corresponding set of a class
    from CLASSES, we use the cheapest (with load/store point of view)
-   class from CLASSES whose set intersects with given class set */
+   class from CLASSES whose set intersects with given class set */
 static void
 setup_class_translate_array (enum reg_class *class_translate,
                             int classes_num, enum reg_class *classes)
@@ -1311,7 +1328,7 @@ setup_reg_class_relations (void)
              if (important_class_p[cl3]
                  && hard_reg_set_subset_p (temp_hard_regset, union_set))
                {
-                 /* CL3 allocatbale hard register set is inside of
+                 /* CL3 allocatable hard register set is inside of
                     union of allocatable hard register sets of CL1
                     and CL2.  */
                  COPY_HARD_REG_SET
@@ -1364,7 +1381,7 @@ setup_reg_class_relations (void)
     }
 }
 
-/* Output all unifrom and important classes into file F.  */
+/* Output all uniform and important classes into file F.  */
 static void
 print_unform_and_important_classes (FILE *f)
 {
@@ -1471,7 +1488,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]
-         = targetm.class_max_nregs ((reg_class_t) cl, (enum machine_mode) m);
+         = targetm.class_max_nregs ((reg_class_t) cl, (machine_mode) m);
       for (cl = 0; cl < N_REG_CLASSES; cl++)
        for (i = 0;
             (cl2 = alloc_reg_class_subclasses[cl][i]) != LIM_REG_CLASSES;
@@ -1503,11 +1520,11 @@ setup_prohibited_class_mode_regs (void)
          for (k = ira_class_hard_regs_num[cl] - 1; k >= 0; k--)
            {
              hard_regno = ira_class_hard_regs[cl][k];
-             if (! HARD_REGNO_MODE_OK (hard_regno, (enum machine_mode) j))
+             if (! HARD_REGNO_MODE_OK (hard_regno, (machine_mode) j))
                SET_HARD_REG_BIT (ira_prohibited_class_mode_regs[cl][j],
                                  hard_regno);
              else if (in_hard_reg_set_p (temp_hard_regset,
-                                         (enum machine_mode) j, hard_regno))
+                                         (machine_mode) j, hard_regno))
                {
                  last_hard_regno = hard_regno;
                  count++;
@@ -1555,7 +1572,7 @@ clarify_prohibited_class_mode_regs (void)
            if (!TEST_HARD_REG_BIT (ira_prohibited_class_mode_regs[cl][j],
                                    hard_regno))
              add_to_hard_reg_set (&ira_useful_class_mode_regs[cl][j],
-                                  (enum machine_mode) j, hard_regno);
+                                  (machine_mode) j, hard_regno);
          }
       }
 }
@@ -1563,7 +1580,7 @@ clarify_prohibited_class_mode_regs (void)
 /* Allocate and initialize IRA_REGISTER_MOVE_COST, IRA_MAY_MOVE_IN_COST
    and IRA_MAY_MOVE_OUT_COST for MODE.  */
 void
-ira_init_register_move_cost (enum machine_mode mode)
+ira_init_register_move_cost (machine_mode mode)
 {
   static unsigned short last_move_cost[N_REG_CLASSES][N_REG_CLASSES];
   bool all_match = true;
@@ -1672,40 +1689,46 @@ ira_init_once (void)
 
 /* Free ira_max_register_move_cost, ira_may_move_in_cost and
    ira_may_move_out_cost for each mode.  */
-static void
-free_register_move_costs (void)
+void
+target_ira_int::free_register_move_costs (void)
 {
   int mode, i;
 
   /* Reset move_cost and friends, making sure we only free shared
      table entries once.  */
   for (mode = 0; mode < MAX_MACHINE_MODE; mode++)
-    if (ira_register_move_cost[mode])
+    if (x_ira_register_move_cost[mode])
       {
        for (i = 0;
-            i < mode && (ira_register_move_cost[i]
-                         != ira_register_move_cost[mode]);
+            i < mode && (x_ira_register_move_cost[i]
+                         != x_ira_register_move_cost[mode]);
             i++)
          ;
        if (i == mode)
          {
-           free (ira_register_move_cost[mode]);
-           free (ira_may_move_in_cost[mode]);
-           free (ira_may_move_out_cost[mode]);
+           free (x_ira_register_move_cost[mode]);
+           free (x_ira_may_move_in_cost[mode]);
+           free (x_ira_may_move_out_cost[mode]);
          }
       }
-  memset (ira_register_move_cost, 0, sizeof ira_register_move_cost);
-  memset (ira_may_move_in_cost, 0, sizeof ira_may_move_in_cost);
-  memset (ira_may_move_out_cost, 0, sizeof ira_may_move_out_cost);
+  memset (x_ira_register_move_cost, 0, sizeof x_ira_register_move_cost);
+  memset (x_ira_may_move_in_cost, 0, sizeof x_ira_may_move_in_cost);
+  memset (x_ira_may_move_out_cost, 0, sizeof x_ira_may_move_out_cost);
   last_mode_for_init_move_cost = -1;
 }
 
+target_ira_int::~target_ira_int ()
+{
+  free_ira_costs ();
+  free_register_move_costs ();
+}
+
 /* This is called every time when register related information is
    changed.  */
 void
 ira_init (void)
 {
-  free_register_move_costs ();
+  this_target_ira_int->free_register_move_costs ();
   setup_reg_mode_hard_regset ();
   setup_alloc_regs (flag_omit_frame_pointer != 0);
   setup_class_subset_and_memory_move_costs ();
@@ -1717,15 +1740,6 @@ ira_init (void)
   ira_init_costs ();
 }
 
-/* Function called once at the end of compiler work.  */
-void
-ira_finish_once (void)
-{
-  ira_finish_costs_once ();
-  free_register_move_costs ();
-  lra_finish_once ();
-}
-
 \f
 #define ira_prohibited_mode_move_regs_initialized_p \
   (this_target_ira_int->x_ira_prohibited_mode_move_regs_initialized_p)
@@ -1735,32 +1749,33 @@ static void
 setup_prohibited_mode_move_regs (void)
 {
   int i, j;
-  rtx test_reg1, test_reg2, move_pat, move_insn;
+  rtx test_reg1, test_reg2, move_pat;
+  rtx_insn *move_insn;
 
   if (ira_prohibited_mode_move_regs_initialized_p)
     return;
   ira_prohibited_mode_move_regs_initialized_p = true;
-  test_reg1 = gen_rtx_REG (VOIDmode, 0);
-  test_reg2 = gen_rtx_REG (VOIDmode, 0);
-  move_pat = gen_rtx_SET (VOIDmode, test_reg1, test_reg2);
+  test_reg1 = gen_rtx_REG (word_mode, LAST_VIRTUAL_REGISTER + 1);
+  test_reg2 = gen_rtx_REG (word_mode, LAST_VIRTUAL_REGISTER + 2);
+  move_pat = gen_rtx_SET (test_reg1, test_reg2);
   move_insn = gen_rtx_INSN (VOIDmode, 0, 0, 0, move_pat, 0, -1, 0);
   for (i = 0; i < NUM_MACHINE_MODES; i++)
     {
       SET_HARD_REG_SET (ira_prohibited_mode_move_regs[i]);
       for (j = 0; j < FIRST_PSEUDO_REGISTER; j++)
        {
-         if (! HARD_REGNO_MODE_OK (j, (enum machine_mode) i))
+         if (! HARD_REGNO_MODE_OK (j, (machine_mode) i))
            continue;
-         SET_REGNO_RAW (test_reg1, j);
-         PUT_MODE (test_reg1, (enum machine_mode) i);
-         SET_REGNO_RAW (test_reg2, j);
-         PUT_MODE (test_reg2, (enum machine_mode) i);
+         set_mode_and_regno (test_reg1, (machine_mode) i, j);
+         set_mode_and_regno (test_reg2, (machine_mode) i, j);
          INSN_CODE (move_insn) = -1;
          recog_memoized (move_insn);
          if (INSN_CODE (move_insn) < 0)
            continue;
          extract_insn (move_insn);
-         if (! constrain_operands (1))
+         /* We don't know whether the move will be in code that is optimized
+            for size or speed, so consider all enabled alternatives.  */
+         if (! constrain_operands (1, get_enabled_alternatives (move_insn)))
            continue;
          CLEAR_HARD_REG_BIT (ira_prohibited_mode_move_regs[i], j);
        }
@@ -1771,18 +1786,18 @@ setup_prohibited_mode_move_regs (void)
 
 /* Setup possible alternatives in ALTS for INSN.  */
 void
-ira_setup_alts (rtx insn, HARD_REG_SET &alts)
+ira_setup_alts (rtx_insn *insn, HARD_REG_SET &alts)
 {
   /* MAP nalt * nop -> start of constraints for given operand and
-     alternative */
+     alternative */
   static vec<const char *> insn_constraints;
   int nop, nalt;
   bool curr_swapped;
   const char *p;
-  rtx op;
   int commutative = -1;
 
   extract_insn (insn);
+  alternative_mask preferred = get_preferred_alternatives (insn);
   CLEAR_HARD_REG_SET (alts);
   insn_constraints.release ();
   insn_constraints.safe_grow_cleared (recog_data.n_operands
@@ -1812,7 +1827,7 @@ ira_setup_alts (rtx insn, HARD_REG_SET &alts)
        }
       for (nalt = 0; nalt < recog_data.n_alternatives; nalt++)
        {
-         if (!TEST_BIT (recog_data.enabled_alternatives, nalt)
+         if (!TEST_BIT (preferred, nalt)
              || TEST_HARD_REG_BIT (alts, nalt))
            continue;
 
@@ -1820,7 +1835,7 @@ ira_setup_alts (rtx insn, HARD_REG_SET &alts)
            {
              int c, len;
 
-             op = recog_data.operand[nop];
+             rtx op = recog_data.operand[nop];
              p = insn_constraints[nop * recog_data.n_alternatives + nalt];
              if (*p == 0 || *p == ',')
                continue;
@@ -1893,10 +1908,8 @@ ira_setup_alts (rtx insn, HARD_REG_SET &alts)
        break;
       if (curr_swapped)
        break;
-      op = recog_data.operand[commutative];
-      recog_data.operand[commutative] = recog_data.operand[commutative + 1];
-      recog_data.operand[commutative + 1] = op;
-
+      std::swap (recog_data.operand[commutative],
+                recog_data.operand[commutative + 1]);
     }
 }
 
@@ -2015,7 +2028,8 @@ decrease_live_ranges_number (void)
 {
   basic_block bb;
   rtx_insn *insn;
-  rtx set, src, dest, dest_death, p, q, note;
+  rtx set, src, dest, dest_death, note;
+  rtx_insn *p, *q;
   int sregno, dregno;
 
   if (! flag_expensive_optimizations)
@@ -2310,19 +2324,20 @@ ira_setup_eliminable_regset (void)
       else
        df_set_regs_ever_live (eliminables[i].from, true);
     }
-#if !HARD_FRAME_POINTER_IS_FRAME_POINTER
-  if (!TEST_HARD_REG_BIT (crtl->asm_clobbers, HARD_FRAME_POINTER_REGNUM))
+  if (!HARD_FRAME_POINTER_IS_FRAME_POINTER)
     {
-      SET_HARD_REG_BIT (eliminable_regset, HARD_FRAME_POINTER_REGNUM);
-      if (frame_pointer_needed)
-       SET_HARD_REG_BIT (ira_no_alloc_regs, HARD_FRAME_POINTER_REGNUM);
+      if (!TEST_HARD_REG_BIT (crtl->asm_clobbers, HARD_FRAME_POINTER_REGNUM))
+       {
+         SET_HARD_REG_BIT (eliminable_regset, HARD_FRAME_POINTER_REGNUM);
+         if (frame_pointer_needed)
+           SET_HARD_REG_BIT (ira_no_alloc_regs, HARD_FRAME_POINTER_REGNUM);
+       }
+      else if (frame_pointer_needed)
+       error ("%s cannot be used in asm here",
+              reg_names[HARD_FRAME_POINTER_REGNUM]);
+      else
+       df_set_regs_ever_live (HARD_FRAME_POINTER_REGNUM, true);
     }
-  else if (frame_pointer_needed)
-    error ("%s cannot be used in asm here",
-          reg_names[HARD_FRAME_POINTER_REGNUM]);
-  else
-    df_set_regs_ever_live (HARD_FRAME_POINTER_REGNUM, true);
-#endif
 
 #else
   if (!TEST_HARD_REG_BIT (crtl->asm_clobbers, HARD_FRAME_POINTER_REGNUM))
@@ -2474,10 +2489,15 @@ calculate_allocation_cost (void)
   if (internal_flag_ira_verbose > 0 && ira_dump_file != NULL)
     {
       fprintf (ira_dump_file,
-              "+++Costs: overall %d, reg %d, mem %d, ld %d, st %d, move %d\n",
+              "+++Costs: overall %" PRId64
+              ", reg %" PRId64
+              ", mem %" PRId64
+              ", ld %" PRId64
+              ", st %" PRId64
+              ", move %" PRId64,
               ira_overall_cost, ira_reg_cost, ira_mem_cost,
               ira_load_cost, ira_store_cost, ira_shuffle_cost);
-      fprintf (ira_dump_file, "+++       move loops %d, new jumps %d\n",
+      fprintf (ira_dump_file, "\n+++       move loops %d, new jumps %d\n",
               ira_move_loops_num, ira_additional_jumps_num);
     }
 
@@ -2580,9 +2600,10 @@ setup_reg_equiv_init (void)
    to update equiv info for register shuffles on the region borders
    and for caller save/restore insns.  */
 void
-ira_update_equiv_info_by_shuffle_insn (int to_regno, int from_regno, rtx insns)
+ira_update_equiv_info_by_shuffle_insn (int to_regno, int from_regno, rtx_insn *insns)
 {
-  rtx insn, x, note;
+  rtx_insn *insn;
+  rtx x, note;
 
   if (! ira_reg_equiv[from_regno].defined_p
       && (! ira_reg_equiv[to_regno].defined_p
@@ -2601,7 +2622,7 @@ ira_update_equiv_info_by_shuffle_insn (int to_regno, int from_regno, rtx insns)
       ira_reg_equiv[to_regno].memory
        = ira_reg_equiv[to_regno].constant
        = ira_reg_equiv[to_regno].invariant
-       = ira_reg_equiv[to_regno].init_insns = NULL_RTX;
+       = ira_reg_equiv[to_regno].init_insns = NULL;
       if (internal_flag_ira_verbose > 3 && ira_dump_file != NULL)
        fprintf (ira_dump_file,
                 "      Invalidating equiv info for reg %d\n", to_regno);
@@ -2671,19 +2692,21 @@ fix_reg_equiv_init (void)
 {
   int max_regno = max_reg_num ();
   int i, new_regno, max;
-  rtx x, prev, next, insn, set;
+  rtx set;
+  rtx_insn_list *x, *next, *prev;
+  rtx_insn *insn;
 
   if (max_regno_before_ira < max_regno)
     {
       max = vec_safe_length (reg_equivs);
       grow_reg_equivs ();
       for (i = FIRST_PSEUDO_REGISTER; i < max; i++)
-       for (prev = NULL_RTX, x = reg_equiv_init (i);
+       for (prev = NULL, x = reg_equiv_init (i);
             x != NULL_RTX;
             x = next)
          {
-           next = XEXP (x, 1);
-           insn = XEXP (x, 0);
+           next = x->next ();
+           insn = x->insn ();
            set = single_set (insn);
            ira_assert (set != NULL_RTX
                        && (REG_P (SET_DEST (set)) || REG_P (SET_SRC (set))));
@@ -2726,7 +2749,7 @@ print_redundant_copies (void)
   FOR_EACH_ALLOCNO (a, ai)
     {
       if (ALLOCNO_CAP_MEMBER (a) != NULL)
-       /* It is a cap. */
+       /* It is a cap.  */
        continue;
       hard_regno = ALLOCNO_HARD_REGNO (a);
       if (hard_regno >= 0)
@@ -2772,7 +2795,7 @@ setup_preferred_alternate_classes_for_new_pseudos (int start)
 }
 
 \f
-/* The number of entries allocated in teg_info.  */
+/* The number of entries allocated in reg_info.  */
 static int allocated_reg_info_size;
 
 /* Regional allocation can create new pseudo-registers.  This function
@@ -2888,16 +2911,26 @@ struct equivalence
      e.g. by reload.  */
   rtx replacement;
   rtx *src_p;
-  /* The list of each instruction which initializes this register.  */
-  rtx init_insns;
+
+  /* The list of each instruction which initializes this register.
+
+     NULL indicates we know nothing about this register's equivalence
+     properties.
+
+     An INSN_LIST with a NULL insn indicates this pseudo is already
+     known to not have a valid equivalence.  */
+  rtx_insn_list *init_insns;
+
   /* Loop depth is used to recognize equivalences which appear
      to be present within the same loop (or in an inner loop).  */
-  int loop_depth;
+  short loop_depth;
   /* Nonzero if this had a preexisting REG_EQUIV note.  */
-  int is_arg_equivalence;
+  unsigned char is_arg_equivalence : 1;
   /* Set when an attempt should be made to replace a register
      with the associated src_p entry.  */
-  char replace;
+  unsigned char replace : 1;
+  /* Set if this register has no known equivalence.  */
+  unsigned char no_equiv : 1;
 };
 
 /* reg_equiv[N] (where N is a pseudo reg number) is the equivalence
@@ -2931,9 +2964,9 @@ validate_equiv_mem_from_store (rtx dest, const_rtx set ATTRIBUTE_UNUSED,
 
    Return 1 if MEMREF remains valid.  */
 static int
-validate_equiv_mem (rtx start, rtx reg, rtx memref)
+validate_equiv_mem (rtx_insn *start, rtx reg, rtx memref)
 {
-  rtx insn;
+  rtx_insn *insn;
   rtx note;
 
   equiv_mem = memref;
@@ -3207,9 +3240,9 @@ memref_referenced_p (rtx memref, rtx x)
 /* TRUE if some insn in the range (START, END] references a memory location
    that would be affected by a store to MEMREF.  */
 static int
-memref_used_between_p (rtx memref, rtx start, rtx end)
+memref_used_between_p (rtx memref, rtx_insn *start, rtx_insn *end)
 {
-  rtx insn;
+  rtx_insn *insn;
 
   for (insn = NEXT_INSN (start); insn != NEXT_INSN (end);
        insn = NEXT_INSN (insn))
@@ -3240,25 +3273,26 @@ no_equiv (rtx reg, const_rtx store ATTRIBUTE_UNUSED,
          void *data ATTRIBUTE_UNUSED)
 {
   int regno;
-  rtx list;
+  rtx_insn_list *list;
 
   if (!REG_P (reg))
     return;
   regno = REGNO (reg);
+  reg_equiv[regno].no_equiv = 1;
   list = reg_equiv[regno].init_insns;
-  if (list == const0_rtx)
+  if (list && list->insn () == NULL)
     return;
-  reg_equiv[regno].init_insns = const0_rtx;
+  reg_equiv[regno].init_insns = gen_rtx_INSN_LIST (VOIDmode, NULL_RTX, NULL);
   reg_equiv[regno].replacement = NULL_RTX;
   /* This doesn't matter for equivalences made for argument registers, we
      should keep their initialization insns.  */
   if (reg_equiv[regno].is_arg_equivalence)
     return;
   ira_reg_equiv[regno].defined_p = false;
-  ira_reg_equiv[regno].init_insns = NULL_RTX;
-  for (; list; list =  XEXP (list, 1))
+  ira_reg_equiv[regno].init_insns = NULL;
+  for (; list; list = list->next ())
     {
-      rtx insn = XEXP (list, 0);
+      rtx_insn *insn = list->insn ();
       remove_note (insn, find_reg_note (insn, REG_EQUIV, NULL_RTX));
     }
 }
@@ -3266,23 +3300,20 @@ no_equiv (rtx reg, const_rtx store ATTRIBUTE_UNUSED,
 /* Check whether the SUBREG is a paradoxical subreg and set the result
    in PDX_SUBREGS.  */
 
-static int
-set_paradoxical_subreg (rtx *subreg, void *pdx_subregs)
+static void
+set_paradoxical_subreg (rtx_insn *insn, bool *pdx_subregs)
 {
-  rtx reg;
-
-  if ((*subreg) == NULL_RTX)
-    return 1;
-  if (GET_CODE (*subreg) != SUBREG)
-    return 0;
-  reg = SUBREG_REG (*subreg);
-  if (!REG_P (reg))
-    return 0;
-
-  if (paradoxical_subreg_p (*subreg))
-    ((bool *)pdx_subregs)[REGNO (reg)] = true;
-
-  return 0;
+  subrtx_iterator::array_type array;
+  FOR_EACH_SUBRTX (iter, array, PATTERN (insn), NONCONST)
+    {
+      const_rtx subreg = *iter;
+      if (GET_CODE (subreg) == SUBREG)
+       {
+         const_rtx reg = SUBREG_REG (subreg);
+         if (REG_P (reg) && paradoxical_subreg_p (subreg))
+           pdx_subregs[REGNO (reg)] = true;
+       }
+    }
 }
 
 /* In DEBUG_INSN location adjust REGs from CLEARED_REGS bitmap to the
@@ -3319,7 +3350,7 @@ static int recorded_label_ref;
 static int
 update_equiv_regs (void)
 {
-  rtx insn;
+  rtx_insn *insn;
   basic_block bb;
   int loop_depth;
   bitmap cleared_regs;
@@ -3339,13 +3370,13 @@ update_equiv_regs (void)
   init_alias_analysis ();
 
   /* Scan insns and set pdx_subregs[regno] if the reg is used in a
-     paradoxical subreg. Don't set such reg sequivalent to a mem,
+     paradoxical subreg. Don't set such reg equivalent to a mem,
      because lra will not substitute such equiv memory in order to
      prevent access beyond allocated memory for paradoxical memory subreg.  */
   FOR_EACH_BB_FN (bb, cfun)
     FOR_BB_INSNS (bb, insn)
       if (NONDEBUG_INSN_P (insn))
-       for_each_rtx (&insn, set_paradoxical_subreg, (void *) pdx_subregs);
+       set_paradoxical_subreg (insn, pdx_subregs);
 
   /* Scan the insns and find which registers have equivalences.  Do this
      in a separate scan of the insns because (due to -fcse-follow-jumps)
@@ -3374,7 +3405,7 @@ update_equiv_regs (void)
 
          /* If this insn contains more (or less) than a single SET,
             only mark all destinations as having no known equivalence.  */
-         if (set == 0)
+         if (set == NULL_RTX)
            {
              note_stores (PATTERN (insn), no_equiv, NULL);
              continue;
@@ -3438,7 +3469,8 @@ update_equiv_regs (void)
 
          if (!REG_P (dest)
              || (regno = REGNO (dest)) < FIRST_PSEUDO_REGISTER
-             || reg_equiv[regno].init_insns == const0_rtx
+             || (reg_equiv[regno].init_insns
+                 && reg_equiv[regno].init_insns->insn () == NULL)
              || (targetm.class_likely_spilled_p (reg_preferred_class (regno))
                  && MEM_P (src) && ! reg_equiv[regno].is_arg_equivalence))
            {
@@ -3464,20 +3496,53 @@ update_equiv_regs (void)
            note = set_unique_reg_note (insn, REG_EQUAL, copy_rtx (src));
 
          /* Don't bother considering a REG_EQUAL note containing an EXPR_LIST
-            since it represents a function call */
+            since it represents a function call */
          if (note && GET_CODE (XEXP (note, 0)) == EXPR_LIST)
            note = NULL_RTX;
 
-         if (DF_REG_DEF_COUNT (regno) != 1
-             && (! note
+         if (DF_REG_DEF_COUNT (regno) != 1)
+           {
+             bool equal_p = true;
+             rtx_insn_list *list;
+
+             /* If we have already processed this pseudo and determined it
+                can not have an equivalence, then honor that decision.  */
+             if (reg_equiv[regno].no_equiv)
+               continue;
+
+             if (! note
                  || rtx_varies_p (XEXP (note, 0), 0)
                  || (reg_equiv[regno].replacement
                      && ! rtx_equal_p (XEXP (note, 0),
-                                       reg_equiv[regno].replacement))))
-           {
-             no_equiv (dest, set, NULL);
-             continue;
+                                       reg_equiv[regno].replacement)))
+               {
+                 no_equiv (dest, set, NULL);
+                 continue;
+               }
+
+             list = reg_equiv[regno].init_insns;
+             for (; list; list = list->next ())
+               {
+                 rtx note_tmp;
+                 rtx_insn *insn_tmp;
+
+                 insn_tmp = list->insn ();
+                 note_tmp = find_reg_note (insn_tmp, REG_EQUAL, NULL_RTX);
+                 gcc_assert (note_tmp);
+                 if (! rtx_equal_p (XEXP (note, 0), XEXP (note_tmp, 0)))
+                   {
+                     equal_p = false;
+                     break;
+                   }
+               }
+
+             if (! equal_p)
+               {
+                 no_equiv (dest, set, NULL);
+                 continue;
+               }
            }
+
          /* Record this insn as initializing this register.  */
          reg_equiv[regno].init_insns
            = gen_rtx_INSN_LIST (VOIDmode, insn, reg_equiv[regno].init_insns);
@@ -3506,10 +3571,9 @@ update_equiv_regs (void)
             a register used only in one basic block from a MEM.  If so, and the
             MEM remains unchanged for the life of the register, add a REG_EQUIV
             note.  */
-
          note = find_reg_note (insn, REG_EQUIV, NULL_RTX);
 
-         if (note == 0 && REG_BASIC_BLOCK (regno) >= NUM_FIXED_BLOCKS
+         if (note == NULL_RTX && REG_BASIC_BLOCK (regno) >= NUM_FIXED_BLOCKS
              && MEM_P (SET_SRC (set))
              && validate_equiv_mem (insn, dest, SET_SRC (set)))
            note = set_unique_reg_note (insn, REG_EQUIV, copy_rtx (SET_SRC (set)));
@@ -3539,7 +3603,7 @@ update_equiv_regs (void)
 
              reg_equiv[regno].replacement = x;
              reg_equiv[regno].src_p = &SET_SRC (set);
-             reg_equiv[regno].loop_depth = loop_depth;
+             reg_equiv[regno].loop_depth = (short) loop_depth;
 
              /* Don't mess with things live during setjmp.  */
              if (REG_LIVE_LENGTH (regno) >= 0 && optimize)
@@ -3609,14 +3673,15 @@ update_equiv_regs (void)
          && (regno = REGNO (src)) >= FIRST_PSEUDO_REGISTER
          && REG_BASIC_BLOCK (regno) >= NUM_FIXED_BLOCKS
          && DF_REG_DEF_COUNT (regno) == 1
-         && reg_equiv[regno].init_insns != 0
-         && reg_equiv[regno].init_insns != const0_rtx
+         && reg_equiv[regno].init_insns != NULL
+         && reg_equiv[regno].init_insns->insn () != NULL
          && ! find_reg_note (XEXP (reg_equiv[regno].init_insns, 0),
                              REG_EQUIV, NULL_RTX)
          && ! contains_replace_regs (XEXP (dest, 0))
          && ! pdx_subregs[regno])
        {
-         rtx init_insn = XEXP (reg_equiv[regno].init_insns, 0);
+         rtx_insn *init_insn =
+           as_a <rtx_insn *> (XEXP (reg_equiv[regno].init_insns, 0));
          if (validate_equiv_mem (init_insn, src, dest)
              && ! memref_used_between_p (dest, init_insn, insn)
              /* Attaching a REG_EQUIV note will fail if INIT_INSN has
@@ -3668,7 +3733,7 @@ update_equiv_regs (void)
                  rtx equiv_insn;
 
                  if (! reg_equiv[regno].replace
-                     || reg_equiv[regno].loop_depth < loop_depth
+                     || reg_equiv[regno].loop_depth < (short) loop_depth
                      /* There is no sense to move insns if live range
                         shrinkage or register pressure-sensitive
                         scheduling were done because it will not
@@ -3728,16 +3793,16 @@ update_equiv_regs (void)
                      delete_insn (equiv_insn);
 
                      reg_equiv[regno].init_insns
-                       = XEXP (reg_equiv[regno].init_insns, 1);
+                       = reg_equiv[regno].init_insns->next ();
 
-                     ira_reg_equiv[regno].init_insns = NULL_RTX;
+                     ira_reg_equiv[regno].init_insns = NULL;
                      bitmap_set_bit (cleared_regs, regno);
                    }
                  /* Move the initialization of the register to just before
                     INSN.  Update the flow information.  */
                  else if (prev_nondebug_insn (insn) != equiv_insn)
                    {
-                     rtx new_insn;
+                     rtx_insn *new_insn;
 
                      new_insn = emit_insn_before (PATTERN (equiv_insn), insn);
                      REG_NOTES (new_insn) = REG_NOTES (equiv_insn);
@@ -3818,15 +3883,17 @@ static void
 setup_reg_equiv (void)
 {
   int i;
-  rtx elem, prev_elem, next_elem, insn, set, x;
+  rtx_insn_list *elem, *prev_elem, *next_elem;
+  rtx_insn *insn;
+  rtx set, x;
 
   for (i = FIRST_PSEUDO_REGISTER; i < ira_reg_equiv_len; i++)
     for (prev_elem = NULL, elem = ira_reg_equiv[i].init_insns;
         elem;
         prev_elem = elem, elem = next_elem)
       {
-       next_elem = XEXP (elem, 1);
-       insn = XEXP (elem, 0);
+       next_elem = elem->next ();
+       insn = elem->insn ();
        set = single_set (insn);
        
        /* Init insns can set up equivalence when the reg is a destination or
@@ -3879,7 +3946,7 @@ setup_reg_equiv (void)
                  }
                else if (function_invariant_p (x))
                  {
-                   enum machine_mode mode;
+                   machine_mode mode;
                    
                    mode = GET_MODE (SET_DEST (set));
                    if (GET_CODE (x) == PLUS
@@ -3895,7 +3962,7 @@ setup_reg_equiv (void)
                        if (ira_reg_equiv[i].memory == NULL_RTX)
                          {
                            ira_reg_equiv[i].defined_p = false;
-                           ira_reg_equiv[i].init_insns = NULL_RTX;
+                           ira_reg_equiv[i].init_insns = NULL;
                            break;
                          }
                      }
@@ -3905,7 +3972,7 @@ setup_reg_equiv (void)
              }
          }
        ira_reg_equiv[i].defined_p = false;
-       ira_reg_equiv[i].init_insns = NULL_RTX;
+       ira_reg_equiv[i].init_insns = NULL;
        break;
       }
 }
@@ -4135,7 +4202,7 @@ build_insn_chain (void)
                       to a multiword reg.  Here, we only model the
                       subreg case that is not wrapped in ZERO_EXTRACT
                       precisely so we do not need to look at the
-                      fabricated use. */
+                      fabricated use.  */
                    if (DF_REF_FLAGS_IS_SET (use, DF_REF_READ_WRITE)
                        && !DF_REF_FLAGS_IS_SET (use, DF_REF_ZERO_EXTRACT)
                        && DF_REF_FLAGS_IS_SET (use, DF_REF_SUBREG))
@@ -4298,6 +4365,12 @@ rtx_moveable_p (rtx *loc, enum op_type type)
     case CLOBBER:
       return rtx_moveable_p (&SET_DEST (x), OP_OUT);
 
+    case UNSPEC_VOLATILE:
+      /* It is a bad idea to consider insns with with such rtl
+        as moveable ones.  The insn scheduler also considers them as barrier
+        for a reason.  */
+      return false;
+
     default:
       break;
     }
@@ -4474,7 +4547,7 @@ find_moveable_pseudos (void)
            df_ref def, use;
            unsigned regno;
            bool all_dominated, all_local;
-           enum machine_mode mode;
+           machine_mode mode;
 
            def = df_single_def (insn_info);
            /* There must be exactly one def in this insn.  */
@@ -4554,15 +4627,14 @@ find_moveable_pseudos (void)
                           ? " (no unique first use)" : "");
                continue;
              }
-#ifdef HAVE_cc0
-           if (reg_referenced_p (cc0_rtx, PATTERN (closest_use)))
+           if (HAVE_cc0 && reg_referenced_p (cc0_rtx, PATTERN (closest_use)))
              {
                if (dump_file)
                  fprintf (dump_file, "Reg %d: closest user uses cc0\n",
                           regno);
                continue;
              }
-#endif
+
            bitmap_set_bit (&interesting, regno);
            /* If we get here, we know closest_use is a non-NULL insn
               (as opposed to const_0_rtx).  */
@@ -4637,10 +4709,7 @@ find_moveable_pseudos (void)
            {
              if (bitmap_bit_p (def_bb_moveable, regno)
                  && !control_flow_insn_p (use_insn)
-#ifdef HAVE_cc0
-                 && !sets_cc0_p (use_insn)
-#endif
-                 )
+                 && (!HAVE_cc0 || !sets_cc0_p (use_insn)))
                {
                  if (modified_between_p (DF_REF_REG (use), def_insn, use_insn))
                    {
@@ -4730,7 +4799,7 @@ interesting_dest_for_shprep_1 (rtx set, basic_block call_dom)
   return dest;
 }
 
-/* If insn is interesting for parameter range-splitting shring-wrapping
+/* If insn is interesting for parameter range-splitting shrink-wrapping
    preparation, i.e. it is a single set from a hard register to a pseudo, which
    is live at CALL_DOM (if non-NULL, otherwise this check is omitted), or a
    parallel statement with only one such statement, return the destination.
@@ -4779,7 +4848,7 @@ split_live_ranges_for_shrink_wrap (void)
   bitmap_head need_new, reachable;
   vec<basic_block> queue;
 
-  if (!flag_shrink_wrap)
+  if (!SHRINK_WRAPPING_ENABLED)
     return false;
 
   bitmap_initialize (&need_new, 0);
@@ -4885,7 +4954,7 @@ split_live_ranges_for_shrink_wrap (void)
   FOR_BB_INSNS (first, insn)
     {
       rtx dest = interesting_dest_for_shprep (insn, call_dom);
-      if (!dest)
+      if (!dest || dest == pic_offset_table_rtx)
        continue;
 
       rtx newreg = NULL_RTX;
@@ -4907,7 +4976,7 @@ split_live_ranges_for_shrink_wrap (void)
 
       if (newreg)
        {
-         rtx new_move = gen_move_insn (newreg, dest);
+         rtx_insn *new_move = gen_move_insn (newreg, dest);
          emit_insn_after (new_move, bb_note (call_dom));
          if (dump_file)
            {
@@ -5037,6 +5106,9 @@ ira (FILE *f)
   bool saved_flag_caller_saves = flag_caller_saves;
   enum ira_region saved_flag_ira_region = flag_ira_region;
 
+  /* Perform target specific PIC register initialization.  */
+  targetm.init_pic_reg ();
+
   ira_conflicts_p = optimize > 0;
 
   ira_use_lra_p = targetm.lra_p ();
@@ -5200,7 +5272,18 @@ ira (FILE *f)
              ira_allocno_iterator ai;
 
              FOR_EACH_ALLOCNO (a, ai)
-               ALLOCNO_REGNO (a) = REGNO (ALLOCNO_EMIT_DATA (a)->reg);
+                {
+                  int old_regno = ALLOCNO_REGNO (a);
+                  int new_regno = REGNO (ALLOCNO_EMIT_DATA (a)->reg);
+
+                  ALLOCNO_REGNO (a) = new_regno;
+
+                  if (old_regno != new_regno)
+                    setup_reg_classes (new_regno, reg_preferred_class (old_regno),
+                                       reg_alternate_class (old_regno),
+                                       reg_allocno_class (old_regno));
+                }
+
            }
          else
            {
@@ -5258,14 +5341,16 @@ ira (FILE *f)
 #ifdef ENABLE_IRA_CHECKING
       print_redundant_copies ();
 #endif
-
-      ira_spilled_reg_stack_slots_num = 0;
-      ira_spilled_reg_stack_slots
-       = ((struct ira_spilled_reg_stack_slot *)
-          ira_allocate (max_regno
-                        * sizeof (struct ira_spilled_reg_stack_slot)));
-      memset (ira_spilled_reg_stack_slots, 0,
-             max_regno * sizeof (struct ira_spilled_reg_stack_slot));
+      if (! ira_use_lra_p)
+       {
+         ira_spilled_reg_stack_slots_num = 0;
+         ira_spilled_reg_stack_slots
+           = ((struct ira_spilled_reg_stack_slot *)
+              ira_allocate (max_regno
+                            * sizeof (struct ira_spilled_reg_stack_slot)));
+         memset (ira_spilled_reg_stack_slots, 0,
+                 max_regno * sizeof (struct ira_spilled_reg_stack_slot));
+       }
     }
   allocate_initial_values ();
 
@@ -5286,10 +5371,18 @@ do_reload (void)
 {
   basic_block bb;
   bool need_dce;
+  unsigned pic_offset_table_regno = INVALID_REGNUM;
 
   if (flag_ira_verbose < 10)
     ira_dump_file = dump_file;
 
+  /* If pic_offset_table_rtx is a pseudo register, then keep it so
+     after reload to avoid possible wrong usages of hard reg assigned
+     to it.  */
+  if (pic_offset_table_rtx
+      && REGNO (pic_offset_table_rtx) >= FIRST_PSEUDO_REGISTER)
+    pic_offset_table_regno = REGNO (pic_offset_table_rtx);
+
   timevar_push (TV_RELOAD);
   if (ira_use_lra_p)
     {
@@ -5301,9 +5394,6 @@ do_reload (void)
       FOR_ALL_BB_FN (bb, cfun)
        bb->loop_father = NULL;
       current_loops = NULL;
-      
-      if (ira_conflicts_p)
-       ira_free (ira_spilled_reg_stack_slots);
 
       ira_destroy ();
 
@@ -5335,7 +5425,8 @@ do_reload (void)
 
   if (internal_flag_ira_verbose > 0 && ira_dump_file != NULL
       && overall_cost_before != ira_overall_cost)
-    fprintf (ira_dump_file, "+++Overall after reload %d\n", ira_overall_cost);
+    fprintf (ira_dump_file, "+++Overall after reload %" PRId64 "\n",
+            ira_overall_cost);
 
   flag_ira_share_spill_slots = saved_flag_ira_share_spill_slots;
 
@@ -5397,6 +5488,9 @@ do_reload (void)
       inform (DECL_SOURCE_LOCATION (decl), "for %qD", decl);
     }
 
+  if (pic_offset_table_regno != INVALID_REGNUM)
+    pic_offset_table_rtx = gen_rtx_REG (Pmode, pic_offset_table_regno);
+
   timevar_pop (TV_IRA);
 }
 \f
@@ -5425,6 +5519,10 @@ public:
   {}
 
   /* opt_pass methods: */
+  virtual bool gate (function *)
+    {
+      return !targetm.no_register_allocation;
+    }
   virtual unsigned int execute (function *)
     {
       ira (dump_file);
@@ -5464,6 +5562,10 @@ public:
   {}
 
   /* opt_pass methods: */
+  virtual bool gate (function *)
+    {
+      return !targetm.no_register_allocation;
+    }
   virtual unsigned int execute (function *)
     {
       do_reload ();