[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