Commit bdb01696 by Richard Biener Committed by Richard Biener

re PR middle-end/39326 (Segmentation fault with -O1, out of memory with -O2)

2013-03-18  Richard Biener  <rguenther@suse.de>

	PR tree-optimization/39326
	* tree-ssa-loop-im.c (refs_independent_p): Exploit symmetry.
	(struct mem_ref): Replace mem member with ao_ref typed member.
	(MEM_ANALYZABLE): Adjust.
	(memref_eq): Likewise.
	(mem_ref_alloc): Likewise.
	(gather_mem_refs_stmt): Likewise.
	(mem_refs_may_alias_p): Use the ao_ref to query the alias oracle.
	(execute_sm_if_changed_flag_set): Adjust.
	(execute_sm): Likewise.
	(ref_always_accessed_p): Likewise.
	(refs_independent_p): Likewise.
	(can_sm_ref_p): Likewise.

From-SVN: r196768
parent 12d2dc5e
2013-03-18 Richard Biener <rguenther@suse.de>
PR tree-optimization/39326
* tree-ssa-loop-im.c (refs_independent_p): Exploit symmetry.
(struct mem_ref): Replace mem member with ao_ref typed member.
(MEM_ANALYZABLE): Adjust.
(memref_eq): Likewise.
(mem_ref_alloc): Likewise.
(gather_mem_refs_stmt): Likewise.
(mem_refs_may_alias_p): Use the ao_ref to query the alias oracle.
(execute_sm_if_changed_flag_set): Adjust.
(execute_sm): Likewise.
(ref_always_accessed_p): Likewise.
(refs_independent_p): Likewise.
(can_sm_ref_p): Likewise.
2013-03-18 Jakub Jelinek <jakub@redhat.com> 2013-03-18 Jakub Jelinek <jakub@redhat.com>
PR c/56566 PR c/56566
......
...@@ -117,10 +117,14 @@ typedef struct mem_ref_locs ...@@ -117,10 +117,14 @@ typedef struct mem_ref_locs
typedef struct mem_ref typedef struct mem_ref
{ {
tree mem; /* The memory itself. */
unsigned id; /* ID assigned to the memory reference unsigned id; /* ID assigned to the memory reference
(its index in memory_accesses.refs_list) */ (its index in memory_accesses.refs_list) */
hashval_t hash; /* Its hash value. */ hashval_t hash; /* Its hash value. */
/* The memory access itself and associated caching of alias-oracle
query meta-data. */
ao_ref mem;
bitmap stored; /* The set of loops in that this memory location bitmap stored; /* The set of loops in that this memory location
is stored to. */ is stored to. */
vec<mem_ref_locs_p> accesses_in_loop; vec<mem_ref_locs_p> accesses_in_loop;
...@@ -186,7 +190,7 @@ static bool ref_indep_loop_p (struct loop *, mem_ref_p); ...@@ -186,7 +190,7 @@ static bool ref_indep_loop_p (struct loop *, mem_ref_p);
#define SET_ALWAYS_EXECUTED_IN(BB, VAL) ((BB)->aux = (void *) (VAL)) #define SET_ALWAYS_EXECUTED_IN(BB, VAL) ((BB)->aux = (void *) (VAL))
/* Whether the reference was analyzable. */ /* Whether the reference was analyzable. */
#define MEM_ANALYZABLE(REF) ((REF)->mem != error_mark_node) #define MEM_ANALYZABLE(REF) ((REF)->mem.ref != error_mark_node)
static struct lim_aux_data * static struct lim_aux_data *
init_lim_data (gimple stmt) init_lim_data (gimple stmt)
...@@ -1449,7 +1453,7 @@ memref_eq (const void *obj1, const void *obj2) ...@@ -1449,7 +1453,7 @@ memref_eq (const void *obj1, const void *obj2)
{ {
const struct mem_ref *const mem1 = (const struct mem_ref *) obj1; const struct mem_ref *const mem1 = (const struct mem_ref *) obj1;
return operand_equal_p (mem1->mem, (const_tree) obj2, 0); return operand_equal_p (mem1->mem.ref, (const_tree) obj2, 0);
} }
/* Releases list of memory reference locations ACCS. */ /* Releases list of memory reference locations ACCS. */
...@@ -1491,7 +1495,7 @@ static mem_ref_p ...@@ -1491,7 +1495,7 @@ static mem_ref_p
mem_ref_alloc (tree mem, unsigned hash, unsigned id) mem_ref_alloc (tree mem, unsigned hash, unsigned id)
{ {
mem_ref_p ref = XNEW (struct mem_ref); mem_ref_p ref = XNEW (struct mem_ref);
ref->mem = mem; ao_ref_init (&ref->mem, mem);
ref->id = id; ref->id = id;
ref->hash = hash; ref->hash = hash;
ref->stored = BITMAP_ALLOC (&lim_bitmap_obstack); ref->stored = BITMAP_ALLOC (&lim_bitmap_obstack);
...@@ -1606,7 +1610,7 @@ gather_mem_refs_stmt (struct loop *loop, gimple stmt) ...@@ -1606,7 +1610,7 @@ gather_mem_refs_stmt (struct loop *loop, gimple stmt)
if (dump_file && (dump_flags & TDF_DETAILS)) if (dump_file && (dump_flags & TDF_DETAILS))
{ {
fprintf (dump_file, "Memory reference %u: ", id); fprintf (dump_file, "Memory reference %u: ", id);
print_generic_expr (dump_file, ref->mem, TDF_SLIM); print_generic_expr (dump_file, ref->mem.ref, TDF_SLIM);
fprintf (dump_file, "\n"); fprintf (dump_file, "\n");
} }
} }
...@@ -1730,7 +1734,8 @@ analyze_memory_references (void) ...@@ -1730,7 +1734,8 @@ analyze_memory_references (void)
tree_to_aff_combination_expand. */ tree_to_aff_combination_expand. */
static bool static bool
mem_refs_may_alias_p (tree mem1, tree mem2, struct pointer_map_t **ttae_cache) mem_refs_may_alias_p (mem_ref_p mem1, mem_ref_p mem2,
struct pointer_map_t **ttae_cache)
{ {
/* Perform BASE + OFFSET analysis -- if MEM1 and MEM2 are based on the same /* Perform BASE + OFFSET analysis -- if MEM1 and MEM2 are based on the same
object and their offset differ in such a way that the locations cannot object and their offset differ in such a way that the locations cannot
...@@ -1739,7 +1744,7 @@ mem_refs_may_alias_p (tree mem1, tree mem2, struct pointer_map_t **ttae_cache) ...@@ -1739,7 +1744,7 @@ mem_refs_may_alias_p (tree mem1, tree mem2, struct pointer_map_t **ttae_cache)
aff_tree off1, off2; aff_tree off1, off2;
/* Perform basic offset and type-based disambiguation. */ /* Perform basic offset and type-based disambiguation. */
if (!refs_may_alias_p (mem1, mem2)) if (!refs_may_alias_p_1 (&mem1->mem, &mem2->mem, true))
return false; return false;
/* The expansion of addresses may be a bit expensive, thus we only do /* The expansion of addresses may be a bit expensive, thus we only do
...@@ -1747,8 +1752,8 @@ mem_refs_may_alias_p (tree mem1, tree mem2, struct pointer_map_t **ttae_cache) ...@@ -1747,8 +1752,8 @@ mem_refs_may_alias_p (tree mem1, tree mem2, struct pointer_map_t **ttae_cache)
if (optimize < 2) if (optimize < 2)
return true; return true;
get_inner_reference_aff (mem1, &off1, &size1); get_inner_reference_aff (mem1->mem.ref, &off1, &size1);
get_inner_reference_aff (mem2, &off2, &size2); get_inner_reference_aff (mem2->mem.ref, &off2, &size2);
aff_combination_expand (&off1, ttae_cache); aff_combination_expand (&off1, ttae_cache);
aff_combination_expand (&off2, ttae_cache); aff_combination_expand (&off2, ttae_cache);
aff_combination_scale (&off1, double_int_minus_one); aff_combination_scale (&off1, double_int_minus_one);
...@@ -2079,7 +2084,7 @@ execute_sm_if_changed_flag_set (struct loop *loop, mem_ref_p ref) ...@@ -2079,7 +2084,7 @@ execute_sm_if_changed_flag_set (struct loop *loop, mem_ref_p ref)
mem_ref_loc_p loc; mem_ref_loc_p loc;
tree flag; tree flag;
vec<mem_ref_loc_p> locs = vNULL; vec<mem_ref_loc_p> locs = vNULL;
char *str = get_lsm_tmp_name (ref->mem, ~0); char *str = get_lsm_tmp_name (ref->mem.ref, ~0);
lsm_tmp_name_add ("_flag"); lsm_tmp_name_add ("_flag");
flag = create_tmp_reg (boolean_type_node, str); flag = create_tmp_reg (boolean_type_node, str);
...@@ -2121,16 +2126,16 @@ execute_sm (struct loop *loop, vec<edge> exits, mem_ref_p ref) ...@@ -2121,16 +2126,16 @@ execute_sm (struct loop *loop, vec<edge> exits, mem_ref_p ref)
if (dump_file && (dump_flags & TDF_DETAILS)) if (dump_file && (dump_flags & TDF_DETAILS))
{ {
fprintf (dump_file, "Executing store motion of "); fprintf (dump_file, "Executing store motion of ");
print_generic_expr (dump_file, ref->mem, 0); print_generic_expr (dump_file, ref->mem.ref, 0);
fprintf (dump_file, " from loop %d\n", loop->num); fprintf (dump_file, " from loop %d\n", loop->num);
} }
tmp_var = create_tmp_reg (TREE_TYPE (ref->mem), tmp_var = create_tmp_reg (TREE_TYPE (ref->mem.ref),
get_lsm_tmp_name (ref->mem, ~0)); get_lsm_tmp_name (ref->mem.ref, ~0));
fmt_data.loop = loop; fmt_data.loop = loop;
fmt_data.orig_loop = loop; fmt_data.orig_loop = loop;
for_each_index (&ref->mem, force_move_till, &fmt_data); for_each_index (&ref->mem.ref, force_move_till, &fmt_data);
if (block_in_transaction (loop_preheader_edge (loop)->src) if (block_in_transaction (loop_preheader_edge (loop)->src)
|| !PARAM_VALUE (PARAM_ALLOW_STORE_DATA_RACES)) || !PARAM_VALUE (PARAM_ALLOW_STORE_DATA_RACES))
...@@ -2148,7 +2153,7 @@ execute_sm (struct loop *loop, vec<edge> exits, mem_ref_p ref) ...@@ -2148,7 +2153,7 @@ execute_sm (struct loop *loop, vec<edge> exits, mem_ref_p ref)
/* FIXME/TODO: For the multi-threaded variant, we could avoid this /* FIXME/TODO: For the multi-threaded variant, we could avoid this
load altogether, since the store is predicated by a flag. We load altogether, since the store is predicated by a flag. We
could, do the load only if it was originally in the loop. */ could, do the load only if it was originally in the loop. */
load = gimple_build_assign (tmp_var, unshare_expr (ref->mem)); load = gimple_build_assign (tmp_var, unshare_expr (ref->mem.ref));
lim_data = init_lim_data (load); lim_data = init_lim_data (load);
lim_data->max_loop = loop; lim_data->max_loop = loop;
lim_data->tgt_loop = loop; lim_data->tgt_loop = loop;
...@@ -2168,11 +2173,11 @@ execute_sm (struct loop *loop, vec<edge> exits, mem_ref_p ref) ...@@ -2168,11 +2173,11 @@ execute_sm (struct loop *loop, vec<edge> exits, mem_ref_p ref)
if (!multi_threaded_model_p) if (!multi_threaded_model_p)
{ {
gimple store; gimple store;
store = gimple_build_assign (unshare_expr (ref->mem), tmp_var); store = gimple_build_assign (unshare_expr (ref->mem.ref), tmp_var);
gsi_insert_on_edge (ex, store); gsi_insert_on_edge (ex, store);
} }
else else
execute_sm_if_changed (ex, ref->mem, tmp_var, store_flag); execute_sm_if_changed (ex, ref->mem.ref, tmp_var, store_flag);
} }
/* Hoists memory references MEM_REFS out of LOOP. EXITS is the list of exit /* Hoists memory references MEM_REFS out of LOOP. EXITS is the list of exit
...@@ -2206,9 +2211,8 @@ ref_always_accessed_p (struct loop *loop, mem_ref_p ref, bool stored_p) ...@@ -2206,9 +2211,8 @@ ref_always_accessed_p (struct loop *loop, mem_ref_p ref, bool stored_p)
struct loop *must_exec; struct loop *must_exec;
tree base; tree base;
base = get_base_address (ref->mem); base = ao_ref_base (&ref->mem);
if (INDIRECT_REF_P (base) if (TREE_CODE (base) == MEM_REF)
|| TREE_CODE (base) == MEM_REF)
base = TREE_OPERAND (base, 0); base = TREE_OPERAND (base, 0);
get_all_locs_in_loop (loop, ref, &locs); get_all_locs_in_loop (loop, ref, &locs);
...@@ -2255,24 +2259,33 @@ ref_always_accessed_p (struct loop *loop, mem_ref_p ref, bool stored_p) ...@@ -2255,24 +2259,33 @@ ref_always_accessed_p (struct loop *loop, mem_ref_p ref, bool stored_p)
static bool static bool
refs_independent_p (mem_ref_p ref1, mem_ref_p ref2) refs_independent_p (mem_ref_p ref1, mem_ref_p ref2)
{ {
if (ref1 == ref2 if (ref1 == ref2)
|| bitmap_bit_p (ref1->indep_ref, ref2->id))
return true; return true;
if (bitmap_bit_p (ref1->dep_ref, ref2->id))
return false;
if (!MEM_ANALYZABLE (ref1) if (!MEM_ANALYZABLE (ref1)
|| !MEM_ANALYZABLE (ref2)) || !MEM_ANALYZABLE (ref2))
return false; return false;
/* Reference dependence in a loop is symmetric. */
if (ref1->id > ref2->id)
{
mem_ref_p tem = ref1;
ref1 = ref2;
ref2 = tem;
}
if (bitmap_bit_p (ref1->indep_ref, ref2->id))
return true;
if (bitmap_bit_p (ref1->dep_ref, ref2->id))
return false;
if (dump_file && (dump_flags & TDF_DETAILS)) if (dump_file && (dump_flags & TDF_DETAILS))
fprintf (dump_file, "Querying dependency of refs %u and %u: ", fprintf (dump_file, "Querying dependency of refs %u and %u: ",
ref1->id, ref2->id); ref1->id, ref2->id);
if (mem_refs_may_alias_p (ref1->mem, ref2->mem, if (mem_refs_may_alias_p (ref1, ref2, &memory_accesses.ttae_cache))
&memory_accesses.ttae_cache))
{ {
bitmap_set_bit (ref1->dep_ref, ref2->id); bitmap_set_bit (ref1->dep_ref, ref2->id);
bitmap_set_bit (ref2->dep_ref, ref1->id);
if (dump_file && (dump_flags & TDF_DETAILS)) if (dump_file && (dump_flags & TDF_DETAILS))
fprintf (dump_file, "dependent.\n"); fprintf (dump_file, "dependent.\n");
return false; return false;
...@@ -2280,7 +2293,6 @@ refs_independent_p (mem_ref_p ref1, mem_ref_p ref2) ...@@ -2280,7 +2293,6 @@ refs_independent_p (mem_ref_p ref1, mem_ref_p ref2)
else else
{ {
bitmap_set_bit (ref1->indep_ref, ref2->id); bitmap_set_bit (ref1->indep_ref, ref2->id);
bitmap_set_bit (ref2->indep_ref, ref1->id);
if (dump_file && (dump_flags & TDF_DETAILS)) if (dump_file && (dump_flags & TDF_DETAILS))
fprintf (dump_file, "independent.\n"); fprintf (dump_file, "independent.\n");
return true; return true;
...@@ -2371,21 +2383,21 @@ can_sm_ref_p (struct loop *loop, mem_ref_p ref) ...@@ -2371,21 +2383,21 @@ can_sm_ref_p (struct loop *loop, mem_ref_p ref)
return false; return false;
/* It should be movable. */ /* It should be movable. */
if (!is_gimple_reg_type (TREE_TYPE (ref->mem)) if (!is_gimple_reg_type (TREE_TYPE (ref->mem.ref))
|| TREE_THIS_VOLATILE (ref->mem) || TREE_THIS_VOLATILE (ref->mem.ref)
|| !for_each_index (&ref->mem, may_move_till, loop)) || !for_each_index (&ref->mem.ref, may_move_till, loop))
return false; return false;
/* If it can throw fail, we do not properly update EH info. */ /* If it can throw fail, we do not properly update EH info. */
if (tree_could_throw_p (ref->mem)) if (tree_could_throw_p (ref->mem.ref))
return false; return false;
/* If it can trap, it must be always executed in LOOP. /* If it can trap, it must be always executed in LOOP.
Readonly memory locations may trap when storing to them, but Readonly memory locations may trap when storing to them, but
tree_could_trap_p is a predicate for rvalues, so check that tree_could_trap_p is a predicate for rvalues, so check that
explicitly. */ explicitly. */
base = get_base_address (ref->mem); base = get_base_address (ref->mem.ref);
if ((tree_could_trap_p (ref->mem) if ((tree_could_trap_p (ref->mem.ref)
|| (DECL_P (base) && TREE_READONLY (base))) || (DECL_P (base) && TREE_READONLY (base)))
&& !ref_always_accessed_p (loop, ref, true)) && !ref_always_accessed_p (loop, ref, true))
return false; return false;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment