From patchwork Wed Aug 18 10:28:48 2010 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Maxim Kuvyrkov X-Patchwork-Id: 62025 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 CDAFEB70DF for ; Wed, 18 Aug 2010 20:29:03 +1000 (EST) Received: (qmail 455 invoked by alias); 18 Aug 2010 10:29:02 -0000 Received: (qmail 447 invoked by uid 22791); 18 Aug 2010 10:29:01 -0000 X-SWARE-Spam-Status: No, hits=-1.9 required=5.0 tests=AWL, BAYES_00, 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; Wed, 18 Aug 2010 10:28:56 +0000 Received: (qmail 1666 invoked from network); 18 Aug 2010 10:28:54 -0000 Received: from unknown (HELO mbp.local) (maxim@127.0.0.2) by mail.codesourcery.com with ESMTPA; 18 Aug 2010 10:28:54 -0000 Message-ID: <4C6BB5E0.5040006@codesourcery.com> Date: Wed, 18 Aug 2010 14:28:48 +0400 From: Maxim Kuvyrkov User-Agent: Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10.6; en-US; rv:1.9.2.8) Gecko/20100802 Thunderbird/3.1.2 MIME-Version: 1.0 To: gcc-patches CC: Bernd Schmidt Subject: [PATCH, PR42575, approved] Shorten pseudos live ranges when expanding doubleword mult X-IsSubscribed: yes 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 gets rid of the extraneous move when generating doubleword multiplication. The patch was approved off-list by Bernd. One of the problems in PR42575 when compiled for ARMv7-A is an extra move that, ideally, should not be there (-O2 -march=armv7-a): longfunc: @ args = 0, pretend = 0, frame = 0 @ frame_needed = 0, uses_anonymous_args = 0 @ link register save eliminated. mul r3, r0, r3 mla r3, r2, r1, r3 umull r0, r1, r0, r2 add r3, r3, r1 mov r1, r3 // Extra move bx lr The problem is in expand. Expand unnecessarily lengthens live range of the pseudo that gets allocated to r3. IRA cannot allocate that pseudo to r1 as part of its live range crosses with previous value of r1. The problem is fixed by making expand not reuse the pseudo (adjust variable in the patch). With the patch GCC generates : longfunc: @ args = 0, pretend = 0, frame = 0 @ frame_needed = 0, uses_anonymous_args = 0 @ link register save eliminated. mul r3, r0, r3 mla r3, r2, r1, r3 umull r0, r1, r0, r2 add r1, r3, r1 bx lr .size longfunc, .-longfunc Bootstrapped and regtested on i686-pc-linux-gnu{-m32/-m64}. Bernd also verified that the patch doesn't cause any negative change in the generated code on this collection of examples. Will check in shortly. Thanks, diff --git a/gcc/optabs.c b/gcc/optabs.c index b9db02f..1fcbedc 100644 --- a/gcc/optabs.c +++ b/gcc/optabs.c @@ -1257,7 +1257,7 @@ expand_doubleword_mult (enum machine_mode mode, rtx op0, rtx op1, rtx target, /* OP1_HIGH should now be dead. */ adjust = expand_binop (word_mode, add_optab, adjust, temp, - adjust, 0, OPTAB_DIRECT); + NULL_RTX, 0, OPTAB_DIRECT); if (target && !REG_P (target)) target = NULL_RTX; @@ -1274,8 +1274,7 @@ expand_doubleword_mult (enum machine_mode mode, rtx op0, rtx op1, rtx target, product_high = operand_subword (product, high, 1, mode); adjust = expand_binop (word_mode, add_optab, product_high, adjust, - REG_P (product_high) ? product_high : adjust, - 0, OPTAB_DIRECT); + NULL_RTX, 0, OPTAB_DIRECT); emit_move_insn (product_high, adjust); return product; } diff --git a/gcc/testsuite/gcc.target/arm/pr42575.c b/gcc/testsuite/gcc.target/arm/pr42575.c new file mode 100644 index 0000000..474bf6c --- /dev/null +++ b/gcc/testsuite/gcc.target/arm/pr42575.c @@ -0,0 +1,9 @@ +/* { dg-options "-O2 -march=armv7-a" } */ +/* Make sure RA does good job allocating registers and avoids + unnecessary moves. */ +/* { dg-final { scan-assembler-not "mov" } } */ + +long long longfunc(long long x, long long y) +{ + return x * y; +}