summaryrefslogtreecommitdiff
path: root/gcc/tree-ssa-structalias.c
diff options
context:
space:
mode:
authordnovillo <dnovillo@138bc75d-0d04-0410-961f-82ee72b054a4>2007-04-11 16:14:06 +0000
committerdnovillo <dnovillo@138bc75d-0d04-0410-961f-82ee72b054a4>2007-04-11 16:14:06 +0000
commitc227f8def1ec1ff3dba7bc6459029e97da4885af (patch)
tree40007b60a5085028843a5b427234f0fd32072b58 /gcc/tree-ssa-structalias.c
parent10e1d11768fec298b027d11575e9847febb3ed9a (diff)
downloadgcc-c227f8def1ec1ff3dba7bc6459029e97da4885af.tar.gz
PR 30735
PR 31090 * doc/invoke.texi: Document --params max-aliased-vops and avg-aliased-vops. * tree-ssa-operands.h (get_mpt_for, dump_memory_partitions, debug_memory_partitions): Move to tree-flow.h * params.h (AVG_ALIASED_VOPS): Define. * tree-ssa-alias.c (struct mp_info_def): Remove. Update all users. (mp_info_t): Likewise. (get_mem_sym_stats_for): New. (set_memory_partition): Move from tree-flow-inline.h. (mark_non_addressable): Only clear the set of symbols for the partition if it exists. (dump_memory_partitions): Move from tree-ssa-operands.c (debug_memory_partitions): Likewise. (need_to_partition_p): New. (dump_mem_ref_stats): New. (debug_mem_ref_stats): New. (dump_mem_sym_stats): New. (debug_mem_sym_stats): New. (update_mem_sym_stats_from_stmt): New. (compare_mp_info_entries): New. (mp_info_cmp): Call it. (sort_mp_info): Change argument to a list of mem_sym_stats_t objects. (get_mpt_for): Move from tree-ssa-operands.c. (find_partition_for): New. (create_partition_for): Remove. (estimate_vop_reduction): New. (update_reference_counts): New. (build_mp_info): New. (compute_memory_partitions): Refactor. Document new heuristic. Call build_mp_info, update_reference_counts, find_partition_for and estimate_vop_reduction. (compute_may_aliases): Populate virtual operands before calling debugging dumps. (delete_mem_sym_stats): New. (delete_mem_ref_stats): New. (init_mem_ref_stats): New. (init_alias_info): Call it. (maybe_create_global_var): Remove alias_info argument. Get number of call sites and number of pure/const call sites from gimple_mem_ref_stats(). (dump_alias_info): Call dump_memory_partitions first. (dump_points_to_info_for): Show how many times a pointer has been dereferenced. * opts.c (decode_options): For -O2 set --param max-aliased-vops to 500. For -O3 set --param max-aliased-vops to 1000 and --param avg-aliased-vops to 3. * fortran/options.c (gfc_init_options): Remove assignment to MAX_ALIASED_VOPS. * tree-flow-inline.h (gimple_mem_ref_stats): New. * tree-dfa.c (dump_variable): Dump memory reference statistics. Dump NO_ALIAS* settings. (referenced_var_lookup): Tidy. (mem_sym_stats): New. * tree-ssa-copy.c (may_propagate_copy): Return true if DEST and ORIG are different SSA names for a memory partition. * tree-ssa.c (delete_tree_ssa): Call delete_mem_ref_stats. * tree-flow.h (struct mem_sym_stats_d): Define. (mem_sym_stats_t): Define. (struct mem_ref_stats_d): Define. (struct gimple_df): Add field mem_ref_stats. (enum noalias_state): Define. (struct var_ann_d): Add bitfield noalias_state. (mem_sym_stats, delete_mem_ref_stats, dump_mem_ref_stats, debug_mem_ref_stats, debug_memory_partitions, debug_mem_sym_stats): Declare. * tree-ssa-structalias.c (update_alias_info): Update call sites, pure/const call sites and asm sites in structure returned by gimple_mem_ref_stats. Remove local variable IS_POTENTIAL_DEREF. Increase NUM_DEREFS if the memory expression is a potential dereference. Call update_mem_sym_stats_from_stmt. If the memory references memory, call update_mem_sym_stats_from_stmt for all the direct memory symbol references found. (intra_create_variable_infos): Set noalias_state field for pointer arguments according to the value of flag_argument_noalias. * tree-ssa-structalias.h (struct alias_info): Remove fields num_calls_found and num_pure_const_calls_found. (update_mem_sym_stats_from_stmt): Declare. * params.def (PARAM_MAX_ALIASED_VOPS): Change description. Set default value to 100. (PARAM_AVG_ALIASED_VOPS): Define. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@123719 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/tree-ssa-structalias.c')
-rw-r--r--gcc/tree-ssa-structalias.c117
1 files changed, 90 insertions, 27 deletions
diff --git a/gcc/tree-ssa-structalias.c b/gcc/tree-ssa-structalias.c
index b29619ec205..865770ad8a8 100644
--- a/gcc/tree-ssa-structalias.c
+++ b/gcc/tree-ssa-structalias.c
@@ -3011,15 +3011,21 @@ 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)
{
- ai->num_calls_found++;
+ mem_ref_stats->num_call_sites++;
if (stmt_escape_type == ESCAPE_TO_PURE_CONST)
- ai->num_pure_const_calls_found++;
+ 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);
@@ -3043,17 +3049,15 @@ update_alias_info (tree stmt, struct alias_info *ai)
}
}
- /* Process each operand use. If an operand may be aliased, keep
- track of how many times it's being used. For pointers, determine
- whether they are dereferenced by the statement, or whether their
- value escapes, etc. */
+ /* 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;
- bool is_store, is_potential_deref;
- unsigned num_uses, num_derefs;
+ unsigned num_uses, num_loads, num_stores;
op = USE_FROM_PTR (use_p);
@@ -3073,12 +3077,11 @@ update_alias_info (tree stmt, struct alias_info *ai)
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);
+ add_to_addressable_set (TREE_OPERAND (op, 0), &addressable_vars);
continue;
}
- /* Ignore constants. */
+ /* Ignore constants (they may occur in PHI node arguments). */
if (TREE_CODE (op) != SSA_NAME)
continue;
@@ -3109,7 +3112,7 @@ update_alias_info (tree stmt, struct alias_info *ai)
/* 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_derefs, &is_store);
+ count_uses_and_derefs (op, stmt, &num_uses, &num_loads, &num_stores);
/* Handle a corner case involving address expressions of the
form '&PTR->FLD'. The problem with these expressions is that
@@ -3132,7 +3135,6 @@ update_alias_info (tree stmt, struct alias_info *ai)
are not GIMPLE invariants), they can only appear on the RHS
of an assignment and their base address is always an
INDIRECT_REF expression. */
- is_potential_deref = false;
if (TREE_CODE (stmt) == GIMPLE_MODIFY_STMT
&& TREE_CODE (GIMPLE_STMT_OPERAND (stmt, 1)) == ADDR_EXPR
&& !is_gimple_val (GIMPLE_STMT_OPERAND (stmt, 1)))
@@ -3143,10 +3145,10 @@ update_alias_info (tree stmt, struct alias_info *ai)
tree base = get_base_address (TREE_OPERAND (rhs, 0));
if (TREE_CODE (base) == INDIRECT_REF
&& TREE_OPERAND (base, 0) == op)
- is_potential_deref = true;
+ num_loads++;
}
- if (num_derefs > 0 || is_potential_deref)
+ if (num_loads + num_stores > 0)
{
/* Mark OP as dereferenced. In a subsequent pass,
dereferenced pointers that point to a set of
@@ -3157,13 +3159,20 @@ update_alias_info (tree stmt, struct alias_info *ai)
/* If this is a store operation, mark OP as being
dereferenced to store, otherwise mark it as being
dereferenced to load. */
- if (is_store)
+ 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_derefs < num_uses)
+ 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
@@ -3188,13 +3197,55 @@ update_alias_info (tree stmt, struct alias_info *ai)
return;
/* Mark stored variables in STMT as being written to and update the
- reference counter for potentially aliased symbols in STMT. */
- if (stmt_references_memory_p (stmt) && STORED_SYMS (stmt))
+ memory reference stats for all memory symbols referenced by STMT. */
+ if (stmt_references_memory_p (stmt))
{
unsigned i;
bitmap_iterator bi;
- EXECUTE_IF_SET_IN_BITMAP (STORED_SYMS (stmt), 0, i, bi)
- pointer_set_insert (ai->written_vars, referenced_var (i));
+
+ 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 constitue 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);
}
}
@@ -4108,11 +4159,11 @@ intra_create_variable_infos (void)
if (!could_have_pointers (t))
continue;
- /* With flag_argument_noalias greater than two means that the incoming
- argument cannot alias anything except for itself so create a HEAP
- variable. */
- if (POINTER_TYPE_P (TREE_TYPE (t))
- && flag_argument_noalias > 2)
+ /* If flag_argument_noalias is set, then function pointer
+ arguments are guaranteed not to point to each other. In that
+ case, create an artificial variable PARM_NOALIAS and the
+ constraint ARG = &PARM_NOALIAS. */
+ if (POINTER_TYPE_P (TREE_TYPE (t)) && flag_argument_noalias > 0)
{
varinfo_t vi;
tree heapvar = heapvar_lookup (t);
@@ -4123,14 +4174,26 @@ intra_create_variable_infos (void)
if (heapvar == NULL_TREE)
{
+ var_ann_t ann;
heapvar = create_tmp_var_raw (TREE_TYPE (TREE_TYPE (t)),
"PARM_NOALIAS");
- get_var_ann (heapvar)->is_heapvar = 1;
DECL_EXTERNAL (heapvar) = 1;
if (gimple_referenced_vars (cfun))
add_referenced_var (heapvar);
+
heapvar_insert (t, heapvar);
+
+ ann = get_var_ann (heapvar);
+ if (flag_argument_noalias == 1)
+ ann->noalias_state = NO_ALIAS;
+ else if (flag_argument_noalias == 2)
+ ann->noalias_state = NO_ALIAS_GLOBAL;
+ else if (flag_argument_noalias == 3)
+ ann->noalias_state = NO_ALIAS_ANYTHING;
+ else
+ gcc_unreachable ();
}
+
vi = get_vi_for_tree (heapvar);
vi->is_artificial_var = 1;
vi->is_heap_var = 1;