From patchwork Tue Jun 28 16:23:11 2011 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Andrew Stubbs X-Patchwork-Id: 2362 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 1B3B523F08 for ; Tue, 28 Jun 2011 16:23:20 +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 C2EB6A185AB for ; Tue, 28 Jun 2011 16:23:19 +0000 (UTC) Received: by qwb8 with SMTP id 8so268220qwb.11 for ; Tue, 28 Jun 2011 09:23:19 -0700 (PDT) Received: by 10.229.1.140 with SMTP id 12mr5845060qcf.118.1309278199027; Tue, 28 Jun 2011 09:23:19 -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.48.135 with SMTP id r7cs13034qcf; Tue, 28 Jun 2011 09:23:18 -0700 (PDT) Received: by 10.231.211.72 with SMTP id gn8mr3035653ibb.24.1309278197841; Tue, 28 Jun 2011 09:23:17 -0700 (PDT) Received: from mail.codesourcery.com (mail.codesourcery.com [38.113.113.100]) by mx.google.com with ESMTPS id f13si574875ibc.83.2011.06.28.09.23.17 (version=TLSv1/SSLv3 cipher=OTHER); Tue, 28 Jun 2011 09:23:17 -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 7516 invoked from network); 28 Jun 2011 16:23:15 -0000 Received: from unknown (HELO ?192.168.0.100?) (ams@127.0.0.2) by mail.codesourcery.com with ESMTPA; 28 Jun 2011 16:23:15 -0000 Message-ID: <4E09FFEF.6010603@codesourcery.com> Date: Tue, 28 Jun 2011 17:23:11 +0100 From: Andrew Stubbs Organization: CodeSourcery User-Agent: Mozilla/5.0 (X11; U; Linux x86_64; en-US; rv:1.9.2.17) Gecko/20110516 Lightning/1.0b2 Thunderbird/3.1.10 MIME-Version: 1.0 To: gcc-patches@gcc.gnu.org CC: patches@linaro.org Subject: Re: [PATCH (7/7)] Mixed-sign multiplies using narrowest mode References: <4E034EF2.3070503@codesourcery.com> <4E03511F.9040507@codesourcery.com> In-Reply-To: <4E03511F.9040507@codesourcery.com> 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. 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. --- /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" } } */ --- a/gcc/tree-ssa-math-opts.c +++ b/gcc/tree-ssa-math-opts.c @@ -2103,9 +2103,17 @@ 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_UNSIGNED (type2) + && TYPE_MODE (type2) == 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, @@ -2227,14 +2235,21 @@ convert_plusminus_to_widen (gimple_stmt_iterator *gsi, gimple stmt, if (TYPE_UNSIGNED (type1) != TYPE_UNSIGNED (type2)) { enum machine_mode mode = TYPE_MODE (type1); - mode = GET_MODE_WIDER_MODE (mode); - if (GET_MODE_SIZE (mode) < GET_MODE_SIZE (TYPE_MODE (type))) + + /* 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_UNSIGNED (type2) + && TYPE_MODE (type2) == mode)) { - type1 = type2 = lang_hooks.types.type_for_mode (mode, 0); - cast1 = cast2 = true; + mode = GET_MODE_WIDER_MODE (mode); + if (GET_MODE_SIZE (mode) >= GET_MODE_SIZE (TYPE_MODE (type))) + return false; } - else - return false; + + type1 = type2 = lang_hooks.types.type_for_mode (mode, 0); + cast1 = cast2 = true; } if (TYPE_MODE (type2) != TYPE_MODE (type1))