aboutsummaryrefslogtreecommitdiff
path: root/gcc/tree-ssa-loop-im.c
diff options
context:
space:
mode:
authorRichard Biener <rguenther@suse.de>2013-03-22 09:12:46 +0000
committerRichard Biener <rguenth@gcc.gnu.org>2013-03-22 09:12:46 +0000
commit15d19bf8d041f6afcf951f1bd130f36947634467 (patch)
tree6564d1b5884d7bca34a263a8372358c9e3b53cc9 /gcc/tree-ssa-loop-im.c
parent9dc6f476cea37cef0802c02e0914f9583dd0206c (diff)
downloadgcc-15d19bf8d041f6afcf951f1bd130f36947634467.zip
gcc-15d19bf8d041f6afcf951f1bd130f36947634467.tar.gz
gcc-15d19bf8d041f6afcf951f1bd130f36947634467.tar.bz2
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
Diffstat (limited to 'gcc/tree-ssa-loop-im.c')
-rw-r--r--gcc/tree-ssa-loop-im.c261
1 files changed, 113 insertions, 148 deletions
diff --git a/gcc/tree-ssa-loop-im.c b/gcc/tree-ssa-loop-im.c
index ac62595..eb12f72 100644
--- a/gcc/tree-ssa-loop-im.c
+++ b/gcc/tree-ssa-loop-im.c
@@ -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. */
-
-static void
-rewrite_mem_ref_loc (mem_ref_loc_p loc, tree tmp_var)
-{
- *loc->ref = tmp_var;
- update_stmt (loc->stmt);
-}
-
-/* Adds all locations of REF in LOOP and its subloops to LOCS. */
+/* 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
-get_all_locs_in_loop (struct loop *loop, mem_ref_p ref,
- vec<mem_ref_loc_p> *locs)
+template <typename FN>
+static bool
+for_all_locs_in_loop (struct loop *loop, mem_ref_p ref, FN fn)
{
- 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,
}
}
-/* Returns true if REF is always accessed in LOOP. If STORED_P is true
- make sure REF is always stored to in LOOP. */
+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;
+};
-static bool
-ref_always_accessed_p (struct loop *loop, mem_ref_p ref, bool stored_p)
+bool
+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;
- tree base;
- base = ao_ref_base (&ref->mem);
- if (TREE_CODE (base) == MEM_REF)
- base = TREE_OPERAND (base, 0);
+ if (!get_lim_data (loc->stmt))
+ return false;
- get_all_locs_in_loop (loop, ref, &locs);
- FOR_EACH_VEC_ELT (locs, i, loc)
+ /* If we require an always executed store make sure the statement
+ stores to the reference. */
+ if (stored_p)
{
- if (!get_lim_data (loc->stmt))
- continue;
+ 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;
+ }
- /* 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)
+ return false;
- 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))
+ return true;
- if (must_exec == loop
- || flow_loop_nested_p (must_exec, loop))
- {
- ret = true;
- break;
- }
- }
- locs.release ();
+ return false;
+}
- 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. */