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:
Diego Novillo 2007-04-11 16:14:06 +00:00 committed by Diego Novillo
parent 574e75f5fb
commit e9e0aa2c96
17 changed files with 1467 additions and 465 deletions

View File

@ -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

View File

@ -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

View File

@ -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;
}

View File

@ -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)

View File

@ -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",

View File

@ -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 \

View File

@ -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;
}

View File

@ -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 */

View File

@ -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. */

File diff suppressed because it is too large Load Diff

View File

@ -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))

View File

@ -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);
}

View File

@ -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 */

View File

@ -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;

View File

@ -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 *);

View File

@ -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;
}

View File

@ -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;