From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 16649 invoked by alias); 15 Apr 2011 16:15:30 -0000 Received: (qmail 16636 invoked by uid 22791); 15 Apr 2011 16:15:27 -0000 X-SWARE-Spam-Status: No, hits=-1.1 required=5.0 tests=AWL,BAYES_00,KAM_STOCKGEN,T_RP_MATCHES_RCVD X-Spam-Check-By: sourceware.org Received: from mail.codesourcery.com (HELO mail.codesourcery.com) (38.113.113.100) by sourceware.org (qpsmtpd/0.43rc1) with ESMTP; Fri, 15 Apr 2011 16:14:53 +0000 Received: (qmail 2627 invoked from network); 15 Apr 2011 16:14:52 -0000 Received: from unknown (HELO ?84.152.202.246?) (bernds@127.0.0.2) by mail.codesourcery.com with ESMTPA; 15 Apr 2011 16:14:52 -0000 Message-ID: <4DA86E71.7050605@codesourcery.com> Date: Fri, 15 Apr 2011 16:29:00 -0000 From: Bernd Schmidt User-Agent: Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.2.15) Gecko/20110325 Lightning/1.0b3pre Thunderbird/3.1.9 MIME-Version: 1.0 To: Richard Henderson CC: GCC Patches Subject: Re: [PATCH 3/6] Allow jumps in epilogues References: <4D8A0703.9090306@codesourcery.com> <4D8A089D.7020507@codesourcery.com> <4D8A23E8.4090802@redhat.com> <4D8A245A.20701@codesourcery.com> <4D8A2B86.4080402@redhat.com> <4D8CD227.5090205@codesourcery.com> <4D8D5CCC.10705@redhat.com> <4D94DD06.9030507@codesourcery.com> <4D94F1E2.8000906@redhat.com> <4D9B9083.3050706@codesourcery.com> <4DA335E9.4000806@redhat.com> <4DA5994E.3020407@codesourcery.com> In-Reply-To: <4DA5994E.3020407@codesourcery.com> Content-Type: multipart/mixed; boundary="------------040401070102060709040107" Mailing-List: contact gcc-patches-help@gcc.gnu.org; run by ezmlm Precedence: bulk List-Id: List-Archive: List-Post: List-Help: Sender: gcc-patches-owner@gcc.gnu.org X-SW-Source: 2011-04/txt/msg01217.txt.bz2 This is a multi-part message in MIME format. --------------040401070102060709040107 Content-Type: text/plain; charset=ISO-8859-1 Content-Transfer-Encoding: 7bit Content-length: 559 On 04/13/2011 02:38 PM, Bernd Schmidt wrote: > This still requires the i386 output_set_got which I think I can cope > with [...] Patch below, to be applied on top of all the others. Only lightly tested so far beyond standard (fairly useless) regression tests, by comparing generated assembly before/after, for -fpic -march=pentium and core2, for i686-linux and i686-apple-darwin10 (for TARGET_MACHO). I've not found or managed to create a testcase for making MI thunks generate a call to output_set_got. I think it should work, but it's not tested. Bernd --------------040401070102060709040107 Content-Type: text/plain; name="i386-got.diff" Content-Transfer-Encoding: 7bit Content-Disposition: attachment; filename="i386-got.diff" Content-length: 8998 * config/i386/i386.c (output_set_got): Don't call dwarf2out_flush_queued_reg_saves. (ix86_reorg): Split set_got patterns. (i386_dwarf_handle_frame_unspec, i386_dwarf_flush_queued_register_saves): New static functions. (TARGET_DWARF_HANDLE_FRAME_UNSPEC, TARGET_DWARF_FLUSH_QUEUED_REGISTER_SAVES): New macros. * config/i386/i386.md (set_got_call, set_got_pop, set_got_add): New patterns. * dwarf2out.c (scan_until_barrier): Use the target's dwarf_flush_queued_register_saves hook. * target.def (dwarf_flush_queued_register_saves): New hook. * doc/tm.texi: Regenerate. Index: gcc/config/i386/i386.c =================================================================== --- gcc.orig/config/i386/i386.c +++ gcc/config/i386/i386.c @@ -8953,6 +8953,8 @@ output_set_got (rtx dest, rtx label ATTR output_asm_insn ("mov%z0\t{%2, %0|%0, %2}", xops); else { + /* For normal functions, this pattern is split, but we can still + get here for thunks. */ output_asm_insn ("call\t%a2", xops); #ifdef DWARF2_UNWIND_INFO /* The call to next label acts as a push. */ @@ -9010,12 +9012,6 @@ output_set_got (rtx dest, rtx label ATTR get_pc_thunk_name (name, REGNO (dest)); pic_labels_used |= 1 << REGNO (dest); -#ifdef DWARF2_UNWIND_INFO - /* Ensure all queued register saves are flushed before the - call. */ - if (dwarf2out_do_frame ()) - dwarf2out_flush_queued_reg_saves (); -#endif xops[2] = gen_rtx_SYMBOL_REF (Pmode, ggc_strdup (name)); xops[2] = gen_rtx_MEM (QImode, xops[2]); output_asm_insn ("call\t%X2", xops); @@ -30458,6 +30454,56 @@ ix86_reorg (void) with old MDEP_REORGS that are not CFG based. Recompute it now. */ compute_bb_for_insn (); + /* Split any set_got patterns so that we interact correctly with + dwarf2out. */ + if (!TARGET_64BIT && !TARGET_VXWORKS_RTP && !TARGET_DEEP_BRANCH_PREDICTION + && flag_pic) + { + rtx insn, next; + for (insn = get_insns (); insn; insn = next) + { + rtx pat, label, dest, cst, gotsym, new_insn; + int icode; + + next = NEXT_INSN (insn); + if (!NONDEBUG_INSN_P (insn)) + continue; + + icode = recog_memoized (insn); + if (icode != CODE_FOR_set_got && icode != CODE_FOR_set_got_labelled) + continue; + + extract_insn (insn); + if (icode == CODE_FOR_set_got) + { + label = gen_label_rtx (); + cst = const0_rtx; + } + else + { + label = recog_data.operand[1]; + cst = const1_rtx; + } + + dest = recog_data.operand[0]; + pat = gen_set_got_call (label, cst); + new_insn = emit_insn_before (pat, insn); + RTX_FRAME_RELATED_P (new_insn) = 1; + RTX_FRAME_RELATED_P (XVECEXP (PATTERN (new_insn), 0, 1)) = 1; + gotsym = gen_rtx_SYMBOL_REF (Pmode, GOT_SYMBOL_NAME); + pat = gen_set_got_pop (dest, label); + new_insn = emit_insn_before (pat, insn); + RTX_FRAME_RELATED_P (new_insn) = 1; + RTX_FRAME_RELATED_P (XVECEXP (PATTERN (new_insn), 0, 1)) = 1; + if (!TARGET_MACHO) + { + pat = gen_set_got_add (dest, gotsym, label); + new_insn = emit_insn_before (pat, insn); + } + delete_insn (insn); + } + } + if (optimize && optimize_function_for_speed_p (cfun)) { if (TARGET_PAD_SHORT_FUNCTION) @@ -30475,6 +30521,30 @@ ix86_reorg (void) move_or_delete_vzeroupper (); } +/* Handle the TARGET_DWARF_HANDLE_FRAME_UNSPEC hook. + This is called from dwarf2out.c to emit call frame instructions + for frame-related insns containing UNSPECs and UNSPEC_VOLATILEs. */ +static void +i386_dwarf_handle_frame_unspec (rtx pattern ATTRIBUTE_UNUSED, + int index ATTRIBUTE_UNUSED) +{ + gcc_assert (index == UNSPEC_SET_GOT); +} + +/* Handle the TARGET_DWARF_FLUSH_QUEUED_REGISTER_SAVES hook. + This is called from dwarf2out.c to decide whether all queued + register saves should be emitted before INSN. */ +static bool +i386_dwarf_flush_queued_register_saves (rtx insn) +{ + if (!TARGET_VXWORKS_RTP || !flag_pic) + { + int icode = recog_memoized (insn); + return (icode == CODE_FOR_set_got || icode == CODE_FOR_set_got_labelled); + } + return false; +} + /* Return nonzero when QImode register that must be represented via REX prefix is used. */ bool @@ -35321,6 +35391,13 @@ ix86_autovectorize_vector_sizes (void) #define TARGET_ASM_OUTPUT_DWARF_DTPREL i386_output_dwarf_dtprel #endif +#undef TARGET_DWARF_HANDLE_FRAME_UNSPEC +#define TARGET_DWARF_HANDLE_FRAME_UNSPEC i386_dwarf_handle_frame_unspec + +#undef TARGET_DWARF_FLUSH_QUEUED_REGISTER_SAVES +#define TARGET_DWARF_FLUSH_QUEUED_REGISTER_SAVES \ + i386_dwarf_flush_queued_register_saves + #ifdef SUBTARGET_INSERT_ATTRIBUTES #undef TARGET_INSERT_ATTRIBUTES #define TARGET_INSERT_ATTRIBUTES SUBTARGET_INSERT_ATTRIBUTES Index: gcc/config/i386/i386.md =================================================================== --- gcc.orig/config/i386/i386.md +++ gcc/config/i386/i386.md @@ -11797,6 +11797,52 @@ "" "ix86_expand_prologue (); DONE;") +(define_insn "set_got_call" + [(unspec [(label_ref (match_operand 0 "" "")) + (match_operand:SI 1 "const_int_operand" "")] UNSPEC_SET_GOT) + (set (reg:SI SP_REG) (plus:SI (reg:SI SP_REG) (const_int -4)))] + "!TARGET_64BIT && !TARGET_VXWORKS_RTP && !TARGET_DEEP_BRANCH_PREDICTION + && flag_pic" +{ + output_asm_insn ("call\t%l0", operands); +#if TARGET_MACHO + /* If this was for an unlabelled set_got instruction, output the Mach-O + "canonical" label name ("Lxx$pb") here too. This is what will be + referenced by the Mach-O PIC subsystem. */ + if (operands[1] == const0_rtx) + ASM_OUTPUT_LABEL (asm_out_file, MACHOPIC_FUNCTION_BASE_NAME); +#endif + targetm.asm_out.internal_label (asm_out_file, "L", + CODE_LABEL_NUMBER (operands[0])); + return ""; +} + [(set_attr "type" "call") + (set_attr "length" "5")]) + +(define_insn "set_got_pop" + [(set (match_operand:SI 0 "register_operand" "=r") + (unspec [(label_ref (match_operand 1 "" ""))] UNSPEC_SET_GOT)) + (set (reg:SI SP_REG) (plus:SI (reg:SI SP_REG) (const_int 4))) + (clobber (reg:CC FLAGS_REG))] + "!TARGET_64BIT && !TARGET_VXWORKS_RTP && !TARGET_DEEP_BRANCH_PREDICTION + && flag_pic" + "pop%z0\t%0" + [(set_attr "type" "multi") + (set_attr "length" "7")]) + +(define_insn "set_got_add" + [(set (match_operand:SI 0 "register_operand" "=r") + (unspec [(match_dup 0) + (match_operand 1 "" "") + (label_ref (match_operand 2 "" ""))] UNSPEC_SET_GOT)) + (set (reg:SI SP_REG) (plus:SI (reg:SI SP_REG) (const_int 4))) + (clobber (reg:CC FLAGS_REG))] + "!TARGET_64BIT && !TARGET_VXWORKS_RTP && !TARGET_DEEP_BRANCH_PREDICTION + && flag_pic" + "add%z0\t{%1+[.-%l2], %0|%0, %1+(.-%l2)}" + [(set_attr "type" "multi") + (set_attr "length" "7")]) + (define_insn "set_got" [(set (match_operand:SI 0 "register_operand" "=r") (unspec:SI [(const_int 0)] UNSPEC_SET_GOT)) Index: gcc/doc/tm.texi =================================================================== --- gcc.orig/doc/tm.texi +++ gcc/doc/tm.texi @@ -3204,6 +3204,10 @@ terminate the stack backtrace. New port @end defmac @deftypefn {Target Hook} void TARGET_DWARF_HANDLE_FRAME_UNSPEC (rtx @var{pattern}, int @var{index}) + +@deftypefn {Target Hook} bool TARGET_DWARF_FLUSH_QUEUED_REGISTER_SAVES (rtx @var{insn}) +This target hook allows the backend to force dwarf2out to flush queued register saves before an insn when generating unwind information. It is called with an insn as its argument and should return true if register saves must be flushed. +@end deftypefn This target hook allows the backend to emit frame-related insns that contain UNSPECs or UNSPEC_VOLATILEs. The DWARF 2 call frame debugging info engine will invoke it on insns of the form Index: gcc/dwarf2out.c =================================================================== --- gcc.orig/dwarf2out.c +++ gcc/dwarf2out.c @@ -2972,7 +2972,9 @@ scan_until_barrier (rtx insn, jump_targe } if (!NONJUMP_INSN_P (insn) || clobbers_queued_reg_save (insn) - || (NOTE_P (insn) && NOTE_KIND (insn) == NOTE_INSN_PROLOGUE_END)) + || (NOTE_P (insn) && NOTE_KIND (insn) == NOTE_INSN_PROLOGUE_END) + || (targetm.dwarf_flush_queued_register_saves != NULL + && targetm.dwarf_flush_queued_register_saves (insn))) { cfi_insn = PREV_INSN (insn); dwarf2out_flush_queued_reg_saves (); Index: gcc/target.def =================================================================== --- gcc.orig/target.def +++ gcc/target.def @@ -1794,6 +1794,14 @@ DEFHOOK "", void, (rtx pattern, int index), NULL) +DEFHOOK +(dwarf_flush_queued_register_saves, +"This target hook allows the backend to force dwarf2out to flush queued\ + register saves before an insn when generating unwind information. It\ + is called with an insn as its argument and should return true if\ + register saves must be flushed.", + bool, (rtx insn), NULL) + /* ??? Documenting this hook requires a GFDL license grant. */ DEFHOOK_UNDOC (stdarg_optimize_hook, --------------040401070102060709040107--