diff options
author | Richard Biener <rguenther@suse.de> | 2013-04-30 13:54:14 +0000 |
---|---|---|
committer | Richard Biener <rguenth@gcc.gnu.org> | 2013-04-30 13:54:14 +0000 |
commit | 4c1aff1ce430fdf4b46caa632fd44b4d0f557720 (patch) | |
tree | b5bca3706a64ea2adc3ab07083628f891afef77b /gcc | |
parent | 54b8379a261d1b36958aecbca568ef6475a8e1ca (diff) | |
download | gcc-4c1aff1ce430fdf4b46caa632fd44b4d0f557720.zip gcc-4c1aff1ce430fdf4b46caa632fd44b4d0f557720.tar.gz gcc-4c1aff1ce430fdf4b46caa632fd44b4d0f557720.tar.bz2 |
re PR middle-end/57107 (tree check fail in unlink_stmt_vdef)
2013-04-30 Richard Biener <rguenther@suse.de>
PR middle-end/57107
* tree-eh.c (sink_clobbers): Preserve virtual SSA form.
* g++.dg/torture/pr57107.C: New testcase.
From-SVN: r198454
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/ChangeLog | 5 | ||||
-rw-r--r-- | gcc/testsuite/ChangeLog | 5 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/torture/pr57107.C | 193 | ||||
-rw-r--r-- | gcc/tree-eh.c | 48 |
4 files changed, 241 insertions, 10 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index cde1dec..bb86d6e 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,8 @@ +2013-04-30 Richard Biener <rguenther@suse.de> + + PR middle-end/57107 + * tree-eh.c (sink_clobbers): Preserve virtual SSA form. + 2013-04-30 Andrey Belevantsev <abel@ispras.ru> PR rtl-optimization/56957 diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 00576ee..0d5705a 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2013-04-30 Richard Biener <rguenther@suse.de> + + PR middle-end/57107 + * g++.dg/torture/pr57107.C: New testcase. + 2013-04-30 Andrey Belevantsev <abel@ispras.ru> PR rtl-optimization/57105 diff --git a/gcc/testsuite/g++.dg/torture/pr57107.C b/gcc/testsuite/g++.dg/torture/pr57107.C new file mode 100644 index 0000000..516dec1 --- /dev/null +++ b/gcc/testsuite/g++.dg/torture/pr57107.C @@ -0,0 +1,193 @@ +// { dg-do compile } + +typedef long unsigned int size_t; +namespace std { +} +namespace std __attribute__ ((__visibility__ ("default"))) { + template<class _Sp, class _Tp> struct __traitor { + enum { + __value = bool(_Sp::__value) || bool(_Tp::__value) }; + }; + template<typename _Tp> struct __is_integer { + enum { + __value = 0 }; + }; + template<typename _Tp> struct __is_floating { + enum { + __value = 0 }; + }; + template<typename _Tp> struct __is_pointer { + enum { + __value = 0 }; + }; + template<typename _Tp> struct __is_normal_iterator { + enum { + __value = 0 }; + }; + template<typename _Tp> struct __is_arithmetic : public __traitor<__is_integer<_Tp>, __is_floating<_Tp> > { + }; + template<typename _Tp> struct __is_scalar : public __traitor<__is_arithmetic<_Tp>, __is_pointer<_Tp> > { + }; +} +namespace __gnu_cxx __attribute__ ((__visibility__ ("default"))) { + template<bool, typename> struct __enable_if { + }; + template<typename _Tp> struct __enable_if<true, _Tp> { + typedef _Tp __type; + }; +} +namespace std __attribute__ ((__visibility__ ("default"))) { + template<typename _Iterator> struct iterator_traits { + }; + template<typename _Tp> struct iterator_traits<_Tp*> { + typedef _Tp value_type; + }; + template<typename _Iterator, bool _HasBase> struct _Iter_base { + typedef _Iterator iterator_type; + }; +} +namespace __gnu_cxx __attribute__ ((__visibility__ ("default"))) { +} +namespace std __attribute__ ((__visibility__ ("default"))) { + template<typename _Iterator> struct _Niter_base : _Iter_base<_Iterator, __is_normal_iterator<_Iterator>::__value> { + }; + template<typename _Iterator> inline typename _Niter_base<_Iterator>::iterator_type __niter_base(_Iterator __it) { + } + template<typename _OutputIterator, typename _Size, typename _Tp> inline typename __gnu_cxx::__enable_if<!__is_scalar<_Tp>::__value, _OutputIterator>::__type __fill_n_a(_OutputIterator __first, _Size __n, const _Tp& __value) { + for (__decltype(__n + 0) __niter = __n; + __niter > 0; + --__niter, ++__first) *__first = __value; + } + template<typename _OI, typename _Size, typename _Tp> inline _OI fill_n(_OI __first, _Size __n, const _Tp& __value) { + return _OI(std::__fill_n_a(std::__niter_base(__first), __n, __value)); + } +} +namespace __gnu_cxx __attribute__ ((__visibility__ ("default"))) { + template<typename _Tp> class new_allocator { + public: + typedef size_t size_type; + typedef _Tp* pointer; + ~new_allocator() throw() { + } + pointer allocate(size_type __n, const void* = 0) { + return static_cast<_Tp*>(::operator new(__n * sizeof(_Tp))); + } + }; +} +namespace std __attribute__ ((__visibility__ ("default"))) { + template<typename _Tp> class allocator: public __gnu_cxx::new_allocator<_Tp> { + public: + template<typename _Tp1> struct rebind { + typedef allocator<_Tp1> other; + }; + }; +} +namespace __gnu_cxx __attribute__ ((__visibility__ ("default"))) { + template<typename _Alloc> struct __alloc_traits { + typedef typename _Alloc::pointer pointer; + template<typename _Tp> struct rebind { + typedef typename _Alloc::template rebind<_Tp>::other other; + }; + }; +} +class QString { +public: + bool isEmpty() const; +}; +class QObject { +}; +namespace std __attribute__ ((__visibility__ ("default"))) { + template<bool _TrivialValueType> struct __uninitialized_fill_n { + template<typename _ForwardIterator, typename _Size, typename _Tp> static void __uninit_fill_n(_ForwardIterator __first, _Size __n, const _Tp& __x) { + std::fill_n(__first, __n, __x); + } + }; + template<typename _ForwardIterator, typename _Size, typename _Tp> inline void uninitialized_fill_n(_ForwardIterator __first, _Size __n, const _Tp& __x) { + typedef typename iterator_traits<_ForwardIterator>::value_type _ValueType; + std::__uninitialized_fill_n<__is_trivial(_ValueType)>:: __uninit_fill_n(__first, __n, __x); + } + template<typename _ForwardIterator, typename _Size, typename _Tp, typename _Tp2> inline void __uninitialized_fill_n_a(_ForwardIterator __first, _Size __n, const _Tp& __x, allocator<_Tp2>&) { + std::uninitialized_fill_n(__first, __n, __x); + } + template<typename _Tp, typename _Alloc> struct _Vector_base { + typedef typename __gnu_cxx::__alloc_traits<_Alloc>::template rebind<_Tp>::other _Tp_alloc_type; + typedef typename __gnu_cxx::__alloc_traits<_Tp_alloc_type>::pointer pointer; + struct _Vector_impl : public _Tp_alloc_type { + pointer _M_start; + pointer _M_finish; + pointer _M_end_of_storage; + _Vector_impl(_Tp_alloc_type const& __a) : _Tp_alloc_type(__a), _M_start(0), _M_finish(0), _M_end_of_storage(0) { + } + }; + typedef _Alloc allocator_type; + _Tp_alloc_type& _M_get_Tp_allocator() { + } + _Vector_base(size_t __n, const allocator_type& __a) : _M_impl(__a) { + _M_create_storage(__n); + } + _Vector_impl _M_impl; + pointer _M_allocate(size_t __n) { + return __n != 0 ? _M_impl.allocate(__n) : 0; + } + void _M_create_storage(size_t __n) { + this->_M_impl._M_start = this->_M_allocate(__n); + this->_M_impl._M_finish = this->_M_impl._M_start; + } + }; + template<typename _Tp, typename _Alloc = std::allocator<_Tp> > class vector : protected _Vector_base<_Tp, _Alloc> { + typedef _Vector_base<_Tp, _Alloc> _Base; + typedef _Tp value_type; + typedef size_t size_type; + typedef _Alloc allocator_type; + using _Base::_M_get_Tp_allocator; + public: + explicit vector(size_type __n, const value_type& __value = value_type(), const allocator_type& __a = allocator_type()) : _Base(__n, __a) { + _M_fill_initialize(__n, __value); + } + void _M_fill_initialize(size_type __n, const value_type& __value) { + std::__uninitialized_fill_n_a(this->_M_impl._M_start, __n, __value, _M_get_Tp_allocator()); + } + }; +}; +class QPaintDevice { +public: + int width() const { + } + int height() const { + } +}; +class QImage : public QPaintDevice { +}; +extern "C" { + struct __jmp_buf_tag { + }; + typedef struct __jmp_buf_tag jmp_buf[1]; + extern int _setjmp (struct __jmp_buf_tag __env[1]) throw (); + extern void longjmp (struct __jmp_buf_tag __env[1], int __val) throw () __attribute__ ((__noreturn__)); +} +typedef unsigned int png_uint_32; +typedef void * png_voidp; +typedef const char * png_const_charp; +extern "C" { + typedef struct png_struct_def png_struct; + typedef png_struct * png_structp; + typedef void ( *png_error_ptr) (png_structp, png_const_charp); + typedef void ( *png_longjmp_ptr) (jmp_buf, int); + extern __attribute__((__malloc__)) png_structp ( png_create_write_struct) (png_const_charp user_png_ver, png_voidp error_ptr, png_error_ptr error_fn, png_error_ptr warn_fn) ; + extern jmp_buf* ( png_set_longjmp_fn) (png_structp png_ptr, png_longjmp_ptr longjmp_fn, size_t jmp_buf_size) ; +} +class PngWriter : public QObject { + const QImage *m_out_qimage; + QString m_fname; + bool writeQImageToPng(); +}; +bool PngWriter::writeQImageToPng() { + png_uint_32 width = m_out_qimage->width(); + png_uint_32 height = m_out_qimage->height(); + if ( !m_fname.isEmpty() ) { + std::vector<char> t(width * height * 4 + (width * height * 4) * 0.1); + } + png_structp png_ptr = png_create_write_struct ("1.5.13", __null, __null, __null); + if (_setjmp ((*png_set_longjmp_fn((png_ptr), longjmp, sizeof (jmp_buf))))) { + } +} diff --git a/gcc/tree-eh.c b/gcc/tree-eh.c index 56132e1..c900949 100644 --- a/gcc/tree-eh.c +++ b/gcc/tree-eh.c @@ -3342,7 +3342,24 @@ sink_clobbers (basic_block bb) if (!any_clobbers) return 0; - succbb = single_succ (bb); + edge succe = single_succ_edge (bb); + succbb = succe->dest; + + /* See if there is a virtual PHI node to take an updated virtual + operand from. */ + gimple vphi = NULL; + tree vuse = NULL_TREE; + for (gsi = gsi_start_phis (succbb); !gsi_end_p (gsi); gsi_next (&gsi)) + { + tree res = gimple_phi_result (gsi_stmt (gsi)); + if (virtual_operand_p (res)) + { + vphi = gsi_stmt (gsi); + vuse = res; + break; + } + } + dgsi = gsi_after_labels (succbb); gsi = gsi_last_bb (bb); for (gsi_prev (&gsi); !gsi_end_p (gsi); gsi_prev (&gsi)) @@ -3353,7 +3370,6 @@ sink_clobbers (basic_block bb) continue; if (gimple_code (stmt) == GIMPLE_LABEL) break; - unlink_stmt_vdef (stmt); lhs = gimple_assign_lhs (stmt); /* Unfortunately we don't have dominance info updated at this point, so checking if @@ -3365,21 +3381,33 @@ sink_clobbers (basic_block bb) && TREE_CODE (TREE_OPERAND (lhs, 0)) == SSA_NAME && !SSA_NAME_IS_DEFAULT_DEF (TREE_OPERAND (lhs, 0))) { + unlink_stmt_vdef (stmt); gsi_remove (&gsi, true); release_defs (stmt); continue; } + + /* As we do not change stmt order when sinking across a + forwarder edge we can keep virtual operands in place. */ gsi_remove (&gsi, false); - /* Trigger the operand scanner to cause renaming for virtual - operands for this statement. - ??? Given the simple structure of this code manually - figuring out the reaching definition should not be too hard. */ - if (gimple_vuse (stmt)) - gimple_set_vuse (stmt, NULL_TREE); - gsi_insert_before (&dgsi, stmt, GSI_SAME_STMT); + gsi_insert_before (&dgsi, stmt, GSI_NEW_STMT); + + /* But adjust virtual operands if we sunk across a PHI node. */ + if (vuse) + { + gimple use_stmt; + imm_use_iterator iter; + use_operand_p use_p; + FOR_EACH_IMM_USE_STMT (use_stmt, iter, vuse) + FOR_EACH_IMM_USE_ON_STMT (use_p, iter) + SET_USE (use_p, gimple_vdef (stmt)); + /* Adjust the incoming virtual operand. */ + SET_USE (PHI_ARG_DEF_PTR_FROM_EDGE (vphi, succe), gimple_vuse (stmt)); + SET_USE (gimple_vuse_op (stmt), vuse); + } } - return TODO_update_ssa_only_virtuals; + return 0; } /* At the end of inlining, we can lower EH_DISPATCH. Return true when |