This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[PATCH] VEC and tree aliasing


This patch reworks the field offset VEC creation in tree alias handling.

The primary goal is to use a vector of objects, rather than a vector of
pointers.  Whilst there I became somewhat confused by the funky loop
peeling in push_fields_onto_fieldstack.  There's no guarantee that the
first member of a type's DECL_FIELDS list will be a FIELD_DECL, and why
should the first one be handled specially anyway?  AFAICT the only
difference in the handling of the first one, and the handling of the
remainder is the non-addition of 'bitpos_of_field (field)' to the
recursive call (but not the direct push).  That looks like a noop to me,
because the first encountered field would be expected to have an offset
of zero anyway (unless some FE makes funky structures -- in which case
it would be a _bug_).

So, I removed that explicit handling and created a simple loop.

booted & tested on i686-pc-linux-gnu, ok?

nathan

--
Nathan Sidwell    ::   http://www.codesourcery.com   ::     CodeSourcery LLC
nathan@codesourcery.com    ::     http://www.planetfall.pwp.blueyonder.co.uk

2005-04-21  Nathan Sidwell  <nathan@codesourcery.com>

	* tree-ssa-alias.c (fieldoff_t): Remove.
	(fieldoff_s): typedef the structure itself.  Create a vector of
	objects.
	(push_fields_onto_fieldstack): Return count of fields pushed.
	Remove peeling of first field.  Adjust.
	(fieldoff_compare): Adjust.
	(create_overlap_variables_for): Adjust.

Index: tree-ssa-alias.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/tree-ssa-alias.c,v
retrieving revision 2.89
diff -c -3 -p -r2.89 tree-ssa-alias.c
*** tree-ssa-alias.c	21 Apr 2005 18:05:23 -0000	2.89
--- tree-ssa-alias.c	22 Apr 2005 07:48:19 -0000
*************** typedef struct fieldoff
*** 2789,2799 ****
  {
    tree field;
    HOST_WIDE_INT offset;  
! } *fieldoff_t;
  
! DEF_VEC_P (fieldoff_t);  /* FIXME: This can be a vector of struct
! 			    fieldoff objects (nathan 2005/04/15)  */
! DEF_VEC_ALLOC_P(fieldoff_t,heap);
  
  /* Return the position, in bits, of FIELD_DECL from the beginning of its
     structure. 
--- 2789,2798 ----
  {
    tree field;
    HOST_WIDE_INT offset;  
! } fieldoff_s;
  
! DEF_VEC_O (fieldoff_s);
! DEF_VEC_ALLOC_O(fieldoff_s,heap);
  
  /* Return the position, in bits, of FIELD_DECL from the beginning of its
     structure. 
*************** bitpos_of_field (const tree fdecl)
*** 2815,2885 ****
  /* Given a TYPE, and a vector of field offsets FIELDSTACK, push all the fields
     of TYPE onto fieldstack, recording their offsets along the way.
     OFFSET is used to keep track of the offset in this entire structure, rather
!    than just the immediately containing structure.  */
  
! static void
! push_fields_onto_fieldstack (tree type, VEC(fieldoff_t,heap) **fieldstack, 
  			     HOST_WIDE_INT offset)
  {
!   fieldoff_t pair;
!   tree field = TYPE_FIELDS (type);
!   if (!field)
!     return;
!   if (var_can_have_subvars (field)
!       && TREE_CODE (field) == FIELD_DECL)
!     {
!       size_t before = VEC_length (fieldoff_t, *fieldstack);
!       /* Empty structures may have actual size, like in C++. So see if we
! 	 actually end up pushing a field, and if not, if the size is nonzero,
! 	 push the field onto the stack */
!       push_fields_onto_fieldstack (TREE_TYPE (field), fieldstack, offset);
!       if (before == VEC_length (fieldoff_t, *fieldstack)
! 	  && DECL_SIZE (field)
! 	  && !integer_zerop (DECL_SIZE (field)))
! 	{
! 	  pair = xmalloc (sizeof (struct fieldoff));
! 	  pair->field = field;
! 	  pair->offset = offset;
! 	  VEC_safe_push (fieldoff_t, heap, *fieldstack, pair);
! 	}
!     }
!   else if (TREE_CODE (field) == FIELD_DECL)
!     {
!       pair = xmalloc (sizeof (struct fieldoff));
!       pair->field = field;
!       pair->offset = offset + bitpos_of_field (field);
!       VEC_safe_push (fieldoff_t, heap, *fieldstack, pair);
!     }
!   for (field = TREE_CHAIN (field); field; field = TREE_CHAIN (field))
!     {
!       if (TREE_CODE (field) != FIELD_DECL)
! 	continue;
!       if (var_can_have_subvars (field))
! 	{
! 	  size_t before = VEC_length (fieldoff_t, *fieldstack);
! 	  push_fields_onto_fieldstack (TREE_TYPE (field), fieldstack, 
! 				       offset + bitpos_of_field (field));
!       /* Empty structures may have actual size, like in C++. So see if we
! 	 actually end up pushing a field, and if not, if the size is nonzero,
! 	 push the field onto the stack */
! 	  if (before == VEC_length (fieldoff_t, *fieldstack)
! 	      && DECL_SIZE (field)
! 	      && !integer_zerop (DECL_SIZE (field)))
! 	    {
! 	      pair = xmalloc (sizeof (struct fieldoff));
! 	      pair->field = field;
! 	      pair->offset = offset + bitpos_of_field (field);
! 	      VEC_safe_push (fieldoff_t, heap, *fieldstack, pair);
! 	    }
! 	}
!       else
! 	{
! 	  pair = xmalloc (sizeof (struct fieldoff));
! 	  pair->field = field;
! 	  pair->offset = offset + bitpos_of_field (field);
! 	  VEC_safe_push (fieldoff_t, heap, *fieldstack, pair);
! 	}
!     }
  }
  
  
--- 2814,2857 ----
  /* Given a TYPE, and a vector of field offsets FIELDSTACK, push all the fields
     of TYPE onto fieldstack, recording their offsets along the way.
     OFFSET is used to keep track of the offset in this entire structure, rather
!    than just the immediately containing structure.  Returns the number
!    of fields pushed. */
  
! static int
! push_fields_onto_fieldstack (tree type, VEC(fieldoff_s,heap) **fieldstack, 
  			     HOST_WIDE_INT offset)
  {
!   tree field;
!   int count = 0;
!   
!   for (field = TYPE_FIELDS (type); field; field = TREE_CHAIN (field))
!     if (TREE_CODE (field) == FIELD_DECL)
!       {
! 	bool push = false;
!       
! 	if (!var_can_have_subvars (field))
! 	  push = true;
! 	else if (!(push_fields_onto_fieldstack
! 		   (TREE_TYPE (field), fieldstack,
! 		    offset + bitpos_of_field (field)))
! 		 && DECL_SIZE (field)
! 		 && !integer_zerop (DECL_SIZE (field)))
! 	   /* Empty structures may have actual size, like in C++. So
! 	      see if we didn't push any subfields and the size is
! 	      nonzero, push the field onto the stack */
! 	  push = true;
! 	
! 	if (push)
! 	  {
! 	    fieldoff_s *pair;
! 
! 	    pair = VEC_safe_push (fieldoff_s, heap, *fieldstack, NULL);
! 	    pair->field = field;
! 	    pair->offset = offset + bitpos_of_field (field);
! 	    count++;
! 	  }
!       }
!   return count;
  }
  
  
*************** get_or_create_used_part_for (size_t uid)
*** 2922,2943 ****
    return up;
  }
  
! /* qsort comparison function for two fieldoff_t's PA and PB */
  
  static int 
  fieldoff_compare (const void *pa, const void *pb)
  {
!   const fieldoff_t foa = *(fieldoff_t *)pa;
!   const fieldoff_t fob = *(fieldoff_t *)pb;
    HOST_WIDE_INT foasize, fobsize;
    if (foa->offset != fob->offset)
      return foa->offset - fob->offset;
  
    foasize = TREE_INT_CST_LOW (DECL_SIZE (foa->field));
    fobsize = TREE_INT_CST_LOW (DECL_SIZE (fob->field));
!   if (foasize != fobsize)
!     return foasize - fobsize;
!   return 0;
  }
  
  /* Given an aggregate VAR, create the subvariables that represent its
--- 2894,2914 ----
    return up;
  }
  
! /* qsort comparison function for two fieldoff's PA and PB */
  
  static int 
  fieldoff_compare (const void *pa, const void *pb)
  {
!   const fieldoff_s *foa = (const fieldoff_s *)pa;
!   const fieldoff_s *fob = (const fieldoff_s *)pb;
    HOST_WIDE_INT foasize, fobsize;
+   
    if (foa->offset != fob->offset)
      return foa->offset - fob->offset;
  
    foasize = TREE_INT_CST_LOW (DECL_SIZE (foa->field));
    fobsize = TREE_INT_CST_LOW (DECL_SIZE (fob->field));
!   return foasize - fobsize;
  }
  
  /* Given an aggregate VAR, create the subvariables that represent its
*************** fieldoff_compare (const void *pa, const 
*** 2946,2952 ****
  static void
  create_overlap_variables_for (tree var)
  {
!   VEC(fieldoff_t,heap) *fieldstack = NULL;
    used_part_t up;
    size_t uid = var_ann (var)->uid;
  
--- 2917,2923 ----
  static void
  create_overlap_variables_for (tree var)
  {
!   VEC(fieldoff_s,heap) *fieldstack = NULL;
    used_part_t up;
    size_t uid = var_ann (var)->uid;
  
*************** create_overlap_variables_for (tree var)
*** 2955,2964 ****
  
    up = used_portions[uid];
    push_fields_onto_fieldstack (TREE_TYPE (var), &fieldstack, 0);
!   if (VEC_length (fieldoff_t, fieldstack) != 0)
      {
        subvar_t *subvars;
!       fieldoff_t fo;
        bool notokay = false;
        int fieldcount = 0;
        int i;
--- 2926,2935 ----
  
    up = used_portions[uid];
    push_fields_onto_fieldstack (TREE_TYPE (var), &fieldstack, 0);
!   if (VEC_length (fieldoff_s, fieldstack) != 0)
      {
        subvar_t *subvars;
!       fieldoff_s *fo;
        bool notokay = false;
        int fieldcount = 0;
        int i;
*************** create_overlap_variables_for (tree var)
*** 2975,2981 ****
  	 currently don't.  Doing so would require some extra changes to
  	 tree-ssa-operands.c.  */
  
!       for (i = 0; VEC_iterate (fieldoff_t, fieldstack, i, fo); i++)
  	{
  	  if (!DECL_SIZE (fo->field) 
  	      || TREE_CODE (DECL_SIZE (fo->field)) != INTEGER_CST
--- 2946,2952 ----
  	 currently don't.  Doing so would require some extra changes to
  	 tree-ssa-operands.c.  */
  
!       for (i = 0; VEC_iterate (fieldoff_s, fieldstack, i, fo); i++)
  	{
  	  if (!DECL_SIZE (fo->field) 
  	      || TREE_CODE (DECL_SIZE (fo->field)) != INTEGER_CST
*************** create_overlap_variables_for (tree var)
*** 3012,3045 ****
  	  notokay = true;
  	}
        
!     
!       /* Cleanup after ourselves if we can't create overlap variables.  */
        if (notokay)
  	{
! 	  while (VEC_length (fieldoff_t, fieldstack) != 0)
! 	    {
! 	      fo = VEC_pop (fieldoff_t, fieldstack);
! 	      free (fo);
! 	    }
! 	  VEC_free (fieldoff_t, heap, fieldstack);
  	  return;
  	}
        /* Otherwise, create the variables.  */
        subvars = lookup_subvars_for_var (var);
        
!       qsort (VEC_address (fieldoff_t, fieldstack), 
! 	     VEC_length (fieldoff_t, fieldstack), 
! 	     sizeof (fieldoff_t),
  	     fieldoff_compare);
  
!       while (VEC_length (fieldoff_t, fieldstack) != 0)
  	{
  	  subvar_t sv;
  	  HOST_WIDE_INT fosize;
  	  var_ann_t ann;
  	  tree currfotype;
  
- 	  fo = VEC_pop (fieldoff_t, fieldstack);	  
  	  fosize = TREE_INT_CST_LOW (DECL_SIZE (fo->field));
  	  currfotype = TREE_TYPE (fo->field);
  
--- 2983,3011 ----
  	  notokay = true;
  	}
        
!       /* Bail out, if we can't create overlap variables.  */
        if (notokay)
  	{
! 	  VEC_free (fieldoff_s, heap, fieldstack);
  	  return;
  	}
+       
        /* Otherwise, create the variables.  */
        subvars = lookup_subvars_for_var (var);
        
!       qsort (VEC_address (fieldoff_s, fieldstack), 
! 	     VEC_length (fieldoff_s, fieldstack), 
! 	     sizeof (fieldoff_s),
  	     fieldoff_compare);
  
!       for (i = VEC_length (fieldoff_s, fieldstack);
! 	   VEC_iterate (fieldoff_s, fieldstack, --i, fo);)
  	{
  	  subvar_t sv;
  	  HOST_WIDE_INT fosize;
  	  var_ann_t ann;
  	  tree currfotype;
  
  	  fosize = TREE_INT_CST_LOW (DECL_SIZE (fo->field));
  	  currfotype = TREE_TYPE (fo->field);
  
*************** create_overlap_variables_for (tree var)
*** 3053,3062 ****
  	      || (fo->offset == lastfooffset
  		  && fosize == lastfosize
  		  && currfotype == lastfotype))
! 	    {
! 	      free (fo);
! 	      continue;
! 	    }
  	  sv = ggc_alloc (sizeof (struct subvar));
  	  sv->offset = fo->offset;
  	  sv->size = fosize;
--- 3019,3025 ----
  	      || (fo->offset == lastfooffset
  		  && fosize == lastfosize
  		  && currfotype == lastfotype))
! 	    continue;
  	  sv = ggc_alloc (sizeof (struct subvar));
  	  sv->offset = fo->offset;
  	  sv->size = fosize;
*************** create_overlap_variables_for (tree var)
*** 3071,3077 ****
  	      fprintf (dump_file, " size " HOST_WIDE_INT_PRINT_DEC,
  		       sv->size);
  	      fprintf (dump_file, "\n");
- 	      
  	    }
  	  
  	  /* We need to copy the various flags from var to sv->var, so that
--- 3034,3039 ----
*************** create_overlap_variables_for (tree var)
*** 3097,3103 ****
  	  lastfooffset = fo->offset;
  	  lastfosize = fosize;
  	  *subvars = sv;
- 	  free (fo);
  	}
  
        /* Once we have created subvars, the original is no longer call
--- 3059,3064 ----
*************** create_overlap_variables_for (tree var)
*** 3108,3117 ****
  	 marking subvars of global variables as call clobbered for us
  	 to start, since they are global as well.  */
        clear_call_clobbered (var);
- 
      }
  
!   VEC_free (fieldoff_t, heap, fieldstack);
  }
  
  
--- 3069,3077 ----
  	 marking subvars of global variables as call clobbered for us
  	 to start, since they are global as well.  */
        clear_call_clobbered (var);
      }
  
!   VEC_free (fieldoff_s, heap, fieldstack);
  }
  
  

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]