re PR tree-optimization/91280 (ICE in get_constraint_for_component_ref, at tree-ssa...
authorRichard Biener <rguenther@suse.de>
Wed, 31 Jul 2019 14:38:21 +0000 (14:38 +0000)
committerRichard Biener <rguenth@gcc.gnu.org>
Wed, 31 Jul 2019 14:38:21 +0000 (14:38 +0000)
2019-07-31  Richard Biener  <rguenther@suse.de>

PR tree-optimization/91280
* tree-ssa-structalias.c (get_constraint_for_component_ref):
Decompose MEM_REF manually for offset handling.

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

From-SVN: r273936

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

index ef8ee9f..18f2ce2 100644 (file)
@@ -1,5 +1,11 @@
 2019-07-31  Richard Biener  <rguenther@suse.de>
 
+       PR tree-optimization/91280
+       * tree-ssa-structalias.c (get_constraint_for_component_ref):
+       Decompose MEM_REF manually for offset handling.
+
+2019-07-31  Richard Biener  <rguenther@suse.de>
+
        PR tree-optimization/91293
        * tree-vect-slp.c (vect_build_slp_tree_2): Do not swap operands
        of reduction stmts.
index 6cffdc2..f490292 100644 (file)
@@ -1,5 +1,10 @@
 2019-07-31  Richard Biener  <rguenther@suse.de>
 
+       PR tree-optimization/91280
+       * g++.dg/torture/pr91280.C: New testcase.
+
+2019-07-31  Richard Biener  <rguenther@suse.de>
+
        PR tree-optimization/91293
        * gcc.dg/vect/pr91293-1.c: New testcase.
        * gcc.dg/vect/pr91293-2.c: Likewise.
diff --git a/gcc/testsuite/g++.dg/torture/pr91280.C b/gcc/testsuite/g++.dg/torture/pr91280.C
new file mode 100644 (file)
index 0000000..063bef8
--- /dev/null
@@ -0,0 +1,223 @@
+// { dg-do compile }
+
+enum { Aligned, RowMajor };
+enum { ReadOnlyAccessors };
+template <typename> struct K {
+  enum { value };
+};
+template <typename> struct traits;
+template <typename T> struct traits<const T> : traits<T> {};
+struct A {
+  enum { has_write_access, value };
+};
+template <typename, int n> class array {
+public:
+  int operator[](unsigned long p1) { return values[p1]; }
+  int values[n];
+};
+template <typename> struct I;
+template <typename, int, template <class> class = I> class M;
+template <typename, int, int, typename> class J;
+template <typename, int> class N;
+template <typename, typename> class D;
+template <typename, typename, typename, typename> class TensorContractionOp;
+template <long, typename> class TensorChippingOp;
+class C;
+template <typename DenseIndex, int NumDims>
+struct K<array<DenseIndex, NumDims>> {
+  static const long value = NumDims;
+};
+template <typename Scalar_, int NumIndices_, int Options_, typename IndexType_>
+struct traits<J<Scalar_, NumIndices_, Options_, IndexType_>> {
+  typedef IndexType_ Index;
+};
+template <typename PlainObjectType, int Options_,
+          template <class> class MakePointer_>
+struct traits<M<PlainObjectType, Options_, MakePointer_>>
+    : traits<PlainObjectType> {};
+template <typename T> struct B { typedef T type; };
+template <typename Derived> class N<Derived, ReadOnlyAccessors> {
+public:
+  typedef typename traits<Derived>::Index Index;
+  D<int, Derived> m_fn1();
+  template <typename OtherDerived, typename Dimensions>
+  TensorContractionOp<Dimensions, Derived, const OtherDerived, int>
+      m_fn2(OtherDerived, Dimensions);
+  template <Index> TensorChippingOp<1, Derived> m_fn3(Index);
+};
+template <typename Derived, int = A::value>
+class N : public N<Derived, ReadOnlyAccessors> {
+public:
+  template <typename DeviceType> C m_fn4(DeviceType);
+};
+template <typename, typename> struct TensorEvaluator;
+template <typename UnaryOp, typename ArgType, typename Device>
+struct TensorEvaluator<const D<UnaryOp, ArgType>, Device> {
+  TensorEvaluator(D<UnaryOp, ArgType>, Device);
+};
+template <typename, typename> class D {
+public:
+  typedef typename B<D>::type Nested;
+};
+template <typename Indices_, typename LeftArgType_, typename RightArgType_,
+          typename OutputKernelType_, typename Device_>
+struct traits<
+    TensorEvaluator<const TensorContractionOp<Indices_, LeftArgType_,
+                                              RightArgType_, OutputKernelType_>,
+                    Device_>> {
+  typedef Indices_ Indices;
+  typedef LeftArgType_ LeftArgType;
+  typedef RightArgType_ RightArgType;
+  typedef OutputKernelType_ OutputKernelType;
+  typedef Device_ Device;
+};
+template <typename, typename LhsXprType, typename RhsXprType, typename>
+class TensorContractionOp {
+public:
+  typedef typename B<TensorContractionOp>::type Nested;
+  typename LhsXprType::Nested m_fn5();
+  typename RhsXprType::Nested m_fn6();
+};
+template <typename Derived> struct TensorContractionEvaluatorBase {
+  typedef typename traits<Derived>::LeftArgType LeftArgType;
+  typedef typename traits<Derived>::RightArgType RightArgType;
+  typedef typename traits<Derived>::Device Device;
+  TensorContractionEvaluatorBase(
+      TensorContractionOp<typename traits<Derived>::Indices, LeftArgType,
+                          RightArgType,
+                          typename traits<Derived>::OutputKernelType>
+          p1,
+      Device p2)
+      : m_leftImpl(p1.m_fn6(), p2), m_rightImpl(p1.m_fn5(), p2) {
+    long nocontract_idx;
+    for (int i;; i++) {
+      bool contracting;
+      if (contracting) {
+        if (nocontract_idx < K<int>::value)
+          m_j_size = m_j_strides[nocontract_idx];
+        nocontract_idx++;
+      }
+    }
+  }
+  array<long, 1> m_j_strides;
+  long m_j_size;
+  TensorEvaluator<RightArgType, Device> m_leftImpl;
+  TensorEvaluator<LeftArgType, Device> m_rightImpl;
+};
+template <typename Indices, typename LeftArgType, typename RightArgType,
+          typename OutputKernelType, typename Device>
+struct TensorEvaluator<
+    const TensorContractionOp<Indices, LeftArgType, RightArgType,
+                              OutputKernelType>,
+    Device>
+    : TensorContractionEvaluatorBase<TensorEvaluator<
+          const TensorContractionOp<Indices, LeftArgType, RightArgType,
+                                    OutputKernelType>,
+          Device>> {
+  typedef TensorEvaluator Self;
+  typedef TensorContractionEvaluatorBase<Self> Base;
+  TensorEvaluator(
+      TensorContractionOp<Indices, LeftArgType, RightArgType, OutputKernelType>
+          p1,
+      Device p2)
+      : Base(p1, p2) {}
+};
+template <long DimId, typename XprType>
+struct traits<TensorChippingOp<DimId, XprType>> : traits<XprType> {};
+template <long, typename XprType>
+class TensorChippingOp : public N<TensorChippingOp<1, XprType>> {
+public:
+  typedef typename B<TensorChippingOp>::type Nested;
+};
+template <long DimId, typename ArgType, typename Device>
+struct TensorEvaluator<const TensorChippingOp<DimId, ArgType>, Device> {
+  static const int NumInputDims = K<typename ArgType::Dimensions>::value;
+  array<long, NumInputDims> m_dimensions;
+};
+template <long DimId, typename ArgType, typename Device>
+struct TensorEvaluator<TensorChippingOp<DimId, ArgType>, Device>
+    : TensorEvaluator<const TensorChippingOp<1, ArgType>, Device> {
+  TensorEvaluator(TensorChippingOp<DimId, ArgType>, Device);
+};
+template <typename, typename RhsXprType> class TensorAssignOp {
+public:
+  TensorAssignOp(TensorChippingOp<0, const M<J<int, 3, 1, int>, 1>>,
+                 RhsXprType);
+  TensorChippingOp<0, const M<J<int, 3, 1, int>, 1>> m_fn7();
+  typename RhsXprType::Nested m_fn8();
+};
+template <typename LeftArgType, typename RightArgType, typename Device>
+struct TensorEvaluator<const TensorAssignOp<LeftArgType, RightArgType>,
+                       Device> {
+  TensorEvaluator(TensorAssignOp<LeftArgType, RightArgType> p1, Device p2)
+      : m_leftImpl(p1.m_fn7(), p2), m_rightImpl(p1.m_fn8(), p2) {}
+  TensorEvaluator<LeftArgType, Device> m_leftImpl;
+  TensorEvaluator<RightArgType, Device> m_rightImpl;
+};
+template <typename Expression> class F {
+public:
+  static void m_fn9(Expression p1) {
+    int device;
+    TensorEvaluator<Expression, int>(p1, device);
+  }
+};
+class C {
+public:
+  void
+  operator=(TensorContractionOp<array<int, 1>,
+                                TensorChippingOp<1, M<J<float, 3, 1, int>, 0>>,
+                                const D<int, M<J<float, 3, 1, int>, 0>>, int>
+                p1) {
+    TensorAssignOp<
+        TensorChippingOp<0, const M<J<int, 3, 1, int>, 1>>,
+        const TensorContractionOp<
+            array<int, 1>, TensorChippingOp<1, M<J<float, 3, 1, int>, 0>>,
+            const D<int, M<J<float, 3, 1, int>, 0>>, int>>
+        assign(m_expression, p1);
+    F<const TensorAssignOp<
+        TensorChippingOp<0, const M<J<int, 3, 1, int>, 1>>,
+        const TensorContractionOp<
+            array<int, 1>, TensorChippingOp<1, M<J<float, 3, 1, int>, 0>>,
+            const D<int, M<J<float, 3, 1, int>, 0>>, int>>>::m_fn9(assign);
+  }
+  TensorChippingOp<0, const M<J<int, 3, 1, int>, 1>> m_expression;
+};
+template <typename, int NumIndices_, int, typename> class J {
+public:
+  typedef array<long, NumIndices_> Dimensions;
+};
+template <typename PlainObjectType, int Options_, template <class> class>
+class M : public N<M<PlainObjectType, Options_>> {
+public:
+  typedef typename PlainObjectType::Dimensions Dimensions;
+};
+template <int NDIMS> struct TTypes {
+  typedef M<J<float, NDIMS, RowMajor, int>, Aligned> ConstTensor;
+};
+class L {
+public:
+  template <typename, long NDIMS> typename TTypes<NDIMS>::ConstTensor m_fn10();
+};
+class H {
+public:
+  H(int *);
+};
+class G {
+public:
+  G(H *(int *));
+};
+int Run_d;
+class O : H {
+public:
+  int BatchMatMul_context;
+  O() : H(&BatchMatMul_context) {
+    L out, in_y, in_x;
+    auto Tx = in_x.m_fn10<float, 3>(), Ty = in_y.m_fn10<float, 3>(),
+         Tz = out.m_fn10<float, 3>(), z = Tz;
+    array<int, 1> contract_pairs;
+    auto x = Tx.m_fn3<0>(0);
+    auto y = Ty.m_fn1();
+    z.m_fn4(Run_d) = x.m_fn2(y, contract_pairs);
+  }
+};
+G registrar__body__0__object([](int *) -> H * { O(); return 0; });
index 974b639..75c6fae 100644 (file)
@@ -3289,9 +3289,29 @@ get_constraint_for_component_ref (tree t, vec<ce_s> *results,
       return;
     }
 
-  /* Pretend to take the address of the base, we'll take care of
-     adding the required subset of sub-fields below.  */
-  get_constraint_for_1 (t, results, true, lhs_p);
+  /* Avoid creating pointer-offset constraints, so handle MEM_REF
+     offsets directly.  Pretend to take the address of the base,
+     we'll take care of adding the required subset of sub-fields below.  */
+  if (TREE_CODE (t) == MEM_REF
+      && !integer_zerop (TREE_OPERAND (t, 0)))
+    {
+      poly_offset_int off = mem_ref_offset (t);
+      off <<= LOG2_BITS_PER_UNIT;
+      off += bitpos;
+      poly_int64 off_hwi;
+      if (off.to_shwi (&off_hwi))
+       bitpos = off_hwi;
+      else
+       {
+         bitpos = 0;
+         bitmaxsize = -1;
+       }
+      get_constraint_for_1 (TREE_OPERAND (t, 0), results, false, lhs_p);
+      do_deref (results);
+    }
+  else
+    get_constraint_for_1 (t, results, true, lhs_p);
+
   /* Strip off nothing_id.  */
   if (results->length () == 2)
     {