diff options
author | Daniel Berlin <dberlin@dberlin.org> | 2005-02-28 03:48:13 +0000 |
---|---|---|
committer | Daniel Berlin <dberlin@dberlin.org> | 2005-02-28 03:48:13 +0000 |
commit | ff5f58a960ef5ebef296b78380ac21ec73eb60d3 (patch) | |
tree | 6b416e8523c502a82d386c98de1a39da6527b040 /gcc/tree-ssa-alias.c | |
parent | f9f5c9e8498b005d223e54abc259d8edc19f22f3 (diff) |
Merge from the pain trainstructure-aliasing-branch
git-svn-id: https://gcc.gnu.org/svn/gcc/branches/structure-aliasing-branch@95649 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/tree-ssa-alias.c')
-rw-r--r-- | gcc/tree-ssa-alias.c | 189 |
1 files changed, 88 insertions, 101 deletions
diff --git a/gcc/tree-ssa-alias.c b/gcc/tree-ssa-alias.c index 18e88e3db58..943cc47609e 100644 --- a/gcc/tree-ssa-alias.c +++ b/gcc/tree-ssa-alias.c @@ -44,6 +44,9 @@ Boston, MA 02111-1307, USA. */ #include "params.h" #include "vec.h" +/* 'true' after aliases have been computed (see compute_may_aliases). */ +bool aliases_computed_p; + /* Structure to map a variable to its alias set and keep track of the virtual operands that will be needed to represent it. */ struct alias_map_d @@ -94,6 +97,9 @@ struct alias_info /* Number of function calls found in the program. */ size_t num_calls_found; + /* Number of const/pure function calls found in the program. */ + size_t num_pure_const_calls_found; + /* Array of counters to keep track of how many times each pointer has been dereferenced in the program. This is used by the alias grouping heuristic in compute_flow_insensitive_aliasing. */ @@ -145,7 +151,7 @@ static void compute_points_to_and_addr_escape (struct alias_info *); static void compute_flow_sensitive_aliasing (struct alias_info *); static void setup_pointers_and_addressables (struct alias_info *); static bool collect_points_to_info_r (tree, tree, void *); -static bool is_escape_site (tree, size_t *); +static bool is_escape_site (tree, struct alias_info *); static void add_pointed_to_var (struct alias_info *, tree, tree); static void create_global_var (void); static void collect_points_to_info_for (struct alias_info *, tree); @@ -441,7 +447,7 @@ count_uses_and_derefs (tree ptr, tree stmt, unsigned *num_uses_p, rhs = stmt; } - if (lhs && EXPR_P (lhs)) + if (lhs && (TREE_CODE (lhs) == TREE_LIST || EXPR_P (lhs))) { struct count_ptr_d count; count.ptr = ptr; @@ -451,7 +457,7 @@ count_uses_and_derefs (tree ptr, tree stmt, unsigned *num_uses_p, *num_derefs_p = count.count; } - if (rhs && EXPR_P (rhs)) + if (rhs && (TREE_CODE (rhs) == TREE_LIST || EXPR_P (rhs))) { struct count_ptr_d count; count.ptr = ptr; @@ -465,80 +471,22 @@ count_uses_and_derefs (tree ptr, tree stmt, unsigned *num_uses_p, } -/* Count the number of calls in the function and conditionally - create GLOBAL_VAR. This is performed before translation - into SSA (and thus before alias analysis) to avoid compile time - and memory utilization explosions in functions with many - of calls and call clobbered variables. */ - -static void -count_calls_and_maybe_create_global_var (void) -{ - struct alias_info ai; - basic_block bb; - bool temp; - - memset (&ai, 0, sizeof (struct alias_info)); - - /* First count the number of calls in the IL. */ - FOR_EACH_BB (bb) - { - block_stmt_iterator si; - - for (si = bsi_start (bb); !bsi_end_p (si); bsi_next (&si)) - { - tree stmt = bsi_stmt (si); - - if (get_call_expr_in (stmt) != NULL_TREE) - ai.num_calls_found++; - } - } - - /* If there are no call clobbered variables, then maybe_create_global_var - will always create a GLOBAL_VAR. At this point we do not want that - behavior. So we turn on one bit in CALL_CLOBBERED_VARs, call - maybe_create_global_var, then reset the bit to its original state. */ - temp = bitmap_bit_p (call_clobbered_vars, 0); - bitmap_set_bit (call_clobbered_vars, 0); - maybe_create_global_var (&ai); - if (!temp) - bitmap_clear_bit (call_clobbered_vars, 0); -} - -struct tree_opt_pass pass_maybe_create_global_var = -{ - "maybe_create_global_var", /* name */ - NULL, /* gate */ - count_calls_and_maybe_create_global_var, /* execute */ - NULL, /* sub */ - NULL, /* next */ - 0, /* static_pass_number */ - TV_TREE_MAY_ALIAS, /* tv_id */ - PROP_cfg, /* properties_required */ - 0, /* properties_provided */ - 0, /* properties_destroyed */ - 0, /* todo_flags_start */ - 0, /* todo_flags_finish */ - 0 /* letter */ -}; - /* Initialize the data structures used for alias analysis. */ static struct alias_info * init_alias_info (void) { struct alias_info *ai; - static bool aliases_computed_p = false; ai = xcalloc (1, sizeof (struct alias_info)); ai->ssa_names_visited = sbitmap_alloc (num_ssa_names); sbitmap_zero (ai->ssa_names_visited); VARRAY_TREE_INIT (ai->processed_ptrs, 50, "processed_ptrs"); - ai->addresses_needed = BITMAP_XMALLOC (); + ai->addresses_needed = BITMAP_ALLOC (NULL); VARRAY_UINT_INIT (ai->num_references, num_referenced_vars, "num_references"); - ai->written_vars = BITMAP_XMALLOC (); - ai->dereferenced_ptrs_store = BITMAP_XMALLOC (); - ai->dereferenced_ptrs_load = BITMAP_XMALLOC (); + ai->written_vars = BITMAP_ALLOC (NULL); + ai->dereferenced_ptrs_store = BITMAP_ALLOC (NULL); + ai->dereferenced_ptrs_load = BITMAP_ALLOC (NULL); /* If aliases have been computed before, clear existing information. */ if (aliases_computed_p) @@ -633,7 +581,7 @@ delete_alias_info (struct alias_info *ai) sbitmap_free (ai->ssa_names_visited); ai->processed_ptrs = NULL; - BITMAP_XFREE (ai->addresses_needed); + BITMAP_FREE (ai->addresses_needed); for (i = 0; i < ai->num_addressable_vars; i++) { @@ -650,9 +598,9 @@ delete_alias_info (struct alias_info *ai) free (ai->pointers); ai->num_references = NULL; - BITMAP_XFREE (ai->written_vars); - BITMAP_XFREE (ai->dereferenced_ptrs_store); - BITMAP_XFREE (ai->dereferenced_ptrs_load); + BITMAP_FREE (ai->written_vars); + BITMAP_FREE (ai->dereferenced_ptrs_store); + BITMAP_FREE (ai->dereferenced_ptrs_load); free (ai); } @@ -702,7 +650,7 @@ compute_points_to_and_addr_escape (struct alias_info *ai) { bitmap addr_taken; tree stmt = bsi_stmt (si); - bool stmt_escapes_p = is_escape_site (stmt, &ai->num_calls_found); + bool stmt_escapes_p = is_escape_site (stmt, ai); bitmap_iterator bi; /* Mark all the variables whose address are taken by the @@ -1139,6 +1087,7 @@ compute_flow_insensitive_aliasing (struct alias_info *ai) /* Since TAG2 does not have any aliases of its own, add TAG2 itself to the alias set of TAG1. */ add_may_alias (tag1, tag2); + SET_BIT (may_aliases1, var_ann (tag2)->uid); } } } @@ -1642,31 +1591,67 @@ maybe_create_global_var (struct alias_info *ai) n_clobbered++; } - if (ai->num_calls_found * n_clobbered >= (size_t) GLOBAL_VAR_THRESHOLD) - create_global_var (); - } + /* If the number of virtual operands that would be needed to + model all the call-clobbered variables is larger than + GLOBAL_VAR_THRESHOLD, create .GLOBAL_VAR. - /* If the function has calls to clobbering functions and .GLOBAL_VAR has - been created, make it an alias for all call-clobbered variables. */ - if (global_var) - EXECUTE_IF_SET_IN_BITMAP (call_clobbered_vars, 0, i, bi) - { - tree var = referenced_var (i); - if (var != global_var) - { - subvar_t svars; - add_may_alias (var, global_var); - bitmap_set_bit (vars_to_rename, var_ann (var)->uid); - if (AGGREGATE_TYPE_P (TREE_TYPE (var)) - && TREE_CODE (TREE_TYPE (var)) != ARRAY_TYPE - && (svars = get_subvars_for_var (var))) + Also create .GLOBAL_VAR if there are no call-clobbered + variables and the program contains a mixture of pure/const + and regular function calls. This is to avoid the problem + described in PR 20115: + + int X; + int func_pure (void) { return X; } + int func_non_pure (int a) { X += a; } + int foo () { - subvar_t sv; - for (sv = svars; sv; sv = sv->next) - bitmap_set_bit (vars_to_rename, var_ann (sv->var)->uid); + int a = func_pure (); + func_non_pure (a); + a = func_pure (); + return a; } - } - } + + Since foo() has no call-clobbered variables, there is + no relationship between the calls to func_pure and + func_non_pure. Since func_pure has no side-effects, value + numbering optimizations elide the second call to func_pure. + So, if we have some pure/const and some regular calls in the + program we create .GLOBAL_VAR to avoid missing these + relations. */ + if (ai->num_calls_found * n_clobbered >= (size_t) GLOBAL_VAR_THRESHOLD + || (n_clobbered == 0 + && ai->num_calls_found > 0 + && ai->num_pure_const_calls_found > 0 + && ai->num_calls_found > ai->num_pure_const_calls_found)) + create_global_var (); + } + + /* Mark all call-clobbered symbols for renaming. Since the initial + rewrite into SSA ignored all call sites, we may need to rename + .GLOBAL_VAR and the call-clobbered variables. */ + EXECUTE_IF_SET_IN_BITMAP (call_clobbered_vars, 0, i, bi) + { + tree var = referenced_var (i); + + /* If the function has calls to clobbering functions and + .GLOBAL_VAR has been created, make it an alias for all + call-clobbered variables. */ + if (global_var && var != global_var) + { + subvar_t svars; + add_may_alias (var, global_var); + if (AGGREGATE_TYPE_P (TREE_TYPE (var)) + && TREE_CODE (TREE_TYPE (var)) != ARRAY_TYPE + && (svars = get_subvars_for_var (var))) + { + subvar_t sv; + for (sv = svars; sv; sv = sv->next) + bitmap_set_bit (vars_to_rename, var_ann (sv->var)->uid); + } + } + + bitmap_set_bit (vars_to_rename, var_ann (var)->uid); + } } @@ -1826,8 +1811,8 @@ set_pt_malloc (tree ptr) /* Given two different pointers DEST and ORIG. Merge the points-to - information in ORIG into DEST. AI is as in - collect_points_to_info. */ + information in ORIG into DEST. AI contains all the alias + information collected up to this point. */ static void merge_pointed_to_info (struct alias_info *ai, tree dest, tree orig) @@ -1972,7 +1957,7 @@ add_pointed_to_expr (struct alias_info *ai, tree ptr, tree expr) /* If VALUE is of the form &DECL, add DECL to the set of variables pointed-to by PTR. Otherwise, add VALUE as a pointed-to expression by - PTR. AI is as in collect_points_to_info. */ + PTR. AI points to the collected alias information. */ static void add_pointed_to_var (struct alias_info *ai, tree ptr, tree value) @@ -2155,16 +2140,18 @@ collect_points_to_info_r (tree var, tree stmt, void *data) 3- STMT is an assignment to a non-local variable, or 4- STMT is a return statement. - If NUM_CALLS_P is not NULL, the counter is incremented if STMT contains - a function call. */ + AI points to the alias information collected so far. */ static bool -is_escape_site (tree stmt, size_t *num_calls_p) +is_escape_site (tree stmt, struct alias_info *ai) { - if (get_call_expr_in (stmt) != NULL_TREE) + tree call = get_call_expr_in (stmt); + if (call != NULL_TREE) { - if (num_calls_p) - (*num_calls_p)++; + ai->num_calls_found++; + + if (!TREE_SIDE_EFFECTS (call)) + ai->num_pure_const_calls_found++; return true; } |