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]: Alias analysis update


Now bootstraps with -ftree-points-to=andersen again, and can do limited
interprocedural analysis.

2002-12-29  Daniel Berlin  <dberlin@dberlin.org>

	* toplev.c: Add flag_ip, enable by default at -O4+ (This is not
	set in stone, and thus, not documented).
	(decode_f_option): Add warning if andersen's PTA is selected but
	not compiled in.

	* flags.h: Add flag_ip.

	* tree-alias-ander.c: Fix todo.
	(andersen_function_call): Return 1 if we don't need to process
	the function.
	(ptset_map): New map, cache points-to sets.
	(andersen_op): We can do IP on all statics without help.
	(andersen_init): Only init once if we are doing ip analysis.
	(andersen_cleanup): Don't cleanup if we need the info for ip.
	(andersen_add_var): Clear points-to set if it exists already.
	(andersen_add_var_same): Ditto.
	(andersen_function_call): We can do interprocedural analysis on
	statics.
	(andersen_may_alias): Cache points-to sets.

	* c-decl.c (c_expand_body): Don't throw away tree if flag_ip is
	on, even if they are uninlinable, they may be wanted for ip
	optimizations.

	* tree-alias-common.c (get_values_from_constructor): New
	function to collect alias_typevars from constructors.
	(alias_annot): Fix where the GTY is so gengtype picks it up.
	(intra_function_call): Ignore non-pointers for global var
	assignment. What arguments point to can now point to a global var
	as well.
	(find_func_aliases): We need to handle decl's with initials as
	well.
	Only call intra_function_call if we have to.
	Handle constructors.
	(create_fun_alias_var): Incoming pointer arguments could be
	pointing to a global var, unless this is a static function and we
	are doing interprocedural analysis.
	(create_alias_vars): Take an fndecl argument, and use it.
	(init_alias_vars): Handle ip_partial as well.
	(ptr_may_alias_var): Simplify, fix.

	* tree-alias-common.h (tree_alias_ops): function_call now returns
	an int, and we have an extra member named ip_partial.

	* tree-alias-steen.c (steen_ops): We can't do ip_partial.
	(steen_function_call): Update definition and return 1.

	* tree-dfa.c (compute_may_aliases): Call create_alias_vars with
	current_function_decl.

	* tree-flow.h (create_alias_vars): Remove proto from here, it's
	in tree-alias-common.h.
	(tree_perform_ssapre): Take a tree, like the other optimizers.

	* tree-optimize.c (optimize_function_tree): Call
	tree_perform_ssapre with a tree.

	* tree-ssa-pre.c: Remove dead, #if 0'd code.
	(tree_perform_ssapre): Use passed in tree.

Index: c-decl.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/c-decl.c,v
retrieving revision 1.334.2.29
diff -u -3 -p -r1.334.2.29 c-decl.c
--- c-decl.c	17 Dec 2002 20:46:19 -0000	1.334.2.29
+++ c-decl.c	29 Dec 2002 21:52:09 -0000
@@ -6556,7 +6556,7 @@ c_expand_body (fndecl, nested_p, can_def
   else
     expand_expr_stmt_value (DECL_SAVED_TREE (fndecl), 0, 0);

-  if (uninlinable)
+  if (uninlinable && !flag_ip)
     {
       /* Allow the body of the function to be garbage collected.  */
       DECL_SAVED_TREE (fndecl) = NULL_TREE;
Index: flags.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/flags.h,v
retrieving revision 1.86.2.14
diff -u -3 -p -r1.86.2.14 flags.h
--- flags.h	5 Nov 2002 23:50:37 -0000	1.86.2.14
+++ flags.h	29 Dec 2002 21:52:10 -0000
@@ -659,14 +659,20 @@ extern int flag_mudflap;
 /* Disable tree simplification.  */
 extern int flag_disable_simple;

-/* Enable the SSA-PRE on trees.  */
+/* Enable SSA-PRE on trees.  */
 extern int flag_tree_pre;

+/* Enable SSA-CP on trees. */
+extern int flag_tree_cp;
+
 /* Enable SSA-CCP on trees.  */
 extern int flag_tree_ccp;

 /* Enable SSA-DCE on trees.  */
 extern int flag_tree_dce;
+
+/* Enable interprocedural analysis.  */
+extern int flag_ip;

 /* Nonzero means put zero initialized data in the bss section.  */
 extern int flag_zero_initialized_in_bss;
Index: toplev.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/toplev.c,v
retrieving revision 1.654.2.36
diff -u -3 -p -r1.654.2.36 toplev.c
--- toplev.c	27 Dec 2002 01:51:22 -0000	1.654.2.36
+++ toplev.c	29 Dec 2002 21:52:12 -0000
@@ -897,9 +897,15 @@ enum pta_type flag_tree_points_to = PTA_
 /* Enable SSA-CCP on trees.  */
 int flag_tree_ccp = 0;

+/* Enable SSA-CP on trees.  */
+int flag_tree_cp = 0;
+
 /* Enable SSA-DCE on trees.  */
 int flag_tree_dce = 0;

+/* Enable interprocedural analysis.  */
+int flag_ip = 0;
+
 /* Nonzero if we perform superblock formation.  */
 int flag_tracer = 0;

@@ -1216,8 +1222,12 @@ static const lang_independent_options f_
    N_("Enable SSA-PRE optimization on trees") },
   { "tree-ccp", &flag_tree_ccp, 1,
    N_("Enable SSA-CCP optimization on trees") },
+  { "tree-cp", &flag_tree_cp, 1,
+   N_("Enable SSA-CP optimization on trees") },
   { "tree-dce", &flag_tree_dce, 1,
    N_("Enable SSA dead code elimination optimization on trees") },
+  { "ip", &flag_ip, 1,
+   N_("Enable interprocedural analysis") },
 };

 /* Table of language-specific options.  */
@@ -3034,6 +3044,7 @@ rest_of_compilation (decl)
 	estimate_probability (&loops);

       flow_loops_free (&loops);
+
       close_dump_file (DFI_bp, print_rtl_with_bb, insns);
       timevar_pop (TV_BRANCH_PROB);
     }
@@ -3995,7 +4006,13 @@ decode_f_option (arg)
       if (strcmp (option_value, "steen") == 0)
         flag_tree_points_to = PTA_STEEN;
       else if (strcmp (option_value, "andersen") == 0)
+	{
+#ifdef HAVE_BANSHEE
         flag_tree_points_to = PTA_ANDERSEN;
+#else
+	warning ("Andersen's PTA not available - libbanshee not compiled.");
+#endif
+	}
       else
         warning ("`%s`: unknown points-to analysis algorithm", arg - 2);
     }
@@ -4753,7 +4770,6 @@ general_init (argv0)
   hex_init ();

   gcc_init_libintl ();
-
   /* Trap fatal signals, e.g. SIGSEGV, and convert them to ICE messages.  */
 #ifdef SIGSEGV
   signal (SIGSEGV, crash_signal);
@@ -4773,7 +4789,6 @@ general_init (argv0)
 #ifdef SIGFPE
   signal (SIGFPE, crash_signal);
 #endif
-
   /* Initialize the diagnostics reporting machinery, so option parsing
      can give warnings and errors.  */
   diagnostic_initialize (global_dc);
@@ -4898,6 +4913,11 @@ parse_options_and_default_flags (argc, a
     {
       flag_inline_functions = 1;
       flag_rename_registers = 1;
+    }
+
+  if  (optimize >= 4)
+    {
+      flag_ip = 1;
     }

   if (optimize < 2 || optimize_size)
Index: tree-alias-ander.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/Attic/tree-alias-ander.c,v
retrieving revision 1.1.2.5
diff -u -3 -p -r1.1.2.5 tree-alias-ander.c
--- tree-alias-ander.c	3 Dec 2002 22:54:32 -0000	1.1.2.5
+++ tree-alias-ander.c	29 Dec 2002 21:52:12 -0000
@@ -57,8 +57,8 @@ Foundation, Inc., 59 Temple Place, Suite
    Andersen's interprocedural points-to analysis.
    This is a flow-insensitive, context insensitive algorithm.

-   @todo {Don't pass alias ops as first argument, just have a global
-   "current_alias_ops".}
+   @todo Don't pass alias ops as first argument, just have a global
+   "current_alias_ops".
 */

 static unsigned int id_num = 1;
@@ -80,7 +80,7 @@ static void andersen_assign_ptr PARAMS (
 static void andersen_function_def PARAMS ((struct tree_alias_ops *,
 					   alias_typevar, varray_type,
 					   alias_typevar));
-static void andersen_function_call PARAMS ((struct tree_alias_ops *,
+static int andersen_function_call PARAMS ((struct tree_alias_ops *,
 					    alias_typevar, alias_typevar,
 					    varray_type));
 static void andersen_init PARAMS ((struct tree_alias_ops *));
@@ -90,7 +90,31 @@ static bool andersen_may_alias PARAMS ((
 					alias_typevar, alias_typevar));
 static alias_typevar andersen_add_var PARAMS ((struct tree_alias_ops *, tree));
 static alias_typevar andersen_add_var_same PARAMS ((struct tree_alias_ops *, tree, alias_typevar));
+static hashval_t ptset_map_hash PARAMS ((const PTR));
+static int ptset_map_eq PARAMS ((const PTR, const PTR));
+
 static splay_tree ptamap;
+static htab_t ptset_map;
+
+#define POINTER_HASH(x) (hashval_t)((long)x >> 3)
+struct ptset_map_data
+{
+  tree decl;
+  aterm_list ptset;
+};
+static hashval_t
+ptset_map_hash (p)
+     const PTR p;
+{
+  return POINTER_HASH (((struct ptset_map_data *)p)->decl);
+}
+static int
+ptset_map_eq (p1, p2)
+     const PTR p1;
+     const PTR p2;
+{
+  return ((struct ptset_map_data *)p1)->decl == p2;
+}

 static struct tree_alias_ops andersen_ops = {
   andersen_init,
@@ -106,8 +130,9 @@ static struct tree_alias_ops andersen_op
   andersen_function_def,
   andersen_function_call,
   andersen_may_alias,
-  0,				/* data */
-  0				/* Currently non-interprocedural */
+  0, /* data */
+  0, /* Currently non-interprocedural */
+  1  /* Can do IP on all statics without help. */
 };
 struct tree_alias_ops *andersen_alias_ops = &andersen_ops;

@@ -387,18 +412,27 @@ pta_get_ptsize (t)
   return aterm_list_length (ptset);
 }

-/* Initialize Andersen alias analysis.
-   Currently does nothing.  */
+/* Initialize Andersen alias analysis. */
+static int initted = 0;
+
 static void
 andersen_init (ops)
      struct tree_alias_ops *ops ATTRIBUTE_UNUSED;
 {
-  pta_init ();
-  flag_eliminate_cycles = 1;
-  flag_merge_projections = 1;
+  if (!initted || !flag_ip)
+    {
+      pta_init ();
+      andersen_rgn = newregion ();
+      initted = 1;
+    }
+
   dump_file = dump_begin (TDI_pta, &dump_flags);
   ptamap = splay_tree_new (splay_tree_compare_pointers, NULL, NULL);
-  andersen_rgn = newregion ();
+  ptset_map = htab_create (7, ptset_map_hash, ptset_map_eq, free);
+  /* Don't claim we can do ip partial unless the user requests it. */
+  if (!flag_ip)
+    andersen_ops.ip_partial = 0;
+
 }

 static int
@@ -442,9 +476,14 @@ andersen_cleanup (ops)
     }


-  pta_reset ();
-  splay_tree_delete (ptamap);
-  deleteregion (andersen_rgn);
+  if (!flag_ip)
+    {
+      pta_reset ();
+      splay_tree_delete (ptamap);
+      htab_delete (ptset_map);
+      deleteregion (andersen_rgn);
+    }
+

 }

@@ -458,6 +497,7 @@ andersen_add_var (ops, decl)
      tree decl;
 {
   alias_typevar ret;
+  PTR *slot;
   if (dump_file && (dump_flags & TDF_DETAILS))
     fprintf (dump_file, "Adding variable %s\n",
 	     alias_get_name (decl));
@@ -475,6 +515,13 @@ andersen_add_var (ops, decl)
     }
   splay_tree_insert (ptamap, (splay_tree_key) ALIAS_TVAR_ATERM (ret),
 		     (splay_tree_value) ret);
+  slot = htab_find_slot_with_hash (ptset_map,
+				   decl,
+				   POINTER_HASH (decl),
+				   NO_INSERT);
+  if (slot)
+    htab_clear_slot (ptset_map, slot);
+
   return ret;
 }

@@ -488,6 +535,8 @@ andersen_add_var_same (ops, decl, tv)
      alias_typevar tv;
 {
   alias_typevar ret;
+  PTR *slot;
+
   if (dump_file && (dump_flags & TDF_DETAILS))
     fprintf (dump_file, "Adding variable %s same as %s\n",
 	     alias_get_name (decl), alias_get_name (ALIAS_TVAR_DECL (tv)));
@@ -505,6 +554,20 @@ andersen_add_var_same (ops, decl, tv)
   pta_join (ALIAS_TVAR_ATERM (tv), ALIAS_TVAR_ATERM (ret));
   splay_tree_insert (ptamap, (splay_tree_key) ALIAS_TVAR_ATERM (ret),
 		     (splay_tree_value) ret);
+  slot = htab_find_slot_with_hash (ptset_map,
+				   decl,
+				   POINTER_HASH (decl),
+				   NO_INSERT);
+  if (slot)
+    htab_clear_slot (ptset_map, slot);
+
+  slot = htab_find_slot_with_hash (ptset_map,
+				   ALIAS_TVAR_DECL (tv),
+				   POINTER_HASH (ALIAS_TVAR_DECL (tv)),
+				   NO_INSERT);
+  if (slot)
+    htab_clear_slot (ptset_map, slot);
+
   return ret;
 }

@@ -645,13 +708,13 @@ andersen_function_def (ops, func, params
       alias_typevar tv = VARRAY_GENERIC_PTR (params, i);
       aterm_list_cons (ALIAS_TVAR_ATERM (tv), args);
     }
-  fun_type = pta_make_fun (get_name (ALIAS_TVAR_DECL (func)),
+  fun_type = pta_make_fun (alias_get_name (ALIAS_TVAR_DECL (func)),
 			   ALIAS_TVAR_ATERM (retval), args);
   pta_assignment (ALIAS_TVAR_ATERM (func), fun_type);
 }

 /* Inference for a function call assignment */
-static void
+static int
 andersen_function_call (ops, lhs, func, args)
      struct tree_alias_ops *ops ATTRIBUTE_UNUSED;
      alias_typevar lhs;
@@ -662,6 +725,8 @@ andersen_function_call (ops, lhs, func,
   aterm ftype = ALIAS_TVAR_ATERM (func);
   aterm ret = NULL;
   aterm res;
+  tree decl = ALIAS_TVAR_DECL (func);
+
   size_t i;

   if (lhs)
@@ -673,9 +738,22 @@ andersen_function_call (ops, lhs, func,
       aterm_list_cons (pta_rvalue (arg), actuals);
     }
   aterm_list_reverse (actuals);
+
   res = pta_application (pta_rvalue (ftype), actuals);
   if (ret)
     pta_assignment (ret, pta_rvalue (res));
+
+  /* We can handle functions we've got trees for. non-statics will
+     just have incoming parameters assigned to global_var if
+     necessary. */
+  if (TREE_CODE (decl) == FUNCTION_DECL
+      && DECL_SAVED_TREE (decl) != NULL_TREE
+      && flag_ip
+      && (!TREE_PUBLIC (decl) && TREE_STATIC (decl)))
+    {
+      return 0;
+    }
+  return 1;
 }


@@ -695,8 +773,26 @@ andersen_may_alias (ops, ptrtv, vartv)
      alias_typevar vartv;
 {
   aterm_list ptset;
-
-  ptset = aterm_tlb (pta_get_contents (ALIAS_TVAR_ATERM (ptrtv)));
+  struct ptset_map_data *data;
+
+  data = htab_find_with_hash (ptset_map, ALIAS_TVAR_DECL (ptrtv),
+			      POINTER_HASH (ALIAS_TVAR_DECL (ptrtv)));
+
+  if (!data)
+    {
+      ptset = aterm_tlb (pta_get_contents (ALIAS_TVAR_ATERM (ptrtv)));
+      data = xmalloc (sizeof (struct ptset_map_data));
+      data->decl = ALIAS_TVAR_DECL (ptrtv);
+      data->ptset = ptset;
+      *(htab_find_slot_with_hash (ptset_map,
+				  ALIAS_TVAR_DECL (ptrtv),
+				  POINTER_HASH (ALIAS_TVAR_DECL (ptrtv)),
+				  INSERT)) = data;
+    }
+  else
+    {
+      ptset = data->ptset;
+    }

   if (aterm_list_empty (ptset))
     return false;
Index: tree-alias-common.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/Attic/tree-alias-common.c,v
retrieving revision 1.1.2.12
diff -u -3 -p -r1.1.2.12 tree-alias-common.c
--- tree-alias-common.c	3 Dec 2002 22:54:32 -0000	1.1.2.12
+++ tree-alias-common.c	29 Dec 2002 21:52:12 -0000
@@ -88,6 +88,7 @@ static alias_typevar create_alias_var PA
 static void intra_function_call PARAMS ((varray_type));
 static hashval_t annot_hash PARAMS ((const PTR));
 static int annot_eq PARAMS ((const PTR, const PTR));
+static void get_values_from_constructor PARAMS ((tree, varray_type *));

 /**
    @brief Alias annotation hash table entry.
@@ -136,7 +137,7 @@ annot_hash (pentry)

    Maps vars to alias_typevars.
 */
-htab_t GTY ((param_is (struct alias_annot_entry))) alias_annot;
+static GTY ((param_is (struct alias_annot_entry))) htab_t alias_annot;

 /**
    @brief Get the alias_type for a *_DECL.
@@ -294,14 +295,26 @@ intra_function_call (args)
   for (i = 0; i < l; i++)
     {
       alias_typevar argav = VARRAY_GENERIC_PTR (args, i);
-
+       if (!POINTER_TYPE_P (TREE_TYPE (ALIAS_TVAR_DECL (argav))))
+         continue;
       /* Restricted pointers can't be aliased with other
 	 restricted pointers. */
       if (!TYPE_RESTRICT (TREE_TYPE (ALIAS_TVAR_DECL (argav)))
 	  || !TYPE_RESTRICT (TREE_TYPE (ALIAS_TVAR_DECL (av))))
-	current_alias_ops->addr_assign (current_alias_ops, argav, av);
+	{
+	  alias_typevar tempvar;
+	  tempvar = current_alias_ops->add_var (current_alias_ops,
+						create_tmp_alias_var
+						(void_type_node,
+						 "aliastmp"));
+	  /* Arguments can alias globals, and whatever they point to
+	     can point to a global as well. */
+	  current_alias_ops->addr_assign (current_alias_ops, argav, av);
+	  current_alias_ops->addr_assign (current_alias_ops, tempvar, av);
+	  current_alias_ops->assign_ptr (current_alias_ops, argav, tempvar);
+
+	}
     }
-
   /* We assume assignments among the actual parameters. */
   for (i = 0; i < l; i++)
     {
@@ -323,6 +336,54 @@ intra_function_call (args)
     }
 }

+/** @brief Put all pointers in a constructor in an array.
+ */
+static void
+get_values_from_constructor (constructor, vals)
+  tree constructor;
+  varray_type *vals;
+{
+#if FIELD_BASED
+ #error "Don't know how to do this at the moment"
+#else
+  tree elt_list;
+  switch (TREE_CODE (constructor))
+    {
+    case CONSTRUCTOR:
+      {
+	for (elt_list = CONSTRUCTOR_ELTS (constructor);
+	     elt_list;
+	     elt_list = TREE_CHAIN (elt_list))
+	  {
+	    tree value = TREE_VALUE (elt_list);
+	    if (TREE_CODE (value) == TREE_LIST
+		|| TREE_CODE (value) == CONSTRUCTOR)
+	      {
+		get_values_from_constructor (value, vals);
+	      }
+	    else
+	      {
+		alias_typevar aav;
+		aav = get_alias_var (value);
+		if (aav)
+		  VARRAY_PUSH_GENERIC_PTR (*vals, aav);
+	      }
+	  }
+      }
+      break;
+    case TREE_LIST:
+      for (elt_list = constructor;
+	   elt_list;
+	   elt_list = TREE_CHAIN (elt_list))
+	{
+	  get_values_from_constructor (TREE_VALUE (elt_list), vals);
+	}
+      break;
+    default:
+      abort();
+    }
+#endif
+}
 /**
    @brief Tree walker that is the heart of the aliasing
    infrastructure.
@@ -351,14 +412,24 @@ find_func_aliases (tp, walk_subtrees, da
       return NULL_TREE;
     }

-  if (is_simple_modify_expr (stp))
+  if (is_simple_modify_expr (stp)
+      || (TREE_CODE (stp) == VAR_DECL
+	  && DECL_INITIAL (stp) != NULL_TREE ))
     {
       tree op0, op1;
       alias_typevar lhsAV = NULL;
       alias_typevar rhsAV = NULL;
-
-      op0 = TREE_OPERAND (stp, 0);
-      op1 = TREE_OPERAND (stp, 1);
+
+      if (TREE_CODE (stp) == VAR_DECL)
+	{
+	  op0 = stp;
+	  op1 = DECL_INITIAL (stp);
+	}
+      else
+	{
+	  op0 = TREE_OPERAND (stp, 0);
+	  op1 = TREE_OPERAND (stp, 1);
+	}
       STRIP_WFL (op0);
       STRIP_WFL (op1);
       /* lhsAV should always have an alias variable */
@@ -439,47 +510,59 @@ find_func_aliases (tp, walk_subtrees, da
 		  if (TREE_CODE (callop0) == ADDR_EXPR)
 		    create_fun_alias_var (TREE_OPERAND (callop0, 0), 0);

-		  current_alias_ops->function_call (current_alias_ops, lhsAV,
+		  if (current_alias_ops->function_call (current_alias_ops, lhsAV,
 						    get_alias_var (callop0),
-						    args);
-		  if (!current_alias_ops->ip)
-		    intra_function_call (args);
-	      *walk_subtrees = 0;
+						    args))
+		    if (!current_alias_ops->ip
+			&& ! (call_expr_flags (op1) & ECF_NORETURN))
+		      intra_function_call (args);
+		  *walk_subtrees = 0;
 		}

 	    }
 	  /* x = op (...) */
 	  else
 	    {
-	      switch (TREE_CODE_CLASS (TREE_CODE (op1)))
-		{
-		case 'e':  /* an expression */
-		case 's':  /* an expression with side effects */
-		case '<':  /* a comparison expression */
-		case '1':  /* a unary arithmetic expression */
-		case 'r':  /* a reference */
-		case '2':  /* a binary arithmetic expression */
+	      if (TREE_CODE (op1) == CONSTRUCTOR)
+	        {
+		  varray_type ops;
+		  int i;
+		  VARRAY_GENERIC_PTR_INIT (ops, 1, "Operands");
+		  get_values_from_constructor (op1, &ops);
+		  current_alias_ops->op_assign (current_alias_ops, lhsAV,
+						ops);
+		  *walk_subtrees = 0;
+		}
+	      else
+		switch (TREE_CODE_CLASS (TREE_CODE (op1)))
 		  {
-		    tree op;
-		    varray_type ops;
-		    int i;
-		    VARRAY_GENERIC_PTR_INIT (ops, 1, "Operands");
-		    for (i=0; i < TREE_CODE_LENGTH (TREE_CODE (op1)); i++)
-		      {
-			alias_typevar aav;
-			op = TREE_OPERAND (op1, i);
-			aav = get_alias_var (op);
-			if (aav)
-			  VARRAY_PUSH_GENERIC_PTR (ops, aav);
-		      }
-		    current_alias_ops->op_assign (current_alias_ops, lhsAV,
-						  ops);
-	      *walk_subtrees = 0;
+		  case 'e':  /* an expression */
+		  case 's':  /* an expression with side effects */
+		  case '<':  /* a comparison expression */
+		  case '1':  /* a unary arithmetic expression */
+		  case 'r':  /* a reference */
+		  case '2':  /* a binary arithmetic expression */
+		    {
+		      tree op;
+		      varray_type ops;
+		      int i;
+		      VARRAY_GENERIC_PTR_INIT (ops, 1, "Operands");
+		      for (i=0; i < TREE_CODE_LENGTH (TREE_CODE (op1)); i++)
+			{
+			  alias_typevar aav;
+			  op = TREE_OPERAND (op1, i);
+			  aav = get_alias_var (op);
+			  if (aav)
+			    VARRAY_PUSH_GENERIC_PTR (ops, aav);
+			}
+		      current_alias_ops->op_assign (current_alias_ops, lhsAV,
+						    ops);
+		      *walk_subtrees = 0;
+		    }
+		    break;
+		  default:
+		    break;
 		  }
-		  break;
-		default:
-		  break;
-		}
 	    }
 	}
       /* *x = <something> */
@@ -553,7 +636,7 @@ find_func_aliases (tp, walk_subtrees, da
 					     tempvar);
 	      *walk_subtrees = 0;
 	    }
-	  /* *x = <something else */
+	  /* *x = <something else> */
 	  else
 	    {
 	      if (rhsAV != NULL)
@@ -577,11 +660,13 @@ find_func_aliases (tp, walk_subtrees, da
 	}
       if (TREE_CODE (TREE_OPERAND (stp, 0)) == ADDR_EXPR)
 	create_fun_alias_var (TREE_OPERAND (TREE_OPERAND (stp, 0), 0), 0);
-      current_alias_ops->function_call (current_alias_ops, NULL,
+
+      if (current_alias_ops->function_call (current_alias_ops, NULL,
 				      get_alias_var (TREE_OPERAND (stp, 0)),
-				      args);
-      if (!current_alias_ops->ip)
-	intra_function_call (args);
+				      args))
+	if (!current_alias_ops->ip
+	    && ! (call_expr_flags (stp) & ECF_NORETURN))
+	  intra_function_call (args);
       *walk_subtrees = 0;
   }
   return NULL_TREE;
@@ -654,6 +739,18 @@ create_fun_alias_var (decl, force)
 	  *slot = newentry;

 	  VARRAY_PUSH_GENERIC_PTR (params, tvar);
+	  /* Incoming pointers can point to global_var, unless
+	     either we are interprocedural, or we can do ip on all
+	     statics + this function has been defined + it's not an
+	     external function. */
+	  if (POINTER_TYPE_P (TREE_TYPE (arg))
+	      && !current_alias_ops->ip
+	      /* FIXME: Need to let analyzer decide in partial case. */
+	      && (!current_alias_ops->ip_partial
+		  || !TREE_STATIC (decl)
+		  || TREE_PUBLIC (decl)))
+	    current_alias_ops->addr_assign (current_alias_ops, tvar,
+				  	    get_alias_var (global_var));
 	}
     }
   else if (TYPE_ARG_TYPES (TREE_TYPE (decl)) != NULL)
@@ -666,7 +763,20 @@ create_fun_alias_var (decl, force)
 	{
 	  tree fakedecl = create_tmp_alias_var (TREE_VALUE (arg), "normarg");
 	  alias_typevar tvar = create_alias_var (fakedecl);
-	  VARRAY_PUSH_GENERIC_PTR (params, tvar);
+	  VARRAY_PUSH_GENERIC_PTR (params, tvar);
+
+	  /* Incoming pointers can point to global_var, unless
+	     either we are interprocedural, or we can do ip on all
+	     statics + this function has been defined + it's not an
+	     external function. */
+	  if (POINTER_TYPE_P (TREE_TYPE (fakedecl))
+	      && !current_alias_ops->ip
+	      /* FIXME: need to let analyzer decide in partial case. */
+	      && (!current_alias_ops->ip_partial
+		  || !TREE_STATIC (decl)
+		  || TREE_PUBLIC (decl)))
+	    current_alias_ops->addr_assign (current_alias_ops, tvar,
+					    get_alias_var (global_var));
 	}
     }
   /* Functions declared like void f() are *not* equivalent to void
@@ -814,8 +924,7 @@ create_alias_var (decl)
   *slot = newentry;

   VARRAY_PUSH_GENERIC_PTR (alias_vars, avar);
-
-  /* FIXME: Add the annotation to all extern definitions of this variable. */
+
   return avar;
 }

@@ -843,9 +952,14 @@ display_points_to_set_helper (tvar)

 /**
    @brief Create points-to sets for a function.
+   @param fndecl Function we are creating alias variables for.
+
+   @note fndecl might not be current_function_decl, if we are in ip
+   mode or ip'ing all statics.
 */
 void
-create_alias_vars ()
+create_alias_vars (fndecl)
+	tree fndecl;
 {
 #if 0
   tree currdecl = getdecls ();
@@ -862,17 +976,23 @@ create_alias_vars ()
 #else
   current_alias_ops = steen_alias_ops;
 #endif
-  init_alias_vars ();
-  create_fun_alias_var (current_function_decl, 1);
+
+  /* If fndecl is current_function_decl, we are at the top level. */
+  if (fndecl  == current_function_decl)
+    init_alias_vars ();
+
+  /* Don't force creation unless we are processing the top level
+     function decl. */
+  create_fun_alias_var (fndecl, fndecl == current_function_decl);
   /* For debugging, disable the on-the-fly variable creation,
      and reenable this. */
-  /*  walk_tree_without_duplicates (&DECL_SAVED_TREE (current_function_decl),
+  /*  walk_tree_without_duplicates (&DECL_SAVED_TREE (fndecl),
       find_func_decls, NULL);*/
-  walk_tree_without_duplicates (&DECL_SAVED_TREE (current_function_decl),
+  walk_tree_without_duplicates (&DECL_SAVED_TREE (fndecl),
 				find_func_aliases, NULL);
 #if 0
   fprintf (stderr, "\nOriginal points to sets for function %s:\n",
-	   IDENTIFIER_POINTER (DECL_NAME (current_function_decl)));
+	   IDENTIFIER_POINTER (DECL_NAME (fndecl)));
   for (i = 0; i < VARRAY_ACTIVE_SIZE (alias_vars); i++)
      display_points_to_set_helper (VARRAY_GENERIC_PTR (alias_vars, i));
 #endif
@@ -915,9 +1035,9 @@ init_alias_vars ()
   current_alias_ops->init (current_alias_ops);
   VARRAY_GENERIC_PTR_INIT (local_alias_vars, 10, "Local alias vars");
   VARRAY_INT_INIT (local_alias_varnums, 10, "Local alias varnums");
-  if (!current_alias_ops->ip || alias_vars == NULL)
+  if ((!current_alias_ops->ip && !current_alias_ops->ip_partial) || alias_vars == NULL)
     VARRAY_GENERIC_PTR_INIT (alias_vars, 10, "Alias vars");
-  if (!current_alias_ops->ip || alias_annot == NULL)
+  if ((!current_alias_ops->ip && !current_alias_ops->ip_partial) || alias_annot == NULL)
     alias_annot = htab_create_ggc (7, annot_hash, annot_eq, NULL);

 }
@@ -946,39 +1066,46 @@ ptr_may_alias_var (ptr, var)
   if (TREE_CODE (var) == COMPONENT_REF)
     var = TREE_OPERAND (var, 1);
 #endif
+  if (ptr == var)
+    return true;
+
   entry.key = ptr;
   result = htab_find (alias_annot, &entry);
+
   if (!result
-      && (TREE_PUBLIC (ptr) || TREE_STATIC (ptr))
-      && TREE_CODE (ptr) != FUNCTION_DECL)
+      && decl_function_context (ptr) == NULL)
     {
       entry.key = global_var;
       result = htab_find (alias_annot, &entry);
     }

-  if (!result && !AGGREGATE_TYPE_P (TREE_TYPE (ptr)))
+  if (!result && !current_alias_ops->ip && ptr != global_var)
     abort ();
+
   else if (!result)
     return false;
-
+
   ptrtv = result->value;
   entry.key = var;
   result = htab_find (alias_annot, &entry);
-
-  if (!result && (TREE_PUBLIC (var) || TREE_STATIC (var))
-      && TREE_CODE (var) != FUNCTION_DECL)
+
+  if (!result
+      && decl_function_context (var) == NULL)
     {
       entry.key = global_var;
       result = htab_find (alias_annot, &entry);
     }

-  if (!result && !AGGREGATE_TYPE_P (TREE_TYPE (var)))
+  if (!result && !current_alias_ops->ip && var != global_var)
     abort ();
   else if (!result)
     return false;
-

   vartv = result->value;
+
+  if (ptrtv == vartv)
+    return true;
+
   return current_alias_ops->may_alias (current_alias_ops, ptrtv, vartv);

 }
@@ -987,7 +1114,8 @@ const char *
 alias_get_name (t)
      tree t;
 {
-
+  const char *name;
+
 #if FIELD_BASED
   if (TREE_CODE (t) == FIELD_DECL)
     {
@@ -999,19 +1127,24 @@ alias_get_name (t)
       size_t neededlen = strlen (fieldname) + strlen (prefix) + 2;
       smashed = ggc_alloc (neededlen);
       sprintf (smashed, "%s.%s", prefix, fieldname);
-      return smashed;
+      name = smashed;

     }
   else if (TYPE_P (t))
     {
       if (TYPE_NAME (t) && IDENTIFIER_POINTER (TYPE_NAME (t)))
-	return IDENTIFIER_POINTER (TYPE_NAME (t));
+	name = IDENTIFIER_POINTER (TYPE_NAME (t));
       else
-	return "<unnamed type>";
+	name = "<unnamed type>";
     }
   else
 #endif
-    return get_name (t);
+    name = get_name (t);
+
+  if (!name)
+    return name;
+
+  return name;
 }
-
+
 #include "gt-tree-alias-common.h"
Index: tree-alias-common.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/Attic/tree-alias-common.h,v
retrieving revision 1.1.2.4
diff -u -3 -p -r1.1.2.4 tree-alias-common.h
--- tree-alias-common.h	29 Nov 2002 02:03:22 -0000	1.1.2.4
+++ tree-alias-common.h	29 Dec 2002 21:52:12 -0000
@@ -100,9 +100,11 @@ struct tree_alias_ops

   /**
      @brief Process a function call
+     @return Return 1 if we need to assume conservative side-effects.
+
   */
-  void (*function_call) (struct tree_alias_ops *, alias_typevar,
-			 alias_typevar, varray_type);
+  int (*function_call) (struct tree_alias_ops *, alias_typevar,
+			alias_typevar, varray_type);

   /**
      @brief Determine if two typevars may alias
@@ -114,10 +116,13 @@ struct tree_alias_ops
   */
   void *data;
   int ip:1; /*Interprocedural */
+  int ip_partial:1; /* Can do conservative interprocedural
+		       analysis if we save the info.*/
+
 };

 extern struct tree_alias_ops *current_alias_ops;
-extern void create_alias_vars PARAMS ((void));
+extern void create_alias_vars PARAMS ((tree));
 extern void delete_alias_vars PARAMS ((void));
 extern void init_alias_vars PARAMS ((void));
 extern bool ptr_may_alias_var PARAMS ((tree, tree));
Index: tree-alias-steen.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/Attic/tree-alias-steen.c,v
retrieving revision 1.1.2.14
diff -u -3 -p -r1.1.2.14 tree-alias-steen.c
--- tree-alias-steen.c	3 Dec 2002 22:54:32 -0000	1.1.2.14
+++ tree-alias-steen.c	29 Dec 2002 21:52:12 -0000
@@ -96,7 +96,7 @@ static void steen_assign_ptr PARAMS ((st
 static void steen_function_def PARAMS ((struct tree_alias_ops *,
 					alias_typevar, varray_type,
 					alias_typevar));
-static void steen_function_call PARAMS ((struct tree_alias_ops *,
+static int steen_function_call PARAMS ((struct tree_alias_ops *,
 					 alias_typevar, alias_typevar,
 					 varray_type));
 static void steen_init PARAMS ((struct tree_alias_ops *));
@@ -121,7 +121,8 @@ static struct tree_alias_ops steen_ops =
   steen_function_call,
   steen_may_alias,
   0, /* data */
-  0 /* Currently non-interprocedural */
+  0, /* Currently non-interprocedural */
+  0 /* Can't do IP on all statics without help. */
 };
 struct tree_alias_ops *steen_alias_ops = &steen_ops;

@@ -490,7 +491,7 @@ steen_function_def (ops, func, params, r
 }

 /* Inference for a function call assignment */
-static void
+static int
 steen_function_call (ops, lhs, func, args)
      struct tree_alias_ops *ops ATTRIBUTE_UNUSED;
      alias_typevar lhs;
@@ -568,6 +569,7 @@ steen_function_call (ops, lhs, func, arg
       if (!ECR_equiv (lambda1, lambda2))
 	ECR_cjoin (lambda1, lambda2);
     }
+  return 1;
 }

 static bool
Index: tree-dfa.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/Attic/tree-dfa.c,v
retrieving revision 1.1.4.61
diff -u -3 -p -r1.1.4.61 tree-dfa.c
--- tree-dfa.c	23 Dec 2002 15:42:39 -0000	1.1.4.61
+++ tree-dfa.c	29 Dec 2002 21:52:13 -0000
@@ -2179,7 +2179,7 @@ compute_may_aliases ()
   if (flag_tree_points_to != PTA_NONE && num_referenced_vars)
     {
       timevar_push (TV_TREE_PTA);
-      create_alias_vars ();
+      create_alias_vars (current_function_decl);
       timevar_pop (TV_TREE_PTA);
     }

Index: tree-flow.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/Attic/tree-flow.h,v
retrieving revision 1.1.4.41
diff -u -3 -p -r1.1.4.41 tree-flow.h
--- tree-flow.h	11 Dec 2002 19:47:50 -0000	1.1.4.41
+++ tree-flow.h	29 Dec 2002 21:52:13 -0000
@@ -715,13 +715,11 @@ extern void debug_reaching_defs		PARAMS
 extern void dump_tree_ssa		PARAMS ((FILE *));
 extern void debug_tree_ssa		PARAMS ((void));

-
-/* In tree-alias-steen.c  */
-extern void create_alias_vars		PARAMS ((void));
-
+/* In tree-loop.c  */
+extern struct loops *tree_find_loops PARAMS ((tree));

 /* In tree-ssa-pre.c  */
-extern void tree_perform_ssapre PARAMS ((void));
+extern void tree_perform_ssapre PARAMS ((tree));


 /* In tree-ssa-ccp.c  */
Index: tree-optimize.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/Attic/tree-optimize.c,v
retrieving revision 1.1.4.27
diff -u -3 -p -r1.1.4.27 tree-optimize.c
--- tree-optimize.c	18 Dec 2002 03:58:55 -0000	1.1.4.27
+++ tree-optimize.c	29 Dec 2002 21:52:13 -0000
@@ -88,13 +88,14 @@ optimize_function_tree (fndecl)
       build_tree_ssa (fndecl);

       if (flag_tree_pre)
-	tree_perform_ssapre ();
+	tree_perform_ssapre (fndecl);

       if (flag_tree_ccp)
 	tree_ssa_ccp (fndecl);

       if (flag_tree_dce)
 	tree_ssa_eliminate_dead_code (fndecl);
+
     }

 #if 0
Index: tree-ssa-pre.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/Attic/tree-ssa-pre.c,v
retrieving revision 1.1.4.40
diff -u -3 -p -r1.1.4.40 tree-ssa-pre.c
--- tree-ssa-pre.c	3 Dec 2002 22:54:34 -0000	1.1.4.40
+++ tree-ssa-pre.c	29 Dec 2002 21:52:14 -0000
@@ -1729,97 +1729,7 @@ finalize_1 (ei, temp)
 		     knowing what to do about it. */
 		  if (!endtree)
 		    abort ();
-#if 0
-		  if (!endtree)
-		    {
-		      gimple_stmt_iterator gsi;
-		      edge e;
-		      if (bb->parent_tree_p)
-		        {
-				*bb->parent_tree_p = stmt;
-				bb->end_tree_p = bb->parent_tree_p;
-				endtreep = bb->end_tree_p;
-				goto done;
-			}
-#if 1
-		      for (e = bb->pred; e; e = e->pred_next)
-			{
-			  for (gsi = gsi_start_bb (e->src);
-			       !gsi_end_bb (gsi);
-			       gsi_step (&gsi))
-			    {
-			      tree temp = gsi_stmt (gsi);
-			      STRIP_WFL (temp);
-			      STRIP_NOPS(temp);
-			      if (TREE_CODE (temp) == COND_EXPR)
-				{
-				  if (COND_EXPR_COND (temp) == endtree)
-				    {
-				      COND_EXPR_COND (temp) = stmt;
-				      bb->end_tree_p = &COND_EXPR_COND (temp);
-				    }
-				  else if (COND_EXPR_THEN (temp) == endtree)
-				    {
-				      COND_EXPR_THEN (temp) = stmt;
-				      bb->end_tree_p = &COND_EXPR_THEN (temp);
-				    }
-				  else if (COND_EXPR_ELSE (temp) == endtree)
-				    {
-				      COND_EXPR_ELSE (temp) = stmt;
-				      bb->end_tree_p = &COND_EXPR_ELSE (temp);
-				    }
-				  endtreep = bb->end_tree_p;
-				  goto done;
-				}
-			    }
-			}
-#endif
-#if 1
-		      for (gsi = gsi_start_bb (parent_block (bb));
-			   !gsi_end_bb (gsi);
-			   gsi_step (&gsi))
-			{
-			  tree temp = gsi_stmt (gsi);
-			  STRIP_WFL (temp);
-			  STRIP_NOPS (temp);
-			  if (TREE_CODE (temp) == LOOP_EXPR)
-			    {
-			      gsi = gsi_start (&TREE_OPERAND (LOOP_EXPR_BODY (temp), 0));
-			      temp = gsi_stmt (gsi);
-			      if (!temp)
-			        continue;
-			      STRIP_WFL (temp);
-			      STRIP_NOPS (temp);
-
-			    }
-
-			  if (TREE_CODE (temp) == COND_EXPR)
-			    {
-			      if (COND_EXPR_COND (temp) == endtree)
-				{
-				  COND_EXPR_COND (temp) = stmt;
-				  bb->end_tree_p = &COND_EXPR_COND (temp);
-				}
-			      else if (COND_EXPR_THEN (temp) == endtree)
-				{
-				  COND_EXPR_THEN (temp) = stmt;
-				  bb->end_tree_p = &COND_EXPR_THEN (temp);
-				}
-			      else if (COND_EXPR_ELSE (temp) == endtree)
-				{
-				  COND_EXPR_ELSE (temp) = stmt;
-				  bb->end_tree_p = &COND_EXPR_ELSE (temp);
-				}
-			      endtreep = bb->end_tree_p;
-			      goto done;
-			    }
-			}
-#endif
-done:
-		    }
-		    /* END TEMPORARY HACK */
 		  else
-#endif
 		    {
 		      *endtreep = stmt;
 		      update_old_new (ei, endtreep, otherexprplace);
@@ -2090,36 +2000,6 @@ reset_can_be_avail (ei, phi)
      struct expr_info *ei;
      tree_ref phi;
 {
-#if 0
-  basic_block block;
-
-  set_exprphi_canbeavail (phi, false);
-  FOR_EACH_BB (block)
-    {
-      edge pred;
-      tree_ref other = phi_at_block (ei, block);
-
-      if (other == NULL)
-        continue;
-
-      for (pred = block->pred; pred; pred = pred->pred_next)
-        {
-          if (pred->src != ENTRY_BLOCK_PTR)
-            {
-              tree_ref operand = phi_operand_for_pred (other, pred);
-              if (expruse_def (operand) == phi)
-                {
-                  if (!expruse_has_real_use(operand))
-		    {
-		      if (!exprphi_downsafe (other)
-			  && exprphi_canbeavail (other))
-			reset_can_be_avail (ei, other);
-		    }
-                }
-            }
-        }
-    }
-#else
   ref_list_iterator rli;

   set_exprphi_canbeavail (phi, false);
@@ -2136,7 +2016,6 @@ reset_can_be_avail (ei, phi)
 	    reset_can_be_avail (ei, f);
 	}
     }
-#endif
 }

 /*  Reset later flags.  */
@@ -2145,32 +2024,6 @@ reset_later (ei, phi)
      struct expr_info *ei;
      tree_ref phi;
 {
-#if 0
-  basic_block block;
-
-  set_exprphi_later (phi, false);
-  FOR_EACH_BB (block)
-    {
-      edge pred;
-      tree_ref other = phi_at_block (ei, block);
-
-      if (other == NULL)
-        continue;
-
-      for (pred = block->pred; pred; pred = pred->pred_next)
-        {
-          if (pred->src != ENTRY_BLOCK_PTR)
-            {
-              tree_ref operand = phi_operand_for_pred (other, pred);
-              if (expruse_def (operand) == phi)
-                {
-                  if (exprphi_later (other))
-                    reset_later (ei, other);
-                }
-            }
-        }
-    }
-#else
   ref_list_iterator rli;

   set_exprphi_later (phi, false);
@@ -2189,7 +2042,6 @@ reset_later (ei, phi)
 	    reset_later (ei, f);
 	}
     }
-#endif
 }

 /*  Compute later flags.  */
@@ -3338,9 +3190,10 @@ process_left_occs_and_kills (bexprs, slo
 }

 void
-tree_perform_ssapre ()
+tree_perform_ssapre (fndecl)
+     tree fndecl;
 {
-  tree fn = DECL_SAVED_TREE (current_function_decl);
+  tree fn = DECL_SAVED_TREE (fndecl);
     /* First, we need to find our candidate expressions. */
   varray_type bexprs;
   htab_t seen = htab_create (37, htab_hash_pointer, htab_eq_pointer, NULL);


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