diff mbox

Fix PR54735

Message ID alpine.LNX.2.00.1210021534210.4063@zhemvz.fhfr.qr
State New
Headers show

Commit Message

Richard Biener Oct. 2, 2012, 1:38 p.m. UTC
This fixes PR54735 - a bad interaction of non-up-to-date virtual
SSA form, update-SSA and cfg cleanup.  Morale of the story:
cfg cleanup can remove blocks and thus release SSA names - SSA
update is rightfully confused when such released SSA name is
still used at update time.

The following patch fixes the case in question simply by making
sure to run update-SSA before cfg cleanup.

[eventually release_ssa_name could treat virtual operands the
same as regular SSA names when they are scheduled for a re-write,
that would make this whole mess more robust - I am thinking of this]

Bootstrapped on x86_64-unknown-linux-gnu, testing in progress.

Richard.

2012-10-02  Richard Guenther  <rguenther@suse.de>

	PR middle-end/54735
	* tree-ssa-pre.c (do_pre): Make sure to update virtual SSA form before
	cleaning up the CFG.

	* g++.dg/torture/pr54735.C: New testcase.
diff mbox

Patch

Index: gcc/tree-ssa-pre.c
===================================================================
--- gcc/tree-ssa-pre.c	(revision 191969)
+++ gcc/tree-ssa-pre.c	(working copy)
@@ -4820,6 +4820,13 @@  do_pre (void)
 
   free_scc_vn ();
 
+  /* Tail merging invalidates the virtual SSA web, together with
+     cfg-cleanup opportunities exposed by PRE this will wreck the
+     SSA updating machinery.  So make sure to run update-ssa
+     manually, before eventually scheduling cfg-cleanup as part of
+     the todo.  */
+  update_ssa (TODO_update_ssa_only_virtuals);
+
   return todo;
 }
 
@@ -4845,8 +4852,7 @@  struct gimple_opt_pass pass_pre =
   0,					/* properties_provided */
   0,					/* properties_destroyed */
   TODO_rebuild_alias,			/* todo_flags_start */
-  TODO_update_ssa_only_virtuals  | TODO_ggc_collect
-  | TODO_verify_ssa /* todo_flags_finish */
+  TODO_ggc_collect | TODO_verify_ssa	/* todo_flags_finish */
  }
 };
 
Index: gcc/testsuite/g++.dg/torture/pr54735.C
===================================================================
--- gcc/testsuite/g++.dg/torture/pr54735.C	(revision 0)
+++ gcc/testsuite/g++.dg/torture/pr54735.C	(working copy)
@@ -0,0 +1,179 @@ 
+// { dg-do compile }
+
+class Gmpfr
+{};
+class M : Gmpfr
+{
+public:
+  Gmpfr infconst;
+  M(int);
+};
+template<typename>struct A;
+template<typename, int, int, int = 0 ? : 0, int = 0, int = 0>class N;
+template<typename>class O;
+template<typename>struct B;
+struct C
+{
+  enum
+  { value };
+};
+class D
+{
+public:
+  enum
+  { ret };
+};
+struct F
+{
+  enum
+  { ret = 0 ? : 0 };
+};
+template<typename Derived>struct G
+{
+  typedef O<Derived>type;
+};
+struct H
+{
+  void operator * ();
+};
+struct I
+{
+  enum
+  { RequireInitialization = C::value ? : 0, ReadCost };
+};
+template<typename Derived>struct J
+{
+  enum
+  { ret = A<Derived>::InnerStrideAtCompileTime };
+};
+template<typename Derived>struct K
+{
+  enum
+  { ret = A<Derived>::OuterStrideAtCompileTime };
+};
+template<typename Derived>class P : H
+{
+public:
+  using H::operator *;
+  typedef typename A<Derived>::Scalar Scalar;
+  enum
+  { RowsAtCompileTime                                        =
+      A<Derived>::RowsAtCompileTime, ColsAtCompileTime       =
+      A<Derived>::ColsAtCompileTime, SizeAtCompileTime       =
+      F::ret, MaxRowsAtCompileTime                           =
+      A<Derived>::MaxRowsAtCompileTime, MaxColsAtCompileTime =
+      A<Derived>::MaxColsAtCompileTime, MaxSizeAtCompileTime =
+      F::ret, Flags                                          =
+      A<Derived>::Flags ? : 0 ? : 0, CoeffReadCost           =
+      A<Derived>::CoeffReadCost, InnerStrideAtCompileTime    =
+      J<Derived>::ret, OuterStrideAtCompileTime              = K<Derived>::ret };
+  B<Derived> operator << (const Scalar&);
+};
+
+template<typename Derived>class O : public P<Derived>
+{};
+
+template<int _Cols>class L
+{
+public:
+
+  int cols()
+  {
+    return _Cols;
+  }
+};
+template<typename Derived>class Q : public G<Derived>::type
+{
+public:
+  typedef typename G<Derived>::type   Base;
+  typedef typename A<Derived>::Index  Index;
+  typedef typename A<Derived>::Scalar Scalar;
+  L<Base::ColsAtCompileTime> m_storage;
+  Index cols()
+  {
+    return m_storage.cols();
+  }
+
+  Scalar& coeffRef(Index,
+                   Index);
+};
+
+template<typename _Scalar, int _Rows, int _Cols, int _Options, int _MaxRows,
+         int _MaxCols>struct A<N<_Scalar, _Rows, _Cols, _Options, _MaxRows,
+                                 _MaxCols> >
+{
+  typedef _Scalar Scalar;
+  typedef int     Index;
+  enum
+  { RowsAtCompileTime, ColsAtCompileTime                              =
+      _Cols, MaxRowsAtCompileTime, MaxColsAtCompileTime, Flags        =
+      D::ret, CoeffReadCost                                           =
+      I::ReadCost, InnerStrideAtCompileTime, OuterStrideAtCompileTime =
+      0 ? : 0 };
+};
+template<typename _Scalar, int, int _Cols, int, int,
+         int>class N : public Q<N<_Scalar, 0, _Cols> >
+{
+public:
+  Q<N> Base;
+  template<typename T0, typename T1>N(const T0&,
+                                      const T1&);
+};
+void
+__assert_fail(int)
+throw() __attribute__((__noreturn__));
+template<typename XprType>struct B
+{
+  typedef typename XprType::Scalar Scalar;
+  typedef typename XprType::Index  Index;
+  B(XprType & p1, const Scalar &) : m_xpr(p1), m_col(),
+                                    m_currentBlockRows(1)
+  {} B& operator, (const Scalar&)
+  {
+    Index a;
+
+    if (m_col == m_xpr.cols())
+    {
+      m_col              = 0;
+      m_currentBlockRows = 1;
+      a && "Too       " ? static_cast<void>(0) : __assert_fail(0);
+    }
+    m_col < m_xpr.cols()
+    && "Too       " ? static_cast<void>(0) : __assert_fail(1);
+    m_currentBlockRows ? static_cast<void>(0) : __assert_fail(4);
+    m_xpr.coeffRef(0, m_col++) = 0;
+    return *this;
+  }
+  ~B()
+  {
+    1 + m_currentBlockRows && m_col
+    && "Too       " ? static_cast<void>(0) : __assert_fail(0);
+  }
+
+  XprType& m_xpr;
+  Index    m_col;
+  Index    m_currentBlockRows;
+};
+
+template<typename Derived>B<Derived>P<
+  Derived >::operator << (const Scalar&)
+{
+    return B<Derived>(*static_cast<Derived *>(this), 0);
+}
+
+template<class NT, int s>void
+               check_()
+{
+    N<NT, 0, s>m(0, 0);
+    m << 0, 0, 0, 0;
+}
+
+template<class NT>void check()
+{
+    check_<NT, 3>();
+}
+
+int main()
+{
+    check<M>();
+}