From patchwork Fri Jul 29 12:58:28 2011 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Alan Modra X-Patchwork-Id: 107391 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 B7A16B6F6B for ; Fri, 29 Jul 2011 22:58:58 +1000 (EST) Received: (qmail 25650 invoked by alias); 29 Jul 2011 12:58:57 -0000 Received: (qmail 25641 invoked by uid 22791); 29 Jul 2011 12:58:56 -0000 X-SWARE-Spam-Status: No, hits=-2.7 required=5.0 tests=AWL, BAYES_00, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, FREEMAIL_FROM, RCVD_IN_DNSWL_LOW X-Spam-Check-By: sourceware.org Received: from mail-pz0-f49.google.com (HELO mail-pz0-f49.google.com) (209.85.210.49) by sourceware.org (qpsmtpd/0.43rc1) with ESMTP; Fri, 29 Jul 2011 12:58:41 +0000 Received: by pzk33 with SMTP id 33so6613555pzk.36 for ; Fri, 29 Jul 2011 05:58:40 -0700 (PDT) Received: by 10.68.12.101 with SMTP id x5mr2238836pbb.267.1311944318329; Fri, 29 Jul 2011 05:58:38 -0700 (PDT) Received: from bubble.grove.modra.org ([115.187.252.19]) by mx.google.com with ESMTPS id 9sm2145843pbx.50.2011.07.29.05.58.33 (version=TLSv1/SSLv3 cipher=OTHER); Fri, 29 Jul 2011 05:58:36 -0700 (PDT) Received: by bubble.grove.modra.org (Postfix, from userid 1000) id 7ADC8170C1B3; Fri, 29 Jul 2011 22:28:28 +0930 (CST) Date: Fri, 29 Jul 2011 22:28:28 +0930 From: Alan Modra To: Richard Henderson , David Edelsohn , Michael Meissner , gcc-patches@gcc.gnu.org Subject: Re: [RS6000] asynch exceptions and unwind info Message-ID: <20110729125828.GY1081@bubble.grove.modra.org> Mail-Followup-To: Richard Henderson , David Edelsohn , Michael Meissner , gcc-patches@gcc.gnu.org References: <20110727053045.GO1081@bubble.grove.modra.org> <20110728072753.GQ1081@bubble.grove.modra.org> <4E31AF2C.2070404@redhat.com> <20110729012748.GR1081@bubble.grove.modra.org> MIME-Version: 1.0 Content-Disposition: inline In-Reply-To: <20110729012748.GR1081@bubble.grove.modra.org> User-Agent: Mutt/1.5.20 (2009-06-14) 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 Fri, Jul 29, 2011 at 10:57:48AM +0930, Alan Modra wrote: > Except that any info about r2 in an indirect call sequence really > belongs to the *called* function frame, not the callee. I woke up > this morning with the realization that what I'd done in > frob_update_context for indirect call sequences was wrong. Ditto for > the r2 store that Michael moved into the prologue. The only time we > want the unwinder to restore from that particular save is if r2 isn't > saved in the current frame. > > Untested patch follows. Here's a tested patch that fixes an issue with TOC_SINGLE_PIC_BASE and enables Michael's save_toc_in_prologue optimization for all functions except those that make dynamic stack adjustments. Incidentally, the rs6000_emit_prologue comment I added below suggests another solution. Since all we need is the toc pointer for the frame, it would be possible to tell the unwinder to simply load r2 from the .opd entry. I think.. libgcc/ * config/rs6000/linux-unwind.h (frob_update_context <__powerpc64__>): Restore for indirect call bcrtl from correct stack slot, and only if cfa+40 isn't valid. gcc/ * config/rs6000/rs6000-protos.h (rs6000_save_toc_in_prologue_p): Delete. * config/rs6000/rs6000.c (rs6000_save_toc_in_prologue_p): Make static. (rs6000_emit_prologue): Don't prematurely return when TARGET_SINGLE_PIC_BASE. Don't emit eh_frame info in save_toc_in_prologue case. (rs6000_call_indirect_aix): Only disallow save_toc_in_prologue for calls_alloca. Index: libgcc/config/rs6000/linux-unwind.h =================================================================== --- libgcc/config/rs6000/linux-unwind.h (revision 176905) +++ libgcc/config/rs6000/linux-unwind.h (working copy) @@ -354,20 +354,22 @@ frob_update_context (struct _Unwind_Cont /* We are in a plt call stub or r2 adjusting long branch stub, before r2 has been saved. Keep REG_UNSAVED. */ } - else if (pc[0] == 0x4E800421 - && pc[1] == 0xE8410028) - { - /* We are at the bctrl instruction in a call via function - pointer. gcc always emits the load of the new r2 just - before the bctrl. */ - _Unwind_SetGRPtr (context, 2, context->cfa + 40); - } else { unsigned int *insn = (unsigned int *) _Unwind_GetGR (context, R_LR); if (insn && *insn == 0xE8410028) _Unwind_SetGRPtr (context, 2, context->cfa + 40); + else if (pc[0] == 0x4E800421 + && pc[1] == 0xE8410028) + { + /* We are at the bctrl instruction in a call via function + pointer. gcc always emits the load of the new R2 just + before the bctrl so this is the first and only place + we need to use the stored R2. */ + _Unwind_Word sp = _Unwind_GetGR (context, 1); + _Unwind_SetGRPtr (context, 2, sp + 40); + } } } #endif Index: gcc/config/rs6000/rs6000-protos.h =================================================================== --- gcc/config/rs6000/rs6000-protos.h (revision 176905) +++ gcc/config/rs6000/rs6000-protos.h (working copy) @@ -172,8 +172,6 @@ extern void rs6000_emit_epilogue (int); extern void rs6000_emit_eh_reg_restore (rtx, rtx); extern const char * output_isel (rtx *); extern void rs6000_call_indirect_aix (rtx, rtx, rtx); -extern bool rs6000_save_toc_in_prologue_p (void); - extern void rs6000_aix_asm_output_dwarf_table_ref (char *); /* Declare functions in rs6000-c.c */ Index: gcc/config/rs6000/rs6000.c =================================================================== --- gcc/config/rs6000/rs6000.c (revision 176905) +++ gcc/config/rs6000/rs6000.c (working copy) @@ -1178,6 +1178,7 @@ static void rs6000_conditional_register_ static void rs6000_trampoline_init (rtx, tree, rtx); static bool rs6000_cannot_force_const_mem (enum machine_mode, rtx); static bool rs6000_legitimate_constant_p (enum machine_mode, rtx); +static bool rs6000_save_toc_in_prologue_p (void); /* Hash table stuff for keeping track of TOC entries. */ @@ -20478,14 +20504,12 @@ rs6000_emit_prologue (void) insn = emit_insn (generate_set_vrsave (reg, info, 0)); } - if (TARGET_SINGLE_PIC_BASE) - return; /* Do not set PIC register */ - /* If we are using RS6000_PIC_OFFSET_TABLE_REGNUM, we need to set it up. */ - if ((TARGET_TOC && TARGET_MINIMAL_TOC && get_pool_size () != 0) - || (DEFAULT_ABI == ABI_V4 - && (flag_pic == 1 || (flag_pic && TARGET_SECURE_PLT)) - && df_regs_ever_live_p (RS6000_PIC_OFFSET_TABLE_REGNUM))) + if (!TARGET_SINGLE_PIC_BASE + && ((TARGET_TOC && TARGET_MINIMAL_TOC && get_pool_size () != 0) + || (DEFAULT_ABI == ABI_V4 + && (flag_pic == 1 || (flag_pic && TARGET_SECURE_PLT)) + && df_regs_ever_live_p (RS6000_PIC_OFFSET_TABLE_REGNUM)))) { /* If emit_load_toc_table will use the link register, we need to save it. We use R12 for this purpose because emit_load_toc_table @@ -20513,7 +20537,8 @@ rs6000_emit_prologue (void) } #if TARGET_MACHO - if (DEFAULT_ABI == ABI_DARWIN + if (!TARGET_SINGLE_PIC_BASE + && DEFAULT_ABI == ABI_DARWIN && flag_pic && crtl->uses_pic_offset_table) { rtx lr = gen_rtx_REG (Pmode, LR_REGNO); @@ -20534,10 +20559,26 @@ rs6000_emit_prologue (void) } #endif - /* If we need to, save the TOC register after doing the stack setup. */ + /* If we need to, save the TOC register after doing the stack setup. + Do not emit eh frame info for this save. We don't attempt to + write accurate DWARF EH frame info for R2 because code emitted by + gcc for a (non-pointer) function call doesn't save and restore + R2. Instead, R2 is managed out-of-line by a linker generated plt + call stub when the function resides in a shared library. This + behaviour is costly to describe in DWARF, both in terms of the + size of DWARF info and the time taken in the unwinder to + interpret it. R2 changes, apart from the calls_eh_return case + earlier in this function, are handled by linux-unwind.h + frob_update_context. Even in frob_update_context we don't try to + keep the unwinder's copy of R2 accurate on an instruction by + instruction basis, as we only need it set to the correct TOC + pointer for the current frame. */ if (rs6000_save_toc_in_prologue_p ()) - emit_frame_save (sp_reg_rtx, sp_reg_rtx, reg_mode, TOC_REGNUM, - 5 * reg_size, info->total_size); + { + rtx addr = gen_rtx_PLUS (Pmode, sp_reg_rtx, GEN_INT (5 * reg_size)); + rtx mem = gen_frame_mem (reg_mode, addr); + emit_move_insn (mem, gen_rtx_REG (reg_mode, TOC_REGNUM)); + } } /* Write function prologue. */ @@ -27795,10 +27838,7 @@ rs6000_call_indirect_aix (rtx value, rtx /* Can we optimize saving the TOC in the prologue or do we need to do it at every call? */ - if (TARGET_SAVE_TOC_INDIRECT && !cfun->calls_alloca - && !cfun->calls_setjmp && !cfun->has_nonlocal_label - && !cfun->can_throw_non_call_exceptions - && ((flags_from_decl_or_type (cfun->decl) & ECF_NOTHROW) == ECF_NOTHROW)) + if (TARGET_SAVE_TOC_INDIRECT && !cfun->calls_alloca) cfun->machine->save_toc_in_prologue = true; else @@ -27834,13 +27874,12 @@ rs6000_call_indirect_aix (rtx value, rtx insn = call_func (func_addr, flag, func_toc_mem, stack_toc_mem); emit_call_insn (insn); - return; } /* Return whether we need to always update the saved TOC pointer when we update the stack pointer. */ -bool +static bool rs6000_save_toc_in_prologue_p (void) { return (cfun && cfun->machine && cfun->machine->save_toc_in_prologue);