[PATCH] Fix PR35472, wrong-code with DSE (again)

Richard Guenther rguenther@suse.de
Wed Mar 5 15:07:00 GMT 2008


So we missed some cases in the fix for PR34459, and the issue is
masked for the testcase for that PR because of PR27799.  Still
I had a one that triggers.

So the failure mode is that DSE removes a store because there is
a noop store following.  Which is of course bad and exactly the
failure mode of PR34459.  The real fix is to punt if there is
any overlap in the LOADED/STORED syms of the use shadowing the
store, as it then possibly can be a noop store (it could even
look like *p = *q, not exposing a symbol directly).

Bootstrap and regtest running on x86_64-unknown-linux-gnu.

Richard.

2008-03-05  Richard Guenther  <rguenther@suse.de>

	PR tree-optimization/35472
	* tree-ssa-dse.c (dse_optimize_stmt): Do not delete a store
	whose single use_stmt has a overlapping set of loaded and
	stored symbols as that use_stmt might be a noop assignment then.

	* gcc.c-torture/execute/pr35472.c: New testcase.

Index: tree-ssa-dse.c
===================================================================
*** tree-ssa-dse.c	(revision 132896)
--- tree-ssa-dse.c	(working copy)
*************** dse_optimize_stmt (struct dom_walk_data 
*** 470,493 ****
  	  vuse_vec_p vv;
  	  tree stmt_lhs;
  
! 	  if (LOADED_SYMS (use_stmt))
  	    {
! 	      tree use_base
! 		= get_base_address (GIMPLE_STMT_OPERAND (use_stmt, 0));
! 	      /* If use_stmt is or might be a nop assignment, e.g. for
! 		 struct { ... } S a, b, *p; ...
! 		 b = a; b = b;
! 		 or
! 		 b = a; b = *p; where p might be &b, then USE_STMT
! 		 acts as a use as well as definition, so store in STMT
! 		 is not dead.  */
! 	      if (TREE_CODE (use_base) == VAR_DECL
! 		  && bitmap_bit_p (LOADED_SYMS (use_stmt),
! 				   DECL_UID (use_base)))
! 		{
! 		  record_voperand_set (dse_gd->stores, &bd->stores, ann->uid);
! 		  return;
! 		}
  	    }
  
  	  if (dump_file && (dump_flags & TDF_DETAILS))
--- 470,492 ----
  	  vuse_vec_p vv;
  	  tree stmt_lhs;
  
! 	  /* If use_stmt is or might be a nop assignment, e.g. for
! 	     struct { ... } S a, b, *p; ...
! 	     b = a; b = b;
! 	     or
! 	     b = a; b = *p; where p might be &b,
! 	     or
! 	     *p = a; *p = b; where p might be &b,
! 	     or
! 	     *p = *u; *p = *v; where p might be v, then USE_STMT
! 	     acts as a use as well as definition, so store in STMT
! 	     is not dead.  */
! 	  if (LOADED_SYMS (use_stmt)
! 	      && bitmap_intersect_p (LOADED_SYMS (use_stmt),
! 				     STORED_SYMS (use_stmt)))
  	    {
! 	      record_voperand_set (dse_gd->stores, &bd->stores, ann->uid);
! 	      return;
  	    }
  
  	  if (dump_file && (dump_flags & TDF_DETAILS))
Index: testsuite/gcc.c-torture/execute/pr35472.c
===================================================================
*** testsuite/gcc.c-torture/execute/pr35472.c	(revision 0)
--- testsuite/gcc.c-torture/execute/pr35472.c	(revision 0)
***************
*** 0 ****
--- 1,22 ----
+ extern void abort (void);
+ extern void *memset (void *s, int c, __SIZE_TYPE__ n);
+ struct S { int i[16]; };
+ struct S *p;
+ void __attribute__((noinline))
+ foo(struct S *a, struct S *b) { a->i[0] = -1; p = b; }
+ void test (void)
+ {
+   struct S a, b;
+   memset (&a.i[0], '\0', sizeof (a.i));
+   memset (&b.i[0], '\0', sizeof (b.i));
+   foo (&a, &b);
+   *p = a;
+   *p = b;
+   if (b.i[0] != -1)
+     abort ();
+ }
+ int main()
+ {
+   test();
+   return 0;
+ }



More information about the Gcc-patches mailing list