Blob Blame History Raw
2005-06-08  Eric Botcazou  <ebotcazou@libertysurf.fr>

	PR debug/21946
	* dwarf2out.c (add_loc_descr_op_piece): Move to the
	DWARF2_DEBUGGING_INFO section.

2005-06-07  Jakub Jelinek  <jakub@redhat.com>

	PR debug/21946
	* dwarf2out.c (add_loc_descr_op_piece): New function.
	(multiple_reg_loc_descriptor, concat_loc_descriptor,
	loc_descriptor): Use it.

	* var-tracking.c: Include regs.h and expr.h.
	(emit_note_insn_var_location): Skip over pieces where offset
	is smaller than previous offset plus previous piece mode size.
	Optimize adjacent hard registers or memory locations.
	* Makefile.in (var-tracking.o): Depend on $(REGS_H) and $(EXPR_H).

--- gcc/dwarf2out.c.jj	2005-06-07 00:39:11.000000000 +0200
+++ gcc/dwarf2out.c	2005-06-07 00:54:10.000000000 +0200
@@ -3747,6 +3748,7 @@ static dw_die_ref subrange_type_die (tre
 static dw_die_ref modified_type_die (tree, int, int, dw_die_ref);
 static int type_is_enum (tree);
 static unsigned int dbx_reg_number (rtx);
+static void add_loc_descr_op_piece (dw_loc_descr_ref *, int);
 static dw_loc_descr_ref reg_loc_descriptor (rtx);
 static dw_loc_descr_ref one_reg_loc_descriptor (unsigned int);
 static dw_loc_descr_ref multiple_reg_loc_descriptor (rtx, rtx);
@@ -8176,6 +8178,26 @@ dbx_reg_number (rtx rtl)
   return DBX_REGISTER_NUMBER (regno);
 }
 
+/* Optionally add a DW_OP_piece term to a location description expression.
+   DW_OP_piece is only added if the location description expression already
+   doesn't end with DW_OP_piece.  */
+
+static void
+add_loc_descr_op_piece (dw_loc_descr_ref *list_head, int size)
+{
+  dw_loc_descr_ref loc;
+
+  if (*list_head != NULL)
+    {
+      /* Find the end of the chain.  */
+      for (loc = *list_head; loc->dw_loc_next != NULL; loc = loc->dw_loc_next)
+	;
+
+      if (loc->dw_loc_opc != DW_OP_piece)
+	loc->dw_loc_next = new_loc_descr (DW_OP_piece, size, 0);
+    }
+}
+
 /* Return a location descriptor that designates a machine register or
    zero if there is none.  */
 
@@ -8235,7 +8257,7 @@ multiple_reg_loc_descriptor (rtx rtl, rt
 
 	  t = one_reg_loc_descriptor (reg);
 	  add_loc_descr (&loc_result, t);
-	  add_loc_descr (&loc_result, new_loc_descr (DW_OP_piece, size, 0));
+	  add_loc_descr_op_piece (&loc_result, size);
 	  ++reg;
 	}
       return loc_result;
@@ -8256,7 +8278,7 @@ multiple_reg_loc_descriptor (rtx rtl, rt
       t = one_reg_loc_descriptor (REGNO (XVECEXP (regs, 0, i)));
       add_loc_descr (&loc_result, t);
       size = GET_MODE_SIZE (GET_MODE (XVECEXP (regs, 0, 0)));
-      add_loc_descr (&loc_result, new_loc_descr (DW_OP_piece, size, 0));
+      add_loc_descr_op_piece (&loc_result, size);
     }
   return loc_result;
 }
@@ -8551,14 +8573,10 @@ concat_loc_descriptor (rtx x0, rtx x1)
     return 0;
 
   cc_loc_result = x0_ref;
-  add_loc_descr (&cc_loc_result,
-		 new_loc_descr (DW_OP_piece,
-				GET_MODE_SIZE (GET_MODE (x0)), 0));
+  add_loc_descr_op_piece (&cc_loc_result, GET_MODE_SIZE (GET_MODE (x0)));
 
   add_loc_descr (&cc_loc_result, x1_ref);
-  add_loc_descr (&cc_loc_result,
-		 new_loc_descr (DW_OP_piece,
-				GET_MODE_SIZE (GET_MODE (x1)), 0));
+  add_loc_descr_op_piece (&cc_loc_result, GET_MODE_SIZE (GET_MODE (x1)));
 
   return cc_loc_result;
 }
@@ -8619,8 +8637,7 @@ loc_descriptor (rtx rtl, bool can_use_fb
 	  loc_result = loc_descriptor (XEXP (RTVEC_ELT (par_elems, 0), 0),
 				       can_use_fbreg);
 	  mode = GET_MODE (XEXP (RTVEC_ELT (par_elems, 0), 0));
-	  add_loc_descr (&loc_result,
-			 new_loc_descr (DW_OP_piece, GET_MODE_SIZE (mode), 0));
+	  add_loc_descr_op_piece (&loc_result, GET_MODE_SIZE (mode));
 	  for (i = 1; i < num_elem; i++)
 	    {
 	      dw_loc_descr_ref temp;
@@ -8629,9 +8646,7 @@ loc_descriptor (rtx rtl, bool can_use_fb
 				     can_use_fbreg);
 	      add_loc_descr (&loc_result, temp);
 	      mode = GET_MODE (XEXP (RTVEC_ELT (par_elems, i), 0));
-	      add_loc_descr (&loc_result,
-			     new_loc_descr (DW_OP_piece,
-					    GET_MODE_SIZE (mode), 0));
+	      add_loc_descr_op_piece (&loc_result, GET_MODE_SIZE (mode));
 	    }
 	}
       break;
@@ -9930,8 +9945,7 @@ add_location_or_const_value_attribute (d
 	/* Create the first one, so we have something to add to.  */
 	descr = loc_descriptor (XEXP (RTVEC_ELT (par_elems, 0), 0), true);
 	mode = GET_MODE (XEXP (RTVEC_ELT (par_elems, 0), 0));
-	add_loc_descr (&descr,
-		       new_loc_descr (DW_OP_piece, GET_MODE_SIZE (mode), 0));
+	add_loc_descr_op_piece (&descr, GET_MODE_SIZE (mode));
 	for (i = 1; i < num_elem; i++)
 	  {
 	    dw_loc_descr_ref temp;
@@ -9939,9 +9953,7 @@ add_location_or_const_value_attribute (d
 	    temp = loc_descriptor (XEXP (RTVEC_ELT (par_elems, i), 0), true);
 	    add_loc_descr (&descr, temp);
 	    mode = GET_MODE (XEXP (RTVEC_ELT (par_elems, i), 0));
-	    add_loc_descr (&descr,
-			   new_loc_descr (DW_OP_piece,
-					  GET_MODE_SIZE (mode), 0));
+	    add_loc_descr_op_piece (&descr, GET_MODE_SIZE (mode));
 	  }
       }
       add_AT_location_description (die, DW_AT_location, descr);
--- gcc/var-tracking.c.jj	2005-06-07 00:39:11.000000000 +0200
+++ gcc/var-tracking.c	2005-06-07 00:52:15.000000000 +0200
@@ -102,6 +102,8 @@
 #include "alloc-pool.h"
 #include "fibheap.h"
 #include "hashtab.h"
+#include "regs.h"
+#include "expr.h"
 
 /* Type of micro operation.  */
 enum micro_operation_type
@@ -2185,10 +2187,12 @@ emit_note_insn_var_location (void **varp
   rtx insn = ((emit_note_data *)data)->insn;
   enum emit_note_where where = ((emit_note_data *)data)->where;
   rtx note;
-  int i;
+  int i, j, n_var_parts;
   bool complete;
   HOST_WIDE_INT last_limit;
   tree type_size_unit;
+  HOST_WIDE_INT offsets[MAX_VAR_PARTS];
+  rtx loc[MAX_VAR_PARTS];
 
 #ifdef ENABLE_CHECKING
   if (!var->decl)
@@ -2197,16 +2201,90 @@ emit_note_insn_var_location (void **varp
 
   complete = true;
   last_limit = 0;
+  n_var_parts = 0;
   for (i = 0; i < var->n_var_parts; i++)
     {
+      enum machine_mode mode, wider_mode;
+
       if (last_limit < var->var_part[i].offset)
 	{
 	  complete = false;
 	  break;
 	}
-      last_limit
-	= (var->var_part[i].offset
-	   + GET_MODE_SIZE (GET_MODE (var->var_part[i].loc_chain->loc)));
+      else if (last_limit > var->var_part[i].offset)
+	continue;
+      offsets[n_var_parts] = var->var_part[i].offset;
+      loc[n_var_parts] = var->var_part[i].loc_chain->loc;
+      mode = GET_MODE (loc[n_var_parts]);
+      last_limit = offsets[n_var_parts] + GET_MODE_SIZE (mode);
+
+      /* Attempt to merge adjacent registers or memory.  */
+      wider_mode = GET_MODE_WIDER_MODE (mode);
+      for (j = i + 1; j < var->n_var_parts; j++)
+	if (last_limit <= var->var_part[j].offset)
+	  break;
+      if (j < var->n_var_parts
+	  && wider_mode != VOIDmode
+	  && GET_CODE (loc[n_var_parts])
+	     == GET_CODE (var->var_part[j].loc_chain->loc)
+	  && mode == GET_MODE (var->var_part[j].loc_chain->loc)
+	  && last_limit == var->var_part[j].offset)
+	{
+	  rtx new_loc = NULL;
+	  rtx loc2 = var->var_part[j].loc_chain->loc;
+
+	  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)
+	      && REGNO (loc[n_var_parts])
+		 + HARD_REGNO_NREGS (REGNO (loc[n_var_parts]), mode)
+		 == REGNO (loc2))
+	    {
+	      if (! WORDS_BIG_ENDIAN && ! BYTES_BIG_ENDIAN)
+		new_loc = simplify_subreg (wider_mode, loc[n_var_parts],
+					   mode, 0);
+	      else if (WORDS_BIG_ENDIAN && BYTES_BIG_ENDIAN)
+		new_loc = simplify_subreg (wider_mode, loc2, mode, 0);
+	      if (new_loc)
+		{
+		  if (!REG_P (new_loc)
+		      || REGNO (new_loc) != REGNO (loc[n_var_parts]))
+		    new_loc = NULL;
+		  else
+		    REG_ATTRS (new_loc) = REG_ATTRS (loc[n_var_parts]);
+		}
+	    }
+	  else if (GET_CODE (loc[n_var_parts]) == MEM
+		   && GET_CODE (XEXP (loc2, 0)) == PLUS
+		   && GET_CODE (XEXP (XEXP (loc2, 0), 0)) == REG
+		   && GET_CODE (XEXP (XEXP (loc2, 0), 1)) == CONST_INT)
+	    {
+	      if ((GET_CODE (XEXP (loc[n_var_parts], 0)) == REG
+		   && rtx_equal_p (XEXP (loc[n_var_parts], 0),
+				   XEXP (XEXP (loc2, 0), 0))
+		   && INTVAL (XEXP (XEXP (loc2, 0), 1))
+		      == GET_MODE_SIZE (mode))
+		  || (GET_CODE (XEXP (loc[n_var_parts], 0)) == PLUS
+		      && GET_CODE (XEXP (XEXP (loc[n_var_parts], 0), 1))
+			 == CONST_INT
+		      && rtx_equal_p (XEXP (XEXP (loc[n_var_parts], 0), 0),
+				      XEXP (XEXP (loc2, 0), 0))
+		      && INTVAL (XEXP (XEXP (loc[n_var_parts], 0), 1))
+			 + GET_MODE_SIZE (mode)
+			 == INTVAL (XEXP (XEXP (loc2, 0), 1))))
+		new_loc = adjust_address_nv (loc[n_var_parts],
+					     wider_mode, 0);
+	    }
+
+	  if (new_loc)
+	    {
+	      loc[n_var_parts] = new_loc;
+	      mode = wider_mode;
+	      last_limit = offsets[n_var_parts] + GET_MODE_SIZE (mode);
+	      i = j;
+	    }
+	}
+      ++n_var_parts;
     }
   type_size_unit = TYPE_SIZE_UNIT (TREE_TYPE (var->decl));
   if ((unsigned HOST_WIDE_INT) last_limit < TREE_INT_CST_LOW (type_size_unit))
@@ -2222,26 +2300,24 @@ emit_note_insn_var_location (void **varp
       NOTE_VAR_LOCATION (note) = gen_rtx_VAR_LOCATION (VOIDmode, var->decl,
 						       NULL_RTX);
     }
-  else if (var->n_var_parts == 1)
+  else if (n_var_parts == 1)
     {
       rtx expr_list
-	= gen_rtx_EXPR_LIST (VOIDmode,
-			     var->var_part[0].loc_chain->loc,
-			     GEN_INT (var->var_part[0].offset));
+	= gen_rtx_EXPR_LIST (VOIDmode, loc[0], GEN_INT (offsets[0]));
 
       NOTE_VAR_LOCATION (note) = gen_rtx_VAR_LOCATION (VOIDmode, var->decl,
 						       expr_list);
     }
-  else if (var->n_var_parts)
+  else if (n_var_parts)
     {
-      rtx argp[MAX_VAR_PARTS];
       rtx parallel;
 
-      for (i = 0; i < var->n_var_parts; i++)
-	argp[i] = gen_rtx_EXPR_LIST (VOIDmode, var->var_part[i].loc_chain->loc,
-				     GEN_INT (var->var_part[i].offset));
+      for (i = 0; i < n_var_parts; i++)
+	loc[i]
+	  = gen_rtx_EXPR_LIST (VOIDmode, loc[i], GEN_INT (offsets[i]));
+
       parallel = gen_rtx_PARALLEL (VOIDmode,
-				   gen_rtvec_v (var->n_var_parts, argp));
+				   gen_rtvec_v (n_var_parts, loc));
       NOTE_VAR_LOCATION (note) = gen_rtx_VAR_LOCATION (VOIDmode, var->decl,
 						       parallel);
     }
--- gcc/Makefile.in.jj	2005-06-07 00:39:11.000000000 +0200
+++ gcc/Makefile.in	2005-06-07 00:55:12.000000000 +0200
@@ -1693,7 +1693,8 @@ df.o : df.c $(CONFIG_H) $(SYSTEM_H) core
    $(BASIC_BLOCK_H) df.h $(FIBHEAP_H)
 var-tracking.o : var-tracking.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \
    $(RTL_H) $(TREE_H) hard-reg-set.h insn-config.h reload.h flags.h \
-   $(BASIC_BLOCK_H) output.h sbitmap.h alloc-pool.h $(FIBHEAP_H) $(HASHTAB_H)
+   $(BASIC_BLOCK_H) output.h sbitmap.h alloc-pool.h $(FIBHEAP_H) $(HASHTAB_H) \
+   $(REGS_H) $(EXPR_H)
 conflict.o : conflict.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(OBSTACK_H) \
    $(HASHTAB_H) $(RTL_H) hard-reg-set.h $(BASIC_BLOCK_H)
 profile.o : profile.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_H) \