diff --git a/gcc/ChangeLog b/gcc/ChangeLog index f599f04e594a..7828291c81c0 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,16 @@ +2005-07-18 Daniel Berlin + + Fix PR tree-optimization/22483 + + * tree-complex.c (create_components): Use + safe_referenced_var_iterator and FOR_EACH_REFERENCED_VAR_SAFE. + * tree-flow-inline.h (fill_referenced_var_vec): New function. + * tree-flow.h (safe_referenced_var_iterator): New structure. + (FOR_EACH_REFERENCED_VAR_SAFE): New macro. + * tree-ssa-alias.c (setup_pointers_and_addressables): Use + safe_referenced_var iterator. + (add_type_alias): Ditto. + 2005-07-19 Steven Bosscher * loop-init.c (rest_of_handle_loop2): Remove. diff --git a/gcc/tree-complex.c b/gcc/tree-complex.c index 21e924560514..54f3ace791dd 100644 --- a/gcc/tree-complex.c +++ b/gcc/tree-complex.c @@ -386,7 +386,8 @@ create_components (void) { size_t n; tree var; - referenced_var_iterator rvi; + safe_referenced_var_iterator rvi; + VEC (tree, heap) *refvars; n = num_referenced_vars; if (n == 0) @@ -395,7 +396,7 @@ create_components (void) complex_variable_components = htab_create (10, int_tree_map_hash, int_tree_map_eq, free); - FOR_EACH_REFERENCED_VAR (var, rvi) + FOR_EACH_REFERENCED_VAR_SAFE (var, refvars, rvi) { tree r = NULL, i = NULL; @@ -442,6 +443,7 @@ create_components (void) cvc_insert (2 * DECL_UID (var), r); cvc_insert (2 * DECL_UID (var) + 1, i); } + VEC_free (tree, heap, refvars); } /* Extract the real or imaginary part of a complex variable or constant. diff --git a/gcc/tree-flow-inline.h b/gcc/tree-flow-inline.h index 4874c77f686c..30d13ab4ae40 100644 --- a/gcc/tree-flow-inline.h +++ b/gcc/tree-flow-inline.h @@ -105,7 +105,19 @@ next_referenced_var (referenced_var_iterator *iter) return NULL; return itm->to; } - + +/* Fill up VEC with the variables in the referenced vars hashtable. */ + +static inline void +fill_referenced_var_vec (VEC (tree, heap) **vec) +{ + referenced_var_iterator rvi; + tree var; + *vec = NULL; + FOR_EACH_REFERENCED_VAR (var, rvi) + VEC_safe_push (tree, heap, *vec, var); +} + /* Return the variable annotation for T, which must be a _DECL node. Return NULL if the variable annotation doesn't already exist. */ static inline var_ann_t diff --git a/gcc/tree-flow.h b/gcc/tree-flow.h index 2bf40df5fa31..da49ed199e9d 100644 --- a/gcc/tree-flow.h +++ b/gcc/tree-flow.h @@ -389,11 +389,35 @@ typedef struct } referenced_var_iterator; +/* This macro loops over all the referenced vars, one at a time, putting the + current var in VAR. Note: You are not allowed to add referenced variables + to the hashtable while using this macro. Doing so may cause it to behave + erratically. */ + #define FOR_EACH_REFERENCED_VAR(VAR, ITER) \ for ((VAR) = first_referenced_var (&(ITER)); \ !end_referenced_vars_p (&(ITER)); \ (VAR) = next_referenced_var (&(ITER))) + +typedef struct +{ + int i; +} safe_referenced_var_iterator; + +/* This macro loops over all the referenced vars, one at a time, putting the + current var in VAR. You are allowed to add referenced variables during the + execution of this macro, however, the macro will not iterate over them. It + requires a temporary vector of trees, VEC, whose lifetime is controlled by + the caller. The purpose of the vector is to temporarily store the + referenced_variables hashtable so that adding referenced variables does not + affect the hashtable. */ + +#define FOR_EACH_REFERENCED_VAR_SAFE(VAR, VEC, ITER) \ + for ((ITER).i = 0, fill_referenced_var_vec (&(VEC)); \ + VEC_iterate (tree, (VEC), (ITER).i, (VAR)); \ + (ITER).i++) + /* Array of all variables referenced in the function. */ extern GTY((param_is (struct int_tree_map))) htab_t referenced_vars; diff --git a/gcc/tree-ssa-alias.c b/gcc/tree-ssa-alias.c index 387a6961cd5c..c65fe8d043ff 100644 --- a/gcc/tree-ssa-alias.c +++ b/gcc/tree-ssa-alias.c @@ -1168,6 +1168,8 @@ setup_pointers_and_addressables (struct alias_info *ai) size_t n_vars, num_addressable_vars, num_pointers; referenced_var_iterator rvi; tree var; + VEC (tree, heap) *varvec = NULL; + safe_referenced_var_iterator srvi; /* Size up the arrays ADDRESSABLE_VARS and POINTERS. */ num_addressable_vars = num_pointers = 0; @@ -1204,7 +1206,7 @@ setup_pointers_and_addressables (struct alias_info *ai) unnecessarily. */ n_vars = num_referenced_vars; - FOR_EACH_REFERENCED_VAR (var, rvi) + FOR_EACH_REFERENCED_VAR_SAFE (var, varvec, srvi) { var_ann_t v_ann = var_ann (var); subvar_t svars; @@ -1336,6 +1338,7 @@ setup_pointers_and_addressables (struct alias_info *ai) } } } + VEC_free (tree, heap, varvec); } @@ -2218,14 +2221,14 @@ add_type_alias (tree ptr, tree var) tree tag; var_ann_t ann = var_ann (ptr); subvar_t svars; - + VEC (tree, heap) *varvec = NULL; if (ann->type_mem_tag == NULL_TREE) { tree q = NULL_TREE; tree tag_type = TREE_TYPE (TREE_TYPE (ptr)); HOST_WIDE_INT tag_set = get_alias_set (tag_type); - referenced_var_iterator rvi; + safe_referenced_var_iterator rvi; /* PTR doesn't have a type tag, create a new one and add VAR to the new tag's alias set. @@ -2234,7 +2237,7 @@ add_type_alias (tree ptr, tree var) whether there is another pointer Q with the same alias set as PTR. This could be sped up by having type tags associated with types. */ - FOR_EACH_REFERENCED_VAR (q, rvi) + FOR_EACH_REFERENCED_VAR_SAFE (q, varvec, rvi) { if (POINTER_TYPE_P (TREE_TYPE (q)) && tag_set == get_alias_set (TREE_TYPE (TREE_TYPE (q)))) @@ -2292,6 +2295,7 @@ found_tag: for (i = 0; i < VARRAY_ACTIVE_SIZE (aliases); i++) mark_sym_for_renaming (VARRAY_TREE (aliases, i)); } + VEC_free (tree, heap, varvec); } @@ -2766,7 +2770,8 @@ static void create_structure_vars (void) { basic_block bb; - referenced_var_iterator rvi; + safe_referenced_var_iterator rvi; + VEC (tree, heap) *varvec = NULL; tree var; used_portions = htab_create (10, used_part_map_hash, used_part_map_eq, @@ -2782,7 +2787,7 @@ create_structure_vars (void) NULL); } } - FOR_EACH_REFERENCED_VAR (var, rvi) + FOR_EACH_REFERENCED_VAR_SAFE (var, varvec, rvi) { /* The C++ FE creates vars without DECL_SIZE set, for some reason. */ if (var @@ -2793,6 +2798,7 @@ create_structure_vars (void) create_overlap_variables_for (var); } htab_delete (used_portions); + VEC_free (tree, heap, varvec); }