From patchwork Tue Jul 12 14:07:05 2011 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Andrew Stubbs X-Patchwork-Id: 2672 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 EFCA223F42 for ; Tue, 12 Jul 2011 14:07:15 +0000 (UTC) Received: from mail-qy0-f173.google.com (mail-qy0-f173.google.com [209.85.216.173]) by fiordland.canonical.com (Postfix) with ESMTP id A239FA18A04 for ; Tue, 12 Jul 2011 14:07:15 +0000 (UTC) Received: by qyk10 with SMTP id 10so2378477qyk.11 for ; Tue, 12 Jul 2011 07:07:15 -0700 (PDT) Received: by 10.229.25.212 with SMTP id a20mr4709231qcc.148.1310479635081; Tue, 12 Jul 2011 07:07:15 -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 hl14cs244328qcb; Tue, 12 Jul 2011 07:07:14 -0700 (PDT) Received: by 10.101.189.38 with SMTP id r38mr4946823anp.119.1310479633202; Tue, 12 Jul 2011 07:07:13 -0700 (PDT) Received: from mail.codesourcery.com (mail.codesourcery.com [38.113.113.100]) by mx.google.com with ESMTPS id s14si12833399ank.77.2011.07.12.07.07.11 (version=TLSv1/SSLv3 cipher=OTHER); Tue, 12 Jul 2011 07:07:12 -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 6326 invoked from network); 12 Jul 2011 14:07:09 -0000 Received: from unknown (HELO ?192.168.0.100?) (ams@127.0.0.2) by mail.codesourcery.com with ESMTPA; 12 Jul 2011 14:07:09 -0000 Message-ID: <4E1C5509.6030505@codesourcery.com> Date: Tue, 12 Jul 2011 15:07:05 +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 (4/7)] Unsigned multiplies using wider signed multiplies References: <4E034EF2.3070503@codesourcery.com> <4E035084.2010503@codesourcery.com> <4E09CA21.3030605@codesourcery.com> <4E09E1B1.2090005@codesourcery.com> <4E11CDAF.3040308@codesourcery.com> In-Reply-To: <4E11CDAF.3040308@codesourcery.com> On 04/07/11 15:26, Andrew Stubbs wrote: > On 28/06/11 15:14, Andrew Stubbs wrote: >> On 28/06/11 13:33, Andrew Stubbs wrote: >>> On 23/06/11 15:41, Andrew Stubbs wrote: >>>> If one or both of the inputs to a widening multiply are of unsigned >>>> type >>>> then the compiler will attempt to use usmul_widen_optab or >>>> umul_widen_optab, respectively. >>>> >>>> That works fine, but only if the target supports those operations >>>> directly. Otherwise, it just bombs out and reverts to the normal >>>> inefficient non-widening multiply. >>>> >>>> This patch attempts to catch these cases and use an alternative signed >>>> widening multiply instruction, if one of those is available. >>>> >>>> I believe this should be legal as long as the top bit of both inputs is >>>> guaranteed to be zero. The code achieves this guarantee by >>>> zero-extending the inputs to a wider mode (which must still be narrower >>>> than the output mode). >>>> >>>> OK? >>> >>> This update fixes the testsuite issue Janis pointed out. >> >> And this one fixes up the wmul-5.c testcase also. The patch has changed >> the correct result. > > Here's an update for the context changed by the update to patch 3. > > The content of the patch has not changed. This update does the same thing as before, but updated for the changes earlier in the patch series. In particular, the build_and_insert_cast function and find_widening_optab_handler_and_mode changes have been moved up to patch 2. OK? Andrew 2011-07-12 Andrew Stubbs gcc/ * tree-ssa-math-opts.c (convert_mult_to_widen): Convert unsupported unsigned multiplies to signed. (convert_plusminus_to_widen): Likewise. gcc/testsuite/ * gcc.target/arm/wmul-6.c: New file. --- /dev/null +++ b/gcc/testsuite/gcc.target/arm/wmul-6.c @@ -0,0 +1,10 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -march=armv7-a" } */ + +long long +foo (long long a, unsigned char *b, signed char *c) +{ + return a + (long long)*b * (long long)*c; +} + +/* { dg-final { scan-assembler "smlal" } } */ --- a/gcc/tree-ssa-math-opts.c +++ b/gcc/tree-ssa-math-opts.c @@ -2071,6 +2071,7 @@ convert_mult_to_widen (gimple stmt, gimple_stmt_iterator *gsi) enum insn_code handler; enum machine_mode to_mode, from_mode; optab op; + bool do_cast = false; lhs = gimple_assign_lhs (stmt); type = TREE_TYPE (lhs); @@ -2094,9 +2095,32 @@ convert_mult_to_widen (gimple stmt, gimple_stmt_iterator *gsi) 0, &from_mode); if (handler == CODE_FOR_nothing) - return false; + { + 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; + + op = smul_widen_optab; + handler = find_widening_optab_handler_and_mode (op, to_mode, + from_mode, 0, + &from_mode); - if (from_mode != TYPE_MODE (type1)) + if (handler == CODE_FOR_nothing) + return false; + + type1 = build_nonstandard_integer_type ( + GET_MODE_PRECISION (from_mode), + 0); + type2 = type1; + do_cast = true; + } + else + return false; + } + + if (from_mode != TYPE_MODE (type1) || do_cast) { location_t loc = gimple_location (stmt); tree tmp1, tmp2; @@ -2143,6 +2167,7 @@ convert_plusminus_to_widen (gimple_stmt_iterator *gsi, gimple stmt, enum tree_code wmult_code; enum insn_code handler; enum machine_mode from_mode; + bool do_cast = false; lhs = gimple_assign_lhs (stmt); type = TREE_TYPE (lhs); @@ -2234,8 +2259,21 @@ convert_plusminus_to_widen (gimple_stmt_iterator *gsi, gimple stmt, else return false; + /* We don't support usmadd yet, so try a wider signed mode. */ if (TYPE_UNSIGNED (type1) != TYPE_UNSIGNED (type2)) - return false; + { + enum machine_mode mode = TYPE_MODE (type1); + mode = GET_MODE_WIDER_MODE (mode); + if (GET_MODE_SIZE (mode) < GET_MODE_SIZE (TYPE_MODE (type))) + { + type1 = build_nonstandard_integer_type (GET_MODE_PRECISION (mode), + 0); + type2 = type1; + do_cast = true; + } + else + return false; + } /* If there was a conversion between the multiply and addition then we need to make sure it fits a multiply-and-accumulate. @@ -2276,7 +2314,7 @@ convert_plusminus_to_widen (gimple_stmt_iterator *gsi, gimple stmt, if (handler == CODE_FOR_nothing) return false; - if (TYPE_MODE (type1) != from_mode) + if (TYPE_MODE (type1) != from_mode || do_cast) { location_t loc = gimple_location (stmt); tree tmp;