From patchwork Mon Jul 4 14:31:59 2011 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Andrew Stubbs X-Patchwork-Id: 2440 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 A79622412F for ; Mon, 4 Jul 2011 14:32:04 +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 5C275A184BB for ; Mon, 4 Jul 2011 14:32:04 +0000 (UTC) Received: by qyk10 with SMTP id 10so1224046qyk.11 for ; Mon, 04 Jul 2011 07:32:03 -0700 (PDT) Received: by 10.229.102.98 with SMTP id f34mr4769590qco.42.1309789923817; Mon, 04 Jul 2011 07:32:03 -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.48.135 with SMTP id r7cs29602qcf; Mon, 4 Jul 2011 07:32:03 -0700 (PDT) Received: by 10.42.133.8 with SMTP id f8mr7643000ict.176.1309789922880; Mon, 04 Jul 2011 07:32:02 -0700 (PDT) Received: from mail.codesourcery.com (mail.codesourcery.com [38.113.113.100]) by mx.google.com with ESMTPS id uf10si18990420icb.113.2011.07.04.07.32.02 (version=TLSv1/SSLv3 cipher=OTHER); Mon, 04 Jul 2011 07:32:02 -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 28813 invoked from network); 4 Jul 2011 14:32:01 -0000 Received: from unknown (HELO ?192.168.0.100?) (ams@127.0.0.2) by mail.codesourcery.com with ESMTPA; 4 Jul 2011 14:32:01 -0000 Message-ID: <4E11CEDF.6060004@codesourcery.com> Date: Mon, 04 Jul 2011 15:31:59 +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 CC: gcc-patches@gcc.gnu.org, patches@linaro.org Subject: Re: [PATCH (6/7)] More widening multiply-and-accumulate pattern matching References: <4E034EF2.3070503@codesourcery.com> <4E0350EF.4090500@codesourcery.com> <4E09F38D.8000606@codesourcery.com> In-Reply-To: <4E09F38D.8000606@codesourcery.com> On 28/06/11 16:30, Andrew Stubbs wrote: > On 23/06/11 15:42, Andrew Stubbs wrote: >> This patch fixes the case where widening multiply-and-accumulate were >> not recognised because the multiplication itself is not actually >> widening. >> >> This can happen when you have "DI + SI * SI" - the multiplication will >> be done in SImode as a non-widening multiply, and it's only the final >> accumulate step that is widening. >> >> This was not recognised for two reasons: >> >> 1. is_widening_mult_p inferred the output type from the multiply >> statement, which in not useful in this case. >> >> 2. The inputs to the multiply instruction may not have been converted at >> all (because they're not being widened), so the pattern match failed. >> >> The patch fixes these issues by making the output type explicit, and by >> permitting unconverted inputs (the types are still checked, so this is >> safe). >> >> OK? > > This update fixes Janis' testsuite issue. This updates the context changed by my update to patch 3. The content of this patch has not changed. Andrew 2011-07-04 Andrew Stubbs gcc/ * tree-ssa-math-opts.c (is_widening_mult_rhs_p): Add new argument 'type'. Use 'type' from caller, not inferred from 'rhs'. Don't reject non-conversion statements. Do return lhs in this case. (is_widening_mult_p): Add new argument 'type'. Use 'type' from caller, not inferred from 'stmt'. Pass type to is_widening_mult_rhs_p. (convert_mult_to_widen): Pass type to is_widening_mult_p. (convert_plusminus_to_widen): Likewise. gcc/testsuite/ * gcc.target/arm/wmul-8.c: New file. --- /dev/null +++ b/gcc/testsuite/gcc.target/arm/wmul-8.c @@ -0,0 +1,10 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -march=armv7-a" } */ + +long long +foo (long long a, int *b, int *c) +{ + return a + *b * *c; +} + +/* { dg-final { scan-assembler "smlal" } } */ --- a/gcc/tree-ssa-math-opts.c +++ b/gcc/tree-ssa-math-opts.c @@ -1963,7 +1963,8 @@ struct gimple_opt_pass pass_optimize_bswap = } }; -/* Return true if RHS is a suitable operand for a widening multiplication. +/* Return true if RHS is a suitable operand for a widening multiplication, + assuming a target type of TYPE. There are two cases: - RHS makes some value at least twice as wide. Store that value @@ -1973,32 +1974,32 @@ struct gimple_opt_pass pass_optimize_bswap = but leave *TYPE_OUT untouched. */ static bool -is_widening_mult_rhs_p (tree rhs, tree *type_out, tree *new_rhs_out) +is_widening_mult_rhs_p (tree type, tree rhs, tree *type_out, + tree *new_rhs_out) { gimple stmt; - tree type, type1, rhs1; + tree type1, rhs1; enum tree_code rhs_code; if (TREE_CODE (rhs) == SSA_NAME) { - type = TREE_TYPE (rhs); stmt = SSA_NAME_DEF_STMT (rhs); if (!is_gimple_assign (stmt)) return false; - rhs_code = gimple_assign_rhs_code (stmt); - if (TREE_CODE (type) == INTEGER_TYPE - ? !CONVERT_EXPR_CODE_P (rhs_code) - : rhs_code != FIXED_CONVERT_EXPR) - return false; - rhs1 = gimple_assign_rhs1 (stmt); type1 = TREE_TYPE (rhs1); if (TREE_CODE (type1) != TREE_CODE (type) || TYPE_PRECISION (type1) * 2 > TYPE_PRECISION (type)) return false; - *new_rhs_out = rhs1; + rhs_code = gimple_assign_rhs_code (stmt); + if (TREE_CODE (type) == INTEGER_TYPE + ? !CONVERT_EXPR_CODE_P (rhs_code) + : rhs_code != FIXED_CONVERT_EXPR) + *new_rhs_out = gimple_assign_lhs (stmt); + else + *new_rhs_out = rhs1; *type_out = type1; return true; } @@ -2013,28 +2014,27 @@ is_widening_mult_rhs_p (tree rhs, tree *type_out, tree *new_rhs_out) return false; } -/* Return true if STMT performs a widening multiplication. If so, - store the unwidened types of the operands in *TYPE1_OUT and *TYPE2_OUT - respectively. Also fill *RHS1_OUT and *RHS2_OUT such that converting - those operands to types *TYPE1_OUT and *TYPE2_OUT would give the - operands of the multiplication. */ +/* Return true if STMT performs a widening multiplication, assuming the + output type is TYPE. If so, store the unwidened types of the operands + in *TYPE1_OUT and *TYPE2_OUT respectively. Also fill *RHS1_OUT and + *RHS2_OUT such that converting those operands to types *TYPE1_OUT + and *TYPE2_OUT would give the operands of the multiplication. */ static bool -is_widening_mult_p (gimple stmt, +is_widening_mult_p (tree type, gimple stmt, tree *type1_out, tree *rhs1_out, tree *type2_out, tree *rhs2_out) { - tree type; - - type = TREE_TYPE (gimple_assign_lhs (stmt)); if (TREE_CODE (type) != INTEGER_TYPE && TREE_CODE (type) != FIXED_POINT_TYPE) return false; - if (!is_widening_mult_rhs_p (gimple_assign_rhs1 (stmt), type1_out, rhs1_out)) + if (!is_widening_mult_rhs_p (type, gimple_assign_rhs1 (stmt), type1_out, + rhs1_out)) return false; - if (!is_widening_mult_rhs_p (gimple_assign_rhs2 (stmt), type2_out, rhs2_out)) + if (!is_widening_mult_rhs_p (type, gimple_assign_rhs2 (stmt), type2_out, + rhs2_out)) return false; if (*type1_out == NULL) @@ -2084,7 +2084,7 @@ convert_mult_to_widen (gimple stmt, gimple_stmt_iterator *gsi) if (TREE_CODE (type) != INTEGER_TYPE) return false; - if (!is_widening_mult_p (stmt, &type1, &rhs1, &type2, &rhs2)) + if (!is_widening_mult_p (type, stmt, &type1, &rhs1, &type2, &rhs2)) return false; to_mode = TYPE_MODE (type); @@ -2280,7 +2280,7 @@ convert_plusminus_to_widen (gimple_stmt_iterator *gsi, gimple stmt, if (code == PLUS_EXPR && rhs1_code == MULT_EXPR) { - if (!is_widening_mult_p (rhs1_stmt, &type1, &mult_rhs1, + if (!is_widening_mult_p (type, rhs1_stmt, &type1, &mult_rhs1, &type2, &mult_rhs2)) return false; mult_rhs = rhs1; @@ -2288,7 +2288,7 @@ convert_plusminus_to_widen (gimple_stmt_iterator *gsi, gimple stmt, } else if (rhs2_code == MULT_EXPR) { - if (!is_widening_mult_p (rhs2_stmt, &type1, &mult_rhs1, + if (!is_widening_mult_p (type, rhs2_stmt, &type1, &mult_rhs1, &type2, &mult_rhs2)) return false; mult_rhs = rhs2;