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
This commit is contained in:
parent
54b8379a26
commit
4c1aff1ce4
4 changed files with 241 additions and 10 deletions
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
193
gcc/testsuite/g++.dg/torture/pr57107.C
Normal file
193
gcc/testsuite/g++.dg/torture/pr57107.C
Normal file
|
@ -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))))) {
|
||||
}
|
||||
}
|
|
@ -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
|
||||
|
|
Loading…
Add table
Reference in a new issue