From 7c3e70560bcf162884f414c54720efcd8e68304f Mon Sep 17 00:00:00 2001 From: Jeff Law Date: Sun, 20 Sep 2015 00:37:39 -0600 Subject: [PATCH] [PATCH] Fix 47679 by improving jump threading PR tree-optimization/47679 * tree-ssa-dom.c (record_temporary_equivalences): No longer static. * tree-ssa-dom.h (record_temporary_equivalences): Add prototype. * tree-ssa-threadedge.c: Include tree-ssa-dom.h. (thread_through_normal_block): Use record_temporary_equivalences. PR tree-optimization/47679 * g++.dg/warn/Wuninitialized-6.C: New test. From-SVN: r227942 --- gcc/ChangeLog | 8 + gcc/testsuite/ChangeLog | 5 + gcc/testsuite/g++.dg/warn/Wuninitialized-6.C | 333 +++++++++++++++++++ gcc/tree-ssa-dom.c | 2 +- gcc/tree-ssa-dom.h | 3 + gcc/tree-ssa-threadedge.c | 5 + 6 files changed, 355 insertions(+), 1 deletion(-) create mode 100644 gcc/testsuite/g++.dg/warn/Wuninitialized-6.C diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 86e2c05e31a..8bb16d04bd3 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,11 @@ +2015-09-20 Jeff Law + + PR tree-optimization/47679 + * tree-ssa-dom.c (record_temporary_equivalences): No longer static. + * tree-ssa-dom.h (record_temporary_equivalences): Add prototype. + * tree-ssa-threadedge.c: Include tree-ssa-dom.h. + (thread_through_normal_block): Use record_temporary_equivalences. + 2015-09-19 Trevor Saunders * coretypes.h (gimple): Change typedef to be a forward diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index a5901a15c50..74afa641325 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2015-09-20 Jeff Law + + PR tree-optimization/47679 + * g++.dg/warn/Wuninitialized-6.C: New test. + 2015-09-18 Ville Voutilainen Implement nested namespace definitions. diff --git a/gcc/testsuite/g++.dg/warn/Wuninitialized-6.C b/gcc/testsuite/g++.dg/warn/Wuninitialized-6.C new file mode 100644 index 00000000000..771752c7562 --- /dev/null +++ b/gcc/testsuite/g++.dg/warn/Wuninitialized-6.C @@ -0,0 +1,333 @@ +/* { dg-do compile } */ +/* { dg-options "-Wuninitialized -O2" } */ + +namespace std { + typedef __SIZE_TYPE__ size_t; + } + extern "C++" { + inline void* operator new(std::size_t, void* __p) throw() { + return __p; + } + } + namespace boost{ + __extension__ typedef long long long_long_type; + } + namespace mpl_ { + namespace aux { + } + } + namespace boost { + namespace mpl { + using namespace mpl_; + } + } + namespace mpl_ { + struct integral_c_tag { + }; + template< int N > struct int_ { + }; + } + namespace boost { + namespace mpl { + } + } + namespace mpl_ { + template< bool C_ > struct bool_; + typedef bool_ true_; + typedef bool_ false_; + } + namespace mpl_ { + template< bool C_ > struct bool_ { + static const bool value = C_; + }; + template< typename T, T N > struct integral_c { + static const T value = N; + }; + } + namespace boost{ + template struct integral_constant : public mpl::integral_c { + }; + template<> struct integral_constant : public mpl::false_ { + typedef integral_constant type; + }; + template< typename T > struct is_lvalue_reference : ::boost::integral_constant { + }; + template< typename T > struct is_rvalue_reference : ::boost::integral_constant { + }; + namespace type_traits { + template struct ice_or; + template <> struct ice_or { + static const bool value = false; + }; + } + } + namespace boost { + namespace detail { + template struct is_reference_impl { + static const bool value = (::boost::type_traits::ice_or< ::boost::is_lvalue_reference::value, ::boost::is_rvalue_reference::value >::value) ; + }; + } + template< typename T > struct is_reference : ::boost::integral_constant::value> { + }; + namespace detail { + template< typename T > struct alignment_of_impl { + static const std::size_t value = __alignof__(T); + }; + } + template< typename T > struct alignment_of : ::boost::integral_constant::value> { + }; + } + namespace mpl_ { + struct na { + }; + } + namespace boost { + namespace mpl { + } + } + namespace boost { + namespace mpl { + template< bool C , typename T1 , typename T2 > struct if_c { + typedef T1 type; + }; + template< typename T1 , typename T2 > struct if_c { + typedef T2 type; + }; + template< typename T1 = na , typename T2 = na , typename T3 = na > struct if_ { + private: typedef if_c< static_cast(T1::value) , T2 , T3 > almost_type_; + public: typedef typename almost_type_::type type; + }; + } + } + namespace boost{ + template struct STATIC_ASSERTION_FAILURE; + template <> struct STATIC_ASSERTION_FAILURE { + }; + template struct static_assert_test{ + }; + namespace detail { + class alignment_dummy; + typedef void (*function_ptr)(); + typedef int (alignment_dummy::*member_ptr); + typedef int (alignment_dummy::*member_function_ptr)(); + template struct lower_alignment_helper { + typedef char type; + enum { value = true }; + }; + template struct lower_alignment_helper { + enum { value = (alignment_of::value == target) }; + typedef typename mpl::if_c::type type; + }; + template struct has_one_T { + T data; + }; + template union lower_alignment { + enum { found0 = false }; + typename lower_alignment_helper< found0,target,char >::type t0; + enum { found1 = lower_alignment_helper::value }; + typename lower_alignment_helper< found1,target,short >::type t1; + enum { found2 = lower_alignment_helper::value }; + typename lower_alignment_helper< found2,target,int >::type t2; + enum { found3 = lower_alignment_helper::value }; + typename lower_alignment_helper< found3,target,long >::type t3; + enum { found4 = lower_alignment_helper::value }; + typename lower_alignment_helper< found4,target,::boost::long_long_type >::type t4; + enum { found5 = lower_alignment_helper::value }; + typename lower_alignment_helper< found5,target,float >::type t5; + enum { found6 = lower_alignment_helper::value }; + typename lower_alignment_helper< found6,target,double >::type t6; + enum { found7 = lower_alignment_helper::value }; + typename lower_alignment_helper< found7,target,long double >::type t7; + enum { found8 = lower_alignment_helper::value }; + typename lower_alignment_helper< found8,target,void* >::type t8; + enum { found9 = lower_alignment_helper::value }; + typename lower_alignment_helper< found9,target,function_ptr >::type t9; + enum { found10 = lower_alignment_helper::value }; + typename lower_alignment_helper< found10,target,member_ptr >::type t10; + enum { found11 = lower_alignment_helper::value }; + typename lower_alignment_helper< found11,target,member_function_ptr >::type t11; + enum { found12 = lower_alignment_helper::value }; + typename lower_alignment_helper< found12,target,boost::detail::has_one_T< char > >::type t12; + enum { found13 = lower_alignment_helper >::value }; + typename lower_alignment_helper< found13,target,boost::detail::has_one_T< short > >::type t13; + enum { found14 = lower_alignment_helper >::value }; + typename lower_alignment_helper< found14,target,boost::detail::has_one_T< int > >::type t14; + enum { found15 = lower_alignment_helper >::value }; + typename lower_alignment_helper< found15,target,boost::detail::has_one_T< long > >::type t15; + enum { found16 = lower_alignment_helper >::value }; + typename lower_alignment_helper< found16,target,boost::detail::has_one_T< ::boost::long_long_type > >::type t16; + enum { found17 = lower_alignment_helper >::value }; + typename lower_alignment_helper< found17,target,boost::detail::has_one_T< float > >::type t17; + enum { found18 = lower_alignment_helper >::value }; + typename lower_alignment_helper< found18,target,boost::detail::has_one_T< double > >::type t18; + enum { found19 = lower_alignment_helper >::value }; + typename lower_alignment_helper< found19,target,boost::detail::has_one_T< long double > >::type t19; + enum { found20 = lower_alignment_helper >::value }; + typename lower_alignment_helper< found20,target,boost::detail::has_one_T< void* > >::type t20; + enum { found21 = lower_alignment_helper >::value }; + typename lower_alignment_helper< found21,target,boost::detail::has_one_T< function_ptr > >::type t21; + enum { found22 = lower_alignment_helper >::value }; + typename lower_alignment_helper< found22,target,boost::detail::has_one_T< member_ptr > >::type t22; + enum { found23 = lower_alignment_helper >::value }; + typename lower_alignment_helper< found23,target,boost::detail::has_one_T< member_function_ptr > >::type t23; + enum { found24 = lower_alignment_helper >::value }; + }; + union max_align { + }; + template struct is_aligned { + static const bool value = (TAlign >= Align) & (TAlign % Align == 0) ; + }; + template class type_with_alignment_imp { + typedef ::boost::detail::lower_alignment t1; + typedef typename mpl::if_c< ::boost::detail::is_aligned< ::boost::alignment_of::value,Align >::value , t1 , ::boost::detail::max_align >::type align_t; + static const std::size_t found = alignment_of::value; + typedef ::boost::static_assert_test< sizeof(::boost::STATIC_ASSERTION_FAILURE< ((found >= Align) == 0 ? false : true) >)> boost_static_assert_typedef_206; + typedef ::boost::static_assert_test< sizeof(::boost::STATIC_ASSERTION_FAILURE< ((found % Align == 0) == 0 ? false : true) >)> boost_static_assert_typedef_207; + public: typedef align_t type; + }; + } + template class type_with_alignment : public ::boost::detail::type_with_alignment_imp { + }; + } + namespace boost { + namespace detail{ + } + template< typename T > struct remove_reference { + }; + } + namespace boost { + namespace mpl { + namespace aux { + template< typename T > struct nested_type_wknd : T::type { }; + } + } + namespace mpl { + namespace aux { + template< long C_ > struct not_impl : bool_ { }; + } + template< typename T = na > struct not_ : aux::not_impl< ::boost::mpl::aux::nested_type_wknd::value > { + }; + } + namespace detail { + template struct make_reference_content { + typedef T type; + }; + } + namespace detail { + struct none_helper{ +}; + } + typedef int detail::none_helper::*none_t ; + } + namespace boost_optional_detail { + template inline void construct(Factory const& factory, void* address) { + } + } + namespace boost { + class in_place_factory_base ; + class typed_in_place_factory_base ; + namespace optional_detail { + template class aligned_storage { + union __attribute__((may_alias)) dummy_u { char data[ sizeof(T) ]; typename type_with_alignment< ::boost::alignment_of::value >::type aligner_; } + dummy_ ; + public: void const* address() const { return &dummy_; } + void * address() { return &dummy_; } + } + ; + template struct types_when_isnt_ref { + typedef T const& reference_const_type ; + typedef T & reference_type ; + typedef T const* pointer_const_type ; + typedef T * pointer_type ; + typedef T const& argument_type ; + } + ; + template struct types_when_is_ref { + typedef typename remove_reference::type raw_type ; + typedef raw_type& reference_const_type ; + typedef raw_type& argument_type ; + } + ; + struct optional_tag { +} + ; + template struct optional_base : public optional_tag { + typedef typename ::boost::detail::make_reference_content::type internal_type ; + typedef aligned_storage storage_type ; + typedef types_when_isnt_ref types_when_not_ref ; + typedef types_when_is_ref types_when_ref ; + typedef optional_base this_type ; + typedef T value_type ; + typedef mpl::true_ is_reference_tag ; + typedef mpl::false_ is_not_reference_tag ; + typedef typename is_reference::type is_reference_predicate ; + typedef typename mpl::if_::type types ; + typedef bool (this_type::*unspecified_bool_type)() const; + typedef typename types::reference_type reference_type ; + typedef typename types::reference_const_type reference_const_type ; + typedef typename types::pointer_type pointer_type ; + typedef typename types::pointer_const_type pointer_const_type ; + typedef typename types::argument_type argument_type ; + optional_base() : m_initialized(false) {} + optional_base ( argument_type val ) : m_initialized(false) { construct(val); } + optional_base ( bool cond, argument_type val ) : m_initialized(false) { if ( cond ) construct(val); } + optional_base ( optional_base const& rhs ) : m_initialized(false) { if ( rhs.is_initialized() ) construct(rhs.get_impl()); } + pointer_const_type get_ptr() const { return m_initialized ? get_ptr_impl() : 0 ; } + pointer_type get_ptr() { return m_initialized ? get_ptr_impl() : 0 ; } + bool is_initialized() const { return m_initialized ; } + void construct ( argument_type val ) { new (m_storage.address()) internal_type(val) ; m_initialized = true ; } + template void construct ( Expr const& factory, in_place_factory_base const* ) { typedef ::boost::static_assert_test< sizeof(::boost::STATIC_ASSERTION_FAILURE< ((::boost::mpl::not_::value) == 0 ? false : true) >)> boost_static_assert_typedef_355 ; boost_optional_detail::construct(factory, m_storage.address()); m_initialized = true ; } + template void construct ( Expr const& factory, typed_in_place_factory_base const* ) { typedef ::boost::static_assert_test< sizeof(::boost::STATIC_ASSERTION_FAILURE< ((::boost::mpl::not_::value) == 0 ? false : true) >)> boost_static_assert_typedef_364 ; factory.apply(m_storage.address()) ; m_initialized = true ; } + void destroy() { } + unspecified_bool_type safe_bool() const { return m_initialized ? &this_type::is_initialized : 0 ; } + reference_const_type get_impl() const { return dereference(get_object(), is_reference_predicate() ) ; } + reference_type get_impl() { return dereference(get_object(), is_reference_predicate() ) ; } + pointer_const_type get_ptr_impl() const { return cast_ptr(get_object(), is_reference_predicate() ) ; } + pointer_type get_ptr_impl() { return cast_ptr(get_object(), is_reference_predicate() ) ; } + internal_type const* get_object() const { union { void const* ap_pvoid; internal_type const* as_ptype; } caster = { m_storage.address() }; return caster.as_ptype; } + internal_type * get_object() { union { void* ap_pvoid; internal_type* as_ptype; } caster = { m_storage.address() }; return caster.as_ptype; } + reference_const_type dereference( internal_type const* p, is_not_reference_tag ) const { return *p ; } + pointer_type cast_ptr( internal_type * p, is_reference_tag ) { return &p->get() ; } + bool m_initialized ; + storage_type m_storage ; + } + ; + } + template class optional : public optional_detail::optional_base { + typedef optional_detail::optional_base base ; + public : typedef optional this_type ; + typedef typename base::reference_const_type reference_const_type ; + reference_const_type get() const { + (static_cast (0)) ; + return this->get_impl(); + } + reference_const_type operator *() const { + return this->get() ; + } + bool operator!() const { + return !this->is_initialized() ; + } + } + ; + template inline bool equal_pointees2 ( OptionalPointee const& x, OptionalPointee const& y ) { + return (!x) != (!y) ? false : ( !x ? true : (*x) == (*y) ) ; + } + template inline bool operator == ( optional const& x, optional const& y ) { + return equal_pointees2(x,y); + } + template inline bool operator != ( optional const& x, optional const& y ) { + return !( x == y ) ; + } + } + ::boost::optional< std::size_t > getitem(); + class BAR { + public: int FOO(); + private: ::boost::optional< std::size_t > m_aHoveredItem; + }; + int BAR::FOO() { + ::boost::optional< std::size_t > aOldItem(getitem()); + ::boost::optional< std::size_t > aNewItem(m_aHoveredItem); + if (aOldItem != aNewItem) return 1; + return 0; + } + diff --git a/gcc/tree-ssa-dom.c b/gcc/tree-ssa-dom.c index 135eb0e619c..2c51e365b0c 100644 --- a/gcc/tree-ssa-dom.c +++ b/gcc/tree-ssa-dom.c @@ -780,7 +780,7 @@ dom_valueize (tree t) by traversing edge E (which are cached in E->aux). Callers are responsible for managing the unwinding markers. */ -static void +void record_temporary_equivalences (edge e, class const_and_copies *const_and_copies, class avail_exprs_stack *avail_exprs_stack) diff --git a/gcc/tree-ssa-dom.h b/gcc/tree-ssa-dom.h index f1004db792b..15a2d166fda 100644 --- a/gcc/tree-ssa-dom.h +++ b/gcc/tree-ssa-dom.h @@ -21,5 +21,8 @@ along with GCC; see the file COPYING3. If not see #define GCC_TREE_SSA_DOM_H extern bool simple_iv_increment_p (gimple *); +extern void record_temporary_equivalences (edge, + class const_and_copies *, + class avail_exprs_stack *); #endif /* GCC_TREE_SSA_DOM_H */ diff --git a/gcc/tree-ssa-threadedge.c b/gcc/tree-ssa-threadedge.c index b28fff3dc19..c58b5e35408 100644 --- a/gcc/tree-ssa-threadedge.c +++ b/gcc/tree-ssa-threadedge.c @@ -44,6 +44,7 @@ along with GCC; see the file COPYING3. If not see #include "tree-ssa-scopedtables.h" #include "tree-ssa-threadedge.h" #include "tree-ssa-loop.h" +#include "tree-ssa-dom.h" #include "builtins.h" #include "cfganal.h" @@ -1213,6 +1214,10 @@ thread_through_normal_block (edge e, if (*backedge_seen_p) simplify = dummy_simplify; + /* We want to record any equivalences created by traversing E. */ + if (!handle_dominating_asserts) + record_temporary_equivalences (e, const_and_copies, avail_exprs_stack); + /* PHIs create temporary equivalences. Note that if we found a PHI that made the block non-threadable, then we need to bubble that up to our caller in the same manner we do -- 2.30.2