diff options
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/ChangeLog | 6 | ||||
-rw-r--r-- | gcc/testsuite/ChangeLog | 5 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/torture/pr39362.C | 105 | ||||
-rw-r--r-- | gcc/tree-ssa-sccvn.c | 21 |
4 files changed, 129 insertions, 8 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 451eafa..333fd9d 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,9 @@ +2009-03-04 Richard Guenther <rguenther@suse.de> + + PR tree-optimization/39362 + * tree-ssa-sccvn.c (visit_use): Stores and copies from SSA_NAMEs + that occur in abnormal PHIs should be varying. + 2009-03-04 Zdenek Dvorak <ook@ucw.cz> * tree-scalar-evolution.c (analyze_scalar_evolution_in_loop): diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 97668fd..ca0a6ee 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2009-03-04 Richard Guenther <rguenther@suse.de> + + PR tree-optimization/39362 + * g++.dg/torture/pr39362.C: New testcase. + 2009-03-04 Jason Merrill <jason@redhat.com> Giovanni Bajo <giovannibajo@gcc.gnu.org> diff --git a/gcc/testsuite/g++.dg/torture/pr39362.C b/gcc/testsuite/g++.dg/torture/pr39362.C new file mode 100644 index 0000000..fb23439 --- /dev/null +++ b/gcc/testsuite/g++.dg/torture/pr39362.C @@ -0,0 +1,105 @@ +/* { dg-do compile } */ + +void *fastMalloc (int n); +void fastFree (void *p); +template <class T> struct C +{ + void deref () { delete static_cast <T *>(this); } +}; +template <typename T> +struct D +{ + D (T *ptr) : m_ptr (ptr) { } + ~D () { if (T * ptr = m_ptr) ptr->deref (); } + T *operator-> () const; + T *m_ptr; + typedef T *UnspecifiedBoolType; + operator UnspecifiedBoolType () const; +}; +template <typename T> struct E +{ + static void destruct (T * begin, T * end) + { + for (T * cur = begin; cur != end; ++cur) + cur->~T (); + } +}; +template <typename T> class F; +template <typename T> struct G +{ + static void destruct (T * begin, T * end) + { + E <T>::destruct (begin, end); + } + static void uninitializedFill (T * dst, T * dstEnd, const T & val) + { + F<T>::uninitializedFill (dst, dstEnd, val); + } +}; +template <typename T> struct H +{ + void allocateBuffer (int newCapacity) + { + m_buffer = static_cast <T *>(fastMalloc (newCapacity * sizeof (T))); + } + void deallocateBuffer (T * bufferToDeallocate) + { + if (m_buffer == bufferToDeallocate) + fastFree (bufferToDeallocate); + } + T *buffer () { } + int capacity () const { } + T *m_buffer; +}; +template <typename T, int cap> class I; +template <typename T> struct I <T, 0> : H <T> +{ + I (int capacity) { allocateBuffer (capacity); } + ~I () { deallocateBuffer (buffer ()); } + using H <T>::allocateBuffer; + H <T>::buffer; +}; +template <typename T, int cap = 0> struct J +{ + typedef T *iterator; + ~J () { if (m_size) shrink (0); } + J (const J &); + int capacity () const { m_buffer.capacity (); } + T & operator[](int i) { } + iterator begin () { } + iterator end () { return begin () + m_size; } + void shrink (int size); + template <typename U> void append (const U &); + int m_size; + I <T, cap> m_buffer; +}; +template <typename T, int cap> +J <T, cap>::J (const J & other) : m_buffer (other.capacity ()) +{ +} +template <typename T, int cap> +void J <T, cap>::shrink (int size) +{ + G <T>::destruct (begin () + size, end ()); + m_size = size; +} +struct A : public C <A> +{ + virtual ~A (); + typedef J <D <A> > B; + virtual A *firstChild () const; + virtual A *nextSibling () const; + virtual const B & children (int length); + B m_children; +}; +const A::B & +A::children (int length) +{ + for (D <A> obj = firstChild (); obj; obj = obj->nextSibling ()) + { + B children = obj->children (2); + for (unsigned i = 0; i <length; ++i) + m_children.append (children[i]); + } +} + diff --git a/gcc/tree-ssa-sccvn.c b/gcc/tree-ssa-sccvn.c index bc4fd7c..dc55676 100644 --- a/gcc/tree-ssa-sccvn.c +++ b/gcc/tree-ssa-sccvn.c @@ -2367,14 +2367,19 @@ visit_use (tree use) VN_INFO (lhs)->expr = NULL_TREE; } - if (TREE_CODE (lhs) == SSA_NAME - /* We can substitute SSA_NAMEs that are live over - abnormal edges with their constant value. */ - && !(gimple_assign_copy_p (stmt) - && is_gimple_min_invariant (gimple_assign_rhs1 (stmt))) - && !(simplified - && is_gimple_min_invariant (simplified)) - && SSA_NAME_OCCURS_IN_ABNORMAL_PHI (lhs)) + if ((TREE_CODE (lhs) == SSA_NAME + /* We can substitute SSA_NAMEs that are live over + abnormal edges with their constant value. */ + && !(gimple_assign_copy_p (stmt) + && is_gimple_min_invariant (gimple_assign_rhs1 (stmt))) + && !(simplified + && is_gimple_min_invariant (simplified)) + && SSA_NAME_OCCURS_IN_ABNORMAL_PHI (lhs)) + /* Stores or copies from SSA_NAMEs that are live over + abnormal edges are a problem. */ + || (gimple_assign_single_p (stmt) + && TREE_CODE (gimple_assign_rhs1 (stmt)) == SSA_NAME + && SSA_NAME_OCCURS_IN_ABNORMAL_PHI (gimple_assign_rhs1 (stmt)))) changed = defs_to_varying (stmt); else if (REFERENCE_CLASS_P (lhs) || DECL_P (lhs)) { |