diff options
author | Richard Guenther <rguenther@suse.de> | 2008-06-29 15:44:00 +0000 |
---|---|---|
committer | Richard Biener <rguenth@gcc.gnu.org> | 2008-06-29 15:44:00 +0000 |
commit | faf2ecc57e3ef478efebee6f83c440df073152c2 (patch) | |
tree | 38b5df5e06de9bf257f1600a6446d2b744b0ab56 /gcc/tree-ssa-structalias.c | |
parent | b03717765d0d62af54bdb3112ac90ca6d7dd7c75 (diff) | |
download | gcc-faf2ecc57e3ef478efebee6f83c440df073152c2.zip gcc-faf2ecc57e3ef478efebee6f83c440df073152c2.tar.gz gcc-faf2ecc57e3ef478efebee6f83c440df073152c2.tar.bz2 |
tree-ssa-structalias.h (compute_points_to_sets): Adjust prototype.
2008-06-29 Richard Guenther <rguenther@suse.de>
* tree-ssa-structalias.h (compute_points_to_sets): Adjust
prototype.
(struct alias_info): Move ...
* tree-ssa-alias.c: ... here.
(update_alias_info): Declare.
(compute_may_aliases): Call it.
(update_alias_info): New function.
* tree-ssa-structalias.c (update_alias_info): Move ...
* tree-ssa-alias.c (update_alias_info_1): ... here.
* tree-ssa-structalias.c (process_constraint_1): Remove
unused from_call argument. Rename to ...
(process_constraint): ... this. Delete old wrapper.
(make_constraint_to): Adjust callers.
(handle_const_call): Likewise.
(handle_pure_call): Likewise.
(init_base_vars): Likewise.
(handle_lhs_call): Likewise. Remove unnecessary constraint.
(find_func_aliases): We don't need structure copies for
complex types.
(make_constraint_from_anything): Remove.
(create_variable_info_for): For globals make constraints
from escaped, not from anything.
(compute_points_to_sets): Do not call update_alias_info.
(ipa_pta_execute): Use make_constraint_from.
From-SVN: r137252
Diffstat (limited to 'gcc/tree-ssa-structalias.c')
-rw-r--r-- | gcc/tree-ssa-structalias.c | 344 |
1 files changed, 31 insertions, 313 deletions
diff --git a/gcc/tree-ssa-structalias.c b/gcc/tree-ssa-structalias.c index 4a3896b..b2ba204 100644 --- a/gcc/tree-ssa-structalias.c +++ b/gcc/tree-ssa-structalias.c @@ -2526,13 +2526,11 @@ get_constraint_exp_from_ssa_var (tree t) return cexpr; } -/* Process a completed constraint T, and add it to the constraint - list. FROM_CALL is true if this is a constraint coming from a - call, which means any DEREFs we see are "may-deref's", not - "must-deref"'s. */ +/* Process constraint T, performing various simplifications and then + adding it to our list of overall constraints. */ static void -process_constraint_1 (constraint_t t, bool from_call) +process_constraint (constraint_t t) { struct constraint_expr rhs = t->rhs; struct constraint_expr lhs = t->lhs; @@ -2556,7 +2554,7 @@ process_constraint_1 (constraint_t t, bool from_call) rhs = t->lhs; t->lhs = t->rhs; t->rhs = rhs; - process_constraint_1 (t, from_call); + process_constraint (t); } /* This can happen in our IR with things like n->a = *p */ else if (rhs.type == DEREF && lhs.type == DEREF && rhs.var != anything_id) @@ -2574,8 +2572,8 @@ process_constraint_1 (constraint_t t, bool from_call) gcc_assert (!AGGREGATE_TYPE_P (pointedtotype) || get_varinfo (rhs.var)->is_unknown_size_var); - process_constraint_1 (new_constraint (tmplhs, rhs), from_call); - process_constraint_1 (new_constraint (lhs, tmplhs), from_call); + process_constraint (new_constraint (tmplhs, rhs)); + process_constraint (new_constraint (lhs, tmplhs)); } else if (rhs.type == ADDRESSOF && lhs.type == DEREF) { @@ -2585,8 +2583,8 @@ process_constraint_1 (constraint_t t, bool from_call) tree tmpvar = create_tmp_var_raw (pointertype, "derefaddrtmp"); struct constraint_expr tmplhs = get_constraint_exp_from_ssa_var (tmpvar); - process_constraint_1 (new_constraint (tmplhs, rhs), from_call); - process_constraint_1 (new_constraint (lhs, tmplhs), from_call); + process_constraint (new_constraint (tmplhs, rhs)); + process_constraint (new_constraint (lhs, tmplhs)); } else { @@ -2595,16 +2593,6 @@ process_constraint_1 (constraint_t t, bool from_call) } } - -/* Process constraint T, performing various simplifications and then - adding it to our list of overall constraints. */ - -static void -process_constraint (constraint_t t) -{ - process_constraint_1 (t, false); -} - /* Return true if T is a variable of a type that could contain pointers. */ @@ -3267,248 +3255,6 @@ do_structure_copy (tree lhsop, tree rhsop) } -/* Update related alias information kept in AI. This is used when - building name tags, alias sets and deciding grouping heuristics. - STMT is the statement to process. This function also updates - ADDRESSABLE_VARS. */ - -static void -update_alias_info (tree stmt, struct alias_info *ai) -{ - bitmap addr_taken; - use_operand_p use_p; - ssa_op_iter iter; - bool stmt_dereferences_ptr_p; - enum escape_type stmt_escape_type = is_escape_site (stmt); - struct mem_ref_stats_d *mem_ref_stats = gimple_mem_ref_stats (cfun); - - stmt_dereferences_ptr_p = false; - - if (stmt_escape_type == ESCAPE_TO_CALL - || stmt_escape_type == ESCAPE_TO_PURE_CONST) - { - mem_ref_stats->num_call_sites++; - if (stmt_escape_type == ESCAPE_TO_PURE_CONST) - mem_ref_stats->num_pure_const_call_sites++; - } - else if (stmt_escape_type == ESCAPE_TO_ASM) - mem_ref_stats->num_asm_sites++; - - /* Mark all the variables whose address are taken by the statement. */ - addr_taken = addresses_taken (stmt); - if (addr_taken) - bitmap_ior_into (gimple_addressable_vars (cfun), addr_taken); - - /* Process each operand use. For pointers, determine whether they - are dereferenced by the statement, or whether their value - escapes, etc. */ - FOR_EACH_PHI_OR_STMT_USE (use_p, stmt, iter, SSA_OP_USE) - { - tree op, var; - var_ann_t v_ann; - struct ptr_info_def *pi; - unsigned num_uses, num_loads, num_stores; - - op = USE_FROM_PTR (use_p); - - /* If STMT is a PHI node, OP may be an ADDR_EXPR. If so, add it - to the set of addressable variables. */ - if (TREE_CODE (op) == ADDR_EXPR) - { - bitmap addressable_vars = gimple_addressable_vars (cfun); - - gcc_assert (TREE_CODE (stmt) == PHI_NODE); - gcc_assert (addressable_vars); - - /* PHI nodes don't have annotations for pinning the set - of addresses taken, so we collect them here. - - FIXME, should we allow PHI nodes to have annotations - so that they can be treated like regular statements? - Currently, they are treated as second-class - statements. */ - add_to_addressable_set (TREE_OPERAND (op, 0), &addressable_vars); - continue; - } - - /* Ignore constants (they may occur in PHI node arguments). */ - if (TREE_CODE (op) != SSA_NAME) - continue; - - var = SSA_NAME_VAR (op); - v_ann = var_ann (var); - - /* The base variable of an SSA name must be a GIMPLE register, and thus - it cannot be aliased. */ - gcc_assert (!may_be_aliased (var)); - - /* We are only interested in pointers. */ - if (!POINTER_TYPE_P (TREE_TYPE (op))) - continue; - - pi = get_ptr_info (op); - - /* Add OP to AI->PROCESSED_PTRS, if it's not there already. */ - if (!TEST_BIT (ai->ssa_names_visited, SSA_NAME_VERSION (op))) - { - SET_BIT (ai->ssa_names_visited, SSA_NAME_VERSION (op)); - VEC_safe_push (tree, heap, ai->processed_ptrs, op); - } - - /* If STMT is a PHI node, then it will not have pointer - dereferences and it will not be an escape point. */ - if (TREE_CODE (stmt) == PHI_NODE) - continue; - - /* Determine whether OP is a dereferenced pointer, and if STMT - is an escape point, whether OP escapes. */ - count_uses_and_derefs (op, stmt, &num_uses, &num_loads, &num_stores); - - /* For directly dereferenced pointers we can apply - TBAA-pruning to their points-to set. We may not count the - implicit dereferences &PTR->FLD here. */ - if (num_loads + num_stores > 0) - pi->is_dereferenced = 1; - - /* Handle a corner case involving address expressions of the - form '&PTR->FLD'. The problem with these expressions is that - they do not represent a dereference of PTR. However, if some - other transformation propagates them into an INDIRECT_REF - expression, we end up with '*(&PTR->FLD)' which is folded - into 'PTR->FLD'. - - So, if the original code had no other dereferences of PTR, - the aliaser will not create memory tags for it, and when - &PTR->FLD gets propagated to INDIRECT_REF expressions, the - memory operations will receive no VDEF/VUSE operands. - - One solution would be to have count_uses_and_derefs consider - &PTR->FLD a dereference of PTR. But that is wrong, since it - is not really a dereference but an offset calculation. - - What we do here is to recognize these special ADDR_EXPR - nodes. Since these expressions are never GIMPLE values (they - are not GIMPLE invariants), they can only appear on the RHS - of an assignment and their base address is always an - INDIRECT_REF expression. */ - if (TREE_CODE (stmt) == GIMPLE_MODIFY_STMT - && TREE_CODE (GIMPLE_STMT_OPERAND (stmt, 1)) == ADDR_EXPR - && !is_gimple_val (GIMPLE_STMT_OPERAND (stmt, 1))) - { - /* If the RHS if of the form &PTR->FLD and PTR == OP, then - this represents a potential dereference of PTR. */ - tree rhs = GIMPLE_STMT_OPERAND (stmt, 1); - tree base = get_base_address (TREE_OPERAND (rhs, 0)); - if (TREE_CODE (base) == INDIRECT_REF - && TREE_OPERAND (base, 0) == op) - num_loads++; - } - - if (num_loads + num_stores > 0) - { - /* Mark OP as dereferenced. In a subsequent pass, - dereferenced pointers that point to a set of - variables will be assigned a name tag to alias - all the variables OP points to. */ - pi->memory_tag_needed = 1; - - /* ??? For always executed direct dereferences we can - apply TBAA-pruning to their escape set. */ - - /* If this is a store operation, mark OP as being - dereferenced to store, otherwise mark it as being - dereferenced to load. */ - if (num_stores > 0) - pointer_set_insert (ai->dereferenced_ptrs_store, var); - else - pointer_set_insert (ai->dereferenced_ptrs_load, var); - - /* Update the frequency estimate for all the dereferences of - pointer OP. */ - update_mem_sym_stats_from_stmt (op, stmt, num_loads, num_stores); - - /* Indicate that STMT contains pointer dereferences. */ - stmt_dereferences_ptr_p = true; - } - - if (stmt_escape_type != NO_ESCAPE && num_loads + num_stores < num_uses) - { - /* If STMT is an escape point and STMT contains at - least one direct use of OP, then the value of OP - escapes and so the pointed-to variables need to - be marked call-clobbered. */ - pi->value_escapes_p = 1; - pi->escape_mask |= stmt_escape_type; - - /* If the statement makes a function call, assume - that pointer OP will be dereferenced in a store - operation inside the called function. */ - if (get_call_expr_in (stmt) - || stmt_escape_type == ESCAPE_STORED_IN_GLOBAL) - { - pointer_set_insert (ai->dereferenced_ptrs_store, var); - pi->memory_tag_needed = 1; - } - } - } - - if (TREE_CODE (stmt) == PHI_NODE) - return; - - /* Mark stored variables in STMT as being written to and update the - memory reference stats for all memory symbols referenced by STMT. */ - if (stmt_references_memory_p (stmt)) - { - unsigned i; - bitmap_iterator bi; - - mem_ref_stats->num_mem_stmts++; - - /* Notice that we only update memory reference stats for symbols - loaded and stored by the statement if the statement does not - contain pointer dereferences and it is not a call/asm site. - This is to avoid double accounting problems when creating - memory partitions. After computing points-to information, - pointer dereference statistics are used to update the - reference stats of the pointed-to variables, so here we - should only update direct references to symbols. - - Indirect references are not updated here for two reasons: (1) - The first time we compute alias information, the sets - LOADED/STORED are empty for pointer dereferences, (2) After - partitioning, LOADED/STORED may have references to - partitions, not the original pointed-to variables. So, if we - always counted LOADED/STORED here and during partitioning, we - would count many symbols more than once. - - This does cause some imprecision when a statement has a - combination of direct symbol references and pointer - dereferences (e.g., MEMORY_VAR = *PTR) or if a call site has - memory symbols in its argument list, but these cases do not - occur so frequently as to constitute a serious problem. */ - if (STORED_SYMS (stmt)) - EXECUTE_IF_SET_IN_BITMAP (STORED_SYMS (stmt), 0, i, bi) - { - tree sym = referenced_var (i); - pointer_set_insert (ai->written_vars, sym); - if (!stmt_dereferences_ptr_p - && stmt_escape_type != ESCAPE_TO_CALL - && stmt_escape_type != ESCAPE_TO_PURE_CONST - && stmt_escape_type != ESCAPE_TO_ASM) - update_mem_sym_stats_from_stmt (sym, stmt, 0, 1); - } - - if (!stmt_dereferences_ptr_p - && LOADED_SYMS (stmt) - && stmt_escape_type != ESCAPE_TO_CALL - && stmt_escape_type != ESCAPE_TO_PURE_CONST - && stmt_escape_type != ESCAPE_TO_ASM) - EXECUTE_IF_SET_IN_BITMAP (LOADED_SYMS (stmt), 0, i, bi) - update_mem_sym_stats_from_stmt (referenced_var (i), stmt, 1, 0); - } -} - - /* Handle pointer arithmetic EXPR when creating aliasing constraints. Expressions of the type PTR + CST can be handled in two ways: @@ -3598,7 +3344,7 @@ make_constraint_to (unsigned id, tree op) get_constraint_for (op, &rhsc); for (j = 0; VEC_iterate (ce_s, rhsc, j, c); j++) - process_constraint_1 (new_constraint (includes, *c), true); + process_constraint (new_constraint (includes, *c)); VEC_free (ce_s, heap, rhsc); } @@ -3643,16 +3389,11 @@ handle_lhs_call (tree lhs) struct constraint_expr *lhsp; get_constraint_for (lhs, &lhsc); - rhsc.var = nonlocal_id; - rhsc.offset = 0; - rhsc.type = ADDRESSOF; - for (j = 0; VEC_iterate (ce_s, lhsc, j, lhsp); j++) - process_constraint_1 (new_constraint (*lhsp, rhsc), true); rhsc.var = escaped_id; rhsc.offset = 0; rhsc.type = ADDRESSOF; for (j = 0; VEC_iterate (ce_s, lhsc, j, lhsp); j++) - process_constraint_1 (new_constraint (*lhsp, rhsc), true); + process_constraint (new_constraint (*lhsp, rhsc)); VEC_free (ce_s, heap, lhsc); } @@ -3680,7 +3421,7 @@ handle_const_call (tree stmt) rhsc.offset = 0; rhsc.type = ADDRESSOF; for (j = 0; VEC_iterate (ce_s, lhsc, j, lhsp); j++) - process_constraint_1 (new_constraint (*lhsp, rhsc), true); + process_constraint (new_constraint (*lhsp, rhsc)); VEC_free (ce_s, heap, lhsc); return; } @@ -3690,7 +3431,7 @@ handle_const_call (tree stmt) rhsc.offset = 0; rhsc.type = ADDRESSOF; for (j = 0; VEC_iterate (ce_s, lhsc, j, lhsp); j++) - process_constraint_1 (new_constraint (*lhsp, rhsc), true); + process_constraint (new_constraint (*lhsp, rhsc)); /* May return arguments. */ FOR_EACH_CALL_EXPR_ARG (arg, iter, call) @@ -3702,7 +3443,7 @@ handle_const_call (tree stmt) get_constraint_for (arg, &argc); for (i = 0; VEC_iterate (ce_s, argc, i, argp); i++) for (j = 0; VEC_iterate (ce_s, lhsc, j, lhsp); j++) - process_constraint_1 (new_constraint (*lhsp, *argp), true); + process_constraint (new_constraint (*lhsp, *argp)); VEC_free (ce_s, heap, argc); } @@ -3748,7 +3489,7 @@ handle_pure_call (tree stmt) rhsc.offset = 0; rhsc.type = ADDRESSOF; for (j = 0; VEC_iterate (ce_s, lhsc, j, lhsp); j++) - process_constraint_1 (new_constraint (*lhsp, rhsc), true); + process_constraint (new_constraint (*lhsp, rhsc)); VEC_free (ce_s, heap, lhsc); return; } @@ -3759,7 +3500,7 @@ handle_pure_call (tree stmt) rhsc.offset = 0; rhsc.type = ADDRESSOF; for (j = 0; VEC_iterate (ce_s, lhsc, j, lhsp); j++) - process_constraint_1 (new_constraint (*lhsp, rhsc), true); + process_constraint (new_constraint (*lhsp, rhsc)); VEC_free (ce_s, heap, lhsc); } } @@ -3957,10 +3698,8 @@ find_func_aliases (tree origt) tree rhsop = GIMPLE_STMT_OPERAND (t, 1); int i; - if ((AGGREGATE_TYPE_P (TREE_TYPE (lhsop)) - || TREE_CODE (TREE_TYPE (lhsop)) == COMPLEX_TYPE) - && (AGGREGATE_TYPE_P (TREE_TYPE (rhsop)) - || TREE_CODE (TREE_TYPE (lhsop)) == COMPLEX_TYPE)) + if (AGGREGATE_TYPE_P (TREE_TYPE (lhsop)) + && AGGREGATE_TYPE_P (TREE_TYPE (rhsop))) { do_structure_copy (lhsop, rhsop); } @@ -4340,13 +4079,6 @@ make_constraint_from (varinfo_t vi, int from) process_constraint (new_constraint (lhs, rhs)); } -/* Create a constraint from ANYTHING variable to VI. */ -static void -make_constraint_from_anything (varinfo_t vi) -{ - make_constraint_from (vi, anything_id); -} - /* Count the number of arguments DECL has, and set IS_VARARGS to true if it is a varargs function. */ @@ -4552,8 +4284,9 @@ create_variable_info_for (tree decl, const char *name) insert_vi_for_tree (vi->decl, vi); VEC_safe_push (varinfo_t, heap, varmap, vi); - if (is_global && (!flag_whole_program || !in_ipa_mode)) - make_constraint_from_anything (vi); + if (is_global && (!flag_whole_program || !in_ipa_mode) + && could_have_pointers (decl)) + make_constraint_from (vi, escaped_id); stats.total_vars++; if (use_field_sensitive @@ -4633,8 +4366,9 @@ create_variable_info_for (tree decl, const char *name) newvi->fullsize = vi->fullsize; insert_into_field_list (vi, newvi); VEC_safe_push (varinfo_t, heap, varmap, newvi); - if (is_global && (!flag_whole_program || !in_ipa_mode)) - make_constraint_from_anything (newvi); + if (is_global && (!flag_whole_program || !in_ipa_mode) + && (!fo->decl || could_have_pointers (fo->decl))) + make_constraint_from (newvi, escaped_id); stats.total_vars++; } @@ -5296,7 +5030,7 @@ init_base_vars (void) rhs.type = DEREF; rhs.var = escaped_id; rhs.offset = 0; - process_constraint_1 (new_constraint (lhs, rhs), true); + process_constraint (new_constraint (lhs, rhs)); /* Create the NONLOCAL variable, used to represent the set of nonlocal memory. */ @@ -5339,7 +5073,7 @@ init_base_vars (void) rhs.type = DEREF; rhs.var = callused_id; rhs.offset = 0; - process_constraint_1 (new_constraint (lhs, rhs), true); + process_constraint (new_constraint (lhs, rhs)); /* Create the INTEGER variable, used to represent that a variable points to an INTEGER. */ @@ -5372,7 +5106,7 @@ init_base_vars (void) rhs.type = ADDRESSOF; rhs.var = escaped_id; rhs.offset = 0; - process_constraint_1 (new_constraint (lhs, rhs), true); + process_constraint (new_constraint (lhs, rhs)); /* *ESCAPED = &NONLOCAL. This is true because we have to assume everything pointed to by escaped can also point to nonlocal. */ @@ -5382,7 +5116,7 @@ init_base_vars (void) rhs.type = ADDRESSOF; rhs.var = nonlocal_id; rhs.offset = 0; - process_constraint_1 (new_constraint (lhs, rhs), true); + process_constraint (new_constraint (lhs, rhs)); } /* Initialize things necessary to perform PTA */ @@ -5581,7 +5315,7 @@ compute_tbaa_pruning (void) at the start of the file for an algorithmic overview. */ void -compute_points_to_sets (struct alias_info *ai) +compute_points_to_sets (void) { struct scc_info *si; basic_block bb; @@ -5600,18 +5334,8 @@ compute_points_to_sets (struct alias_info *ai) tree phi; for (phi = phi_nodes (bb); phi; phi = PHI_CHAIN (phi)) - { - if (is_gimple_reg (PHI_RESULT (phi))) - { - find_func_aliases (phi); - - /* Update various related attributes like escaped - addresses, pointer dereferences for loads and stores. - This is used when creating name tags and alias - sets. */ - update_alias_info (phi, ai); - } - } + if (is_gimple_reg (PHI_RESULT (phi))) + find_func_aliases (phi); for (bsi = bsi_start (bb); !bsi_end_p (bsi); ) { @@ -5619,12 +5343,6 @@ compute_points_to_sets (struct alias_info *ai) find_func_aliases (stmt); - /* Update various related attributes like escaped - addresses, pointer dereferences for loads and stores. - This is used when creating name tags and alias - sets. */ - update_alias_info (stmt, ai); - /* The information in CHANGE_DYNAMIC_TYPE_EXPR nodes has now been captured, and we can remove them. */ if (TREE_CODE (stmt) == CHANGE_DYNAMIC_TYPE_EXPR) @@ -5761,7 +5479,7 @@ ipa_pta_execute (void) { varinfo_t fi = get_varinfo (varid); for (; fi; fi = fi->next) - make_constraint_from_anything (fi); + make_constraint_from (fi, anything_id); } } } |