From patchwork Thu Jun 23 14:41: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: 101637 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 64724B6F88 for ; Fri, 24 Jun 2011 00:42:21 +1000 (EST) Received: (qmail 939 invoked by alias); 23 Jun 2011 14:42:19 -0000 Received: (qmail 930 invoked by uid 22791); 23 Jun 2011 14:42:18 -0000 X-SWARE-Spam-Status: No, hits=-2.5 required=5.0 tests=BAYES_00, RCVD_IN_DNSWL_LOW, TW_TM X-Spam-Check-By: sourceware.org Received: from mail-ww0-f51.google.com (HELO mail-ww0-f51.google.com) (74.125.82.51) by sourceware.org (qpsmtpd/0.43rc1) with ESMTP; Thu, 23 Jun 2011 14:42:04 +0000 Received: by wwj26 with SMTP id 26so1808889wwj.8 for ; Thu, 23 Jun 2011 07:42:03 -0700 (PDT) Received: by 10.227.61.148 with SMTP id t20mr2090088wbh.103.1308840122981; Thu, 23 Jun 2011 07:42:02 -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 c17sm1282964wbh.46.2011.06.23.07.42.01 (version=SSLv3 cipher=OTHER); Thu, 23 Jun 2011 07:42:02 -0700 (PDT) Message-ID: <4E0350B7.7080802@codesourcery.com> Date: Thu, 23 Jun 2011 15:41: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 To: gcc-patches@gcc.gnu.org CC: patches@linaro.org Subject: [PATCH (5/7)] Widening multiplies for mis-matched mode inputs References: <4E034EF2.3070503@codesourcery.com> In-Reply-To: <4E034EF2.3070503@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 This patch removes the restriction that the inputs to a widening multiply must be of the same mode. It does this by extending the smaller of the two inputs to match the larger; therefore, it remains the case that subsequent code (in the expand pass, for example) can rely on the type of rhs1 being the input type of the operation, and the gimple verification code is still valid. OK? Andrew 2011-06-23 Andrew Stubbs gcc/ * tree-ssa-math-opts.c (is_widening_mult_p): Remove FIXME. Ensure the the larger type is the first operand. (convert_mult_to_widen): Insert cast if type2 is smaller than type1. (convert_plusminus_to_widen): Likewise. gcc/testsuite/ * gcc.target/arm/smlalbb-2.c: New file. --- /dev/null +++ b/gcc/testsuite/gcc.target/arm/smlalbb-2.c @@ -0,0 +1,10 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -march=armv7-a" } */ + +unsigned long long +foo (unsigned long long a, unsigned char *b, unsigned short *c) +{ + return a + *b * *c; +} + +/* { dg-final { scan-assembler "smlalbb" } } */ --- a/gcc/tree-ssa-math-opts.c +++ b/gcc/tree-ssa-math-opts.c @@ -2051,9 +2051,17 @@ is_widening_mult_p (gimple stmt, *type2_out = *type1_out; } - /* FIXME: remove this restriction. */ - if (TYPE_PRECISION (*type1_out) != TYPE_PRECISION (*type2_out)) - return false; + /* Ensure that the larger of the two operands comes first. */ + if (TYPE_PRECISION (*type1_out) < TYPE_PRECISION (*type2_out)) + { + tree tmp; + tmp = *type1_out; + *type1_out = *type2_out; + *type2_out = tmp; + tmp = *rhs1_out; + *rhs1_out = *rhs2_out; + *rhs2_out = tmp; + } return true; } @@ -2069,6 +2077,7 @@ convert_mult_to_widen (gimple stmt, gimple_stmt_iterator *gsi) enum insn_code handler; enum machine_mode to_mode, from_mode; optab op; + int cast1 = false, cast2 = false; lhs = gimple_assign_lhs (stmt); type = TREE_TYPE (lhs); @@ -2107,16 +2116,26 @@ convert_mult_to_widen (gimple stmt, gimple_stmt_iterator *gsi) return false; type1 = type2 = lang_hooks.types.type_for_mode (from_mode, 0); - - rhs1 = build_and_insert_cast (gsi, gimple_location (stmt), - create_tmp_var (type1, NULL), rhs1, type1); - rhs2 = build_and_insert_cast (gsi, gimple_location (stmt), - create_tmp_var (type2, NULL), rhs2, type2); + cast1 = cast2 = true; } else return false; } + if (TYPE_MODE (type2) != from_mode) + { + type2 = lang_hooks.types.type_for_mode (from_mode, + TYPE_UNSIGNED (type2)); + cast2 = true; + } + + if (cast1) + rhs1 = build_and_insert_cast (gsi, gimple_location (stmt), + create_tmp_var (type1, NULL), rhs1, type1); + if (cast2) + rhs2 = build_and_insert_cast (gsi, gimple_location (stmt), + create_tmp_var (type2, NULL), rhs2, type2); + gimple_assign_set_rhs1 (stmt, fold_convert (type1, rhs1)); gimple_assign_set_rhs2 (stmt, fold_convert (type2, rhs2)); gimple_assign_set_rhs_code (stmt, WIDEN_MULT_EXPR); @@ -2142,6 +2161,7 @@ convert_plusminus_to_widen (gimple_stmt_iterator *gsi, gimple stmt, optab this_optab; enum tree_code wmult_code; enum insn_code handler; + int cast1 = false, cast2 = false; lhs = gimple_assign_lhs (stmt); type = TREE_TYPE (lhs); @@ -2228,17 +2248,28 @@ convert_plusminus_to_widen (gimple_stmt_iterator *gsi, gimple stmt, if (GET_MODE_SIZE (mode) < GET_MODE_SIZE (TYPE_MODE (type))) { type1 = type2 = lang_hooks.types.type_for_mode (mode, 0); - mult_rhs1 = build_and_insert_cast (gsi, gimple_location (stmt), - create_tmp_var (type1, NULL), - mult_rhs1, type1); - mult_rhs2 = build_and_insert_cast (gsi, gimple_location (stmt), - create_tmp_var (type2, NULL), - mult_rhs2, type2); + cast1 = cast2 = true; } else return false; } + if (TYPE_MODE (type2) != TYPE_MODE (type1)) + { + type2 = lang_hooks.types.type_for_mode (TYPE_MODE (type1), + TYPE_UNSIGNED (type2)); + cast2 = true; + } + + if (cast1) + mult_rhs1 = build_and_insert_cast (gsi, gimple_location (stmt), + create_tmp_var (type1, NULL), + mult_rhs1, type1); + if (cast2) + mult_rhs2 = build_and_insert_cast (gsi, gimple_location (stmt), + create_tmp_var (type2, NULL), + mult_rhs2, type2); + /* Verify that the machine can perform a widening multiply accumulate in this mode/signedness combination, otherwise this transformation is likely to pessimize code. */