From patchwork Mon Mar 26 17:25:01 2012 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Uros Bizjak X-Patchwork-Id: 148782 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 A2B75B6EE7 for ; Tue, 27 Mar 2012 04:25:41 +1100 (EST) Comment: DKIM? See http://www.dkim.org DKIM-Signature: v=1; a=rsa-sha1; c=relaxed/relaxed; d=gcc.gnu.org; s=default; x=1333387541; h=Comment: DomainKey-Signature:Received:Received:Received:Received: MIME-Version:Received:Received:Date:Message-ID:Subject:From:To: Cc:Content-Type:Mailing-List:Precedence:List-Id:List-Unsubscribe: List-Archive:List-Post:List-Help:Sender:Delivered-To; bh=+4ycI0R yfkt+p43a23GjQ7h5lho=; b=OSGqlFlPdNbGU6vwrTvlBW3Zax/DUkaOzHLlEuX gs3VzPG1IMLhOVgIyUvfWugs7ZL8PVAMkQ66klCswrp39rYoCUjAyYMeJzC+9ztc eIufPCwY6iFCX6VU1MjCsSvodLY/tYR1ZbowEXRZvxd3TVVzbDDyAyYqdjNtucgb P2ng= Comment: DomainKeys? See http://antispam.yahoo.com/domainkeys DomainKey-Signature: a=rsa-sha1; q=dns; c=nofws; s=default; d=gcc.gnu.org; h=Received:Received:X-SWARE-Spam-Status:X-Spam-Check-By:Received:Received:MIME-Version:Received:Received:Date:Message-ID:Subject:From:To:Cc:Content-Type:Mailing-List:Precedence:List-Id:List-Unsubscribe:List-Archive:List-Post:List-Help:Sender:Delivered-To; b=R8dMfWZLIGWD6wdOzclWfvZeGK+JKXsqJu2brYvHxrTR4fu+O4i/bkgPLF+pdS WvHsnGDZCDrNpwdBlkqHg7DXcHkCJ19lRcHFOiwQ4PZ0i8ckV7XBusshw51S6P90 xvUQdHRjgMB/7S1LzWiaJSAlLhYHURKjqkC9Fwi9tHJdU=; Received: (qmail 22637 invoked by alias); 26 Mar 2012 17:25:23 -0000 Received: (qmail 22600 invoked by uid 22791); 26 Mar 2012 17:25:18 -0000 X-SWARE-Spam-Status: No, hits=-2.3 required=5.0 tests=AWL, BAYES_00, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, FREEMAIL_FROM, RCVD_IN_DNSWL_LOW, TW_ZJ X-Spam-Check-By: sourceware.org Received: from mail-gx0-f175.google.com (HELO mail-gx0-f175.google.com) (209.85.161.175) by sourceware.org (qpsmtpd/0.43rc1) with ESMTP; Mon, 26 Mar 2012 17:25:01 +0000 Received: by ggcy3 with SMTP id y3so4249562ggc.20 for ; Mon, 26 Mar 2012 10:25:01 -0700 (PDT) MIME-Version: 1.0 Received: by 10.236.138.110 with SMTP id z74mr22493881yhi.114.1332782701160; Mon, 26 Mar 2012 10:25:01 -0700 (PDT) Received: by 10.147.32.18 with HTTP; Mon, 26 Mar 2012 10:25:01 -0700 (PDT) Date: Mon, 26 Mar 2012 19:25:01 +0200 Message-ID: Subject: [PATCH, i386]: FIX PR 52698, reload failure with complex address From: Uros Bizjak To: gcc-patches@gcc.gnu.org Cc: Richard Henderson , Ulrich Weigand , "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! In a corner case of a reload, reload pass can generate partially reloaded address, where not all registers get allocated to a hard reg. When this address is checked with ix86_legitimate_address, it is rejected, since in strict mode, pseudos are not valid address registers. So, reload tries to legitimize following (partially invalid) address: (plus:DI (plus:DI (unspec:DI [(const_int 0 [0])] UNSPEC_TP) (reg:DI 97)) (reg:DI 2 cx)) via generic way by pushing all components into a register, forming (even more invalid) address that involves three registers (r8, r9 and rcx): (insn 52 78 53 5 (set (mem/j:QI (plus:DI (plus:DI (reg:DI 37 r8) (reg:DI 38 r9)) (reg:DI 2 cx [orig:98 D.1709 ] [98])) [0 foo S1 A8]) (reg:QI 1 dx [100])) /tmp/x.c:12 66 {*movqi_internal} (nil)) BTW: x86 declares MAX_REGISTER_PER_ADDRESS to 2... Attached patch fixes this situation by (partially) reloading only remaining pseudo(s), leaving UNSPEC in the address RTX. 2012-03-26 Uros Bizjak PR target/52698 * config/i386/i386-protos.h (ix86_legitimize_reload_address): New prototype. * config/i386/i386.h (LEGITIMIZE_RELOAD_ADDRESS): New define. * config/i386/i386.c: Include reload.h. (ix86_legitimize_reload_address): New function. testsuite/ChangeLog: 2012-03-26 Uros Bizjak H.J. Lu PR target/52698 * gcc.target/i386/pr52698.c: New test. The patch was bootstrapped and regression tested on x86_64-pc-linux-gnu {,-m32}. Since fixing reload issues is some kind of black magic, I'd like to ask Ulrich and Richard for their opinion on this approach. H.J., can you please test this fix on x32 testsuite for both address modes? Thanks, Uros. Index: config/i386/i386.c =================================================================== --- config/i386/i386.c (revision 185807) +++ config/i386/i386.c (working copy) @@ -47,6 +47,7 @@ #include "target-def.h" #include "common/common-target.h" #include "langhooks.h" +#include "reload.h" #include "cgraph.h" #include "gimple.h" #include "dwarf2.h" @@ -12010,6 +12011,64 @@ return false; } +/* Our implementation of LEGITIMIZE_RELOAD_ADDRESS. Returns a value to + replace the input X, or the original X if no replacement is called for. + The output parameter *WIN is 1 if the calling macro should goto WIN, + 0 if it should not. */ + +bool +ix86_legitimize_reload_address (rtx x, + enum machine_mode mode ATTRIBUTE_UNUSED, + int opnum, int type, + int ind_levels ATTRIBUTE_UNUSED) +{ + /* Reload can generate: + + (plus:DI (plus:DI (unspec:DI [(const_int 0 [0])] UNSPEC_TP) + (reg:DI 97)) + (reg:DI 2 cx)) + + This RTX is rejected from ix86_legitimate_address_p due to + non-strictness of base register 97. Following this rejection, + reload pushes all three components into separate registers, + creating invalid memory address RTX. + + Following code reloads only the invalid part of the + memory address RTX. */ + + if (GET_CODE (x) == PLUS + && REG_P (XEXP (x, 1)) + && GET_CODE (XEXP (x, 0)) == PLUS + && REG_P (XEXP (XEXP (x, 0), 1))) + { + rtx base, index; + bool something_reloaded = false; + + base = XEXP (XEXP (x, 0), 1); + if (!REG_OK_FOR_BASE_STRICT_P (base)) + { + push_reload (base, NULL_RTX, &XEXP (XEXP (x, 0), 1), NULL, + BASE_REG_CLASS, GET_MODE (x), VOIDmode, 0, 0, + opnum, (enum reload_type)type); + something_reloaded = true; + } + + index = XEXP (x, 1); + if (!REG_OK_FOR_INDEX_STRICT_P (index)) + { + push_reload (index, NULL_RTX, &XEXP (x, 1), NULL, + INDEX_REG_CLASS, GET_MODE (x), VOIDmode, 0, 0, + opnum, (enum reload_type)type); + something_reloaded = true; + } + + gcc_assert (something_reloaded); + return true; + } + + return false; +} + /* Recognizes RTL expressions that are valid memory addresses for an instruction. The MODE argument is the machine mode for the MEM expression that wants to use this address. Index: config/i386/i386.h =================================================================== --- config/i386/i386.h (revision 185807) +++ config/i386/i386.h (working copy) @@ -1630,6 +1630,17 @@ #define CONSTANT_ADDRESS_P(X) constant_address_p (X) +/* Try a machine-dependent way of reloading an illegitimate address + operand. If we find one, push the reload and jump to WIN. This + macro is used in only one place: `find_reloads_address' in reload.c. */ + +#define LEGITIMIZE_RELOAD_ADDRESS(X, MODE, OPNUM, TYPE, INDL, WIN) \ +do { \ + if (ix86_legitimize_reload_address ((X), (MODE), (OPNUM), \ + (int)(TYPE), (INDL))) \ + goto WIN; \ +} while (0) + /* If defined, a C expression to determine the base term of address X. This macro is used in only one place: `find_base_term' in alias.c. Index: config/i386/i386-protos.h =================================================================== --- config/i386/i386-protos.h (revision 185807) +++ config/i386/i386-protos.h (working copy) @@ -65,7 +65,8 @@ extern bool constant_address_p (rtx); extern bool legitimate_pic_operand_p (rtx); extern bool legitimate_pic_address_disp_p (rtx); - +extern bool ix86_legitimize_reload_address (rtx, enum machine_mode, + int, int, int); extern void print_reg (rtx, int, FILE*); extern void ix86_print_operand (FILE *, rtx, int); Index: testsuite/gcc.target/i386/pr52698.c =================================================================== --- testsuite/gcc.target/i386/pr52698.c (revision 0) +++ testsuite/gcc.target/i386/pr52698.c (revision 0) @@ -0,0 +1,18 @@ +/* { dg-do compile { target { ! { ia32 } } } } */ +/* { dg-options "-O2 -mx32 -maddress-mode=long" } */ + +extern void abort (void); +static __thread unsigned char foo [32] +__attribute__ ((tls_model ("initial-exec"), aligned (sizeof (void *)))); + +void +test2 (void) +{ + unsigned int s; + for (s = 0; s < sizeof (foo); ++s) + { + if (foo [s] != s) + abort (); + foo [s] = sizeof (foo) - s; + } +}