aboutsummaryrefslogtreecommitdiff
path: root/gcc/tree-ssa-loop-im.c
diff options
context:
space:
mode:
authorRichard Guenther <rguenther@suse.de>2010-03-29 15:20:07 +0000
committerRichard Biener <rguenth@gcc.gnu.org>2010-03-29 15:20:07 +0000
commit58adb739eff82cda929295c909e70be78f81ffbe (patch)
treef88e6ff40be54449b7f60f480ca30300c46d4eb3 /gcc/tree-ssa-loop-im.c
parent521506258fa5b6b57a50b0570d8208894ed19f79 (diff)
downloadgcc-58adb739eff82cda929295c909e70be78f81ffbe.zip
gcc-58adb739eff82cda929295c909e70be78f81ffbe.tar.gz
gcc-58adb739eff82cda929295c909e70be78f81ffbe.tar.bz2
re PR tree-optimization/43560 (possible wrong code bug)
2010-03-29 Richard Guenther <rguenther@suse.de> PR tree-optimization/43560 * tree-ssa-loop-im.c (ref_always_accessed_p): Add store_p parameter. (can_sm_ref_p): Treat stores to readonly locations as trapping. * gcc.dg/torture/pr43560.c: New testcase. From-SVN: r157799
Diffstat (limited to 'gcc/tree-ssa-loop-im.c')
-rw-r--r--gcc/tree-ssa-loop-im.c39
1 files changed, 34 insertions, 5 deletions
diff --git a/gcc/tree-ssa-loop-im.c b/gcc/tree-ssa-loop-im.c
index 528db65..825fb71 100644
--- a/gcc/tree-ssa-loop-im.c
+++ b/gcc/tree-ssa-loop-im.c
@@ -1900,16 +1900,22 @@ hoist_memory_references (struct loop *loop, bitmap mem_refs,
}
}
-/* Returns true if REF is always accessed in LOOP. */
+/* 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)
+ref_always_accessed_p (struct loop *loop, mem_ref_p ref, bool stored_p)
{
VEC (mem_ref_loc_p, heap) *locs = NULL;
unsigned i;
mem_ref_loc_p loc;
bool ret = false;
struct loop *must_exec;
+ tree base;
+
+ base = get_base_address (ref->mem);
+ if (INDIRECT_REF_P (base))
+ base = TREE_OPERAND (base, 0);
get_all_locs_in_loop (loop, ref, &locs);
for (i = 0; VEC_iterate (mem_ref_loc_p, locs, i, loc); i++)
@@ -1917,6 +1923,22 @@ ref_always_accessed_p (struct loop *loop, mem_ref_p ref)
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))
+ lhs = TREE_OPERAND (lhs, 0);
+ if (lhs != base)
+ continue;
+ }
+
must_exec = get_lim_data (loc->stmt)->always_executed_in;
if (!must_exec)
continue;
@@ -2054,6 +2076,8 @@ ref_indep_loop_p (struct loop *loop, mem_ref_p ref)
static bool
can_sm_ref_p (struct loop *loop, mem_ref_p ref)
{
+ tree base;
+
/* Unless the reference is stored in the loop, there is nothing to do. */
if (!bitmap_bit_p (ref->stored, loop->num))
return false;
@@ -2064,9 +2088,14 @@ can_sm_ref_p (struct loop *loop, mem_ref_p ref)
|| !for_each_index (&ref->mem, may_move_till, loop))
return false;
- /* If it can trap, it must be always executed in LOOP. */
- if (tree_could_trap_p (ref->mem)
- && !ref_always_accessed_p (loop, ref))
+ /* If it can trap, it must be always executed in LOOP.
+ Readonly memory locations may trap when storing to them, but
+ tree_could_trap_p is a predicate for rvalues, so check that
+ explicitly. */
+ base = get_base_address (ref->mem);
+ if ((tree_could_trap_p (ref->mem)
+ || (DECL_P (base) && TREE_READONLY (base)))
+ && !ref_always_accessed_p (loop, ref, true))
return false;
/* And it must be independent on all other memory references