[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