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] Improve PTA to not make all indirectly stored pointers escaped


This improves PTA so that we can optimize

int *q;
void __attribute__((noinline))
bar (void)
{
  *q = 1;
}
int foo(int which_p)
{
  int x = 0;
  int *i,*j;
  int **p;
  if (which_p)
    p = &i;
  else
    p = &j;
  *p = &x;
  bar ();
  return x;
}

to return 0.  Previously the store *p = &x made x escape even though
p only points to local memory.

This should especially help for early points-to analysis but is also
a requirement for IPA-PTA to do anything meaningful.

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

Richard.

2009-06-16  Richard Guenther  <rguenther@suse.de>

	* tree-ssa-structalias.c (do_ds_constraint): Stores in global
	variables add them to ESCAPED.
	(find_func_aliases): Do not make all indirectly stored values
	escaped.

	* gcc.dg/tree-ssa/pta-escape-1.c: New testcase.
	* gcc.dg/tree-ssa/pta-escape-2.c: Likewise.
	* gcc.dg/tree-ssa/pta-escape-3.c: Likewise.
	* gcc.dg/tree-ssa/ssa-fre-27.c: Likewise.

Index: gcc/tree-ssa-structalias.c
===================================================================
*** gcc/tree-ssa-structalias.c.orig	2009-06-16 11:56:41.000000000 +0200
--- gcc/tree-ssa-structalias.c	2009-06-16 12:25:18.000000000 +0200
*************** do_ds_constraint (constraint_t c, bitmap
*** 1664,1669 ****
--- 1664,1682 ----
        unsigned int t;
        HOST_WIDE_INT fieldoffset = v->offset + loff;
  
+       /* If v is a NONLOCAL then this is an escape point.  */
+       if (j == nonlocal_id)
+ 	{
+ 	  t = find (escaped_id);
+ 	  if (add_graph_edge (graph, t, rhs)
+ 	      && bitmap_ior_into (get_varinfo (t)->solution, sol)
+ 	      && !TEST_BIT (changed, t))
+ 	    {
+ 	      SET_BIT (changed, t);
+ 	      changed_count++;
+ 	    }
+ 	}
+ 
        if (v->is_special_var)
  	continue;
  
*************** do_ds_constraint (constraint_t c, bitmap
*** 1680,1697 ****
  	  if (v->may_have_pointers)
  	    {
  	      t = find (v->id);
! 	      if (add_graph_edge (graph, t, rhs))
  		{
! 		  if (bitmap_ior_into (get_varinfo (t)->solution, sol))
! 		    {
! 		      if (t == rhs)
! 			sol = get_varinfo (rhs)->solution;
! 		      if (!TEST_BIT (changed, t))
! 			{
! 			  SET_BIT (changed, t);
! 			  changed_count++;
! 			}
! 		    }
  		}
  	    }
  
--- 1693,1716 ----
  	  if (v->may_have_pointers)
  	    {
  	      t = find (v->id);
! 	      if (add_graph_edge (graph, t, rhs)
! 		  && bitmap_ior_into (get_varinfo (t)->solution, sol)
! 		  && !TEST_BIT (changed, t))
  		{
! 		  SET_BIT (changed, t);
! 		  changed_count++;
! 		}
! 	    }
! 	  /* If v is a global variable then this is an escape point.  */
! 	  if (is_global_var (v->decl))
! 	    {
! 	      t = find (escaped_id);
! 	      if (add_graph_edge (graph, t, rhs)
! 		  && bitmap_ior_into (get_varinfo (t)->solution, sol)
! 		  && !TEST_BIT (changed, t))
! 		{
! 		  SET_BIT (changed, t);
! 		  changed_count++;
  		}
  	    }
  
*************** find_func_aliases (gimple origt)
*** 3734,3764 ****
  		process_constraint (new_constraint (*c, *c2));
  	    }
  	}
      }
  
    stmt_escape_type = is_escape_site (t);
!   if (stmt_escape_type == ESCAPE_STORED_IN_GLOBAL)
!     {
!       gcc_assert (is_gimple_assign (t));
!       if (gimple_assign_rhs_code (t) == ADDR_EXPR)
! 	{
! 	  tree rhs = gimple_assign_rhs1 (t);
! 	  tree base = get_base_address (TREE_OPERAND (rhs, 0));
! 	  if (base
! 	      && (!DECL_P (base)
! 		  || !is_global_var (base)))
! 	    make_escape_constraint (rhs);
! 	}
!       else if (get_gimple_rhs_class (gimple_assign_rhs_code (t))
! 	       == GIMPLE_SINGLE_RHS)
! 	{
! 	  if (could_have_pointers (gimple_assign_rhs1 (t)))
! 	    make_escape_constraint (gimple_assign_rhs1 (t));
! 	}
!       else
! 	gcc_unreachable ();
!     }
!   else if (stmt_escape_type == ESCAPE_BAD_CAST)
      {
        gcc_assert (is_gimple_assign (t));
        gcc_assert (CONVERT_EXPR_CODE_P (gimple_assign_rhs_code (t))
--- 3753,3767 ----
  		process_constraint (new_constraint (*c, *c2));
  	    }
  	}
+       /* If there is a store to a global variable the rhs escapes.  */
+       if ((lhsop = get_base_address (lhsop)) != NULL_TREE
+ 	  && DECL_P (lhsop)
+ 	  && is_global_var (lhsop))
+ 	make_escape_constraint (rhsop);
      }
  
    stmt_escape_type = is_escape_site (t);
!   if (stmt_escape_type == ESCAPE_BAD_CAST)
      {
        gcc_assert (is_gimple_assign (t));
        gcc_assert (CONVERT_EXPR_CODE_P (gimple_assign_rhs_code (t))
Index: gcc/testsuite/gcc.dg/tree-ssa/pta-escape-1.c
===================================================================
*** /dev/null	1970-01-01 00:00:00.000000000 +0000
--- gcc/testsuite/gcc.dg/tree-ssa/pta-escape-1.c	2009-06-16 12:10:42.000000000 +0200
***************
*** 0 ****
--- 1,37 ----
+ /* { dg-do run } */
+ /* { dg-options "-O -fdump-tree-alias-details" } */
+ 
+ int *i;
+ void __attribute__((noinline))
+ foo (void)
+ {
+   *i = 1;
+ }
+ int __attribute__((noinline))
+ bar(int local_p)
+ {
+   int x = 0;
+   int *j;
+   int **p;
+   if (local_p)
+     p = &j;
+   else
+     p = &i;
+   *p = &x;  /* This makes x escape.  */
+   foo ();
+   return x;
+ }
+ extern void abort (void);
+ int main()
+ {
+   int k = 2;
+   i = &k;
+   if (bar (1) != 0 || k != 1)
+     abort ();
+   if (bar (0) != 1)
+     abort ();
+   return 0;
+ }
+ 
+ /* { dg-final { scan-tree-dump "ESCAPED, points-to vars: { x }" "alias" } } */
+ /* { dg-final { cleanup-tree-dump "alias" } } */
Index: gcc/testsuite/gcc.dg/tree-ssa/pta-escape-2.c
===================================================================
*** /dev/null	1970-01-01 00:00:00.000000000 +0000
--- gcc/testsuite/gcc.dg/tree-ssa/pta-escape-2.c	2009-06-16 12:26:18.000000000 +0200
***************
*** 0 ****
--- 1,38 ----
+ /* { dg-do run } */
+ /* { dg-options "-O -fdump-tree-alias-details" } */
+ 
+ int *i;
+ void __attribute__((noinline))
+ foo (void)
+ {
+   *i = 1;
+ }
+ int __attribute__((noinline))
+ bar(int local_p, int **q)
+ {
+   int x = 0;
+   int *j;
+   int **p;
+   if (local_p)
+     p = &j;
+   else
+     p = q;
+   *p = &x;  /* This makes x escape.  */
+   foo ();
+   return x;
+ }
+ extern void abort (void);
+ int main()
+ {
+   int k = 2;
+   int **q = &i;
+   i = &k;
+   if (bar (1, q) != 0 || k != 1)
+     abort ();
+   if (bar (0, q) != 1)
+     abort ();
+   return 0;
+ }
+ 
+ /* { dg-final { scan-tree-dump "ESCAPED, points-to vars: { x }" "alias" } } */
+ /* { dg-final { cleanup-tree-dump "alias" } } */
Index: gcc/testsuite/gcc.dg/tree-ssa/pta-escape-3.c
===================================================================
*** /dev/null	1970-01-01 00:00:00.000000000 +0000
--- gcc/testsuite/gcc.dg/tree-ssa/pta-escape-3.c	2009-06-16 12:28:29.000000000 +0200
***************
*** 0 ****
--- 1,42 ----
+ /* { dg-do run } */
+ /* { dg-options "-O -fdump-tree-alias-details" } */
+ 
+ int *i;
+ void __attribute__((noinline))
+ foo (void)
+ {
+   *i = 1;
+ }
+ int **__attribute__((noinline,const))
+ foobar (void)
+ {
+   return &i;
+ }
+ int __attribute__((noinline))
+ bar(int local_p)
+ {
+   int x = 0;
+   int *j;
+   int **p;
+   if (local_p)
+     p = &j;
+   else
+     p = foobar();
+   *p = &x;  /* This makes x escape.  */
+   foo ();
+   return x;
+ }
+ extern void abort (void);
+ int main()
+ {
+   int k = 2;
+   i = &k;
+   if (bar (1) != 0 || k != 1)
+     abort ();
+   if (bar (0) != 1)
+     abort ();
+   return 0;
+ }
+ 
+ /* { dg-final { scan-tree-dump "ESCAPED, points-to vars: { x }" "alias" } } */
+ /* { dg-final { cleanup-tree-dump "alias" } } */
Index: gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-27.c
===================================================================
*** /dev/null	1970-01-01 00:00:00.000000000 +0000
--- gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-27.c	2009-06-16 12:36:12.000000000 +0200
***************
*** 0 ****
--- 1,25 ----
+ /* { dg-do compile } */
+ /* { dg-options "-O -fdump-tree-fre-details" } */
+ 
+ int *q;
+ void __attribute__((noinline))
+ bar (void)
+ {
+   *q = 1;
+ }
+ int foo(int which_p)
+ {
+   int x = 0;
+   int *i,*j;
+   int **p;
+   if (which_p)
+     p = &i;
+   else
+     p = &j;
+   *p = &x;
+   bar ();
+   return x;
+ }
+ 
+ /* { dg-final { scan-tree-dump "Replaced x with 0" "fre" } } */
+ /* { dg-final { cleanup-tree-dump "fre" } } */


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