Commit 15d19bf8 by Richard Biener Committed by Richard Biener

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
parent 9dc6f476
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> 2013-03-21 Marc Glisse <marc.glisse@inria.fr>
* tree-pass.h (PROP_gimple_lvec): New. * tree-pass.h (PROP_gimple_lvec): New.
......
...@@ -105,14 +105,6 @@ typedef struct mem_ref_loc ...@@ -105,14 +105,6 @@ typedef struct mem_ref_loc
} *mem_ref_loc_p; } *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. */ /* Description of a memory reference. */
typedef struct mem_ref typedef struct mem_ref
...@@ -127,7 +119,7 @@ typedef struct mem_ref ...@@ -127,7 +119,7 @@ typedef struct mem_ref
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<vec<mem_ref_loc> > accesses_in_loop;
/* The locations of the accesses. Vector /* The locations of the accesses. Vector
indexed by the loop number. */ indexed by the loop number. */
...@@ -1459,33 +1451,16 @@ memref_eq (const void *obj1, const void *obj2) ...@@ -1459,33 +1451,16 @@ memref_eq (const void *obj1, const void *obj2)
return operand_equal_p (mem1->mem.ref, (const_tree) obj2, 0); 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. */ /* A function to free the mem_ref object OBJ. */
static void static void
memref_free (struct mem_ref *mem) memref_free (struct mem_ref *mem)
{ {
unsigned i; unsigned i;
mem_ref_locs_p accs; vec<mem_ref_loc> *accs;
FOR_EACH_VEC_ELT (mem->accesses_in_loop, i, accs) FOR_EACH_VEC_ELT (mem->accesses_in_loop, i, accs)
free_mem_ref_locs (accs); accs->release ();
mem->accesses_in_loop.release (); mem->accesses_in_loop.release ();
free (mem); free (mem);
...@@ -1511,39 +1486,21 @@ mem_ref_alloc (tree mem, unsigned hash, unsigned id) ...@@ -1511,39 +1486,21 @@ mem_ref_alloc (tree mem, unsigned hash, unsigned id)
return ref; 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 /* Records memory reference location *LOC in LOOP to the memory reference
description REF. The reference occurs in statement STMT. */ description REF. The reference occurs in statement STMT. */
static void static void
record_mem_ref_loc (mem_ref_p ref, struct loop *loop, gimple stmt, tree *loc) 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_loc aref;
mem_ref_locs_p accs;
if (ref->accesses_in_loop.length () if (ref->accesses_in_loop.length ()
<= (unsigned) loop->num) <= (unsigned) loop->num)
ref->accesses_in_loop.safe_grow_cleared (loop->num + 1); 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. */ /* Marks reference REF as stored in LOOP. */
...@@ -1804,43 +1761,50 @@ mem_refs_may_alias_p (mem_ref_p mem1, mem_ref_p mem2, ...@@ -1804,43 +1761,50 @@ mem_refs_may_alias_p (mem_ref_p mem1, mem_ref_p mem2,
return true; 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
static void returns true the iteration is stopped and true is returned.
rewrite_mem_ref_loc (mem_ref_loc_p loc, tree tmp_var) Otherwise false is returned. */
{
*loc->ref = tmp_var;
update_stmt (loc->stmt);
}
/* Adds all locations of REF in LOOP and its subloops to LOCS. */
static void template <typename FN>
get_all_locs_in_loop (struct loop *loop, mem_ref_p ref, static bool
vec<mem_ref_loc_p> *locs) for_all_locs_in_loop (struct loop *loop, mem_ref_p ref, FN fn)
{ {
mem_ref_locs_p accs;
unsigned i; unsigned i;
mem_ref_loc_p loc; mem_ref_loc_p loc;
bitmap refs = memory_accesses.all_refs_in_loop[loop->num]; bitmap refs = memory_accesses.all_refs_in_loop[loop->num];
struct loop *subloop; struct loop *subloop;
if (!bitmap_bit_p (refs, ref->id)) if (!bitmap_bit_p (refs, ref->id))
return; return false;
if (ref->accesses_in_loop.length () if (ref->accesses_in_loop.length () > (unsigned) loop->num)
> (unsigned) loop->num) FOR_EACH_VEC_ELT (ref->accesses_in_loop[loop->num], i, loc)
{ if (fn (loc))
accs = ref->accesses_in_loop[loop->num]; return true;
if (accs)
{
FOR_EACH_VEC_ELT (accs->locs, i, loc)
locs->safe_push (loc);
}
}
for (subloop = loop->inner; subloop != NULL; subloop = subloop->next) 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. */ /* 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, ...@@ -1848,14 +1812,7 @@ get_all_locs_in_loop (struct loop *loop, mem_ref_p ref,
static void static void
rewrite_mem_refs (struct loop *loop, mem_ref_p ref, tree tmp_var) rewrite_mem_refs (struct loop *loop, mem_ref_p ref, tree tmp_var)
{ {
unsigned i; for_all_locs_in_loop (loop, ref, rewrite_mem_ref_loc (tmp_var));
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 ();
} }
/* The name and the length of the currently generated variable /* 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) ...@@ -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; 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 /* Helper function for execute_sm. On every location where REF is
set, set an appropriate flag indicating the store. */ set, set an appropriate flag indicating the store. */
static tree static tree
execute_sm_if_changed_flag_set (struct loop *loop, mem_ref_p ref) execute_sm_if_changed_flag_set (struct loop *loop, mem_ref_p ref)
{ {
unsigned i;
mem_ref_loc_p loc;
tree flag; tree flag;
vec<mem_ref_loc_p> locs = vNULL;
char *str = get_lsm_tmp_name (ref->mem.ref, ~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);
get_all_locs_in_loop (loop, ref, &locs); for_all_locs_in_loop (loop, ref, sm_set_flag_if_changed (flag));
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 ();
return flag; return flag;
} }
...@@ -2237,60 +2198,64 @@ hoist_memory_references (struct loop *loop, bitmap mem_refs, ...@@ -2237,60 +2198,64 @@ hoist_memory_references (struct loop *loop, bitmap mem_refs,
} }
} }
/* Returns true if REF is always accessed in LOOP. If STORED_P is true struct ref_always_accessed
make sure REF is always stored to in LOOP. */ {
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;
};
static bool bool
ref_always_accessed_p (struct loop *loop, mem_ref_p ref, bool stored_p) ref_always_accessed::operator()(mem_ref_loc_p loc)
{ {
vec<mem_ref_loc_p> locs = vNULL;
unsigned i;
mem_ref_loc_p loc;
bool ret = false;
struct loop *must_exec; struct loop *must_exec;
tree base;
base = ao_ref_base (&ref->mem); if (!get_lim_data (loc->stmt))
if (TREE_CODE (base) == MEM_REF) return false;
base = TREE_OPERAND (base, 0);
get_all_locs_in_loop (loop, ref, &locs); /* If we require an always executed store make sure the statement
FOR_EACH_VEC_ELT (locs, i, loc) stores to the reference. */
if (stored_p)
{ {
if (!get_lim_data (loc->stmt)) tree lhs;
continue; 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;
}
/* If we require an always executed store make sure the statement must_exec = get_lim_data (loc->stmt)->always_executed_in;
stores to the reference. */ if (!must_exec)
if (stored_p) return false;
{
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 == loop
if (!must_exec) || flow_loop_nested_p (must_exec, loop))
continue; return true;
if (must_exec == loop return false;
|| flow_loop_nested_p (must_exec, loop)) }
{
ret = true;
break;
}
}
locs.release ();
return ret; /* 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)
{
tree base = ao_ref_base (&ref->mem);
if (TREE_CODE (base) == MEM_REF)
base = TREE_OPERAND (base, 0);
return for_all_locs_in_loop (loop, ref,
ref_always_accessed (loop, base, stored_p));
} }
/* Returns true if REF1 and REF2 are independent. */ /* Returns true if REF1 and REF2 are independent. */
......
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