mirror of
git://gcc.gnu.org/git/gcc.git
synced 2025-03-19 22:41:28 +08:00
re PR tree-optimization/30735 (50% slow down due to mem-ssa merge)
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. From-SVN: r123719
This commit is contained in:
parent
574e75f5fb
commit
e9e0aa2c96
@ -1,3 +1,97 @@
|
||||
2007-04-11 Diego Novillo <dnovillo@redhat.com>
|
||||
|
||||
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.
|
||||
|
||||
2007-04-11 Richard Guenther <rguenther@suse.de>
|
||||
|
||||
PR middle-end/31530
|
||||
|
@ -6588,10 +6588,29 @@ The maximum instructions CSE process before flushing. The default is 1000.
|
||||
|
||||
@item max-aliased-vops
|
||||
|
||||
Maximum number of virtual operands per statement allowed to represent
|
||||
aliases before triggering the alias grouping heuristic. Alias
|
||||
grouping reduces compile times and memory consumption needed for
|
||||
aliasing at the expense of precision loss in alias information.
|
||||
Maximum number of virtual operands per function allowed to represent
|
||||
aliases before triggering the alias partitioning heuristic. Alias
|
||||
partitioning reduces compile times and memory consumption needed for
|
||||
aliasing at the expense of precision loss in alias information. The
|
||||
default value for this parameter is 100 for -O1, 500 for -O2 and 1000
|
||||
for -O3.
|
||||
|
||||
Notice that if a function contains more memory statements than the
|
||||
value of this parameter, it is not really possible to achieve this
|
||||
reduction. In this case, the compiler will use the number of memory
|
||||
statements as the value for @option{max-aliased-vops}.
|
||||
|
||||
@item avg-aliased-vops
|
||||
|
||||
Average number of virtual operands per statement allowed to represent
|
||||
aliases before triggering the alias partitioning heuristic. This
|
||||
works in conjunction with @option{max-aliased-vops}. If a function
|
||||
contains more than @option{max-aliased-vops} virtual operators, then
|
||||
memory symbols will be grouped into memory partitions until either the
|
||||
total number of virtual operators is below @option{max-aliased-vops}
|
||||
or the average number of virtual operators per memory statement is
|
||||
below @option{avg-aliased-vops}. The default value for this parameter
|
||||
is 1 for -O1 and -O2, and 3 for -O3.
|
||||
|
||||
@item ggc-min-expand
|
||||
|
||||
|
@ -117,10 +117,6 @@ gfc_init_options (unsigned int argc ATTRIBUTE_UNUSED,
|
||||
/* -fshort-enums can be default on some targets. */
|
||||
gfc_option.fshort_enums = targetm.default_short_enums ();
|
||||
|
||||
/* Increase MAX_ALIASED_VOPS to account for different characteristics
|
||||
of Fortran regarding VOPs. */
|
||||
MAX_ALIASED_VOPS = 50;
|
||||
|
||||
return CL_Fortran;
|
||||
}
|
||||
|
||||
|
@ -506,6 +506,9 @@ decode_options (unsigned int argc, const char **argv)
|
||||
/* PRE tends to generate bigger code. */
|
||||
flag_tree_pre = 1;
|
||||
}
|
||||
|
||||
/* Allow more virtual operators to increase alias precision. */
|
||||
set_param_value ("max-aliased-vops", 500);
|
||||
}
|
||||
|
||||
if (optimize >= 3)
|
||||
@ -513,6 +516,10 @@ decode_options (unsigned int argc, const char **argv)
|
||||
flag_inline_functions = 1;
|
||||
flag_unswitch_loops = 1;
|
||||
flag_gcse_after_reload = 1;
|
||||
|
||||
/* Allow even more virtual operators. */
|
||||
set_param_value ("max-aliased-vops", 1000);
|
||||
set_param_value ("avg-aliased-vops", 3);
|
||||
}
|
||||
|
||||
if (optimize < 2 || optimize_size)
|
||||
|
@ -530,8 +530,13 @@ DEFPARAM(PARAM_MAX_RELOAD_SEARCH_INSNS,
|
||||
|
||||
DEFPARAM(PARAM_MAX_ALIASED_VOPS,
|
||||
"max-aliased-vops",
|
||||
"The maximum number of virtual operators per statement allowed to represent aliases before triggering alias grouping",
|
||||
10, 0, 0)
|
||||
"The maximum number of virtual operators that a function is allowed to have before triggering memory partitioning heuristics",
|
||||
100, 0, 0)
|
||||
|
||||
DEFPARAM(PARAM_AVG_ALIASED_VOPS,
|
||||
"avg-aliased-vops",
|
||||
"The average number of virtual operators that memory statements are allowed to have before triggering memory partitioning heuristics",
|
||||
1, 0, 0)
|
||||
|
||||
DEFPARAM(PARAM_MAX_SCHED_REGION_BLOCKS,
|
||||
"max-sched-region-blocks",
|
||||
|
@ -146,6 +146,8 @@ typedef enum compiler_param
|
||||
PARAM_VALUE (PARAM_SMS_LOOP_AVERAGE_COUNT_THRESHOLD)
|
||||
#define MAX_ALIASED_VOPS \
|
||||
PARAM_VALUE (PARAM_MAX_ALIASED_VOPS)
|
||||
#define AVG_ALIASED_VOPS \
|
||||
PARAM_VALUE (PARAM_AVG_ALIASED_VOPS)
|
||||
#define INTEGER_SHARE_LIMIT \
|
||||
PARAM_VALUE (PARAM_INTEGER_SHARE_LIMIT)
|
||||
#define MAX_LAST_VALUE_RTL \
|
||||
|
@ -346,34 +346,54 @@ dump_variable (FILE *file, tree var)
|
||||
if (TREE_THIS_VOLATILE (var))
|
||||
fprintf (file, ", is volatile");
|
||||
|
||||
if (mem_sym_stats (cfun, var))
|
||||
{
|
||||
mem_sym_stats_t stats = mem_sym_stats (cfun, var);
|
||||
fprintf (file, ", direct reads: %ld", stats->num_direct_reads);
|
||||
fprintf (file, ", direct writes: %ld", stats->num_direct_writes);
|
||||
fprintf (file, ", indirect reads: %ld", stats->num_indirect_reads);
|
||||
fprintf (file, ", indirect writes: %ld", stats->num_indirect_writes);
|
||||
fprintf (file, ", read frequency: %ld", stats->frequency_reads);
|
||||
fprintf (file, ", write frequency: %ld", stats->frequency_writes);
|
||||
}
|
||||
|
||||
if (is_call_clobbered (var))
|
||||
{
|
||||
const char *s = "";
|
||||
var_ann_t va = var_ann (var);
|
||||
unsigned int escape_mask = va->escape_mask;
|
||||
|
||||
fprintf (file, ", call clobbered");
|
||||
fprintf (file, " (");
|
||||
if (escape_mask & ESCAPE_STORED_IN_GLOBAL)
|
||||
fprintf (file, ", stored in global");
|
||||
{ fprintf (file, "%sstored in global", s); s = ", "; }
|
||||
if (escape_mask & ESCAPE_TO_ASM)
|
||||
fprintf (file, ", goes through ASM");
|
||||
{ fprintf (file, "%sgoes through ASM", s); s = ", "; }
|
||||
if (escape_mask & ESCAPE_TO_CALL)
|
||||
fprintf (file, ", passed to call");
|
||||
{ fprintf (file, "%spassed to call", s); s = ", "; }
|
||||
if (escape_mask & ESCAPE_BAD_CAST)
|
||||
fprintf (file, ", bad cast");
|
||||
{ fprintf (file, "%sbad cast", s); s = ", "; }
|
||||
if (escape_mask & ESCAPE_TO_RETURN)
|
||||
fprintf (file, ", returned from func");
|
||||
{ fprintf (file, "%sreturned from func", s); s = ", "; }
|
||||
if (escape_mask & ESCAPE_TO_PURE_CONST)
|
||||
fprintf (file, ", passed to pure/const");
|
||||
{ fprintf (file, "%spassed to pure/const", s); s = ", "; }
|
||||
if (escape_mask & ESCAPE_IS_GLOBAL)
|
||||
fprintf (file, ", is global var");
|
||||
{ fprintf (file, "%sis global var", s); s = ", "; }
|
||||
if (escape_mask & ESCAPE_IS_PARM)
|
||||
fprintf (file, ", is incoming pointer");
|
||||
{ fprintf (file, "%sis incoming pointer", s); s = ", "; }
|
||||
if (escape_mask & ESCAPE_UNKNOWN)
|
||||
fprintf (file, ", unknown escape");
|
||||
fprintf (file, " )");
|
||||
{ fprintf (file, "%sunknown escape", s); s = ", "; }
|
||||
fprintf (file, ")");
|
||||
}
|
||||
|
||||
if (ann->noalias_state == NO_ALIAS)
|
||||
fprintf (file, ", NO_ALIAS (does not alias other NO_ALIAS symbols)");
|
||||
else if (ann->noalias_state == NO_ALIAS_GLOBAL)
|
||||
fprintf (file, ", NO_ALIAS_GLOBAL (does not alias other NO_ALIAS symbols"
|
||||
" and global vars)");
|
||||
else if (ann->noalias_state == NO_ALIAS_ANYTHING)
|
||||
fprintf (file, ", NO_ALIAS_ANYTHING (does not alias any other symbols)");
|
||||
|
||||
if (gimple_default_def (cfun, var))
|
||||
{
|
||||
fprintf (file, ", default def: ");
|
||||
@ -618,8 +638,8 @@ referenced_var_lookup (unsigned int uid)
|
||||
{
|
||||
struct int_tree_map *h, in;
|
||||
in.uid = uid;
|
||||
h = (struct int_tree_map *) htab_find_with_hash (gimple_referenced_vars (cfun),
|
||||
&in, uid);
|
||||
h = (struct int_tree_map *)
|
||||
htab_find_with_hash (gimple_referenced_vars (cfun), &in, uid);
|
||||
gcc_assert (h || uid == 0);
|
||||
if (h)
|
||||
return h->to;
|
||||
@ -1011,3 +1031,26 @@ get_ref_base_and_extent (tree exp, HOST_WIDE_INT *poffset,
|
||||
|
||||
return exp;
|
||||
}
|
||||
|
||||
|
||||
/* Return memory reference statistics for variable VAR in function FN.
|
||||
This is computed by alias analysis, but it is not kept
|
||||
incrementally up-to-date. So, these stats are only accurate if
|
||||
pass_may_alias has been run recently. If no alias information
|
||||
exists, this function returns NULL. */
|
||||
|
||||
mem_sym_stats_t
|
||||
mem_sym_stats (struct function *fn, tree var)
|
||||
{
|
||||
void **slot;
|
||||
struct pointer_map_t *stats_map = gimple_mem_ref_stats (fn)->mem_sym_stats;
|
||||
|
||||
if (stats_map == NULL)
|
||||
return NULL;
|
||||
|
||||
slot = pointer_map_contains (stats_map, var);
|
||||
if (slot == NULL)
|
||||
return NULL;
|
||||
|
||||
return (mem_sym_stats_t) *slot;
|
||||
}
|
||||
|
@ -871,31 +871,6 @@ memory_partition (tree sym)
|
||||
return tag;
|
||||
}
|
||||
|
||||
|
||||
/* Set MPT to be the memory partition associated with symbol SYM. */
|
||||
|
||||
static inline void
|
||||
set_memory_partition (tree sym, tree mpt)
|
||||
{
|
||||
#if defined ENABLE_CHECKING
|
||||
if (mpt)
|
||||
gcc_assert (TREE_CODE (mpt) == MEMORY_PARTITION_TAG
|
||||
&& !is_gimple_reg (sym));
|
||||
#endif
|
||||
var_ann (sym)->mpt = mpt;
|
||||
if (mpt)
|
||||
{
|
||||
bitmap_set_bit (MPT_SYMBOLS (mpt), DECL_UID (sym));
|
||||
|
||||
/* MPT inherits the call-clobbering attributes from SYM. */
|
||||
if (is_call_clobbered (sym))
|
||||
{
|
||||
MTAG_GLOBAL (mpt) = 1;
|
||||
mark_call_clobbered (mpt, ESCAPE_IS_GLOBAL);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Return true if NAME is a memory factoring SSA name (i.e., an SSA
|
||||
name for a memory partition. */
|
||||
|
||||
@ -1810,4 +1785,11 @@ gimple_ssa_operands (struct function *fun)
|
||||
{
|
||||
return &fun->gimple_df->ssa_operands;
|
||||
}
|
||||
|
||||
/* Map describing reference statistics for function FN. */
|
||||
static inline struct mem_ref_stats_d *
|
||||
gimple_mem_ref_stats (struct function *fn)
|
||||
{
|
||||
return &fn->gimple_df->mem_ref_stats;
|
||||
}
|
||||
#endif /* _TREE_FLOW_INLINE_H */
|
||||
|
125
gcc/tree-flow.h
125
gcc/tree-flow.h
@ -41,10 +41,85 @@ typedef struct basic_block_def *basic_block;
|
||||
#endif
|
||||
struct static_var_ann_d;
|
||||
|
||||
/* Memory reference statistics for individual memory symbols,
|
||||
collected during alias analysis. */
|
||||
struct mem_sym_stats_d GTY(())
|
||||
{
|
||||
/* Memory symbol. */
|
||||
tree var;
|
||||
|
||||
/* Nonzero if this entry has been assigned a partition. */
|
||||
unsigned int partitioned_p : 1;
|
||||
|
||||
/* Nonzero if VAR is a memory partition tag that already contains
|
||||
call-clobbered variables in its partition set. */
|
||||
unsigned int has_call_clobbered_vars : 1;
|
||||
|
||||
/* Number of direct reference sites. A direct reference to VAR is any
|
||||
reference of the form 'VAR = ' or ' = VAR'. For GIMPLE reg
|
||||
pointers, this is the number of sites where the pointer is
|
||||
dereferenced. */
|
||||
long num_direct_writes;
|
||||
long num_direct_reads;
|
||||
|
||||
/* Number of indirect reference sites. An indirect reference to VAR
|
||||
is any reference via a pointer that contains VAR in its points-to
|
||||
set or, in the case of call-clobbered symbols, a function call. */
|
||||
long num_indirect_writes;
|
||||
long num_indirect_reads;
|
||||
|
||||
/* Execution frequency. This is the sum of the execution
|
||||
frequencies of all the statements that reference this object
|
||||
weighted by the number of references in each statement. This is
|
||||
the main key used to sort the list of symbols to partition.
|
||||
Symbols with high execution frequencies are put at the bottom of
|
||||
the work list (ie, they are partitioned last).
|
||||
Execution frequencies are taken directly from each basic block,
|
||||
so compiling with PGO enabled will increase the precision of this
|
||||
estimate. */
|
||||
long frequency_reads;
|
||||
long frequency_writes;
|
||||
|
||||
/* Set of memory tags that contain VAR in their alias set. */
|
||||
bitmap parent_tags;
|
||||
};
|
||||
|
||||
typedef struct mem_sym_stats_d *mem_sym_stats_t;
|
||||
DEF_VEC_P(mem_sym_stats_t);
|
||||
DEF_VEC_ALLOC_P(mem_sym_stats_t, heap);
|
||||
|
||||
/* Memory reference statistics collected during alias analysis. */
|
||||
struct mem_ref_stats_d GTY(())
|
||||
{
|
||||
/* Number of statements that make memory references. */
|
||||
long num_mem_stmts;
|
||||
|
||||
/* Number of statements that make function calls. */
|
||||
long num_call_sites;
|
||||
|
||||
/* Number of statements that make calls to pure/const functions. */
|
||||
long num_pure_const_call_sites;
|
||||
|
||||
/* Number of ASM statements. */
|
||||
long num_asm_sites;
|
||||
|
||||
/* Estimated number of virtual operands needed as computed by
|
||||
compute_memory_partitions. */
|
||||
long num_vuses;
|
||||
long num_vdefs;
|
||||
|
||||
/* This maps every symbol used to make "memory" references
|
||||
(pointers, arrays, structures, etc) to an instance of struct
|
||||
mem_sym_stats_d describing reference statistics for the symbol. */
|
||||
struct pointer_map_t * GTY((skip)) mem_sym_stats;
|
||||
};
|
||||
|
||||
|
||||
/* Gimple dataflow datastructure. All publicly available fields shall have
|
||||
gimple_ accessor defined in tree-flow-inline.h, all publicly modifiable
|
||||
fields should have gimple_set accessor. */
|
||||
struct gimple_df GTY(()) {
|
||||
struct gimple_df GTY(())
|
||||
{
|
||||
/* Array of all variables referenced in the function. */
|
||||
htab_t GTY((param_is (struct int_tree_map))) referenced_vars;
|
||||
|
||||
@ -98,6 +173,11 @@ struct gimple_df GTY(()) {
|
||||
/* Hashtable of variables annotations. Used for static variables only;
|
||||
local variables have direct pointer in the tree node. */
|
||||
htab_t GTY((param_is (struct static_var_ann_d))) var_anns;
|
||||
|
||||
/* Memory reference statistics collected during alias analysis.
|
||||
This information is used to drive the memory partitioning
|
||||
heuristics in compute_memory_partitions. */
|
||||
struct mem_ref_stats_d mem_ref_stats;
|
||||
};
|
||||
|
||||
/* Accessors for internal use only. Generic code should use abstraction
|
||||
@ -205,6 +285,30 @@ enum need_phi_state {
|
||||
NEED_PHI_STATE_MAYBE
|
||||
};
|
||||
|
||||
|
||||
/* The "no alias" attribute allows alias analysis to make more
|
||||
aggressive assumptions when assigning alias sets, computing
|
||||
points-to information and memory partitions. These attributes
|
||||
are the result of user annotations or flags (e.g.,
|
||||
-fargument-noalias). */
|
||||
enum noalias_state {
|
||||
/* Default state. No special assumptions can be made about this
|
||||
symbol. */
|
||||
MAY_ALIAS = 0,
|
||||
|
||||
/* The symbol does not alias with other symbols that have a
|
||||
NO_ALIAS* attribute. */
|
||||
NO_ALIAS,
|
||||
|
||||
/* The symbol does not alias with other symbols that have a
|
||||
NO_ALIAS*, and it may not alias with global symbols. */
|
||||
NO_ALIAS_GLOBAL,
|
||||
|
||||
/* The symbol does not alias with any other symbols. */
|
||||
NO_ALIAS_ANYTHING
|
||||
};
|
||||
|
||||
|
||||
struct subvar;
|
||||
typedef struct subvar *subvar_t;
|
||||
|
||||
@ -246,12 +350,18 @@ struct var_ann_d GTY(())
|
||||
in the VDEF list. */
|
||||
unsigned in_vdef_list : 1;
|
||||
|
||||
/* True for HEAP and PARM_NOALIAS artificial variables. */
|
||||
/* True for HEAP artificial variables. These variables represent
|
||||
the memory area allocated by a call to malloc. */
|
||||
unsigned is_heapvar : 1;
|
||||
|
||||
/* True if the variable is call clobbered. */
|
||||
unsigned int call_clobbered : 1;
|
||||
|
||||
/* This field describes several "no alias" attributes that some
|
||||
symbols are known to have. See the enum's definition for more
|
||||
information on each attribute. */
|
||||
ENUM_BITFIELD (noalias_state) noalias_state : 2;
|
||||
|
||||
/* Memory partition tag assigned to this symbol. */
|
||||
tree mpt;
|
||||
|
||||
@ -694,10 +804,10 @@ extern void add_referenced_var (tree);
|
||||
extern void remove_referenced_var (tree);
|
||||
extern void mark_symbols_for_renaming (tree);
|
||||
extern void find_new_referenced_vars (tree *);
|
||||
|
||||
extern tree make_rename_temp (tree, const char *);
|
||||
extern void set_default_def (tree, tree);
|
||||
extern tree gimple_default_def (struct function *, tree);
|
||||
extern struct mem_sym_stats_d *mem_sym_stats (struct function *, tree);
|
||||
|
||||
/* In tree-phinodes.c */
|
||||
extern void reserve_phi_args_for_new_edge (basic_block);
|
||||
@ -725,7 +835,8 @@ extern bool may_be_aliased (tree);
|
||||
extern bool is_aliased_with (tree, tree);
|
||||
extern struct ptr_info_def *get_ptr_info (tree);
|
||||
extern void new_type_alias (tree, tree, tree);
|
||||
extern void count_uses_and_derefs (tree, tree, unsigned *, unsigned *, bool *);
|
||||
extern void count_uses_and_derefs (tree, tree, unsigned *, unsigned *,
|
||||
unsigned *);
|
||||
static inline subvar_t get_subvars_for_var (tree);
|
||||
static inline tree get_subvar_at (tree, unsigned HOST_WIDE_INT);
|
||||
static inline bool ref_contains_array_ref (tree);
|
||||
@ -737,6 +848,12 @@ static inline bool overlap_subvar (unsigned HOST_WIDE_INT,
|
||||
unsigned HOST_WIDE_INT,
|
||||
tree, bool *);
|
||||
extern tree create_tag_raw (enum tree_code, tree, const char *);
|
||||
extern void delete_mem_ref_stats (struct function *);
|
||||
extern void dump_mem_ref_stats (FILE *);
|
||||
extern void debug_mem_ref_stats (void);
|
||||
extern void debug_memory_partitions (void);
|
||||
extern void debug_mem_sym_stats (tree var);
|
||||
extern void debug_all_mem_sym_stats (void);
|
||||
|
||||
/* Call-back function for walk_use_def_chains(). At each reaching
|
||||
definition, a function with this prototype is called. */
|
||||
|
1285
gcc/tree-ssa-alias.c
1285
gcc/tree-ssa-alias.c
File diff suppressed because it is too large
Load Diff
@ -69,17 +69,17 @@ may_propagate_copy (tree dest, tree orig)
|
||||
&& TREE_CODE (SSA_NAME_VAR (dest)) == MEMORY_PARTITION_TAG)
|
||||
return (TREE_CODE (orig) == SSA_NAME
|
||||
&& !is_gimple_reg (orig)
|
||||
&& (bitmap_bit_p (MPT_SYMBOLS (SSA_NAME_VAR (dest)),
|
||||
DECL_UID (SSA_NAME_VAR (orig)))
|
||||
|| SSA_NAME_VAR (dest) == SSA_NAME_VAR (orig)));
|
||||
&& (SSA_NAME_VAR (dest) == SSA_NAME_VAR (orig)
|
||||
|| bitmap_bit_p (MPT_SYMBOLS (SSA_NAME_VAR (dest)),
|
||||
DECL_UID (SSA_NAME_VAR (orig)))));
|
||||
|
||||
if (TREE_CODE (orig) == SSA_NAME
|
||||
&& TREE_CODE (SSA_NAME_VAR (orig)) == MEMORY_PARTITION_TAG)
|
||||
return (TREE_CODE (dest) == SSA_NAME
|
||||
&& !is_gimple_reg (dest)
|
||||
&& (bitmap_bit_p (MPT_SYMBOLS (SSA_NAME_VAR (orig)),
|
||||
DECL_UID (SSA_NAME_VAR (dest)))
|
||||
|| SSA_NAME_VAR (dest) == SSA_NAME_VAR (orig)));
|
||||
&& (SSA_NAME_VAR (dest) == SSA_NAME_VAR (orig)
|
||||
|| bitmap_bit_p (MPT_SYMBOLS (SSA_NAME_VAR (orig)),
|
||||
DECL_UID (SSA_NAME_VAR (dest)))));
|
||||
|
||||
/* Do not copy between types for which we *do* need a conversion. */
|
||||
if (!tree_ssa_useless_type_conversion_1 (type_d, type_o))
|
||||
|
@ -2980,89 +2980,3 @@ stmt_references_memory_p (tree stmt)
|
||||
|
||||
return stmt_ann (stmt)->references_memory;
|
||||
}
|
||||
|
||||
|
||||
/* Return the memory partition tag (MPT) associated with memory
|
||||
symbol SYM. From a correctness standpoint, memory partitions can
|
||||
be assigned in any arbitrary fashion as long as this rule is
|
||||
observed: Given two memory partitions MPT.i and MPT.j, they must
|
||||
not contain symbols in common.
|
||||
|
||||
Memory partitions are used when putting the program into Memory-SSA
|
||||
form. In particular, in Memory-SSA PHI nodes are not computed for
|
||||
individual memory symbols. They are computed for memory
|
||||
partitions. This reduces the amount of PHI nodes in the SSA graph
|
||||
at the expense of precision (i.e., it makes unrelated stores affect
|
||||
each other).
|
||||
|
||||
However, it is possible to increase precision by changing this
|
||||
partitioning scheme. For instance, if the partitioning scheme is
|
||||
such that get_mpt_for is the identity function (that is,
|
||||
get_mpt_for (s) = s), this will result in ultimate precision at the
|
||||
expense of huge SSA webs.
|
||||
|
||||
At the other extreme, a partitioning scheme that groups all the
|
||||
symbols in the same set results in minimal SSA webs and almost
|
||||
total loss of precision. */
|
||||
|
||||
tree
|
||||
get_mpt_for (tree sym)
|
||||
{
|
||||
tree mpt;
|
||||
|
||||
/* Don't create a new tag unnecessarily. */
|
||||
mpt = memory_partition (sym);
|
||||
if (mpt == NULL_TREE)
|
||||
{
|
||||
mpt = create_tag_raw (MEMORY_PARTITION_TAG, TREE_TYPE (sym), "MPT");
|
||||
TREE_ADDRESSABLE (mpt) = 0;
|
||||
MTAG_GLOBAL (mpt) = 1;
|
||||
add_referenced_var (mpt);
|
||||
VEC_safe_push (tree, heap, gimple_ssa_operands (cfun)->mpt_table, mpt);
|
||||
MPT_SYMBOLS (mpt) = BITMAP_ALLOC (&operands_bitmap_obstack);
|
||||
set_memory_partition (sym, mpt);
|
||||
}
|
||||
|
||||
return mpt;
|
||||
}
|
||||
|
||||
|
||||
/* Dump memory partition information to FILE. */
|
||||
|
||||
void
|
||||
dump_memory_partitions (FILE *file)
|
||||
{
|
||||
unsigned i, npart;
|
||||
unsigned long nsyms;
|
||||
tree mpt;
|
||||
|
||||
fprintf (file, "\nMemory partitions\n\n");
|
||||
for (i = 0, npart = 0, nsyms = 0;
|
||||
VEC_iterate (tree, gimple_ssa_operands (cfun)->mpt_table, i, mpt);
|
||||
i++)
|
||||
{
|
||||
if (mpt)
|
||||
{
|
||||
bitmap syms = MPT_SYMBOLS (mpt);
|
||||
unsigned long n = bitmap_count_bits (syms);
|
||||
|
||||
fprintf (file, "#%u: ", i);
|
||||
print_generic_expr (file, mpt, 0);
|
||||
fprintf (file, ": %lu elements: ", n);
|
||||
dump_decl_set (file, syms);
|
||||
npart++;
|
||||
nsyms += n;
|
||||
}
|
||||
}
|
||||
|
||||
fprintf (file, "\n%u memory partitions holding %lu symbols\n", npart, nsyms);
|
||||
}
|
||||
|
||||
|
||||
/* Dump memory partition information to stderr. */
|
||||
|
||||
void
|
||||
debug_memory_partitions (void)
|
||||
{
|
||||
dump_memory_partitions (stderr);
|
||||
}
|
||||
|
@ -357,8 +357,4 @@ typedef struct ssa_operand_iterator_d
|
||||
/* This macro counts the number of operands in STMT matching FLAGS. */
|
||||
#define NUM_SSA_OPERANDS(STMT, FLAGS) num_ssa_operands (STMT, FLAGS)
|
||||
|
||||
extern tree get_mpt_for (tree);
|
||||
extern void dump_memory_partitions (FILE *);
|
||||
extern void debug_memory_partitions (void);
|
||||
|
||||
#endif /* GCC_TREE_SSA_OPERANDS_H */
|
||||
|
@ -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;
|
||||
|
@ -49,12 +49,6 @@ struct alias_info
|
||||
struct alias_map_d **pointers;
|
||||
size_t num_pointers;
|
||||
|
||||
/* 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;
|
||||
|
||||
/* Variables that have been written to directly (i.e., not through a
|
||||
pointer dereference). */
|
||||
struct pointer_set_t *written_vars;
|
||||
@ -71,6 +65,7 @@ struct alias_info
|
||||
|
||||
/* In tree-ssa-alias.c. */
|
||||
enum escape_type is_escape_site (tree);
|
||||
void update_mem_sym_stats_from_stmt (tree, tree, long, long);
|
||||
|
||||
/* In tree-ssa-structalias.c. */
|
||||
extern void compute_points_to_sets (struct alias_info *);
|
||||
|
@ -538,6 +538,51 @@ verify_call_clobbering (void)
|
||||
internal_error ("verify_call_clobbering failed");
|
||||
}
|
||||
|
||||
|
||||
/* Verify invariants in memory partitions. */
|
||||
|
||||
static void
|
||||
verify_memory_partitions (void)
|
||||
{
|
||||
unsigned i;
|
||||
tree mpt;
|
||||
VEC(tree,heap) *mpt_table = gimple_ssa_operands (cfun)->mpt_table;
|
||||
struct pointer_set_t *partitioned_syms = pointer_set_create ();
|
||||
|
||||
for (i = 0; VEC_iterate (tree, mpt_table, i, mpt); i++)
|
||||
{
|
||||
unsigned j;
|
||||
bitmap_iterator bj;
|
||||
|
||||
if (MPT_SYMBOLS (mpt) == NULL)
|
||||
{
|
||||
error ("Memory partitions should have at least one symbol");
|
||||
debug_variable (mpt);
|
||||
goto err;
|
||||
}
|
||||
|
||||
EXECUTE_IF_SET_IN_BITMAP (MPT_SYMBOLS (mpt), 0, j, bj)
|
||||
{
|
||||
tree var = referenced_var (j);
|
||||
if (pointer_set_insert (partitioned_syms, var))
|
||||
{
|
||||
error ("Partitioned symbols should belong to exactly one "
|
||||
"partition");
|
||||
debug_variable (var);
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pointer_set_destroy (partitioned_syms);
|
||||
|
||||
return;
|
||||
|
||||
err:
|
||||
internal_error ("verify_memory_partitions failed");
|
||||
}
|
||||
|
||||
|
||||
/* Verify the consistency of aliasing information. */
|
||||
|
||||
static void
|
||||
@ -546,6 +591,7 @@ verify_alias_info (void)
|
||||
verify_flow_sensitive_alias_info ();
|
||||
verify_call_clobbering ();
|
||||
verify_flow_insensitive_alias_info ();
|
||||
verify_memory_partitions ();
|
||||
}
|
||||
|
||||
|
||||
@ -835,6 +881,7 @@ delete_tree_ssa (void)
|
||||
gcc_assert (!need_ssa_update_p ());
|
||||
}
|
||||
cfun->gimple_df->aliases_computed_p = false;
|
||||
delete_mem_ref_stats (cfun);
|
||||
|
||||
cfun->gimple_df = NULL;
|
||||
}
|
||||
|
@ -3121,11 +3121,10 @@ infer_value_range (tree stmt, tree op, enum tree_code *comp_code_p, tree *val_p)
|
||||
non-NULL if -fdelete-null-pointer-checks is enabled. */
|
||||
if (flag_delete_null_pointer_checks && POINTER_TYPE_P (TREE_TYPE (op)))
|
||||
{
|
||||
bool is_store;
|
||||
unsigned num_uses, num_derefs;
|
||||
unsigned num_uses, num_loads, num_stores;
|
||||
|
||||
count_uses_and_derefs (op, stmt, &num_uses, &num_derefs, &is_store);
|
||||
if (num_derefs > 0)
|
||||
count_uses_and_derefs (op, stmt, &num_uses, &num_loads, &num_stores);
|
||||
if (num_loads + num_stores > 0)
|
||||
{
|
||||
*val_p = build_int_cst (TREE_TYPE (op), 0);
|
||||
*comp_code_p = NE_EXPR;
|
||||
|
Loading…
x
Reference in New Issue
Block a user