diff options
author | Richard Guenther <rguenther@suse.de> | 2010-03-29 15:20:07 +0000 |
---|---|---|
committer | Richard Biener <rguenth@gcc.gnu.org> | 2010-03-29 15:20:07 +0000 |
commit | 58adb739eff82cda929295c909e70be78f81ffbe (patch) | |
tree | f88e6ff40be54449b7f60f480ca30300c46d4eb3 /gcc/tree-ssa-loop-im.c | |
parent | 521506258fa5b6b57a50b0570d8208894ed19f79 (diff) | |
download | gcc-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.c | 39 |
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 |