From patchwork Tue Jul 24 19:32:57 2012 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Uros Bizjak X-Patchwork-Id: 173038 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 68C792C008F for ; Wed, 25 Jul 2012 05:33:16 +1000 (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=1343763198; 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=nJHX4f+ ljirzUXGrI61QeM1xWDk=; b=nbs0dbJxhshd12OXR2P+2w3L/u0tUX81k9W4Up+ 2Idy70FYO1kUv8D9w3CklDal3/HS/vyZ8uLDkilzVIxNjyVf/tc3Cu9daD/R/OoK x12zhEbG0VxXZ4nkALXqSUwMa9FsooDpq7yd9oQdunQO+O74QUiUD1EcR1ez+yWd c858= 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=Jvn40Wl/4nLx9QtglD8NRlBVKImBT5lo+oQueXyBBfS2wEGIjXkl6zE3iqn0bH vCbAyTXeYyP940MIISfPR6XwldHM95/OTIOh/EqCUS1GZmvIBcDkRZA/Se7oW+th LDm3UXGB59olY7yiEYeaHbm/S7KjI9I6KcX2FFWj28DcE=; Received: (qmail 28033 invoked by alias); 24 Jul 2012 19:33:14 -0000 Received: (qmail 28021 invoked by uid 22791); 24 Jul 2012 19:33:12 -0000 X-SWARE-Spam-Status: No, hits=-4.1 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_XF, TW_ZJ X-Spam-Check-By: sourceware.org Received: from mail-ob0-f175.google.com (HELO mail-ob0-f175.google.com) (209.85.214.175) by sourceware.org (qpsmtpd/0.43rc1) with ESMTP; Tue, 24 Jul 2012 19:32:58 +0000 Received: by obcva7 with SMTP id va7so13982957obc.20 for ; Tue, 24 Jul 2012 12:32:57 -0700 (PDT) MIME-Version: 1.0 Received: by 10.182.46.41 with SMTP id s9mr26577473obm.57.1343158377526; Tue, 24 Jul 2012 12:32:57 -0700 (PDT) Received: by 10.76.112.44 with HTTP; Tue, 24 Jul 2012 12:32:57 -0700 (PDT) Date: Tue, 24 Jul 2012 21:32:57 +0200 Message-ID: Subject: [4.7 RFT PATCH, i386]: Backport recent LEA improvements to 4.7 branch From: Uros Bizjak To: gcc-patches@gcc.gnu.org Cc: "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 patch backports recent LEA improvements to 4.7 branch. The patch unifies handling of LEA addresses with generic address handling, allowing some more zero-extended addresses for both cases. 2012-XX-XX Uros Bizjak Backport from mainline 2012-07-24 Uros Bizjak PR target/53961 * config/i386/i386.c (ix86_legitimate_address_p): Move check for negative constant address for TARGET_X32 ... (ix86_decompose_address): ... here. Reject constant addresses that don't satisfy x86_64_immediate_operand predicate. 2012-07-23 Uros Bizjak PR target/53961 * config/i386/i386.md (*lea): Add asserts to detect invalid addresses. * config/i386/i386.c (ix86_print_operand_address): Ditto. (ix86_decompose_address): Allow (zero_extend:DI (subreg:SI (...))) addresses. Prevent zero extensions of CONST_INT operands. 2012-07-22 Uros Bizjak PR target/53961 * config/i386/i386.md (*lea): New insn pattern. (*lea_1): Remove. (*lea_2): Ditto. (*lea_{3,4,5,6}_zext): Ditto. * config/i386/predicates.md (lea_address_operand): Do not reject zero-extended address operands. * config/i386/constraints.md (j): Remove address constraint. * config/i386/i386.c (ix86_decompose_address): Allow SImode subreg of an address. (ix86_print_operand_address): Handle SImode subreg of an address. (ix86_avoid_lea_for_addr): Reject zero-extended addresses for now. 2012-03-09 Uros Bizjak PR target/52530 * config/i386/i386.c (ix86_print_operand): Handle 'E' operand modifier. (ix86_print_operand_address): Handle UNSPEC_LEA_ADDR. Do not fallback to set code to 'q'. * config/i386/i386.md (UNSPEC_LEA_ADDR): New unspec. (*movdi_internal_rex64): Use %E operand modifier for lea. (*movsi_internal): Ditto. (*lea_1): Ditto. (*lea_2): Ditto. (*lea_{3,4,5,6}_zext): Ditto. (*tls_global_dynamic_32_gnu): Ditto. (*tls_global_dynamic_64): Ditto. (*tls_dynamic_gnu2_lea_32): Ditto. (*tls_dynamic_gnu2_lea_64): Ditto. (pro_epilogue_adjust_stack__add): Ditto. testsuite/ChangeLog: 2012-XX-XX Uros Bizjak Backport from mainline 2012-03-11 Uros Bizjak PR target/52530 * gcc.dg/torture/pr52530.c: New test. Patch was bootstrapped and regression tested on x86_64-pc-linux-gnu {,-m32} and various x32 compile tests. However, this patch needs further testing on a real x32 target and maybe SPEC 2000/2006 benchmark for x86_64, i686 and x32 target. On mainline, this patch works OK everywhere. Uros. Index: config/i386/i386.c =================================================================== --- config/i386/i386.c (revision 189815) +++ config/i386/i386.c (working copy) @@ -11421,19 +11421,44 @@ ix86_decompose_address (rtx addr, struct ix86_addr { if (GET_CODE (addr) == ZERO_EXTEND && GET_MODE (XEXP (addr, 0)) == SImode) - addr = XEXP (addr, 0); + { + addr = XEXP (addr, 0); + if (CONST_INT_P (addr)) + return 0; + } else if (GET_CODE (addr) == AND && const_32bit_mask (XEXP (addr, 1), DImode)) { addr = XEXP (addr, 0); - /* Strip subreg. */ + /* Adjust SUBREGs. */ if (GET_CODE (addr) == SUBREG && GET_MODE (SUBREG_REG (addr)) == SImode) - addr = SUBREG_REG (addr); + { + addr = SUBREG_REG (addr); + if (CONST_INT_P (addr)) + return 0; + } + else if (GET_MODE (addr) == DImode) + addr = gen_rtx_SUBREG (SImode, addr, 0); + else if (GET_MODE (addr) != VOIDmode) + return 0; } } + /* Allow SImode subregs of DImode addresses, + they will be emitted with addr32 prefix. */ + if (TARGET_64BIT && GET_MODE (addr) == SImode) + { + if (GET_CODE (addr) == SUBREG + && GET_MODE (SUBREG_REG (addr)) == DImode) + { + addr = SUBREG_REG (addr); + if (CONST_INT_P (addr)) + return 0; + } + } + if (REG_P (addr)) base = addr; else if (GET_CODE (addr) == SUBREG) @@ -11541,6 +11566,19 @@ ix86_decompose_address (rtx addr, struct ix86_addr scale = 1 << scale; retval = -1; } + else if (CONST_INT_P (addr)) + { + if (!x86_64_immediate_operand (addr, VOIDmode)) + return 0; + + /* Constant addresses are sign extended to 64bit, we have to + prevent addresses from 0x80000000 to 0xffffffff in x32 mode. */ + if (TARGET_X32 + && val_signbit_known_set_p (SImode, INTVAL (addr))) + return 0; + + disp = addr; + } else disp = addr; /* displacement */ @@ -12044,13 +12082,6 @@ ix86_legitimate_address_p (enum machine_mode mode rtx base, index, disp; HOST_WIDE_INT scale; - /* Since constant address in x32 is signed extended to 64bit, - we have to prevent addresses from 0x80000000 to 0xffffffff. */ - if (TARGET_X32 - && CONST_INT_P (addr) - && INTVAL (addr) < 0) - return false; - if (ix86_decompose_address (addr, &parts) <= 0) /* Decomposition failed. */ return false; @@ -13883,7 +13914,14 @@ ix86_print_operand (FILE *file, rtx x, int code) ix86_print_operand (file, x, 0); return; + case 'E': + /* Wrap address in an UNSPEC to declare special handling. */ + if (TARGET_64BIT) + x = gen_rtx_UNSPEC (DImode, gen_rtvec (1, x), UNSPEC_LEA_ADDR); + output_address (x); + return; + case 'L': if (ASSEMBLER_DIALECT == ASM_ATT) putc ('l', file); @@ -14488,6 +14526,7 @@ ix86_print_operand_address (FILE *file, rtx addr) int scale; int ok; bool vsib = false; + int code = 0; if (GET_CODE (addr) == UNSPEC && XINT (addr, 1) == UNSPEC_VSIBADDR) { @@ -14498,6 +14537,12 @@ ix86_print_operand_address (FILE *file, rtx addr) addr = XVECEXP (addr, 0, 0); vsib = true; } + else if (GET_CODE (addr) == UNSPEC && XINT (addr, 1) == UNSPEC_LEA_ADDR) + { + gcc_assert (TARGET_64BIT); + ok = ix86_decompose_address (XVECEXP (addr, 0, 0), &parts); + code = 'q'; + } else ok = ix86_decompose_address (addr, &parts); @@ -14568,16 +14613,24 @@ ix86_print_operand_address (FILE *file, rtx addr) } else { - int code = 0; + /* Print SImode register names to force addr32 prefix. */ + if (GET_CODE (addr) == SUBREG) + { + gcc_assert (TARGET_64BIT); + gcc_assert (GET_MODE (addr) == SImode); + gcc_assert (GET_MODE (SUBREG_REG (addr)) == DImode); + gcc_assert (!code); + code = 'l'; + } + else if (GET_CODE (addr) == ZERO_EXTEND + || GET_CODE (addr) == AND) + { + gcc_assert (TARGET_64BIT); + gcc_assert (GET_MODE (addr) == DImode); + gcc_assert (!code); + code = 'l'; + } - /* Print SImode registers for zero-extended addresses to force - addr32 prefix. Otherwise print DImode registers to avoid it. */ - if (TARGET_64BIT) - code = ((GET_CODE (addr) == ZERO_EXTEND - || GET_CODE (addr) == AND) - ? 'l' - : 'q'); - if (ASSEMBLER_DIALECT == ASM_ATT) { if (disp) @@ -16781,6 +16834,11 @@ ix86_avoid_lea_for_addr (rtx insn, rtx operands[]) struct ix86_address parts; int ok; + /* FIXME: Handle zero-extended addresses. */ + if (GET_CODE (operands[1]) == ZERO_EXTEND + || GET_CODE (operands[1]) == AND) + return false; + /* Check we need to optimize. */ if (!TARGET_OPT_AGU || optimize_function_for_size_p (cfun)) return false; Index: config/i386/predicates.md =================================================================== --- config/i386/predicates.md (revision 189815) +++ config/i386/predicates.md (working copy) @@ -817,11 +817,6 @@ struct ix86_address parts; int ok; - /* LEA handles zero-extend by itself. */ - if (GET_CODE (op) == ZERO_EXTEND - || GET_CODE (op) == AND) - return false; - ok = ix86_decompose_address (op, &parts); gcc_assert (ok); return parts.seg == SEG_DEFAULT; Index: config/i386/i386.md =================================================================== --- config/i386/i386.md (revision 189815) +++ config/i386/i386.md (working copy) @@ -107,6 +107,7 @@ UNSPEC_MS_TO_SYSV_CALL UNSPEC_CALL_NEEDS_VZEROUPPER UNSPEC_PAUSE + UNSPEC_LEA_ADDR ;; For SSE/MMX support: UNSPEC_FIX_NOTRUNC @@ -1956,7 +1957,7 @@ return "#"; case TYPE_LEA: - return "lea{q}\t{%a1, %0|%0, %a1}"; + return "lea{q}\t{%E1, %0|%0, %E1}"; default: gcc_assert (!flag_pic || LEGITIMATE_PIC_OPERAND_P (operands[1])); @@ -1965,7 +1966,7 @@ else if (which_alternative == 2) return "movabs{q}\t{%1, %0|%0, %1}"; else if (ix86_use_lea_for_mov (insn, operands)) - return "lea{q}\t{%a1, %0|%0, %a1}"; + return "lea{q}\t{%E1, %0|%0, %E1}"; else return "mov{q}\t{%1, %0|%0, %1}"; } @@ -2197,12 +2198,12 @@ return "movd\t{%1, %0|%0, %1}"; case TYPE_LEA: - return "lea{l}\t{%a1, %0|%0, %a1}"; + return "lea{l}\t{%E1, %0|%0, %E1}"; default: gcc_assert (!flag_pic || LEGITIMATE_PIC_OPERAND_P (operands[1])); if (ix86_use_lea_for_mov (insn, operands)) - return "lea{l}\t{%a1, %0|%0, %a1}"; + return "lea{l}\t{%E1, %0|%0, %E1}"; else return "mov{l}\t{%1, %0|%0, %1}"; } @@ -5373,6 +5374,41 @@ DONE; }) +;; Load effective address instructions + +(define_insn_and_split "*lea" + [(set (match_operand:SWI48 0 "register_operand" "=r") + (match_operand:SWI48 1 "lea_address_operand" "p"))] + "" +{ + rtx addr = operands[1]; + + if (GET_CODE (addr) == SUBREG) + { + gcc_assert (TARGET_64BIT); + gcc_assert (mode == SImode); + gcc_assert (GET_MODE (SUBREG_REG (addr)) == DImode); + return "lea{l}\t{%E1, %0|%0, %E1}"; + } + else if (GET_CODE (addr) == ZERO_EXTEND + || GET_CODE (addr) == AND) + { + gcc_assert (TARGET_64BIT); + gcc_assert (mode == DImode); + return "lea{l}\t{%E1, %k0|%k0, %E1}"; + } + else + return "lea{}\t{%E1, %0|%0, %E1}"; +} + "reload_completed && ix86_avoid_lea_for_addr (insn, operands)" + [(const_int 0)] +{ + ix86_split_lea_for_addr (operands, mode); + DONE; +} + [(set_attr "type" "lea") + (set_attr "mode" "")]) + ;; Add instructions (define_expand "add3" @@ -5431,72 +5467,6 @@ [(set_attr "type" "alu") (set_attr "mode" "QI")]) -(define_insn_and_split "*lea_1" - [(set (match_operand:SI 0 "register_operand" "=r") - (subreg:SI (match_operand:DI 1 "lea_address_operand" "p") 0))] - "TARGET_64BIT" - "lea{l}\t{%a1, %0|%0, %a1}" - "&& reload_completed && ix86_avoid_lea_for_addr (insn, operands)" - [(const_int 0)] -{ - ix86_split_lea_for_addr (operands, SImode); - DONE; -} - [(set_attr "type" "lea") - (set_attr "mode" "SI")]) - -(define_insn_and_split "*lea_2" - [(set (match_operand:SWI48 0 "register_operand" "=r") - (match_operand:SWI48 1 "lea_address_operand" "p"))] - "" - "lea{}\t{%a1, %0|%0, %a1}" - "reload_completed && ix86_avoid_lea_for_addr (insn, operands)" - [(const_int 0)] -{ - ix86_split_lea_for_addr (operands, mode); - DONE; -} - [(set_attr "type" "lea") - (set_attr "mode" "")]) - -(define_insn "*lea_3_zext" - [(set (match_operand:DI 0 "register_operand" "=r") - (zero_extend:DI - (subreg:SI (match_operand:DI 1 "lea_address_operand" "j") 0)))] - "TARGET_64BIT" - "lea{l}\t{%a1, %k0|%k0, %a1}" - [(set_attr "type" "lea") - (set_attr "mode" "SI")]) - -(define_insn "*lea_4_zext" - [(set (match_operand:DI 0 "register_operand" "=r") - (zero_extend:DI - (match_operand:SI 1 "lea_address_operand" "j")))] - "TARGET_64BIT" - "lea{l}\t{%a1, %k0|%k0, %a1}" - [(set_attr "type" "lea") - (set_attr "mode" "SI")]) - -(define_insn "*lea_5_zext" - [(set (match_operand:DI 0 "register_operand" "=r") - (and:DI - (subreg:DI (match_operand:SI 1 "lea_address_operand" "p") 0) - (match_operand:DI 2 "const_32bit_mask" "n")))] - "TARGET_64BIT" - "lea{l}\t{%a1, %k0|%k0, %a1}" - [(set_attr "type" "lea") - (set_attr "mode" "SI")]) - -(define_insn "*lea_6_zext" - [(set (match_operand:DI 0 "register_operand" "=r") - (and:DI - (match_operand:DI 1 "lea_address_operand" "p") - (match_operand:DI 2 "const_32bit_mask" "n")))] - "TARGET_64BIT" - "lea{l}\t{%a1, %k0|%k0, %a1}" - [(set_attr "type" "lea") - (set_attr "mode" "SI")]) - (define_insn "*add_1" [(set (match_operand:SWI48 0 "nonimmediate_operand" "=r,rm,r,r") (plus:SWI48 @@ -12597,7 +12567,7 @@ "!TARGET_64BIT && TARGET_GNU_TLS" { output_asm_insn - ("lea{l}\t{%a2@tlsgd(,%1,1), %0|%0, %a2@tlsgd[%1*1]}", operands); + ("lea{l}\t{%E2@tlsgd(,%1,1), %0|%0, %E2@tlsgd[%1*1]}", operands); if (TARGET_SUN_TLS) #ifdef HAVE_AS_IX86_TLSGDPLT return "call\t%a2@tlsgdplt"; @@ -12632,7 +12602,7 @@ if (!TARGET_X32) fputs (ASM_BYTE "0x66\n", asm_out_file); output_asm_insn - ("lea{q}\t{%a1@tlsgd(%%rip), %%rdi|rdi, %a1@tlsgd[rip]}", operands); + ("lea{q}\t{%E1@tlsgd(%%rip), %%rdi|rdi, %E1@tlsgd[rip]}", operands); fputs (ASM_SHORT "0x6666\n", asm_out_file); fputs ("\trex64\n", asm_out_file); if (TARGET_SUN_TLS) @@ -12858,7 +12828,7 @@ (unspec:SI [(match_operand:SI 2 "tls_symbolic_operand" "")] UNSPEC_TLSDESC))))] "!TARGET_64BIT && TARGET_GNU2_TLS" - "lea{l}\t{%a2@TLSDESC(%1), %0|%0, %a2@TLSDESC[%1]}" + "lea{l}\t{%E2@TLSDESC(%1), %0|%0, %E2@TLSDESC[%1]}" [(set_attr "type" "lea") (set_attr "mode" "SI") (set_attr "length" "6") @@ -12920,7 +12890,7 @@ (unspec:DI [(match_operand 1 "tls_symbolic_operand" "")] UNSPEC_TLSDESC))] "TARGET_64BIT && TARGET_GNU2_TLS" - "lea{q}\t{%a1@TLSDESC(%%rip), %0|%0, %a1@TLSDESC[rip]}" + "lea{q}\t{%E1@TLSDESC(%%rip), %0|%0, %E1@TLSDESC[rip]}" [(set_attr "type" "lea") (set_attr "mode" "DI") (set_attr "length" "7") @@ -16675,7 +16645,7 @@ default: operands[2] = SET_SRC (XVECEXP (PATTERN (insn), 0, 0)); - return "lea{}\t{%a2, %0|%0, %a2}"; + return "lea{}\t{%E2, %0|%0, %E2}"; } } [(set (attr "type") Index: config/i386/constraints.md =================================================================== --- config/i386/constraints.md (revision 189815) +++ config/i386/constraints.md (working copy) @@ -19,7 +19,7 @@ ;;; Unused letters: ;;; B H T W -;;; h k v +;;; h jk v ;; Integer register constraints. ;; It is not necessary to define 'r' here. @@ -127,11 +127,6 @@ (and (not (match_test "TARGET_X32")) (match_operand 0 "memory_operand"))) -(define_address_constraint "j" - "@internal Address operand that can be zero extended in LEA instruction." - (and (not (match_code "const_int")) - (match_operand 0 "address_operand"))) - ;; Integer constant constraints. (define_constraint "I" "Integer constant in the range 0 @dots{} 31, for 32-bit shifts." Index: testsuite/gcc.dg/pr52530.c =================================================================== --- testsuite/gcc.dg/pr52530.c (revision 0) +++ testsuite/gcc.dg/pr52530.c (working copy) @@ -0,0 +1,40 @@ +/* { dg-do run } */ + +extern void abort (void); + +#if __SIZEOF_INT__ > 2 +struct foo +{ + int *f; + int i; +}; + +int baz; +#else +struct foo +{ + long *f; + long i; +}; + +long baz; +#endif + +void __attribute__ ((noinline)) +bar (struct foo x) +{ + *(x.f) = x.i; +} + +int +main () +{ + struct foo x = { &baz, 0xdeadbeef }; + + bar (x); + + if (baz != 0xdeadbeef) + abort (); + + return 0; +}