diff mbox

[lra] a patch to fix a ppc testsuite regression

Message ID 4FF4AC28.7030705@redhat.com
State New
Headers show

Commit Message

Vladimir Makarov July 4, 2012, 8:48 p.m. UTC
The following patch fixes one testsuite regression on ppc64.  LRA 
removed two insns setting asm reg variable assigned to eliminable hard 
regnos.  It should be not done.

The patch was successfully bootstrapped on x86-64, ppc64, ia64.

Committed as rev. 189264.


2012-07-04  Vladimir Makarov <vmakarov@redhat.com>

         * lra-eliminations.c (get_elimination): Change prototype.
         (lra_eliminate_regs_1, eliminate_regs_in_insn): Transfer reg
         instead of regno to get_elimination.
         (lra_eliminate_reg_if_possible): Ditto.
diff mbox

Patch

Index: lra-eliminations.c
===================================================================
--- lra-eliminations.c	(revision 189236)
+++ lra-eliminations.c	(working copy)
@@ -225,18 +225,22 @@  lra_get_elimation_hard_regno (int hard_r
   return ep->to;
 }
 
-/* Return elimination which will be used for HARD_REGNO, NULL otherwise.  */
+/* Return elimination which will be used for hard reg REG, NULL
+   otherwise.  */
 static struct elim_table *
-get_elimination (int hard_regno)
+get_elimination (rtx reg)
 {
+  int hard_regno;
   struct elim_table *ep;
   HOST_WIDE_INT offset;
 
-  if (hard_regno < 0 || hard_regno >= FIRST_PSEUDO_REGISTER)
+  lra_assert (REG_P (reg));
+  if ((hard_regno = REGNO (reg)) < 0 || hard_regno >= FIRST_PSEUDO_REGISTER)
+    return NULL;
+  if ((ep = elimination_map[hard_regno]) != NULL)
+    return ep->from_rtx != reg ? NULL : ep;
+  if ((offset = self_elim_offsets[hard_regno]) == 0)
     return NULL;
-  if ((ep = elimination_map[hard_regno]) != NULL
-      || (offset = self_elim_offsets[hard_regno]) == 0)
-    return ep;
   /* This is an iteration to restore offsets just after HARD_REGNO
      stopped to be eliminable.  */
   self_elim_table.from = self_elim_table.to = hard_regno;
@@ -268,7 +272,6 @@  lra_eliminate_regs_1 (rtx x, enum machin
 {
   enum rtx_code code = GET_CODE (x);
   struct elim_table *ep;
-  int regno;
   rtx new_rtx;
   int i, j;
   const char *fmt;
@@ -295,24 +298,18 @@  lra_eliminate_regs_1 (rtx x, enum machin
       return x;
 
     case REG:
-      regno = REGNO (x);
-
       /* First handle the case where we encounter a bare register that
 	 is eliminable.  Replace it with a PLUS.  */
-      if (regno < FIRST_PSEUDO_REGISTER)
+      if ((ep = get_elimination (x)) != NULL)
 	{
-	  if ((ep = get_elimination (regno)) != NULL)
-	    {
-	      rtx to = subst_p ? ep->to_rtx : ep->from_rtx;
-
-	      if (update_p)
-		return plus_constant (Pmode, to,
-				      ep->offset - ep->previous_offset);
-	      else if (full_p)
-		return plus_constant (Pmode, to, ep->offset);
-	      else
-		return to;
-	    }
+	  rtx to = subst_p ? ep->to_rtx : ep->from_rtx;
+	  
+	  if (update_p)
+	    return plus_constant (Pmode, to, ep->offset - ep->previous_offset);
+	  else if (full_p)
+	    return plus_constant (Pmode, to, ep->offset);
+	  else
+	    return to;
 	}
       return x;
 
@@ -333,11 +330,9 @@  lra_eliminate_regs_1 (rtx x, enum machin
     case PLUS:
       /* If this is the sum of an eliminable register and a constant, rework
 	 the sum.  */
-      if (REG_P (XEXP (x, 0))
-	  && (regno = REGNO (XEXP (x, 0))) < FIRST_PSEUDO_REGISTER
-	  && CONSTANT_P (XEXP (x, 1)))
+      if (REG_P (XEXP (x, 0)) && CONSTANT_P (XEXP (x, 1)))
 	{
-	  if ((ep = get_elimination (regno)) != NULL)
+	  if ((ep = get_elimination (XEXP (x, 0))) != NULL)
 	    {
 	      HOST_WIDE_INT offset;
 	      rtx to = subst_p ? ep->to_rtx : ep->from_rtx;
@@ -407,27 +402,25 @@  lra_eliminate_regs_1 (rtx x, enum machin
 	 so that we have (plus (mult ..) ..).  This is needed in order
 	 to keep load-address insns valid.   This case is pathological.
 	 We ignore the possibility of overflow here.  */
-      if (REG_P (XEXP (x, 0))
-	  && (regno = REGNO (XEXP (x, 0))) < FIRST_PSEUDO_REGISTER
-	  && CONST_INT_P (XEXP (x, 1)))
-	  if ((ep = get_elimination (regno)) != NULL)
-	    {
-	      rtx to = subst_p ? ep->to_rtx : ep->from_rtx;
-	      
-	      if (update_p)
-		return
-		  plus_constant (Pmode,
-				 gen_rtx_MULT (Pmode, to, XEXP (x, 1)),
-				 (ep->offset - ep->previous_offset)
-				 * INTVAL (XEXP (x, 1)));
-	      else if (full_p)
-		return
-		  plus_constant (Pmode,
-				 gen_rtx_MULT (Pmode, to, XEXP (x, 1)),
-				 ep->offset * INTVAL (XEXP (x, 1)));
-	      else
-		return gen_rtx_MULT (Pmode, to, XEXP (x, 1));
-	    }
+      if (REG_P (XEXP (x, 0)) && CONST_INT_P (XEXP (x, 1))
+	  && (ep = get_elimination (XEXP (x, 0))) != NULL)
+	{
+	  rtx to = subst_p ? ep->to_rtx : ep->from_rtx;
+	  
+	  if (update_p)
+	    return
+	      plus_constant (Pmode,
+			     gen_rtx_MULT (Pmode, to, XEXP (x, 1)),
+			     (ep->offset - ep->previous_offset)
+			     * INTVAL (XEXP (x, 1)));
+	  else if (full_p)
+	    return
+	      plus_constant (Pmode,
+			     gen_rtx_MULT (Pmode, to, XEXP (x, 1)),
+			     ep->offset * INTVAL (XEXP (x, 1)));
+	  else
+	    return gen_rtx_MULT (Pmode, to, XEXP (x, 1));
+	}
       
       /* ... fall through ...  */
 
@@ -769,7 +762,7 @@  eliminate_regs_in_insn (rtx insn, bool r
   int icode = recog_memoized (insn);
   rtx old_set = single_set (insn);
   bool val;
-  int i, regno;
+  int i;
   rtx substed_operand[MAX_RECOG_OPERANDS];
   rtx orig_operand[MAX_RECOG_OPERANDS];
   struct elim_table *ep;
@@ -787,93 +780,88 @@  eliminate_regs_in_insn (rtx insn, bool r
       return;
     }
 
+  /* Check for setting an eliminable register.  */
   if (old_set != 0 && REG_P (SET_DEST (old_set))
-      && (regno = REGNO (SET_DEST (old_set))) < FIRST_PSEUDO_REGISTER)
+      && (ep = get_elimination (SET_DEST (old_set))) != NULL)
     {
-      /* Check for setting an eliminable register.  */
-      if ((ep = get_elimination (regno)) != NULL)
-	{
-	  bool delete_p = replace_p;
-
+      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)
+      /* 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)
+	{
+	  if (replace_p)
 	    {
-	      if (replace_p)
-		{
-		  SET_DEST (old_set) = ep->to_rtx;
-		  lra_update_insn_recog_data (insn);
-		  return;
-		}
-	      else
+	      SET_DEST (old_set) = ep->to_rtx;
+	      lra_update_insn_recog_data (insn);
+	      return;
+	    }
+	  else
+	    {
+	      rtx base = SET_SRC (old_set);
+	      HOST_WIDE_INT offset = 0;
+	      rtx base_insn = insn;
+	      
+	      while (base != ep->to_rtx)
 		{
-		  rtx base = SET_SRC (old_set);
-		  HOST_WIDE_INT offset = 0;
-		  rtx base_insn = insn;
-
-		  while (base != ep->to_rtx)
+		  rtx prev_insn, prev_set;
+		  
+		  if (GET_CODE (base) == PLUS && CONST_INT_P (XEXP (base, 1)))
 		    {
-		      rtx prev_insn, prev_set;
-		      
-		      if (GET_CODE (base) == PLUS
-			  && CONST_INT_P (XEXP (base, 1)))
-			{
-			  offset += INTVAL (XEXP (base, 1));
-			  base = XEXP (base, 0);
-			}
-		      else if ((prev_insn = prev_nonnote_insn (base_insn)) != 0
-			       && (prev_set = single_set (prev_insn)) != 0
-			       && rtx_equal_p (SET_DEST (prev_set), base))
-			{
-			  base = SET_SRC (prev_set);
-			  base_insn = prev_insn;
-			}
-		      else
-			break;
+		      offset += INTVAL (XEXP (base, 1));
+		      base = XEXP (base, 0);
 		    }
-
-		  if (base == ep->to_rtx)
+		  else if ((prev_insn = prev_nonnote_insn (base_insn)) != 0
+			   && (prev_set = single_set (prev_insn)) != 0
+			   && rtx_equal_p (SET_DEST (prev_set), base))
 		    {
-		      rtx src;
-		      
-		      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 reload 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);
-		      return;
+		      base = SET_SRC (prev_set);
+		      base_insn = prev_insn;
 		    }
+		  else
+		    break;
+		}
+	      
+	      if (base == ep->to_rtx)
+		{
+		  rtx src;
+		  
+		  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 reload 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);
+		  return;
 		}
-
-	     
-	      /* We can't delete this insn, but needn't process it
-		 since it won't be used unless something changes. */
-	      delete_p = false;
 	    }
-#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;
+	  
+	  /* We can't delete this insn, but needn't process it
+	     since it won't be used unless something changes. */
+	  delete_p = false;
 	}
+#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;
     }
 
   /* We allow one special case which happens to work on all machines we
@@ -909,8 +897,7 @@  eliminate_regs_in_insn (rtx insn, bool r
       if (GET_CODE (reg) == SUBREG)
 	reg = SUBREG_REG (reg);
 
-      if (REG_P (reg) && (regno = REGNO (reg)) < FIRST_PSEUDO_REGISTER
-	  && (ep = get_elimination (regno)) != NULL)
+      if (REG_P (reg) && (ep = get_elimination (reg)) != NULL)
 	{
 	  rtx to_rtx = replace_p ? ep->to_rtx : ep->from_rtx;
 	  
@@ -1234,7 +1221,7 @@  lra_eliminate_reg_if_possible (rtx *loc)
       /* Virtual registers are not allocatable. ??? */
       || ! TEST_HARD_REG_BIT (lra_no_alloc_regs, regno))
     return;
-  if ((ep = get_elimination (regno)) != NULL)
+  if ((ep = get_elimination (*loc)) != NULL)
     *loc = ep->to_rtx;
 }