From patchwork Thu Jul 21 12:53:28 2011 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Andrew Stubbs X-Patchwork-Id: 3018 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 C9EEF23DE6 for ; Thu, 21 Jul 2011 12:53:36 +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 7596EA18326 for ; Thu, 21 Jul 2011 12:53:36 +0000 (UTC) Received: by qyk10 with SMTP id 10so3969331qyk.11 for ; Thu, 21 Jul 2011 05:53:36 -0700 (PDT) Received: by 10.229.25.212 with SMTP id a20mr183339qcc.148.1311252815934; Thu, 21 Jul 2011 05:53:35 -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 hl14cs139755qcb; Thu, 21 Jul 2011 05:53:35 -0700 (PDT) Received: by 10.236.173.131 with SMTP id v3mr331073yhl.423.1311252814947; Thu, 21 Jul 2011 05:53:34 -0700 (PDT) Received: from mail.codesourcery.com (mail.codesourcery.com [38.113.113.100]) by mx.google.com with ESMTPS id i4si1565132ibe.72.2011.07.21.05.53.34 (version=TLSv1/SSLv3 cipher=OTHER); Thu, 21 Jul 2011 05:53:34 -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 3960 invoked from network); 21 Jul 2011 12:53:31 -0000 Received: from unknown (HELO ?192.168.0.104?) (ams@127.0.0.2) by mail.codesourcery.com with ESMTPA; 21 Jul 2011 12:53:31 -0000 Message-ID: <4E282148.9080100@codesourcery.com> Date: Thu, 21 Jul 2011 13:53:28 +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 To: gcc-patches@gcc.gnu.org CC: patches@linaro.org Subject: [PATCH (9/7)] Widening multiplies with constant inputs References: <4E034EF2.3070503@codesourcery.com> In-Reply-To: <4E034EF2.3070503@codesourcery.com> This patch is part bug fix, part better optimization. Firstly, my initial patch series introduced a bug that caused an internal compiler error when the input to a multiply was a constant. This was caused by the gimple verification rejecting such things. I'm not totally clear how this ever worked, but I've corrected it by inserting a temporary SSA_NAME between the constant and the multiply. I also discovered that widening multiply-and-accumulate operations were not recognised if any one of the three inputs were a constant. I've corrected this by adjusting the pattern matching. This also required inserting new SSA_NAMEs to make it work. In order to insert the new SSA_NAME, I've simply reused the existing type conversion code - the only difference is that the conversion may be a no-op, so it just generates a straight forward assignment. OK? Andrew 2011-07-21 Andrew Stubbs gcc/ * tree-ssa-math-opts.c (is_widening_mult_rhs_p): Handle constants beyond conversions. (convert_mult_to_widen): Create SSA_NAME for constant inputs. (convert_plusminus_to_widen): Don't automatically reject inputs that are not an SSA_NAME. Create SSA_NAME for constant inputs. gcc/testsuite/ * gcc.target/arm/wmul-11.c: New file. * gcc.target/arm/wmul-12.c: New file. * gcc.target/arm/wmul-13.c: New file. --- /dev/null +++ b/gcc/testsuite/gcc.target/arm/wmul-11.c @@ -0,0 +1,11 @@ +/* { dg-do compile } */ +/* { dg-options "-O2" } */ +/* { dg-require-effective-target arm_dsp } */ + +long long +foo (int *b) +{ + return 10 * (long long)*b; +} + +/* { dg-final { scan-assembler "smull" } } */ --- /dev/null +++ b/gcc/testsuite/gcc.target/arm/wmul-12.c @@ -0,0 +1,12 @@ +/* { dg-do compile } */ +/* { dg-options "-O2" } */ +/* { dg-require-effective-target arm_dsp } */ + +long long +foo (int *b, int *c) +{ + int tmp = *b * *c; + return 10 + (long long)tmp; +} + +/* { dg-final { scan-assembler "smlal" } } */ --- /dev/null +++ b/gcc/testsuite/gcc.target/arm/wmul-13.c @@ -0,0 +1,11 @@ +/* { dg-do compile } */ +/* { dg-options "-O2" } */ +/* { dg-require-effective-target arm_dsp } */ + +long long +foo (int *a, int *b) +{ + return *a + (long long)*b * 10; +} + +/* { dg-final { scan-assembler "smlal" } } */ --- a/gcc/tree-ssa-math-opts.c +++ b/gcc/tree-ssa-math-opts.c @@ -1997,6 +1997,13 @@ is_widening_mult_rhs_p (tree type, tree rhs, tree *type_out, type1 = TREE_TYPE (rhs1); } + if (TREE_CODE (rhs1) == INTEGER_CST) + { + *new_rhs_out = rhs1; + *type_out = NULL; + return true; + } + if (TREE_CODE (type1) != TREE_CODE (type) || TYPE_PRECISION (type1) * 2 > TYPE_PRECISION (type)) return false; @@ -2152,7 +2159,8 @@ convert_mult_to_widen (gimple stmt, gimple_stmt_iterator *gsi) for the opcode. This will be the full mode size. */ actual_precision = GET_MODE_PRECISION (actual_mode); if (actual_precision != TYPE_PRECISION (type1) - || from_unsigned1 != TYPE_UNSIGNED (type1)) + || from_unsigned1 != TYPE_UNSIGNED (type1) + || TREE_CODE (rhs1) != SSA_NAME) { tmp = create_tmp_var (build_nonstandard_integer_type (actual_precision, from_unsigned1), @@ -2160,7 +2168,8 @@ convert_mult_to_widen (gimple stmt, gimple_stmt_iterator *gsi) rhs1 = build_and_insert_cast (gsi, loc, tmp, rhs1); } if (actual_precision != TYPE_PRECISION (type2) - || from_unsigned2 != TYPE_UNSIGNED (type2)) + || from_unsigned2 != TYPE_UNSIGNED (type2) + || TREE_CODE (rhs2) != SSA_NAME) { /* Reuse the same type info, if possible. */ if (!tmp || from_unsigned1 != from_unsigned2) @@ -2221,8 +2230,6 @@ convert_plusminus_to_widen (gimple_stmt_iterator *gsi, gimple stmt, if (is_gimple_assign (rhs1_stmt)) rhs1_code = gimple_assign_rhs_code (rhs1_stmt); } - else - return false; if (TREE_CODE (rhs2) == SSA_NAME) { @@ -2230,8 +2237,6 @@ convert_plusminus_to_widen (gimple_stmt_iterator *gsi, gimple stmt, if (is_gimple_assign (rhs2_stmt)) rhs2_code = gimple_assign_rhs_code (rhs2_stmt); } - else - return false; /* Allow for one conversion statement between the multiply and addition/subtraction statement. If there are more than @@ -2358,7 +2363,8 @@ convert_plusminus_to_widen (gimple_stmt_iterator *gsi, gimple stmt, for the opcode. This will be the full mode size. */ actual_precision = GET_MODE_PRECISION (actual_mode); if (actual_precision != TYPE_PRECISION (type1) - || from_unsigned1 != TYPE_UNSIGNED (type1)) + || from_unsigned1 != TYPE_UNSIGNED (type1) + || TREE_CODE (mult_rhs1) != SSA_NAME) { tmp = create_tmp_var (build_nonstandard_integer_type (actual_precision, from_unsigned1), @@ -2366,7 +2372,8 @@ convert_plusminus_to_widen (gimple_stmt_iterator *gsi, gimple stmt, mult_rhs1 = build_and_insert_cast (gsi, loc, tmp, mult_rhs1); } if (actual_precision != TYPE_PRECISION (type2) - || from_unsigned2 != TYPE_UNSIGNED (type2)) + || from_unsigned2 != TYPE_UNSIGNED (type2) + || TREE_CODE (mult_rhs2) != SSA_NAME) { if (!tmp || from_unsigned1 != from_unsigned2) tmp = create_tmp_var (build_nonstandard_integer_type