From patchwork Thu Jun 23 14:43:43 2011 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Andrew Stubbs X-Patchwork-Id: 2230 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 10ECE23F6D for ; Thu, 23 Jun 2011 14:43:50 +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 BA84DA18178 for ; Thu, 23 Jun 2011 14:43:49 +0000 (UTC) Received: by qwb8 with SMTP id 8so1408179qwb.11 for ; Thu, 23 Jun 2011 07:43:49 -0700 (PDT) Received: by 10.229.30.3 with SMTP id s3mr468038qcc.21.1308840229284; Thu, 23 Jun 2011 07:43:49 -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.230.139 with SMTP id jm11cs19981qcb; Thu, 23 Jun 2011 07:43:49 -0700 (PDT) Received: by 10.216.220.220 with SMTP id o70mr1720837wep.71.1308840228451; Thu, 23 Jun 2011 07:43:48 -0700 (PDT) Received: from mail-wy0-f178.google.com (mail-wy0-f178.google.com [74.125.82.178]) by mx.google.com with ESMTPS id s68si4009853weq.8.2011.06.23.07.43.47 (version=TLSv1/SSLv3 cipher=OTHER); Thu, 23 Jun 2011 07:43:47 -0700 (PDT) Received-SPF: neutral (google.com: 74.125.82.178 is neither permitted nor denied by best guess record for domain of andrew.stubbs@linaro.org) client-ip=74.125.82.178; Authentication-Results: mx.google.com; spf=neutral (google.com: 74.125.82.178 is neither permitted nor denied by best guess record for domain of andrew.stubbs@linaro.org) smtp.mail=andrew.stubbs@linaro.org Received: by wya21 with SMTP id 21so1623327wya.37 for ; Thu, 23 Jun 2011 07:43:47 -0700 (PDT) Received: by 10.227.11.143 with SMTP id t15mr2062036wbt.56.1308840226973; Thu, 23 Jun 2011 07:43:46 -0700 (PDT) Received: from [192.168.0.100] (cpc2-hawk4-0-0-cust828.aztw.cable.virginmedia.com [82.32.123.61]) by mx.google.com with ESMTPS id ge4sm1285790wbb.30.2011.06.23.07.43.45 (version=SSLv3 cipher=OTHER); Thu, 23 Jun 2011 07:43:46 -0700 (PDT) Message-ID: <4E03511F.9040507@codesourcery.com> Date: Thu, 23 Jun 2011 15:43:43 +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: [PATCH (7/7)] Mixed-sign multiplies using narrowest mode References: <4E034EF2.3070503@codesourcery.com> In-Reply-To: <4E034EF2.3070503@codesourcery.com> 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? Andrew 2011-06-23 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/smlalbb-3.c: New file. --- /dev/null +++ b/gcc/testsuite/gcc.target/arm/smlalbb-3.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, @@ -2244,14 +2252,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))