[PATCH][alias-improvements] Fix SCCVN DSE fallout

Richard Guenther rguenther@suse.de
Sun Mar 29 13:10:00 GMT 2009


The redundant store removal is more effective on the branch and thus
uncovered some issue that manifests itself in

FAIL: 25_algorithms/lexicographical_compare/check_type.cc (test for excess 
errors)

Fixed by making sure not to disturb VN by delaying stmt removal until
after elimination.

Bootstrapped and tested on x86_64-unknown-linux-gnu, applied to the
branch.

Richard.

2009-03-29  Richard Guenther  <rguenther@suse.de>

	* tree-ssa-pre.c (eliminate): Do not remove stmts during elimination,
	instead queue and remove them afterwards.

	* g++.dg/torture/20090329-1.C: New testcase.

Index: gcc/tree-ssa-pre.c
===================================================================
*** gcc/tree-ssa-pre.c	(revision 145211)
--- gcc/tree-ssa-pre.c	(working copy)
*************** do_SCCVN_insertion (gimple stmt, tree ss
*** 3918,3933 ****
  static unsigned int
  eliminate (void)
  {
    basic_block b;
    unsigned int todo = 0;
  
    FOR_EACH_BB (b)
      {
!       gimple_stmt_iterator i;
! 
!       for (i = gsi_start_bb (b); !gsi_end_p (i);)
  	{
! 	  gimple stmt = gsi_stmt (i);
  
  	  /* Lookup the RHS of the expression, see if we have an
  	     available computation for it.  If so, replace the RHS with
--- 3918,3935 ----
  static unsigned int
  eliminate (void)
  {
+   VEC (gimple, heap) *to_remove = NULL;
    basic_block b;
    unsigned int todo = 0;
+   gimple_stmt_iterator gsi;
+   gimple stmt;
+   unsigned i;
  
    FOR_EACH_BB (b)
      {
!       for (gsi = gsi_start_bb (b); !gsi_end_p (gsi); gsi_next (&gsi))
  	{
! 	  stmt = gsi_stmt (gsi);
  
  	  /* Lookup the RHS of the expression, see if we have an
  	     available computation for it.  If so, replace the RHS with
*************** eliminate (void)
*** 3980,3989 ****
  		      print_gimple_stmt (dump_file, stmt, 0, 0);
  		    }
  		  pre_stats.eliminations++;
! 		  propagate_tree_value_into_stmt (&i, sprime);
! 		  stmt = gsi_stmt (i);
  		  update_stmt (stmt);
- 		  gsi_next (&i);
  		  continue;
  		}
  
--- 3982,3990 ----
  		      print_gimple_stmt (dump_file, stmt, 0, 0);
  		    }
  		  pre_stats.eliminations++;
! 		  propagate_tree_value_into_stmt (&gsi, sprime);
! 		  stmt = gsi_stmt (gsi);
  		  update_stmt (stmt);
  		  continue;
  		}
  
*************** eliminate (void)
*** 4029,4036 ****
  		    sprime = fold_convert (gimple_expr_type (stmt), sprime);
  
  		  pre_stats.eliminations++;
! 		  propagate_tree_value_into_stmt (&i, sprime);
! 		  stmt = gsi_stmt (i);
  		  update_stmt (stmt);
  
  		  /* If we removed EH side effects from the statement, clean
--- 4030,4037 ----
  		    sprime = fold_convert (gimple_expr_type (stmt), sprime);
  
  		  pre_stats.eliminations++;
! 		  propagate_tree_value_into_stmt (&gsi, sprime);
! 		  stmt = gsi_stmt (gsi);
  		  update_stmt (stmt);
  
  		  /* If we removed EH side effects from the statement, clean
*************** eliminate (void)
*** 4063,4076 ****
  		{
  		  if (dump_file && (dump_flags & TDF_DETAILS))
  		    {
! 		      fprintf (dump_file, "Deleted dead store ");
  		      print_gimple_stmt (dump_file, stmt, 0, 0);
  		    }
  
! 		  unlink_stmt_vdef (stmt);
! 		  gsi_remove (&i, true);
! 		  release_defs (stmt);
! 		  continue;
  		}
  	    }
  	  /* Visit COND_EXPRs and fold the comparison with the
--- 4064,4075 ----
  		{
  		  if (dump_file && (dump_flags & TDF_DETAILS))
  		    {
! 		      fprintf (dump_file, "Deleted redundant store ");
  		      print_gimple_stmt (dump_file, stmt, 0, 0);
  		    }
  
! 		  /* Queue stmt for removal.  */
! 		  VEC_safe_push (gimple, heap, to_remove, stmt);
  		}
  	    }
  	  /* Visit COND_EXPRs and fold the comparison with the
*************** eliminate (void)
*** 4097,4107 ****
  		  todo = TODO_cleanup_cfg;
  		}
  	    }
- 
- 	  gsi_next (&i);
  	}
      }
  
    return todo;
  }
  
--- 4096,4115 ----
  		  todo = TODO_cleanup_cfg;
  		}
  	    }
  	}
      }
  
+   /* We cannot remove stmts during BB walk, especially not release SSA
+      names there as this confuses the VN machinery.  */
+   for (i = 0; VEC_iterate (gimple, to_remove, i, stmt); ++i)
+     {
+       gsi = gsi_for_stmt (stmt);
+       unlink_stmt_vdef (stmt);
+       gsi_remove (&gsi, true);
+       release_defs (stmt);
+     }
+   VEC_free (gimple, heap, to_remove);
+ 
    return todo;
  }
  
Index: gcc/testsuite/g++.dg/torture/20090329-1.C
===================================================================
*** gcc/testsuite/g++.dg/torture/20090329-1.C	(revision 0)
--- gcc/testsuite/g++.dg/torture/20090329-1.C	(revision 0)
***************
*** 0 ****
--- 1,59 ----
+ /* { dg-do compile } */
+ 
+ struct input_iterator_tag { };
+ template<typename _Category, typename _Tp, typename _Distance = long, typename _Pointer = _Tp*, typename _Reference = _Tp&>
+ struct iterator {
+     typedef _Category iterator_category;
+ };
+ template<typename _Iterator> struct iterator_traits {
+     typedef typename _Iterator::iterator_category iterator_category;
+ };
+ template<typename, typename> struct __lc_rai {
+     template<typename _II1, typename _II2>
+ 	static _II1 __newlast1(_II1, _II1 __last1, _II2, _II2) {
+ 	    return __last1;
+ 	}
+     template<typename _II> 
+ 	static bool __cnd2(_II __first, _II __last) {
+ 	    return __first != __last;
+ 	}
+ };
+ template<typename _II1, typename _II2, typename _Compare>
+ bool lexicographical_compare(_II1 __first1, _II1 __last1, _II2 __first2,
+ 			     _II2 __last2, _Compare __comp) {
+     typedef typename iterator_traits<_II1>::iterator_category _Category1;
+     typedef typename iterator_traits<_II2>::iterator_category _Category2;
+     typedef __lc_rai<_Category1, _Category2> __rai_type;
+     __last1 = __rai_type::__newlast1(__first1, __last1, __first2, __last2);
+     for (;
+ 	 __first1 != __last1 && __rai_type::__cnd2(__first2, __last2);
+ 	 ++__first1, ++__first2) {
+ 	if (__comp(*__first1, *__first2)) return true;
+     }
+ }
+ void __assert_fail () throw () __attribute__ ((__noreturn__));
+ template<typename T> struct BoundsContainer { };
+ template<class T> class input_iterator_wrapper : public iterator<input_iterator_tag, T, long, T*, T&> {
+ public:
+     typedef BoundsContainer<T> ContainerType;
+     T* ptr;
+     ContainerType* SharedInfo;
+     input_iterator_wrapper(const input_iterator_wrapper& in) : ptr(in.ptr), SharedInfo(in.SharedInfo) { }
+     bool operator==(const input_iterator_wrapper& in) const {
+ 	(static_cast<void> ((SharedInfo != __null
+ 			     && SharedInfo == in.SharedInfo)
+ 			    ? 0 : (__assert_fail (), 0)));
+     }
+     bool operator!=(const input_iterator_wrapper& in) const {
+ 	return !(*this == in);
+     }
+     T& operator*() const { }
+     input_iterator_wrapper& operator++() { }
+ };
+ struct X { };
+ bool predicate(const X&, const X&) {
+     return true;
+ }
+ bool test2(input_iterator_wrapper<X>& x) {
+     return lexicographical_compare(x, x, x, x, predicate);
+ }



More information about the Gcc-patches mailing list