tree-ssa-loop-im.c (struct mem_ref_locs): Remove.

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

	* tree-ssa-loop-im.c (struct mem_ref_locs): Remove.
	(struct mem_ref): Make accesses_in_loop a vec of a vec of
	aggregate mem_ref_loc.
	(free_mem_ref_locs): Inline into ...
	(memref_free): ... this and adjust.
	(mem_ref_alloc): Adjust.
	(mem_ref_locs_alloc): Remove.
	(record_mem_ref_loc): Adjust.
	(get_all_locs_in_loop): Rewrite into ...
	(for_all_locs_in_loop): ... this iterator.
	(rewrite_mem_ref_loc): New functor.
	(rewrite_mem_refs): Use for_all_locs_in_loop.
	(sm_set_flag_if_changed): New functor.
	(execute_sm_if_changed_flag_set): Use for_all_locs_in_loop.
	(ref_always_accessed): New functor.
	(ref_always_accessed_p): Use for_all_locs_in_loop.

From-SVN: r196899
This commit is contained in:
Richard Biener 2013-03-22 09:12:46 +00:00 committed by Richard Biener
parent 9dc6f476ce
commit 15d19bf8d0
2 changed files with 133 additions and 149 deletions

View File

@ -1,3 +1,22 @@
2013-03-22 Richard Biener <rguenther@suse.de>
* tree-ssa-loop-im.c (struct mem_ref_locs): Remove.
(struct mem_ref): Make accesses_in_loop a vec of a vec of
aggregate mem_ref_loc.
(free_mem_ref_locs): Inline into ...
(memref_free): ... this and adjust.
(mem_ref_alloc): Adjust.
(mem_ref_locs_alloc): Remove.
(record_mem_ref_loc): Adjust.
(get_all_locs_in_loop): Rewrite into ...
(for_all_locs_in_loop): ... this iterator.
(rewrite_mem_ref_loc): New functor.
(rewrite_mem_refs): Use for_all_locs_in_loop.
(sm_set_flag_if_changed): New functor.
(execute_sm_if_changed_flag_set): Use for_all_locs_in_loop.
(ref_always_accessed): New functor.
(ref_always_accessed_p): Use for_all_locs_in_loop.
2013-03-21 Marc Glisse <marc.glisse@inria.fr>
* tree-pass.h (PROP_gimple_lvec): New.

View File

@ -105,14 +105,6 @@ typedef struct mem_ref_loc
} *mem_ref_loc_p;
/* The list of memory reference locations in a loop. */
typedef struct mem_ref_locs
{
vec<mem_ref_loc_p> locs;
} *mem_ref_locs_p;
/* Description of a memory reference. */
typedef struct mem_ref
@ -127,7 +119,7 @@ typedef struct mem_ref
bitmap stored; /* The set of loops in that this memory location
is stored to. */
vec<mem_ref_locs_p> accesses_in_loop;
vec<vec<mem_ref_loc> > accesses_in_loop;
/* The locations of the accesses. Vector
indexed by the loop number. */
@ -1459,33 +1451,16 @@ memref_eq (const void *obj1, const void *obj2)
return operand_equal_p (mem1->mem.ref, (const_tree) obj2, 0);
}
/* Releases list of memory reference locations ACCS. */
static void
free_mem_ref_locs (mem_ref_locs_p accs)
{
unsigned i;
mem_ref_loc_p loc;
if (!accs)
return;
FOR_EACH_VEC_ELT (accs->locs, i, loc)
free (loc);
accs->locs.release ();
free (accs);
}
/* A function to free the mem_ref object OBJ. */
static void
memref_free (struct mem_ref *mem)
{
unsigned i;
mem_ref_locs_p accs;
vec<mem_ref_loc> *accs;
FOR_EACH_VEC_ELT (mem->accesses_in_loop, i, accs)
free_mem_ref_locs (accs);
accs->release ();
mem->accesses_in_loop.release ();
free (mem);
@ -1511,39 +1486,21 @@ mem_ref_alloc (tree mem, unsigned hash, unsigned id)
return ref;
}
/* Allocates and returns the new list of locations. */
static mem_ref_locs_p
mem_ref_locs_alloc (void)
{
mem_ref_locs_p accs = XNEW (struct mem_ref_locs);
accs->locs.create (0);
return accs;
}
/* Records memory reference location *LOC in LOOP to the memory reference
description REF. The reference occurs in statement STMT. */
static void
record_mem_ref_loc (mem_ref_p ref, struct loop *loop, gimple stmt, tree *loc)
{
mem_ref_loc_p aref = XNEW (struct mem_ref_loc);
mem_ref_locs_p accs;
mem_ref_loc aref;
if (ref->accesses_in_loop.length ()
<= (unsigned) loop->num)
ref->accesses_in_loop.safe_grow_cleared (loop->num + 1);
accs = ref->accesses_in_loop[loop->num];
if (!accs)
{
accs = mem_ref_locs_alloc ();
ref->accesses_in_loop[loop->num] = accs;
}
aref->stmt = stmt;
aref->ref = loc;
accs->locs.safe_push (aref);
aref.stmt = stmt;
aref.ref = loc;
ref->accesses_in_loop[loop->num].safe_push (aref);
}
/* Marks reference REF as stored in LOOP. */
@ -1804,43 +1761,50 @@ mem_refs_may_alias_p (mem_ref_p mem1, mem_ref_p mem2,
return true;
}
/* Rewrites location LOC by TMP_VAR. */
/* Iterates over all locations of REF in LOOP and its subloops calling
fn.operator() with the location as argument. When that operator
returns true the iteration is stopped and true is returned.
Otherwise false is returned. */
static void
rewrite_mem_ref_loc (mem_ref_loc_p loc, tree tmp_var)
template <typename FN>
static bool
for_all_locs_in_loop (struct loop *loop, mem_ref_p ref, FN fn)
{
*loc->ref = tmp_var;
update_stmt (loc->stmt);
}
/* Adds all locations of REF in LOOP and its subloops to LOCS. */
static void
get_all_locs_in_loop (struct loop *loop, mem_ref_p ref,
vec<mem_ref_loc_p> *locs)
{
mem_ref_locs_p accs;
unsigned i;
mem_ref_loc_p loc;
bitmap refs = memory_accesses.all_refs_in_loop[loop->num];
struct loop *subloop;
if (!bitmap_bit_p (refs, ref->id))
return;
return false;
if (ref->accesses_in_loop.length ()
> (unsigned) loop->num)
{
accs = ref->accesses_in_loop[loop->num];
if (accs)
{
FOR_EACH_VEC_ELT (accs->locs, i, loc)
locs->safe_push (loc);
}
}
if (ref->accesses_in_loop.length () > (unsigned) loop->num)
FOR_EACH_VEC_ELT (ref->accesses_in_loop[loop->num], i, loc)
if (fn (loc))
return true;
for (subloop = loop->inner; subloop != NULL; subloop = subloop->next)
get_all_locs_in_loop (subloop, ref, locs);
if (for_all_locs_in_loop (subloop, ref, fn))
return true;
return false;
}
/* Rewrites location LOC by TMP_VAR. */
struct rewrite_mem_ref_loc
{
rewrite_mem_ref_loc (tree tmp_var_) : tmp_var (tmp_var_) {}
bool operator()(mem_ref_loc_p loc);
tree tmp_var;
};
bool
rewrite_mem_ref_loc::operator()(mem_ref_loc_p loc)
{
*loc->ref = tmp_var;
update_stmt (loc->stmt);
return false;
}
/* Rewrites all references to REF in LOOP by variable TMP_VAR. */
@ -1848,14 +1812,7 @@ get_all_locs_in_loop (struct loop *loop, mem_ref_p ref,
static void
rewrite_mem_refs (struct loop *loop, mem_ref_p ref, tree tmp_var)
{
unsigned i;
mem_ref_loc_p loc;
vec<mem_ref_loc_p> locs = vNULL;
get_all_locs_in_loop (loop, ref, &locs);
FOR_EACH_VEC_ELT (locs, i, loc)
rewrite_mem_ref_loc (loc, tmp_var);
locs.release ();
for_all_locs_in_loop (loop, ref, rewrite_mem_ref_loc (tmp_var));
}
/* The name and the length of the currently generated variable
@ -2113,36 +2070,40 @@ execute_sm_if_changed (edge ex, tree mem, tree tmp_var, tree flag)
EDGE_SUCC (new_bb, 0)->flags &= ~EDGE_FALLTHRU;
}
/* When REF is set on the location, set flag indicating the store. */
struct sm_set_flag_if_changed
{
sm_set_flag_if_changed (tree flag_) : flag (flag_) {}
bool operator()(mem_ref_loc_p loc);
tree flag;
};
bool
sm_set_flag_if_changed::operator()(mem_ref_loc_p loc)
{
/* Only set the flag for writes. */
if (is_gimple_assign (loc->stmt)
&& gimple_assign_lhs_ptr (loc->stmt) == loc->ref)
{
gimple_stmt_iterator gsi = gsi_for_stmt (loc->stmt);
gimple stmt = gimple_build_assign (flag, boolean_true_node);
gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
}
return false;
}
/* Helper function for execute_sm. On every location where REF is
set, set an appropriate flag indicating the store. */
static tree
execute_sm_if_changed_flag_set (struct loop *loop, mem_ref_p ref)
{
unsigned i;
mem_ref_loc_p loc;
tree flag;
vec<mem_ref_loc_p> locs = vNULL;
char *str = get_lsm_tmp_name (ref->mem.ref, ~0);
lsm_tmp_name_add ("_flag");
flag = create_tmp_reg (boolean_type_node, str);
get_all_locs_in_loop (loop, ref, &locs);
FOR_EACH_VEC_ELT (locs, i, loc)
{
gimple_stmt_iterator gsi;
gimple stmt;
/* Only set the flag for writes. */
if (is_gimple_assign (loc->stmt)
&& gimple_assign_lhs_ptr (loc->stmt) == loc->ref)
{
gsi = gsi_for_stmt (loc->stmt);
stmt = gimple_build_assign (flag, boolean_true_node);
gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
}
}
locs.release ();
for_all_locs_in_loop (loop, ref, sm_set_flag_if_changed (flag));
return flag;
}
@ -2237,60 +2198,64 @@ hoist_memory_references (struct loop *loop, bitmap mem_refs,
}
}
struct ref_always_accessed
{
ref_always_accessed (struct loop *loop_, tree base_, bool stored_p_)
: loop (loop_), base (base_), stored_p (stored_p_) {}
bool operator()(mem_ref_loc_p loc);
struct loop *loop;
tree base;
bool stored_p;
};
bool
ref_always_accessed::operator()(mem_ref_loc_p loc)
{
struct loop *must_exec;
if (!get_lim_data (loc->stmt))
return false;
/* If we require an always executed store make sure the statement
stores to the reference. */
if (stored_p)
{
tree lhs;
if (!gimple_get_lhs (loc->stmt))
return false;
lhs = get_base_address (gimple_get_lhs (loc->stmt));
if (!lhs)
return false;
if (INDIRECT_REF_P (lhs)
|| TREE_CODE (lhs) == MEM_REF)
lhs = TREE_OPERAND (lhs, 0);
if (lhs != base)
return false;
}
must_exec = get_lim_data (loc->stmt)->always_executed_in;
if (!must_exec)
return false;
if (must_exec == loop
|| flow_loop_nested_p (must_exec, loop))
return true;
return false;
}
/* Returns true if REF is always accessed in LOOP. If STORED_P is true
make sure REF is always stored to in LOOP. */
static bool
ref_always_accessed_p (struct loop *loop, mem_ref_p ref, bool stored_p)
{
vec<mem_ref_loc_p> locs = vNULL;
unsigned i;
mem_ref_loc_p loc;
bool ret = false;
struct loop *must_exec;
tree base;
base = ao_ref_base (&ref->mem);
tree base = ao_ref_base (&ref->mem);
if (TREE_CODE (base) == MEM_REF)
base = TREE_OPERAND (base, 0);
get_all_locs_in_loop (loop, ref, &locs);
FOR_EACH_VEC_ELT (locs, i, loc)
{
if (!get_lim_data (loc->stmt))
continue;
/* If we require an always executed store make sure the statement
stores to the reference. */
if (stored_p)
{
tree lhs;
if (!gimple_get_lhs (loc->stmt))
continue;
lhs = get_base_address (gimple_get_lhs (loc->stmt));
if (!lhs)
continue;
if (INDIRECT_REF_P (lhs)
|| TREE_CODE (lhs) == MEM_REF)
lhs = TREE_OPERAND (lhs, 0);
if (lhs != base)
continue;
}
must_exec = get_lim_data (loc->stmt)->always_executed_in;
if (!must_exec)
continue;
if (must_exec == loop
|| flow_loop_nested_p (must_exec, loop))
{
ret = true;
break;
}
}
locs.release ();
return ret;
return for_all_locs_in_loop (loop, ref,
ref_always_accessed (loop, base, stored_p));
}
/* Returns true if REF1 and REF2 are independent. */