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][alias-improvements] Fix PR39074


This fixes yet another PTA bug, this time dealing with stores
through pointers that may point to anything.  We have to be
conservative and assume that all aliased variables receive the
rhs.

Bootstrapped and tested on x86_64-unknown-linux-gnu, applied to the 
branch.

Richard.

2009-02-03  Richard Guenther  <rguenther@suse.de>

	PR tree-optimization/39074
	* tree-ssa-structalias.c (storedanything_id, var_storedanything,
	storedanything_tree): New.
	(do_ds_constraint): Simplify ANYTHING shortcutting.  Update
	the STOREDANYTHING solution if the lhs solution contains
	ANYTHING.
	(build_pred_graph): Add edges from STOREDANYTHING to all
	non-direct nodes.
	(get_constraint_for_1): CONSTRUCTOR
	is a zero-initializer.  Generate &NOTHING for it.
	(init_base_vars): Initialize STOREDANYTHING.
	(compute_points_to_sets): Free substitution info after
	building the succ graph.
	(ipa_pta_execute): Likewise.

	* gcc.dg/torture/pr39074.c: New testcase.
	* gcc.dg/torture/pr39074-2.c: Likewise.
	* gcc.dg/torture/pr39074-3.c: Likewise.


Index: gcc/tree-ssa-structalias.c
===================================================================
*** gcc/tree-ssa-structalias.c.orig	2009-02-05 11:35:21.000000000 +0100
--- gcc/tree-ssa-structalias.c	2009-02-05 15:13:19.000000000 +0100
*************** get_varinfo_fc (unsigned int n)
*** 302,308 ****
  
  /* Static IDs for the special variables.  */
  enum { nothing_id = 0, anything_id = 1, readonly_id = 2,
!        escaped_id = 3, nonlocal_id = 4, callused_id = 5, integer_id = 6 };
  
  /* Variable that represents the unknown pointer.  */
  static varinfo_t var_anything;
--- 302,309 ----
  
  /* Static IDs for the special variables.  */
  enum { nothing_id = 0, anything_id = 1, readonly_id = 2,
!        escaped_id = 3, nonlocal_id = 4, callused_id = 5,
!        storedanything_id = 6, integer_id = 7 };
  
  /* Variable that represents the unknown pointer.  */
  static varinfo_t var_anything;
*************** static tree nonlocal_tree;
*** 328,333 ****
--- 329,338 ----
  static varinfo_t var_callused;
  static tree callused_tree;
  
+ /* Variable that represents variables that are stored to anything.  */
+ static varinfo_t var_storedanything;
+ static tree storedanything_tree;
+ 
  /* Variable that represents integers.  This is used for when people do things
     like &0->a.b.  */
  static varinfo_t var_integer;
*************** build_pred_graph (void)
*** 1243,1249 ****
  static void
  build_succ_graph (void)
  {
!   int i;
    constraint_t c;
  
    for (i = 0; VEC_iterate (constraint_t, constraints, i, c); i++)
--- 1248,1254 ----
  static void
  build_succ_graph (void)
  {
!   unsigned i, t;
    constraint_t c;
  
    for (i = 0; VEC_iterate (constraint_t, constraints, i, c); i++)
*************** build_succ_graph (void)
*** 1284,1289 ****
--- 1289,1302 ----
  	  add_graph_edge (graph, lhsvar, rhsvar);
  	}
      }
+ 
+   /* Add edges from STOREDANYTHING to all non-direct nodes.  */
+   t = find (storedanything_id);
+   for (i = integer_id + 1; i < FIRST_REF_NODE; ++i)
+     {
+       if (!TEST_BIT (graph->direct_nodes, i))
+ 	add_graph_edge (graph, find (i), t);
+     }
  }
  
  
*************** do_ds_constraint (constraint_t c, bitmap
*** 1635,1683 ****
    /* Our IL does not allow this.  */
    gcc_assert (c->rhs.offset == 0);
  
    if (bitmap_bit_p (sol, anything_id))
!     {
!       EXECUTE_IF_SET_IN_BITMAP (delta, 0, j, bi)
!         {
! 	  varinfo_t v = get_varinfo (j);
! 	  unsigned int t;
! 	  HOST_WIDE_INT fieldoffset = v->offset + loff;
! 
! 	  if (v->is_special_var)
! 	    continue;
  
! 	  if (v->is_full_var)
! 	    fieldoffset = v->offset;
! 	  else if (loff != 0)
! 	    v = first_vi_for_offset (v, fieldoffset);
! 	  /* If the access is outside of the variable we can ignore it.  */
! 	  if (!v)
! 	    continue;
! 
! 	  do
  	    {
! 	      if (v->may_have_pointers)
  		{
! 		  t = find (v->id);
! 
! 		  if (bitmap_set_bit (get_varinfo (t)->solution, anything_id)
! 		      && !TEST_BIT (changed, t))
! 		    {
! 		      SET_BIT (changed, t);
! 		      changed_count++;
! 		    }
  		}
- 
- 	      /* If the variable is not exactly at the requested offset
- 		 we have to include the next one.  */
- 	      if (v->offset == (unsigned HOST_WIDE_INT)fieldoffset
- 		  || v->next == NULL)
- 		break;
- 
- 	      v = v->next;
- 	      fieldoffset = v->offset;
  	    }
- 	  while (1);
  	}
        return;
      }
--- 1648,1674 ----
    /* Our IL does not allow this.  */
    gcc_assert (c->rhs.offset == 0);
  
+   /* If the solution of y contains ANYTHING simply use the ANYTHING
+      solution.  This avoids needlessly increasing the points-to sets.  */
    if (bitmap_bit_p (sol, anything_id))
!     sol = get_varinfo (find (anything_id))->solution;
  
!   /* If the solution for x contains ANYTHING we have to merge the
!      solution of y into all pointer variables which we do via
!      STOREDANYTHING.  */
!   if (bitmap_bit_p (delta, anything_id))
!     {
!       unsigned t = find (storedanything_id);
!       if (add_graph_edge (graph, t, rhs))
! 	{
! 	  if (bitmap_ior_into (get_varinfo (t)->solution, sol))
  	    {
! 	      if (!TEST_BIT (changed, t))
  		{
! 		  SET_BIT (changed, t);
! 		  changed_count++;
  		}
  	    }
  	}
        return;
      }
*************** get_constraint_for_1 (tree t, VEC (ce_s,
*** 3124,3131 ****
       It is not worth adding a new option or renaming the existing one,
       since this case is relatively obscure.  */
    if (flag_delete_null_pointer_checks
!       && TREE_CODE (t) == INTEGER_CST
!       && integer_zerop (t))
      {
        temp.var = nothing_id;
        temp.type = ADDRESSOF;
--- 3115,3125 ----
       It is not worth adding a new option or renaming the existing one,
       since this case is relatively obscure.  */
    if (flag_delete_null_pointer_checks
!       && ((TREE_CODE (t) == INTEGER_CST
! 	   && integer_zerop (t))
! 	  /* The only valid CONSTRUCTORs in gimple with pointer typed
! 	     elements are zero-initializer.  */
! 	  || TREE_CODE (t) == CONSTRUCTOR))
      {
        temp.var = nothing_id;
        temp.type = ADDRESSOF;
*************** init_base_vars (void)
*** 5459,5464 ****
--- 5453,5471 ----
    rhs.offset = UNKNOWN_OFFSET;
    process_constraint (new_constraint (lhs, rhs));
  
+   /* Create the STOREDANYTHING variable, used to represent the set of
+      variables stored to *ANYTHING.  */
+   storedanything_tree = create_tmp_var_raw (ptr_type_node, "STOREDANYTHING");
+   var_storedanything = new_var_info (storedanything_tree, storedanything_id,
+ 				     "STOREDANYTHING");
+   insert_vi_for_tree (storedanything_tree, var_storedanything);
+   var_storedanything->is_artificial_var = 1;
+   var_storedanything->offset = 0;
+   var_storedanything->size = ~0;
+   var_storedanything->fullsize = ~0;
+   var_storedanything->is_special_var = 0;
+   VEC_safe_push (varinfo_t, heap, varmap, var_storedanything);
+ 
    /* Create the INTEGER variable, used to represent that a variable points
       to what an INTEGER "points to".  */
    integer_tree = create_tmp_var_raw (ptr_type_node, "INTEGER");
*************** compute_points_to_sets (void)
*** 5796,5804 ****
      fprintf (dump_file, "Rewriting constraints and unifying "
  	     "variables\n");
    rewrite_constraints (graph, si);
-   free_var_substitution_info (si);
  
    build_succ_graph ();
  
    if (dump_file && (dump_flags & TDF_GRAPH))
      dump_constraint_graph (dump_file);
--- 5803,5811 ----
      fprintf (dump_file, "Rewriting constraints and unifying "
  	     "variables\n");
    rewrite_constraints (graph, si);
  
    build_succ_graph ();
+   free_var_substitution_info (si);
  
    if (dump_file && (dump_flags & TDF_GRAPH))
      dump_constraint_graph (dump_file);
*************** ipa_pta_execute (void)
*** 6026,6034 ****
    build_pred_graph ();
    si = perform_var_substitution (graph);
    rewrite_constraints (graph, si);
-   free_var_substitution_info (si);
  
    build_succ_graph ();
    move_complex_constraints (graph);
    unite_pointer_equivalences (graph);
    find_indirect_cycles (graph);
--- 6033,6041 ----
    build_pred_graph ();
    si = perform_var_substitution (graph);
    rewrite_constraints (graph, si);
  
    build_succ_graph ();
+   free_var_substitution_info (si);
    move_complex_constraints (graph);
    unite_pointer_equivalences (graph);
    find_indirect_cycles (graph);
Index: gcc/testsuite/gcc.dg/torture/pr39074.c
===================================================================
*** /dev/null	1970-01-01 00:00:00.000000000 +0000
--- gcc/testsuite/gcc.dg/torture/pr39074.c	2009-02-05 11:41:06.000000000 +0100
***************
*** 0 ****
--- 1,31 ----
+ /* { dg-do run } */
+ /* { dg-options "-fdump-tree-alias" } */
+ /* { dg-skip-if "" { *-*-* } { "-O0" } { "" } } */
+ 
+ int i;
+ void __attribute__((noinline))
+ foo(long b, long q)
+ {
+   int *y;
+   int **a = &y, **x;
+   int ***p;
+   if (b)
+     p = (int ***)q;
+   else
+     p = &a;
+   x = *p;
+   *x = &i;  /* *ANYTHING = &i has to make sure that y points to i.  */
+   *y = 0;
+ }
+ extern void abort (void);
+ int main()
+ {
+   i = 1;
+   foo (0, 0);
+   if (i != 0)
+     abort ();
+   return 0;
+ }
+ 
+ /* { dg-final { scan-tree-dump "y.._., is dereferenced, points-to vars: { i }" "alias" } } */
+ /* { dg-final { cleanup-tree-dump "alias" } } */
Index: gcc/testsuite/gcc.dg/torture/pr39074-2.c
===================================================================
*** /dev/null	1970-01-01 00:00:00.000000000 +0000
--- gcc/testsuite/gcc.dg/torture/pr39074-2.c	2009-02-05 11:41:06.000000000 +0100
***************
*** 0 ****
--- 1,34 ----
+ /* { dg-do run } */
+ /* { dg-require-effective-target stdint_types } */
+ /* { dg-options "-fdump-tree-alias" } */
+ /* { dg-skip-if "" { *-*-* } { "-O0" } { "" } } */
+ 
+ #include <stdint.h>
+ 
+ int i;
+ uintptr_t __attribute__((noinline,const)) bar(int ***p) { return (uintptr_t)p; }
+ void __attribute__((noinline))
+ foo(void)
+ {
+   int *y;
+   int **a = &y, **x;
+   int ***p;
+   uintptr_t b;
+   b = bar(&a);
+   p = (int ***)b;
+   x = *p;
+   *x = &i; /* *ANYTHING = &i has to make sure that y points to i.  */
+   *y = 0;
+ }
+ extern void abort (void);
+ int main()
+ {
+   i = 1;
+   foo ();
+   if (i != 0)
+     abort ();
+   return 0;
+ }
+ 
+ /* { dg-final { scan-tree-dump "y.._., is dereferenced, points-to vars: { i }" "alias" } } */
+ /* { dg-final { cleanup-tree-dump "alias" } } */
Index: gcc/testsuite/gcc.dg/torture/pr39074-3.c
===================================================================
*** /dev/null	1970-01-01 00:00:00.000000000 +0000
--- gcc/testsuite/gcc.dg/torture/pr39074-3.c	2009-02-05 11:41:06.000000000 +0100
***************
*** 0 ****
--- 1,25 ----
+ /* { dg-do run } */
+ /* { dg-require-effective-target stdint_types } */
+ 
+ #include <stdint.h>
+ 
+ uintptr_t __attribute__((noinline,const)) bar(int ***p) { return (uintptr_t)p; }
+ extern void abort (void);
+ int main()
+ {
+   int i, j;
+   int *y = &j;
+   int **a = &y, **x;
+   int ***p;
+   uintptr_t b;
+   b = bar(&a);
+   p = (int ***)b;
+   x = *p;
+   *x = &i;
+   i = 1;
+   *y = 0;
+   if (i != 0)
+     abort ();
+   return 0;
+ }
+ 


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