var-tracking wrt. leaf regs on sparc

David Miller davem@davemloft.net
Wed Feb 6 03:53:00 GMT 2013


From: David Miller <davem@davemloft.net>
Date: Tue, 05 Feb 2013 18:18:39 -0500 (EST)

> The only other alternative I can see would be to get everything in
> var-tracking.c and the other subsystems it uses to do leaf register
> remapping, but that seems completely like the wrong way to handle
> this.

Following up to myself... :-)

Now that I understand fully what we're trying to accomplish with the
DT_OP_GNU_entry_value and DT_OP_GNU_call_site_parameter extensions, it
does in fact seem like we will need to do leaf register remapping in
var-tracking.c

Here below is a patch I'm playing with.  It's a rough draft but it
definitely fixes the pr54200.c problem completely.

Another way to do this would be to not translate the incoming
parameter registers (leave them at %i*) if we don't see the window
save.  That way we only have to play the regno remapping game for
these specific incoming argument pieces, rather than for everything we
look at in the RTL stream.

diff --git a/gcc/var-tracking.c b/gcc/var-tracking.c
index 714acb69..14635b9 100644
--- a/gcc/var-tracking.c
+++ b/gcc/var-tracking.c
@@ -1057,6 +1057,32 @@ adjust_mem_stores (rtx loc, const_rtx expr, void *data)
     }
 }
 
+/* Given a regno from the RTL instruction stream, return the
+   actual register number that will be used by final and debug
+   info emission.  */
+static unsigned int
+real_regno (unsigned int regno)
+{
+#ifdef LEAF_REG_REMAP
+  if (regno < FIRST_PSEUDO_REGISTER
+      && crtl->uses_only_leaf_regs)
+    {
+      int remapped = LEAF_REG_REMAP (regno);
+
+      if (remapped >= 0)
+	regno = (unsigned int) remapped;
+    }
+#endif
+
+  return regno;
+}
+
+static unsigned int
+real_regno_rtx (rtx reg)
+{
+  return real_regno (REGNO (reg));
+}
+
 /* Simplify INSN.  Remove all {PRE,POST}_{INC,DEC,MODIFY} rtxes,
    replace them with their value in the insn and add the side-effects
    as other sets to the insn.  */
@@ -1804,12 +1830,12 @@ var_reg_decl_set (dataflow_set *set, rtx loc, enum var_init_status initialized,
   if (decl_p)
     dv = dv_from_decl (var_debug_decl (dv_as_decl (dv)));
 
-  for (node = set->regs[REGNO (loc)]; node; node = node->next)
+  for (node = set->regs[real_regno_rtx (loc)]; node; node = node->next)
     if (dv_as_opaque (node->dv) == dv_as_opaque (dv)
 	&& node->offset == offset)
       break;
   if (!node)
-    attrs_list_insert (&set->regs[REGNO (loc)], dv, offset, loc);
+    attrs_list_insert (&set->regs[real_regno_rtx (loc)], dv, offset, loc);
   set_variable_part (set, loc, dv, offset, initialized, set_src, iopt);
 }
 
@@ -1875,7 +1901,7 @@ var_reg_delete_and_set (dataflow_set *set, rtx loc, bool modify,
   if (initialized == VAR_INIT_STATUS_UNKNOWN)
     initialized = get_init_value (set, loc, dv_from_decl (decl));
 
-  nextp = &set->regs[REGNO (loc)];
+  nextp = &set->regs[real_regno_rtx (loc)];
   for (node = *nextp; node; node = next)
     {
       next = node->next;
@@ -1904,7 +1930,7 @@ var_reg_delete_and_set (dataflow_set *set, rtx loc, bool modify,
 static void
 var_reg_delete (dataflow_set *set, rtx loc, bool clobber)
 {
-  attrs *nextp = &set->regs[REGNO (loc)];
+  attrs *nextp = &set->regs[real_regno_rtx (loc)];
   attrs node, next;
 
   if (clobber)
@@ -2386,7 +2412,7 @@ val_bind (dataflow_set *set, rtx val, rtx loc, bool modified)
   if (REG_P (loc))
     {
       if (modified)
-	var_regno_delete (set, REGNO (loc));
+	var_regno_delete (set, real_regno_rtx (loc));
       var_reg_decl_set (set, loc, VAR_INIT_STATUS_INITIALIZED,
 			dv_from_value (val), 0, NULL_RTX, INSERT);
     }
@@ -2584,7 +2610,7 @@ val_resolve (dataflow_set *set, rtx val, rtx loc, rtx insn)
     {
       attrs node, found = NULL;
 
-      for (node = set->regs[REGNO (loc)]; node; node = node->next)
+      for (node = set->regs[real_regno_rtx (loc)]; node; node = node->next)
 	if (dv_is_value_p (node->dv)
 	    && GET_MODE (dv_as_value (node->dv)) == GET_MODE (loc))
 	  {
@@ -2838,7 +2864,8 @@ variable_union (variable src, dataflow_set *set)
 		{
 		  if (!((REG_P (node2->loc)
 			 && REG_P (node->loc)
-			 && REGNO (node2->loc) == REGNO (node->loc))
+			 && (real_regno_rtx (node2->loc)
+			     == real_regno_rtx (node->loc)))
 			|| rtx_equal_p (node2->loc, node->loc)))
 		    {
 		      if (node2->init < node->init)
@@ -2871,7 +2898,8 @@ variable_union (variable src, dataflow_set *set)
 	      for (node = src->var_part[i].loc_chain; node; node = node->next)
 		if (!((REG_P (dstnode->loc)
 		       && REG_P (node->loc)
-		       && REGNO (dstnode->loc) == REGNO (node->loc))
+		       && (real_regno_rtx (dstnode->loc)
+			   == real_regno_rtx (node->loc)))
 		      || rtx_equal_p (dstnode->loc, node->loc)))
 		  {
 		    location_chain new_node;
@@ -2920,7 +2948,8 @@ variable_union (variable src, dataflow_set *set)
 		    {
 		      if ((REG_P (vui[jj].lc->loc)
 			   && REG_P (node->loc)
-			   && REGNO (vui[jj].lc->loc) == REGNO (node->loc))
+			   && (real_regno_rtx (vui[jj].lc->loc)
+			       == real_regno_rtx (node->loc)))
 			  || rtx_equal_p (vui[jj].lc->loc, node->loc))
 			{
 			  vui[jj].pos = jj + ii;
@@ -3372,9 +3401,9 @@ loc_cmp (rtx x, rtx y)
       if (!REG_P (y))
 	return -1;
       gcc_assert (GET_MODE (x) == GET_MODE (y));
-      if (REGNO (x) == REGNO (y))
+      if (real_regno_rtx (x) == real_regno_rtx (y))
 	return 0;
-      else if (REGNO (x) < REGNO (y))
+      else if (real_regno_rtx (x) < real_regno_rtx (y))
 	return -1;
       else
 	return 1;
@@ -3720,7 +3749,7 @@ canonicalize_values_star (void **slot, void *data)
 	  }
 	else if (GET_CODE (node->loc) == REG)
 	  {
-	    attrs list = set->regs[REGNO (node->loc)], *listp;
+	    attrs list = set->regs[real_regno_rtx (node->loc)], *listp;
 
 	    /* Change an existing attribute referring to dv so that it
 	       refers to cdv, removing any duplicate this might
@@ -3982,13 +4011,14 @@ variable_merge_over_cur (variable s1var, struct dfset_merge *dsm)
 	{
 	  attrs list;
 
-	  for (list = dst->regs[REGNO (node->loc)]; list; list = list->next)
+	  for (list = dst->regs[real_regno_rtx (node->loc)]; list;
+	       list = list->next)
 	    if (GET_MODE (node->loc) == GET_MODE (list->loc)
 		&& dv_is_value_p (list->dv))
 	      break;
 
 	  if (!list)
-	    attrs_list_insert (&dst->regs[REGNO (node->loc)],
+	    attrs_list_insert (&dst->regs[real_regno_rtx (node->loc)],
 			       dv, 0, node->loc);
 	  /* If this value became canonical for another value that had
 	     this register, we want to leave it alone.  */
@@ -4364,7 +4394,7 @@ variable_post_merge_new_vals (void **slot, void *info)
 		  goto restart;
 		}
 
-	      for (attp = &set->regs[REGNO (node->loc)]; (att = *attp);
+	      for (attp = &set->regs[real_regno_rtx (node->loc)]; (att = *attp);
 		   attp = &att->next)
 		if (att->offset == 0
 		    && GET_MODE (att->loc) == GET_MODE (node->loc))
@@ -4404,7 +4434,7 @@ variable_post_merge_new_vals (void **slot, void *info)
 		      dataflow_set_init (*dfpm->permp);
 		    }
 
-		  for (att = (*dfpm->permp)->regs[REGNO (node->loc)];
+		  for (att = (*dfpm->permp)->regs[real_regno_rtx (node->loc)];
 		       att; att = att->next)
 		    if (GET_MODE (att->loc) == GET_MODE (node->loc))
 		      {
@@ -4437,7 +4467,7 @@ variable_post_merge_new_vals (void **slot, void *info)
 		      if (dump_file)
 			fprintf (dump_file,
 				 "Created new value %u:%u for reg %i\n",
-				 v->uid, v->hash, REGNO (node->loc));
+				 v->uid, v->hash, real_regno_rtx (node->loc));
 		    }
 
 		  var_reg_decl_set (*dfpm->permp, node->loc,
@@ -4500,7 +4530,7 @@ variable_post_merge_perm_vals (void **pslot, void *info)
       val_reset (set, dv);
     }
 
-  for (att = set->regs[REGNO (pnode->loc)]; att; att = att->next)
+  for (att = set->regs[real_regno_rtx (pnode->loc)]; att; att = att->next)
     if (att->offset == 0
 	&& GET_MODE (att->loc) == GET_MODE (pnode->loc)
 	&& dv_is_value_p (att->dv))
@@ -4517,7 +4547,7 @@ variable_post_merge_perm_vals (void **pslot, void *info)
     }
   else if (!att)
     {
-      attrs_list_insert (&set->regs[REGNO (pnode->loc)],
+      attrs_list_insert (&set->regs[real_regno_rtx (pnode->loc)],
 			 dv, 0, pnode->loc);
       variable_union (pvar, set);
     }
@@ -4836,7 +4866,7 @@ variable_part_different_p (variable_part *vp1, variable_part *vp2)
 	{
 	  if (REG_P (lc1->loc) && REG_P (lc2->loc))
 	    {
-	      if (REGNO (lc1->loc) == REGNO (lc2->loc))
+	      if (real_regno_rtx (lc1->loc) == real_regno_rtx (lc2->loc))
 		break;
 	    }
 	  if (rtx_equal_p (lc1->loc, lc2->loc))
@@ -5189,7 +5219,7 @@ track_loc_p (rtx loc, tree expr, HOST_WIDE_INT offset, bool store_reg_p,
   if ((GET_MODE_SIZE (mode) > GET_MODE_SIZE (DECL_MODE (expr))
        || (store_reg_p
 	   && !COMPLEX_MODE_P (DECL_MODE (expr))
-	   && hard_regno_nregs[REGNO (loc)][DECL_MODE (expr)] == 1))
+	   && hard_regno_nregs[real_regno_rtx (loc)][DECL_MODE (expr)] == 1))
       && offset + byte_lowpart_offset (DECL_MODE (expr), mode) == 0)
     {
       mode = DECL_MODE (expr);
@@ -5227,8 +5257,9 @@ var_lowpart (enum machine_mode mode, rtx loc)
     return adjust_address_nv (loc, mode, offset);
 
   reg_offset = subreg_lowpart_offset (mode, GET_MODE (loc));
-  regno = REGNO (loc) + subreg_regno_offset (REGNO (loc), GET_MODE (loc),
-					     reg_offset, mode);
+  regno = real_regno_rtx (loc) + subreg_regno_offset (real_regno_rtx (loc),
+						      GET_MODE (loc),
+						      reg_offset, mode);
   return gen_rtx_REG_offset (loc, mode, regno, offset);
 }
 
@@ -6231,7 +6262,7 @@ prepare_call_arguments (basic_block bb, rtx insn)
 		&& GET_MODE (reg) == mode
 		&& GET_MODE_CLASS (mode) == MODE_INT
 		&& REG_P (x)
-		&& REGNO (x) == REGNO (reg)
+		&& real_regno_rtx (x) == real_regno_rtx (reg)
 		&& GET_MODE (x) == mode
 		&& item)
 	      {
@@ -6747,7 +6778,7 @@ compute_bb_dataflow (basic_block bb)
 		    }
 		}
 	      else if (REG_P (uloc))
-		var_regno_delete (out, REGNO (uloc));
+		var_regno_delete (out, real_regno_rtx (uloc));
 	      else if (MEM_P (uloc))
 		{
 		  gcc_checking_assert (GET_CODE (vloc) == MEM);
@@ -7504,11 +7535,11 @@ set_slot_part (dataflow_set *set, rtx loc, void **slot,
 	       nextp = &node->next)
 	    if (REG_P (node->loc))
 	      {
-		if (REGNO (node->loc) < REGNO (loc))
+		if (real_regno_rtx (node->loc) < real_regno_rtx (loc))
 		  c++;
 		else
 		  {
-		    if (REGNO (node->loc) == REGNO (loc))
+		    if (real_regno_rtx (node->loc) == real_regno_rtx (loc))
 		      r = 0;
 		    else
 		      r = 1;
@@ -7575,7 +7606,7 @@ set_slot_part (dataflow_set *set, rtx loc, void **slot,
 
 	  if (node
 	      && ((REG_P (node->loc) && REG_P (loc)
-		   && REGNO (node->loc) == REGNO (loc))
+		   && real_regno_rtx (node->loc) == real_regno_rtx (loc))
 		  || rtx_equal_p (node->loc, loc)))
 	    {
 	      /* LOC is in the beginning of the chain so we have nothing
@@ -7631,7 +7662,7 @@ set_slot_part (dataflow_set *set, rtx loc, void **slot,
 	{
 	  next = node->next;
 	  if ((REG_P (node->loc) && REG_P (loc)
-	       && REGNO (node->loc) == REGNO (loc))
+	       && real_regno_rtx (node->loc) == real_regno_rtx (loc))
 	      || rtx_equal_p (node->loc, loc))
 	    {
 	      /* Save these values, to assign to the new node, before
@@ -7729,7 +7760,7 @@ clobber_slot_part (dataflow_set *set, rtx loc, void **slot,
 		     list, but preserve any other variable parts
 		     that might be regarded as live in that same
 		     register.  */
-		  anextp = &set->regs[REGNO (node->loc)];
+		  anextp = &set->regs[real_regno_rtx (node->loc)];
 		  for (anode = *anextp; anode; anode = anext)
 		    {
 		      anext = anode->next;
@@ -7800,7 +7831,7 @@ delete_slot_part (dataflow_set *set, rtx loc, void **slot,
 	       node = node->next)
 	    {
 	      if ((REG_P (node->loc) && REG_P (loc)
-		   && REGNO (node->loc) == REGNO (loc))
+		   && real_regno_rtx (node->loc) == real_regno_rtx (loc))
 		  || rtx_equal_p (node->loc, loc))
 		{
 		  slot = unshare_variable (set, slot, var,
@@ -7823,7 +7854,7 @@ delete_slot_part (dataflow_set *set, rtx loc, void **slot,
 	{
 	  next = node->next;
 	  if ((REG_P (node->loc) && REG_P (loc)
-	       && REGNO (node->loc) == REGNO (loc))
+	       && real_regno_rtx (node->loc) == real_regno_rtx (loc))
 	      || rtx_equal_p (node->loc, loc))
 	    {
 	      /* If we have deleted the location which was last emitted
@@ -8596,10 +8627,10 @@ emit_note_insn_var_location (void **varp, void *data)
 	  rtx new_loc = NULL;
 
 	  if (REG_P (loc[n_var_parts])
-	      && hard_regno_nregs[REGNO (loc[n_var_parts])][mode] * 2
-		 == hard_regno_nregs[REGNO (loc[n_var_parts])][wider_mode]
-	      && end_hard_regno (mode, REGNO (loc[n_var_parts]))
-		 == REGNO (loc2))
+	      && hard_regno_nregs[real_regno_rtx (loc[n_var_parts])][mode] * 2
+		 == hard_regno_nregs[real_regno_rtx (loc[n_var_parts])][wider_mode]
+	      && end_hard_regno (mode, real_regno_rtx (loc[n_var_parts]))
+		 == real_regno_rtx (loc2))
 	    {
 	      if (! WORDS_BIG_ENDIAN && ! BYTES_BIG_ENDIAN)
 		new_loc = simplify_subreg (wider_mode, loc[n_var_parts],
@@ -8609,7 +8640,7 @@ emit_note_insn_var_location (void **varp, void *data)
 	      if (new_loc)
 		{
 		  if (!REG_P (new_loc)
-		      || REGNO (new_loc) != REGNO (loc[n_var_parts]))
+		      || real_regno_rtx (new_loc) != real_regno_rtx (loc[n_var_parts]))
 		    new_loc = NULL;
 		  else
 		    REG_ATTRS (new_loc) = REG_ATTRS (loc[n_var_parts]);
@@ -9065,8 +9096,8 @@ emit_notes_in_bb (basic_block bb, dataflow_set *set)
 			   && MEM_P (XEXP (XEXP (XEXP (*p, 1), 0), 0))
 			   && REG_P (XEXP (XEXP (XEXP (XEXP (*p, 1), 0), 0),
 					   0))
-			   && REGNO (XEXP (XEXP (*p, 0), 0))
-			      == REGNO (XEXP (XEXP (XEXP (XEXP (*p, 1), 0),
+			   && real_regno_rtx (XEXP (XEXP (*p, 0), 0))
+			      == real_regno_rtx (XEXP (XEXP (XEXP (XEXP (*p, 1), 0),
 						    0), 0)))
 		    *p = XEXP (XEXP (*p, 1), 1);
 		  /* Just drop this item.  */
@@ -9255,7 +9286,7 @@ emit_notes_in_bb (basic_block bb, dataflow_set *set)
 		    }
 		}
 	      else if (REG_P (uloc))
-		var_regno_delete (set, REGNO (uloc));
+		var_regno_delete (set, real_regno_rtx (uloc));
 	      else if (MEM_P (uloc))
 		{
 		  gcc_checking_assert (GET_CODE (vloc) == MEM);
@@ -9621,7 +9652,7 @@ vt_add_function_parameter (tree parm)
     {
       incoming = var_lowpart (mode, incoming);
       gcc_assert (REGNO (incoming) < FIRST_PSEUDO_REGISTER);
-      attrs_list_insert (&out->regs[REGNO (incoming)], dv, offset,
+      attrs_list_insert (&out->regs[real_regno_rtx (incoming)], dv, offset,
 			 incoming);
       set_variable_part (out, incoming, dv, offset,
 			 VAR_INIT_STATUS_INITIALIZED, NULL, INSERT);
@@ -9795,7 +9826,7 @@ vt_initialize (void)
       val = cselib_lookup_from_insn (reg, GET_MODE (reg), 1,
 				     VOIDmode, get_insns ());
       preserve_value (val);
-      cselib_preserve_cfa_base_value (val, REGNO (reg));
+      cselib_preserve_cfa_base_value (val, real_regno_rtx (reg));
       expr = plus_constant (GET_MODE (stack_pointer_rtx),
 			    stack_pointer_rtx, -ofst);
       cselib_add_permanent_equiv (val, expr, get_insns ());



More information about the Gcc-patches mailing list