From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 32358 invoked by alias); 13 Apr 2011 15:14:21 -0000 Received: (qmail 32349 invoked by uid 22791); 13 Apr 2011 15:14:19 -0000 X-SWARE-Spam-Status: No, hits=-1.8 required=5.0 tests=AWL,BAYES_00,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; Wed, 13 Apr 2011 15:14:09 +0000 Received: (qmail 23192 invoked from network); 13 Apr 2011 15:14:08 -0000 Received: from unknown (HELO ?84.152.181.146?) (bernds@127.0.0.2) by mail.codesourcery.com with ESMTPA; 13 Apr 2011 15:14:08 -0000 Message-ID: <4DA5BD43.1090102@codesourcery.com> Date: Wed, 13 Apr 2011 15:14: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: gcc-patches@gcc.gnu.org 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> <4DA5AFB9.9040706@codesourcery.com> In-Reply-To: <4DA5AFB9.9040706@codesourcery.com> Content-Type: multipart/mixed; boundary="------------080204050101090303000604" 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/msg01000.txt.bz2 This is a multi-part message in MIME format. --------------080204050101090303000604 Content-Type: text/plain; charset=ISO-8859-1 Content-Transfer-Encoding: 7bit Content-length: 4775 On 04/13/2011 04:14 PM, Bernd Schmidt wrote: > On 04/11/2011 07:10 PM, Richard Henderson wrote: >> Ok. > > Did you receive my reply to this message from earlier today? It doesn't > seem to have made it to gcc-patches yet. Since gcc-patches appears to have dropped the message, I'll resend it in three parts. There are three patches here, but they must be applied together (things will mostly work otherwise, but I expect -freorder-blocks-and-partition is broken in the intermediate stages). Below is the ChangeLog for the entire set, and the first of the patches. This is just a new version of the previously posted 002-scanfirst patch, now changed to delete the CFI notes afterwards in order to avoid -fcompare-debug failures. Bernd * target.def (dwarf_handle_frame_unspec): Remove label argument. * doc/tm.texi: Regenerate. * tree.h (dwarf2out_cfi_label, dwarf2out_def_cfa, dwarf2out_window_save, dwarf2out_reg_save, dwarf2out_return_save, dwarf2out_return_reg, dwarf2out_reg_save_reg): Don't declare. * final.c (final_start_function): Call dwarf2out_frame_debug_after_prologue. (final_scan_insn): Don't call dwarf2out_frame_debug for anything. Handle NOTE_INSN_CFI and NOTE_INSN_CFI_LABEL. (final): Delete these notes. * insn-notes.def (CFI, CFI_LABEL): New. * jump.c (addr_vec_p): New function. * dwarf2out.c (cfi_insn): New static variable. (dwarf2out_cfi_label): Remove force argument. All callers changed. Only generate the label, don't emit it. (dwarf2out_maybe_emit_cfi_label): New function. (add_fde_cfi): Remove label argument. All callers changed. Remove most code; leave a condition to either emit a CFI insn, or add the CFI to the FDE CFI vector. (add_cie_cfi): New static function. (add_cfi): Remove function. (old_cfa): New static variable. (cfa_remember): Remove static variable. (dwarf2out_def_cfa): Replace label argument with a bool for_cie argument. All callers changed. Don't use lookup_cfa; use and update the global old_cfa variable. Call add_fde_cfi or add_cie_cfi at the end. (reg_save): Replace label argument with a bool. All callers changed. Call add_fde_cfi or add_cie_cfi at the end. (dwarf2out_reg_save, dwarf2out_return_save, dwarf2out_return_reg, dwarf2out_args_szie, dwarf2out_stack_adjust, dwarf2out_reg_save_reg, dwarf2out_frame_debug_def_cfa, dwarf2out_frame_debug_cfa_offset, dwarf2out_frame_debug_cfa_register, dwarf2out_frame_debug_cfa_restore, dwarf2out_frame_debug_cfa_expression, dwarf2out_frame_debug_expr): Remove label argument. All callers changed. (barrier_args_size): Remove variable. (compute_barrier_args_size_1, compute_barrier_args_size): Remove functions. (dwarf2out_notice_stack_adjust): Don't handle barriers. (last_reg_save_label): Remove variable. All sets and uses removed. (cfi_label_required_p, add_cfis_to_fde): New static functions. (dwarf2out_frame_debug_restore_state): Simply add the new CFI. (dwarf2out_frame_debug): Set cfi_insn, and clear it. Don't call dwarf2out_flush_queued_reg_saves at the top. (dwarf2out_frame_debug_init): Initialize old_cfa. (copy_cfi_vec_parts): New static function. (jump_target_info): New struct type. (dwarf2out_cfi_begin_epilogue): Remove. (save_point_p, record_current_state, maybe_record_jump_target, vec_is_prefix_of, append_extra_cfis, debug_cfi_vec, switch_note_p, scan_until_barrier, find_best_starting_point): New static functions. (dwarf2out_frame_debug_after_prologue): New function. (dwarf2out_emit_cfi): New function. (output_cfi_directive): New FILE argument. All callers changed. Avoid some paths if it is not asm_out_file; otherwise print to it. (output_all_cfis): Remove function. (output_cfis): Remove do_cfi_asm arg. All callers changed. Never call output_cfi_directive. (dwarf2out_frame_init): Initialize old_cfa. (dwarf2out_switch_text_section): Don't initialize dw_fde_current_label. Don't call output_all_cfis. * dwarf2out.h (dwarf2out_cfi_label, dwarf2out_def_cfa, dwarf2out_window_save, dwarf2out_reg_save, dwarf2out_return_save, dwarf2out_return_reg, dwarf2out_reg_save_reg, dwarf2out_emit_cfi, dwarf2out_frame_debug_after_prologue): Declare. (dwarf2out_cfi_begin_epilogue, dwarf2out_frame_debug_restore_state): Don't declare. (struct dw_cfi_struct): Add forward declaration. * rtl.h (union rtunion_def): Add rt_cfi member. (XCFI, XCCFI, NOTE_CFI, NOTE_LABEL_NUMBER): New macros. (addr_vec_p): Declare. * config/sparc/sparc.c (sparc_dwarf_handle_frame_unspec): Remove label argument. * config/ia64/ia64.c (ia64_dwarf_handle_frame_unspec): Likewise. * config/arm/arm.c (thumb_pushpop): Use dwarf2out_maybe_emit_cfi_label rather than dwarf2out_cfi_label. (thumb1_output_function_prologue): Likewise. (arm_dwarf_handle_frame_unspec): Remove label argument. --------------080204050101090303000604 Content-Type: text/plain; name="005-scanfirst.diff" Content-Transfer-Encoding: 7bit Content-Disposition: attachment; filename="005-scanfirst.diff" Content-length: 11200 * cfgcleanup.c (flow_find_head_matching_sequence): Ignore epilogue notes. * df-problems.c (can_move_insns_across): Don't stop at epilogue notes. * dwarf2out.c (dwarf2out_cfi_begin_epilogue): Also allow a simplejump to end the block. Index: gcc/dwarf2out.c =================================================================== --- gcc.orig/dwarf2out.c +++ gcc/dwarf2out.c @@ -470,6 +470,8 @@ 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_cfi_begin_epilogue (rtx); +static void dwarf2out_frame_debug_restore_state (void); /* Support for complex CFA locations. */ static void output_cfa_loc (dw_cfi_ref, int); @@ -847,6 +849,15 @@ add_cfi (cfi_vec *vec, dw_cfi_ref cfi) VEC_safe_push (dw_cfi_ref, gc, *vec, cfi); } +/* The insn after which a new CFI note should be emitted. */ +static rtx cfi_insn; + +/* True if remember_state should be emitted before following CFI directive. */ +static bool emit_cfa_remember; + +/* True if any CFI directives were emitted at the current insn. */ +static bool any_cfis_emitted; + /* Generate a new label for the CFI info to refer to. FORCE is true if a label needs to be output even when using .cfi_* directives. */ @@ -866,18 +877,13 @@ dwarf2out_cfi_label (bool force) { int num = dwarf2out_cfi_label_num++; ASM_GENERATE_INTERNAL_LABEL (label, "LCFI", num); - ASM_OUTPUT_DEBUG_LABEL (asm_out_file, "LCFI", num); + cfi_insn = emit_note_after (NOTE_INSN_CFI_LABEL, cfi_insn); + NOTE_LABEL_NUMBER (cfi_insn) = num; } return label; } -/* True if remember_state should be emitted before following CFI directive. */ -static bool emit_cfa_remember; - -/* True if any CFI directives were emitted at the current insn. */ -static bool any_cfis_emitted; - /* Add CFI to the current fde at the PC value indicated by LABEL if specified, or to the CIE if LABEL is NULL. */ @@ -957,7 +963,8 @@ add_fde_cfi (const char *label, dw_cfi_r } } - output_cfi_directive (cfi); + cfi_insn = emit_note_after (NOTE_INSN_CFI, cfi_insn); + NOTE_CFI (cfi_insn) = cfi; vec = &fde->dw_fde_cfi; any_cfis_emitted = true; @@ -2791,6 +2798,11 @@ dwarf2out_frame_debug (rtx insn, bool af rtx note, n; bool handled_one = false; + if (after_p) + cfi_insn = insn; + else + cfi_insn = PREV_INSN (insn); + if (!NONJUMP_INSN_P (insn) || clobbers_queued_reg_save (insn)) dwarf2out_flush_queued_reg_saves (); @@ -2914,6 +2926,7 @@ void dwarf2out_frame_debug_init (void) { size_t i; + rtx insn; /* Flush any queued register saves. */ dwarf2out_flush_queued_reg_saves (); @@ -2940,12 +2953,64 @@ dwarf2out_frame_debug_init (void) XDELETEVEC (barrier_args_size); barrier_args_size = NULL; } + for (insn = get_insns (); insn; insn = NEXT_INSN (insn)) + { + rtx pat; + if (BARRIER_P (insn)) + { + dwarf2out_frame_debug (insn, false); + continue; + } + else if (NOTE_P (insn)) + { + switch (NOTE_KIND (insn)) + { + case NOTE_INSN_EPILOGUE_BEG: +#if defined (HAVE_epilogue) + dwarf2out_cfi_begin_epilogue (insn); +#endif + break; + case NOTE_INSN_CFA_RESTORE_STATE: + cfi_insn = insn; + dwarf2out_frame_debug_restore_state (); + break; + } + continue; + } + if (!NONDEBUG_INSN_P (insn)) + continue; + pat = PATTERN (insn); + if (asm_noperands (pat) >= 0) + continue; + if (GET_CODE (pat) == SEQUENCE) + { + int j; + for (j = 1; j < XVECLEN (pat, 0); j++) + dwarf2out_frame_debug (XVECEXP (pat, 0, j), false); + insn = XVECEXP (pat, 0, 0); + } + + if (CALL_P (insn) && dwarf2out_do_frame ()) + dwarf2out_frame_debug (insn, false); + if (dwarf2out_do_frame () +#if !defined (HAVE_prologue) + && !ACCUMULATE_OUTGOING_ARGS +#endif + ) + dwarf2out_frame_debug (insn, true); + } +} + +void +dwarf2out_emit_cfi (dw_cfi_ref cfi) +{ + output_cfi_directive (cfi); } -/* Determine if we need to save and restore CFI information around this - epilogue. If SIBCALL is true, then this is a sibcall epilogue. If - we do need to save/restore, then emit the save now, and insert a - NOTE_INSN_CFA_RESTORE_STATE at the appropriate place in the stream. */ +/* Determine if we need to save and restore CFI information around + this epilogue. If we do need to save/restore, then emit the save + now, and insert a NOTE_INSN_CFA_RESTORE_STATE at the appropriate + place in the stream. */ void dwarf2out_cfi_begin_epilogue (rtx insn) @@ -2960,8 +3025,10 @@ dwarf2out_cfi_begin_epilogue (rtx insn) if (!INSN_P (i)) continue; - /* Look for both regular and sibcalls to end the block. */ - if (returnjump_p (i)) + /* Look for both regular and sibcalls to end the block. Various + optimization passes may cause us to jump to a common epilogue + tail, so we also accept simplejumps. */ + if (returnjump_p (i) || simplejump_p (i)) break; if (CALL_P (i) && SIBLING_CALL_P (i)) break; Index: gcc/dwarf2out.h =================================================================== --- gcc.orig/dwarf2out.h +++ gcc/dwarf2out.h @@ -18,11 +18,11 @@ You should have received a copy of the G along with GCC; see the file COPYING3. If not see . */ +struct dw_cfi_struct; extern void dwarf2out_decl (tree); extern void dwarf2out_frame_debug (rtx, bool); extern void dwarf2out_frame_debug_init (void); -extern void dwarf2out_cfi_begin_epilogue (rtx); -extern void dwarf2out_frame_debug_restore_state (void); +extern void dwarf2out_emit_cfi (struct dw_cfi_struct *); extern void dwarf2out_flush_queued_reg_saves (void); extern void debug_dwarf (void); Index: gcc/insn-notes.def =================================================================== --- gcc.orig/insn-notes.def +++ gcc/insn-notes.def @@ -77,4 +77,12 @@ INSN_NOTE (SWITCH_TEXT_SECTIONS) when an epilogue appears in the middle of a function. */ INSN_NOTE (CFA_RESTORE_STATE) +/* When emitting dwarf2 frame information, contains a directive that + should be emitted. */ +INSN_NOTE (CFI) + +/* When emitting dwarf2 frame information, contains the number of a debug + label that should be emitted. */ +INSN_NOTE (CFI_LABEL) + #undef INSN_NOTE Index: gcc/rtl.h =================================================================== --- gcc.orig/rtl.h +++ gcc/rtl.h @@ -180,6 +180,7 @@ union rtunion_def mem_attrs *rt_mem; reg_attrs *rt_reg; struct constant_descriptor_rtx *rt_constant; + struct dw_cfi_struct *rt_cfi; }; typedef union rtunion_def rtunion; @@ -708,6 +709,7 @@ extern void rtl_check_failed_flag (const #define XTREE(RTX, N) (RTL_CHECK1 (RTX, N, 't').rt_tree) #define XBBDEF(RTX, N) (RTL_CHECK1 (RTX, N, 'B').rt_bb) #define XTMPL(RTX, N) (RTL_CHECK1 (RTX, N, 'T').rt_str) +#define XCFI(RTX, N) (RTL_CHECK1 (RTX, N, 'C').rt_cfi) #define XVECEXP(RTX, N, M) RTVEC_ELT (XVEC (RTX, N), M) #define XVECLEN(RTX, N) GET_NUM_ELEM (XVEC (RTX, N)) @@ -740,6 +742,7 @@ extern void rtl_check_failed_flag (const #define XCMODE(RTX, N, C) (RTL_CHECKC1 (RTX, N, C).rt_type) #define XCTREE(RTX, N, C) (RTL_CHECKC1 (RTX, N, C).rt_tree) #define XCBBDEF(RTX, N, C) (RTL_CHECKC1 (RTX, N, C).rt_bb) +#define XCCFI(RTX, N, C) (RTL_CHECKC1 (RTX, N, C).rt_cfi) #define XCCSELIB(RTX, N, C) (RTL_CHECKC1 (RTX, N, C).rt_cselib) #define XCVECEXP(RTX, N, M, C) RTVEC_ELT (XCVEC (RTX, N, C), M) @@ -882,6 +885,8 @@ extern const char * const reg_note_name[ #define NOTE_BLOCK(INSN) XCTREE (INSN, 4, NOTE) #define NOTE_EH_HANDLER(INSN) XCINT (INSN, 4, NOTE) #define NOTE_BASIC_BLOCK(INSN) XCBBDEF (INSN, 4, NOTE) +#define NOTE_CFI(INSN) XCCFI (INSN, 4, NOTE) +#define NOTE_LABEL_NUMBER(INSN) XCINT (INSN, 4, NOTE) #define NOTE_VAR_LOCATION(INSN) XCEXP (INSN, 4, NOTE) /* In a NOTE that is a line number, this is the line number. Index: gcc/final.c =================================================================== --- gcc.orig/final.c +++ gcc/final.c @@ -1678,7 +1678,7 @@ final_end_function (void) void final (rtx first, FILE *file, int optimize_p) { - rtx insn; + rtx insn, next; int max_uid = 0; int seen = 0; @@ -1723,6 +1723,15 @@ final (rtx first, FILE *file, int optimi insn = final_scan_insn (insn, file, optimize_p, 0, &seen); } + + for (insn = first; insn; insn = next) + { + next = NEXT_INSN (insn); + if (NOTE_P (insn) + && (NOTE_KIND (insn) == NOTE_INSN_CFI + || NOTE_KIND (insn) == NOTE_INSN_CFI_LABEL)) + delete_insn (insn); + } } const char * @@ -1899,16 +1908,19 @@ final_scan_insn (rtx insn, FILE *file, i break; case NOTE_INSN_EPILOGUE_BEG: -#if defined (HAVE_epilogue) - if (dwarf2out_do_frame ()) - dwarf2out_cfi_begin_epilogue (insn); -#endif (*debug_hooks->begin_epilogue) (last_linenum, last_filename); targetm.asm_out.function_begin_epilogue (file); break; case NOTE_INSN_CFA_RESTORE_STATE: - dwarf2out_frame_debug_restore_state (); + break; + + case NOTE_INSN_CFI: + dwarf2out_emit_cfi (NOTE_CFI (insn)); + break; + + case NOTE_INSN_CFI_LABEL: + ASM_OUTPUT_DEBUG_LABEL (asm_out_file, "LCFI", NOTE_LABEL_NUMBER (insn)); break; case NOTE_INSN_FUNCTION_BEG: @@ -2018,8 +2030,6 @@ final_scan_insn (rtx insn, FILE *file, i break; case BARRIER: - if (dwarf2out_do_frame ()) - dwarf2out_frame_debug (insn, false); break; case CODE_LABEL: @@ -2285,12 +2295,6 @@ final_scan_insn (rtx insn, FILE *file, i final_sequence = body; - /* Record the delay slots' frame information before the branch. - This is needed for delayed calls: see execute_cfa_program(). */ - if (dwarf2out_do_frame ()) - for (i = 1; i < XVECLEN (body, 0); i++) - dwarf2out_frame_debug (XVECEXP (body, 0, i), false); - /* The first insn in this SEQUENCE might be a JUMP_INSN that will force the restoration of a comparison that was previously thought unnecessary. If that happens, cancel this sequence @@ -2604,9 +2608,6 @@ final_scan_insn (rtx insn, FILE *file, i current_output_insn = debug_insn = insn; - if (CALL_P (insn) && dwarf2out_do_frame ()) - dwarf2out_frame_debug (insn, false); - /* Find the proper template for this insn. */ templ = get_insn_template (insn_code_number, insn); @@ -2686,16 +2687,6 @@ final_scan_insn (rtx insn, FILE *file, i targetm.asm_out.final_postscan_insn (file, insn, recog_data.operand, recog_data.n_operands); - /* If necessary, report the effect that the instruction has on - the unwind info. We've already done this for delay slots - and call instructions. */ - if (final_sequence == 0 -#if !defined (HAVE_prologue) - && !ACCUMULATE_OUTGOING_ARGS -#endif - && dwarf2out_do_frame ()) - dwarf2out_frame_debug (insn, true); - if (!targetm.asm_out.unwind_emit_before_insn && targetm.asm_out.unwind_emit) targetm.asm_out.unwind_emit (asm_out_file, insn); --------------080204050101090303000604--