From 58adb739eff82cda929295c909e70be78f81ffbe Mon Sep 17 00:00:00 2001 From: Richard Guenther Date: Mon, 29 Mar 2010 15:20:07 +0000 Subject: [PATCH] re PR tree-optimization/43560 (possible wrong code bug) 2010-03-29 Richard Guenther 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 --- gcc/ChangeLog | 8 ++++++ gcc/testsuite/ChangeLog | 5 ++++ gcc/testsuite/gcc.dg/torture/pr43560.c | 34 ++++++++++++++++++++++ gcc/tree-ssa-loop-im.c | 39 ++++++++++++++++++++++---- 4 files changed, 81 insertions(+), 5 deletions(-) create mode 100644 gcc/testsuite/gcc.dg/torture/pr43560.c diff --git a/gcc/ChangeLog b/gcc/ChangeLog index f3b75676a023..73f102db9f70 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,11 @@ +2010-03-29 Richard Guenther + + 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. + 2010-03-29 Jie Zhang PR 43564 diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index e2fd72efee58..5fe5fc94a76f 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2010-03-29 Richard Guenther + + PR tree-optimization/43560 + * gcc.dg/torture/pr43560.c: New testcase. + 2010-03-29 Jason Merrill N3077 diff --git a/gcc/testsuite/gcc.dg/torture/pr43560.c b/gcc/testsuite/gcc.dg/torture/pr43560.c new file mode 100644 index 000000000000..44abb80b193b --- /dev/null +++ b/gcc/testsuite/gcc.dg/torture/pr43560.c @@ -0,0 +1,34 @@ +/* { dg-do run } */ +/* { dg-require-weak "" } */ + +int g_6[1][2] = {{1,1}}; +int g_34 = 0; +int *const g_82 = &g_6[0][1]; +int *g_85[2][1] __attribute__((weak)); + +void __attribute__((noinline)) +func_4 (int x) +{ + int i; + for (i = 0; i <= x; i++) { + if (g_6[0][1]) { + *g_82 = 1; + } else { + int **l_109 = &g_85[1][0]; + if (&g_82 != l_109) { + } else { + *l_109 = &g_6[0][1]; + } + *g_82 = 1; + } + } +} + +int main (void) +{ + g_85[0][0] = &g_34; + g_85[1][0] = &g_34; + func_4(1); + return 0; +} + diff --git a/gcc/tree-ssa-loop-im.c b/gcc/tree-ssa-loop-im.c index 528db6505705..825fb71760a0 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 -- 2.43.5