Index: ira-int.h
===================================================================
--- ira-int.h	(revision 191771)
+++ ira-int.h	(working copy)
@@ -795,11 +795,6 @@ struct target_ira_int {
   /* Map class->true if class is a pressure class, false otherwise. */
   bool x_ira_reg_pressure_class_p[N_REG_CLASSES];
 
-  /* Register class subset relation: TRUE if the first class is a subset
-     of the second one considering only hard registers available for the
-     allocation.  */
-  int x_ira_class_subset_p[N_REG_CLASSES][N_REG_CLASSES];
-
   /* Array of the number of hard registers of given class which are
      available for allocation.  The order is defined by the hard
      register numbers.  */
@@ -838,13 +833,8 @@ struct target_ira_int {
      taking all hard-registers including fixed ones into account.  */
   enum reg_class x_ira_reg_class_intersect[N_REG_CLASSES][N_REG_CLASSES];
 
-  /* True if the two classes (that is calculated taking only hard
-     registers available for allocation into account; are
-     intersected.  */
-  bool x_ira_reg_classes_intersect_p[N_REG_CLASSES][N_REG_CLASSES];
-
   /* Classes with end marker LIM_REG_CLASSES which are intersected with
-     given class (the first index;.  That includes given class itself.
+     given class (the first index).  That includes given class itself.
      This is calculated taking only hard registers available for
      allocation into account.  */
   enum reg_class x_ira_reg_class_super_classes[N_REG_CLASSES][N_REG_CLASSES];
@@ -861,7 +851,7 @@ struct target_ira_int {
 
   /* For each reg class, table listing all the classes contained in it
      (excluding the class itself.  Non-allocatable registers are
-     excluded from the consideration;.  */
+     excluded from the consideration).  */
   enum reg_class x_alloc_reg_class_subclasses[N_REG_CLASSES][N_REG_CLASSES];
 
   /* Array whose values are hard regset of hard registers for which
@@ -894,8 +884,6 @@ extern struct target_ira_int *this_targe
   (this_target_ira_int->x_ira_reg_allocno_class_p)
 #define ira_reg_pressure_class_p \
   (this_target_ira_int->x_ira_reg_pressure_class_p)
-#define ira_class_subset_p \
-  (this_target_ira_int->x_ira_class_subset_p)
 #define ira_non_ordered_class_hard_regs \
   (this_target_ira_int->x_ira_non_ordered_class_hard_regs)
 #define ira_class_hard_reg_index \
@@ -912,8 +900,6 @@ extern struct target_ira_int *this_targe
   (this_target_ira_int->x_ira_uniform_class_p)
 #define ira_reg_class_intersect \
   (this_target_ira_int->x_ira_reg_class_intersect)
-#define ira_reg_classes_intersect_p \
-  (this_target_ira_int->x_ira_reg_classes_intersect_p)
 #define ira_reg_class_super_classes \
   (this_target_ira_int->x_ira_reg_class_super_classes)
 #define ira_reg_class_subunion \
@@ -934,17 +920,6 @@ extern void ira_debug_disposition (void)
 extern void ira_debug_allocno_classes (void);
 extern void ira_init_register_move_cost (enum machine_mode);
 
-/* The length of the two following arrays.  */
-extern int ira_reg_equiv_len;
-
-/* The element value is TRUE if the corresponding regno value is
-   invariant.  */
-extern bool *ira_reg_equiv_invariant_p;
-
-/* The element value is equiv constant of given pseudo-register or
-   NULL_RTX.  */
-extern rtx *ira_reg_equiv_const;
-
 /* ira-build.c */
 
 /* The current loop tree node and its regno allocno map.  */
@@ -1028,6 +1003,20 @@ extern void ira_emit (bool);
 
 
 
+/* Return true if equivalence of pseudo REGNO is not a lvalue.  */
+static inline bool
+ira_equiv_no_lvalue_p (int regno)
+{
+  if (regno >= ira_reg_equiv_len)
+    return false;
+  return (ira_reg_equiv[regno].constant != NULL_RTX
+	  || ira_reg_equiv[regno].invariant != NULL_RTX
+	  || (ira_reg_equiv[regno].memory != NULL_RTX
+	      && MEM_READONLY_P (ira_reg_equiv[regno].memory)));
+}
+
+
+
 /* Initialize register costs for MODE if necessary.  */
 static inline void
 ira_init_register_move_cost_if_necessary (enum machine_mode mode)
Index: ira.c
===================================================================
--- ira.c	(revision 191771)
+++ ira.c	(working copy)
@@ -1201,6 +1201,7 @@ setup_reg_class_relations (void)
 	{
 	  ira_reg_classes_intersect_p[cl1][cl2] = false;
 	  ira_reg_class_intersect[cl1][cl2] = NO_REGS;
+	  ira_reg_class_subset[cl1][cl2] = NO_REGS;
 	  COPY_HARD_REG_SET (temp_hard_regset, reg_class_contents[cl1]);
 	  AND_COMPL_HARD_REG_SET (temp_hard_regset, no_unit_alloc_regs);
 	  COPY_HARD_REG_SET (temp_set2, reg_class_contents[cl2]);
@@ -1248,9 +1249,8 @@ setup_reg_class_relations (void)
 	  COPY_HARD_REG_SET (union_set, reg_class_contents[cl1]);
 	  IOR_HARD_REG_SET (union_set, reg_class_contents[cl2]);
 	  AND_COMPL_HARD_REG_SET (union_set, no_unit_alloc_regs);
-	  for (i = 0; i < ira_important_classes_num; i++)
+	  for (cl3 = 0; cl3 < N_REG_CLASSES; cl3++)
 	    {
-	      cl3 = ira_important_classes[i];
 	      COPY_HARD_REG_SET (temp_hard_regset, reg_class_contents[cl3]);
 	      AND_COMPL_HARD_REG_SET (temp_hard_regset, no_unit_alloc_regs);
 	      if (hard_reg_set_subset_p (temp_hard_regset, intersection_set))
@@ -1258,25 +1258,45 @@ setup_reg_class_relations (void)
 		  /* CL3 allocatable hard register set is inside of
 		     intersection of allocatable hard register sets
 		     of CL1 and CL2.  */
+		  if (important_class_p[cl3])
+		    {
+		      COPY_HARD_REG_SET
+			(temp_set2,
+			 reg_class_contents
+			 [(int) ira_reg_class_intersect[cl1][cl2]]);
+		      AND_COMPL_HARD_REG_SET (temp_set2, no_unit_alloc_regs);
+		      if (! hard_reg_set_subset_p (temp_hard_regset, temp_set2)
+			  /* If the allocatable hard register sets are
+			     the same, prefer GENERAL_REGS or the
+			     smallest class for debugging
+			     purposes.  */
+			  || (hard_reg_set_equal_p (temp_hard_regset, temp_set2)
+			      && (cl3 == GENERAL_REGS
+				  || ((ira_reg_class_intersect[cl1][cl2]
+				       != GENERAL_REGS)
+				      && hard_reg_set_subset_p
+				         (reg_class_contents[cl3],
+					  reg_class_contents
+					  [(int)
+					   ira_reg_class_intersect[cl1][cl2]])))))
+			ira_reg_class_intersect[cl1][cl2] = (enum reg_class) cl3;
+		    }
 		  COPY_HARD_REG_SET
 		    (temp_set2,
-		     reg_class_contents[(int)
-					ira_reg_class_intersect[cl1][cl2]]);
+		     reg_class_contents[(int) ira_reg_class_subset[cl1][cl2]]);
 		  AND_COMPL_HARD_REG_SET (temp_set2, no_unit_alloc_regs);
-	 	  if (! hard_reg_set_subset_p (temp_hard_regset, temp_set2)
-		      /* If the allocatable hard register sets are the
-			 same, prefer GENERAL_REGS or the smallest
-			 class for debugging purposes.  */
+		  if (! hard_reg_set_subset_p (temp_hard_regset, temp_set2)
+		      /* Ignore unavailable hard registers and prefer
+			 smallest class for debugging purposes.  */
 		      || (hard_reg_set_equal_p (temp_hard_regset, temp_set2)
-			  && (cl3 == GENERAL_REGS
-			      || (ira_reg_class_intersect[cl1][cl2] != GENERAL_REGS
-				  && hard_reg_set_subset_p
-				     (reg_class_contents[cl3],
-				      reg_class_contents
-				      [(int) ira_reg_class_intersect[cl1][cl2]])))))
-		    ira_reg_class_intersect[cl1][cl2] = (enum reg_class) cl3;
+			  && hard_reg_set_subset_p
+			     (reg_class_contents[cl3],
+			      reg_class_contents
+			      [(int) ira_reg_class_subset[cl1][cl2]])))
+		    ira_reg_class_subset[cl1][cl2] = (enum reg_class) cl3;
 		}
-	      if (hard_reg_set_subset_p (temp_hard_regset, union_set))
+	      if (important_class_p[cl3]
+		  && hard_reg_set_subset_p (temp_hard_regset, union_set))
 		{
 		  /* CL3 allocatbale hard register set is inside of
 		     union of allocatable hard register sets of CL1
@@ -1885,66 +1905,6 @@ ira_setup_eliminable_regset (void)
 
 
 
-/* The length of the following two arrays.  */
-int ira_reg_equiv_len;
-
-/* The element value is TRUE if the corresponding regno value is
-   invariant.  */
-bool *ira_reg_equiv_invariant_p;
-
-/* The element value is equiv constant of given pseudo-register or
-   NULL_RTX.  */
-rtx *ira_reg_equiv_const;
-
-/* Set up the two arrays declared above.  */
-static void
-find_reg_equiv_invariant_const (void)
-{
-  unsigned int i;
-  bool invariant_p;
-  rtx list, insn, note, constant, x;
-
-  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))
-	{
-	  insn = XEXP (list, 0);
-	  note = find_reg_note (insn, REG_EQUIV, NULL_RTX);
-
-	  if (note == NULL_RTX)
-	    continue;
-
-	  x = XEXP (note, 0);
-
-	  if (! CONSTANT_P (x)
-	      || ! flag_pic || LEGITIMATE_PIC_OPERAND_P (x))
-	    {
-	      /* It can happen that a REG_EQUIV note contains a MEM
-		 that is not a legitimate memory operand.  As later
-		 stages of the reload assume that all addresses found
-		 in the reg_equiv_* arrays were originally legitimate,
-		 we ignore such REG_EQUIV notes.  */
-	      if (memory_operand (x, VOIDmode))
-		invariant_p = MEM_READONLY_P (x);
-	      else if (function_invariant_p (x))
-		{
-		  if (GET_CODE (x) == PLUS
-		      || x == frame_pointer_rtx || x == arg_pointer_rtx)
-		    invariant_p = true;
-		  else
-		    constant = x;
-		}
-	    }
-	}
-      ira_reg_equiv_invariant_p[i] = invariant_p;
-      ira_reg_equiv_const[i] = constant;
-    }
-}
-
-
-
 /* Vector of substitutions of register numbers,
    used to map pseudo regs into hardware regs.
    This is set up as a result of register allocation.
@@ -1965,6 +1925,8 @@ setup_reg_renumber (void)
   caller_save_needed = 0;
   FOR_EACH_ALLOCNO (a, ai)
     {
+      if (ira_use_lra_p && ALLOCNO_CAP_MEMBER (a) != NULL)
+	continue;
       /* There are no caps at this point.  */
       ira_assert (ALLOCNO_CAP_MEMBER (a) == NULL);
       if (! ALLOCNO_ASSIGNED_P (a))
@@ -1996,9 +1958,7 @@ setup_reg_renumber (void)
 	      ira_assert (!optimize || flag_caller_saves
 			  || (ALLOCNO_CALLS_CROSSED_NUM (a)
 			      == ALLOCNO_CHEAP_CALLS_CROSSED_NUM (a))
-			  || regno >= ira_reg_equiv_len
-			  || ira_reg_equiv_const[regno]
-			  || ira_reg_equiv_invariant_p[regno]);
+			  || ira_equiv_no_lvalue_p (regno));
 	      caller_save_needed = 1;
 	    }
 	}
@@ -2165,6 +2125,109 @@ check_allocation (void)
 }
 #endif
 
+/* Allocate REG_EQUIV_INIT.  Set up it from IRA_REG_EQUIV which should
+   be already calculated.  */
+static void
+setup_reg_equiv_init (void)
+{
+  int i;
+  int max_regno = max_reg_num ();
+
+  for (i = 0; i < max_regno; i++)
+    reg_equiv_init (i) = ira_reg_equiv[i].init_insns;
+}
+
+/* Update equiv regno from movement of FROM_REGNO to TO_REGNO.  INSNS
+   are insns which were generated for such movement.  It is assumed
+   that FROM_REGNO and TO_REGNO always have the same value at the
+   point of any move containing such registers. This function is used
+   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)
+{
+  rtx insn, x, note;
+
+  if (! ira_reg_equiv[from_regno].defined_p
+      && (! ira_reg_equiv[to_regno].defined_p
+	  || ((x = ira_reg_equiv[to_regno].memory) != NULL_RTX
+	      && ! MEM_READONLY_P (x))))
+      return;
+  insn = insns;
+  if (NEXT_INSN (insn) != NULL_RTX)
+    {
+      if (! ira_reg_equiv[to_regno].defined_p)
+	{
+	  ira_assert (ira_reg_equiv[to_regno].init_insns == NULL_RTX);
+	  return;
+	}
+      ira_reg_equiv[to_regno].defined_p = false;
+      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;
+      if (internal_flag_ira_verbose > 3 && ira_dump_file != NULL)
+	fprintf (ira_dump_file,
+		 "      Invalidating equiv info for reg %d\n", to_regno);
+      return;
+    }
+  /* It is possible that FROM_REGNO still has no equivalence because
+     in shuffles to_regno<-from_regno and from_regno<-to_regno the 2nd
+     insn was not processed yet.  */
+  if (ira_reg_equiv[from_regno].defined_p)
+    {
+      ira_reg_equiv[to_regno].defined_p = true;
+      if ((x = ira_reg_equiv[from_regno].memory) != NULL_RTX)
+	{
+	  ira_assert (ira_reg_equiv[from_regno].invariant == NULL_RTX
+		      && ira_reg_equiv[from_regno].constant == NULL_RTX);
+	  ira_assert (ira_reg_equiv[to_regno].memory == NULL_RTX
+		      || rtx_equal_p (ira_reg_equiv[to_regno].memory, x));
+	  ira_reg_equiv[to_regno].memory = x;
+	  if (! MEM_READONLY_P (x))
+	    /* We don't add the insn to insn init list because memory
+	       equivalence is just to say what memory is better to use
+	       when the pseudo is spilled.  */
+	    return;
+	}
+      else if ((x = ira_reg_equiv[from_regno].constant) != NULL_RTX)
+	{
+	  ira_assert (ira_reg_equiv[from_regno].invariant == NULL_RTX);
+	  ira_assert (ira_reg_equiv[to_regno].constant == NULL_RTX
+		      || rtx_equal_p (ira_reg_equiv[to_regno].constant, x));
+	  ira_reg_equiv[to_regno].constant = x;
+	}
+      else
+	{
+	  x = ira_reg_equiv[from_regno].invariant;
+	  ira_assert (x != NULL_RTX);
+	  ira_assert (ira_reg_equiv[to_regno].invariant == NULL_RTX
+		      || rtx_equal_p (ira_reg_equiv[to_regno].invariant, x));
+	  ira_reg_equiv[to_regno].invariant = x;
+	}
+      if (find_reg_note (insn, REG_EQUIV, x) == NULL_RTX)
+	{
+	  note = set_unique_reg_note (insn, REG_EQUIV, x);
+	  gcc_assert (note != NULL_RTX);
+	  if (internal_flag_ira_verbose > 3 && ira_dump_file != NULL)
+	    {
+	      fprintf (ira_dump_file,
+		       "      Adding equiv note to insn %u for reg %d ",
+		       INSN_UID (insn), to_regno);
+	      print_value_slim (ira_dump_file, x, 1);
+	      fprintf (ira_dump_file, "\n");
+	    }
+	}
+    }
+  ira_reg_equiv[to_regno].init_insns
+    = gen_rtx_INSN_LIST (VOIDmode, insn,
+			 ira_reg_equiv[to_regno].init_insns);
+  if (internal_flag_ira_verbose > 3 && ira_dump_file != NULL)
+    fprintf (ira_dump_file,
+	     "      Adding equiv init move insn %u to reg %d\n",
+	     INSN_UID (insn), to_regno);
+}
+
 /* Fix values of array REG_EQUIV_INIT after live range splitting done
    by IRA.  */
 static void
@@ -2202,6 +2265,7 @@ fix_reg_equiv_init (void)
 	      prev = x;
 	    else
 	      {
+		/* Remove the wrong list element.  */
 		if (prev == NULL_RTX)
 		  reg_equiv_init (i) = next;
 		else
@@ -2334,6 +2398,46 @@ mark_elimination (int from, int to)
 
 
 
+/* The length of the following array.  */
+int ira_reg_equiv_len;
+
+/* Info about equiv. info for each register.  */
+struct ira_reg_equiv *ira_reg_equiv;
+
+/* Expand ira_reg_equiv if necessary.  */
+void
+ira_expand_reg_equiv (void)
+{
+  int old = ira_reg_equiv_len;
+
+  if (ira_reg_equiv_len > max_reg_num ())
+    return;
+  ira_reg_equiv_len = max_reg_num () * 3 / 2 + 1;
+  ira_reg_equiv
+    = (struct ira_reg_equiv *) xrealloc (ira_reg_equiv,
+					 ira_reg_equiv_len
+					 * sizeof (struct ira_reg_equiv));
+  gcc_assert (old < ira_reg_equiv_len);
+  memset (ira_reg_equiv + old, 0,
+	  sizeof (struct ira_reg_equiv) * (ira_reg_equiv_len - old));
+}
+
+static void
+init_reg_equiv (void)
+{
+  ira_reg_equiv_len = 0;
+  ira_reg_equiv = NULL;
+  ira_expand_reg_equiv ();
+}
+
+static void
+finish_reg_equiv (void)
+{
+  free (ira_reg_equiv);
+}
+
+
+
 struct equivalence
 {
   /* Set when a REG_EQUIV note is found or created.  Use to
@@ -2707,7 +2811,8 @@ no_equiv (rtx reg, const_rtx store ATTRI
      should keep their initialization insns.  */
   if (reg_equiv[regno].is_arg_equivalence)
     return;
-  reg_equiv_init (regno) = NULL_RTX;
+  ira_reg_equiv[regno].defined_p = false;
+  ira_reg_equiv[regno].init_insns = NULL_RTX;
   for (; list; list =  XEXP (list, 1))
     {
       rtx insn = XEXP (list, 0);
@@ -2743,7 +2848,7 @@ static int recorded_label_ref;
    value into the using insn.  If it succeeds, we can eliminate the
    register completely.
 
-   Initialize the REG_EQUIV_INIT array of initializing insns.
+   Initialize init_insns in ira_reg_equiv array.
 
    Return non-zero if jump label rebuilding should be done.  */
 static int
@@ -2818,14 +2923,16 @@ update_equiv_regs (void)
 	      gcc_assert (REG_P (dest));
 	      regno = REGNO (dest);
 
-	      /* Note that we don't want to clear reg_equiv_init even if there
-		 are multiple sets of this register.  */
+	      /* Note that we don't want to clear init_insns in
+		 ira_reg_equiv even if there are multiple sets of this
+		 register.  */
 	      reg_equiv[regno].is_arg_equivalence = 1;
 
 	      /* 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));
+		ira_reg_equiv[regno].init_insns
+		  = gen_rtx_INSN_LIST (VOIDmode, insn,
+				       ira_reg_equiv[regno].init_insns);
 
 	      /* Continue normally in case this is a candidate for
 		 replacements.  */
@@ -2925,8 +3032,9 @@ 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));
+		ira_reg_equiv[regno].init_insns
+		  = gen_rtx_INSN_LIST (VOIDmode, insn,
+				       ira_reg_equiv[regno].init_insns);
 
 	      /* 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
@@ -3026,7 +3134,7 @@ update_equiv_regs (void)
 	    {
 	      /* This insn makes the equivalence, not the one initializing
 		 the register.  */
-	      reg_equiv_init (regno)
+	      ira_reg_equiv[regno].init_insns
 		= gen_rtx_INSN_LIST (VOIDmode, insn, NULL_RTX);
 	      df_notes_rescan (init_insn);
 	    }
@@ -3080,9 +3188,10 @@ update_equiv_regs (void)
 
 		  /* reg_equiv[REGNO].replace gets set only when
 		     REG_N_REFS[REGNO] is 2, i.e. the register is set
-		     once and used once.  (If it were only set, but not used,
-		     flow would have deleted the setting insns.)  Hence
-		     there can only be one insn in reg_equiv[REGNO].init_insns.  */
+		     once and used once.  (If it were only set, but
+		     not used, flow would have deleted the setting
+		     insns.)  Hence there can only be one insn in
+		     reg_equiv[REGNO].init_insns.  */
 		  gcc_assert (reg_equiv[regno].init_insns
 			      && !XEXP (reg_equiv[regno].init_insns, 1));
 		  equiv_insn = XEXP (reg_equiv[regno].init_insns, 0);
@@ -3129,7 +3238,7 @@ update_equiv_regs (void)
 		      reg_equiv[regno].init_insns
 			= XEXP (reg_equiv[regno].init_insns, 1);
 
-		      reg_equiv_init (regno) = NULL_RTX;
+		      ira_reg_equiv[regno].init_insns = NULL_RTX;
 		      bitmap_set_bit (cleared_regs, regno);
 		    }
 		  /* Move the initialization of the register to just before
@@ -3162,7 +3271,7 @@ update_equiv_regs (void)
 		      if (insn == BB_HEAD (bb))
 			BB_HEAD (bb) = PREV_INSN (insn);
 
-		      reg_equiv_init (regno)
+		      ira_reg_equiv[regno].init_insns
 			= gen_rtx_INSN_LIST (VOIDmode, new_insn, NULL_RTX);
 		      bitmap_set_bit (cleared_regs, regno);
 		    }
@@ -3208,6 +3317,88 @@ update_equiv_regs (void)
 
 
 
+/* Set up fields memory, constant, and invariant from init_insns in
+   the structures of array ira_reg_equiv.  */
+static void
+setup_reg_equiv (void)
+{
+  int i;
+  rtx elem, insn, set, x;
+
+  for (i = FIRST_PSEUDO_REGISTER; i < ira_reg_equiv_len; i++)
+    for (elem = ira_reg_equiv[i].init_insns; elem; elem = XEXP (elem, 1))
+      {
+	insn = XEXP (elem, 0);
+	set = single_set (insn);
+	
+	/* Init insns can set up equivalence when the reg is a destination or
+	   a source (in this case the destination is memory).  */
+	if (set != 0 && (REG_P (SET_DEST (set)) || REG_P (SET_SRC (set))))
+	  {
+	    if ((x = find_reg_note (insn, REG_EQUIV, NULL_RTX)) != NULL)
+	      x = XEXP (x, 0);
+	    else if (REG_P (SET_DEST (set))
+		     && REGNO (SET_DEST (set)) == (unsigned int) i)
+	      x = SET_SRC (set);
+	    else
+	      {      
+		gcc_assert (REG_P (SET_SRC (set))
+			    && REGNO (SET_SRC (set)) == (unsigned int) i);
+		x = SET_DEST (set);
+	      }
+	    if (! function_invariant_p (x)
+		|| ! flag_pic
+		/* A function invariant is often CONSTANT_P but may
+		   include a register.  We promise to only pass
+		   CONSTANT_P objects to LEGITIMATE_PIC_OPERAND_P.  */
+		|| (CONSTANT_P (x) && LEGITIMATE_PIC_OPERAND_P (x)))
+	      {
+		/* It can happen that a REG_EQUIV note contains a MEM
+		   that is not a legitimate memory operand.  As later
+		   stages of reload assume that all addresses found in
+		   the lra_regno_equiv_* arrays were originally
+		   legitimate, we ignore such REG_EQUIV notes.  */
+		if (memory_operand (x, VOIDmode))
+		  {
+		    ira_reg_equiv[i].defined_p = true;
+		    ira_reg_equiv[i].memory = x;
+		    continue;
+		  }
+		else if (function_invariant_p (x))
+		  {
+		    enum machine_mode mode;
+		    
+		    mode = GET_MODE (SET_DEST (set));
+		    if (GET_CODE (x) == PLUS
+			|| x == frame_pointer_rtx || x == arg_pointer_rtx)
+		      /* This is PLUS of frame pointer and a constant,
+			 or fp, or argp.  */
+		      ira_reg_equiv[i].invariant = x;
+		    else if (targetm.legitimate_constant_p (mode, x))
+		      ira_reg_equiv[i].constant = x;
+		    else
+		      {
+			ira_reg_equiv[i].memory = force_const_mem (mode, x);
+			if (ira_reg_equiv[i].memory == NULL_RTX)
+			  {
+			    ira_reg_equiv[i].defined_p = false;
+			    ira_reg_equiv[i].init_insns = NULL_RTX;
+			    break;
+			  }
+		      }
+		    ira_reg_equiv[i].defined_p = true;
+		    continue;
+		  }
+	      }
+	  }
+	ira_reg_equiv[i].defined_p = false;
+	ira_reg_equiv[i].init_insns = NULL_RTX;
+	break;
+      }
+}
+
+
+
 /* Print chain C to FILE.  */
 static void
 print_insn_chain (FILE *file, struct insn_chain *c)
@@ -4102,6 +4293,11 @@ allocate_initial_values (void)
     }
 }
 
+
+/* True when we use LRA instead of reload pass for the current
+   function.  */
+bool ira_use_lra_p;
+
 /* All natural loops.  */
 struct loops ira_loops;
 
@@ -4120,6 +4316,13 @@ ira (FILE *f)
   int max_regno_before_ira, ira_max_point_before_emit;
   int rebuild_p;
 
+  ira_use_lra_p = targetm.lra_p ();
+
+#ifndef IRA_NO_OBSTACK
+  gcc_obstack_init (&ira_obstack);
+#endif
+  bitmap_obstack_initialize (&ira_bitmap_obstack);
+
   if (flag_caller_saves)
     init_caller_save ();
 
@@ -4166,30 +4369,18 @@ ira (FILE *f)
   if (resize_reg_info () && flag_ira_loop_pressure)
     ira_set_pseudo_classes (ira_dump_file);
 
+  init_reg_equiv ();
   rebuild_p = update_equiv_regs ();
+  setup_reg_equiv ();
+  setup_reg_equiv_init ();
 
-#ifndef IRA_NO_OBSTACK
-  gcc_obstack_init (&ira_obstack);
-#endif
-  bitmap_obstack_initialize (&ira_bitmap_obstack);
-  if (optimize)
+  if (optimize && rebuild_p)
     {
-      max_regno = max_reg_num ();
-      ira_reg_equiv_len = max_regno;
-      ira_reg_equiv_invariant_p
-	= (bool *) ira_allocate (max_regno * sizeof (bool));
-      memset (ira_reg_equiv_invariant_p, 0, max_regno * sizeof (bool));
-      ira_reg_equiv_const = (rtx *) ira_allocate (max_regno * sizeof (rtx));
-      memset (ira_reg_equiv_const, 0, max_regno * sizeof (rtx));
-      find_reg_equiv_invariant_const ();
-      if (rebuild_p)
-	{
-	  timevar_push (TV_JUMP);
-	  rebuild_jump_labels (get_insns ());
-	  if (purge_all_dead_edges ())
-	    delete_unreachable_blocks ();
-	  timevar_pop (TV_JUMP);
-	}
+      timevar_push (TV_JUMP);
+      rebuild_jump_labels (get_insns ());
+      if (purge_all_dead_edges ())
+	delete_unreachable_blocks ();
+      timevar_pop (TV_JUMP);
     }
 
   allocated_reg_info_size = max_reg_num ();
@@ -4241,19 +4432,32 @@ ira (FILE *f)
 
   ira_emit (loops_p);
 
+  max_regno = max_reg_num ();
   if (ira_conflicts_p)
     {
-      max_regno = max_reg_num ();
-
       if (! loops_p)
-	ira_initiate_assign ();
+	{
+	  if (! ira_use_lra_p)
+	    ira_initiate_assign ();
+	}
       else
 	{
 	  expand_reg_info ();
 
-	  if (internal_flag_ira_verbose > 0 && ira_dump_file != NULL)
-	    fprintf (ira_dump_file, "Flattening IR\n");
-	  ira_flattening (max_regno_before_ira, ira_max_point_before_emit);
+	  if (ira_use_lra_p)
+	    {
+	      ira_allocno_t a;
+	      ira_allocno_iterator ai;
+
+	      FOR_EACH_ALLOCNO (a, ai)
+		ALLOCNO_REGNO (a) = REGNO (ALLOCNO_EMIT_DATA (a)->reg);
+	    }
+	  else
+	    {
+	      if (internal_flag_ira_verbose > 0 && ira_dump_file != NULL)
+		fprintf (ira_dump_file, "Flattening IR\n");
+	      ira_flattening (max_regno_before_ira, ira_max_point_before_emit);
+	    }
 	  /* New insns were generated: add notes and recalculate live
 	     info.  */
 	  df_analyze ();
@@ -4262,9 +4466,12 @@ ira (FILE *f)
 	  record_loop_exits ();
 	  current_loops = &ira_loops;
 
-	  setup_allocno_assignment_flags ();
-	  ira_initiate_assign ();
-	  ira_reassign_conflict_allocnos (max_regno);
+	  if (! ira_use_lra_p)
+	    {
+	      setup_allocno_assignment_flags ();
+	      ira_initiate_assign ();
+	      ira_reassign_conflict_allocnos (max_regno);
+	    }
 	}
     }
 
@@ -4322,45 +4529,72 @@ do_reload (void)
   if (flag_ira_verbose < 10)
     ira_dump_file = dump_file;
 
-  df_set_flags (DF_NO_INSN_RESCAN);
-  build_insn_chain ();
+  timevar_push (TV_RELOAD);
+  if (ira_use_lra_p)
+    {
+      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;
+      
+      if (ira_conflicts_p)
+	ira_free (ira_spilled_reg_stack_slots);
 
-  need_dce = reload (get_insns (), ira_conflicts_p);
+      ira_destroy ();
+
+      VEC_free (reg_equivs_t, gc, reg_equivs);
+      reg_equivs = NULL;
+      need_dce = false;
+    }
+  else
+    {
+      df_set_flags (DF_NO_INSN_RESCAN);
+      build_insn_chain ();
+      
+      need_dce = reload (get_insns (), ira_conflicts_p);
+
+    }
+
+  timevar_pop (TV_RELOAD);
 
   timevar_push (TV_IRA);
 
-  if (ira_conflicts_p)
+  if (ira_conflicts_p && ! ira_use_lra_p)
     {
       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)
     fprintf (ira_dump_file, "+++Overall after reload %d\n", ira_overall_cost);
-  ira_destroy ();
 
   flag_ira_share_spill_slots = saved_flag_ira_share_spill_slots;
 
-  if (current_loops != NULL)
+  if (! ira_use_lra_p)
     {
-      flow_loops_free (&ira_loops);
-      free_dominance_info (CDI_DOMINATORS);
+      ira_destroy ();
+      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;
+      
+      regstat_free_ri ();
+      regstat_free_n_sets_and_refs ();
     }
-  FOR_ALL_BB (bb)
-    bb->loop_father = NULL;
-  current_loops = NULL;
-
-  regstat_free_ri ();
-  regstat_free_n_sets_and_refs ();
 
   if (optimize)
-    {
-      cleanup_cfg (CLEANUP_EXPENSIVE);
+    cleanup_cfg (CLEANUP_EXPENSIVE);
 
-      ira_free (ira_reg_equiv_invariant_p);
-      ira_free (ira_reg_equiv_const);
-    }
+  finish_reg_equiv ();
 
   bitmap_obstack_release (&ira_bitmap_obstack);
 #ifndef IRA_NO_OBSTACK
Index: ira.h
===================================================================
--- ira.h	(revision 191771)
+++ ira.h	(working copy)
@@ -20,11 +20,16 @@ You should have received a copy of the G
 along with GCC; see the file COPYING3.  If not see
 <http://www.gnu.org/licenses/>.  */
 
+/* True when we use LRA instead of reload pass for the current
+   function.  */
+extern bool ira_use_lra_p;
+
 /* True if we have allocno conflicts.  It is false for non-optimized
    mode or when the conflict table is too big.  */
 extern bool ira_conflicts_p;
 
-struct target_ira {
+struct target_ira
+{
   /* Map: hard register number -> allocno class it belongs to.  If the
      corresponding class is NO_REGS, the hard register is not available
      for allocation.  */
@@ -79,6 +84,23 @@ struct target_ira {
      class.  */
   int x_ira_class_hard_regs_num[N_REG_CLASSES];
 
+  /* Register class subset relation: TRUE if the first class is a subset
+     of the second one considering only hard registers available for the
+     allocation.  */
+  int x_ira_class_subset_p[N_REG_CLASSES][N_REG_CLASSES];
+
+  /* The biggest class inside of intersection of the two classes (that
+     is calculated taking only hard registers available for allocation
+     into account.  If the both classes contain no hard registers
+     available for allocation, the value is calculated with taking all
+     hard-registers including fixed ones into account.  */
+  enum reg_class x_ira_reg_class_subset[N_REG_CLASSES][N_REG_CLASSES];
+
+  /* True if the two classes (that is calculated taking only hard
+     registers available for allocation into account; are
+     intersected.  */
+  bool x_ira_reg_classes_intersect_p[N_REG_CLASSES][N_REG_CLASSES];
+
   /* Function specific hard registers can not be used for the register
      allocation.  */
   HARD_REG_SET x_ira_no_alloc_regs;
@@ -117,9 +139,37 @@ extern struct target_ira *this_target_ir
   (this_target_ira->x_ira_class_hard_regs)
 #define ira_class_hard_regs_num \
   (this_target_ira->x_ira_class_hard_regs_num)
+#define ira_class_subset_p \
+  (this_target_ira->x_ira_class_subset_p)
+#define ira_reg_class_subset \
+  (this_target_ira->x_ira_reg_class_subset)
+#define ira_reg_classes_intersect_p \
+  (this_target_ira->x_ira_reg_classes_intersect_p)
 #define ira_no_alloc_regs \
   (this_target_ira->x_ira_no_alloc_regs)
 
+/* Major structure describing equivalence info for a pseudo.  */
+struct ira_reg_equiv
+{
+  /* True if we can use this equivalence.  */
+  bool defined_p;
+  /* True if the usage of the equivalence is profitable.  */
+  bool profitable_p;
+  /* Equiv. memory, constant, invariant, and initializing insns of
+     given pseudo-register or NULL_RTX.  */
+  rtx memory;
+  rtx constant;
+  rtx invariant;
+  /* Always NULL_RTX if defined_p is false.  */
+  rtx init_insns;
+};
+
+/* The length of the following array.  */
+extern int ira_reg_equiv_len;
+
+/* Info about equiv. info for each register.  */
+extern struct ira_reg_equiv *ira_reg_equiv;
+
 extern void ira_init_once (void);
 extern void ira_init (void);
 extern void ira_finish_once (void);
@@ -127,6 +177,8 @@ extern void ira_setup_eliminable_regset
 extern rtx ira_eliminate_regs (rtx, enum machine_mode);
 extern void ira_set_pseudo_classes (FILE *);
 extern void ira_implicitly_set_insn_hard_regs (HARD_REG_SET *);
+extern void ira_expand_reg_equiv (void);
+extern void ira_update_equiv_info_by_shuffle_insn (int, int, rtx);
 
 extern void ira_sort_regnos_for_alter_reg (int *, int, unsigned int *);
 extern void ira_mark_allocation_change (int);
Index: ira-color.c
===================================================================
--- ira-color.c	(revision 191771)
+++ ira-color.c	(working copy)
@@ -2835,8 +2835,7 @@ color_pass (ira_loop_tree_node_t loop_tr
 	  exit_freq = ira_loop_edge_freq (subloop_node, regno, true);
 	  enter_freq = ira_loop_edge_freq (subloop_node, regno, false);
 	  ira_assert (regno < ira_reg_equiv_len);
-	  if (ira_reg_equiv_invariant_p[regno]
-	      || ira_reg_equiv_const[regno] != NULL_RTX)
+	  if (ira_equiv_no_lvalue_p (regno))
 	    {
 	      if (! ALLOCNO_ASSIGNED_P (subloop_allocno))
 		{
@@ -2941,9 +2940,7 @@ move_spill_restore (void)
 		 copies and the reload pass can spill the allocno set
 		 by copy although the allocno will not get memory
 		 slot.  */
-	      || (regno < ira_reg_equiv_len
-		  && (ira_reg_equiv_invariant_p[regno]
-		      || ira_reg_equiv_const[regno] != NULL_RTX))
+	      || ira_equiv_no_lvalue_p (regno)
 	      || !bitmap_bit_p (loop_node->border_allocnos, ALLOCNO_NUM (a)))
 	    continue;
 	  mode = ALLOCNO_MODE (a);
@@ -3367,9 +3364,7 @@ coalesce_allocnos (void)
       a = ira_allocnos[j];
       regno = ALLOCNO_REGNO (a);
       if (! ALLOCNO_ASSIGNED_P (a) || ALLOCNO_HARD_REGNO (a) >= 0
-	  || (regno < ira_reg_equiv_len
-	      && (ira_reg_equiv_const[regno] != NULL_RTX
-		  || ira_reg_equiv_invariant_p[regno])))
+	  || ira_equiv_no_lvalue_p (regno))
 	continue;
       for (cp = ALLOCNO_COPIES (a); cp != NULL; cp = next_cp)
 	{
@@ -3384,9 +3379,7 @@ coalesce_allocnos (void)
 	      if ((cp->insn != NULL || cp->constraint_p)
 		  && ALLOCNO_ASSIGNED_P (cp->second)
 		  && ALLOCNO_HARD_REGNO (cp->second) < 0
-		  && (regno >= ira_reg_equiv_len
-		      || (! ira_reg_equiv_invariant_p[regno]
-			  && ira_reg_equiv_const[regno] == NULL_RTX)))
+		  && ! ira_equiv_no_lvalue_p (regno))
 		sorted_copies[cp_num++] = cp;
 	    }
 	  else if (cp->second == a)
@@ -3652,9 +3645,7 @@ coalesce_spill_slots (ira_allocno_t *spi
       allocno = spilled_coalesced_allocnos[i];
       if (ALLOCNO_COALESCE_DATA (allocno)->first != allocno
 	  || bitmap_bit_p (set_jump_crosses, ALLOCNO_REGNO (allocno))
-	  || (ALLOCNO_REGNO (allocno) < ira_reg_equiv_len
-	      && (ira_reg_equiv_const[ALLOCNO_REGNO (allocno)] != NULL_RTX
-		  || ira_reg_equiv_invariant_p[ALLOCNO_REGNO (allocno)])))
+	  || ira_equiv_no_lvalue_p (ALLOCNO_REGNO (allocno)))
 	continue;
       for (j = 0; j < i; j++)
 	{
@@ -3662,9 +3653,7 @@ coalesce_spill_slots (ira_allocno_t *spi
 	  n = ALLOCNO_COALESCE_DATA (a)->temp;
 	  if (ALLOCNO_COALESCE_DATA (a)->first == a
 	      && ! bitmap_bit_p (set_jump_crosses, ALLOCNO_REGNO (a))
-	      && (ALLOCNO_REGNO (a) >= ira_reg_equiv_len
-		  || (! ira_reg_equiv_invariant_p[ALLOCNO_REGNO (a)]
-		      && ira_reg_equiv_const[ALLOCNO_REGNO (a)] == NULL_RTX))
+	      && ! ira_equiv_no_lvalue_p (ALLOCNO_REGNO (a))
 	      && ! slot_coalesced_allocno_live_ranges_intersect_p (allocno, n))
 	    break;
 	}
@@ -3772,9 +3761,7 @@ ira_sort_regnos_for_alter_reg (int *pseu
       allocno = spilled_coalesced_allocnos[i];
       if (ALLOCNO_COALESCE_DATA (allocno)->first != allocno
 	  || ALLOCNO_HARD_REGNO (allocno) >= 0
-	  || (ALLOCNO_REGNO (allocno) < ira_reg_equiv_len
-	      && (ira_reg_equiv_const[ALLOCNO_REGNO (allocno)] != NULL_RTX
-		  || ira_reg_equiv_invariant_p[ALLOCNO_REGNO (allocno)])))
+	  || ira_equiv_no_lvalue_p (ALLOCNO_REGNO (allocno)))
 	continue;
       if (internal_flag_ira_verbose > 3 && ira_dump_file != NULL)
 	fprintf (ira_dump_file, "      Slot %d (freq,size):", slot_num);
Index: ira-emit.c
===================================================================
--- ira-emit.c	(revision 191771)
+++ ira-emit.c	(working copy)
@@ -340,6 +340,7 @@ ira_create_new_reg (rtx original_reg)
   if (internal_flag_ira_verbose > 3 && ira_dump_file != NULL)
     fprintf (ira_dump_file, "      Creating newreg=%i from oldreg=%i\n",
 	     REGNO (new_reg), REGNO (original_reg));
+  ira_expand_reg_equiv ();
   return new_reg;
 }
 
@@ -515,8 +516,7 @@ generate_edge_moves (edge e)
 	/* Remove unnecessary stores at the region exit.  We should do
 	   this for readonly memory for sure and this is guaranteed by
 	   that we never generate moves on region borders (see
-	   checking ira_reg_equiv_invariant_p in function
-	   change_loop).  */
+	   checking in function change_loop).  */
  	if (ALLOCNO_HARD_REGNO (dest_allocno) < 0
 	    && ALLOCNO_HARD_REGNO (src_allocno) >= 0
 	    && store_can_be_removed_p (src_allocno, dest_allocno))
@@ -610,8 +610,7 @@ change_loop (ira_loop_tree_node_t node)
 		  /* don't create copies because reload can spill an
 		     allocno set by copy although the allocno will not
 		     get memory slot.  */
-		  || ira_reg_equiv_invariant_p[regno]
-		  || ira_reg_equiv_const[regno] != NULL_RTX))
+		  || ira_equiv_no_lvalue_p (regno)))
 	    continue;
 	  original_reg = allocno_emit_reg (allocno);
 	  if (parent_allocno == NULL
@@ -899,17 +898,22 @@ modify_move_list (move_t list)
 static rtx
 emit_move_list (move_t list, int freq)
 {
-  int cost, regno;
-  rtx result, insn, set, to;
+  rtx to, from, dest;
+  int to_regno, from_regno, cost, regno;
+  rtx result, insn, set;
   enum machine_mode mode;
   enum reg_class aclass;
 
+  grow_reg_equivs ();
   start_sequence ();
   for (; list != NULL; list = list->next)
     {
       start_sequence ();
-      emit_move_insn (allocno_emit_reg (list->to),
-		      allocno_emit_reg (list->from));
+      to = allocno_emit_reg (list->to);
+      to_regno = REGNO (to);
+      from = allocno_emit_reg (list->from);
+      from_regno = REGNO (from);
+      emit_move_insn (to, from);
       list->insn = get_insns ();
       end_sequence ();
       for (insn = list->insn; insn != NULL_RTX; insn = NEXT_INSN (insn))
@@ -925,21 +929,22 @@ emit_move_list (move_t list, int freq)
 	     to use the equivalence.  */
 	  if ((set = single_set (insn)) != NULL_RTX)
 	    {
-	      to = SET_DEST (set);
-	      if (GET_CODE (to) == SUBREG)
-		to = SUBREG_REG (to);
-	      ira_assert (REG_P (to));
-	      regno = REGNO (to);
+	      dest = SET_DEST (set);
+	      if (GET_CODE (dest) == SUBREG)
+		dest = SUBREG_REG (dest);
+	      ira_assert (REG_P (dest));
+	      regno = REGNO (dest);
 	      if (regno >= ira_reg_equiv_len
-		  || (! ira_reg_equiv_invariant_p[regno]
-		      && ira_reg_equiv_const[regno] == NULL_RTX))
+		  || (ira_reg_equiv[regno].invariant == NULL_RTX
+		      && ira_reg_equiv[regno].constant == NULL_RTX))
 		continue; /* regno has no equivalence.  */
 	      ira_assert ((int) VEC_length (reg_equivs_t, reg_equivs)
-			  >= ira_reg_equiv_len);
+			  > regno);
 	      reg_equiv_init (regno)
 		= gen_rtx_INSN_LIST (VOIDmode, insn, reg_equiv_init (regno));
 	    }
 	}
+      ira_update_equiv_info_by_shuffle_insn (to_regno, from_regno, list->insn);
       emit_insn (list->insn);
       mode = ALLOCNO_MODE (list->to);
       aclass = ALLOCNO_CLASS (list->to);
