From patchwork Wed May 25 12:35:51 2011 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Andrew Stubbs X-Patchwork-Id: 97340 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from sourceware.org (server1.sourceware.org [209.132.180.131]) by ozlabs.org (Postfix) with SMTP id 2AB7FB6F7C for ; Wed, 25 May 2011 22:36:15 +1000 (EST) Received: (qmail 18250 invoked by alias); 25 May 2011 12:36:13 -0000 Received: (qmail 17978 invoked by uid 22791); 25 May 2011 12:36:12 -0000 X-SWARE-Spam-Status: No, hits=-1.7 required=5.0 tests=AWL, BAYES_00, T_RP_MATCHES_RCVD X-Spam-Check-By: sourceware.org Received: from mail.codesourcery.com (HELO mail.codesourcery.com) (38.113.113.100) by sourceware.org (qpsmtpd/0.43rc1) with ESMTP; Wed, 25 May 2011 12:35:57 +0000 Received: (qmail 1475 invoked from network); 25 May 2011 12:35:55 -0000 Received: from unknown (HELO ?192.168.0.100?) (ams@127.0.0.2) by mail.codesourcery.com with ESMTPA; 25 May 2011 12:35:55 -0000 Message-ID: <4DDCF7A7.4000200@codesourcery.com> Date: Wed, 25 May 2011 13:35:51 +0100 From: Andrew Stubbs User-Agent: Mozilla/5.0 (X11; U; Linux x86_64; en-US; rv:1.9.2.17) Gecko/20110424 Lightning/1.0b2 Thunderbird/3.1.10 MIME-Version: 1.0 To: "Joseph S. Myers" CC: Bernd Schmidt , Richard Earnshaw , gcc-patches@gcc.gnu.org Subject: Re: [patch][simplify-rtx] Fix 16-bit -> 64-bit multiply and accumulate References: <4D01018F.3020108@codesourcery.com> <1296153619.9738.16.camel@e102346-lin.cambridge.arm.com> <4D42955C.1060707@codesourcery.com> <1296223929.9738.30.camel@e102346-lin.cambridge.arm.com> <4D42DD32.7020404@codesourcery.com> <1296228038.9738.48.camel@e102346-lin.cambridge.arm.com> <4D8CC0A9.5080504@codesourcery.com> <4DA823F1.2040907@codesourcery.com> <4DBFC5D8.1090009@codesourcery.com> <4DDBE035.8050901@codesourcery.com> In-Reply-To: Mailing-List: contact gcc-patches-help@gcc.gnu.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Archive: List-Post: List-Help: Sender: gcc-patches-owner@gcc.gnu.org Delivered-To: mailing list gcc-patches@gcc.gnu.org On 24/05/11 20:35, Joseph S. Myers wrote: > On Tue, 24 May 2011, Andrew Stubbs wrote: > >> I've created this new, simpler patch that converts >> >> (extend (mult a b)) >> >> into >> >> (mult (extend a) (extend b)) >> >> regardless of what 'a' and 'b' might be. (These are then simplified and >> superfluous extends removed, of course.) > > Are there some missing conditions here? The two aren't equivalent in > general - (extend:SI (mult:HI a b)) multiplies the HImode values in HImode > (with modulo arithmetic on overflow) before extending the possibly wrapped > result to SImode. Ok, I've now modified my patch to prevent it widening regular multiplies. It now converts (extend (mult (extend a) (extend b))) to (mult (newextend a) (newextend b)) But I also have it convert (extend (mult (shift a) (extend b))) to (mult (newextend (shift a)) (newextend b)) The latter case is to catch widening multiplies that extract a subreg using a shift. I don't understand why it doesn't just use subreg in the first place, but apparently it doesn't, and changing it to do that would no doubt break many existing machine descriptions. The latter case also happens to catch cases where an extend is represented by (ashiftrt (ashift x)), which is nice. I know that, potentially, not all shifted operands are going to be widening multiplies, but I *think* this should be safe because other random shift values are unlikely to match a real widening mult instruction (and if they do then the code would already be broken). If somebody knows a reason why this isn't safe then I think I'm going to need some help figuring out what conditions to use. OK? Andrew 2011-05-25 Bernd Schmidt Andrew Stubbs gcc/ * simplify-rtx.c (simplify_unary_operation_1): Canonicalize widening multiplies. * doc/md.texi (Canonicalization of Instructions): Document widening multiply canonicalization. gcc/testsuite/ * gcc.target/arm/mla-2.c: New test. --- a/gcc/doc/md.texi +++ b/gcc/doc/md.texi @@ -5840,6 +5840,21 @@ Equality comparisons of a group of bits (usually a single bit) with zero will be written using @code{zero_extract} rather than the equivalent @code{and} or @code{sign_extract} operations. +@cindex @code{mult}, canonicalization of +@item +@code{(sign_extend:@var{m1} (mult:@var{m2} (sign_extend:@var{m2} @var{x}) +(sign_extend:@var{m2} @var{y})))} is converted to @code{(mult:@var{m1} +(sign_extend:@var{m1} @var{x}) (sign_extend:@var{m1} @var{y}))}, and likewise +for @code{zero_extend}. + +@item +@code{(sign_extend:@var{m1} (mult:@var{m2} (ashiftrt:@var{m2} +@var{x} @var{s}) (sign_extend:@var{m2} @var{y})))} is converted to +@code{(mult:@var{m1} (sign_extend:@var{m1} (ashiftrt:@var{m2} @var{x} @var{s})) +(sign_extend:@var{m1} @var{y}))}, and likewise for patterns using @code{zero_extend} +and @code{lshiftrt}. If the second operand of @code{mult} is also a shift, +then that is extended also. + @end itemize Further canonicalization rules are defined in the function --- a/gcc/simplify-rtx.c +++ b/gcc/simplify-rtx.c @@ -1000,6 +1000,34 @@ simplify_unary_operation_1 (enum rtx_code code, enum machine_mode mode, rtx op) && GET_CODE (XEXP (XEXP (op, 0), 1)) == LABEL_REF) return XEXP (op, 0); + /* Extending a widening multiplication should be canonicalized to + a wider widening multiplication. */ + if (GET_CODE (op) == MULT) + { + rtx lhs = XEXP (op, 0); + rtx rhs = XEXP (op, 1); + enum rtx_code lcode = GET_CODE (lhs); + enum rtx_code rcode = GET_CODE (rhs); + + /* Widening multiplies usually extend both operands, but sometimes + they use a shift to extract a portion of a register. We assume + it is safe to widen all such operands because other examples + won't match real instructions. */ + if ((lcode == SIGN_EXTEND || lcode == ASHIFTRT) + && (rcode == SIGN_EXTEND || rcode == ASHIFTRT)) + { + enum machine_mode lmode = GET_MODE (lhs); + enum machine_mode rmode = GET_MODE (lhs); + return simplify_gen_binary (MULT, mode, + simplify_gen_unary (SIGN_EXTEND, + mode, + lhs, lmode), + simplify_gen_unary (SIGN_EXTEND, + mode, + rhs, rmode)); + } + } + /* Check for a sign extension of a subreg of a promoted variable, where the promotion is sign-extended, and the target mode is the same as the variable's promotion. */ @@ -1071,6 +1099,34 @@ simplify_unary_operation_1 (enum rtx_code code, enum machine_mode mode, rtx op) && GET_MODE_SIZE (mode) <= GET_MODE_SIZE (GET_MODE (XEXP (op, 0)))) return rtl_hooks.gen_lowpart_no_emit (mode, op); + /* Extending a widening multiplication should be canonicalized to + a wider widening multiplication. */ + if (GET_CODE (op) == MULT) + { + rtx lhs = XEXP (op, 0); + rtx rhs = XEXP (op, 1); + enum rtx_code lcode = GET_CODE (lhs); + enum rtx_code rcode = GET_CODE (rhs); + + /* Widening multiplies usually extend both operands, but sometimes + they use a shift to extract a portion of a register. We assume + it is safe to widen all such operands because other examples + won't match real instructions. */ + if ((lcode == ZERO_EXTEND || lcode == LSHIFTRT) + && (rcode == ZERO_EXTEND || rcode == LSHIFTRT)) + { + enum machine_mode lmode = GET_MODE (lhs); + enum machine_mode rmode = GET_MODE (lhs); + return simplify_gen_binary (MULT, mode, + simplify_gen_unary (ZERO_EXTEND, + mode, + lhs, lmode), + simplify_gen_unary (ZERO_EXTEND, + mode, + rhs, rmode)); + } + } + /* (zero_extend:M (zero_extend:N )) is (zero_extend:M ). */ if (GET_CODE (op) == ZERO_EXTEND) return simplify_gen_unary (ZERO_EXTEND, mode, XEXP (op, 0), --- /dev/null +++ b/gcc/testsuite/gcc.target/arm/mla-2.c @@ -0,0 +1,9 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -march=armv7-a" } */ + +long long foolong (long long x, short *a, short *b) +{ + return x + *a * *b; +} + +/* { dg-final { scan-assembler "smlalbb" } } */