From patchwork Thu Jul 14 14:38:32 2011 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Andrew Stubbs X-Patchwork-Id: 2697 Return-Path: X-Original-To: patchwork@peony.canonical.com Delivered-To: patchwork@peony.canonical.com Received: from fiordland.canonical.com (fiordland.canonical.com [91.189.94.145]) by peony.canonical.com (Postfix) with ESMTP id 67FBB24259 for ; Thu, 14 Jul 2011 14:38:39 +0000 (UTC) Received: from mail-qw0-f52.google.com (mail-qw0-f52.google.com [209.85.216.52]) by fiordland.canonical.com (Postfix) with ESMTP id 1C1C8A18105 for ; Thu, 14 Jul 2011 14:38:39 +0000 (UTC) Received: by qwb8 with SMTP id 8so207993qwb.11 for ; Thu, 14 Jul 2011 07:38:38 -0700 (PDT) Received: by 10.229.217.3 with SMTP id hk3mr1956513qcb.38.1310654318542; Thu, 14 Jul 2011 07:38:38 -0700 (PDT) X-Forwarded-To: linaro-patchwork@canonical.com X-Forwarded-For: patch@linaro.org linaro-patchwork@canonical.com Delivered-To: patches@linaro.org Received: by 10.229.217.78 with SMTP id hl14cs17270qcb; Thu, 14 Jul 2011 07:38:38 -0700 (PDT) Received: by 10.236.145.226 with SMTP id p62mr3450810yhj.290.1310654317213; Thu, 14 Jul 2011 07:38:37 -0700 (PDT) Received: from mail.codesourcery.com (mail.codesourcery.com [38.113.113.100]) by mx.google.com with ESMTPS id r61si1217707yhm.79.2011.07.14.07.38.36 (version=TLSv1/SSLv3 cipher=OTHER); Thu, 14 Jul 2011 07:38:37 -0700 (PDT) Received-SPF: pass (google.com: domain of ams@codesourcery.com designates 38.113.113.100 as permitted sender) client-ip=38.113.113.100; Authentication-Results: mx.google.com; spf=pass (google.com: domain of ams@codesourcery.com designates 38.113.113.100 as permitted sender) smtp.mail=ams@codesourcery.com Received: (qmail 11498 invoked from network); 14 Jul 2011 14:38:35 -0000 Received: from unknown (HELO ?192.168.0.100?) (ams@127.0.0.2) by mail.codesourcery.com with ESMTPA; 14 Jul 2011 14:38:35 -0000 Message-ID: <4E1EFF68.10201@codesourcery.com> Date: Thu, 14 Jul 2011 15:38:32 +0100 From: Andrew Stubbs Organization: CodeSourcery User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:5.0) Gecko/20110627 Thunderbird/5.0 MIME-Version: 1.0 CC: gcc-patches@gcc.gnu.org, patches@linaro.org Subject: Re: [PATCH (7/7)] Mixed-sign multiplies using narrowest mode References: <4E034EF2.3070503@codesourcery.com> <4E03511F.9040507@codesourcery.com> <4E09FFEF.6010603@codesourcery.com> In-Reply-To: <4E09FFEF.6010603@codesourcery.com> On 28/06/11 17:23, Andrew Stubbs wrote: > On 23/06/11 15:43, Andrew Stubbs wrote: >> Patch 4 introduced support for using signed multiplies to code unsigned >> multiplies in a narrower mode. Patch 5 then introduced support for >> mis-matched input modes. >> >> These two combined mean that there is case where only the smaller of two >> inputs is unsigned, and yet it still tries to user a mode wider than the >> larger, signed input. This is bad because it means unnecessary extends >> and because the wider operation might not exist. >> >> This patch catches that case, and ensures that the smaller, unsigned >> input, is zero-extended to match the mode of the larger, signed input. >> >> Of course, both inputs may still have to be extended to fit the nearest >> available instruction, so it doesn't make a difference every time. >> >> OK? > > This update fixes Janis' issue with the testsuite. And this version is updated to fit the changes made earlier in the series, and also to use the precision, instead of the mode-size, in order to better optimize bitfields. OK? Andrew 2011-06-24 Andrew Stubbs gcc/ * tree-ssa-math-opts.c (convert_mult_to_widen): Better handle unsigned inputs of different modes. (convert_plusminus_to_widen): Likewise. gcc/testsuite/ * gcc.target/arm/wmul-9.c: New file. * gcc.target/arm/wmul-bitfield-2.c: New file. --- /dev/null +++ b/gcc/testsuite/gcc.target/arm/wmul-9.c @@ -0,0 +1,10 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -march=armv7-a" } */ + +long long +foo (long long a, short *b, char *c) +{ + return a + *b * *c; +} + +/* { dg-final { scan-assembler "smlalbb" } } */ --- /dev/null +++ b/gcc/testsuite/gcc.target/arm/wmul-bitfield-2.c @@ -0,0 +1,17 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -march=armv7-a" } */ + +struct bf +{ + int a : 3; + unsigned int b : 15; + int c : 3; +}; + +long long +foo (long long a, struct bf b, struct bf c) +{ + return a + b.b * c.c; +} + +/* { dg-final { scan-assembler "smlalbb" } } */ --- a/gcc/tree-ssa-math-opts.c +++ b/gcc/tree-ssa-math-opts.c @@ -2121,9 +2121,18 @@ convert_mult_to_widen (gimple stmt, gimple_stmt_iterator *gsi) { if (op != smul_widen_optab) { - from_mode = GET_MODE_WIDER_MODE (from_mode); - if (GET_MODE_SIZE (to_mode) <= GET_MODE_SIZE (from_mode)) - return false; + /* We can use a signed multiply with unsigned types as long as + there is a wider mode to use, or it is the smaller of the two + types that is unsigned. Note that type1 >= type2, always. */ + if ((TYPE_UNSIGNED (type1) + && TYPE_PRECISION (type1) == GET_MODE_PRECISION (from_mode)) + || (TYPE_UNSIGNED (type2) + && TYPE_PRECISION (type2) == GET_MODE_PRECISION (from_mode))) + { + from_mode = GET_MODE_WIDER_MODE (from_mode); + if (GET_MODE_SIZE (to_mode) <= GET_MODE_SIZE (from_mode)) + return false; + } op = smul_widen_optab; handler = find_widening_optab_handler_and_mode (op, to_mode, @@ -2290,14 +2299,20 @@ convert_plusminus_to_widen (gimple_stmt_iterator *gsi, gimple stmt, /* There's no such thing as a mixed sign madd yet, so use a wider mode. */ if (from_unsigned1 != from_unsigned2) { - enum machine_mode mode = GET_MODE_WIDER_MODE (from_mode); - if (GET_MODE_PRECISION (mode) < GET_MODE_PRECISION (to_mode)) + /* We can use a signed multiply with unsigned types as long as + there is a wider mode to use, or it is the smaller of the two + types that is unsigned. Note that type1 >= type2, always. */ + if ((from_unsigned1 + && TYPE_PRECISION (type1) == GET_MODE_PRECISION (from_mode)) + || (from_unsigned2 + && TYPE_PRECISION (type2) == GET_MODE_PRECISION (from_mode))) { - from_mode = mode; - from_unsigned1 = from_unsigned2 = false; + from_mode = GET_MODE_WIDER_MODE (from_mode); + if (GET_MODE_SIZE (from_mode) >= GET_MODE_SIZE (to_mode)) + return false; } - else - return false; + + from_unsigned1 = from_unsigned2 = false; } /* If there was a conversion between the multiply and addition