re PR c++/63419 (verify_gimple failed: "vector CONSTRUCTOR element is not a GIMPLE...
authorRichard Biener <rguenther@suse.de>
Mon, 13 Oct 2014 07:58:05 +0000 (07:58 +0000)
committerRichard Biener <rguenth@gcc.gnu.org>
Mon, 13 Oct 2014 07:58:05 +0000 (07:58 +0000)
2014-10-13  Richard Biener  <rguenther@suse.de>

PR tree-optimization/63419
* gimple-fold.h (gimple_convert): New function.
* gimple-fold.c (gimple_convert): Likewise.
* tree-ssa-pre.c (create_expression_by_pieces): Use gimple_convert
to split out required conversions early.

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

From-SVN: r216138

gcc/ChangeLog
gcc/gimple-fold.c
gcc/gimple-fold.h
gcc/testsuite/ChangeLog
gcc/testsuite/g++.dg/torture/pr63419.C [new file with mode: 0644]
gcc/tree-ssa-pre.c

index e01505f32824d2001fbd6e0885ff925f9229c856..a8359339684339cf780f06fbb5328e6eb24c2fa2 100644 (file)
@@ -1,3 +1,11 @@
+2014-10-13  Richard Biener  <rguenther@suse.de>
+
+       PR tree-optimization/63419
+       * gimple-fold.h (gimple_convert): New function.
+       * gimple-fold.c (gimple_convert): Likewise.
+       * tree-ssa-pre.c (create_expression_by_pieces): Use gimple_convert
+       to split out required conversions early.
+
 2014-10-13  Richard Sandiford  <richard.sandiford@arm.com>
 
        * rtlanal.c (generic_subrtx_iterator <T>::add_subrtxes_to_queue):
index 76441c746bc868ab6e127d69f357de359b266298..a0ce0db9766f2ce7e1eace92b01826b00f981bd6 100644 (file)
@@ -5295,3 +5295,20 @@ rewrite_to_defined_overflow (gimple stmt)
 
   return stmts;
 }
+
+/* Return OP converted to TYPE by emitting a conversion statement on SEQ
+   if required using location LOC.  Note that OP will be returned
+   unmodified if GIMPLE does not require an explicit conversion between
+   its type and TYPE.  */
+
+tree
+gimple_convert (gimple_seq *seq, location_t loc, tree type, tree op)
+{
+  if (useless_type_conversion_p (type, TREE_TYPE (op)))
+    return op;
+  op = fold_convert_loc (loc, type, op);
+  gimple_seq stmts = NULL;
+  op = force_gimple_operand (op, &stmts, true, NULL_TREE);
+  gimple_seq_add_seq_without_update (seq, stmts);
+  return op;
+}
index 9b4e4566a1268f336b78526ed6a6d0b1dbafa352..b55a3ef8b3e878b82122506b09d6da10395e573b 100644 (file)
@@ -45,4 +45,11 @@ extern tree gimple_fold_indirect_ref (tree);
 extern bool arith_code_with_undefined_signed_overflow (tree_code);
 extern gimple_seq rewrite_to_defined_overflow (gimple);
 
+extern tree gimple_convert (gimple_seq *, location_t, tree, tree);
+inline tree
+gimple_convert (gimple_seq *seq, tree type, tree op)
+{
+  return gimple_convert (seq, UNKNOWN_LOCATION, type, op);
+}
+
 #endif  /* GCC_GIMPLE_FOLD_H */
index f34d55f8a754e143a995a06e9b395f05a1a70ce0..1ab2f218049f1abfdf36d332ef3adf76c3d6b2df 100644 (file)
@@ -1,3 +1,8 @@
+2014-10-13  Richard Biener  <rguenther@suse.de>
+
+       PR tree-optimization/63419
+       * g++.dg/torture/pr63419.C: New testcase.
+
 2014-10-12  Oleg Endo  <olegendo@gcc.gnu.org>
 
        PR target/59401
diff --git a/gcc/testsuite/g++.dg/torture/pr63419.C b/gcc/testsuite/g++.dg/torture/pr63419.C
new file mode 100644 (file)
index 0000000..53f7c3e
--- /dev/null
@@ -0,0 +1,225 @@
+// { dg-do compile }
+
+typedef float __m128 __attribute__ ((__vector_size__ (16)));
+const int a = 0;
+enum
+{
+  ReadOnlyAccessors
+};
+template <typename> struct traits;
+struct A
+{
+  enum
+  {
+    value = 1
+  };
+};
+template <typename> struct EigenBase;
+template <typename> class J;
+template <typename, int = A::value> class DenseCoeffsBase;
+template <typename, int, int, int = 0, int = 0, int = 0> class K;
+template <typename> class N;
+template <typename, typename> class CwiseUnaryOp;
+template <typename> class L;
+template <typename> class P;
+template <typename> struct B;
+template <typename> struct C;
+template <typename Derived> struct dense_xpr_base
+{
+  typedef N<Derived> type;
+};
+template <typename Packet> void padd (Packet);
+template <> struct C<float>
+{
+  typedef __m128 type;
+};
+struct D
+{
+  void
+  packetOp (C<float>::type)
+  {
+    __m128 b = { m_other };
+    padd (b);
+  }
+  float m_other;
+};
+template <typename Derived>
+class DenseCoeffsBase<Derived, ReadOnlyAccessors> : public EigenBase<Derived>
+{
+public:
+  typedef typename C<typename traits<Derived>::Scalar>::type PacketScalar;
+};
+template <typename Derived>
+class DenseCoeffsBase<Derived>
+    : public DenseCoeffsBase<Derived, ReadOnlyAccessors>
+{
+public:
+  template <typename OtherDerived, int, int LoadMode>
+  void
+  copyPacket (typename traits<Derived>::Index, J<OtherDerived> p2)
+  {
+    p2.derived ().template packet<LoadMode> (0);
+  }
+};
+template <typename Derived> class J : public DenseCoeffsBase<Derived>
+{
+public:
+  using DenseCoeffsBase<Derived>::derived;
+  template <typename OtherDerived>
+  Derived &lazyAssign (const J<OtherDerived> &);
+};
+template <typename Derived> class N : public J<Derived>
+{
+public:
+  template <typename OtherDerived>
+  typename B<OtherDerived>::Type operator*(N<OtherDerived>);
+  L<Derived> array ();
+};
+template <typename Derived> struct EigenBase
+{
+  Derived
+  derived () const
+  {
+    return *static_cast<const Derived *> (this);
+  }
+};
+template <typename Derived1, typename Derived2> struct F
+{
+  static void
+  run (Derived1 p1, Derived2 p2)
+  {
+    enum
+    {
+      srcAlignment
+    };
+    for (;;)
+      p1.template copyPacket<Derived2, 0, srcAlignment> (0, p2);
+  }
+};
+template <typename Derived>
+template <typename OtherDerived>
+Derived &
+J<Derived>::lazyAssign (const J<OtherDerived> &p1)
+{
+  F<Derived, OtherDerived>::run (derived (), p1.derived ());
+}
+template <typename Derived, typename OtherDerived> struct G
+{
+  static Derived
+  run (Derived p1, OtherDerived p2)
+  {
+    p1.lazyAssign (p2);
+  }
+};
+class H
+{
+public:
+  H (int, int, int);
+};
+template <typename Derived> class M : public dense_xpr_base<Derived>::type
+{
+public:
+  typedef typename traits<Derived>::Index Index;
+  H m_storage;
+  M (Index, Index, Index) : m_storage (0, 0, 0) {}
+  template <typename OtherDerived>
+  void
+  _set_noalias (J<OtherDerived> p1)
+  {
+    G<Derived, OtherDerived>::run (this->derived (), p1.derived ());
+  }
+};
+template <typename _Scalar, int _Rows, int _Cols, int _Options, int _MaxRows,
+          int _MaxCols>
+struct traits<K<_Scalar, _Rows, _Cols, _Options, _MaxRows, _MaxCols> >
+{
+  typedef _Scalar Scalar;
+  typedef int StorageKind;
+  typedef int Index;
+};
+template <typename, int _Rows, int _Cols, int, int, int>
+class K : public M<K<float, _Rows, _Cols> >
+{
+public:
+  typedef M<K> Base;
+  typedef K Nested;
+  template <typename T0, typename T1> K (T0, T1);
+  template <typename OtherDerived> K (N<OtherDerived> p1) : Base (0, 0, 0)
+  {
+    Base::_set_noalias (p1);
+  }
+};
+template <typename UnaryOp, typename XprType>
+struct traits<CwiseUnaryOp<UnaryOp, XprType> > : traits<XprType>
+{
+};
+template <typename, typename, typename> class I;
+template <typename, typename XprType>
+class CwiseUnaryOp
+    : public I<D, XprType, typename traits<XprType>::StorageKind>
+{
+public:
+  D
+  functor ()
+  {
+    return m_functor;
+  }
+  typename XprType::Nested nestedExpression ();
+  D m_functor;
+};
+template <typename UnaryOp, typename XprType>
+class I<UnaryOp, XprType, int>
+    : public dense_xpr_base<CwiseUnaryOp<UnaryOp, XprType> >::type
+{
+public:
+  typedef CwiseUnaryOp<UnaryOp, XprType> Derived;
+  typedef typename dense_xpr_base<CwiseUnaryOp<UnaryOp, XprType> >::type Base;
+  typedef Derived Nested;
+  using Base::derived;
+  template <int LoadMode> void packet (typename traits<Derived>::Index)
+  {
+    derived ().functor ().packetOp (
+        derived ().nestedExpression ().template packet<LoadMode> (0));
+  }
+};
+template <typename> struct B
+{
+  typedef P<CwiseUnaryOp<D, L<K<float, 0, 1> > > > Type;
+};
+template <typename Derived> class O : public J<Derived>
+{
+public:
+  P<Derived> matrix ();
+};
+template <typename ExpressionType>
+struct traits<L<ExpressionType> > : traits<typename ExpressionType::Nested>
+{
+};
+template <typename ExpressionType> class L : public O<L<ExpressionType> >
+{
+public:
+  typedef L Nested;
+  template <int>
+  typename O<L>::PacketScalar packet (typename traits<L>::Index);
+};
+template <typename ExpressionType>
+struct traits<P<ExpressionType> > : traits<typename ExpressionType::Nested>
+{
+};
+template <typename ExpressionType> class P : public N<P<ExpressionType> >
+{
+public:
+  N<P> Base;
+  template <int LoadMode> void packet (typename traits<P>::Index)
+  {
+    m_expression.template packet<LoadMode> (0);
+  }
+  ExpressionType m_expression;
+};
+int
+main ()
+{
+  K<float, 0, a> m (0, 0);
+  K<float, 0, 1> c (0, 0);
+  c = m.array ().matrix () * m;
+}
index a447c1e4f06d974353f10538455f8bb0f640be08..60ff70fa42b09c2374327973ff753e0f9a1e60d6 100644 (file)
@@ -2819,12 +2819,15 @@ create_expression_by_pieces (basic_block block, pre_expr expr,
            if (nary->opcode == POINTER_PLUS_EXPR)
              {
                if (i == 0)
-                 genop[i] = fold_convert (nary->type, genop[i]);
+                 genop[i] = gimple_convert (&forced_stmts,
+                                            nary->type, genop[i]);
                else if (i == 1)
-                 genop[i] = convert_to_ptrofftype (genop[i]);
+                 genop[i] = gimple_convert (&forced_stmts,
+                                            sizetype, genop[i]);
              }
            else
-             genop[i] = fold_convert (TREE_TYPE (nary->op[i]), genop[i]);
+             genop[i] = gimple_convert (&forced_stmts,
+                                        TREE_TYPE (nary->op[i]), genop[i]);
          }
        if (nary->opcode == CONSTRUCTOR)
          {
@@ -2866,8 +2869,10 @@ create_expression_by_pieces (basic_block block, pre_expr expr,
      statements.
      We have to call unshare_expr because force_gimple_operand may
      modify the tree we pass to it.  */
-  folded = force_gimple_operand (unshare_expr (folded), &forced_stmts,
+  gimple_seq tem = NULL;
+  folded = force_gimple_operand (unshare_expr (folded), &tem,
                                 false, NULL);
+  gimple_seq_add_seq_without_update (&forced_stmts, tem);
 
   /* If we have any intermediate expressions to the value sets, add them
      to the value sets and chain them in the instruction stream.  */