From patchwork Tue Jul 26 12:03:49 2011 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Uros Bizjak X-Patchwork-Id: 106843 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 5D7ACB70B1 for ; Tue, 26 Jul 2011 22:04:15 +1000 (EST) Received: (qmail 9568 invoked by alias); 26 Jul 2011 12:04:13 -0000 Received: (qmail 9555 invoked by uid 22791); 26 Jul 2011 12:04:08 -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 X-Spam-Check-By: sourceware.org Received: from mail-yi0-f47.google.com (HELO mail-yi0-f47.google.com) (209.85.218.47) by sourceware.org (qpsmtpd/0.43rc1) with ESMTP; Tue, 26 Jul 2011 12:03:50 +0000 Received: by yib18 with SMTP id 18so196765yib.20 for ; Tue, 26 Jul 2011 05:03:50 -0700 (PDT) MIME-Version: 1.0 Received: by 10.68.27.168 with SMTP id u8mr2755114pbg.447.1311681829220; Tue, 26 Jul 2011 05:03:49 -0700 (PDT) Received: by 10.143.34.2 with HTTP; Tue, 26 Jul 2011 05:03:49 -0700 (PDT) In-Reply-To: References: Date: Tue, 26 Jul 2011 14:03:49 +0200 Message-ID: Subject: Re: [PATCH, i386, take 2]: Rewrite LEA handling (was:Re: PATCH [10/n] X32: Support x32 LEA insns) From: Uros Bizjak To: "H.J. Lu" Cc: gcc-patches@gcc.gnu.org, Richard Henderson , jh@suse.cz 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 Mon, Jul 25, 2011 at 11:09 PM, Uros Bizjak wrote: >>>>> Attached patch implements -fpic handling for x32. In x32 mode, we now >>>>> use x86_64_general_operand and corresponding "e" constraints for adds >>>>> in SImode, since it looks that invalid addresses can only be generated >>>>> through adds. This avoids a whole bunch of new predicates and >>>>> constraints. >>> >>>> X32 glibc is miscompiled: >>>> >>>> CPP='/export/build/gnu/gcc-x32/release/usr/gcc-4.7.0-x32/bin/gcc -mx32 >>>>  -E -x c-header' >>>> /export/build/gnu/glibc-x32/build-x86_64-linux/elf/ld-linux-x32.so.2 >>>> --library-path /export/build/gnu/glibc-x32/build-x86_64-linux:/export/build/gnu/glibc-x32/build-x86_64-linux/math:/export/build/gnu/glibc-x32/build-x86_64-linux/elf:/export/build/gnu/glibc-x32/build-x86_64-linux/dlfcn:/export/build/gnu/glibc-x32/build-x86_64-linux/nss:/export/build/gnu/glibc-x32/build-x86_64-linux/nis:/export/build/gnu/glibc-x32/build-x86_64-linux/rt:/export/build/gnu/glibc-x32/build-x86_64-linux/resolv:/export/build/gnu/glibc-x32/build-x86_64-linux/crypt:/export/build/gnu/glibc-x32/build-x86_64-linux/nptl >>>> /export/build/gnu/glibc-x32/build-x86_64-linux/sunrpc/rpcgen -Y >>>> ../scripts -h rpcsvc/yppasswd.x -o >>>> /export/build/gnu/glibc-x32/build-x86_64-linux/sunrpc/rpcsvc/yppasswd.T >>>> make[5]: *** [/export/build/gnu/glibc-x32/build-x86_64-linux/sunrpc/rpcsvc/yppasswd.stmp] >>>> Segmentation fault (core dumped) >>>> >>>> Some LEA patterns are wrong for x32.  I will investigate. >>> >>> We have to prevent symbols from entering general_operand predicated >>> SImode operands. Fortunatelly, x86_64_general_operand works OK for >>> x32, while both for i686 and x86_64 are unaffected due to early bypass >>> (i686) and due to the fact that all symbols are DImode (x86_64). > >> GCC and glibc testsuites are clean on x32.  Can you check it in? > > I will do this tomorrow, if anybody has some comment on the patch. Committed slightly updated version: 2011-07-26 Uros Bizjak H.J. Lu PR target/47381 PR target/49832 PR target/49833 * config/i386/i386.md (i): Change SImode attribute to "e". (g): Change SImode attribute to "rme". (di): Change SImode attribute to "nF". (general_operand): Change SImode attribute to x86_64_general_operand. (general_szext_operand): Change SImode attribute to x86_64_szext_general_operand. (immediate_operand): Change SImode attribute to x86_64_immediate_operand. (nonmemory_operand): Change SImode attribute to x86_64_nonmemory_operand. (*movdi_internal_rex64): Remove mode from pic_32bit_operand check. (*movsi_internal): Ditto. Use "e" constraint in alternative 2. (*lea_1): Use SWI48 mode iterator. (*lea_1_zext): New insn pattern. (testsi_ccno_1): Use x86_64_nonmemory_operand predicate for operand 2. (*bt): Ditto. (*add1): Use x86_64_general_operand predicate for operand 2. Update operand constraints. (addsi_1_zext): Ditto. (*add2): Ditto. (*addsi_3_zext): Ditto. (*subsi_1_zext): Ditto. (*subsi_2_zext): Ditto. (*subsi_3_zext): Ditto. (*addsi3_carry_zext): Ditto. (*si3_zext_cc_overflow): Ditto. (*mulsi3_1_zext): Ditto. (*andsi_1): Ditto. (*andsi_1_zext): Ditto. (*andsi_2_zext): Ditto. (*si_1_zext): Ditto. (*si_2_zext): Ditto. (*test_1): Use predicate for operand 1. (*and_2): Ditto. (movcc): Use predicate for operands 1 and 2. (add->lea splitter): Check operand modes in insn constraint. Extend operands less than SImode wide to SImode. (add->lea zext splitter): Do not extend input operands to DImode. (*lea_general_1): Handle only QImode and HImode operands. (*lea_general_2): Ditto. (*lea_general_3): Ditto. (*lea_general_1_zext): Remove. (*lea_general_2_zext): Ditto. (*lea_general_3_zext): Ditto. (*lea_general_4): Check operand modes in insn constraint. Extend operands less than SImode wide to SImode. (ashift->lea splitter): Ditto. * config/i386/i386.c (ix86_print_operand_address): Print address registers with 'q' modifier on 64bit targets. * config/i386/predicates.md (pic_32bit_opreand): Define as special predicate. Reject non-SI and non-DI modes. Tested on x86_64-pc-linux-gnu {,-m32}, committed to mainline SVN. Uros. Index: i386.md =================================================================== --- i386.md (revision 176782) +++ i386.md (working copy) @@ -861,13 +861,13 @@ (define_mode_attr r [(QI "q") (HI "r") (SI "r") (DI "r")]) ;; Immediate operand constraint for integer modes. -(define_mode_attr i [(QI "n") (HI "n") (SI "i") (DI "e")]) +(define_mode_attr i [(QI "n") (HI "n") (SI "e") (DI "e")]) ;; General operand constraint for word modes. -(define_mode_attr g [(QI "qmn") (HI "rmn") (SI "g") (DI "rme")]) +(define_mode_attr g [(QI "qmn") (HI "rmn") (SI "rme") (DI "rme")]) ;; Immediate operand constraint for double integer modes. -(define_mode_attr di [(SI "iF") (DI "e")]) +(define_mode_attr di [(SI "nF") (DI "e")]) ;; Immediate operand constraint for shifts. (define_mode_attr S [(QI "I") (HI "I") (SI "I") (DI "J") (TI "O")]) @@ -876,7 +876,7 @@ (define_mode_attr general_operand [(QI "general_operand") (HI "general_operand") - (SI "general_operand") + (SI "x86_64_general_operand") (DI "x86_64_general_operand") (TI "x86_64_general_operand")]) @@ -884,21 +884,21 @@ (define_mode_attr general_szext_operand [(QI "general_operand") (HI "general_operand") - (SI "general_operand") + (SI "x86_64_szext_general_operand") (DI "x86_64_szext_general_operand")]) ;; Immediate operand predicate for integer modes. (define_mode_attr immediate_operand [(QI "immediate_operand") (HI "immediate_operand") - (SI "immediate_operand") + (SI "x86_64_immediate_operand") (DI "x86_64_immediate_operand")]) ;; Nonmemory operand predicate for integer modes. (define_mode_attr nonmemory_operand [(QI "nonmemory_operand") (HI "nonmemory_operand") - (SI "nonmemory_operand") + (SI "x86_64_nonmemory_operand") (DI "x86_64_nonmemory_operand")]) ;; Operand predicate for shifts. @@ -2039,7 +2039,7 @@ (const_string "ssemov") (eq_attr "alternative" "16,17") (const_string "ssecvt") - (match_operand:DI 1 "pic_32bit_operand" "") + (match_operand 1 "pic_32bit_operand" "") (const_string "lea") ] (const_string "imov"))) @@ -2184,7 +2184,7 @@ [(set (match_operand:SI 0 "nonimmediate_operand" "=r,m ,*y,*y,?rm,?*y,*x,*x,?r ,m ,?*Yi,*x") (match_operand:SI 1 "general_operand" - "g ,ri,C ,*y,*y ,rm ,C ,*x,*Yi,*x,r ,m "))] + "g ,re,C ,*y,*y ,rm ,C ,*x,*Yi,*x,r ,m "))] "!(MEM_P (operands[0]) && MEM_P (operands[1]))" { switch (get_attr_type (insn)) @@ -2232,7 +2232,7 @@ (const_string "sselog1") (eq_attr "alternative" "7,8,9,10,11") (const_string "ssemov") - (match_operand:DI 1 "pic_32bit_operand" "") + (match_operand 1 "pic_32bit_operand" "") (const_string "lea") ] (const_string "imov"))) @@ -5425,13 +5425,22 @@ (set_attr "mode" "QI")]) (define_insn "*lea_1" - [(set (match_operand:P 0 "register_operand" "=r") - (match_operand:P 1 "no_seg_address_operand" "p"))] + [(set (match_operand:SWI48 0 "register_operand" "=r") + (match_operand:SWI48 1 "no_seg_address_operand" "p"))] "" "lea{}\t{%a1, %0|%0, %a1}" [(set_attr "type" "lea") (set_attr "mode" "")]) +(define_insn "*lea_1_zext" + [(set (match_operand:DI 0 "register_operand" "=r") + (zero_extend:DI + (match_operand:SI 1 "no_seg_address_operand" "p")))] + "TARGET_64BIT" + "lea{l}\t{%a1, %k0|%k0, %a1}" + [(set_attr "type" "lea") + (set_attr "mode" "SI")]) + (define_insn "*lea_2" [(set (match_operand:SI 0 "register_operand" "=r") (subreg:SI (match_operand:DI 1 "no_seg_address_operand" "p") 0))] @@ -5453,7 +5462,7 @@ [(set (match_operand:SWI48 0 "nonimmediate_operand" "=r,rm,r,r") (plus:SWI48 (match_operand:SWI48 1 "nonimmediate_operand" "%0,0,r,r") - (match_operand:SWI48 2 "" ",r,0,l"))) + (match_operand:SWI48 2 "x86_64_general_operand" "rme,re,0,le"))) (clobber (reg:CC FLAGS_REG))] "ix86_binary_operator_ok (PLUS, mode, operands)" { @@ -5512,7 +5521,7 @@ [(set (match_operand:DI 0 "register_operand" "=r,r,r") (zero_extend:DI (plus:SI (match_operand:SI 1 "nonimmediate_operand" "%0,r,r") - (match_operand:SI 2 "general_operand" "g,0,li")))) + (match_operand:SI 2 "x86_64_general_operand" "rme,0,le")))) (clobber (reg:CC FLAGS_REG))] "TARGET_64BIT && ix86_binary_operator_ok (PLUS, SImode, operands)" { @@ -5794,39 +5803,36 @@ (const_string "none"))) (set_attr "mode" "QI")]) -;; Convert lea to the lea pattern to avoid flags dependency. +;; Convert add to the lea pattern to avoid flags dependency. (define_split [(set (match_operand 0 "register_operand" "") (plus (match_operand 1 "register_operand" "") (match_operand 2 "nonmemory_operand" ""))) (clobber (reg:CC FLAGS_REG))] - "reload_completed && ix86_lea_for_add_ok (insn, operands)" + "GET_MODE (operands[0]) == GET_MODE (operands[1]) + && (GET_MODE (operands[0]) == GET_MODE (operands[2]) + || GET_MODE (operands[2]) == VOIDmode) + && reload_completed && ix86_lea_for_add_ok (insn, operands)" [(const_int 0)] { - rtx pat; enum machine_mode mode = GET_MODE (operands[0]); - - /* In -fPIC mode the constructs like (const (unspec [symbol_ref])) - may confuse gen_lowpart. */ - if (mode != Pmode) - { - operands[1] = gen_lowpart (Pmode, operands[1]); - operands[2] = gen_lowpart (Pmode, operands[2]); - } - - pat = gen_rtx_PLUS (Pmode, operands[1], operands[2]); + rtx pat; if (GET_MODE_SIZE (mode) < GET_MODE_SIZE (SImode)) - operands[0] = gen_lowpart (SImode, operands[0]); + { + mode = SImode; + operands[0] = gen_lowpart (mode, operands[0]); + operands[1] = gen_lowpart (mode, operands[1]); + operands[2] = gen_lowpart (mode, operands[2]); + } - if (TARGET_64BIT && mode != Pmode) - pat = gen_rtx_SUBREG (SImode, pat, 0); + pat = gen_rtx_PLUS (mode, operands[1], operands[2]); emit_insn (gen_rtx_SET (VOIDmode, operands[0], pat)); DONE; }) -;; Convert lea to the lea pattern to avoid flags dependency. +;; Convert add to the lea pattern to avoid flags dependency. ;; ??? This pattern handles immediate operands that do not satisfy immediate ;; operand predicate (TARGET_LEGITIMATE_CONSTANT_P) in the previous pattern. (define_split @@ -5839,7 +5845,7 @@ [(set (match_dup 0) (plus:DI (match_dup 1) (match_dup 2)))]) -;; Convert lea to the lea pattern to avoid flags dependency. +;; Convert add to the lea pattern to avoid flags dependency. (define_split [(set (match_operand:DI 0 "register_operand" "") (zero_extend:DI @@ -5849,11 +5855,7 @@ "TARGET_64BIT && reload_completed && ix86_lea_for_add_ok (insn, operands)" [(set (match_dup 0) - (zero_extend:DI (subreg:SI (plus:DI (match_dup 1) (match_dup 2)) 0)))] -{ - operands[1] = gen_lowpart (DImode, operands[1]); - operands[2] = gen_lowpart (DImode, operands[2]); -}) + (zero_extend:DI (plus:SI (match_dup 1) (match_dup 2))))]) (define_insn "*add_2" [(set (reg FLAGS_REG) @@ -5901,7 +5903,7 @@ [(set (reg FLAGS_REG) (compare (plus:SI (match_operand:SI 1 "nonimmediate_operand" "%0") - (match_operand:SI 2 "general_operand" "g")) + (match_operand:SI 2 "x86_64_general_operand" "rme")) (const_int 0))) (set (match_operand:DI 0 "register_operand" "=r") (zero_extend:DI (plus:SI (match_dup 1) (match_dup 2))))] @@ -5979,7 +5981,7 @@ (define_insn "*addsi_3_zext" [(set (reg FLAGS_REG) (compare - (neg:SI (match_operand:SI 2 "general_operand" "g")) + (neg:SI (match_operand:SI 2 "x86_64_general_operand" "rme")) (match_operand:SI 1 "nonimmediate_operand" "%0"))) (set (match_operand:DI 0 "register_operand" "=r") (zero_extend:DI (plus:SI (match_dup 1) (match_dup 2))))] @@ -6233,7 +6235,7 @@ [(set_attr "type" "alu") (set_attr "mode" "QI")]) -;; The lea patterns for non-Pmodes needs to be matched by +;; The lea patterns for modes less than 32 bits need to be matched by ;; several insns converted to real lea by splitters. (define_insn_and_split "*lea_general_1" @@ -6241,8 +6243,7 @@ (plus (plus (match_operand 1 "index_register_operand" "l") (match_operand 2 "register_operand" "r")) (match_operand 3 "immediate_operand" "i")))] - "(GET_MODE (operands[0]) == QImode || GET_MODE (operands[0]) == HImode - || (TARGET_64BIT && GET_MODE (operands[0]) == SImode)) + "(GET_MODE (operands[0]) == QImode || GET_MODE (operands[0]) == HImode) && (!TARGET_PARTIAL_REG_STALL || optimize_function_for_size_p (cfun)) && GET_MODE (operands[0]) == GET_MODE (operands[1]) && GET_MODE (operands[0]) == GET_MODE (operands[2]) @@ -6252,53 +6253,30 @@ "&& reload_completed" [(const_int 0)] { + enum machine_mode mode = SImode; rtx pat; - operands[0] = gen_lowpart (SImode, operands[0]); - operands[1] = gen_lowpart (Pmode, operands[1]); - operands[2] = gen_lowpart (Pmode, operands[2]); - operands[3] = gen_lowpart (Pmode, operands[3]); - pat = gen_rtx_PLUS (Pmode, gen_rtx_PLUS (Pmode, operands[1], operands[2]), + + operands[0] = gen_lowpart (mode, operands[0]); + operands[1] = gen_lowpart (mode, operands[1]); + operands[2] = gen_lowpart (mode, operands[2]); + operands[3] = gen_lowpart (mode, operands[3]); + + pat = gen_rtx_PLUS (mode, gen_rtx_PLUS (mode, operands[1], operands[2]), operands[3]); - if (Pmode != SImode) - pat = gen_rtx_SUBREG (SImode, pat, 0); + emit_insn (gen_rtx_SET (VOIDmode, operands[0], pat)); DONE; } [(set_attr "type" "lea") (set_attr "mode" "SI")]) -(define_insn_and_split "*lea_general_1_zext" - [(set (match_operand:DI 0 "register_operand" "=r") - (zero_extend:DI - (plus:SI (plus:SI - (match_operand:SI 1 "index_register_operand" "l") - (match_operand:SI 2 "register_operand" "r")) - (match_operand:SI 3 "immediate_operand" "i"))))] - "TARGET_64BIT" - "#" - "&& reload_completed" - [(set (match_dup 0) - (zero_extend:DI (subreg:SI (plus:DI (plus:DI (match_dup 1) - (match_dup 2)) - (match_dup 3)) 0)))] -{ - operands[1] = gen_lowpart (Pmode, operands[1]); - operands[2] = gen_lowpart (Pmode, operands[2]); - operands[3] = gen_lowpart (Pmode, operands[3]); -} - [(set_attr "type" "lea") - (set_attr "mode" "SI")]) - (define_insn_and_split "*lea_general_2" [(set (match_operand 0 "register_operand" "=r") (plus (mult (match_operand 1 "index_register_operand" "l") - (match_operand 2 "const248_operand" "i")) + (match_operand 2 "const248_operand" "n")) (match_operand 3 "nonmemory_operand" "ri")))] - "(GET_MODE (operands[0]) == QImode || GET_MODE (operands[0]) == HImode - || (TARGET_64BIT && GET_MODE (operands[0]) == SImode)) - && (!TARGET_PARTIAL_REG_STALL - || GET_MODE (operands[0]) == SImode - || optimize_function_for_size_p (cfun)) + "(GET_MODE (operands[0]) == QImode || GET_MODE (operands[0]) == HImode) + && (!TARGET_PARTIAL_REG_STALL || optimize_function_for_size_p (cfun)) && GET_MODE (operands[0]) == GET_MODE (operands[1]) && (GET_MODE (operands[0]) == GET_MODE (operands[3]) || GET_MODE (operands[3]) == VOIDmode)" @@ -6306,110 +6284,68 @@ "&& reload_completed" [(const_int 0)] { + enum machine_mode mode = SImode; rtx pat; - operands[0] = gen_lowpart (SImode, operands[0]); - operands[1] = gen_lowpart (Pmode, operands[1]); - operands[3] = gen_lowpart (Pmode, operands[3]); - pat = gen_rtx_PLUS (Pmode, gen_rtx_MULT (Pmode, operands[1], operands[2]), - operands[3]); - if (Pmode != SImode) - pat = gen_rtx_SUBREG (SImode, pat, 0); + + operands[0] = gen_lowpart (mode, operands[0]); + operands[1] = gen_lowpart (mode, operands[1]); + operands[3] = gen_lowpart (mode, operands[3]); + + pat = gen_rtx_PLUS (mode, gen_rtx_MULT (mode, operands[1], operands[2]), + operands[3]); + emit_insn (gen_rtx_SET (VOIDmode, operands[0], pat)); DONE; } [(set_attr "type" "lea") (set_attr "mode" "SI")]) -(define_insn_and_split "*lea_general_2_zext" - [(set (match_operand:DI 0 "register_operand" "=r") - (zero_extend:DI - (plus:SI (mult:SI - (match_operand:SI 1 "index_register_operand" "l") - (match_operand:SI 2 "const248_operand" "n")) - (match_operand:SI 3 "nonmemory_operand" "ri"))))] - "TARGET_64BIT" - "#" - "&& reload_completed" - [(set (match_dup 0) - (zero_extend:DI (subreg:SI (plus:DI (mult:DI (match_dup 1) - (match_dup 2)) - (match_dup 3)) 0)))] -{ - operands[1] = gen_lowpart (Pmode, operands[1]); - operands[3] = gen_lowpart (Pmode, operands[3]); -} - [(set_attr "type" "lea") - (set_attr "mode" "SI")]) - (define_insn_and_split "*lea_general_3" [(set (match_operand 0 "register_operand" "=r") (plus (plus (mult (match_operand 1 "index_register_operand" "l") - (match_operand 2 "const248_operand" "i")) + (match_operand 2 "const248_operand" "n")) (match_operand 3 "register_operand" "r")) (match_operand 4 "immediate_operand" "i")))] - "(GET_MODE (operands[0]) == QImode || GET_MODE (operands[0]) == HImode - || (TARGET_64BIT && GET_MODE (operands[0]) == SImode)) - && (!TARGET_PARTIAL_REG_STALL - || GET_MODE (operands[0]) == SImode - || optimize_function_for_size_p (cfun)) + "(GET_MODE (operands[0]) == QImode || GET_MODE (operands[0]) == HImode) + && (!TARGET_PARTIAL_REG_STALL || optimize_function_for_size_p (cfun)) && GET_MODE (operands[0]) == GET_MODE (operands[1]) && GET_MODE (operands[0]) == GET_MODE (operands[3])" "#" "&& reload_completed" [(const_int 0)] { + enum machine_mode mode = SImode; rtx pat; - operands[0] = gen_lowpart (SImode, operands[0]); - operands[1] = gen_lowpart (Pmode, operands[1]); - operands[3] = gen_lowpart (Pmode, operands[3]); - operands[4] = gen_lowpart (Pmode, operands[4]); - pat = gen_rtx_PLUS (Pmode, - gen_rtx_PLUS (Pmode, gen_rtx_MULT (Pmode, operands[1], - operands[2]), + + operands[0] = gen_lowpart (mode, operands[0]); + operands[1] = gen_lowpart (mode, operands[1]); + operands[3] = gen_lowpart (mode, operands[3]); + operands[4] = gen_lowpart (mode, operands[4]); + + pat = gen_rtx_PLUS (mode, + gen_rtx_PLUS (mode, + gen_rtx_MULT (mode, operands[1], + operands[2]), operands[3]), operands[4]); - if (Pmode != SImode) - pat = gen_rtx_SUBREG (SImode, pat, 0); + emit_insn (gen_rtx_SET (VOIDmode, operands[0], pat)); DONE; } [(set_attr "type" "lea") (set_attr "mode" "SI")]) -(define_insn_and_split "*lea_general_3_zext" - [(set (match_operand:DI 0 "register_operand" "=r") - (zero_extend:DI - (plus:SI (plus:SI - (mult:SI - (match_operand:SI 1 "index_register_operand" "l") - (match_operand:SI 2 "const248_operand" "n")) - (match_operand:SI 3 "register_operand" "r")) - (match_operand:SI 4 "immediate_operand" "i"))))] - "TARGET_64BIT" - "#" - "&& reload_completed" - [(set (match_dup 0) - (zero_extend:DI (subreg:SI (plus:DI (plus:DI (mult:DI (match_dup 1) - (match_dup 2)) - (match_dup 3)) - (match_dup 4)) 0)))] -{ - operands[1] = gen_lowpart (Pmode, operands[1]); - operands[3] = gen_lowpart (Pmode, operands[3]); - operands[4] = gen_lowpart (Pmode, operands[4]); -} - [(set_attr "type" "lea") - (set_attr "mode" "SI")]) - (define_insn_and_split "*lea_general_4" - [(set (match_operand:SWI 0 "register_operand" "=r") - (any_or:SWI (ashift:SWI (match_operand:SWI 1 "index_register_operand" "l") - (match_operand:SWI 2 "const_int_operand" "n")) - (match_operand 3 "const_int_operand" "n")))] - "(mode == DImode - || mode == SImode - || !TARGET_PARTIAL_REG_STALL - || optimize_function_for_size_p (cfun)) + [(set (match_operand 0 "register_operand" "=r") + (any_or (ashift + (match_operand 1 "index_register_operand" "l") + (match_operand 2 "const_int_operand" "n")) + (match_operand 3 "const_int_operand" "n")))] + "(((GET_MODE (operands[0]) == QImode || GET_MODE (operands[0]) == HImode) + && (!TARGET_PARTIAL_REG_STALL || optimize_function_for_size_p (cfun))) + || GET_MODE (operands[0]) == SImode + || (TARGET_64BIT && GET_MODE (operands[0]) == DImode)) + && GET_MODE (operands[0]) == GET_MODE (operands[1]) && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) - 1 < 3 && ((unsigned HOST_WIDE_INT) INTVAL (operands[3]) < ((unsigned HOST_WIDE_INT) 1 << INTVAL (operands[2])))" @@ -6417,23 +6353,29 @@ "&& reload_completed" [(const_int 0)] { + enum machine_mode mode = GET_MODE (operands[0]); rtx pat; - if (mode != DImode) - operands[0] = gen_lowpart (SImode, operands[0]); - operands[1] = gen_lowpart (Pmode, operands[1]); + + if (GET_MODE_SIZE (mode) < GET_MODE_SIZE (SImode)) + { + mode = SImode; + operands[0] = gen_lowpart (mode, operands[0]); + operands[1] = gen_lowpart (mode, operands[1]); + } + operands[2] = GEN_INT (1 << INTVAL (operands[2])); - pat = plus_constant (gen_rtx_MULT (Pmode, operands[1], operands[2]), + + pat = plus_constant (gen_rtx_MULT (mode, operands[1], operands[2]), INTVAL (operands[3])); - if (Pmode != SImode && mode != DImode) - pat = gen_rtx_SUBREG (SImode, pat, 0); + emit_insn (gen_rtx_SET (VOIDmode, operands[0], pat)); DONE; } [(set_attr "type" "lea") (set (attr "mode") - (if_then_else (eq (symbol_ref "mode == DImode") (const_int 0)) - (const_string "SI") - (const_string "DI")))]) + (if_then_else (match_operand:DI 0 "" "") + (const_string "DI") + (const_string "SI")))]) ;; Subtract instructions @@ -6481,7 +6423,7 @@ [(set (match_operand:DI 0 "register_operand" "=r") (zero_extend:DI (minus:SI (match_operand:SI 1 "register_operand" "0") - (match_operand:SI 2 "general_operand" "g")))) + (match_operand:SI 2 "x86_64_general_operand" "rme")))) (clobber (reg:CC FLAGS_REG))] "TARGET_64BIT && ix86_binary_operator_ok (MINUS, SImode, operands)" "sub{l}\t{%2, %k0|%k0, %2}" @@ -6518,7 +6460,7 @@ [(set (reg FLAGS_REG) (compare (minus:SI (match_operand:SI 1 "register_operand" "0") - (match_operand:SI 2 "general_operand" "g")) + (match_operand:SI 2 "x86_64_general_operand" "rme")) (const_int 0))) (set (match_operand:DI 0 "register_operand" "=r") (zero_extend:DI @@ -6545,7 +6487,7 @@ (define_insn "*subsi_3_zext" [(set (reg FLAGS_REG) (compare (match_operand:SI 1 "register_operand" "0") - (match_operand:SI 2 "general_operand" "g"))) + (match_operand:SI 2 "x86_64_general_operand" "rme"))) (set (match_operand:DI 0 "register_operand" "=r") (zero_extend:DI (minus:SI (match_dup 1) @@ -6592,7 +6534,7 @@ (plus:SI (match_operand:SI 1 "nonimmediate_operand" "%0") (plus:SI (match_operator 3 "ix86_carry_flag_operator" [(reg FLAGS_REG) (const_int 0)]) - (match_operand:SI 2 "general_operand" "g"))))) + (match_operand:SI 2 "x86_64_general_operand" "rme"))))) (clobber (reg:CC FLAGS_REG))] "TARGET_64BIT && ix86_binary_operator_ok (PLUS, SImode, operands)" "adc{l}\t{%2, %k0|%k0, %2}" @@ -6607,7 +6549,7 @@ (minus:SI (match_operand:SI 1 "register_operand" "0") (plus:SI (match_operator 3 "ix86_carry_flag_operator" [(reg FLAGS_REG) (const_int 0)]) - (match_operand:SI 2 "general_operand" "g"))))) + (match_operand:SI 2 "x86_64_general_operand" "rme"))))) (clobber (reg:CC FLAGS_REG))] "TARGET_64BIT && ix86_binary_operator_ok (MINUS, SImode, operands)" "sbb{l}\t{%2, %k0|%k0, %2}" @@ -6661,7 +6603,7 @@ (compare:CCC (plusminus:SI (match_operand:SI 1 "nonimmediate_operand" "0") - (match_operand:SI 2 "general_operand" "g")) + (match_operand:SI 2 "x86_64_general_operand" "rme")) (match_dup 1))) (set (match_operand:DI 0 "register_operand" "=r") (zero_extend:DI (plusminus:SI (match_dup 1) (match_dup 2))))] @@ -6748,7 +6690,7 @@ [(set (match_operand:DI 0 "register_operand" "=r,r,r") (zero_extend:DI (mult:SI (match_operand:SI 1 "nonimmediate_operand" "%rm,rm,0") - (match_operand:SI 2 "general_operand" "K,i,mr")))) + (match_operand:SI 2 "x86_64_general_operand" "K,e,mr")))) (clobber (reg:CC FLAGS_REG))] "TARGET_64BIT && !(MEM_P (operands[1]) && MEM_P (operands[2]))" @@ -7374,7 +7316,7 @@ [(set (reg:CCNO FLAGS_REG) (compare:CCNO (and:SI (match_operand:SI 0 "nonimmediate_operand" "") - (match_operand:SI 1 "nonmemory_operand" "")) + (match_operand:SI 1 "x86_64_nonmemory_operand" "")) (const_int 0)))]) (define_expand "testqi_ccz_1" @@ -7440,7 +7382,7 @@ (compare (and:SWI124 (match_operand:SWI124 0 "nonimmediate_operand" "%!*a,,m") - (match_operand:SWI124 1 "general_operand" ",,")) + (match_operand:SWI124 1 "" ",,")) (const_int 0)))] "ix86_match_ccmode (insn, CCNOmode) && !(MEM_P (operands[0]) && MEM_P (operands[1]))" @@ -7730,7 +7672,7 @@ (define_insn "*andsi_1" [(set (match_operand:SI 0 "nonimmediate_operand" "=rm,r,r") (and:SI (match_operand:SI 1 "nonimmediate_operand" "%0,0,qm") - (match_operand:SI 2 "general_operand" "ri,rm,L"))) + (match_operand:SI 2 "x86_64_general_operand" "re,rm,L"))) (clobber (reg:CC FLAGS_REG))] "ix86_binary_operator_ok (AND, SImode, operands)" { @@ -7777,7 +7719,7 @@ [(set (match_operand:DI 0 "register_operand" "=r") (zero_extend:DI (and:SI (match_operand:SI 1 "nonimmediate_operand" "%0") - (match_operand:SI 2 "general_operand" "g")))) + (match_operand:SI 2 "x86_64_general_operand" "rme")))) (clobber (reg:CC FLAGS_REG))] "TARGET_64BIT && ix86_binary_operator_ok (AND, SImode, operands)" "and{l}\t{%2, %k0|%k0, %2}" @@ -7925,7 +7867,7 @@ [(set (reg FLAGS_REG) (compare (and:SWI124 (match_operand:SWI124 1 "nonimmediate_operand" "%0,0") - (match_operand:SWI124 2 "general_operand" ",")) + (match_operand:SWI124 2 "" ",")) (const_int 0))) (set (match_operand:SWI124 0 "nonimmediate_operand" "=,m") (and:SWI124 (match_dup 1) (match_dup 2)))] @@ -7940,7 +7882,7 @@ [(set (reg FLAGS_REG) (compare (and:SI (match_operand:SI 1 "nonimmediate_operand" "%0") - (match_operand:SI 2 "general_operand" "g")) + (match_operand:SI 2 "x86_64_general_operand" "rme")) (const_int 0))) (set (match_operand:DI 0 "register_operand" "=r") (zero_extend:DI (and:SI (match_dup 1) (match_dup 2))))] @@ -8157,7 +8099,7 @@ [(set (match_operand:DI 0 "register_operand" "=r") (zero_extend:DI (any_or:SI (match_operand:SI 1 "nonimmediate_operand" "%0") - (match_operand:SI 2 "general_operand" "g")))) + (match_operand:SI 2 "x86_64_general_operand" "rme")))) (clobber (reg:CC FLAGS_REG))] "TARGET_64BIT && ix86_binary_operator_ok (, SImode, operands)" "{l}\t{%2, %k0|%k0, %2}" @@ -8205,7 +8147,7 @@ (define_insn "*si_2_zext" [(set (reg FLAGS_REG) (compare (any_or:SI (match_operand:SI 1 "nonimmediate_operand" "%0") - (match_operand:SI 2 "general_operand" "g")) + (match_operand:SI 2 "x86_64_general_operand" "rme")) (const_int 0))) (set (match_operand:DI 0 "register_operand" "=r") (zero_extend:DI (any_or:SI (match_dup 1) (match_dup 2))))] @@ -9395,36 +9337,36 @@ (const_string "*"))) (set_attr "mode" "QI")]) -;; Convert lea to the lea pattern to avoid flags dependency. +;; Convert ashift to the lea pattern to avoid flags dependency. (define_split [(set (match_operand 0 "register_operand" "") (ashift (match_operand 1 "index_register_operand" "") (match_operand:QI 2 "const_int_operand" ""))) (clobber (reg:CC FLAGS_REG))] - "reload_completed + "GET_MODE (operands[0]) == GET_MODE (operands[1]) + && reload_completed && true_regnum (operands[0]) != true_regnum (operands[1])" [(const_int 0)] { - rtx pat; enum machine_mode mode = GET_MODE (operands[0]); - - if (mode != Pmode) - operands[1] = gen_lowpart (Pmode, operands[1]); - operands[2] = gen_int_mode (1 << INTVAL (operands[2]), Pmode); - - pat = gen_rtx_MULT (Pmode, operands[1], operands[2]); + rtx pat; if (GET_MODE_SIZE (mode) < GET_MODE_SIZE (SImode)) - operands[0] = gen_lowpart (SImode, operands[0]); + { + mode = SImode; + operands[0] = gen_lowpart (mode, operands[0]); + operands[1] = gen_lowpart (mode, operands[1]); + } + + operands[2] = gen_int_mode (1 << INTVAL (operands[2]), mode); - if (TARGET_64BIT && mode != Pmode) - pat = gen_rtx_SUBREG (SImode, pat, 0); + pat = gen_rtx_MULT (mode, operands[1], operands[2]); emit_insn (gen_rtx_SET (VOIDmode, operands[0], pat)); DONE; }) -;; Convert lea to the lea pattern to avoid flags dependency. +;; Convert ashift to the lea pattern to avoid flags dependency. (define_split [(set (match_operand:DI 0 "register_operand" "") (zero_extend:DI @@ -10364,7 +10306,7 @@ (zero_extract:SWI48 (match_operand:SWI48 0 "register_operand" "r") (const_int 1) - (match_operand:SWI48 1 "nonmemory_operand" "rN")) + (match_operand:SWI48 1 "x86_64_nonmemory_operand" "rN")) (const_int 0)))] "TARGET_USE_BT || optimize_function_for_size_p (cfun)" "bt{}\t{%1, %0|%0, %1}" @@ -16021,8 +15963,8 @@ (define_expand "movcc" [(set (match_operand:SWIM 0 "register_operand" "") (if_then_else:SWIM (match_operand 1 "ordered_comparison_operator" "") - (match_operand:SWIM 2 "general_operand" "") - (match_operand:SWIM 3 "general_operand" "")))] + (match_operand:SWIM 2 "" "") + (match_operand:SWIM 3 "" "")))] "" "if (ix86_expand_int_movcc (operands)) DONE; else FAIL;") Index: predicates.md =================================================================== --- predicates.md (revision 176782) +++ predicates.md (working copy) @@ -366,9 +366,13 @@ ;; Return true when operand is PIC expression that can be computed by lea ;; operation. -(define_predicate "pic_32bit_operand" +(define_special_predicate "pic_32bit_operand" (match_code "const,symbol_ref,label_ref") { + if (GET_MODE (op) != SImode + && GET_MODE (op) != DImode) + return false; + if (!flag_pic) return false; /* Rule out relocations that translate into 64bit constants. */ Index: i386.c =================================================================== --- i386.c (revision 176782) +++ i386.c (working copy) @@ -14122,6 +14122,9 @@ ix86_print_operand_address (FILE *file, } else { + /* Print DImode registers on 64bit targets to avoid addr32 prefixes. */ + int code = TARGET_64BIT ? 'q' : 0; + if (ASSEMBLER_DIALECT == ASM_ATT) { if (disp) @@ -14136,11 +14139,11 @@ ix86_print_operand_address (FILE *file, putc ('(', file); if (base) - print_reg (base, 0, file); + print_reg (base, code, file); if (index) { putc (',', file); - print_reg (index, 0, file); + print_reg (index, code, file); if (scale != 1) fprintf (file, ",%d", scale); } @@ -14175,7 +14178,7 @@ ix86_print_operand_address (FILE *file, putc ('[', file); if (base) { - print_reg (base, 0, file); + print_reg (base, code, file); if (offset) { if (INTVAL (offset) >= 0) @@ -14191,7 +14194,7 @@ ix86_print_operand_address (FILE *file, if (index) { putc ('+', file); - print_reg (index, 0, file); + print_reg (index, code, file); if (scale != 1) fprintf (file, "*%d", scale); }