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]

[tree-ssa] Enable SSA CCP by default [patch]


- Enables SSA CCP by default.

- Fixes a may-alias bug that was causing all the bootstrap
  miscomparisons for the past several weeks.  The dataflow
  builder was not clobbering pointer dereferences at call sites.
  

  	*p = 5;
	foo (p);
	x = *p;

  In the code above, the value 5 was being propagated across the
  call to foo().  This was also creating a regression on
  147.vortex in SPEC95.

- Adds a new test to catch this case.


The next obstacle is making sure that SSA information is kept
up-to-date or rebuilt so that we can chain passes.  Right now,
another pass after CCP will likely fail.  As a temporary kludge
we can tear down and rebuild CFG/DFA/SSA in
optimize_function_tree, but we need to move away from that model
in the long term.


Bootstrapped and tested on x86.


Diego.



	* toplev.c (parse_options_and_default_flags): Enable SSA-CCP by
	default with optimization >= 1.
	* tree-dfa.c (find_refs_in_expr): Clobber '*.GLOBAL_VAR', not
	'GLOBAL_VAR'.
	(collect_dfa_stats): Collect statistics on '*.GLOBAL_VAR'.
	(compute_may_aliases): Make sure that variable is an INDIRECT_REF.
	(may_alias_p): GLOBAL_VAR should alias INDIRECT_REFs.
	Only check addressability on VAR_DECLs.
	(find_may_aliases_for): Make sure argument is an INDIRECT_REF.
	* tree-flow-inline.h (indirect_var): Call DECL_P.
	(set_indirect_var): Call DECL_P.
	Create annotation if it doesn't exist.
	(create_indirect_ref): Move from tree-dfa.c.
	* tree-flow.h (create_indirect_ref): Declare.
	* tree-ssa-ccp.c (visit_phi_node): Avoid debugging dump from
	accessing uninitialized data.
	* tree-ssa.c (init_tree_ssa): Create an INDIRECT_REF node for
	.GLOBAL_VAR.


2002-11-13  Diego Novillo  <dnovillo@redhat.com>

	* testsuite/gcc.c-torture/execute/20021113-1.c: New test.

Index: toplev.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/toplev.c,v
retrieving revision 1.654.2.31
diff -d -u -p -r1.654.2.31 toplev.c
--- toplev.c	6 Nov 2002 12:21:04 -0000	1.654.2.31
+++ toplev.c	13 Nov 2002 19:51:54 -0000
@@ -4861,8 +4861,7 @@ parse_options_and_default_flags (argc, a
       flag_crossjumping = 1;
       flag_if_conversion = 1;
       flag_if_conversion2 = 1;
-      if (getenv ("TREE_CCP"))
-	flag_tree_ccp = 1;
+      flag_tree_ccp = 1;
     }
 
   if (optimize >= 2)
Index: tree-dfa.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/Attic/tree-dfa.c,v
retrieving revision 1.1.4.46
diff -d -u -p -r1.1.4.46 tree-dfa.c
--- tree-dfa.c	12 Nov 2002 22:01:16 -0000	1.1.4.46
+++ tree-dfa.c	13 Nov 2002 19:51:54 -0000
@@ -100,7 +100,6 @@ static void find_may_aliases_for	PARAMS 
 static void add_may_alias		PARAMS ((tree, tree));
 static inline bool may_alias_p		PARAMS ((tree, tree));
 static size_t tree_ref_size		PARAMS ((enum tree_ref_type));
-static inline tree create_indirect_ref	PARAMS ((tree));
 static tree replace_ref_r		PARAMS ((tree *, int *, void *));
 
 
@@ -387,11 +386,14 @@ find_refs_in_expr (expr_p, ref_type, ref
 
   /* Function calls.  Create a V_USE reference for every argument in the call.
      If the callee is neither pure nor const, create a use and a def of
-     GLOBAL_VAR.  Definitions of this variable will reach uses of every call
-     clobbered variable in the function.  Uses of GLOBAL_VAR will be reached by
+     *.GLOBAL_VAR.  This variable is a pointer that is assumed to point to
+     every global variable and locals that have had their address taken.
+     
+     Definitions of this variable will reach uses of every call clobbered
+     variable in the function.  Uses of *.GLOBAL_VAR will be reached by
      definitions of call clobbered variables.  This is used to model the
-     effects that the called function may have on local and global variables
-     that might be visible to it.  */
+     effects that the called function may have on local and global
+     variables that might be visible to it.  */
   if (code == CALL_EXPR)
     {
       tree callee;
@@ -408,8 +410,10 @@ find_refs_in_expr (expr_p, ref_type, ref
 	  may-use followed by a clobbering definition of GLOBAL_VAR.  */
       if (! (flags & (ECF_CONST | ECF_PURE)))
 	{
-	  create_ref (global_var, V_USE, TRM_MAY, bb, parent_stmt_p, 1);
-	  create_ref (global_var, V_DEF, TRM_CLOBBER, bb, parent_stmt_p, 1);
+	  create_ref (indirect_var (global_var), V_USE, TRM_MAY, bb,
+		      parent_stmt_p, 1);
+	  create_ref (indirect_var (global_var), V_DEF, TRM_CLOBBER, bb,
+		      parent_stmt_p, 1);
 	}
 
       return;
@@ -1619,6 +1623,7 @@ collect_dfa_stats (dfa_stats_p)
   htab_t htab;
   tree *first_stmt_p;
   basic_block bb;
+  tree star_global_var;
 
   if (dfa_stats_p == NULL)
     abort ();
@@ -1633,6 +1638,8 @@ collect_dfa_stats (dfa_stats_p)
 
   /* Also look into GLOBAL_VAR (which is not actually part of the program).  */
   walk_tree (&global_var, collect_dfa_stats_r, (void *) dfa_stats_p, NULL);
+  star_global_var = indirect_var (global_var);
+  walk_tree (&star_global_var, collect_dfa_stats_r, (void *) dfa_stats_p, NULL);
 
   FOR_EACH_BB (bb)
     count_tree_refs (dfa_stats_p, bb_refs (bb));
@@ -1840,10 +1847,9 @@ compute_may_aliases ()
   for (i = 0; i < num_referenced_vars; i++)
     {
       tree var = referenced_var (i);
-      tree sym = get_base_symbol (var);
 
       /* Find aliases for pointer variables.  */
-      if (POINTER_TYPE_P (TREE_TYPE (sym)))
+      if (TREE_CODE (var) == INDIRECT_REF)
 	find_may_aliases_for (var);
     }
 
@@ -1856,39 +1862,41 @@ compute_may_aliases ()
 }
 
 
-/* Return true if PTR (an INDIRECT_REF tree) may alias VAR_SYM (a _DECL tree).
-   FIXME  This returns true more often than it should.  */
+/* Return true if INDIRECT_PTR (an INDIRECT_REF node) may alias VAR (a
+   VAR_DECL or INDIRECT_REF node).  FIXME  This returns true more often
+   than it should.  */
 
 static inline bool
-may_alias_p (ptr, var_sym)
-     tree ptr;
-     tree var_sym;
+may_alias_p (indirect_ptr, var)
+     tree indirect_ptr;
+     tree var;
 {
   HOST_WIDE_INT ptr_alias_set, var_alias_set;
-  tree ptr_sym = get_base_symbol (ptr);
+  tree ptr_sym = get_base_symbol (indirect_ptr);
+  tree var_sym = get_base_symbol (var);
   
-  /* GLOBAL_VAR aliases every global variable and locals that have had
-     their address taken, unless points-to analysis is done. This is because
-     points-to is supposed to handle this case, and thus, can give a more
-     accurate answer.   */
-
-  if (!flag_tree_points_to && 
-      ptr == global_var
-      && var_sym != global_var
+  /* GLOBAL_VAR aliases every global variable, pointer dereference and
+     locals that have had their address taken, unless points-to analysis is
+     done.  This is because points-to is supposed to handle this case, and
+     thus, can give a more accurate answer.   */
+  if (flag_tree_points_to == PTA_NONE
+      && ptr_sym == global_var
       && (TREE_ADDRESSABLE (var_sym)
+	  || TREE_CODE (var) == INDIRECT_REF
 	  || decl_function_context (var_sym) == NULL))
     return true;
-  
+
   /* Obvious reasons why PTR_SYM and VAR_SYM can't possibly alias
      each other.  */
   if (var_sym == ptr_sym
-      || !POINTER_TYPE_P (TREE_TYPE (ptr_sym))
-      || !TREE_ADDRESSABLE (var_sym)
-      || DECL_ARTIFICIAL (var_sym))
+      || DECL_ARTIFICIAL (var_sym)
+      /* Only check for addressability on non-pointers.  Even if VAR is 
+	 a non-addressable pointer, it may still alias with INDIRECT_PTR.  */
+      || (DECL_P (var) && !TREE_ADDRESSABLE (var)))
     return false;
 
-  ptr_alias_set = get_alias_set (TREE_TYPE (ptr));
-  var_alias_set = get_alias_set (TREE_TYPE (var_sym));
+  ptr_alias_set = get_alias_set (TREE_TYPE (indirect_ptr));
+  var_alias_set = get_alias_set (TREE_TYPE (var));
   
   if (!alias_sets_conflict_p (ptr_alias_set, var_alias_set))
     return false;
@@ -1901,25 +1909,31 @@ may_alias_p (ptr, var_sym)
 }
 
 
-/* Find variables that PTR may be aliasing.  */
+/* Find variables that INDIRECT_PTR (an INDIRECT_REF node) may be aliasing.  */
 
 static void
-find_may_aliases_for (ptr)
-     tree ptr;
+find_may_aliases_for (indirect_ptr)
+     tree indirect_ptr;
 {
   unsigned long i;
 
+#if defined ENABLE_CHECKING
+  if (TREE_CODE (indirect_ptr) != INDIRECT_REF)
+    abort ();
+#endif
+
   for (i = 0; i < num_referenced_vars; i++)
     {
       tree var = referenced_var (i);
-      tree var_sym = get_base_symbol (var);
 
-      if (may_alias_p (ptr, var_sym)
+      /* If *PTR may alias VAR, add *PTR to the list of may-aliases of VAR,
+	 and VAR to the list of may-aliases of *PTR.  */
+      if (may_alias_p (indirect_ptr, var)
 	  /* Avoid adding duplicate aliases.  */
-	  && get_alias_index (ptr, var_sym) == -1)
+	  && get_alias_index (indirect_ptr, var) == -1)
 	{
-	  add_may_alias (ptr, var_sym);
-	  add_may_alias (var_sym, ptr);
+	  add_may_alias (indirect_ptr, var);
+	  add_may_alias (var, indirect_ptr);
 	}
     }
 }
@@ -2074,20 +2088,6 @@ tree_ref_structure (ref)
     return TR_EXPR_REF_COMMON;
 
   abort ();
-}
-
-
-/* Create and return a new INDIRECT_REF for pointer symbol PTR_SYM.  */
-
-static inline tree
-create_indirect_ref (ptr_sym)
-     tree ptr_sym;
-{
-#if defined ENABLE_CHECKING
-  if (!POINTER_TYPE_P (TREE_TYPE (ptr_sym)))
-    abort ();
-#endif
-  return build1 (INDIRECT_REF, TREE_TYPE (TREE_TYPE (ptr_sym)), ptr_sym);
 }
 
 
Index: tree-flow-inline.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/Attic/tree-flow-inline.h,v
retrieving revision 1.1.2.13
diff -d -u -p -r1.1.2.13 tree-flow-inline.h
--- tree-flow-inline.h	7 Nov 2002 15:55:35 -0000	1.1.2.13
+++ tree-flow-inline.h	13 Nov 2002 19:51:54 -0000
@@ -326,7 +326,7 @@ indirect_var (ptr)
      tree ptr;
 {
 #if defined ENABLE_CHECKING
-  if (TREE_CODE_CLASS (TREE_CODE (ptr)) != 'd'
+  if (!DECL_P (ptr)
       || !POINTER_TYPE_P (TREE_TYPE (ptr)))
     abort ();
 #endif
@@ -340,13 +340,24 @@ set_indirect_var (ptr, indirect)
 {
   tree_ann ann;
 #if defined ENABLE_CHECKING
-  if (TREE_CODE_CLASS (TREE_CODE (ptr)) != 'd'
+  if (!DECL_P (ptr)
       || !POINTER_TYPE_P (TREE_TYPE (ptr))
       || TREE_CODE (indirect) != INDIRECT_REF)
     abort ();
 #endif
-  ann = tree_annotation (ptr);
+  ann = tree_annotation (ptr) ? tree_annotation (ptr) : create_tree_ann (ptr);
   ann->indirect_var = indirect;
+}
+
+static inline tree
+create_indirect_ref (ptr_sym)
+     tree ptr_sym;
+{
+#if defined ENABLE_CHECKING
+  if (!POINTER_TYPE_P (TREE_TYPE (ptr_sym)))
+    abort ();
+#endif
+  return build1 (INDIRECT_REF, TREE_TYPE (TREE_TYPE (ptr_sym)), ptr_sym);
 }
 
 static inline bb_ann
Index: tree-flow.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/Attic/tree-flow.h,v
retrieving revision 1.1.4.35
diff -d -u -p -r1.1.4.35 tree-flow.h
--- tree-flow.h	7 Nov 2002 15:55:35 -0000	1.1.4.35
+++ tree-flow.h	13 Nov 2002 19:51:54 -0000
@@ -528,6 +528,7 @@ static inline enum tree_flags tree_flags
 static inline void reset_tree_flags	PARAMS ((tree));
 static inline tree indirect_var		PARAMS ((tree));
 static inline void set_indirect_var	PARAMS ((tree, tree));
+static inline tree create_indirect_ref	PARAMS ((tree));
 static inline tree may_alias		PARAMS ((tree, size_t));
 static inline size_t num_may_alias	PARAMS ((tree));
 static inline int get_lineno		PARAMS ((tree));
Index: tree-ssa-ccp.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/Attic/tree-ssa-ccp.c,v
retrieving revision 1.1.2.31
diff -d -u -p -r1.1.2.31 tree-ssa-ccp.c
--- tree-ssa-ccp.c	8 Nov 2002 01:01:28 -0000	1.1.2.31
+++ tree-ssa-ccp.c	13 Nov 2002 19:51:55 -0000
@@ -348,14 +348,22 @@ visit_phi_node (phi_node)
 	if (e->flags & EDGE_EXECUTABLE)
 	  {
 	    tree_ref rdef;
-	    value rdef_val;
 	    
 	    rdef = phi_arg_def (arg);
 
 	    if (is_killing_def (rdef, phi_node))
 	      {
+		value rdef_val;
+
 		rdef_val = values[ref_id (rdef)];
 		phi_val = cp_lattice_meet (phi_val, rdef_val);
+
+		if (dump_file && (dump_flags & TDF_DETAILS))
+		  {
+		    dump_ref (dump_file, "\t", phi_arg_def (arg), 0, 0);
+		    dump_lattice_value (dump_file, "\tValue: ", rdef_val);
+		    fprintf (dump_file, "\n");
+		  }
 	      }
 	    else
 	      {
@@ -364,13 +372,6 @@ visit_phi_node (phi_node)
 		   its value to VARYING.  */
 		phi_val.lattice_val = VARYING;
 		phi_val.const_value = NULL_TREE;
-	      }
-
-	    if (dump_file && (dump_flags & TDF_DETAILS))
-	      {
-		dump_ref (dump_file, "\t", phi_arg_def (arg), 0, 0);
-		dump_lattice_value (dump_file, "\tValue: ", rdef_val);
-		fprintf (dump_file, "\n");
 	      }
 
 	    if (phi_val.lattice_val == VARYING)
Index: tree-ssa.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/Attic/tree-ssa.c,v
retrieving revision 1.1.4.31
diff -d -u -p -r1.1.4.31 tree-ssa.c
--- tree-ssa.c	8 Nov 2002 01:01:28 -0000	1.1.4.31
+++ tree-ssa.c	13 Nov 2002 19:51:55 -0000
@@ -987,8 +987,10 @@ init_tree_ssa ()
   DECL_EXTERNAL (global_var) = 0;
   TREE_STATIC (global_var) = 0;
   TREE_USED (global_var) = 1;
-  DECL_CONTEXT (global_var) = 0;
+  DECL_CONTEXT (global_var) = NULL_TREE;
   TREE_THIS_VOLATILE (global_var) = 1;
+  TREE_ADDRESSABLE (global_var) = 1;
+  set_indirect_var (global_var, create_indirect_ref (global_var));
 
   /* If -Wuninitialized was used, set tree_warn_uninitialized and clear
      warn_uninitialized to avoid duplicate warnings.  */
Index: testsuite/gcc.c-torture/execute/20021113-1.c
===================================================================
RCS file: testsuite/gcc.c-torture/execute/20021113-1.c
diff -N testsuite/gcc.c-torture/execute/20021113-1.c
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ testsuite/gcc.c-torture/execute/20021113-1.c	13 Nov 2002 19:52:00 -0000
@@ -0,0 +1,17 @@
+/* This program tests a data flow bug that would cause constant propagation
+   to propagate constants through function calls.  */
+
+foo (int *p)
+{
+  *p = 10;
+}
+
+main()
+{
+  int *ptr = alloca (sizeof (int));
+  *ptr = 5;
+  foo (ptr);
+  if (*ptr == 5)
+    abort ();
+  exit (0);
+}


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