[PATCH] Fix PR43560
Richard Guenther
rguenther@suse.de
Mon Mar 29 13:10:00 GMT 2010
This fixes PR43560, loop store motion does not properly distinguish
between trapping loads and trapping stores, thus it can happen that
store motion is executed on a readonly variable. The following
patch fixes that by making sure a store is always executed in case
a possibly trapping memory is store-motioned. Also readonly
memory locations are assumed as trapping.
Bootstrapped and tested on x86_64-unknown-linux-gnu.
Comments?
Richard.
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.
Index: gcc/tree-ssa-loop-im.c
===================================================================
*** gcc/tree-ssa-loop-im.c (revision 157793)
--- gcc/tree-ssa-loop-im.c (working copy)
*************** hoist_memory_references (struct loop *lo
*** 1900,1915 ****
}
}
! /* Returns true if REF is always accessed in LOOP. */
static bool
! ref_always_accessed_p (struct loop *loop, mem_ref_p ref)
{
VEC (mem_ref_loc_p, heap) *locs = NULL;
unsigned i;
mem_ref_loc_p loc;
bool ret = false;
struct loop *must_exec;
get_all_locs_in_loop (loop, ref, &locs);
for (i = 0; VEC_iterate (mem_ref_loc_p, locs, i, loc); i++)
--- 1900,1921 ----
}
}
! /* 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)
{
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++)
*************** ref_always_accessed_p (struct loop *loop
*** 1917,1922 ****
--- 1923,1944 ----
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;
*************** ref_indep_loop_p (struct loop *loop, mem
*** 2054,2059 ****
--- 2076,2083 ----
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;
*************** can_sm_ref_p (struct loop *loop, mem_ref
*** 2064,2072 ****
|| !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))
return false;
/* And it must be independent on all other memory references
--- 2088,2101 ----
|| !for_each_index (&ref->mem, may_move_till, loop))
return false;
! /* 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
Index: gcc/testsuite/gcc.dg/torture/pr43560.c
===================================================================
*** gcc/testsuite/gcc.dg/torture/pr43560.c (revision 0)
--- gcc/testsuite/gcc.dg/torture/pr43560.c (revision 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;
+ }
+
More information about the Gcc-patches
mailing list