From patchwork Tue Nov 13 14:30:10 2012 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "H.J. Lu" X-Patchwork-Id: 198699 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 3C3B42C00B5 for ; Wed, 14 Nov 2012 01:30:56 +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=1353421857; h=Comment: DomainKey-Signature:Received:Received:Received:Received:Received: Received:Received:Date:From:To:Cc:Subject:Message-ID:References: MIME-Version:Content-Type:Content-Disposition:In-Reply-To: User-Agent:Mailing-List:Precedence:List-Id:List-Unsubscribe: List-Archive:List-Post:List-Help:Sender:Delivered-To; bh=tZwjmSY Sjd3Nbkqpds9ystlhG6I=; b=gOEEmAoiVeaFj5XBsHxgxV7nW8e8bn2uetNGIyR 7YxFFYD0UUc+cf1UjBqiJUYPYmgLvMBUwW599HtailHV/R0hqIWnzlIuQqPsDmfF YYNytozAPM7acFuJNE31/lpDvQVX8lMLEgQ2A5jBn2a465jVFcaYlBgYkIl5WKD4 e7kM= 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:Received:Received:Received:Date:From:To:Cc:Subject:Message-ID:References:MIME-Version:Content-Type:Content-Disposition:In-Reply-To:User-Agent:X-IsSubscribed:Mailing-List:Precedence:List-Id:List-Unsubscribe:List-Archive:List-Post:List-Help:Sender:Delivered-To; b=LRuaABgYc0svg2upY10KqOX7XI0ffxuwemdGpjl27A8wnkN67jCx/G1dApUlme 8cgJ/V6y54DmgY8yK7+kKbcXfL2WvMapNM60bzqILI5TgTVCm265ZacIKvJKBePy 7HfE94wLaGRKP7Kp7We891rFA1d38eVRtPNT4C+TjW/H0=; Received: (qmail 12166 invoked by alias); 13 Nov 2012 14:30:47 -0000 Received: (qmail 12156 invoked by uid 22791); 13 Nov 2012 14:30:46 -0000 X-SWARE-Spam-Status: No, hits=-4.2 required=5.0 tests=AWL, BAYES_00, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, FREEMAIL_FROM, KHOP_RCVD_TRUST, RCVD_IN_DNSWL_LOW, RCVD_IN_HOSTKARMA_YE, TW_ZJ X-Spam-Check-By: sourceware.org Received: from mail-ia0-f175.google.com (HELO mail-ia0-f175.google.com) (209.85.210.175) by sourceware.org (qpsmtpd/0.43rc1) with ESMTP; Tue, 13 Nov 2012 14:30:16 +0000 Received: by mail-ia0-f175.google.com with SMTP id z3so1963046iad.20 for ; Tue, 13 Nov 2012 06:30:15 -0800 (PST) Received: by 10.50.169.102 with SMTP id ad6mr2235477igc.10.1352817015847; Tue, 13 Nov 2012 06:30:15 -0800 (PST) Received: from gnu-tools-1.localdomain (76-220-57-190.lightspeed.sntcca.sbcglobal.net. [76.220.57.190]) by mx.google.com with ESMTPS id u4sm9068641igw.6.2012.11.13.06.30.13 (version=TLSv1/SSLv3 cipher=OTHER); Tue, 13 Nov 2012 06:30:14 -0800 (PST) Received: by gnu-tools-1.localdomain (Postfix, from userid 1000) id 95D0D1A062A; Tue, 13 Nov 2012 06:30:10 -0800 (PST) Date: Tue, 13 Nov 2012 06:30:10 -0800 From: "H.J. Lu" To: Uros Bizjak Cc: gcc-patches@gcc.gnu.org Subject: Patch: PR target/55142: [4.8 Regression] internal compiler error: in plus_constant, at explow.c:88 Message-ID: <20121113143010.GA27142@gmail.com> References: <20121109091727.GA23790@gmail.com> MIME-Version: 1.0 Content-Disposition: inline In-Reply-To: User-Agent: Mutt/1.5.21 (2010-09-15) 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 On Tue, Nov 13, 2012 at 08:28:04AM +0100, Uros Bizjak wrote: > On Tue, Nov 13, 2012 at 8:15 AM, H.J. Lu wrote: > > >>>> Since x32 runs in 64-bit mode, for address -0x40000300(%rax), hardware > >>>> sign-extends displacement from 32-bits to 64-bits and adds it to %rax. > >>>> But x32 wants 32-bit -0x40000300, not 64-bit -0x40000300. This patch > >>>> uses 32-bit registers instead of 64-bit registers when displacement > >>>> < -16*1024*1024. -16*1024*1024 is used instead of 0 so that we will > >>>> still generate -16(%rsp) instead of -16(%esp). > >>>> > >>>> Tested it on Linux/x32. OK to install? > >>> > >>> This problem uncovers a bug in the middle-end, so I guess it would be > >>> better to fix it there. > >>> > >>> Uros. > >> > >> The problem is it isn't safe to transform > >> > >> (zero_extend:DI (plus:SI (FOO:SI) (const_int Y))) > >> > >> to > >> > >> (plus:DI (zero_extend:DI (FOO:SI)) (const_int Y)) > >> > >> when Y is negative and its absolute value is greater than FOO. However, > >> we have to do this transformation since other parts of GCC depend on > >> it. If we revert the fix for > >> > >> http://gcc.gnu.org/bugzilla/show_bug.cgi?id=49721 > >> > >> we will get > >> > >> FAIL: gcc.c-torture/compile/990523-1.c -O3 -g (internal compiler error) > >> FAIL: gcc.c-torture/compile/990523-1.c -O3 -g (test for excess errors) > >> FAIL: gcc.c-torture/compile/pr41634.c -O3 -fomit-frame-pointer -funroll-all-loo > >> ps -finline-functions (internal compiler error) > >> FAIL: gcc.c-torture/compile/pr41634.c -O3 -fomit-frame-pointer -funroll-all-loo > >> ps -finline-functions (test for excess errors) > >> FAIL: gcc.c-torture/compile/pr41634.c -O3 -fomit-frame-pointer -funroll-loops > >> (internal compiler error) > >> FAIL: gcc.c-torture/compile/pr41634.c -O3 -fomit-frame-pointer -funroll-loops > >> (test for excess errors) > >> FAIL: gcc.c-torture/compile/pr41634.c -O3 -fomit-frame-pointer (internal compi > >> ler error) > >> FAIL: gcc.c-torture/compile/pr41634.c -O3 -fomit-frame-pointer (test for exces > >> s errors) > >> FAIL: gcc.c-torture/compile/pr41634.c -O3 -g (internal compiler error) > >> FAIL: gcc.c-torture/compile/pr41634.c -O3 -g (test for excess errors) > >> FAIL: gcc.dg/Warray-bounds.c (internal compiler error) > >> FAIL: gcc.dg/Warray-bounds.c (test for excess errors) > >> > >> since we generate pseudo registers to convert SImode to DImode > >> after reload. Fixing it requires significant changes. > >> > >> This is only a problem for 64-bit register address since the symbolic > >> address is 32-bit. Using 32-bit base/index registers will work around > >> this issue. > > > > This address > > > > (plus:DI (zero_extend:DI (FOO:SI)) (const_int Y)) > > > > is OK for x32 as long as Y, which is encoded as 32-bit immediate, > > is zero-extend from 32-bit to 64-bit. SImode address does it. > > My patch optimizes it a little bit by using SImode address only > > for Y < -16*1024*1024. > > I was wondering, why we operate with constant -16*1024*1024? Should we > use 0x7FFFFFF instead? Since the MSB is always zero, we are safe. > We can check 0x7FFFFFF, i.e., disp < 0. I use -16*1024*1024, which is also used to check legitimate address displacements for PIC, to reduce code sizes for small negative displacements. Or we can always encode negative displacements with zero-extension, including -1(%rsp). > Please add a fat ??? comment, why we paper-over this issue and repost > the latest patch. I got lost in all the versions :( > Here is the updated patch. Thanks. H.J. --- gcc/ 2012-11-13 Eric Botcazou H.J. Lu PR target/55142 * config/i386/i386.c (legitimize_pic_address): Properly handle REG + CONST. (ix86_print_operand_address): For x32, zero-extend negative displacement if it < -16*1024*1024. gcc/testsuite/ 2012-11-13 H.J. Lu PR target/55142 * gcc.target/i386/pr55142-1.c: New file. * gcc.target/i386/pr55142-2.c: Likewise. diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c index 39ed32e..ee75d8e 100644 --- a/gcc/config/i386/i386.c +++ b/gcc/config/i386/i386.c @@ -12195,7 +12195,6 @@ legitimize_pic_address (rtx orig, rtx reg) { rtx addr = orig; rtx new_rtx = orig; - rtx base; #if TARGET_MACHO if (TARGET_MACHO && !TARGET_64BIT) @@ -12400,20 +12399,33 @@ legitimize_pic_address (rtx orig, rtx reg) } else { - base = legitimize_pic_address (XEXP (addr, 0), reg); - new_rtx = legitimize_pic_address (XEXP (addr, 1), - base == reg ? NULL_RTX : reg); + rtx base = legitimize_pic_address (op0, reg); + enum machine_mode mode = GET_MODE (base); + new_rtx + = legitimize_pic_address (op1, base == reg ? NULL_RTX : reg); if (CONST_INT_P (new_rtx)) - new_rtx = plus_constant (Pmode, base, INTVAL (new_rtx)); + { + if (INTVAL (new_rtx) < -16*1024*1024 + || INTVAL (new_rtx) >= 16*1024*1024) + { + if (!x86_64_immediate_operand (new_rtx, mode)) + new_rtx = force_reg (mode, new_rtx); + new_rtx + = gen_rtx_PLUS (mode, force_reg (mode, base), new_rtx); + } + else + new_rtx = plus_constant (mode, base, INTVAL (new_rtx)); + } else { - if (GET_CODE (new_rtx) == PLUS && CONSTANT_P (XEXP (new_rtx, 1))) + if (GET_CODE (new_rtx) == PLUS + && CONSTANT_P (XEXP (new_rtx, 1))) { - base = gen_rtx_PLUS (Pmode, base, XEXP (new_rtx, 0)); + base = gen_rtx_PLUS (mode, base, XEXP (new_rtx, 0)); new_rtx = XEXP (new_rtx, 1); } - new_rtx = gen_rtx_PLUS (Pmode, base, new_rtx); + new_rtx = gen_rtx_PLUS (mode, base, new_rtx); } } } @@ -14504,6 +14516,29 @@ ix86_print_operand_address (FILE *file, rtx addr) gcc_assert (!code); code = 'l'; } + else if (code == 0 + && TARGET_X32 + && disp + && CONST_INT_P (disp) + && INTVAL (disp) < -16*1024*1024) + { + /* X32 runs in 64-bit mode, where displacement, DISP, in + address DISP(%r64), is encoded as 32-bit immediate sign- + extended from 32-bit to 64-bit. For -0x40000300(%r64), + address is %r64 + 0xffffffffbffffd00. When %r64 < + 0x40000300, like 0x37ffe064, address is 0xfffffffff7ffdd64, + which is invalid for x32. The correct address is %r64 + - 0x40000300 == 0xf7ffdd64. To properly encode + -0x40000300(%r64) for x32, we zero-extend negative + displacement by forcing addr32 prefix which truncates + 0xfffffffff7ffdd64 to 0xf7ffdd64. In theory, we should + zero-extend all negative displacements, including -1(%rsp). + However, for small negative displacements, sign-extension + won't cause overflow. We only zero-extend negative + displacements if they < -16*1024*1024, which is also used + to check legitimate address displacements for PIC. */ + code = 'k'; + } if (ASSEMBLER_DIALECT == ASM_ATT) { diff --git a/gcc/testsuite/gcc.target/i386/pr55142-1.c b/gcc/testsuite/gcc.target/i386/pr55142-1.c new file mode 100644 index 0000000..e6b5f12 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/pr55142-1.c @@ -0,0 +1,35 @@ +/* { dg-do compile { target { ! { ia32 } } } } */ +/* { dg-require-effective-target maybe_x32 } */ +/* { dg-require-effective-target fpic } */ +/* { dg-options "-O2 -mx32 -maddress-mode=long -fpic" } */ + +typedef int int32_t; +typedef unsigned int uint32_t; +typedef int32_t Elf32_Sword; +typedef struct +{ + Elf32_Sword d_tag; +} Elf32_Dyn; +struct link_map +{ + Elf32_Dyn *l_ld; + Elf32_Dyn *l_info[34]; +}; +extern struct link_map _dl_rtld_map __attribute__ ((visibility ("hidden"))); +static void elf_get_dynamic_info (struct link_map *l) +{ + Elf32_Dyn *dyn = l->l_ld; + Elf32_Dyn **info; + info = l->l_info; + while (dyn->d_tag != 0) + { + if ((uint32_t) (0x6ffffeff - dyn->d_tag) < 11) + info[0x6ffffeff - dyn->d_tag + 12] = dyn; + ++dyn; + } +} +void +foo (void) +{ + elf_get_dynamic_info (&_dl_rtld_map); +} diff --git a/gcc/testsuite/gcc.target/i386/pr55142-2.c b/gcc/testsuite/gcc.target/i386/pr55142-2.c new file mode 100644 index 0000000..598c524 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/pr55142-2.c @@ -0,0 +1,34 @@ +/* { dg-do compile { target { ! { ia32 } } } } */ +/* { dg-require-effective-target maybe_x32 } */ +/* { dg-require-effective-target fpic } */ +/* { dg-options "-O3 -mx32 -maddress-mode=long -fpic" } */ +/* { dg-final { scan-assembler-not "movl\[\\t \]*%edx,\[\\t \]*-1073742592\\(%r(.x|.i|.p|\[1-9\]*)\\)" } } */ + +typedef int int32_t; +typedef unsigned int uint32_t; +typedef uint32_t Elf32_Word; +typedef int32_t Elf32_Sword; +typedef uint32_t Elf32_Addr; +typedef struct { + Elf32_Sword d_tag; + union { + Elf32_Word d_val; + Elf32_Addr d_ptr; + } d_un; +} Elf32_Dyn; +struct link_map { + Elf32_Dyn *l_ld; + Elf32_Dyn *l_info[34 + 16 + 3 + 12 + 11]; +}; +void +elf_get_dynamic_info (struct link_map *l) +{ + Elf32_Dyn *dyn = l->l_ld; + Elf32_Dyn **info = l->l_info; + typedef Elf32_Word d_tag_utype; + while (dyn->d_tag != 0) { + if ((d_tag_utype) (0x6ffffeff - dyn->d_tag) < 11) + info[(0x6ffffeff - dyn->d_tag) + 34 + 16 + 3 + 12] = dyn; + ++dyn; + } +}