From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 103635 invoked by alias); 31 Jul 2019 13:17:17 -0000 Mailing-List: contact gcc-patches-help@gcc.gnu.org; run by ezmlm Precedence: bulk List-Id: List-Archive: List-Post: List-Help: Sender: gcc-patches-owner@gcc.gnu.org Received: (qmail 103627 invoked by uid 89); 31 Jul 2019 13:17:17 -0000 Authentication-Results: sourceware.org; auth=none X-Spam-SWARE-Status: No, score=-10.2 required=5.0 tests=AWL,BAYES_00,GIT_PATCH_2,GIT_PATCH_3,KAM_ASCII_DIVIDERS,KAM_NUMSUBJECT,SPF_PASS autolearn=ham version=3.3.1 spammy=integer_zerop, traits, !integer_zerop, Dimensions X-HELO: mx1.suse.de Received: from mx2.suse.de (HELO mx1.suse.de) (195.135.220.15) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Wed, 31 Jul 2019 13:17:14 +0000 Received: from relay2.suse.de (unknown [195.135.220.254]) by mx1.suse.de (Postfix) with ESMTP id 5EA89AE21 for ; Wed, 31 Jul 2019 13:17:12 +0000 (UTC) Date: Wed, 31 Jul 2019 13:33:00 -0000 From: Richard Biener To: gcc-patches@gcc.gnu.org Subject: [PATCH] Fix PR91280 Message-ID: User-Agent: Alpine 2.20 (LSU 67 2015-01-07) MIME-Version: 1.0 Content-Type: text/plain; charset=US-ASCII X-SW-Source: 2019-07/txt/msg01880.txt.bz2 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 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 struct K { + enum { value }; +}; +template struct traits; +template struct traits : traits {}; +struct A { + enum { has_write_access, value }; +}; +template class array { +public: + int operator[](unsigned long p1) { return values[p1]; } + int values[n]; +}; +template struct I; +template class = I> class M; +template class J; +template class N; +template class D; +template class TensorContractionOp; +template class TensorChippingOp; +class C; +template +struct K> { + static const long value = NumDims; +}; +template +struct traits> { + typedef IndexType_ Index; +}; +template class MakePointer_> +struct traits> + : traits {}; +template struct B { typedef T type; }; +template class N { +public: + typedef typename traits::Index Index; + D m_fn1(); + template + TensorContractionOp + m_fn2(OtherDerived, Dimensions); + template TensorChippingOp<1, Derived> m_fn3(Index); +}; +template +class N : public N { +public: + template C m_fn4(DeviceType); +}; +template struct TensorEvaluator; +template +struct TensorEvaluator, Device> { + TensorEvaluator(D, Device); +}; +template class D { +public: + typedef typename B::type Nested; +}; +template +struct traits< + TensorEvaluator, + Device_>> { + typedef Indices_ Indices; + typedef LeftArgType_ LeftArgType; + typedef RightArgType_ RightArgType; + typedef OutputKernelType_ OutputKernelType; + typedef Device_ Device; +}; +template +class TensorContractionOp { +public: + typedef typename B::type Nested; + typename LhsXprType::Nested m_fn5(); + typename RhsXprType::Nested m_fn6(); +}; +template struct TensorContractionEvaluatorBase { + typedef typename traits::LeftArgType LeftArgType; + typedef typename traits::RightArgType RightArgType; + typedef typename traits::Device Device; + TensorContractionEvaluatorBase( + TensorContractionOp::Indices, LeftArgType, + RightArgType, + typename traits::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::value) + m_j_size = m_j_strides[nocontract_idx]; + nocontract_idx++; + } + } + } + array m_j_strides; + long m_j_size; + TensorEvaluator m_leftImpl; + TensorEvaluator m_rightImpl; +}; +template +struct TensorEvaluator< + const TensorContractionOp, + Device> + : TensorContractionEvaluatorBase, + Device>> { + typedef TensorEvaluator Self; + typedef TensorContractionEvaluatorBase Base; + TensorEvaluator( + TensorContractionOp + p1, + Device p2) + : Base(p1, p2) {} +}; +template +struct traits> : traits {}; +template +class TensorChippingOp : public N> { +public: + typedef typename B::type Nested; +}; +template +struct TensorEvaluator, Device> { + static const int NumInputDims = K::value; + array m_dimensions; +}; +template +struct TensorEvaluator, Device> + : TensorEvaluator, Device> { + TensorEvaluator(TensorChippingOp, Device); +}; +template class TensorAssignOp { +public: + TensorAssignOp(TensorChippingOp<0, const M, 1>>, + RhsXprType); + TensorChippingOp<0, const M, 1>> m_fn7(); + typename RhsXprType::Nested m_fn8(); +}; +template +struct TensorEvaluator, + Device> { + TensorEvaluator(TensorAssignOp p1, Device p2) + : m_leftImpl(p1.m_fn7(), p2), m_rightImpl(p1.m_fn8(), p2) {} + TensorEvaluator m_leftImpl; + TensorEvaluator m_rightImpl; +}; +template class F { +public: + static void m_fn9(Expression p1) { + int device; + TensorEvaluator(p1, device); + } +}; +class C { +public: + void + operator=(TensorContractionOp, + TensorChippingOp<1, M, 0>>, + const D, 0>>, int> + p1) { + TensorAssignOp< + TensorChippingOp<0, const M, 1>>, + const TensorContractionOp< + array, TensorChippingOp<1, M, 0>>, + const D, 0>>, int>> + assign(m_expression, p1); + F, 1>>, + const TensorContractionOp< + array, TensorChippingOp<1, M, 0>>, + const D, 0>>, int>>>::m_fn9(assign); + } + TensorChippingOp<0, const M, 1>> m_expression; +}; +template class J { +public: + typedef array Dimensions; +}; +template class> +class M : public N> { +public: + typedef typename PlainObjectType::Dimensions Dimensions; +}; +template struct TTypes { + typedef M, Aligned> ConstTensor; +}; +class L { +public: + template typename TTypes::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(), Ty = in_y.m_fn10(), + Tz = out.m_fn10(), z = Tz; + array 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; });