aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDaniel Berlin <dberlin@dberlin.org>2003-08-11 02:30:56 +0000
committerDaniel Berlin <dberlin@dberlin.org>2003-08-11 02:30:56 +0000
commit82f481f62c48fc6cc7cc06b19a7d668c21eab176 (patch)
treea036cb536a469afdcc5a2e272bb23807874d7b22
parentc978a48304ae28c9d77d98fbf99d1bd66adc8a3c (diff)
2003-08-10 Daniel Berlin <dberlin@dberlin.org>
* tree-dfa.c (compute_may_aliases): Move points-to initialization from here. (find_referenced_vars): To here. (get_memory_tag_for): Use new same_points_to_set function. * tree-alias-common.h (struct tree_alias_ops): Remove doxygen markers. Add same_points_to_set function to struct. (same_points_to_set): New function. * tree-alias-common.c (we_created_global_var): A bit of magic to ignore global var aliasing when we didn't create global var. This will go away soon (same_points_to_set): New function. * tree-alias-andersen.c (struct andersen_alias_ops): Add andersen_same_points_to_set. (andersen_same_points_to_set): New function. Return true if the two variables have the same points-to set. * opts.c (common_handle_option): Add "none" as a points-to option. git-svn-id: https://gcc.gnu.org/svn/gcc/branches/tree-ssa-20020619-branch@70314 138bc75d-0d04-0410-961f-82ee72b054a4
-rw-r--r--gcc/ChangeLog.tree-ssa23
-rw-r--r--gcc/opts.c2
-rw-r--r--gcc/tree-alias-ander.c51
-rw-r--r--gcc/tree-alias-common.c115
-rw-r--r--gcc/tree-alias-common.h78
-rw-r--r--gcc/tree-dfa.c15
6 files changed, 218 insertions, 66 deletions
diff --git a/gcc/ChangeLog.tree-ssa b/gcc/ChangeLog.tree-ssa
index d5757c6c67c..ed08523640d 100644
--- a/gcc/ChangeLog.tree-ssa
+++ b/gcc/ChangeLog.tree-ssa
@@ -1,3 +1,26 @@
+2003-08-10 Daniel Berlin <dberlin@dberlin.org>
+
+ * tree-dfa.c (compute_may_aliases): Move points-to initialization from
+ here.
+ (find_referenced_vars): To here.
+ (get_memory_tag_for): Use new same_points_to_set function.
+
+ * tree-alias-common.h (struct tree_alias_ops): Remove doxygen markers.
+ Add same_points_to_set function to struct.
+ (same_points_to_set): New function.
+
+ * tree-alias-common.c (we_created_global_var): A bit of magic to ignore
+ global var aliasing when we didn't create global var. This will go
+ away soon
+ (same_points_to_set): New function.
+
+ * tree-alias-andersen.c (struct andersen_alias_ops): Add
+ andersen_same_points_to_set.
+ (andersen_same_points_to_set): New function. Return true if the two
+ variables have the same points-to set.
+
+ * opts.c (common_handle_option): Add "none" as a points-to option.
+
2003-08-10 Paul Brook <paul@nowt.org>
* doc/install.texi: Mention --enable-languages=f95.
diff --git a/gcc/opts.c b/gcc/opts.c
index bb063f8982f..a4c5cfa3991 100644
--- a/gcc/opts.c
+++ b/gcc/opts.c
@@ -1383,6 +1383,8 @@ common_handle_option (size_t scode, const char *arg,
#else
warning ("Andersen's PTA not available - libbanshee not compiled.");
#endif
+ else if (!strcmp (arg, "none"))
+ flag_tree_points_to = PTA_NONE;
else
{
warning ("`%s`: unknown points-to analysis algorithm", arg);
diff --git a/gcc/tree-alias-ander.c b/gcc/tree-alias-ander.c
index 5e32e777367..76862753db6 100644
--- a/gcc/tree-alias-ander.c
+++ b/gcc/tree-alias-ander.c
@@ -82,6 +82,8 @@ static int print_out_result (splay_tree_node, void *);
static void andersen_cleanup (struct tree_alias_ops *);
static bool andersen_may_alias (struct tree_alias_ops *, alias_typevar,
alias_typevar);
+static bool andersen_same_points_to_set (struct tree_alias_ops *, alias_typevar,
+ alias_typevar);
static alias_typevar andersen_add_var (struct tree_alias_ops *, tree);
static alias_typevar andersen_add_var_same (struct tree_alias_ops *,
tree, alias_typevar);
@@ -104,6 +106,7 @@ static struct tree_alias_ops andersen_ops = {
andersen_function_def,
andersen_function_call,
andersen_may_alias,
+ andersen_same_points_to_set,
0, /* data */
0, /* Currently non-interprocedural */
1 /* Can do IP on all statics without help. */
@@ -699,7 +702,55 @@ eq_to_var (const aterm term)
{
return stupid_hack == term;
}
+static int simple_eq (const aterm a, const aterm b)
+{
+ return (int *)a - (int *)b;
+}
+extern bool we_created_global_var;
+static bool
+andersen_same_points_to_set (struct tree_alias_ops *ops ATTRIBUTE_UNUSED,
+ alias_typevar ptrtv, alias_typevar vartv)
+{
+ aterm_list ptset1, ptset2;
+ aterm_list_scanner scan1, scan2;
+ void *data1, *data2;
+ size_t length1, length2;
+ region scratch_rgn = newregion ();
+ ptset1 = ALIAS_TVAR_PTSET (ptrtv);
+ ptset2 = ALIAS_TVAR_PTSET (vartv);
+ if (!ptset1)
+ {
+ ptset1 = aterm_tlb (pta_get_contents (ALIAS_TVAR_ATERM (ptrtv)));
+ ALIAS_TVAR_PTSET (ptrtv) = ptset1;
+ }
+ if (!ptset2)
+ {
+ ptset2 = aterm_tlb (pta_get_contents (ALIAS_TVAR_ATERM (vartv)));
+ ALIAS_TVAR_PTSET (vartv) = ptset2;
+ }
+ if (aterm_list_length (ptset1) != aterm_list_length (ptset2))
+ return false;
+ if (ptset1 == ptset2)
+ return true;
+ length1 = aterm_list_length (ptset1);
+ length2 = aterm_list_length (ptset2);
+ ptset1 = aterm_list_copy (scratch_rgn, ptset1);
+ ptset2 = aterm_list_copy (scratch_rgn, ptset2);
+
+ ptset1 = aterm_list_sort (ptset1, simple_eq);
+ ptset2 = aterm_list_sort (ptset2, simple_eq);
+
+ aterm_list_scan (ptset1, &scan1);
+ aterm_list_scan (ptset2, &scan2);
+ while (list_next (&scan1, &data1))
+ {
+ list_next (&scan2, &data2);
+ if (data1 != data2)
+ return false;
+ }
+ return true;
+}
static bool
andersen_may_alias (struct tree_alias_ops *ops ATTRIBUTE_UNUSED,
alias_typevar ptrtv, alias_typevar vartv)
diff --git a/gcc/tree-alias-common.c b/gcc/tree-alias-common.c
index 804196c0f3e..19599f5ebaf 100644
--- a/gcc/tree-alias-common.c
+++ b/gcc/tree-alias-common.c
@@ -89,6 +89,7 @@ static hashval_t annot_hash (const PTR);
static int annot_eq (const PTR, const PTR);
static void get_values_from_constructor (tree, varray_type *);
static bool call_may_clobber (tree);
+bool we_created_global_var = false;
static bool
call_may_clobber (tree expr)
@@ -320,11 +321,14 @@ intra_function_call (varray_type args)
alias_typevar tempvar;
tree temp = create_tmp_alias_var (void_type_node, "aliastmp");
tempvar = current_alias_ops->add_var (current_alias_ops, temp);
- /* 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);
+ if (!we_created_global_var)
+ {
+ /* 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. */
@@ -419,14 +423,13 @@ find_func_aliases (tree *tp, int *walk_subtrees, void *data ATTRIBUTE_UNUSED)
}
if (is_gimple_modify_expr (stp)
- || (TREE_CODE (stp) == VAR_DECL
- && DECL_INITIAL (stp) != NULL_TREE ))
+ || (DECL_P (stp) && DECL_INITIAL (stp) != NULL_TREE ))
{
tree op0, op1;
alias_typevar lhsAV = NULL;
alias_typevar rhsAV = NULL;
- if (TREE_CODE (stp) == VAR_DECL)
+ if (DECL_P (stp))
{
op0 = stp;
op1 = DECL_INITIAL (stp);
@@ -441,6 +444,16 @@ find_func_aliases (tree *tp, int *walk_subtrees, void *data ATTRIBUTE_UNUSED)
/* rhsAV might not have one, c.f. c = 5 */
rhsAV = get_alias_var (op1);
+ if (we_created_global_var)
+ {
+ rhsAV = rhsAV == get_alias_var (global_var) ? NULL : rhsAV;
+ if (lhsAV == get_alias_var (global_var))
+ {
+ *walk_subtrees = 0;
+ return NULL_TREE;
+ }
+ }
+
/* You would think we could test rhsAV at the top, rather than
50 separate times, but we can't, because it can be NULL for
operator assignments, where we'd still collect the individual
@@ -734,7 +747,7 @@ create_fun_alias_var (tree decl, int force)
/* FIXME: Need to let analyzer decide in partial case. */
&& (!current_alias_ops->ip_partial
|| !TREE_STATIC (decl)
- || TREE_PUBLIC (decl)))
+ || TREE_PUBLIC (decl)) && !we_created_global_var)
current_alias_ops->addr_assign (current_alias_ops, tvar,
get_alias_var (global_var));
}
@@ -918,7 +931,6 @@ create_alias_var (tree decl)
return avar;
}
-
/**
@brief Create points-to sets for a function.
@param fndecl Function we are creating alias variables for.
@@ -929,12 +941,12 @@ create_alias_var (tree decl)
void
create_alias_vars (tree fndecl)
{
- bool we_created_global_var = false;
#if 0
tree currdecl = getdecls ();
tree fnbody;
#endif
size_t i;
+ we_created_global_var = false;
currptadecl = fndecl;
if (!global_var)
{
@@ -1032,7 +1044,87 @@ init_alias_vars (void)
alias_annot = htab_create_ggc (7, annot_hash, annot_eq, NULL);
}
+bool
+same_points_to_set (tree ptr, tree var)
+{
+ struct alias_annot_entry entry, *result;
+ alias_typevar ptrtv, vartv;
+ tree ptrcontext;
+ tree varcontext;
+#if !FIELD_BASED
+#else
+ if (TREE_CODE (ptr) == COMPONENT_REF)
+ ptr = TREE_OPERAND (ptr, 1);
+ if (TREE_CODE (var) == COMPONENT_REF)
+ var = TREE_OPERAND (var, 1);
+#endif
+
+ ptrcontext = DECL_CONTEXT (ptr);
+ varcontext = DECL_CONTEXT (var);
+ if (TREE_PUBLIC (ptr))
+ ptr = global_var;
+ else
+ {
+ if (ptrcontext != NULL && TREE_CODE (ptrcontext) != FUNCTION_DECL)
+ ptrcontext = decl_function_context (ptr);
+ if (ptrcontext == NULL)
+ ptr = global_var;
+ }
+ if (TREE_PUBLIC (var))
+ var = global_var;
+ else
+ {
+ if (varcontext != NULL && TREE_CODE (varcontext) != FUNCTION_DECL)
+ varcontext = decl_function_context (var);
+ if (varcontext == NULL)
+ var = global_var;
+ }
+ if (ptr == var || (ptrcontext == NULL && varcontext == NULL)
+ || (ptr == global_var))
+ return true;
+
+ if (DECL_P (ptr))
+ {
+ ptrtv = DECL_PTA_TYPEVAR (ptr);
+ if (!ptrtv && !current_alias_ops->ip && ptr != global_var)
+ abort ();
+ else if (!ptrtv)
+ return false;
+ }
+ else
+ {
+ entry.key = ptr;
+ result = htab_find (alias_annot, &entry);
+ if (!result && !current_alias_ops->ip && ptr != global_var)
+ abort ();
+ else if (!result)
+ return false;
+ ptrtv = result->value;
+ }
+ if (var == global_var && global_var == NULL)
+ return false;
+ if (DECL_P (var))
+ {
+ vartv = DECL_PTA_TYPEVAR (var);
+ if (!vartv && !current_alias_ops->ip && var != global_var)
+ abort ();
+ else if (!vartv)
+ return false;
+ }
+ else
+ {
+ entry.key = var;
+ result = htab_find (alias_annot, &entry);
+ if (!result && !current_alias_ops->ip && var != global_var)
+ abort ();
+ else if (!result)
+ return false;
+
+ vartv = result->value;
+ }
+ return current_alias_ops->same_points_to_set (current_alias_ops, vartv, ptrtv);
+}
/**
@brief Determine whether two variables may-alias.
@@ -1121,7 +1213,6 @@ ptr_may_alias_var (tree ptr, tree var)
}
return current_alias_ops->may_alias (current_alias_ops, ptrtv, vartv);
-
}
#define MASK_POINTER(P) ((unsigned)((unsigned long)(P) & 0xffff))
diff --git a/gcc/tree-alias-common.h b/gcc/tree-alias-common.h
index 0c0623690e2..406a4987c73 100644
--- a/gcc/tree-alias-common.h
+++ b/gcc/tree-alias-common.h
@@ -9,68 +9,46 @@
*/
struct tree_alias_ops
{
- /**
- @brief Initialization
-
- Called right before we start using the other functions.
- */
+ /* Initialization.
+ Called right before we start using the other functions. */
void (*init) (struct tree_alias_ops *);
- /**
- @brief Cleanup
-
- Called when we are finished with the alias analyzer.
- */
+ /* Cleanup.
+ Called when we are finished with the alias analyzer. */
void (*cleanup) (struct tree_alias_ops *);
- /**
- @brief Add variable
-
+ /* Add variable.
Called when we want to inform the alias analyzer about a new
- variable we've found.
- */
+ variable we've found. */
alias_typevar (*add_var) (struct tree_alias_ops *, tree);
- /**
- @brief Add variable equivalent to existing one.
-
+ /* Add variable equivalent to existing one.
Called when we want to inform the alias analyzer about a new
- variable that has the same points-to set as an existing variable.
- */
+ variable that has the same points-to set as an existing
+ variable. */
alias_typevar (*add_var_same) (struct tree_alias_ops *, tree,
- alias_typevar);
- /**
- @brief Process a simple assignment (<tt>a = b</tt>)
-
- Called to process simple assignment statements of the form <tt>a =
- b</tt>, where a and b are both variables.
- */
+ alias_typevar);
+
+ /* Process a simple assignment (a = b).
+ Called to process simple assignment statements of the form a = b,
+ where a and b are both variables. */
void (*simple_assign) (struct tree_alias_ops *, alias_typevar,
alias_typevar);
- /**
- @brief Process an address assignment (<tt>a = &b</tt>)
-
- Called to process address assignment statements of the form <tt>a =
- &b</tt>, where a and b are both variables.
- */
+ /* Process an address assignment (a = &b).
+ Called to process address assignment statements of the form a =
+ &b, where a and b are both variables. */
void (*addr_assign) (struct tree_alias_ops *, alias_typevar, alias_typevar);
- /**
- @brief Process a pointer assignment (<tt>a = *b</tt>)
-
- Called to process pointer assignment statements of the form <tt>a =
- *b</tt>, where a and b are both variables.
- */
+ /* Process a pointer assignment (a = *b).
+ Called to process pointer assignment statements of the form a =
+ *b, where a and b are both variables. */
void (*ptr_assign) (struct tree_alias_ops *, alias_typevar, alias_typevar);
- /**
- @brief Process an operator assignment (<tt>a = op (...)</tt>)
-
- Called to process operators of the form <tt>a = op(....)</tt>, where a is
- a variable.
- */
- void (*op_assign) (struct tree_alias_ops *, alias_typevar, varray_type, tree);
-
+ /* Process an operator assignment (a = op (...))
+ Called to process operators of the form a = op(...), where a is a
+ variable. */
+ void (*op_assign) (struct tree_alias_ops *, alias_typevar, varray_type,
+ tree);
/**
@brief Process a heap assignment (<tt>a = alloc (...)</tt>)
@@ -110,6 +88,11 @@ struct tree_alias_ops
*/
bool (*may_alias) (struct tree_alias_ops *, alias_typevar, alias_typevar);
+ /*
+ Determine if two typevars have the same points-to set.
+ */
+ bool (*same_points_to_set) (struct tree_alias_ops *, alias_typevar, alias_typevar);
+
/**
@brief Private data
*/
@@ -125,6 +108,7 @@ extern void create_alias_vars (tree);
extern void delete_alias_vars (void);
extern void init_alias_vars (void);
extern bool ptr_may_alias_var (tree, tree);
+extern bool same_points_to_set (tree, tree);
extern const char *alias_get_name (tree);
#endif
diff --git a/gcc/tree-dfa.c b/gcc/tree-dfa.c
index e8a71957751..bfb681f76bf 100644
--- a/gcc/tree-dfa.c
+++ b/gcc/tree-dfa.c
@@ -1716,12 +1716,6 @@ compute_may_aliases (tree fndecl ATTRIBUTE_UNUSED)
{
timevar_push (TV_TREE_MAY_ALIAS);
- if (flag_tree_points_to != PTA_NONE)
- {
- timevar_push (TV_TREE_PTA);
- create_alias_vars (fndecl);
- timevar_pop (TV_TREE_PTA);
- }
/* Compute alias sets. */
compute_alias_sets ();
@@ -1762,6 +1756,13 @@ find_referenced_vars (tree fndecl)
VARRAY_GENERIC_PTR_INIT (addressable_vars, 20, "addressable_vars");
VARRAY_GENERIC_PTR_INIT (pointers, 20, "pointers");
+
+ if (flag_tree_points_to != PTA_NONE)
+ {
+ timevar_push (TV_TREE_PTA);
+ create_alias_vars (fndecl);
+ timevar_pop (TV_TREE_PTA);
+ }
/* Walk the lexical blocks in the function looking for variables that may
have been used to declare VLAs and for nested functions. Both
@@ -2520,7 +2521,7 @@ get_memory_tag_for (tree ptr)
struct alias_map_d *curr = VARRAY_GENERIC_PTR (pointers, i);
if (alias_sets_conflict_p (curr->set, tag_set)
&& (flag_tree_points_to == PTA_NONE
- || ptr_may_alias_var (ptr, curr->var)))
+ || same_points_to_set (ptr, curr->var)))
{
tag = var_ann (curr->var)->mem_tag;
break;