Index: ChangeLog
===================================================================
--- ChangeLog	(revision 202721)
+++ ChangeLog	(working copy)
@@ -1,3 +1,12 @@
+2013-10-02  Vladimir Makarov  <vmakarov@redhat.com>
+
+	* lra-constraints.c (process_alt_operand): Calculate scratch_p and
+	use it.  Use smaller increase for scratch.  Don't increase reject
+	for early clobber scratch.
+	* lra-eliminations.c (eliminate_regs_in_insn): Remove all insns
+	setting eliminated regs except setting fp from hfp.
+	(lra_eliminate): Check lra_insn_recog_data on NULL.
+
 2013-09-18  Vladimir Makarov  <vmakarov@redhat.com>
 
 	* lra-constraints.c (need_for_all_save_p): Use macro
Index: config/aarch64/aarch64.c
===================================================================
--- config/aarch64/aarch64.c	(revision 202626)
+++ config/aarch64/aarch64.c	(working copy)
@@ -8151,6 +8151,16 @@ aarch64_vectorize_vec_perm_const_ok (enu
   return ret;
 }
 
+/* Return true if we use LRA instead of reload pass.  */
+static bool
+aarch64_lra_p (void)
+{
+  return aarch64_lra_flag;
+}
+
+#undef TARGET_LRA_P
+#define TARGET_LRA_P aarch64_lra_p
+
 #undef TARGET_ADDRESS_COST
 #define TARGET_ADDRESS_COST aarch64_address_cost
 
Index: config/aarch64/aarch64.opt
===================================================================
--- config/aarch64/aarch64.opt	(revision 202626)
+++ config/aarch64/aarch64.opt	(working copy)
@@ -83,6 +83,10 @@ momit-leaf-frame-pointer
 Target Report Save Var(flag_omit_leaf_frame_pointer) Init(1)
 Omit the frame pointer in leaf functions
 
+mlra
+Target Report Save Var(aarch64_lra_flag) Init(0)
+Use LRA
+
 mtls-dialect=
 Target RejectNegative Joined Enum(tls_type) Var(aarch64_tls_dialect) Init(TLS_DESCRIPTORS)
 Specify TLS dialect
Index: lra-constraints.c
===================================================================
--- lra-constraints.c	(revision 202721)
+++ lra-constraints.c	(working copy)
@@ -1453,6 +1453,7 @@ process_alt_operands (int only_alternati
 	  HARD_REG_SET this_alternative_set, this_costly_alternative_set;
 	  bool this_alternative_match_win, this_alternative_win;
 	  bool this_alternative_offmemok;
+	  bool scratch_p;
 	  enum machine_mode mode;
 
 	  opalt_num = nalt * n_operands + nop;
@@ -1858,6 +1859,8 @@ process_alt_operands (int only_alternati
 	    }
 	  while ((p += len), c);
 
+	  scratch_p = (operand_reg[nop] != NULL_RTX
+		       && lra_former_scratch_p (REGNO (operand_reg[nop])));
 	  /* Record which operands fit this alternative.  */
 	  if (win)
 	    {
@@ -1878,14 +1881,17 @@ process_alt_operands (int only_alternati
 		    }
 		  else
 		    {
-		      /* Prefer won reg to spilled pseudo under other equal
-			 conditions.  */
-		      if (lra_dump_file != NULL)
-			fprintf
-			  (lra_dump_file,
-			   "            %d Non pseudo reload: reject++\n",
-			   nop);
-		      reject++;
+		      /* Prefer won reg to spilled pseudo under other
+			 equal conditions for possibe inheritance.  */
+		      if (! scratch_p)
+			{
+			  if (lra_dump_file != NULL)
+			    fprintf
+			      (lra_dump_file,
+			       "            %d Non pseudo reload: reject++\n",
+			       nop);
+			  reject++;
+			}
 		      if (in_class_p (operand_reg[nop],
 				      this_costly_alternative, NULL))
 			{
@@ -1904,13 +1910,13 @@ process_alt_operands (int only_alternati
 		     insns are generated for the scratches.  So it
 		     might cost something but probably less than old
 		     reload pass believes.  */
-		  if (lra_former_scratch_p (REGNO (operand_reg[nop])))
+		  if (scratch_p)
 		    {
 		      if (lra_dump_file != NULL)
 			fprintf (lra_dump_file,
-				 "            %d Scratch win: reject+=3\n",
+				 "            %d Scratch win: reject+=2\n",
 				 nop);
-		      reject += 3;
+		      reject += 2;
 		    }
 		}
 	    }
@@ -2124,7 +2130,7 @@ process_alt_operands (int only_alternati
 		}
 	    }
 
-	  if (early_clobber_p)
+	  if (early_clobber_p && ! scratch_p)
 	    {
 	      if (lra_dump_file != NULL)
 		fprintf (lra_dump_file,
Index: lra-eliminations.c
===================================================================
--- lra-eliminations.c	(revision 202626)
+++ lra-eliminations.c	(working copy)
@@ -808,69 +808,69 @@ eliminate_regs_in_insn (rtx insn, bool r
   if (old_set != 0 && REG_P (SET_DEST (old_set))
       && (ep = get_elimination (SET_DEST (old_set))) != NULL)
     {
-      bool delete_p = replace_p;
-
+      for (ep = reg_eliminate; ep < &reg_eliminate[NUM_ELIMINABLE_REGS]; ep++)
+	if (ep->from_rtx == SET_DEST (old_set) && ep->can_eliminate)
+	  {
+	    bool delete_p = replace_p;
+	    
 #ifdef HARD_FRAME_POINTER_REGNUM
-      /* If this is setting the frame pointer register to the hardware
-	 frame pointer register and this is an elimination that will
-	 be done (tested above), this insn is really adjusting the
-	 frame pointer downward to compensate for the adjustment done
-	 before a nonlocal goto.  */
-      if (ep->from == FRAME_POINTER_REGNUM
-	  && ep->to == HARD_FRAME_POINTER_REGNUM)
-	{
-	  rtx src = SET_SRC (old_set);
-	  rtx off = remove_reg_equal_offset_note (insn, ep->to_rtx);
-
-	  if (replace_p)
-	    {
-	      SET_DEST (old_set) = ep->to_rtx;
-	      lra_update_insn_recog_data (insn);
-	      return;
-	    }
-	  else if (off != NULL_RTX
-		   || src == ep->to_rtx
-		   || (GET_CODE (src) == PLUS
-		       && XEXP (src, 1) == ep->to_rtx
-		       && CONST_INT_P (XEXP (src, 1))))
-	    {
-	      HOST_WIDE_INT offset = (off != NULL_RTX
-				      ? INTVAL (off)
-				      : src == ep->to_rtx
-				      ? 0 : INTVAL (XEXP (src, 1)));
-	      
-	      offset -= (ep->offset - ep->previous_offset);
-	      src = plus_constant (Pmode, ep->to_rtx, offset);
-	      
-	      /* First see if this insn remains valid when we make
-		 the change.  If not, keep the INSN_CODE the same
-		 and let the constraint pass fit it up.  */
-	      validate_change (insn, &SET_SRC (old_set), src, 1);
-	      validate_change (insn, &SET_DEST (old_set),
-			       ep->from_rtx, 1);
-	      if (! apply_change_group ())
-		{
-		  SET_SRC (old_set) = src;
-		  SET_DEST (old_set) = ep->from_rtx;
-		}
-	      lra_update_insn_recog_data (insn);
-	      /* Add offset note for future updates.  */
-	      add_reg_note (insn, REG_EQUAL, src);
-	      return;
-	    }
-
-
-	  /* We can't delete this insn, but needn't process it
-	     since it won't be used unless something changes.  */
-	  delete_p = false;
-	}
+	    if (ep->from == FRAME_POINTER_REGNUM
+		&& ep->to == HARD_FRAME_POINTER_REGNUM)
+	      /* If this is setting the frame pointer register to the
+		 hardware frame pointer register and this is an
+		 elimination that will be done (tested above), this
+		 insn is really adjusting the frame pointer downward
+		 to compensate for the adjustment done before a
+		 nonlocal goto.  */
+	      {
+		rtx src = SET_SRC (old_set);
+		rtx off = remove_reg_equal_offset_note (insn, ep->to_rtx);
+		
+		if (off != NULL_RTX
+		    || src == ep->to_rtx
+		    || (GET_CODE (src) == PLUS
+			&& XEXP (src, 0) == ep->to_rtx
+			&& CONST_INT_P (XEXP (src, 1))))
+		  {
+		    HOST_WIDE_INT offset;
+		    
+		    if (replace_p)
+		      {
+			SET_DEST (old_set) = ep->to_rtx;
+			lra_update_insn_recog_data (insn);
+			return;
+		      }
+		    offset = (off != NULL_RTX ? INTVAL (off)
+			      : src == ep->to_rtx ? 0 : INTVAL (XEXP (src, 1)));
+		    offset -= (ep->offset - ep->previous_offset);
+		    src = plus_constant (Pmode, ep->to_rtx, offset);
+		    
+		    /* First see if this insn remains valid when we
+		       make the change.  If not, keep the INSN_CODE
+		       the same and let the constraint pass fit it
+		       up.  */
+		    validate_change (insn, &SET_SRC (old_set), src, 1);
+		    validate_change (insn, &SET_DEST (old_set),
+				     ep->from_rtx, 1);
+		    if (! apply_change_group ())
+		      {
+			SET_SRC (old_set) = src;
+			SET_DEST (old_set) = ep->from_rtx;
+		      }
+		    lra_update_insn_recog_data (insn);
+		    /* Add offset note for future updates.  */
+		    add_reg_note (insn, REG_EQUAL, src);
+		    return;
+		  }
+	      }
 #endif
-
-      /* This insn isn't serving a useful purpose.  We delete it
-	 when REPLACE is set.  */
-      if (delete_p)
-	lra_delete_dead_insn (insn);
-      return;
+	    
+	    /* This insn isn't serving a useful purpose.  We delete it
+	       when REPLACE is set.  */
+	    if (delete_p)
+	      lra_delete_dead_insn (insn);
+	    return;
+	  }
     }
 
   /* We allow one special case which happens to work on all machines we
@@ -1317,7 +1317,9 @@ lra_eliminate (bool final_p)
 		   "Updating elimination of equiv for reg %d\n", i);
       }
   EXECUTE_IF_SET_IN_BITMAP (&insns_with_changed_offsets, 0, uid, bi)
-    process_insn_for_elimination (lra_insn_recog_data[uid]->insn, final_p);
+    /* A dead insn can be deleted in process_insn_for_elimination.  */
+    if (lra_insn_recog_data[uid] != NULL)
+      process_insn_for_elimination (lra_insn_recog_data[uid]->insn, final_p);
   bitmap_clear (&insns_with_changed_offsets);
 
 lra_eliminate_done:
