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: 104375 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 4C5A7B6F54 for ; Wed, 13 Jul 2011 00:07:27 +1000 (EST) Received: (qmail 17010 invoked by alias); 12 Jul 2011 14:07:25 -0000 Received: (qmail 17002 invoked by uid 22791); 12 Jul 2011 14:07:23 -0000 X-SWARE-Spam-Status: No, hits=-1.1 required=5.0 tests=AWL, BAYES_00, MISSING_HEADERS, 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, 12 Jul 2011 14:07:10 +0000 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 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> 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 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;