diff options
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/ChangeLog | 15 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/tree-ssa/pr23382.c | 24 | ||||
-rw-r--r-- | gcc/tree-dfa.c | 12 | ||||
-rw-r--r-- | gcc/tree-flow.h | 2 | ||||
-rw-r--r-- | gcc/tree-ssa-alias.c | 2 | ||||
-rw-r--r-- | gcc/tree-ssa-structalias.c | 47 | ||||
-rw-r--r-- | gcc/tree-ssa.c | 1 |
7 files changed, 103 insertions, 0 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index bd9a3e0..d6d939b 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,18 @@ +2005-11-08 Daniel Berlin <dberlin@dberlin.org> + + Fix PR tree-optimization/23382 + + * tree-ssa-alias.c (compute_may_aliases): Call + delete_old_heap_vars. + * tree-dfa.c (referenced_var_remove): New function. + * tree-ssa.c (delete_tree_ssa): Call delete_old_heap_vars. + * tree-flow.h (referenced_var_remove): Add prototype. + (delete_old_heap_vars): Ditto. + * tree-ssa-structalias.c (heapvars): New variable. + (oldheapvars): Ditto. + (get_constraint_for): Put heap vars on heapvars list. + (delete_old_heap_vars): New function. + 2005-11-08 Jason Merrill <jason@redhat.com> * tree.h (CALL_FROM_THUNK_P): Add CALL_EXPR_CHECK. diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr23382.c b/gcc/testsuite/gcc.dg/tree-ssa/pr23382.c new file mode 100644 index 0000000..eeeb0ff --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/pr23382.c @@ -0,0 +1,24 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-alias-vops" } */ +struct a +{ + int length; + int a1[256]; +}; + +void *malloc(long size) __attribute__((malloc)); + +void f(void) +{ + struct a *a = malloc(sizeof(struct a)); +} +/* { dg-final { scan-tree-dump-times "V_MAY_DEF <HEAP" 1 "alias1"} } */ +/* { dg-final { scan-tree-dump-times "V_MAY_DEF <HEAP" 1 "alias2"} } */ +/* { dg-final { scan-tree-dump-times "V_MAY_DEF <HEAP" 1 "alias3"} } */ +/* { dg-final { scan-tree-dump-times "V_MAY_DEF <HEAP" 1 "alias4"} } */ +/* { dg-final { scan-tree-dump-times "V_MAY_DEF <HEAP" 1 "alias5"} } */ +/* { dg-final { cleanup-tree-dump "alias1" } } */ +/* { dg-final { cleanup-tree-dump "alias2" } } */ +/* { dg-final { cleanup-tree-dump "alias3" } } */ +/* { dg-final { cleanup-tree-dump "alias4" } } */ +/* { dg-final { cleanup-tree-dump "alias5" } } */ diff --git a/gcc/tree-dfa.c b/gcc/tree-dfa.c index 9fc48d5..2ede8e6 100644 --- a/gcc/tree-dfa.c +++ b/gcc/tree-dfa.c @@ -609,6 +609,18 @@ referenced_var_insert (unsigned int uid, tree to) *(struct int_tree_map **) loc = h; } +/* Remove the pair DECL_UID (TO), TO from the referenced vars + hashtable. */ + +void +referenced_var_remove (tree to) +{ + struct int_tree_map in; + in.uid = DECL_UID (to); + in.to = to; + htab_remove_elt_with_hash (referenced_vars, &in, in.uid); +} + /* Add VAR to the list of dereferenced variables. WALK_STATE contains a hash table used to avoid adding the same diff --git a/gcc/tree-flow.h b/gcc/tree-flow.h index 389ec8f..b61b357 100644 --- a/gcc/tree-flow.h +++ b/gcc/tree-flow.h @@ -423,6 +423,7 @@ extern GTY((param_is (struct int_tree_map))) htab_t referenced_vars; extern tree referenced_var_lookup (unsigned int); extern tree referenced_var_lookup_if_exists (unsigned int); +extern void referenced_var_remove (tree); #define num_referenced_vars htab_elements (referenced_vars) #define referenced_var(i) referenced_var_lookup (i) @@ -891,6 +892,7 @@ int push_fields_onto_fieldstack (tree, VEC(fieldoff_s,heap) **, HOST_WIDE_INT, bool *); void sort_fieldstack (VEC(fieldoff_s,heap) *); +void delete_old_heap_vars (void); #include "tree-flow-inline.h" #endif /* _TREE_FLOW_H */ diff --git a/gcc/tree-ssa-alias.c b/gcc/tree-ssa-alias.c index 84c5225..5397894 100644 --- a/gcc/tree-ssa-alias.c +++ b/gcc/tree-ssa-alias.c @@ -252,6 +252,8 @@ compute_may_aliases (void) memset (&alias_stats, 0, sizeof (alias_stats)); + delete_old_heap_vars (); + /* Initialize aliasing information. */ ai = init_alias_info (); diff --git a/gcc/tree-ssa-structalias.c b/gcc/tree-ssa-structalias.c index aa912cb..67e872a 100644 --- a/gcc/tree-ssa-structalias.c +++ b/gcc/tree-ssa-structalias.c @@ -159,6 +159,9 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA TODO: We could handle unions, but to be honest, it's probably not worth the pain or slowdown. */ +static VEC(tree, heap) *heapvars = NULL; +static VEC(tree, heap) *oldheapvars = NULL; + static bool use_field_sensitive = true; static unsigned int create_variable_info_for (tree, const char *); static struct constraint_expr get_constraint_for (tree, bool *); @@ -2213,6 +2216,7 @@ get_constraint_for (tree t, bool *need_anyoffset) tree heapvar; heapvar = create_tmp_var_raw (ptr_type_node, "HEAP"); + VEC_safe_push (tree, heap, heapvars, heapvar); DECL_EXTERNAL (heapvar) = 1; add_referenced_tmp_var (heapvar); temp.var = create_variable_info_for (heapvar, @@ -3763,3 +3767,46 @@ delete_points_to_sets (void) have_alias_info = false; } + +/* Delete old heap vars, since nothing else will remove them for + us. */ +void +delete_old_heap_vars (void) +{ + if (!in_ssa_p) + { + VEC_free (tree, heap, heapvars); + VEC_free (tree, heap, oldheapvars); + heapvars = NULL; + oldheapvars = NULL; + } + /* Why is this complicated? + We can't remove the heapvars from the referenced var array until + they go away from the ssa form, and we can't remove them from the + ssa form until we've renamed it. We can't renamed it if it's not + in the referenced vars array. + Thus, we have to first mark it for renaming, and then the *next* + time after that we call this function, we can remove it from + referenced vars. */ + + if (!VEC_empty (tree, heapvars)) + { + int i; + tree heapvar; + for (i = 0; VEC_iterate (tree, heapvars, i, heapvar); i++) + { + if (in_ssa_p) + mark_sym_for_renaming (heapvar); + DECL_EXTERNAL (heapvar) = false; + bitmap_clear_bit (call_clobbered_vars, DECL_UID (heapvar)); + } + if (!VEC_empty (tree, oldheapvars)) + { + for (i = 0; VEC_iterate (tree, oldheapvars, i, heapvar); i++) + referenced_var_remove (heapvar); + } + VEC_free (tree, heap, oldheapvars); + oldheapvars = heapvars; + heapvars = NULL; + } +} diff --git a/gcc/tree-ssa.c b/gcc/tree-ssa.c index d78a944..15af7f3 100644 --- a/gcc/tree-ssa.c +++ b/gcc/tree-ssa.c @@ -848,6 +848,7 @@ delete_tree_ssa (void) set_phi_nodes (bb, NULL); } + delete_old_heap_vars (); /* Remove annotations from every referenced variable. */ FOR_EACH_REFERENCED_VAR (var, rvi) { |