From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 46989 invoked by alias); 18 Jan 2019 19:22:56 -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 46974 invoked by uid 89); 18 Jan 2019 19:22:54 -0000 Authentication-Results: sourceware.org; auth=none X-Spam-SWARE-Status: No, score=-11.1 required=5.0 tests=BAYES_00,FREEMAIL_FROM,GIT_PATCH_2,GIT_PATCH_3,KAM_ASCII_DIVIDERS,RCVD_IN_DNSWL_NONE,SPF_PASS autolearn=ham version=3.3.2 spammy=HX-Received:8484 X-HELO: mail-wr1-f66.google.com Received: from mail-wr1-f66.google.com (HELO mail-wr1-f66.google.com) (209.85.221.66) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Fri, 18 Jan 2019 19:22:50 +0000 Received: by mail-wr1-f66.google.com with SMTP id t27so16413706wra.6 for ; Fri, 18 Jan 2019 11:22:50 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=date:user-agent:in-reply-to:references:mime-version :content-transfer-encoding:subject:to:from:message-id; bh=mLe0aXfWQoZpPOOZ0LeNLitWg0AIE6kvVRX+cFEjo/Q=; b=W70P14P5OyjKVO8z4CLg2r1CeAyVOKG/cEDNBva52Z45geHoavwafQ3kHSVvpr9XDc 7PYlhFg9KnhHU8jcSzbiuUc2R4YPehpYN1fyTebM6rvvizVly4OETOi722U2FXOwVNzn qoXjIFavKdSbYr4hCTOoXCTCye2Ot5xG/6tbW8S/UXJ0t1LlhJLIIZd4H24do0Rzm5P1 +58YjPF9uquBg9Hw7D9K3xpzh+lFg+9f6vptZxCzphrAzJ8Pj2PiTugZ89NLhbNElnTA SU06pyZh5rHWaRq+nFFPOVHYvRNG7StgYBJYdZZU4GAL5CVfko8GoAB5Q+hZ2lkCda+l cKLw== Return-Path: Received: from [192.168.178.32] (x4d04409c.dyn.telefonica.de. [77.4.64.156]) by smtp.gmail.com with ESMTPSA id f191sm1532033wmg.12.2019.01.18.11.22.47 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Fri, 18 Jan 2019 11:22:47 -0800 (PST) Date: Fri, 18 Jan 2019 19:22:00 -0000 User-Agent: K-9 Mail for Android In-Reply-To: <87o98drkf9.fsf@arm.com> References: <87o98drkf9.fsf@arm.com> MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: quoted-printable Subject: Re: Claw back some of the code size regression in 548.exchange2_r To: gcc-patches@gcc.gnu.org,Richard Sandiford From: Richard Biener Message-ID: X-IsSubscribed: yes X-SW-Source: 2019-01/txt/msg01096.txt.bz2 On January 18, 2019 5:37:46 PM GMT+01:00, Richard Sandiford wrote: >This patch tries harder to detect cases in which the inner dimension >of an array access is invariant, such as: > > x(i, :) =3D 100 > >It fixes some of the code size regression in 548.exchange2_r, with >size improving by 5% compared to before the patch. Of the two other >SPEC 2017 tests affected by loop versioning, 554.roms_r improved by a >trivial amount (0.3%) and 549.fotonik3d_r didn't change. All three >results are with -Ofast -flto. > >Tested on aarch64-linux-gnu, aarch64_be-elf and x86_64-linux-gnu. >OK to install? OK.=20 Richard.=20 >Richard > > >2019-01-18 Richard Sandiford > >gcc/ > * gimple-loop-versioning.cc (loop_versioning::dump_inner_likelihood): > New function, split out from... > (loop_versioning::analyze_stride): ...here. > (loop_versioning::find_per_loop_multiplication): Use gassign. > (loop_versioning::analyze_term_using_scevs): Return a success code. > (loop_versioning::analyze_arbitrary_term): New function. > (loop_versioning::analyze_address_fragment): Use > analyze_arbitrary_term if all else fails. > >gcc/testsuite/ > * gfortran.dg/loop_versioning_1.f90: Bump the number of identified > inner strides. > * gfortran.dg/loop_versioning_9.f90: New test. > * gfortran.dg/loop_versioning_10.f90: Likewise. > >Index: gcc/gimple-loop-versioning.cc >=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D >--- gcc/gimple-loop-versioning.cc 2019-01-04 11:39:25.918257505 +0000 >+++ gcc/gimple-loop-versioning.cc 2019-01-18 16:36:13.172064883 +0000 >@@ -294,10 +294,12 @@ private: > bool acceptable_type_p (tree, unsigned HOST_WIDE_INT *); > bool multiply_term_by (address_term_info &, tree); > inner_likelihood get_inner_likelihood (tree, unsigned HOST_WIDE_INT); >+ void dump_inner_likelihood (address_info &, address_term_info &); > void analyze_stride (address_info &, address_term_info &, > tree, struct loop *); >bool find_per_loop_multiplication (address_info &, address_term_info >&); >- void analyze_term_using_scevs (address_info &, address_term_info &); >+ bool analyze_term_using_scevs (address_info &, address_term_info &); >+ void analyze_arbitrary_term (address_info &, address_term_info &); > void analyze_address_fragment (address_info &); > void record_address_fragment (gimple *, unsigned HOST_WIDE_INT, > tree, unsigned HOST_WIDE_INT, HOST_WIDE_INT); >@@ -803,6 +805,24 @@ loop_versioning::get_inner_likelihood (t > return unlikely_p ? INNER_UNLIKELY : INNER_DONT_KNOW; > } >=20 >+/* Dump the likelihood that TERM's stride is for the innermost >dimension. >+ ADDRESS is the address that contains TERM. */ >+ >+void >+loop_versioning::dump_inner_likelihood (address_info &address, >+ address_term_info &term) >+{ >+ if (term.inner_likelihood =3D=3D INNER_LIKELY) >+ dump_printf_loc (MSG_NOTE, address.stmt, "%T is likely to be the" >+ " innermost dimension\n", term.stride); >+ else if (term.inner_likelihood =3D=3D INNER_UNLIKELY) >+ dump_printf_loc (MSG_NOTE, address.stmt, "%T is probably not the" >+ " innermost dimension\n", term.stride); >+ else >+ dump_printf_loc (MSG_NOTE, address.stmt, "cannot tell whether %T" >+ " is the innermost dimension\n", term.stride); >+} >+ > /* The caller has identified that STRIDE is the stride of interest > in TERM, and that the stride is applied in OP_LOOP. Record this > information in TERM, deciding whether STRIDE is likely to be for >@@ -818,17 +838,7 @@ loop_versioning::analyze_stride (address >=20 >term.inner_likelihood =3D get_inner_likelihood (stride, term.multiplier); > if (dump_enabled_p ()) >- { >- if (term.inner_likelihood =3D=3D INNER_LIKELY) >- dump_printf_loc (MSG_NOTE, address.stmt, "%T is likely to be the" >- " innermost dimension\n", stride); >- else if (term.inner_likelihood =3D=3D INNER_UNLIKELY) >- dump_printf_loc (MSG_NOTE, address.stmt, "%T is probably not the" >- " innermost dimension\n", stride); >- else >- dump_printf_loc (MSG_NOTE, address.stmt, "cannot tell whether %T" >- " is the innermost dimension\n", stride); >- } >+ dump_inner_likelihood (address, term); >=20 > /* To be a versioning opportunity we require: >=20 >@@ -879,7 +889,7 @@ bool > loop_versioning::find_per_loop_multiplication (address_info &address, > address_term_info &term) > { >- gimple *mult =3D maybe_get_assign (term.expr); >+ gassign *mult =3D maybe_get_assign (term.expr); > if (!mult || gimple_assign_rhs_code (mult) !=3D MULT_EXPR) > return false; >=20 >@@ -909,7 +919,7 @@ loop_versioning::find_per_loop_multiplic > } >=20 > /* Try to use scalar evolutions to find an address stride for TERM, >- which belongs to ADDRESS. >+ which belongs to ADDRESS. Return true and update TERM if so. >=20 > Here we are interested in any evolution information we can find, > not just evolutions wrt ADDRESS->LOOP. For example, if we find that >@@ -917,17 +927,17 @@ loop_versioning::find_per_loop_multiplic >that information can help us eliminate worthless versioning >opportunities > in inner loops. */ >=20 >-void >+bool > loop_versioning::analyze_term_using_scevs (address_info &address, > address_term_info &term) > { > gimple *setter =3D maybe_get_stmt (term.expr); > if (!setter) >- return; >+ return false; >=20 > struct loop *wrt_loop =3D loop_containing_stmt (setter); > if (!loop_outer (wrt_loop)) >- return; >+ return false; >=20 >tree chrec =3D strip_casts (analyze_scalar_evolution (wrt_loop, >term.expr)); > if (TREE_CODE (chrec) =3D=3D POLYNOMIAL_CHREC) >@@ -955,7 +965,53 @@ loop_versioning::analyze_term_using_scev > } >=20 > analyze_stride (address, term, stride, get_chrec_loop (chrec)); >+ return true; >+ } >+ >+ return false; >+} >+ >+/* Address term TERM is an arbitrary term that provides no versioning >+ opportunities. Analyze it to see whether it contains any likely >+ inner strides, so that we don't mistakenly version for other >+ (less likely) candidates. >+ >+ This copes with invariant innermost indices such as: >+ >+ x(i, :) =3D 100 >+ >+ where the "i" component of the address is invariant in the loop >+ but provides the real inner stride. >+ >+ ADDRESS is the address that contains TERM. */ >+ >+void >+loop_versioning::analyze_arbitrary_term (address_info &address, >+ address_term_info &term) >+ >+{ >+ /* A multiplication offers two potential strides. Pick the one that >+ is most likely to be an innermost stride. */ >+ tree expr =3D term.expr, alt =3D NULL_TREE; >+ gassign *mult =3D maybe_get_assign (expr); >+ if (mult && gimple_assign_rhs_code (mult) =3D=3D MULT_EXPR) >+ { >+ expr =3D strip_casts (gimple_assign_rhs1 (mult)); >+ alt =3D strip_casts (gimple_assign_rhs2 (mult)); >+ } >+ term.stride =3D expr; >+ term.inner_likelihood =3D get_inner_likelihood (expr, >term.multiplier); >+ if (alt) >+ { >+ inner_likelihood alt_l =3D get_inner_likelihood (alt, >term.multiplier); >+ if (alt_l > term.inner_likelihood) >+ { >+ term.stride =3D alt; >+ term.inner_likelihood =3D alt_l; >+ } > } >+ if (dump_enabled_p ()) >+ dump_inner_likelihood (address, term); > } >=20 > /* Try to identify loop strides in ADDRESS and try to choose realistic >@@ -1038,8 +1094,10 @@ loop_versioning::analyze_address_fragmen > find_per_loop_multiplication and analyze_term_using_scevs can handle, >but the former is much cheaper than SCEV analysis, so try it first. */ > for (unsigned int i =3D 0; i < address.terms.length (); ++i) >- if (!find_per_loop_multiplication (address, address.terms[i])) >- analyze_term_using_scevs (address, address.terms[i]); >+ if (!find_per_loop_multiplication (address, address.terms[i]) >+ && !analyze_term_using_scevs (address, address.terms[i]) >+ && !POINTER_TYPE_P (TREE_TYPE (address.terms[i].expr))) >+ analyze_arbitrary_term (address, address.terms[i]); >=20 >/* Check for strides that are likely to be for the innermost dimension. >=20 >Index: gcc/testsuite/gfortran.dg/loop_versioning_1.f90 >=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D >--- gcc/testsuite/gfortran.dg/loop_versioning_1.f90 2018-12-17 >10:05:18.091771024 +0000 >+++ gcc/testsuite/gfortran.dg/loop_versioning_1.f90 2019-01-18 >16:36:13.172064883 +0000 >@@ -23,6 +23,6 @@ subroutine f3(x, limit, step) > end do > end subroutine f3 >=20 >-! { dg-final { scan-tree-dump-times {likely to be the innermost >dimension} 1 "lversion" } } >+! { dg-final { scan-tree-dump-times {likely to be the innermost >dimension} 2 "lversion" } } >! { dg-final { scan-tree-dump-times {want to version containing loop} 3 >"lversion" } } >! { dg-final { scan-tree-dump-times {versioned this loop} 3 "lversion" >} } >Index: gcc/testsuite/gfortran.dg/loop_versioning_9.f90 >=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D >--- /dev/null 2018-12-31 11:20:29.178325188 +0000 >+++ gcc/testsuite/gfortran.dg/loop_versioning_9.f90 2019-01-18 >16:36:13.172064883 +0000 >@@ -0,0 +1,31 @@ >+! { dg-options "-O3 -fdump-tree-lversion-details" } >+ >+subroutine f1(x) >+ real :: x(:, :) >+ x(1, :) =3D 100 >+end subroutine f1 >+ >+subroutine f2(x, i) >+ real :: x(:, :) >+ integer :: i >+ x(i, :) =3D 100 >+end subroutine f2 >+ >+subroutine f3(x) >+ real :: x(:, :) >+ do j =3D lbound(x, 2), ubound(x, 2) >+ x(1, j) =3D 100 >+ end do >+end subroutine f3 >+ >+subroutine f4(x, i) >+ real :: x(:, :) >+ integer :: i >+ do j =3D lbound(x, 2), ubound(x, 2) >+ x(i, j) =3D 100 >+ end do >+end subroutine f4 >+ >+! { dg-final { scan-tree-dump-times {likely to be the innermost >dimension} 4 "lversion" } } >+! { dg-final { scan-tree-dump-not {want to version} "lversion" } } >+! { dg-final { scan-tree-dump-not {versioned} "lversion" } } >Index: gcc/testsuite/gfortran.dg/loop_versioning_10.f90 >=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D >--- /dev/null 2018-12-31 11:20:29.178325188 +0000 >+++ gcc/testsuite/gfortran.dg/loop_versioning_10.f90 2019-01-18 >16:36:13.172064883 +0000 >@@ -0,0 +1,31 @@ >+! { dg-options "-O3 -fdump-tree-lversion-details" } >+ >+subroutine f1(x) >+ real :: x(:, :) >+ x(:, 1) =3D 100 >+end subroutine f1 >+ >+subroutine f2(x, i) >+ real :: x(:, :) >+ integer :: i >+ x(:, i) =3D 100 >+end subroutine f2 >+ >+subroutine f3(x) >+ real :: x(:, :) >+ do j =3D lbound(x, 1), ubound(x, 1) >+ x(j, 1) =3D 100 >+ end do >+end subroutine f3 >+ >+subroutine f4(x, i) >+ real :: x(:, :) >+ integer :: i >+ do j =3D lbound(x, 1), ubound(x, 1) >+ x(j, i) =3D 100 >+ end do >+end subroutine f4 >+ >+! { dg-final { scan-tree-dump-times {likely to be the innermost >dimension} 6 "lversion" } } >+! { dg-final { scan-tree-dump-times {want to version} 4 "lversion" } } >+! { dg-final { scan-tree-dump-times {versioned} 4 "lversion" } }