From patchwork Fri Sep 24 21:16:58 2010 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ian Lance Taylor X-Patchwork-Id: 65692 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 AD414B7103 for ; Sat, 25 Sep 2010 07:17:47 +1000 (EST) Received: (qmail 24155 invoked by alias); 24 Sep 2010 21:17:45 -0000 Received: (qmail 24121 invoked by uid 22791); 24 Sep 2010 21:17:43 -0000 X-SWARE-Spam-Status: No, hits=-2.3 required=5.0 tests=AWL, BAYES_00, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, SPF_HELO_PASS, TW_OV, T_RP_MATCHES_RCVD, T_TVD_MIME_NO_HEADERS X-Spam-Check-By: sourceware.org Received: from smtp-out.google.com (HELO smtp-out.google.com) (216.239.44.51) by sourceware.org (qpsmtpd/0.43rc1) with ESMTP; Fri, 24 Sep 2010 21:17:04 +0000 Received: from kpbe13.cbf.corp.google.com (kpbe13.cbf.corp.google.com [172.25.105.77]) by smtp-out.google.com with ESMTP id o8OLH21H028448 for ; Fri, 24 Sep 2010 14:17:02 -0700 Received: from pxi19 (pxi19.prod.google.com [10.243.27.19]) by kpbe13.cbf.corp.google.com with ESMTP id o8OLH0RY011878 for ; Fri, 24 Sep 2010 14:17:01 -0700 Received: by pxi19 with SMTP id 19so1005712pxi.30 for ; Fri, 24 Sep 2010 14:17:00 -0700 (PDT) Received: by 10.114.112.6 with SMTP id k6mr4287192wac.194.1285363020726; Fri, 24 Sep 2010 14:17:00 -0700 (PDT) Received: from coign.google.com (dhcp-172-22-123-203.mtv.corp.google.com [172.22.123.203]) by mx.google.com with ESMTPS id q6sm4226887waj.22.2010.09.24.14.16.59 (version=TLSv1/SSLv3 cipher=RC4-MD5); Fri, 24 Sep 2010 14:16:59 -0700 (PDT) From: Ian Lance Taylor To: gcc-patches@gcc.gnu.org Subject: [split] Revert REG_CFA_TEMPORARY, bring in 32-bit fixes Date: Fri, 24 Sep 2010 14:16:58 -0700 Message-ID: User-Agent: Gnus/5.13 (Gnus v5.13) Emacs/23.1 (gnu/linux) MIME-Version: 1.0 X-System-Of-Record: true 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 This patch reverts the REG_CFA_TEMPORARY changes, and brings in the 32-bit fixes. Committed to split branch. Ian Index: dwarf2out.c =================================================================== --- dwarf2out.c (revision 164490) +++ dwarf2out.c (working copy) @@ -473,7 +473,6 @@ static void output_call_frame_info (int) static void dwarf2out_note_section_used (void); static bool clobbers_queued_reg_save (const_rtx); static void dwarf2out_frame_debug_expr (rtx, const char *); -static void dwarf2out_frame_debug_remember_state (void); /* Support for complex CFA locations. */ static void output_cfa_loc (dw_cfi_ref); @@ -2827,17 +2826,6 @@ dwarf2out_frame_debug (rtx insn, bool af handled_one = true; break; - case REG_CFA_TEMPORARY: - if (!after_p) - { - dwarf2out_frame_debug_remember_state (); - dwarf2out_frame_debug_def_cfa (XEXP (note, 0), label); - } - else - dwarf2out_frame_debug_restore_state (); - handled_one = true; - break; - default: break; } @@ -2926,17 +2914,9 @@ dwarf2out_cfi_begin_epilogue (rtx insn) } emit_note_before (NOTE_INSN_CFA_RESTORE_STATE, i); - dwarf2out_frame_debug_remember_state (); -} - -/* Remember the current state. */ - -static void -dwarf2out_frame_debug_remember_state (void) -{ emit_cfa_remember = true; - /* Emulate the state save. */ + /* And emulate the state save. */ gcc_assert (!cfa_remember.in_use); cfa_remember = cfa; cfa_remember.in_use = 1; Index: config/i386/i386.md =================================================================== --- config/i386/i386.md (revision 164490) +++ config/i386/i386.md (working copy) @@ -11642,23 +11642,25 @@ ;; In order to support the call/return predictor, we use a return ;; instruction which the middle-end doesn't see. (define_insn "split_stack_return" - [(unspec_volatile [(const_int 0)] UNSPEC_STACK_CHECK)] - "" - "ret" - [(set_attr "length" "1") - (set_attr "atom_unit" "jeu") - (set_attr "length_immediate" "0") - (set_attr "modrm" "0")]) - -(define_insn "split_stack_pop_return" [(unspec_volatile [(match_operand:SI 0 "const_int_operand" "")] UNSPEC_STACK_CHECK)] "" - "ret\t%0" - [(set_attr "length" "3") - (set_attr "atom_unit" "jeu") - (set_attr "length_immediate" "2") - (set_attr "modrm" "0")]) +{ + if (operands[0] == const0_rtx) + return "ret"; + else + return "ret\t%0"; +} + [(set_attr "atom_unit" "jeu") + (set_attr "modrm" "0") + (set (attr "length") + (if_then_else (match_operand:SI 0 "const0_operand" "") + (const_int 1) + (const_int 3))) + (set (attr "length_immediate") + (if_then_else (match_operand:SI 0 "const0_operand" "") + (const_int 0) + (const_int 2)))]) ;; If there are operand 0 bytes available on the stack, jump to ;; operand 1. Index: config/i386/i386.c =================================================================== --- config/i386/i386.c (revision 164490) +++ config/i386/i386.c (working copy) @@ -3651,7 +3651,7 @@ ix86_option_override_internal (bool main /* If using typedef char *va_list, signal that __builtin_va_start (&ap, 0) can be optimized to ap = __builtin_next_arg (0). */ - if (!TARGET_64BIT) + if (!TARGET_64BIT && !flag_split_stack) targetm.expand_builtin_va_start = NULL; if (TARGET_64BIT) @@ -7259,7 +7259,6 @@ ix86_va_start (tree valist, rtx nextarg) if (flag_split_stack && cfun->machine->split_stack_varargs_pointer == NULL_RTX) { - rtx reg, seq; unsigned int scratch_regno; /* When we are splitting the stack, we can't refer to the stack @@ -7270,23 +7269,29 @@ ix86_va_start (tree valist, rtx nextarg) stack prologue can't set the pseudo-register directly because it (the prologue) runs before any registers have been saved. */ - reg = gen_reg_rtx (Pmode); - cfun->machine->split_stack_varargs_pointer = reg; scratch_regno = split_stack_prologue_scratch_regno (); - start_sequence (); - emit_move_insn (reg, gen_rtx_REG (Pmode, scratch_regno)); - seq = get_insns (); - end_sequence (); + if (scratch_regno != INVALID_REGNUM) + { + rtx reg, seq; + + reg = gen_reg_rtx (Pmode); + cfun->machine->split_stack_varargs_pointer = reg; - push_topmost_sequence (); - emit_insn_after (seq, entry_of_function ()); - pop_topmost_sequence (); + start_sequence (); + emit_move_insn (reg, gen_rtx_REG (Pmode, scratch_regno)); + seq = get_insns (); + end_sequence (); + + push_topmost_sequence (); + emit_insn_after (seq, entry_of_function ()); + pop_topmost_sequence (); + } } /* Only 64bit target needs something special. */ if (!TARGET_64BIT || is_va_list_char_pointer (TREE_TYPE (valist))) { - if (!flag_split_stack) + if (cfun->machine->split_stack_varargs_pointer == NULL_RTX) std_expand_builtin_va_start (valist, nextarg); else { @@ -7344,7 +7349,7 @@ ix86_va_start (tree valist, rtx nextarg) /* Find the overflow area. */ type = TREE_TYPE (ovf); - if (!flag_split_stack) + if (cfun->machine->split_stack_varargs_pointer == NULL_RTX) ovf_rtx = crtl->args.internal_arg_pointer; else ovf_rtx = cfun->machine->split_stack_varargs_pointer; @@ -10404,8 +10409,11 @@ split_stack_prologue_scratch_regno (void if (is_fastcall) { if (DECL_STATIC_CHAIN (cfun->decl)) - sorry ("-fsplit-stack does not support fastcall with " - "nested function"); + { + sorry ("-fsplit-stack does not support fastcall with " + "nested function"); + return INVALID_REGNUM; + } return AX_REG; } else if (regparm < 3) @@ -10415,8 +10423,11 @@ split_stack_prologue_scratch_regno (void else { if (regparm >= 2) - sorry ("-fsplit-stack does not support 2 register " - " parameters for a nested function"); + { + sorry ("-fsplit-stack does not support 2 register " + " parameters for a nested function"); + return INVALID_REGNUM; + } return DX_REG; } } @@ -10425,7 +10436,7 @@ split_stack_prologue_scratch_regno (void /* FIXME: We could make this work by pushing a register around the addition and comparison. */ sorry ("-fsplit-stack does not support 3 register parameters"); - return CX_REG; + return INVALID_REGNUM; } } } @@ -10481,25 +10492,23 @@ ix86_expand_split_stack_prologue (void) register which is not used for parameters. */ offset = GEN_INT (- allocate); scratch_regno = split_stack_prologue_scratch_regno (); + if (scratch_regno == INVALID_REGNUM) + return; scratch_reg = gen_rtx_REG (Pmode, scratch_regno); - if (!TARGET_64BIT) - emit_insn (gen_addsi3 (scratch_reg, stack_pointer_rtx, offset)); + if (!TARGET_64BIT || x86_64_immediate_operand (offset, Pmode)) + { + /* We don't use ix86_gen_add3 in this case because it will + want to split to lea, but when not optimizing the insn + will not be split after this point. */ + emit_insn (gen_rtx_SET (VOIDmode, scratch_reg, + gen_rtx_PLUS (Pmode, stack_pointer_rtx, + offset))); + } else { - if (x86_64_immediate_operand (offset, Pmode)) - { - /* We don't use gen_adddi3 in this case because it will - want to split to lea, but when not optimizing the - insn will not be split after this point. */ - emit_move_insn (scratch_reg, - gen_rtx_PLUS (Pmode, stack_pointer_rtx, offset)); - } - else - { - emit_move_insn (scratch_reg, offset); - emit_insn (gen_adddi3 (scratch_reg, scratch_reg, - stack_pointer_rtx)); - } + emit_move_insn (scratch_reg, offset); + emit_insn (gen_adddi3 (scratch_reg, scratch_reg, + stack_pointer_rtx)); } current = scratch_reg; } @@ -10520,12 +10529,7 @@ ix86_expand_split_stack_prologue (void) allocate_rtx = GEN_INT (allocate); args_size = crtl->args.size >= 0 ? crtl->args.size : 0; call_fusage = NULL_RTX; - if (!TARGET_64BIT) - { - emit_insn (gen_push (GEN_INT (args_size))); - emit_insn (gen_push (allocate_rtx)); - } - else + if (TARGET_64BIT) { rtx reg; @@ -10548,6 +10552,11 @@ ix86_expand_split_stack_prologue (void) emit_move_insn (reg, GEN_INT (args_size)); use_reg (&call_fusage, reg); } + else + { + emit_insn (gen_push (GEN_INT (args_size))); + emit_insn (gen_push (allocate_rtx)); + } if (split_stack_fn == NULL_RTX) split_stack_fn = gen_rtx_SYMBOL_REF (Pmode, "__morestack"); call_insn = ix86_expand_call (NULL_RTX, gen_rtx_MEM (QImode, split_stack_fn), @@ -10559,27 +10568,11 @@ ix86_expand_split_stack_prologue (void) to execute a return instruction. See libgcc/config/i386/morestack.S for the details on how this works. - In order to support backtracing, we need to set the CFA around - the call, so that the unwinder knows how to correctly pick up the - return address. We set the CFA around the call because the - unwinder looks up to the point of the call but not after the - call. */ - add_reg_note (call_insn, REG_CFA_TEMPORARY, - gen_rtx_PLUS (Pmode, gen_rtx_REG (Pmode, SP_REG), - GEN_INT (UNITS_PER_WORD))); - RTX_FRAME_RELATED_P (call_insn) = 1; - - /* For flow purposes gcc must not see this as a return + For flow purposes gcc must not see this as a return instruction--we need control flow to continue at the subsequent label. Therefore, we use an unspec. */ - if (crtl->args.pops_args == 0) - emit_insn (gen_split_stack_return ()); - else - { - gcc_assert (!TARGET_64BIT); - gcc_assert (crtl->args.pops_args < 65536); - emit_insn (gen_split_stack_pop_return (GEN_INT (crtl->args.pops_args))); - } + gcc_assert (crtl->args.pops_args < 65536); + emit_insn (gen_split_stack_return (GEN_INT (crtl->args.pops_args))); /* If we are in 64-bit mode and this function uses a static chain, we saved %r10 in %rax before calling _morestack. */ @@ -10599,20 +10592,32 @@ ix86_expand_split_stack_prologue (void) { unsigned int scratch_regno; rtx frame_reg; + int words; scratch_regno = split_stack_prologue_scratch_regno (); scratch_reg = gen_rtx_REG (Pmode, scratch_regno); frame_reg = gen_rtx_REG (Pmode, BP_REG); - /* fp -> old fp value + /* 64-bit: + fp -> old fp value return address within this function return address of caller of this function stack arguments So we add three words to get to the stack arguments. + + 32-bit: + fp -> old fp value + return address within this function + first argument to __morestack + second argument to __morestack + return address of caller of this function + stack arguments + So we add five words to get to the stack arguments. */ - emit_move_insn (scratch_reg, - gen_rtx_PLUS (Pmode, frame_reg, - GEN_INT (3 * UNITS_PER_WORD))); + words = TARGET_64BIT ? 3 : 5; + emit_insn (gen_rtx_SET (VOIDmode, scratch_reg, + gen_rtx_PLUS (Pmode, frame_reg, + GEN_INT (words * UNITS_PER_WORD)))); varargs_label = gen_label_rtx (); emit_jump_insn (gen_jump (varargs_label)); @@ -10629,9 +10634,9 @@ ix86_expand_split_stack_prologue (void) case we need to set it based on the stack pointer. */ if (cfun->machine->split_stack_varargs_pointer != NULL_RTX) { - emit_move_insn (scratch_reg, - gen_rtx_PLUS (Pmode, stack_pointer_rtx, - GEN_INT (UNITS_PER_WORD))); + emit_insn (gen_rtx_SET (VOIDmode, scratch_reg, + gen_rtx_PLUS (Pmode, stack_pointer_rtx, + GEN_INT (UNITS_PER_WORD)))); emit_label (varargs_label); LABEL_NUSES (varargs_label) = 1; Index: reg-notes.def =================================================================== --- reg-notes.def (revision 164490) +++ reg-notes.def (working copy) @@ -165,13 +165,6 @@ REG_NOTE (CFA_RESTORE) to the argument, if it is a MEM, it is ignored. */ REG_NOTE (CFA_SET_VDRAP) -/* Temporarily set the CFA for just one insn. This saves the old - state, sets the CFA, and then restores the state after the insn. - The pattern for this note is the new CFA value. This is used by - the split stack code to support unwinding through the call into the - split stack routine. */ -REG_NOTE (CFA_TEMPORARY) - /* Indicates that REG holds the exception context for the function. This context is shared by inline functions, so the code to acquire the real exception context is delayed until after inlining. */