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] Fix TBAA-pruning of points-to sets


We can TBAA-prune the points-to set if the pointer was dereferenced
and use may_alias_p to get better TBAA disambiguation.

This patch renames the pi->is_dereferenced flag to pi->memory_tag_needed,
as this is what it really means - we also set is_dereferenced for call
arguments, which is not a dereference site as far as TBAA is concerned.

Thus the patch adds back a pi->is_dereferenced flag and properly
initializes it.  It removes the code that tried to track the
dereferenced property throughout the PTA solver via looking at the
constraints.

It "breaks" the tree-ssa-alias-warnings code some more (it uses the
TBAA-pruned points-to sets to search for aliases the pointer cannot
alias ...).  I tried to fix it somewhat, but I would suggest to
remove that code and instead implement it as part of the alias
computation before the sets are pruned.  But I have no time for that
now.

Bootstrapped and tested on x86_64-unknown-linux-gnu with the alias.c
fix applied.  Ok for trunk?

Thanks,
Richard.

2008-05-29  Richard Guenther  <rguenther@suse.de>

	PR tree-optimization/36345
	* tree-flow.h (struct ptr_info_def): Align escape_mask,
	add memory_tag_needed flag.
	(may_alias_p): Declare.
	* tree-ssa-alias.c (may_alias_p): Export.
	(set_initial_properties): Use memory_tag_needed flag.
	(update_reference_counts): Likewise.
	(reset_alias_info): Reset memory_tag_needed flag.
	(create_name_tags): Check memory_tag_needed flag.
	(dump_points_to_info_for): Dump it.
	* tree-ssa-structalias.c (struct variable_info): Remove
	directly_dereferenced flag.
	(new_var_info): Do not initialize it.
	(process_constraint_1): Do not set it.
	(update_alias_info): Set is_dereferenced flag.
	(set_uids_in_ptset): Use may_alias_p.
	(set_used_smts): Check memory_tag_needed flag.
	(find_what_p_points_to): Likewise.  Pass is_dereferenced flag.
	* tree-ssa-alias.c (verify_flow_sensitive_alias_info): Check
	memory_tag_needed flag.
	* tree-ssa-alias-warnings.c (dsa_named_for): Try to recover
	from broken design.

	* gcc.c-torture/execute/20020619-1.c: Remove broken testcase.

Index: trunk/gcc/tree-flow.h
===================================================================
*** trunk.orig/gcc/tree-flow.h	2008-06-03 15:14:08.000000000 +0200
--- trunk/gcc/tree-flow.h	2008-06-03 15:14:31.000000000 +0200
*************** typedef struct
*** 227,232 ****
--- 227,235 ----
  /* Aliasing information for SSA_NAMEs representing pointer variables.  */
  struct ptr_info_def GTY(())
  {
+   /* Mask of reasons this pointer's value escapes the function.  */
+   ENUM_BITFIELD (escape_type) escape_mask : 9;
+ 
    /* Nonzero if points-to analysis couldn't determine where this pointer
       is pointing to.  */
    unsigned int pt_anything : 1;
*************** struct ptr_info_def GTY(())
*** 234,240 ****
    /* Nonzero if the value of this pointer escapes the current function.  */
    unsigned int value_escapes_p : 1;
  
!   /* Nonzero if this pointer is dereferenced.  */
    unsigned int is_dereferenced : 1;
  
    /* Nonzero if this pointer points to a global variable.  */
--- 237,247 ----
    /* Nonzero if the value of this pointer escapes the current function.  */
    unsigned int value_escapes_p : 1;
  
!   /* Nonzero if a memory tag is needed for this pointer.  This is
!      true if this pointer is eventually dereferenced.  */
!   unsigned int memory_tag_needed : 1;
! 
!   /* Nonzero if this pointer is really dereferenced.  */
    unsigned int is_dereferenced : 1;
  
    /* Nonzero if this pointer points to a global variable.  */
*************** struct ptr_info_def GTY(())
*** 243,251 ****
    /* Nonzero if this pointer points to NULL.  */
    unsigned int pt_null : 1;
  
-   /* Mask of reasons this pointer's value escapes the function  */
-   ENUM_BITFIELD (escape_type) escape_mask : 9;
- 
    /* Set of variables that this pointer may point to.  */
    bitmap pt_vars;
  
--- 250,255 ----
*************** extern void debug_points_to_info (void);
*** 852,857 ****
--- 856,862 ----
  extern void dump_points_to_info_for (FILE *, tree);
  extern void debug_points_to_info_for (tree);
  extern bool may_be_aliased (tree);
+ extern bool may_alias_p (tree, alias_set_type, tree, alias_set_type, bool);
  extern struct ptr_info_def *get_ptr_info (tree);
  extern void new_type_alias (tree, tree, tree);
  extern void count_uses_and_derefs (tree, tree, unsigned *, unsigned *,
Index: trunk/gcc/tree-ssa-alias.c
===================================================================
*** trunk.orig/gcc/tree-ssa-alias.c	2008-06-03 15:14:08.000000000 +0200
--- trunk/gcc/tree-ssa-alias.c	2008-06-03 15:14:31.000000000 +0200
*************** static bitmap_obstack alias_bitmap_obsta
*** 197,203 ****
  /* Local functions.  */
  static void compute_flow_insensitive_aliasing (struct alias_info *);
  static void dump_alias_stats (FILE *);
- static bool may_alias_p (tree, alias_set_type, tree, alias_set_type, bool);
  static tree create_memory_tag (tree type, bool is_type_tag);
  static tree get_smt_for (tree, struct alias_info *);
  static tree get_nmt_for (tree);
--- 197,202 ----
*************** set_initial_properties (struct alias_inf
*** 591,604 ****
           So removing this code and fixing all the bugs would be nice.
           It is the cause of a bunch of clobbering.  */
        if ((pi->pt_global_mem || pi->pt_anything) 
! 	  && pi->is_dereferenced && pi->name_mem_tag)
  	{
  	  mark_call_clobbered (pi->name_mem_tag, ESCAPE_IS_GLOBAL);
  	  MTAG_GLOBAL (pi->name_mem_tag) = true;
  	}
        
        if ((pi->pt_global_mem || pi->pt_anything) 
! 	  && pi->is_dereferenced
  	  && tag)
  	{
  	  mark_call_clobbered (tag, ESCAPE_IS_GLOBAL);
--- 590,603 ----
           So removing this code and fixing all the bugs would be nice.
           It is the cause of a bunch of clobbering.  */
        if ((pi->pt_global_mem || pi->pt_anything) 
! 	  && pi->memory_tag_needed && pi->name_mem_tag)
  	{
  	  mark_call_clobbered (pi->name_mem_tag, ESCAPE_IS_GLOBAL);
  	  MTAG_GLOBAL (pi->name_mem_tag) = true;
  	}
        
        if ((pi->pt_global_mem || pi->pt_anything) 
! 	  && pi->memory_tag_needed
  	  && tag)
  	{
  	  mark_call_clobbered (tag, ESCAPE_IS_GLOBAL);
*************** update_reference_counts (struct mem_ref_
*** 1281,1287 ****
        if (ptr
  	  && POINTER_TYPE_P (TREE_TYPE (ptr))
  	  && (pi = SSA_NAME_PTR_INFO (ptr)) != NULL
! 	  && pi->is_dereferenced)
  	{
  	  unsigned j;
  	  bitmap_iterator bj;
--- 1280,1286 ----
        if (ptr
  	  && POINTER_TYPE_P (TREE_TYPE (ptr))
  	  && (pi = SSA_NAME_PTR_INFO (ptr)) != NULL
! 	  && pi->memory_tag_needed)
  	{
  	  unsigned j;
  	  bitmap_iterator bj;
*************** reset_alias_info (void)
*** 2039,2044 ****
--- 2038,2044 ----
  	  pi->pt_anything = 0;
  	  pi->pt_null = 0;
  	  pi->value_escapes_p = 0;
+ 	  pi->memory_tag_needed = 0;
  	  pi->is_dereferenced = 0;
  	  if (pi->pt_vars)
  	    bitmap_clear (pi->pt_vars);
*************** create_name_tags (void)
*** 2182,2188 ****
  
        pi = SSA_NAME_PTR_INFO (ptr);
  
!       if (pi->pt_anything || !pi->is_dereferenced)
  	{
  	  /* No name tags for pointers that have not been
  	     dereferenced or point to an arbitrary location.  */
--- 2182,2188 ----
  
        pi = SSA_NAME_PTR_INFO (ptr);
  
!       if (pi->pt_anything || !pi->memory_tag_needed)
  	{
  	  /* No name tags for pointers that have not been
  	     dereferenced or point to an arbitrary location.  */
*************** maybe_create_global_var (void)
*** 2661,2667 ****
     
     VAR_ALIAS_SET is the alias set for VAR.  */
  
! static bool
  may_alias_p (tree ptr, alias_set_type mem_alias_set,
  	     tree var, alias_set_type var_alias_set,
  	     bool alias_set_only)
--- 2661,2667 ----
     
     VAR_ALIAS_SET is the alias set for VAR.  */
  
! bool
  may_alias_p (tree ptr, alias_set_type mem_alias_set,
  	     tree var, alias_set_type var_alias_set,
  	     bool alias_set_only)
*************** dump_points_to_info_for (FILE *file, tre
*** 3224,3229 ****
--- 3224,3231 ----
  
        if (pi->is_dereferenced)
  	fprintf (file, ", is dereferenced");
+       else if (pi->memory_tag_needed)
+ 	fprintf (file, ", is dereferenced in call");
  
        if (pi->value_escapes_p)
  	fprintf (file, ", its value escapes");
Index: trunk/gcc/tree-ssa-structalias.c
===================================================================
*** trunk.orig/gcc/tree-ssa-structalias.c	2008-06-03 15:14:13.000000000 +0200
--- trunk/gcc/tree-ssa-structalias.c	2008-06-03 15:15:12.000000000 +0200
*************** struct variable_info
*** 227,237 ****
    /* A link to the variable for the next field in this structure.  */
    struct variable_info *next;
  
-   /* True if the variable is directly the target of a dereference.
-      This is used to track which variables are *actually* dereferenced
-      so we can prune their points to listed. */
-   unsigned int directly_dereferenced:1;
- 
    /* True if this is a variable created by the constraint analysis, such as
       heap variables and constraints we had to break up.  */
    unsigned int is_artificial_var:1;
--- 227,232 ----
*************** new_var_info (tree t, unsigned int id, c
*** 364,370 ****
    ret->id = id;
    ret->name = name;
    ret->decl = t;
-   ret->directly_dereferenced = false;
    ret->is_artificial_var = false;
    ret->is_heap_var = false;
    ret->is_special_var = false;
--- 359,364 ----
*************** process_constraint_1 (constraint_t t, bo
*** 2520,2533 ****
    gcc_assert (rhs.var < VEC_length (varinfo_t, varmap));
    gcc_assert (lhs.var < VEC_length (varinfo_t, varmap));
  
-   if (!from_call)
-     {
-       if (lhs.type == DEREF)
- 	get_varinfo (lhs.var)->directly_dereferenced = true;
-       if (rhs.type == DEREF)
- 	get_varinfo (rhs.var)->directly_dereferenced = true;
-     }
- 
    if (!use_field_sensitive)
      {
        t->rhs.offset = 0;
--- 2514,2519 ----
*************** update_alias_info (tree stmt, struct ali
*** 3369,3374 ****
--- 3355,3366 ----
  	 is an escape point, whether OP escapes.  */
        count_uses_and_derefs (op, stmt, &num_uses, &num_loads, &num_stores);
  
+       /* For directly dereferenced pointers we can apply
+ 	 TBAA-pruning to their points-to set.  We may not count the
+ 	 implicit dereferences &PTR->FLD here.  */
+       if (num_loads + num_stores > 0)
+ 	pi->is_dereferenced = 1;
+ 
        /* Handle a corner case involving address expressions of the
  	 form '&PTR->FLD'.  The problem with these expressions is that
  	 they do not represent a dereference of PTR.  However, if some
*************** update_alias_info (tree stmt, struct ali
*** 3409,3415 ****
  	     dereferenced pointers that point to a set of
  	     variables will be assigned a name tag to alias
  	     all the variables OP points to.  */
! 	  pi->is_dereferenced = 1;
  
  	  /* If this is a store operation, mark OP as being
  	     dereferenced to store, otherwise mark it as being
--- 3401,3410 ----
  	     dereferenced pointers that point to a set of
  	     variables will be assigned a name tag to alias
  	     all the variables OP points to.  */
! 	  pi->memory_tag_needed = 1;
! 
! 	  /* ???  For always executed direct dereferences we can
! 	     apply TBAA-pruning to their escape set.  */
  
  	  /* If this is a store operation, mark OP as being
  	     dereferenced to store, otherwise mark it as being
*************** update_alias_info (tree stmt, struct ali
*** 3443,3449 ****
  	      || stmt_escape_type == ESCAPE_STORED_IN_GLOBAL)
  	    {
  	      pointer_set_insert (ai->dereferenced_ptrs_store, var);
! 	      pi->is_dereferenced = 1;
  	    }
  	}
      }
--- 3438,3444 ----
  	      || stmt_escape_type == ESCAPE_STORED_IN_GLOBAL)
  	    {
  	      pointer_set_insert (ai->dereferenced_ptrs_store, var);
! 	      pi->memory_tag_needed = 1;
  	    }
  	}
      }
*************** set_uids_in_ptset (tree ptr, bitmap into
*** 4653,4662 ****
  	    bitmap_set_bit (into, DECL_UID (vi->decl));
  	  else
  	    {
! 	      alias_set_type var_alias_set, ptr_alias_set;
  	      var_alias_set = get_alias_set (vi->decl);
! 	      ptr_alias_set = get_alias_set (TREE_TYPE (TREE_TYPE (ptr)));
! 	      if (alias_sets_conflict_p (ptr_alias_set, var_alias_set))
  	        bitmap_set_bit (into, DECL_UID (vi->decl));
  	    }
  	}
--- 4648,4658 ----
  	    bitmap_set_bit (into, DECL_UID (vi->decl));
  	  else
  	    {
! 	      alias_set_type var_alias_set, mem_alias_set;
  	      var_alias_set = get_alias_set (vi->decl);
! 	      mem_alias_set = get_alias_set (TREE_TYPE (TREE_TYPE (ptr)));
! 	      if (may_alias_p (SSA_NAME_VAR (ptr), mem_alias_set,
! 			       vi->decl, var_alias_set, true))
  	        bitmap_set_bit (into, DECL_UID (vi->decl));
  	    }
  	}
*************** set_used_smts (void)
*** 4703,4709 ****
        /* Skip the special variables and those that can't be aliased.  */
        if (vi->is_special_var
  	  || !SSA_VAR_P (var)
! 	  || (pi && !pi->is_dereferenced)
  	  || (TREE_CODE (var) == VAR_DECL && !may_be_aliased (var))
  	  || !POINTER_TYPE_P (TREE_TYPE (var)))
  	continue;
--- 4699,4705 ----
        /* Skip the special variables and those that can't be aliased.  */
        if (vi->is_special_var
  	  || !SSA_VAR_P (var)
! 	  || (pi && !pi->memory_tag_needed)
  	  || (TREE_CODE (var) == VAR_DECL && !may_be_aliased (var))
  	  || !POINTER_TYPE_P (TREE_TYPE (var)))
  	continue;
*************** find_what_p_points_to (tree p)
*** 4797,4803 ****
  	  bitmap finished_solution;
  	  bitmap result;
  
! 	  if (!pi->is_dereferenced)
  	    return false;
  
  	  /* This variable may have been collapsed, let's get the real
--- 4793,4799 ----
  	  bitmap finished_solution;
  	  bitmap result;
  
! 	  if (!pi->memory_tag_needed)
  	    return false;
  
  	  /* This variable may have been collapsed, let's get the real
*************** find_what_p_points_to (tree p)
*** 4842,4848 ****
  	    }
  
  	  set_uids_in_ptset (p, finished_solution, vi->solution,
! 			     vi->directly_dereferenced,
  			     vi->no_tbaa_pruning);
  	  result = shared_bitmap_lookup (finished_solution);
  
--- 4838,4844 ----
  	    }
  
  	  set_uids_in_ptset (p, finished_solution, vi->solution,
! 			     pi->is_dereferenced,
  			     vi->no_tbaa_pruning);
  	  result = shared_bitmap_lookup (finished_solution);
  
Index: trunk/gcc/testsuite/gcc.c-torture/execute/20020619-1.c
===================================================================
*** trunk.orig/gcc/testsuite/gcc.c-torture/execute/20020619-1.c	2008-06-03 15:14:08.000000000 +0200
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
***************
*** 1,32 ****
- static int ref(void)
- {
-   union {
-     char c[5];
-     int i;
-   } u;
- 
-   __builtin_memset (&u, 0, sizeof(u));
-   u.c[0] = 1;
-   u.c[1] = 2;
-   u.c[2] = 3;
-   u.c[3] = 4;
- 
-   return u.i;
- }
- 
- #define MAX(a,b)  (a < b ? b : a)
- 
- static int test(void)
- {
-   char c[MAX(5, sizeof(int))] __attribute__((aligned)) = { 1, 2, 3, 4 };
-   return *(int *)c;
- }
- 
- int main()
- {
-   int a = test();
-   int b = ref();
-   if (a != b)
-     abort ();
-   return 0;
- }
--- 0 ----
Index: trunk/gcc/tree-ssa-alias-warnings.c
===================================================================
*** trunk.orig/gcc/tree-ssa-alias-warnings.c	2008-06-03 15:14:08.000000000 +0200
--- trunk/gcc/tree-ssa-alias-warnings.c	2008-06-03 15:14:31.000000000 +0200
*************** dsa_named_for (tree ptr)
*** 914,919 ****
--- 914,920 ----
  	{
  	  unsigned ix;
  	  bitmap_iterator bi;
+ 	  bool any = false;
  
  	  EXECUTE_IF_SET_IN_BITMAP (pi->pt_vars, 0, ix, bi)
  	    {
*************** dsa_named_for (tree ptr)
*** 922,928 ****
--- 923,938 ----
  	      if (nonstandard_alias_p (ptr, alias, false))
  		strict_aliasing_warn (SSA_NAME_DEF_STMT (ptr),
  				      ptr, true, alias, false, true);
+ 	      else
+ 		any = true;
  	    }
+ 
+ 	  /* If there was no object in the points-to set that the pointer
+ 	     may alias, unconditionally warn.  */
+ 	  if (!any)
+ 	    warning (OPT_Wstrict_aliasing,
+ 		     "dereferencing type-punned pointer %D will "
+ 		     "break strict-aliasing rules", SSA_NAME_VAR (ptr));
  	}
      }
  }
Index: trunk/gcc/tree-ssa.c
===================================================================
*** trunk.orig/gcc/tree-ssa.c	2008-06-03 15:14:08.000000000 +0200
--- trunk/gcc/tree-ssa.c	2008-06-03 15:14:31.000000000 +0200
*************** verify_flow_sensitive_alias_info (void)
*** 558,564 ****
  	continue;
  
        ann = var_ann (var);
!       if (pi->is_dereferenced && !pi->name_mem_tag && !ann->symbol_mem_tag)
  	{
  	  error ("dereferenced pointers should have a name or a symbol tag");
  	  goto err;
--- 558,564 ----
  	continue;
  
        ann = var_ann (var);
!       if (pi->memory_tag_needed && !pi->name_mem_tag && !ann->symbol_mem_tag)
  	{
  	  error ("dereferenced pointers should have a name or a symbol tag");
  	  goto err;


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