public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
* [PATCH] Fix PR91280
@ 2019-07-31 13:33 Richard Biener
  0 siblings, 0 replies; only message in thread
From: Richard Biener @ 2019-07-31 13:33 UTC (permalink / raw)
  To: gcc-patches


There's some longer latent issue with PTAs handling of
offsetted MEM_REFs in get_constraint_for_component_ref when there
are subfields involved.  The following solves this by handling
offsetted MEM_REFs manually.

Bootstrap & regtest running on x86_64-unknown-linux-gnu.

Richard.

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.

Index: gcc/tree-ssa-structalias.c
===================================================================
--- gcc/tree-ssa-structalias.c	(revision 273930)
+++ gcc/tree-ssa-structalias.c	(working copy)
@@ -3289,9 +3289,29 @@ get_constraint_for_component_ref (tree t
       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)
     {
Index: gcc/testsuite/g++.dg/torture/pr91280.C
===================================================================
--- gcc/testsuite/g++.dg/torture/pr91280.C	(nonexistent)
+++ gcc/testsuite/g++.dg/torture/pr91280.C	(working copy)
@@ -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; });

^ permalink raw reply	[flat|nested] only message in thread

only message in thread, other threads:[~2019-07-31 13:17 UTC | newest]

Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2019-07-31 13:33 [PATCH] Fix PR91280 Richard Biener

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).