From patchwork Tue Mar 6 15:37:32 2012 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: "H.J. Lu" X-Patchwork-Id: 144954 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 32A16B6FAA for ; Wed, 7 Mar 2012 02:37:54 +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=1331653075; h=Comment: DomainKey-Signature:Received:Received:Received:Received: Received-SPF:Received:MIME-Version:Received:Received:In-Reply-To: References:Date:Message-ID:Subject:From:To:Cc:Content-Type: Content-Transfer-Encoding:Mailing-List:Precedence:List-Id: List-Unsubscribe:List-Archive:List-Post:List-Help:Sender: Delivered-To; bh=7rCKZs855TowlYWyrqiwxztCfbc=; b=Y4JjsIWL8QMPp/h WZFZh1s0LuJT/C1D/z4akFs5/k2VNHfjf0FYVMKLOZJaP7gRNwPdmPam377D6zKR T1yJKmlwLqXlPVStjOJ9nlImLT+SUZ2JCWiR3X7mUyZbwoMOQd0mdiTvlKq9/bzf lR2ZXRQR5uZa+bwfvo3laSjtbY8I= 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-SPF:Authentication-Results:Received:MIME-Version:Received:Received:In-Reply-To:References:Date:Message-ID:Subject:From:To:Cc:Content-Type:Content-Transfer-Encoding:X-IsSubscribed:Mailing-List:Precedence:List-Id:List-Unsubscribe:List-Archive:List-Post:List-Help:Sender:Delivered-To; b=epAHK9NJNEavajPJ5vXZ6I6Y67BKZsXeKyqfrrKvIhpEpDs+xTF/1XYA9L7/dy q7i6ryABOfTu5Ve2Llh7/gsC/OHxFoK4Dsza/y3F0f/E63m3jPWR6jgIdhsL46ZP EjJiVSqGAiC/1gAX9uKnRgnSb8FbeokTpmxLgSvQJ+Mws=; Received: (qmail 16231 invoked by alias); 6 Mar 2012 15:37:50 -0000 Received: (qmail 16191 invoked by uid 22791); 6 Mar 2012 15:37:47 -0000 X-SWARE-Spam-Status: No, hits=-1.6 required=5.0 tests=AWL, BAYES_00, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, FREEMAIL_FROM, KAM_STOCKGEN, RCVD_IN_DNSWL_LOW, TW_ZJ X-Spam-Check-By: sourceware.org Received: from mail-qy0-f175.google.com (HELO mail-qy0-f175.google.com) (209.85.216.175) by sourceware.org (qpsmtpd/0.43rc1) with ESMTP; Tue, 06 Mar 2012 15:37:33 +0000 Received: by qcso7 with SMTP id o7so2597889qcs.20 for ; Tue, 06 Mar 2012 07:37:32 -0800 (PST) Received-SPF: pass (google.com: domain of hjl.tools@gmail.com designates 10.229.137.16 as permitted sender) client-ip=10.229.137.16; Authentication-Results: mr.google.com; spf=pass (google.com: domain of hjl.tools@gmail.com designates 10.229.137.16 as permitted sender) smtp.mail=hjl.tools@gmail.com; dkim=pass header.i=hjl.tools@gmail.com Received: from mr.google.com ([10.229.137.16]) by 10.229.137.16 with SMTP id u16mr3388630qct.146.1331048252874 (num_hops = 1); Tue, 06 Mar 2012 07:37:32 -0800 (PST) MIME-Version: 1.0 Received: by 10.229.137.16 with SMTP id u16mr2914922qct.146.1331048252317; Tue, 06 Mar 2012 07:37:32 -0800 (PST) Received: by 10.229.144.207 with HTTP; Tue, 6 Mar 2012 07:37:32 -0800 (PST) In-Reply-To: References: <20111112021931.GA26507@intel.com> Date: Tue, 6 Mar 2012 07:37:32 -0800 Message-ID: Subject: Re: PATCH [1/n] addr32: Properly use Pmode and word_mode From: "H.J. Lu" To: Uros Bizjak Cc: Ian Lance Taylor , gcc-patches@gcc.gnu.org, Richard Henderson 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 Mon, Mar 5, 2012 at 9:11 AM, H.J. Lu wrote: > On Sun, Mar 4, 2012 at 11:47 PM, Uros Bizjak wrote: >> On Mon, Mar 5, 2012 at 4:53 AM, H.J. Lu wrote: >> >>> and compiler does generate the same output. i386.c also has >>> >>>        xasm = "jmp\t%A0"; >>>    xasm = "call\t%A0"; >>> >>> for calls.  There are no separate indirect call patterns.  For x32, >>> only indirect register calls have to be in DImode.  The direct call >>> should be in Pmode (SImode). >> >> Direct call just expects label to some abolute address that is assumed >> to fit in 32 bits (see constant_call_address_operand_p). >> >> call and jmp insn expect word_mode operands, so please change >> ix86_expand_call and call patterns in the same way as jump >> instructions above. >> >>> Since x86-64 hardware always zero-extends upper 32bits of 64bit >>> registers when loading its lower 32bits, it is safe and easier to just >>> to output 64bit registers for %A than zero-extend it by hand for all >>> jump/call patterns. >> >> No, the instruction expects word_mode operands, so we have to extend >> values to expected mode. I don't think that patching at insn output >> time is acceptable. > > You are right. I found a testcase to show problem: > > struct foo > { >  void (*f) (void); >  int i; > }; > > void > __attribute__ ((noinline)) > bar (struct foo x) > { >  x.f (); > } > > "x" is passed in RDI and the uppper 32bits of RDI is "int i". > Operand 1 of calls must be in Pmode for SYMOL_REF and word_mode for register. When I removed :P like @@ -11423,7 +11428,7 @@ (define_insn "*call_value" [(set (match_operand 0 "" "") - (call (mem:QI (match_operand:P 1 "call_insn_operand" "zw")) + (call (mem:QI (match_operand 1 "call_insn_operand" "zw")) (match_operand 2 "" "")))] "!SIBLING_CALL_P (insn)" "* return ix86_output_call_insn (insn, operands[1]);" I got In file included from /net/gnu-6/export/gnu/import/git/gcc-addr32/libgcc/unwind-dw2.c:1633:0: /net/gnu-6/export/gnu/import/git/gcc-addr32/libgcc/unwind.inc: In function \u2018_Unwind_ForcedUnwind_Phase2\u2019: /net/gnu-6/export/gnu/import/git/gcc-addr32/libgcc/unwind.inc:189:1: error: unable to find a register to spill in class \u2018CREG\u2019 /net/gnu-6/export/gnu/import/git/gcc-addr32/libgcc/unwind.inc:189:1: error: this is the insn: (call_insn 62 60 63 9 (set (reg:SI 0 ax) (call (mem:QI (reg/f:DI 0 ax [orig:88 D.9044 ] [88]) [0 *D.9044_25 S1 A8]) (const_int 0 [0]))) /net/gnu-6/export/gnu/import/git/gcc-addr32/libgcc/unwind.inc:175 629 {*call_value} (expr_list:REG_DEAD (reg/f:DI 0 ax [orig:88 D.9044 ] [88]) (expr_list:REG_DEAD (reg:DI 37 r8) (expr_list:REG_DEAD (reg:SI 5 di) (expr_list:REG_DEAD (reg:SI 4 si) (expr_list:REG_DEAD (reg:DI 2 cx) (expr_list:REG_DEAD (reg:DI 1 dx) (nil))))))) (expr_list:REG_BR_PRED (use (reg:SI 5 di)) (expr_list:REG_BR_PRED (use (reg:SI 4 si)) (expr_list:REG_FRAME_RELATED_EXPR (use (reg:DI 1 dx)) (expr_list:REG_BR_PRED (use (reg:DI 2 cx)) (expr_list:REG_BR_PRED (use (reg:DI 37 r8)) (nil))))))) /net/gnu-6/export/gnu/import/git/gcc-addr32/libgcc/unwind.inc:189:1: internal compiler error: in spill_failure, at reload1.c:2120 Please submit a full bug report, with preprocessed source if appropriate. See for instructions. Here is a patch to duplicate function symbol to change it from Pmode to word_mode. It seems to work. But I am not sure if it is the right approach. Any suggestions? Thanks. diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c index 1828cf6..26e23c7 100644 --- a/gcc/config/i386/i386.c +++ b/gcc/config/i386/i386.c @@ -22976,6 +22975,19 @@ construct_plt_address (rtx symbol) return tmp; } +static rtx +duplicate_function_symbol_ref (enum machine_mode mode, rtx fnaddr) +{ + rtx dup_symbol_ref; + gcc_assert (!SYMBOL_REF_HAS_BLOCK_INFO_P (fnaddr)); + dup_symbol_ref = gen_rtx_SYMBOL_REF (mode, XSTR (fnaddr, 0)); + SYMBOL_REF_USED (dup_symbol_ref) = SYMBOL_REF_USED (fnaddr); + SYMBOL_REF_WEAK (dup_symbol_ref) = SYMBOL_REF_WEAK (fnaddr); + SET_SYMBOL_REF_DECL (dup_symbol_ref, SYMBOL_REF_DECL (fnaddr)); + SYMBOL_REF_FLAGS (dup_symbol_ref) = SYMBOL_REF_FLAGS (fnaddr); + return dup_symbol_ref; +} + rtx ix86_expand_call (rtx retval, rtx fnaddr, rtx callarg1, rtx callarg2, @@ -23026,13 +23038,22 @@ ix86_expand_call (rtx retval, rtx fnaddr, rtx callarg1, && !local_symbolic_operand (XEXP (fnaddr, 0), VOIDmode)) fnaddr = gen_rtx_MEM (QImode, construct_plt_address (XEXP (fnaddr, 0))); else if (sibcall - ? !sibcall_insn_operand (XEXP (fnaddr, 0), Pmode) - : !call_insn_operand (XEXP (fnaddr, 0), Pmode)) + ? !sibcall_insn_operand (XEXP (fnaddr, 0), word_mode) + : !call_insn_operand (XEXP (fnaddr, 0), word_mode)) { fnaddr = XEXP (fnaddr, 0); - if (GET_MODE (fnaddr) != Pmode) - fnaddr = convert_to_mode (Pmode, fnaddr, 1); - fnaddr = gen_rtx_MEM (QImode, copy_to_mode_reg (Pmode, fnaddr)); + if (TARGET_X32 && GET_CODE (fnaddr) == SYMBOL_REF) + { + fnaddr = duplicate_function_symbol_ref (word_mode, fnaddr); + fnaddr = gen_rtx_MEM (QImode, fnaddr); + } + else + { + if (GET_MODE (fnaddr) != word_mode) + fnaddr = convert_to_mode (word_mode, fnaddr, 1); + fnaddr = gen_rtx_MEM (QImode, + copy_to_mode_reg (word_mode, fnaddr)); + } } vec_len = 0; @@ -23122,7 +23143,7 @@ ix86_split_call_vzeroupper (rtx insn, rtx vzeroupper) const char * ix86_output_call_insn (rtx insn, rtx call_op) { - bool direct_p = constant_call_address_operand (call_op, Pmode); + bool direct_p = constant_call_address_operand (call_op, word_mode); bool seh_nop_p = false; const char *xasm; @@ -32211,6 +32232,16 @@ x86_output_mi_thunk (FILE *file, emit_jump_insn (gen_indirect_jump (fnaddr)); else { + if (GET_MODE (fnaddr) != word_mode) + { + if (TARGET_X32 && GET_CODE (fnaddr) == SYMBOL_REF) + fnaddr = duplicate_function_symbol_ref (word_mode, fnaddr); + else + { + fnaddr = convert_to_mode (word_mode, fnaddr, 1); + fnaddr = copy_to_mode_reg (word_mode, fnaddr); + } + } tmp = gen_rtx_MEM (QImode, fnaddr); tmp = gen_rtx_CALL (VOIDmode, tmp, const0_rtx); tmp = emit_call_insn (tmp); diff --git a/gcc/config/i386/i386.md b/gcc/config/i386/i386.md index 715e7ea..3f7f4f1 100644 --- a/gcc/config/i386/i386.md +++ b/gcc/config/i386/i386.md @@ -11100,10 +11100,15 @@ (set_attr "modrm" "0")]) (define_expand "indirect_jump" - [(set (pc) (match_operand 0 "indirect_branch_operand" ""))]) + [(set (pc) (match_operand 0 "indirect_branch_operand" ""))] + "" +{ + if (TARGET_X32) + operands[0] = convert_memory_address (word_mode, operands[0]); +}) (define_insn "*indirect_jump" - [(set (pc) (match_operand:P 0 "indirect_branch_operand" "rw"))] + [(set (pc) (match_operand:W 0 "indirect_branch_operand" "rw"))] "" "jmp\t%A0" [(set_attr "type" "ibr") @@ -11145,12 +11150,12 @@ operands[0] = expand_simple_binop (Pmode, code, op0, op1, NULL_RTX, 0, OPTAB_DIRECT); } - else if (TARGET_X32) - operands[0] = convert_memory_address (Pmode, operands[0]); + if (TARGET_X32) + operands[0] = convert_memory_address (word_mode, operands[0]); }) (define_insn "*tablejump_1" - [(set (pc) (match_operand:P 0 "indirect_branch_operand" "rw")) + [(set (pc) (match_operand:W 0 "indirect_branch_operand" "rw")) (use (label_ref (match_operand 1 "" "")))] "" "jmp\t%A0" @@ -11237,7 +11242,7 @@ }) (define_insn_and_split "*call_vzeroupper" - [(call (mem:QI (match_operand:P 0 "call_insn_operand" "zw")) + [(call (mem:QI (match_operand:W 0 "call_insn_operand" "zw")) (match_operand 1 "" "")) (unspec [(match_operand 2 "const_int_operand" "")] UNSPEC_CALL_NEEDS_VZEROUPPER)] @@ -11249,7 +11254,7 @@ [(set_attr "type" "call")]) (define_insn "*call" - [(call (mem:QI (match_operand:P 0 "call_insn_operand" "zw")) + [(call (mem:QI (match_operand:W 0 "call_insn_operand" "zw")) (match_operand 1 "" ""))] "!SIBLING_CALL_P (insn)" "* return ix86_output_call_insn (insn, operands[0]);" @@ -11301,7 +11306,7 @@ [(set_attr "type" "call")]) (define_insn_and_split "*sibcall_vzeroupper" - [(call (mem:QI (match_operand:P 0 "sibcall_insn_operand" "Uz")) + [(call (mem:QI (match_operand:W 0 "sibcall_insn_operand" "Uz")) (match_operand 1 "" "")) (unspec [(match_operand 2 "const_int_operand" "")] UNSPEC_CALL_NEEDS_VZEROUPPER)] @@ -11313,7 +11318,7 @@ [(set_attr "type" "call")]) (define_insn "*sibcall" - [(call (mem:QI (match_operand:P 0 "sibcall_insn_operand" "Uz")) + [(call (mem:QI (match_operand:W 0 "sibcall_insn_operand" "Uz")) (match_operand 1 "" ""))] "SIBLING_CALL_P (insn)" "* return ix86_output_call_insn (insn, operands[0]);" @@ -11410,7 +11415,7 @@ (define_insn_and_split "*call_value_vzeroupper" [(set (match_operand 0 "" "") - (call (mem:QI (match_operand:P 1 "call_insn_operand" "zw")) + (call (mem:QI (match_operand:W 1 "call_insn_operand" "zw")) (match_operand 2 "" ""))) (unspec [(match_operand 3 "const_int_operand" "")] UNSPEC_CALL_NEEDS_VZEROUPPER)] @@ -11423,7 +11428,7 @@ (define_insn "*call_value" [(set (match_operand 0 "" "") - (call (mem:QI (match_operand:P 1 "call_insn_operand" "zw")) + (call (mem:QI (match_operand:W 1 "call_insn_operand" "zw")) (match_operand 2 "" "")))] "!SIBLING_CALL_P (insn)" "* return ix86_output_call_insn (insn, operands[1]);" @@ -11431,7 +11436,7 @@ (define_insn_and_split "*sibcall_value_vzeroupper" [(set (match_operand 0 "" "") - (call (mem:QI (match_operand:P 1 "sibcall_insn_operand" "Uz")) + (call (mem:QI (match_operand:W 1 "sibcall_insn_operand" "Uz")) (match_operand 2 "" ""))) (unspec [(match_operand 3 "const_int_operand" "")] UNSPEC_CALL_NEEDS_VZEROUPPER)] @@ -11444,7 +11449,7 @@ (define_insn "*sibcall_value" [(set (match_operand 0 "" "") - (call (mem:QI (match_operand:P 1 "sibcall_insn_operand" "Uz")) + (call (mem:QI (match_operand:W 1 "sibcall_insn_operand" "Uz")) (match_operand 2 "" "")))] "SIBLING_CALL_P (insn)" "* return ix86_output_call_insn (insn, operands[1]);"