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: 102419 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 DFD9CB6F69 for ; Wed, 29 Jun 2011 02:23:35 +1000 (EST) Received: (qmail 2415 invoked by alias); 28 Jun 2011 16:23:31 -0000 Received: (qmail 2405 invoked by uid 22791); 28 Jun 2011 16:23:30 -0000 X-SWARE-Spam-Status: No, hits=-1.6 required=5.0 tests=AWL, BAYES_00, TW_TM, 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; Tue, 28 Jun 2011 16:23:15 +0000 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 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> 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 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))