From patchwork Wed Jul 20 16:41:49 2011 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Uros Bizjak X-Patchwork-Id: 105760 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 14BE8B6F71 for ; Thu, 21 Jul 2011 02:42:10 +1000 (EST) Received: (qmail 29570 invoked by alias); 20 Jul 2011 16:42:06 -0000 Received: (qmail 29552 invoked by uid 22791); 20 Jul 2011 16:42:04 -0000 X-SWARE-Spam-Status: No, hits=-2.2 required=5.0 tests=AWL, BAYES_00, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, FREEMAIL_FROM, RCVD_IN_DNSWL_LOW, TW_ZJ, T_TO_NO_BRKTS_FREEMAIL X-Spam-Check-By: sourceware.org Received: from mail-iy0-f175.google.com (HELO mail-iy0-f175.google.com) (209.85.210.175) by sourceware.org (qpsmtpd/0.43rc1) with ESMTP; Wed, 20 Jul 2011 16:41:50 +0000 Received: by iyj12 with SMTP id 12so403669iyj.20 for ; Wed, 20 Jul 2011 09:41:49 -0700 (PDT) MIME-Version: 1.0 Received: by 10.142.254.21 with SMTP id b21mr4325236wfi.249.1311180109139; Wed, 20 Jul 2011 09:41:49 -0700 (PDT) Received: by 10.142.89.19 with HTTP; Wed, 20 Jul 2011 09:41:49 -0700 (PDT) Date: Wed, 20 Jul 2011 18:41:49 +0200 Message-ID: Subject: [RFC PATCH, i386]: Allow SUBREG_PROMOTED_UNSIGNED_P subregs in address From: Uros Bizjak To: gcc-patches@gcc.gnu.org Cc: Jakub Jelinek , Richard Henderson , "H.J. Lu" 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 Hello! Attached RFC patch buids on recent x86 improvements in ix86_legitimate_address_p/ix86_decompose_address functions. With this patch, we allow SUBREGs with register_no_elim_operand registers in base, index and PLUS chains. As the consequence, we can relax the condition that rejects SUBREGs, wider than word mode due to possible spill failures with double-word SUBREGs. register_no_elim_operand together with REG_OK_FOR_BASE/REG_OK_FOR_INDEX predicates guarantee, that there will be no spills since multi-word registers that satisfy these predicates can easily be decomposed to satisfy SUBREGs. Another improvement is introduction of SUBREG_PROMOTED_UNSIGNED_P predicate in the same area to handle paradoxical SUBREGs. When SUBREG satisfies this predicate, the compiler guarantees, that excess bits are zero (see the documentation). This is exaclty what we want in registers that form the address. In theory, we can allow registers of any integer mode here, but in practice only DImode subreg of SImode register is important. IMO, the first optimization is important on i686, while the second is important on x32 (lots of paradoxical subregs in addresses due to Pmode != ptr_mode), but they are also nice to have on x86_64. Any thoughts? 2011-07-20 Uros Bizjak * config/i386/i386.c (ix86_decompose_address): Also allow promoted paradoxical subregs in base and PLUS chains. Allow only paradoxical subregs and subregs of DImode hard registers in subregs of index. (ix86_legitimate_address_p): Allow subregs of base and index to span more than a word. Assert that subregs of base and index satisfy SUBREG_PROMOTED_UNSIGNED_P or register_no_elim_operand predicates. Patch was bootstrapped and is currently regression testing on x86_64-pc-linux-gnu {,-m32}. Uros. Index: i386.c =================================================================== --- i386.c (revision 176512) +++ i386.c (working copy) @@ -11089,8 +11089,10 @@ ix86_decompose_address (rtx addr, struct base = addr; else if (GET_CODE (addr) == SUBREG) { - /* Allow only subregs of DImode hard regs. */ - if (register_no_elim_operand (SUBREG_REG (addr), DImode)) + /* Allow only promoted paradoxical subregs + or subregs of DImode hard regs. */ + if (SUBREG_PROMOTED_UNSIGNED_P (addr) + || register_no_elim_operand (SUBREG_REG (addr), DImode)) base = addr; else return 0; @@ -11148,8 +11150,10 @@ ix86_decompose_address (rtx addr, struct break; case SUBREG: - /* Allow only subregs of DImode hard regs in PLUS chains. */ - if (!register_no_elim_operand (SUBREG_REG (op), DImode)) + /* Allow only promoted paradoxical subregs + or subregs of DImode hard regs in PLUS chains. */ + if (!(SUBREG_PROMOTED_UNSIGNED_P (op) + || register_no_elim_operand (SUBREG_REG (op), DImode))) return 0; /* FALLTHRU */ @@ -11197,6 +11201,18 @@ ix86_decompose_address (rtx addr, struct else disp = addr; /* displacement */ + if (index) + { + if (REG_P (index)) + ; + /* Allow only promoted paradoxical subregs + or subregs of DImode hard regs. */ + else if (GET_CODE (index) == SUBREG + && !(SUBREG_PROMOTED_UNSIGNED_P (index) + || register_no_elim_operand (SUBREG_REG (index), DImode))) + return 0; + } + /* Extract the integral value of scale. */ if (scale_rtx) { @@ -11630,11 +11646,7 @@ ix86_legitimate_address_p (enum machine_ disp = parts.disp; scale = parts.scale; - /* Validate base register. - - Don't allow SUBREG's that span more than a word here. It can lead to spill - failures when the base is one word out of a two word structure, which is - represented internally as a DImode int. */ + /* Validate base register. */ if (base) { @@ -11642,11 +11654,12 @@ ix86_legitimate_address_p (enum machine_ if (REG_P (base)) reg = base; - else if (GET_CODE (base) == SUBREG - && REG_P (SUBREG_REG (base)) - && GET_MODE_SIZE (GET_MODE (SUBREG_REG (base))) - <= UNITS_PER_WORD) - reg = SUBREG_REG (base); + else if (GET_CODE (base) == SUBREG && REG_P (SUBREG_REG (base))) + { + reg = SUBREG_REG (base); + gcc_assert (SUBREG_PROMOTED_UNSIGNED_P (base) + || register_no_elim_operand (reg, DImode)); + } else /* Base is not a register. */ return false; @@ -11660,9 +11673,7 @@ ix86_legitimate_address_p (enum machine_ return false; } - /* Validate index register. - - Don't allow SUBREG's that span more than a word here -- same as above. */ + /* Validate index register. */ if (index) { @@ -11670,11 +11681,12 @@ ix86_legitimate_address_p (enum machine_ if (REG_P (index)) reg = index; - else if (GET_CODE (index) == SUBREG - && REG_P (SUBREG_REG (index)) - && GET_MODE_SIZE (GET_MODE (SUBREG_REG (index))) - <= UNITS_PER_WORD) - reg = SUBREG_REG (index); + else if (GET_CODE (index) == SUBREG && REG_P (SUBREG_REG (index))) + { + reg = SUBREG_REG (index); + gcc_assert (SUBREG_PROMOTED_UNSIGNED_P (index) + || register_no_elim_operand (reg, DImode)); + } else /* Index is not a register. */ return false;