Bootstrapped and tested on x86_64-unknown-linux-gnu, applied to branch,
testcase also to trunk.

Richard.

2017-11-15  Richard Biener  <rguent...@suse.de>

        PR tree-optimization/82985
        Backport from mainline
        2017-08-15  Richard Biener  <rguent...@suse.de>

        PR tree-optimization/81790
        * tree-ssa-sccvn.c (vn_lookup_simplify_result): Handle both
        CONSTRUCTORs from simplifying and VN.

        * gcc.dg/torture/pr81790.c: New testcase.
        * g++.dg/torture/pr82985.C: Likewise.

Index: gcc/testsuite/gcc.dg/torture/pr81790.c
===================================================================
--- gcc/testsuite/gcc.dg/torture/pr81790.c      (revision 0)
+++ gcc/testsuite/gcc.dg/torture/pr81790.c      (working copy)
@@ -0,0 +1,28 @@
+/* { dg-do compile } */
+/* { dg-additional-options "--param sccvn-max-scc-size=10" } */
+
+typedef int a __attribute__ ((__vector_size__ (16)));
+typedef struct
+{
+  a b;
+} c;
+
+int d, e;
+
+void foo (c *ptr);
+
+void bar ()
+{
+  double b = 1842.9028;
+  c g, h;
+  if (d)
+    b = 77.7998;
+  for (; e;)
+    {
+      g.b = g.b = g.b + g.b;
+      h.b = (a){b};
+      h.b = h.b + h.b;
+    }
+  foo (&g);
+  foo (&h);
+}
Index: gcc/tree-ssa-sccvn.c
===================================================================
--- gcc/tree-ssa-sccvn.c        (revision 254492)
+++ gcc/tree-ssa-sccvn.c        (working copy)
@@ -1643,13 +1643,25 @@ static vn_nary_op_t vn_nary_op_insert_st
 /* Hook for maybe_push_res_to_seq, lookup the expression in the VN tables.  */
 
 static tree
-vn_lookup_simplify_result (code_helper rcode, tree type, tree *ops)
+vn_lookup_simplify_result (code_helper rcode, tree type, tree *ops_)
 {
   if (!rcode.is_tree_code ())
     return NULL_TREE;
+  tree *ops = ops_;
+  unsigned int length = TREE_CODE_LENGTH ((tree_code) rcode);
+  if (rcode == CONSTRUCTOR
+      /* ???  We're arriving here with SCCVNs view, decomposed CONSTRUCTOR
+        and GIMPLEs / match-and-simplifies, CONSTRUCTOR as GENERIC tree.  */
+      && TREE_CODE (ops_[0]) == CONSTRUCTOR)
+    {
+      length = CONSTRUCTOR_NELTS (ops_[0]);
+      ops = XALLOCAVEC (tree, length);
+      for (unsigned i = 0; i < length; ++i)
+       ops[i] = CONSTRUCTOR_ELT (ops_[0], i)->value;
+    }
   vn_nary_op_t vnresult = NULL;
-  return vn_nary_op_lookup_pieces (TREE_CODE_LENGTH ((tree_code) rcode),
-                                  (tree_code) rcode, type, ops, &vnresult);
+  return vn_nary_op_lookup_pieces (length, (tree_code) rcode,
+                                  type, ops, &vnresult);
 }
 
 /* Return a value-number for RCODE OPS... either by looking up an existing
Index: gcc/testsuite/g++.dg/torture/pr82985.C
===================================================================
--- gcc/testsuite/g++.dg/torture/pr82985.C      (nonexistent)
+++ gcc/testsuite/g++.dg/torture/pr82985.C      (working copy)
@@ -0,0 +1,458 @@
+/* { dg-do compile } */
+/* { dg-additional-options "-w" } */
+/* { dg-additional-options "-mavx2" { target { x86_64-*-* i?86-*-* } } } */
+
+namespace std {
+template < typename _Default > struct __detector { using type = _Default; };
+template < typename _Default, template < typename > class >
+using __detected_or = __detector< _Default >;
+template < typename _Default, template < typename > class _Op >
+using __detected_or_t = typename __detected_or< _Default, _Op >::type;
+template < typename > struct iterator_traits;
+template < typename _Tp > struct iterator_traits< _Tp * > {
+  typedef _Tp reference;
+};
+} // std
+using std::iterator_traits;
+template < typename _Iterator, typename > struct __normal_iterator {
+  typename iterator_traits< _Iterator >::reference operator*();
+  void operator++();
+};
+template < typename _IteratorL, typename _IteratorR, typename _Container >
+int operator!=(__normal_iterator< _IteratorL, _Container >,
+               __normal_iterator< _IteratorR, _Container >);
+namespace std {
+template < typename _Tp > struct allocator { typedef _Tp value_type; };
+struct __allocator_traits_base {
+  template < typename _Tp > using __pointer = typename _Tp::pointer;
+};
+template < typename _Alloc > struct allocator_traits : __allocator_traits_base 
{
+  using pointer = __detected_or_t< typename _Alloc::value_type *, __pointer >;
+};
+} // std
+typedef double __m128d __attribute__((__vector_size__(16)));
+typedef double __m256d __attribute__((__vector_size__(32)));
+enum { InnerVectorizedTraversal, LinearVectorizedTraversal };
+enum { ReadOnlyAccessors };
+template < int, typename Then, typename > struct conditional {
+  typedef Then type;
+};
+template < typename Then, typename Else > struct conditional< 0, Then, Else > {
+  typedef Else type;
+};
+template < typename, typename > struct is_same {
+  enum { value };
+};
+template < typename T > struct is_same< T, T > {
+  enum { value = 1 };
+};
+template < typename > struct traits;
+struct accessors_level {
+  enum { has_direct_access, has_write_access, value };
+};
+template < typename > struct EigenBase;
+template < typename > struct PlainObjectBase;
+template < typename, int = accessors_level::value > struct DenseCoeffsBase;
+template < typename, int, int, int = 0, int = 0, int = 0 > struct Matrix;
+template < typename > struct MatrixBase;
+template < typename, int, int, bool = 0 > struct Block;
+struct VectorBlock;
+template < typename, typename > struct CwiseNullaryOp;
+template < typename, typename, typename > struct CwiseBinaryOp;
+template < typename, int = accessors_level::has_write_access > struct MapBase;
+template < typename > struct packet_traits;
+template < typename > struct unpacket_traits;
+template < int Size, typename PacketType,
+           int = Size == is_same< PacketType, typename unpacket_traits<
+                                                  PacketType >::half >::value >
+struct find_best_packet_helper;
+template < int Size, typename PacketType >
+struct find_best_packet_helper< Size, PacketType, 1 > {
+  typedef PacketType type;
+};
+template < int Size, typename PacketType >
+struct find_best_packet_helper< Size, PacketType, 0 > {
+  typedef typename find_best_packet_helper<
+      1, typename unpacket_traits< PacketType >::half >::type type;
+};
+template < typename T, int Size > struct find_best_packet {
+  typedef typename find_best_packet_helper<
+      Size, typename packet_traits< T >::type >::type type;
+};
+struct compute_matrix_flags {
+  enum { ret = 1 };
+};
+struct ref_selector {
+  typedef Matrix< double, 10, 1 > &type;
+};
+template < typename Derived > struct dense_xpr_base {
+  typedef MatrixBase< Derived > type;
+};
+template < typename ExpressionType > struct is_lvalue {
+  enum { value = traits< ExpressionType >::Flags };
+};
+template < typename Packet > void pmul(Packet);
+template < typename Packet >
+Packet pload(const typename unpacket_traits< Packet >::type *);
+template < typename Packet >
+Packet pset1(const typename unpacket_traits< Packet >::type &);
+template < typename Scalar, typename Packet > void pstoreu(Scalar, Packet &);
+template < typename Packet, int >
+Packet ploadt(const typename unpacket_traits< Packet >::type *from) {
+  return pload< Packet >(from);
+}
+template < typename Scalar, typename Packet, int >
+void pstoret(Scalar *to, const Packet from) {
+  pstoreu(to, from);
+}
+typedef __m128d Packet2d;
+template <> struct unpacket_traits< Packet2d > {
+  typedef double type;
+  typedef Packet2d half;
+};
+template <> Packet2d pload(const double *from) { return *(__m128d *)from; }
+typedef __m256d Packet4d;
+template <> struct packet_traits< double > { typedef Packet4d type; };
+template <> struct unpacket_traits< Packet4d > {
+  typedef double type;
+  typedef Packet2d half;
+};
+__m256d pset1___trans_tmp_1;
+template <> Packet4d pset1(const double &) {
+  int __A;
+  pset1___trans_tmp_1 = __m256d{__A};
+  return pset1___trans_tmp_1;
+}
+template <> void pstoreu(double *to, const Packet4d &from) {
+  *(__attribute__((__vector_size__(4 * sizeof(double)))) double *)to = from;
+}
+struct scalar_product_op {
+  template < typename Packet > void packetOp(Packet a, Packet) { pmul(a); }
+};
+struct scalar_constant_op {
+  template < typename PacketType > PacketType packetOp() {
+    return pset1< PacketType >(0);
+  }
+};
+struct assign_op {
+  template < int, typename Packet > void assignPacket(double *a, Packet b) {
+    pstoret< double, Packet, 0 >(a, b);
+  }
+};
+template < typename Derived >
+struct DenseCoeffsBase< Derived, 0 > : EigenBase< Derived > {};
+template < typename Derived >
+struct DenseCoeffsBase< Derived > : DenseCoeffsBase< Derived, 0 > {};
+template < typename Derived > struct DenseBase : DenseCoeffsBase< Derived > {
+  using DenseCoeffsBase< Derived >::derived;
+  enum { SizeAtCompileTime, MaxSizeAtCompileTime };
+  static CwiseNullaryOp< scalar_constant_op, Derived > Constant();
+  Derived &setConstant();
+  struct FixedSegmentReturnType {
+    typedef VectorBlock Type;
+  };
+  template < int > typename FixedSegmentReturnType::Type segment() {
+    return typename FixedSegmentReturnType::Type(derived(), 0, 0);
+  }
+};
+template < typename Derived > struct MatrixBase : DenseBase< Derived > {
+  using DenseBase< Derived >::derived;
+  template < typename OtherDerived >
+  CwiseBinaryOp< scalar_product_op, const Derived, const OtherDerived >
+  cwiseProduct(OtherDerived) {
+    return CwiseBinaryOp< scalar_product_op, const Derived,
+                          const OtherDerived >(derived(), derived());
+  }
+  template < typename OtherDerived >
+  Derived &operator=(const DenseBase< OtherDerived > &);
+};
+template < typename Derived > struct EigenBase {
+  Derived &derived() { return *static_cast< Derived * >(this); }
+  Derived derived() const;
+};
+template < typename > struct binary_evaluator;
+template < typename Derived > struct evaluator {
+  typedef Derived PlainObjectType;
+  typedef typename PlainObjectType::Scalar Scalar;
+  enum { IsVectorAtCompileTime, Flags };
+  evaluator(PlainObjectType m) : m_data(m.data()) {}
+  Scalar &coeffRef(int, int);
+  template < int, typename PacketType > PacketType packet(int, int) {
+    return ploadt< PacketType, 0 >(m_data);
+  }
+  const Scalar *m_data;
+};
+template < typename Scalar, int Rows, int Cols, int Options, int MaxRows,
+           int MaxCols >
+struct evaluator< Matrix< Scalar, Rows, Cols, Options, MaxRows, MaxCols > >
+    : evaluator< PlainObjectBase< Matrix< Scalar, Rows, Cols > > > {
+  typedef Matrix< Scalar, Rows, Cols > XprType;
+  evaluator(XprType m) : evaluator< PlainObjectBase< XprType > >(m) {}
+};
+struct nullary_wrapper {
+  template < typename T, typename IndexType >
+  T packetOp(scalar_constant_op op, IndexType, IndexType) {
+    return op.packetOp< T >();
+  }
+};
+template < typename NullaryOp, typename PlainObjectType >
+struct evaluator< CwiseNullaryOp< NullaryOp, PlainObjectType > > {
+  evaluator(CwiseNullaryOp< NullaryOp, PlainObjectType >);
+  template < int, typename PacketType, typename IndexType >
+  PacketType packet(IndexType row, IndexType col) {
+    return m_wrapper.packetOp< PacketType >(m_functor, row, col);
+  }
+  NullaryOp m_functor;
+  nullary_wrapper m_wrapper;
+};
+template < typename BinaryOp, typename Lhs, typename Rhs >
+struct evaluator< CwiseBinaryOp< BinaryOp, Lhs, Rhs > >
+    : binary_evaluator< CwiseBinaryOp< BinaryOp, Lhs, Rhs > > {
+  evaluator(CwiseBinaryOp< BinaryOp, Lhs, Rhs > xpr)
+      : binary_evaluator< CwiseBinaryOp< BinaryOp, Lhs, Rhs > >(xpr) {}
+};
+template < typename BinaryOp, typename Lhs, typename Rhs >
+struct binary_evaluator< CwiseBinaryOp< BinaryOp, Lhs, Rhs > > {
+  binary_evaluator(CwiseBinaryOp< BinaryOp, Lhs, Rhs > xpr)
+      : m_lhsImpl(xpr.lhs()), m_rhsImpl(xpr.rhs()) {}
+  template < int, typename PacketType > PacketType packet(int, int) {
+    PacketType __trans_tmp_1 = m_lhsImpl.template packet< 0, PacketType >(0, 
0);
+    PacketType __trans_tmp_2;
+    m_functor.packetOp(__trans_tmp_1, __trans_tmp_2);
+  }
+  BinaryOp m_functor;
+  evaluator< Lhs > m_lhsImpl;
+  evaluator< Rhs > m_rhsImpl;
+};
+template < typename Derived > struct mapbase_evaluator {
+  typedef Derived XprType;
+  mapbase_evaluator(XprType map) : m_data(map.data()) {}
+  typename XprType::Scalar &coeffRef(int, int) { return m_data[0]; }
+  typename XprType::PointerType m_data;
+};
+template < int > struct block_evaluator;
+template < typename ArgType, int BlockRows, int BlockCols, bool InnerPanel >
+struct evaluator< Block< ArgType, BlockRows, BlockCols, InnerPanel > >
+    : block_evaluator< BlockCols > {
+  enum { Flags };
+  evaluator(Block< ArgType, 1, 1 > block) : block_evaluator< 1 >(block) {}
+};
+template < int BlockCols >
+struct block_evaluator
+    : mapbase_evaluator< Block< Matrix< double, 10, 1 >, 1, BlockCols > > {
+  typedef Block< Matrix< double, 10, 1 >, 1, BlockCols > XprType;
+  block_evaluator(XprType block) : mapbase_evaluator< XprType >(block) {}
+};
+template < typename DstEvaluator > struct copy_using_evaluator_traits {
+  typedef typename DstEvaluator::XprType Dst;
+  typedef typename Dst::Scalar DstScalar;
+  enum { DstFlags = DstEvaluator::Flags };
+  enum { InnerSize = DstFlags };
+  typedef typename conditional<
+      int() == LinearVectorizedTraversal,
+      typename find_best_packet< DstScalar, Dst::SizeAtCompileTime >::type,
+      typename find_best_packet< DstScalar, InnerSize >::type >::type
+      PacketType;
+};
+template < typename Kernel >
+struct copy_using_evaluator_innervec_CompleteUnrolling {
+  enum { outer, inner, SrcAlignment, DstAlignment };
+  static void run(Kernel kernel) {
+    kernel.template assignPacketByOuterInner< DstAlignment, SrcAlignment,
+                                              typename Kernel::PacketType >(
+        outer, inner);
+  }
+};
+template < typename Kernel > struct dense_assignment_loop {
+  static void run(Kernel kernel) {
+    copy_using_evaluator_innervec_CompleteUnrolling< Kernel >::run(kernel);
+  }
+};
+template < typename DstEvaluatorTypeT, typename SrcEvaluatorTypeT,
+           typename Functor >
+struct generic_dense_assignment_kernel {
+  typedef DstEvaluatorTypeT DstXprType;
+  typedef DstEvaluatorTypeT DstEvaluatorType;
+  typedef SrcEvaluatorTypeT SrcEvaluatorType;
+  typedef typename copy_using_evaluator_traits< DstEvaluatorTypeT >::PacketType
+      PacketType;
+  generic_dense_assignment_kernel(DstEvaluatorType dst, SrcEvaluatorType src,
+                                  Functor, DstXprType dstExpr)
+      : m_dst(dst), m_src(src), m_dstExpr(dstExpr) {}
+  template < int StoreMode, int LoadMode, typename >
+  void assignPacketByOuterInner(long, long) {
+    long row;
+    long col;
+    m_functor.template assignPacket< StoreMode >(
+        &m_dst.coeffRef(row, col),
+        m_src.template packet< LoadMode, PacketType >(row, col));
+  }
+  DstEvaluatorType &m_dst;
+  SrcEvaluatorType m_src;
+  Functor m_functor;
+  DstXprType m_dstExpr;
+};
+template < typename DstXprType, typename SrcXprType, typename Functor >
+void call_dense_assignment_loop(DstXprType dst, SrcXprType src, Functor func) {
+  typedef evaluator< DstXprType > DstEvaluatorType;
+  typedef evaluator< SrcXprType > SrcEvaluatorType;
+  SrcEvaluatorType srcEvaluator(src);
+  DstEvaluatorType dstEvaluator(dst);
+  typedef generic_dense_assignment_kernel< DstEvaluatorType, SrcEvaluatorType,
+                                           Functor >
+      Kernel;
+  Kernel kernel(dstEvaluator, srcEvaluator, func, dst);
+  dense_assignment_loop< Kernel >::run(kernel);
+}
+template < typename, typename, typename > struct Assignment;
+template < typename Dst, typename Src > void call_assignment(Dst dst, Src src) 
{
+  call_assignment(dst, src, assign_op());
+}
+template < typename Dst, typename Src, typename Func >
+void call_assignment(Dst dst, Src src, Func func) {
+  call_assignment_no_alias(dst, src, func);
+}
+template < typename Dst, typename Src, typename Func >
+void call_assignment_no_alias(Dst dst, Src src, Func func) {
+  enum { NeedToTranspose };
+  Assignment< typename conditional< NeedToTranspose, int, Dst >::type, Src,
+              Func >::run(dst, src, func);
+}
+template < typename DstXprType, typename SrcXprType, typename Functor >
+struct Assignment {
+  static void run(DstXprType dst, SrcXprType src, Functor func) {
+    call_dense_assignment_loop(dst, src, func);
+  }
+};
+template < typename Derived >
+template < typename OtherDerived >
+Derived &MatrixBase< Derived >::
+operator=(const DenseBase< OtherDerived > &other) {
+  call_assignment(derived(), other.derived());
+}
+template < int Size > struct plain_array { double array[Size]; };
+template < int Size > class DenseStorage {
+  plain_array< Size > m_data;
+
+public:
+  const double *data() const { return m_data.array; }
+  double *data() { return m_data.array; }
+};
+template < typename Derived >
+struct PlainObjectBase : dense_xpr_base< Derived >::type {
+  typedef typename dense_xpr_base< Derived >::type Base;
+  typedef typename traits< Derived >::Scalar Scalar;
+  DenseStorage< Base::MaxSizeAtCompileTime > m_storage;
+  const Scalar *data() const { return m_storage.data(); }
+  Scalar *data() { return m_storage.data(); }
+  PlainObjectBase() {}
+  template < typename OtherDerived > PlainObjectBase(OtherDerived other) {
+    call_assignment_no_alias(this->derived(), other, assign_op());
+  }
+};
+template < typename _Scalar, int _Rows, int _Cols, int _Options, int _MaxRows,
+           int _MaxCols >
+struct traits< Matrix< _Scalar, _Rows, _Cols, _Options, _MaxRows, _MaxCols > > 
{
+  typedef _Scalar Scalar;
+  enum { Flags = compute_matrix_flags::ret };
+};
+template < typename, int _Rows, int _Cols, int, int, int >
+struct Matrix : PlainObjectBase< Matrix< double, _Rows, _Cols > > {
+  PlainObjectBase< Matrix > Base;
+  Matrix() {}
+  template < typename OtherDerived > Matrix(OtherDerived other) : Base(other) 
{}
+};
+template < typename, typename, typename > struct CwiseBinaryOp {
+  typedef ref_selector::type LhsNested;
+  CwiseBinaryOp(Matrix< double, 10, 1 > &aLhs, Matrix< double, 0, 0 >)
+      : m_lhs(aLhs) {}
+  LhsNested lhs() { return m_lhs; }
+  Matrix< double, 8, 1 > rhs() {}
+  LhsNested m_lhs;
+};
+template < typename NullaryOp, typename >
+struct CwiseNullaryOp
+    : dense_xpr_base< CwiseNullaryOp< NullaryOp, int > >::type {};
+template < typename Derived > Derived &DenseBase< Derived >::setConstant() {
+  derived() = Constant();
+}
+template < typename Derived >
+struct MapBase< Derived, ReadOnlyAccessors > : dense_xpr_base< Derived >::type 
{
+  typedef typename dense_xpr_base< Derived >::type Base;
+  typedef typename traits< Derived >::Scalar Scalar;
+  typedef typename conditional< is_lvalue< Derived >::value, Scalar *,
+                                Scalar >::type PointerType;
+  Scalar *data() { return m_data; }
+  MapBase(PointerType dataPtr, long, long) : m_data(dataPtr) {}
+  PointerType m_data;
+};
+template < typename Derived >
+struct MapBase< Derived > : MapBase< Derived, ReadOnlyAccessors > {
+  typedef MapBase< Derived, ReadOnlyAccessors > Base;
+  MapBase(typename Base::PointerType dataPtr, long rows, long cols)
+      : Base(dataPtr, rows, cols) {}
+  using MapBase< Derived, ReadOnlyAccessors >::Base::operator=;
+};
+template < typename XprType, int BlockRows, int BlockCols, bool InnerPanel >
+struct traits< Block< XprType, BlockRows, BlockCols, InnerPanel > >
+    : traits< XprType > {};
+template < int, int > struct BlockImpl_dense;
+template < typename, int, int, typename > class BlockImpl;
+template < typename, int BlockRows, int BlockCols, bool >
+struct Block : BlockImpl< Matrix< double, 10, 1 >, BlockRows, BlockCols, int > 
{
+  typedef BlockImpl< Matrix< double, 10, 1 >, BlockRows, BlockCols, int > Impl;
+  using Impl::operator=;
+  Block(Matrix< double, 10, 1 > &xpr, long startRow, long startCol,
+        long blockRows, long blockCols)
+      : Impl(xpr, startRow, startCol, blockRows, blockCols) {}
+};
+template < typename XprType, int BlockRows, int BlockCols >
+struct BlockImpl< XprType, BlockRows, BlockCols, int >
+    : BlockImpl_dense< BlockRows, BlockCols > {
+  typedef BlockImpl_dense< BlockRows, BlockCols > Impl;
+  typedef Impl Base;
+  using Base::operator=;
+  BlockImpl(XprType &xpr, long startRow, long startCol, long blockRows,
+            long blockCols)
+      : Impl(xpr, startRow, startCol, blockRows, blockCols) {}
+};
+template < int BlockRows, int BlockCols >
+struct BlockImpl_dense
+    : MapBase< Block< Matrix< double, 10, 1 >, BlockRows, BlockCols > > {
+  typedef MapBase< Block< Matrix< double, 10, 1 >, BlockRows, BlockCols > >
+      Base;
+  using Base::operator=;
+  BlockImpl_dense(Matrix< double, 10, 1 > &xpr, long, long, long blockRows,
+                  long blockCols)
+      : Base(xpr.data(), blockRows, blockCols) {}
+};
+struct VectorBlock : Block< int, traits< Matrix< double, 0, 1 > >::Flags, 1 > {
+  VectorBlock(Matrix< double, 10, 1 > &vector, long start, long size)
+      : Block(vector, 0, start, 1, size) {}
+};
+namespace std {
+template < typename _Alloc > struct _Vector_base {
+  typedef typename allocator_traits< _Alloc >::pointer pointer;
+};
+template < typename _Tp, typename _Alloc = allocator< _Tp > > class vector {
+public:
+  typedef __normal_iterator< typename _Vector_base< _Alloc >::pointer, int >
+      iterator;
+  iterator begin();
+  iterator end();
+};
+struct FrameHessian {
+  Matrix< double, 0, 1 > step;
+  void setState(Matrix< double, 0, 1 >);
+};
+struct FullSystem {
+  bool doStepFromBackup();
+  vector< FrameHessian * > frameHessians;
+};
+bool FullSystem::doStepFromBackup() {
+  Matrix< double, 10, 1 > pstepfac;
+  pstepfac.segment< 4 >().setConstant();
+  for (FrameHessian *fh : frameHessians)
+    fh->setState(pstepfac.cwiseProduct(fh->step));
+}
+} // namespace std

Reply via email to