2009-03-04 Richard Guenther <rguenther@suse.de>
authorrguenth <rguenth@138bc75d-0d04-0410-961f-82ee72b054a4>
Wed, 4 Mar 2009 23:00:25 +0000 (23:00 +0000)
committerrguenth <rguenth@138bc75d-0d04-0410-961f-82ee72b054a4>
Wed, 4 Mar 2009 23:00:25 +0000 (23:00 +0000)
PR tree-optimization/39362
* tree-ssa-sccvn.c (visit_use): Stores and copies from SSA_NAMEs
that occur in abnormal PHIs should be varying.

* g++.dg/torture/pr39362.C: New testcase.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@144626 138bc75d-0d04-0410-961f-82ee72b054a4

gcc/ChangeLog
gcc/testsuite/ChangeLog
gcc/testsuite/g++.dg/torture/pr39362.C [new file with mode: 0644]
gcc/tree-ssa-sccvn.c

index 451eafa..333fd9d 100644 (file)
@@ -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):
index 97668fd..ca0a6ee 100644 (file)
@@ -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 (file)
index 0000000..fb23439
--- /dev/null
@@ -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]);
+    }
+}
+
index bc4fd7c..dc55676 100644 (file)
@@ -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))
            {