From patchwork Sat Sep 30 09:08:19 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Alexandre Oliva X-Patchwork-Id: 820188 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (mailfrom) smtp.mailfrom=gcc.gnu.org (client-ip=209.132.180.131; helo=sourceware.org; envelope-from=gcc-patches-return-463260-incoming=patchwork.ozlabs.org@gcc.gnu.org; receiver=) Authentication-Results: ozlabs.org; dkim=pass (1024-bit key; unprotected) header.d=gcc.gnu.org header.i=@gcc.gnu.org header.b="pj2Ejpus"; dkim-atps=neutral Received: from sourceware.org (server1.sourceware.org [209.132.180.131]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 3y42gf2xPCz9t2h for ; Sat, 30 Sep 2017 19:09:49 +1000 (AEST) DomainKey-Signature: a=rsa-sha1; c=nofws; d=gcc.gnu.org; h=list-id :list-unsubscribe:list-archive:list-post:list-help:sender:from :to:cc:subject:date:message-id:in-reply-to:references; q=dns; s= default; b=h/YoCt3HOtO9+a3094m6PgAex2b6USsRXlZDExaH5GHmlojt54MP2 4Kfxdoz1Kiam2LKmBe2VdyZFCUw+nPmcBcDj6KAlqDiDNZx83yq+K//vQVV5U3mD q2jfErIlC1IeknIrgaVGdJRntVNW9ujExRcV/YO2ubSIyDCRsNYvyI= DKIM-Signature: v=1; a=rsa-sha1; c=relaxed; d=gcc.gnu.org; h=list-id :list-unsubscribe:list-archive:list-post:list-help:sender:from :to:cc:subject:date:message-id:in-reply-to:references; s= default; bh=js0BjIMvw9r9POgthM9r540OL3Q=; b=pj2EjpusjP6fUT91keAH ssRHr1OZ1dU4MR4dUjcRgnhjPBxbakAjljDRKcftLccoziV0KfOSq0vj3WBZ54AZ prfPvqjlpESNOy+Xv/ugLwTF5oRdqGX3hNYpyeIwmQxyAH8Fx0KlocT6dp85gQTx VSFTNaXtO+/J3+icmhvceO8= Received: (qmail 63167 invoked by alias); 30 Sep 2017 09:09:40 -0000 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 Received: (qmail 63158 invoked by uid 89); 30 Sep 2017 09:09:39 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-25.9 required=5.0 tests=BAYES_00, GIT_PATCH_0, GIT_PATCH_1, GIT_PATCH_2, GIT_PATCH_3, KAM_LAZY_DOMAIN_SECURITY, RP_MATCHES_RCVD, SPF_HELO_PASS autolearn=ham version=3.3.2 spammy=H*Ad:U*aoliva, barriers X-HELO: mx1.redhat.com Received: from mx1.redhat.com (HELO mx1.redhat.com) (209.132.183.28) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Sat, 30 Sep 2017 09:09:38 +0000 Received: from smtp.corp.redhat.com (int-mx06.intmail.prod.int.phx2.redhat.com [10.5.11.16]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 0884637E88; Sat, 30 Sep 2017 09:09:37 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.3.2 mx1.redhat.com 0884637E88 Authentication-Results: ext-mx05.extmail.prod.ext.phx2.redhat.com; dmarc=none (p=none dis=none) header.from=redhat.com Authentication-Results: ext-mx05.extmail.prod.ext.phx2.redhat.com; spf=fail smtp.mailfrom=aoliva@redhat.com Received: from freie.home (ovpn04.gateway.prod.ext.phx2.redhat.com [10.5.9.4]) by smtp.corp.redhat.com (Postfix) with ESMTPS id BDF145C881; Sat, 30 Sep 2017 09:09:36 +0000 (UTC) Received: from frit.home (frit.home [172.31.160.7]) by freie.home (8.15.2/8.15.2) with ESMTP id v8U98pIS022010; Sat, 30 Sep 2017 06:08:51 -0300 From: Alexandre Oliva To: Richard Biener Cc: GCC Patches , Alexandre Oliva Subject: [PATCH 1/9] [SFN] adjust RTL insn-walking API Date: Sat, 30 Sep 2017 06:08:19 -0300 Message-Id: <20170930090827.6604-1-aoliva@redhat.com> In-Reply-To: References: This patch removes unused RTL functions, introduces alternate ones for use in a later SFN patch, and regroups other related functions so that they appear in a more consistent order. for gcc/ChangeLog * emit-rtl.c (next_nondebug_insn, prev_nondebug_insn): Reorder. (next_nonnote_nondebug_insn, prev_nonnote_nondebug_insn): Reorder. (next_nonnote_nondebug_insn_bb): New. (prev_nonnote_nondebug_insn_bb): New. (prev_nonnote_insn_bb, next_nonnote_insn_bb): Remove. * rtl.h (prev_nonnote_insn_bb, next_nonnote_insn_bb): Remove decls. (prev_nonnote_nondebug_insn_bb): Declare. (next_nonnote_nondebug_insn_bb): Declare. * cfgbuild.c (find_bb_boundaries): Adjust to skip debug insns. * cfgrtl.c (get_last_bb_insn): Likewise. * lra.c (push_insns): Likewise. --- gcc/cfgbuild.c | 2 +- gcc/cfgrtl.c | 4 ++-- gcc/emit-rtl.c | 69 ++++++++++++++++++++++++++++++++-------------------------- gcc/lra.c | 2 +- gcc/rtl.h | 4 ++-- 5 files changed, 44 insertions(+), 37 deletions(-) diff --git a/gcc/cfgbuild.c b/gcc/cfgbuild.c index 62956b2..76c21d7 100644 --- a/gcc/cfgbuild.c +++ b/gcc/cfgbuild.c @@ -512,7 +512,7 @@ find_bb_boundaries (basic_block bb) the middle of a BB. We need to split it in the same manner as if the barrier were preceded by a control_flow_insn_p insn. */ if (!flow_transfer_insn) - flow_transfer_insn = prev_nonnote_insn_bb (insn); + flow_transfer_insn = prev_nonnote_nondebug_insn_bb (insn); } if (control_flow_insn_p (insn)) diff --git a/gcc/cfgrtl.c b/gcc/cfgrtl.c index 6ef47b7..bce56b4 100644 --- a/gcc/cfgrtl.c +++ b/gcc/cfgrtl.c @@ -2274,11 +2274,11 @@ get_last_bb_insn (basic_block bb) end = table; /* Include any barriers that may follow the basic block. */ - tmp = next_nonnote_insn_bb (end); + tmp = next_nonnote_nondebug_insn_bb (end); while (tmp && BARRIER_P (tmp)) { end = tmp; - tmp = next_nonnote_insn_bb (end); + tmp = next_nonnote_nondebug_insn_bb (end); } return end; diff --git a/gcc/emit-rtl.c b/gcc/emit-rtl.c index e790cbc..68c1f11 100644 --- a/gcc/emit-rtl.c +++ b/gcc/emit-rtl.c @@ -3355,20 +3355,17 @@ next_nonnote_insn (rtx_insn *insn) return insn; } -/* Return the next insn after INSN that is not a NOTE, but stop the - search before we enter another basic block. This routine does not - look inside SEQUENCEs. */ +/* Return the next insn after INSN that is not a DEBUG_INSN. This + routine does not look inside SEQUENCEs. */ rtx_insn * -next_nonnote_insn_bb (rtx_insn *insn) +next_nondebug_insn (rtx_insn *insn) { while (insn) { insn = NEXT_INSN (insn); - if (insn == 0 || !NOTE_P (insn)) + if (insn == 0 || !DEBUG_INSN_P (insn)) break; - if (NOTE_INSN_BASIC_BLOCK_P (insn)) - return NULL; } return insn; @@ -3390,67 +3387,70 @@ prev_nonnote_insn (rtx_insn *insn) return insn; } -/* Return the previous insn before INSN that is not a NOTE, but stop - the search before we enter another basic block. This routine does - not look inside SEQUENCEs. */ +/* Return the previous insn before INSN that is not a DEBUG_INSN. + This routine does not look inside SEQUENCEs. */ rtx_insn * -prev_nonnote_insn_bb (rtx_insn *insn) +prev_nondebug_insn (rtx_insn *insn) { - while (insn) { insn = PREV_INSN (insn); - if (insn == 0 || !NOTE_P (insn)) + if (insn == 0 || !DEBUG_INSN_P (insn)) break; - if (NOTE_INSN_BASIC_BLOCK_P (insn)) - return NULL; } return insn; } -/* Return the next insn after INSN that is not a DEBUG_INSN. This - routine does not look inside SEQUENCEs. */ +/* Return the next insn after INSN that is not a NOTE nor DEBUG_INSN. + This routine does not look inside SEQUENCEs. */ rtx_insn * -next_nondebug_insn (rtx_insn *insn) +next_nonnote_nondebug_insn (rtx_insn *insn) { while (insn) { insn = NEXT_INSN (insn); - if (insn == 0 || !DEBUG_INSN_P (insn)) + if (insn == 0 || (!NOTE_P (insn) && !DEBUG_INSN_P (insn))) break; } return insn; } -/* Return the previous insn before INSN that is not a DEBUG_INSN. - This routine does not look inside SEQUENCEs. */ +/* Return the next insn after INSN that is not a NOTE nor DEBUG_INSN, + but stop the search before we enter another basic block. This + routine does not look inside SEQUENCEs. */ rtx_insn * -prev_nondebug_insn (rtx_insn *insn) +next_nonnote_nondebug_insn_bb (rtx_insn *insn) { while (insn) { - insn = PREV_INSN (insn); - if (insn == 0 || !DEBUG_INSN_P (insn)) + insn = NEXT_INSN (insn); + if (insn == 0) + break; + if (DEBUG_INSN_P (insn)) + continue; + if (!NOTE_P (insn)) break; + if (NOTE_INSN_BASIC_BLOCK_P (insn)) + return NULL; } return insn; } -/* Return the next insn after INSN that is not a NOTE nor DEBUG_INSN. +/* Return the previous insn before INSN that is not a NOTE nor DEBUG_INSN. This routine does not look inside SEQUENCEs. */ rtx_insn * -next_nonnote_nondebug_insn (rtx_insn *insn) +prev_nonnote_nondebug_insn (rtx_insn *insn) { while (insn) { - insn = NEXT_INSN (insn); + insn = PREV_INSN (insn); if (insn == 0 || (!NOTE_P (insn) && !DEBUG_INSN_P (insn))) break; } @@ -3458,17 +3458,24 @@ next_nonnote_nondebug_insn (rtx_insn *insn) return insn; } -/* Return the previous insn before INSN that is not a NOTE nor DEBUG_INSN. - This routine does not look inside SEQUENCEs. */ +/* Return the previous insn before INSN that is not a NOTE nor + DEBUG_INSN, but stop the search before we enter another basic + block. This routine does not look inside SEQUENCEs. */ rtx_insn * -prev_nonnote_nondebug_insn (rtx_insn *insn) +prev_nonnote_nondebug_insn_bb (rtx_insn *insn) { while (insn) { insn = PREV_INSN (insn); - if (insn == 0 || (!NOTE_P (insn) && !DEBUG_INSN_P (insn))) + if (insn == 0) break; + if (DEBUG_INSN_P (insn)) + continue; + if (!NOTE_P (insn)) + break; + if (NOTE_INSN_BASIC_BLOCK_P (insn)) + return NULL; } return insn; diff --git a/gcc/lra.c b/gcc/lra.c index a473777..9037495 100644 --- a/gcc/lra.c +++ b/gcc/lra.c @@ -1810,7 +1810,7 @@ push_insns (rtx_insn *from, rtx_insn *to) static void setup_sp_offset (rtx_insn *from, rtx_insn *last) { - rtx_insn *before = next_nonnote_insn_bb (last); + rtx_insn *before = next_nonnote_nondebug_insn_bb (last); HOST_WIDE_INT offset = (before == NULL_RTX || ! INSN_P (before) ? 0 : lra_get_insn_recog_data (before)->sp_offset); diff --git a/gcc/rtl.h b/gcc/rtl.h index a63f33e..3bda77c 100644 --- a/gcc/rtl.h +++ b/gcc/rtl.h @@ -2980,13 +2980,13 @@ extern rtx_call_insn *last_call_insn (void); extern rtx_insn *previous_insn (rtx_insn *); extern rtx_insn *next_insn (rtx_insn *); extern rtx_insn *prev_nonnote_insn (rtx_insn *); -extern rtx_insn *prev_nonnote_insn_bb (rtx_insn *); extern rtx_insn *next_nonnote_insn (rtx_insn *); -extern rtx_insn *next_nonnote_insn_bb (rtx_insn *); extern rtx_insn *prev_nondebug_insn (rtx_insn *); extern rtx_insn *next_nondebug_insn (rtx_insn *); extern rtx_insn *prev_nonnote_nondebug_insn (rtx_insn *); +extern rtx_insn *prev_nonnote_nondebug_insn_bb (rtx_insn *); extern rtx_insn *next_nonnote_nondebug_insn (rtx_insn *); +extern rtx_insn *next_nonnote_nondebug_insn_bb (rtx_insn *); extern rtx_insn *prev_real_insn (rtx_insn *); extern rtx_insn *next_real_insn (rtx); extern rtx_insn *prev_active_insn (rtx_insn *); From patchwork Sat Sep 30 09:08:20 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Alexandre Oliva X-Patchwork-Id: 820189 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (mailfrom) smtp.mailfrom=gcc.gnu.org (client-ip=209.132.180.131; helo=sourceware.org; envelope-from=gcc-patches-return-463261-incoming=patchwork.ozlabs.org@gcc.gnu.org; receiver=) Authentication-Results: ozlabs.org; dkim=pass (1024-bit key; unprotected) header.d=gcc.gnu.org header.i=@gcc.gnu.org header.b="a8hqWztl"; dkim-atps=neutral Received: from sourceware.org (server1.sourceware.org [209.132.180.131]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 3y42hC2vx0z9t2h for ; Sat, 30 Sep 2017 19:10:16 +1000 (AEST) DomainKey-Signature: a=rsa-sha1; c=nofws; d=gcc.gnu.org; h=list-id :list-unsubscribe:list-archive:list-post:list-help:sender:from :to:cc:subject:date:message-id:in-reply-to:references; q=dns; s= default; b=mAM1i2Wh0aRunJ946ul4nR5gs/Us2YOsJh1x4r7TdA59YYPYLCSV6 yVf98OPbJtCQk2OkbzkfN3RNRprJlFzB+MyaiydRJ9HLu/EBtSOwFMF7Dh3DLyDs 9kPeyJQOgk3x72tpp78d2cAXM0aXcw8ZSviU7UC4OAfk2aMEcpwYVY= DKIM-Signature: v=1; a=rsa-sha1; c=relaxed; d=gcc.gnu.org; h=list-id :list-unsubscribe:list-archive:list-post:list-help:sender:from :to:cc:subject:date:message-id:in-reply-to:references; s= default; bh=M3BvZvjN1Jsj9U/guF0DwHxF+i0=; b=a8hqWztlOfWVvJ8W0TAL PoJwb0AGDMjwHHRqWv5HZvADCVrdp8N/HDzKFTYZepCUHygVU+o3JU7+FyIiyex+ nqXxYN4ZLf9URo/vaO1K1kBG6gP3T9w65AzlLHJ7ayW5qNP+Pu5CnmOvjm7ZinUh p6b9IiHVz4hPhXiwkLxtEcE= Received: (qmail 63426 invoked by alias); 30 Sep 2017 09:09:42 -0000 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 Received: (qmail 63368 invoked by uid 89); 30 Sep 2017 09:09:42 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-25.9 required=5.0 tests=BAYES_00, GIT_PATCH_0, GIT_PATCH_1, GIT_PATCH_2, GIT_PATCH_3, KAM_LAZY_DOMAIN_SECURITY, RP_MATCHES_RCVD, SPF_HELO_PASS autolearn=ham version=3.3.2 spammy=pat, fortunately X-HELO: mx1.redhat.com Received: from mx1.redhat.com (HELO mx1.redhat.com) (209.132.183.28) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Sat, 30 Sep 2017 09:09:36 +0000 Received: from smtp.corp.redhat.com (int-mx06.intmail.prod.int.phx2.redhat.com [10.5.11.16]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 97EA181DFB; Sat, 30 Sep 2017 09:09:35 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.3.2 mx1.redhat.com 97EA181DFB Authentication-Results: ext-mx01.extmail.prod.ext.phx2.redhat.com; dmarc=none (p=none dis=none) header.from=redhat.com Authentication-Results: ext-mx01.extmail.prod.ext.phx2.redhat.com; spf=fail smtp.mailfrom=aoliva@redhat.com Received: from freie.home (ovpn04.gateway.prod.ext.phx2.redhat.com [10.5.9.4]) by smtp.corp.redhat.com (Postfix) with ESMTPS id C74254CC; Sat, 30 Sep 2017 09:09:34 +0000 (UTC) Received: from frit.home (frit.home [172.31.160.7]) by freie.home (8.15.2/8.15.2) with ESMTP id v8U98pIT022010; Sat, 30 Sep 2017 06:09:15 -0300 From: Alexandre Oliva To: Richard Biener Cc: GCC Patches , Alexandre Oliva Subject: [PATCH 2/9] [SFN] boilerplate changes in preparation to introduce nonbind markers Date: Sat, 30 Sep 2017 06:08:20 -0300 Message-Id: <20170930090827.6604-2-aoliva@redhat.com> In-Reply-To: References: This patch introduces a number of new macros and functions that will be used to distinguish between different kinds of debug stmts, insns and notes, namely, preexisting debug bind ones and to-be-introduced nonbind markers. In a seemingly mechanical way, it adjusts several uses of the macros and functions, so that they refer to narrower categories when appropriate. These changes, by themselves, should not have any visible effect in the compiler behavior, since the upcoming debug markers are never created with this patch alone. for gcc/ChangeLog * gimple.h (enum gimple_debug_subcode): Add GIMPLE_DEBUG_BEGIN_STMT. (gimple_debug_begin_stmt_p): New. (gimple_debug_nonbind_marker_p): New. * tree.h (MAY_HAVE_DEBUG_MARKER_STMTS): New. (MAY_HAVE_DEBUG_BIND_STMTS): Renamed from.... (MAY_HAVE_DEBUG_STMTS): ... this. Check both. * insn-notes.def (BEGIN_STMT): New. * rtl.h (MAY_HAVE_DEBUG_MARKER_INSNS): New. (MAY_HAVE_DEBUG_BIND_INSNS): Renamed from.... (MAY_HAVE_DEBUG_INSNS): ... this. Check both. (NOTE_MARKER_LOCATION, NOTE_MARKER_P): New. (DEBUG_BIND_INSN_P, DEBUG_MARKER_INSN_P): New. (INSN_DEBUG_MARKER_KIND): New. (INSN_VAR_LOCATION): Check for VAR_LOCATION. (INSN_VAR_LOCATION_PTR): New. * cfgexpand.c (expand_debug_locations): Handle debug bind insns only. (expand_gimple_basic_block): Likewise. Emit debug temps for TER deps only if debug bind insns are enabled. (pass_expand::execute): Avoid deep TER and expand debug locations for debug bind insns only. * cgraph.c (cgraph_edge::redirect_call_stmt_to_callee): Narrow debug stmts special handling down to debug bind stmts. * combine.c (try_combine): Narrow debug insns special handling down to debug bind insns. * cse.c (delete_trivially_dead_insns): Handle debug bindings. Narrow debug insns preexisting special handling down to debug bind insns. * dce.c (rest_of_handle_ud_dce): Narrow debug insns special handling down to debug bind insns. * function.c (instantiate_virtual_regs): Skip debug markers, adjust handling of debug binds. * gimple-ssa-backprop.c (backprop::prepare_change): Try debug temp insertion iff MAY_HAVE_DEBUG_BIND_STMTS. * haifa-sched.c (schedule_insn): Narrow special handling of debug insns to debug bind insns. * ipa-prop.c (ipa_modify_call_arguments): Narrow special handling of debug insns to debug bind insns. * ipa-split.c (split_function): Likewise. * ira.c (combine_and_move_insns): Adjust debug bind insns only. * loop-unroll.c (apply_opt_in_copies): Adjust tests on bind debug insns. * reg-stack.c (convert_regs_1): Use DEBUG_BIND_INSN_P. * regrename.c (build_def_use): Likewise. * regcprop.c (copyprop_hardreg_forward_1): Likewise. (pass_cprop_hardreg): Narrow special casing of debug insns to debug bind insns. * regstat.c (regstat_init_n_sets_and_refs): Likewise. * reload1.c (reload): Likewise. * sese.c (sese_build_liveouts): Narrow special casing of debug stmts to debug bind stmts. * shrink-wrap.c (move_insn_for_shrink_wrap): Likewise. * ssa-iterators.h (num_imm_uses): Likewise. * tree-cfg.c (gimple_merge_blocks): Narrow special casing of debug stmts to debug bind stmts. * tree-inline.c (tree_function_versioning): Narrow special casing of debug stmts to debug bind stmts. * tree-loop-distribution.c (generate_loops_for_partition): Narrow special casing of debug stmts to debug bind stmts. * tree-sra.c (analyze_access_subtree): Narrow special casing of debug stmts to debug bind stmts. * tree-ssa-dce.c (remove_dead_stmt): Narrow special casing of debug stmts to debug bind stmts. * tree-ssa-loop-ivopt.c (remove_unused_ivs): Narrow special casing of debug stmts to debug bind stmts. * tree-ssa-reassoc.c (reassoc_remove_stmt): Likewise. * tree-ssa-tail-merge.c (tail_merge_optimize): Narrow special casing of debug stmts to debug bind stmts. * tree-ssa-threadedge.c (propagate_threaded_block_debug_info): Likewise. * tree-ssa.c (flush_pending_stmts): Narrow special casing of debug stmts to debug bind stmts. (gimple_replace_ssa_lhs): Likewise. (insert_debug_temp_for_var_def): Likewise. (insert_debug_temps_for_defs): Likewise. (reset_debug_uses): Likewise. * tree-ssanames.c (release_ssa_name_fn): Likewise. * tree-vect-loop-manip.c (adjust_debug_stmts_now): Likewise. (adjust_debug_stmts): Likewise. (adjust_phi_and_debug_stmts): Likewise. (vect_do_peeling): Likewise. * tree-vect-loop.c (vect_transform_loop): Likewise. * valtrack.c (propagate_for_debug): Use BIND_DEBUG_INSN_P. * var-tracking.c (adjust_mems): Narrow special casing of debug insns to debug bind insns. (dv_onepart_p, dataflow_set_clar_at_call, use_type): Likewise. (compute_bb_dataflow, vt_find_locations): Likewise. (vt_expand_loc, emit_notes_for_changes): Likewise. (vt_init_cfa_base): Likewise. (vt_emit_notes): Likewise. (vt_initialize): Likewise. (vt_finalize): Likewise. --- gcc/cfgexpand.c | 8 +++---- gcc/cgraph.c | 2 +- gcc/combine.c | 12 +++++------ gcc/cse.c | 17 ++++++++------- gcc/dce.c | 2 +- gcc/function.c | 7 ++++--- gcc/gimple-ssa-backprop.c | 2 +- gcc/gimple.h | 31 ++++++++++++++++++++++----- gcc/haifa-sched.c | 4 ++-- gcc/insn-notes.def | 3 +++ gcc/ipa-prop.c | 2 +- gcc/ipa-split.c | 11 +++++----- gcc/ira.c | 4 ++-- gcc/loop-unroll.c | 6 ++++-- gcc/reg-stack.c | 4 ++-- gcc/regcprop.c | 4 ++-- gcc/regrename.c | 2 +- gcc/regstat.c | 2 +- gcc/reload1.c | 4 ++-- gcc/rtl.h | 40 +++++++++++++++++++++++++++++++++-- gcc/sese.c | 2 +- gcc/shrink-wrap.c | 4 ++-- gcc/ssa-iterators.h | 2 +- gcc/tree-cfg.c | 2 +- gcc/tree-inline.c | 4 ++-- gcc/tree-loop-distribution.c | 2 +- gcc/tree-sra.c | 2 +- gcc/tree-ssa-dce.c | 2 +- gcc/tree-ssa-loop-ivopts.c | 2 +- gcc/tree-ssa-reassoc.c | 2 +- gcc/tree-ssa-tail-merge.c | 2 +- gcc/tree-ssa-threadedge.c | 2 +- gcc/tree-ssa.c | 10 ++++----- gcc/tree-ssanames.c | 2 +- gcc/tree-vect-loop-manip.c | 8 +++---- gcc/tree-vect-loop.c | 4 ++-- gcc/tree.h | 8 ++++++- gcc/valtrack.c | 2 +- gcc/var-tracking.c | 50 +++++++++++++++++++++----------------------- 39 files changed, 175 insertions(+), 104 deletions(-) diff --git a/gcc/cfgexpand.c b/gcc/cfgexpand.c index bd3312e..cb866aa 100644 --- a/gcc/cfgexpand.c +++ b/gcc/cfgexpand.c @@ -5285,7 +5285,7 @@ expand_debug_locations (void) flag_strict_aliasing = 0; for (insn = get_insns (); insn; insn = NEXT_INSN (insn)) - if (DEBUG_INSN_P (insn)) + if (DEBUG_BIND_INSN_P (insn)) { tree value = (tree)INSN_VAR_LOCATION_LOC (insn); rtx val; @@ -5538,7 +5538,7 @@ expand_gimple_basic_block (basic_block bb, bool disable_tail_calls) a_2 = ... #DEBUG ... => #D1 */ - if (MAY_HAVE_DEBUG_INSNS + if (MAY_HAVE_DEBUG_BIND_INSNS && SA.values && !is_gimple_debug (stmt)) { @@ -6165,7 +6165,7 @@ pass_expand::execute (function *fun) timevar_pop (TV_OUT_OF_SSA); SA.partition_to_pseudo = XCNEWVEC (rtx, SA.map->num_partitions); - if (MAY_HAVE_DEBUG_STMTS && flag_tree_ter) + if (MAY_HAVE_DEBUG_BIND_STMTS && flag_tree_ter) { gimple_stmt_iterator gsi; FOR_EACH_BB_FN (bb, cfun) @@ -6356,7 +6356,7 @@ pass_expand::execute (function *fun) next_bb) bb = expand_gimple_basic_block (bb, var_ret_seq != NULL_RTX); - if (MAY_HAVE_DEBUG_INSNS) + if (MAY_HAVE_DEBUG_BIND_INSNS) expand_debug_locations (); if (deep_ter_debug_map) diff --git a/gcc/cgraph.c b/gcc/cgraph.c index 3d0cefb..cd60193 100644 --- a/gcc/cgraph.c +++ b/gcc/cgraph.c @@ -1459,7 +1459,7 @@ cgraph_edge::redirect_call_stmt_to_callee (void) stmts and associate D#X with parm in decl_debug_args_lookup vector to say for debug info that if parameter parm had been passed, it would have value parm_Y(D). */ - if (e->callee->clone.combined_args_to_skip && MAY_HAVE_DEBUG_STMTS) + if (e->callee->clone.combined_args_to_skip && MAY_HAVE_DEBUG_BIND_STMTS) { vec **debug_args = decl_debug_args_lookup (e->callee->decl); diff --git a/gcc/combine.c b/gcc/combine.c index e502fa1..86d710d 100644 --- a/gcc/combine.c +++ b/gcc/combine.c @@ -3726,7 +3726,7 @@ try_combine (rtx_insn *i3, rtx_insn *i2, rtx_insn *i1, rtx_insn *i0, /* *SPLIT may be part of I2SRC, so make sure we have the original expression around for later debug processing. We should not need I2SRC any more in other cases. */ - if (MAY_HAVE_DEBUG_INSNS) + if (MAY_HAVE_DEBUG_BIND_INSNS) i2src = copy_rtx (i2src); else i2src = NULL; @@ -4083,7 +4083,7 @@ try_combine (rtx_insn *i3, rtx_insn *i2, rtx_insn *i1, rtx_insn *i0, return 0; } - if (MAY_HAVE_DEBUG_INSNS) + if (MAY_HAVE_DEBUG_BIND_INSNS) { struct undo *undo; @@ -4396,7 +4396,7 @@ try_combine (rtx_insn *i3, rtx_insn *i2, rtx_insn *i1, rtx_insn *i0, if (newi2pat) { - if (MAY_HAVE_DEBUG_INSNS && i2scratch) + if (MAY_HAVE_DEBUG_BIND_INSNS && i2scratch) propagate_for_debug (i2, last_combined_insn, i2dest, i2src, this_basic_block); INSN_CODE (i2) = i2_code_number; @@ -4404,7 +4404,7 @@ try_combine (rtx_insn *i3, rtx_insn *i2, rtx_insn *i1, rtx_insn *i0, } else { - if (MAY_HAVE_DEBUG_INSNS && i2src) + if (MAY_HAVE_DEBUG_BIND_INSNS && i2src) propagate_for_debug (i2, last_combined_insn, i2dest, i2src, this_basic_block); SET_INSN_DELETED (i2); @@ -4414,7 +4414,7 @@ try_combine (rtx_insn *i3, rtx_insn *i2, rtx_insn *i1, rtx_insn *i0, { LOG_LINKS (i1) = NULL; REG_NOTES (i1) = 0; - if (MAY_HAVE_DEBUG_INSNS) + if (MAY_HAVE_DEBUG_BIND_INSNS) propagate_for_debug (i1, last_combined_insn, i1dest, i1src, this_basic_block); SET_INSN_DELETED (i1); @@ -4424,7 +4424,7 @@ try_combine (rtx_insn *i3, rtx_insn *i2, rtx_insn *i1, rtx_insn *i0, { LOG_LINKS (i0) = NULL; REG_NOTES (i0) = 0; - if (MAY_HAVE_DEBUG_INSNS) + if (MAY_HAVE_DEBUG_BIND_INSNS) propagate_for_debug (i0, last_combined_insn, i0dest, i0src, this_basic_block); SET_INSN_DELETED (i0); diff --git a/gcc/cse.c b/gcc/cse.c index 672fd2e..d1577a6 100644 --- a/gcc/cse.c +++ b/gcc/cse.c @@ -7054,11 +7054,11 @@ delete_trivially_dead_insns (rtx_insn *insns, int nreg) timevar_push (TV_DELETE_TRIVIALLY_DEAD); /* First count the number of times each register is used. */ - if (MAY_HAVE_DEBUG_INSNS) + if (MAY_HAVE_DEBUG_BIND_INSNS) { counts = XCNEWVEC (int, nreg * 3); for (insn = insns; insn; insn = NEXT_INSN (insn)) - if (DEBUG_INSN_P (insn)) + if (DEBUG_BIND_INSN_P (insn)) count_reg_usage (INSN_VAR_LOCATION_LOC (insn), counts + nreg, NULL_RTX, 1); else if (INSN_P (insn)) @@ -7116,12 +7116,15 @@ delete_trivially_dead_insns (rtx_insn *insns, int nreg) if (! live_insn && dbg_cnt (delete_trivial_dead)) { if (DEBUG_INSN_P (insn)) - count_reg_usage (INSN_VAR_LOCATION_LOC (insn), counts + nreg, - NULL_RTX, -1); + { + if (DEBUG_BIND_INSN_P (insn)) + count_reg_usage (INSN_VAR_LOCATION_LOC (insn), counts + nreg, + NULL_RTX, -1); + } else { rtx set; - if (MAY_HAVE_DEBUG_INSNS + if (MAY_HAVE_DEBUG_BIND_INSNS && (set = single_set (insn)) != NULL_RTX && is_dead_reg (SET_DEST (set), counts) /* Used at least once in some DEBUG_INSN. */ @@ -7161,10 +7164,10 @@ delete_trivially_dead_insns (rtx_insn *insns, int nreg) } } - if (MAY_HAVE_DEBUG_INSNS) + if (MAY_HAVE_DEBUG_BIND_INSNS) { for (insn = get_last_insn (); insn; insn = PREV_INSN (insn)) - if (DEBUG_INSN_P (insn)) + if (DEBUG_BIND_INSN_P (insn)) { /* If this debug insn references a dead register that wasn't replaced with an DEBUG_EXPR, reset the DEBUG_INSN. */ diff --git a/gcc/dce.c b/gcc/dce.c index 7534d2a..6fd9548 100644 --- a/gcc/dce.c +++ b/gcc/dce.c @@ -777,7 +777,7 @@ rest_of_handle_ud_dce (void) } worklist.release (); - if (MAY_HAVE_DEBUG_INSNS) + if (MAY_HAVE_DEBUG_BIND_INSNS) reset_unmarked_insns_debug_uses (); /* Before any insns are deleted, we must remove the chains since diff --git a/gcc/function.c b/gcc/function.c index c03e2ac..ae61d3d 100644 --- a/gcc/function.c +++ b/gcc/function.c @@ -1951,10 +1951,11 @@ instantiate_virtual_regs (void) Fortunately, they shouldn't contain virtual registers either. */ if (GET_CODE (PATTERN (insn)) == USE || GET_CODE (PATTERN (insn)) == CLOBBER - || GET_CODE (PATTERN (insn)) == ASM_INPUT) + || GET_CODE (PATTERN (insn)) == ASM_INPUT + || DEBUG_MARKER_INSN_P (insn)) continue; - else if (DEBUG_INSN_P (insn)) - instantiate_virtual_regs_in_rtx (&INSN_VAR_LOCATION (insn)); + else if (DEBUG_BIND_INSN_P (insn)) + instantiate_virtual_regs_in_rtx (INSN_VAR_LOCATION_PTR (insn)); else instantiate_virtual_regs_in_insn (insn); diff --git a/gcc/gimple-ssa-backprop.c b/gcc/gimple-ssa-backprop.c index f321ebb..b6e11c4 100644 --- a/gcc/gimple-ssa-backprop.c +++ b/gcc/gimple-ssa-backprop.c @@ -726,7 +726,7 @@ strip_sign_op (tree rhs) void backprop::prepare_change (tree var) { - if (MAY_HAVE_DEBUG_STMTS) + if (MAY_HAVE_DEBUG_BIND_STMTS) insert_debug_temp_for_var_def (NULL, var); reset_flow_sensitive_info (var); } diff --git a/gcc/gimple.h b/gcc/gimple.h index 6213c49..1783e11 100644 --- a/gcc/gimple.h +++ b/gcc/gimple.h @@ -198,13 +198,12 @@ enum gf_mask { GF_PREDICT_TAKEN = 1 << 15 }; -/* Currently, there are only two types of gimple debug stmt. Others are - envisioned, for example, to enable the generation of is_stmt notes - in line number information, to mark sequence points, etc. This - subcode is to be used to tell them apart. */ +/* This subcode tells apart different kinds of stmts that are not used + for codegen, but rather to retain debug information. */ enum gimple_debug_subcode { GIMPLE_DEBUG_BIND = 0, - GIMPLE_DEBUG_SOURCE_BIND = 1 + GIMPLE_DEBUG_SOURCE_BIND = 1, + GIMPLE_DEBUG_BEGIN_STMT = 2 }; /* Masks for selecting a pass local flag (PLF) to work on. These @@ -4739,6 +4738,28 @@ gimple_debug_source_bind_set_value (gimple *dbg, tree value) gimple_set_op (dbg, 1, value); } +/* Return true if S is a GIMPLE_DEBUG BEGIN_STMT statement. */ + +static inline bool +gimple_debug_begin_stmt_p (const gimple *s) +{ + if (is_gimple_debug (s)) + return s->subcode == GIMPLE_DEBUG_BEGIN_STMT; + + return false; +} + +/* Return true if S is a GIMPLE_DEBUG non-binding marker statement. */ + +static inline bool +gimple_debug_nonbind_marker_p (const gimple *s) +{ + if (is_gimple_debug (s)) + return s->subcode == GIMPLE_DEBUG_BEGIN_STMT; + + return false; +} + /* Return the line number for EXPR, or return -1 if we have no line number information for it. */ static inline int diff --git a/gcc/haifa-sched.c b/gcc/haifa-sched.c index 549e896..34cc46b 100644 --- a/gcc/haifa-sched.c +++ b/gcc/haifa-sched.c @@ -4010,7 +4010,7 @@ schedule_insn (rtx_insn *insn) gcc_assert (sd_lists_empty_p (insn, SD_LIST_HARD_BACK)); /* Reset debug insns invalidated by moving this insn. */ - if (MAY_HAVE_DEBUG_INSNS && !DEBUG_INSN_P (insn)) + if (MAY_HAVE_DEBUG_BIND_INSNS && !DEBUG_INSN_P (insn)) for (sd_it = sd_iterator_start (insn, SD_LIST_BACK); sd_iterator_cond (&sd_it, &dep);) { @@ -4023,7 +4023,7 @@ schedule_insn (rtx_insn *insn) continue; } - gcc_assert (DEBUG_INSN_P (dbg)); + gcc_assert (DEBUG_BIND_INSN_P (dbg)); if (sched_verbose >= 6) fprintf (sched_dump, ";;\t\tresetting: debug insn %d\n", diff --git a/gcc/insn-notes.def b/gcc/insn-notes.def index f96ce18..960487b 100644 --- a/gcc/insn-notes.def +++ b/gcc/insn-notes.def @@ -68,6 +68,9 @@ INSN_NOTE (VAR_LOCATION) /* The values passed to callee. */ INSN_NOTE (CALL_ARG_LOCATION) +/* The beginning of a statement. */ +INSN_NOTE (BEGIN_STMT) + /* Record the struct for the following basic block. Uses NOTE_BASIC_BLOCK. FIXME: Redundant with the basic block pointer now included in every insn. NOTE: If there's no CFG anymore, in other words, diff --git a/gcc/ipa-prop.c b/gcc/ipa-prop.c index 51f6221..2d15504 100644 --- a/gcc/ipa-prop.c +++ b/gcc/ipa-prop.c @@ -4410,7 +4410,7 @@ ipa_modify_call_arguments (struct cgraph_edge *cs, gcall *stmt, } vargs.quick_push (expr); } - if (adj->op != IPA_PARM_OP_COPY && MAY_HAVE_DEBUG_STMTS) + if (adj->op != IPA_PARM_OP_COPY && MAY_HAVE_DEBUG_BIND_STMTS) { unsigned int ix; tree ddecl = NULL_TREE, origin = DECL_ORIGIN (adj->base), arg; diff --git a/gcc/ipa-split.c b/gcc/ipa-split.c index e3759d6..d45e951 100644 --- a/gcc/ipa-split.c +++ b/gcc/ipa-split.c @@ -1471,7 +1471,7 @@ split_function (basic_block return_bb, struct split_point *split_point, { vec **debug_args = NULL; unsigned i = 0, len = 0; - if (MAY_HAVE_DEBUG_STMTS) + if (MAY_HAVE_DEBUG_BIND_STMTS) { debug_args = decl_debug_args_lookup (node->decl); if (debug_args) @@ -1484,11 +1484,12 @@ split_function (basic_block return_bb, struct split_point *split_point, tree ddecl; gimple *def_temp; - /* This needs to be done even without MAY_HAVE_DEBUG_STMTS, - otherwise if it didn't exist before, we'd end up with - different SSA_NAME_VERSIONs between -g and -g0. */ + /* This needs to be done even without + MAY_HAVE_DEBUG_BIND_STMTS, otherwise if it didn't exist + before, we'd end up with different SSA_NAME_VERSIONs + between -g and -g0. */ arg = get_or_create_ssa_default_def (cfun, parm); - if (!MAY_HAVE_DEBUG_STMTS || debug_args == NULL) + if (!MAY_HAVE_DEBUG_BIND_STMTS || debug_args == NULL) continue; while (i < len && (**debug_args)[i] != DECL_ORIGIN (parm)) diff --git a/gcc/ira.c b/gcc/ira.c index 046ce3b..17f54a0 100644 --- a/gcc/ira.c +++ b/gcc/ira.c @@ -3842,9 +3842,9 @@ combine_and_move_insns (void) } /* Last pass - adjust debug insns referencing cleared regs. */ - if (MAY_HAVE_DEBUG_INSNS) + if (MAY_HAVE_DEBUG_BIND_INSNS) for (rtx_insn *insn = get_insns (); insn; insn = NEXT_INSN (insn)) - if (DEBUG_INSN_P (insn)) + if (DEBUG_BIND_INSN_P (insn)) { rtx old_loc = INSN_VAR_LOCATION_LOC (insn); INSN_VAR_LOCATION_LOC (insn) diff --git a/gcc/loop-unroll.c b/gcc/loop-unroll.c index 322f151..923be72 100644 --- a/gcc/loop-unroll.c +++ b/gcc/loop-unroll.c @@ -2026,12 +2026,14 @@ apply_opt_in_copies (struct opt_info *opt_info, FOR_BB_INSNS_SAFE (bb, insn, next) { if (!INSN_P (insn) - || (DEBUG_INSN_P (insn) + || (DEBUG_BIND_INSN_P (insn) + && INSN_VAR_LOCATION_DECL (insn) && TREE_CODE (INSN_VAR_LOCATION_DECL (insn)) == LABEL_DECL)) continue; while (!INSN_P (orig_insn) - || (DEBUG_INSN_P (orig_insn) + || (DEBUG_BIND_INSN_P (orig_insn) + && INSN_VAR_LOCATION_DECL (orig_insn) && (TREE_CODE (INSN_VAR_LOCATION_DECL (orig_insn)) == LABEL_DECL))) orig_insn = NEXT_INSN (orig_insn); diff --git a/gcc/reg-stack.c b/gcc/reg-stack.c index f238106..e62ccda 100644 --- a/gcc/reg-stack.c +++ b/gcc/reg-stack.c @@ -3028,7 +3028,7 @@ convert_regs_1 (basic_block block) /* Don't bother processing unless there is a stack reg mentioned or if it's a CALL_INSN. */ - if (DEBUG_INSN_P (insn)) + if (DEBUG_BIND_INSN_P (insn)) { if (starting_stack_p) debug_insns_with_starting_stack++; @@ -3068,7 +3068,7 @@ convert_regs_1 (basic_block block) for (insn = BB_HEAD (block); debug_insns_with_starting_stack; insn = NEXT_INSN (insn)) { - if (!DEBUG_INSN_P (insn)) + if (!DEBUG_BIND_INSN_P (insn)) continue; debug_insns_with_starting_stack--; diff --git a/gcc/regcprop.c b/gcc/regcprop.c index 73e945d4..0ce64d7 100644 --- a/gcc/regcprop.c +++ b/gcc/regcprop.c @@ -757,7 +757,7 @@ copyprop_hardreg_forward_1 (basic_block bb, struct value_data *vd) next = NEXT_INSN (insn); if (!NONDEBUG_INSN_P (insn)) { - if (DEBUG_INSN_P (insn)) + if (DEBUG_BIND_INSN_P (insn)) { rtx loc = INSN_VAR_LOCATION_LOC (insn); if (!VAR_LOC_UNKNOWN_P (loc)) @@ -1302,7 +1302,7 @@ pass_cprop_hardreg::execute (function *fun) copyprop_hardreg_forward_1 (bb, all_vd + bb->index); } - if (MAY_HAVE_DEBUG_INSNS) + if (MAY_HAVE_DEBUG_BIND_INSNS) { FOR_EACH_BB_FN (bb, fun) if (bitmap_bit_p (visited, bb->index) diff --git a/gcc/regrename.c b/gcc/regrename.c index 7fbfa31..89380a8 100644 --- a/gcc/regrename.c +++ b/gcc/regrename.c @@ -1876,7 +1876,7 @@ build_def_use (basic_block bb) if (REG_NOTE_KIND (note) == REG_CFA_RESTORE) scan_rtx (insn, &XEXP (note, 0), NO_REGS, mark_all_read, OP_IN); } - else if (DEBUG_INSN_P (insn) + else if (DEBUG_BIND_INSN_P (insn) && !VAR_LOC_UNKNOWN_P (INSN_VAR_LOCATION_LOC (insn))) { scan_rtx (insn, &INSN_VAR_LOCATION_LOC (insn), diff --git a/gcc/regstat.c b/gcc/regstat.c index 3fd26fd..fd3d3a8 100644 --- a/gcc/regstat.c +++ b/gcc/regstat.c @@ -54,7 +54,7 @@ regstat_init_n_sets_and_refs (void) regstat_n_sets_and_refs = XNEWVEC (struct regstat_n_sets_and_refs_t, max_regno); - if (MAY_HAVE_DEBUG_INSNS) + if (MAY_HAVE_DEBUG_BIND_INSNS) for (i = 0; i < max_regno; i++) { int use_count; diff --git a/gcc/reload1.c b/gcc/reload1.c index 5e200b9..cf18b30 100644 --- a/gcc/reload1.c +++ b/gcc/reload1.c @@ -1112,7 +1112,7 @@ reload (rtx_insn *first, int global) /* We don't want complex addressing modes in debug insns if simpler ones will do, so delegitimize equivalences in debug insns. */ - if (MAY_HAVE_DEBUG_INSNS && reg_renumber[i] < 0) + if (MAY_HAVE_DEBUG_BIND_INSNS && reg_renumber[i] < 0) { rtx reg = regno_reg_rtx[i]; rtx equiv = 0; @@ -1140,7 +1140,7 @@ reload (rtx_insn *first, int global) while (next && DF_REF_INSN (next) == insn) next = DF_REF_NEXT_REG (next); - if (DEBUG_INSN_P (insn)) + if (DEBUG_BIND_INSN_P (insn)) { if (!equiv) { diff --git a/gcc/rtl.h b/gcc/rtl.h index 3bda77c..c79a277 100644 --- a/gcc/rtl.h +++ b/gcc/rtl.h @@ -815,8 +815,13 @@ struct GTY(()) rtvec_def { /* Predicate yielding nonzero iff X is an insn that is not a debug insn. */ #define NONDEBUG_INSN_P(X) (INSN_P (X) && !DEBUG_INSN_P (X)) +/* Nonzero if DEBUG_MARKER_INSN_P may possibly hold. */ +#define MAY_HAVE_DEBUG_MARKER_INSNS 0 /* debug_nonbind_markers_p */ +/* Nonzero if DEBUG_BIND_INSN_P may possibly hold. */ +#define MAY_HAVE_DEBUG_BIND_INSNS flag_var_tracking_assignments /* Nonzero if DEBUG_INSN_P may possibly hold. */ -#define MAY_HAVE_DEBUG_INSNS (flag_var_tracking_assignments) +#define MAY_HAVE_DEBUG_INSNS \ + (MAY_HAVE_DEBUG_MARKER_INSNS || MAY_HAVE_DEBUG_BIND_INSNS) /* Predicate yielding nonzero iff X is a real insn. */ #define INSN_P(X) \ @@ -1604,6 +1609,7 @@ extern const char * const reg_note_name[]; #define NOTE_EH_HANDLER(INSN) XCINT (INSN, 3, NOTE) #define NOTE_BASIC_BLOCK(INSN) XCBBDEF (INSN, 3, NOTE) #define NOTE_VAR_LOCATION(INSN) XCEXP (INSN, 3, NOTE) +#define NOTE_MARKER_LOCATION(INSN) XCUINT (INSN, 3, NOTE) #define NOTE_CFI(INSN) XCCFI (INSN, 3, NOTE) #define NOTE_LABEL_NUMBER(INSN) XCINT (INSN, 3, NOTE) @@ -1615,6 +1621,12 @@ extern const char * const reg_note_name[]; #define NOTE_INSN_BASIC_BLOCK_P(INSN) \ (NOTE_P (INSN) && NOTE_KIND (INSN) == NOTE_INSN_BASIC_BLOCK) +/* Nonzero if INSN is a debug nonbind marker note, + for which NOTE_MARKER_LOCATION can be used. */ +#define NOTE_MARKER_P(INSN) \ + (NOTE_P (INSN) && \ + (NOTE_KIND (INSN) == NOTE_INSN_BEGIN_STMT)) + /* Variable declaration and the location of a variable. */ #define PAT_VAR_LOCATION_DECL(PAT) (XCTREE ((PAT), 0, VAR_LOCATION)) #define PAT_VAR_LOCATION_LOC(PAT) (XCEXP ((PAT), 1, VAR_LOCATION)) @@ -1634,8 +1646,32 @@ extern const char * const reg_note_name[]; #define NOTE_VAR_LOCATION_STATUS(NOTE) \ PAT_VAR_LOCATION_STATUS (NOTE_VAR_LOCATION (NOTE)) +/* Evaluate to TRUE if INSN is a debug insn that denotes a variable + location/value tracking annotation. */ +#define DEBUG_BIND_INSN_P(INSN) \ + (DEBUG_INSN_P (INSN) \ + && (GET_CODE (PATTERN (INSN)) \ + == VAR_LOCATION)) +/* Evaluate to TRUE if INSN is a debug insn that denotes a program + source location marker. */ +#define DEBUG_MARKER_INSN_P(INSN) \ + (DEBUG_INSN_P (INSN) \ + && (GET_CODE (PATTERN (INSN)) \ + != VAR_LOCATION)) +/* Evaluate to the marker kind. */ +#define INSN_DEBUG_MARKER_KIND(INSN) \ + (GET_CODE (PATTERN (INSN)) == DEBUG_MARKER \ + ? (GET_MODE (PATTERN (INSN)) == VOIDmode \ + ? NOTE_INSN_BEGIN_STMT \ + : (enum insn_note)-1) \ + : (enum insn_note)-1) + /* The VAR_LOCATION rtx in a DEBUG_INSN. */ -#define INSN_VAR_LOCATION(INSN) PATTERN (INSN) +#define INSN_VAR_LOCATION(INSN) \ + (RTL_FLAG_CHECK1 ("INSN_VAR_LOCATION", PATTERN (INSN), VAR_LOCATION)) +/* A pointer to the VAR_LOCATION rtx in a DEBUG_INSN. */ +#define INSN_VAR_LOCATION_PTR(INSN) \ + (&PATTERN (INSN)) /* Accessors for a tree-expanded var location debug insn. */ #define INSN_VAR_LOCATION_DECL(INSN) \ diff --git a/gcc/sese.c b/gcc/sese.c index ad85aa4..a24688f 100644 --- a/gcc/sese.c +++ b/gcc/sese.c @@ -164,7 +164,7 @@ sese_build_liveouts (sese_info_p region, bitmap liveouts) sese_build_liveouts_bb (region, liveouts, bb); /* FIXME: We could start iterating form the successor of sese. */ - if (MAY_HAVE_DEBUG_STMTS) + if (MAY_HAVE_DEBUG_BIND_STMTS) FOR_EACH_BB_FN (bb, cfun) if (!bb_in_sese_p (bb, region->region)) sese_reset_debug_liveouts_bb (region, liveouts, bb); diff --git a/gcc/shrink-wrap.c b/gcc/shrink-wrap.c index 3cad776..85fe81d 100644 --- a/gcc/shrink-wrap.c +++ b/gcc/shrink-wrap.c @@ -309,10 +309,10 @@ move_insn_for_shrink_wrap (basic_block bb, rtx_insn *insn, move it as far as we can. */ do { - if (MAY_HAVE_DEBUG_INSNS) + if (MAY_HAVE_DEBUG_BIND_INSNS) { FOR_BB_INSNS_REVERSE (bb, dinsn) - if (DEBUG_INSN_P (dinsn)) + if (DEBUG_BIND_INSN_P (dinsn)) { df_ref use; FOR_EACH_INSN_USE (use, dinsn) diff --git a/gcc/ssa-iterators.h b/gcc/ssa-iterators.h index c8aa77b..dca0439 100644 --- a/gcc/ssa-iterators.h +++ b/gcc/ssa-iterators.h @@ -447,7 +447,7 @@ num_imm_uses (const_tree var) const ssa_use_operand_t *ptr; unsigned int num = 0; - if (!MAY_HAVE_DEBUG_STMTS) + if (!MAY_HAVE_DEBUG_BIND_STMTS) { for (ptr = start->next; ptr != start; ptr = ptr->next) if (USE_STMT (ptr)) diff --git a/gcc/tree-cfg.c b/gcc/tree-cfg.c index 99d1f1e..dc9ce3c 100644 --- a/gcc/tree-cfg.c +++ b/gcc/tree-cfg.c @@ -2054,7 +2054,7 @@ gimple_merge_blocks (basic_block a, basic_block b) gsi_insert_before (&dest_gsi, stmt, GSI_NEW_STMT); } /* Other user labels keep around in a form of a debug stmt. */ - else if (!DECL_ARTIFICIAL (label) && MAY_HAVE_DEBUG_STMTS) + else if (!DECL_ARTIFICIAL (label) && MAY_HAVE_DEBUG_BIND_STMTS) { gimple *dbg = gimple_build_debug_bind (label, integer_zero_node, diff --git a/gcc/tree-inline.c b/gcc/tree-inline.c index a226096..a142488 100644 --- a/gcc/tree-inline.c +++ b/gcc/tree-inline.c @@ -6032,7 +6032,7 @@ tree_function_versioning (tree old_decl, tree new_decl, &vars); if (init) init_stmts.safe_push (init); - if (MAY_HAVE_DEBUG_STMTS && args_to_skip) + if (MAY_HAVE_DEBUG_BIND_STMTS && args_to_skip) { if (parm_num == -1) { @@ -6178,7 +6178,7 @@ tree_function_versioning (tree old_decl, tree new_decl, } } - if (debug_args_to_skip && MAY_HAVE_DEBUG_STMTS) + if (debug_args_to_skip && MAY_HAVE_DEBUG_BIND_STMTS) { tree parm; vec **debug_args = NULL; diff --git a/gcc/tree-loop-distribution.c b/gcc/tree-loop-distribution.c index 26b8b9a..65ccd71 100644 --- a/gcc/tree-loop-distribution.c +++ b/gcc/tree-loop-distribution.c @@ -807,7 +807,7 @@ generate_loops_for_partition (struct loop *loop, partition *partition, /* Remove stmts not in the PARTITION bitmap. */ bbs = get_loop_body_in_dom_order (loop); - if (MAY_HAVE_DEBUG_STMTS) + if (MAY_HAVE_DEBUG_BIND_STMTS) for (i = 0; i < loop->num_nodes; i++) { basic_block bb = bbs[i]; diff --git a/gcc/tree-sra.c b/gcc/tree-sra.c index f5675ed..e7167e7 100644 --- a/gcc/tree-sra.c +++ b/gcc/tree-sra.c @@ -2477,7 +2477,7 @@ analyze_access_subtree (struct access *root, struct access *parent, gcc_checking_assert (!root->grp_scalar_read && !root->grp_assignment_read); sth_created = true; - if (MAY_HAVE_DEBUG_STMTS) + if (MAY_HAVE_DEBUG_BIND_STMTS) { root->grp_to_be_debug_replaced = 1; root->replacement_decl = create_access_replacement (root); diff --git a/gcc/tree-ssa-dce.c b/gcc/tree-ssa-dce.c index e62afad..f60670f 100644 --- a/gcc/tree-ssa-dce.c +++ b/gcc/tree-ssa-dce.c @@ -1086,7 +1086,7 @@ remove_dead_stmt (gimple_stmt_iterator *i, basic_block bb) /* If this is a store into a variable that is being optimized away, add a debug bind stmt if possible. */ - if (MAY_HAVE_DEBUG_STMTS + if (MAY_HAVE_DEBUG_BIND_STMTS && gimple_assign_single_p (stmt) && is_gimple_val (gimple_assign_rhs1 (stmt))) { diff --git a/gcc/tree-ssa-loop-ivopts.c b/gcc/tree-ssa-loop-ivopts.c index bbea619..f8fe317 100644 --- a/gcc/tree-ssa-loop-ivopts.c +++ b/gcc/tree-ssa-loop-ivopts.c @@ -7148,7 +7148,7 @@ remove_unused_ivs (struct ivopts_data *data) tree def = info->iv->ssa_name; - if (MAY_HAVE_DEBUG_STMTS && SSA_NAME_DEF_STMT (def)) + if (MAY_HAVE_DEBUG_BIND_STMTS && SSA_NAME_DEF_STMT (def)) { imm_use_iterator imm_iter; use_operand_p use_p; diff --git a/gcc/tree-ssa-reassoc.c b/gcc/tree-ssa-reassoc.c index b2d0f57..a671a16 100644 --- a/gcc/tree-ssa-reassoc.c +++ b/gcc/tree-ssa-reassoc.c @@ -232,7 +232,7 @@ reassoc_remove_stmt (gimple_stmt_iterator *gsi) { gimple *stmt = gsi_stmt (*gsi); - if (!MAY_HAVE_DEBUG_STMTS || gimple_code (stmt) == GIMPLE_PHI) + if (!MAY_HAVE_DEBUG_BIND_STMTS || gimple_code (stmt) == GIMPLE_PHI) return gsi_remove (gsi, true); gimple_stmt_iterator prev = *gsi; diff --git a/gcc/tree-ssa-tail-merge.c b/gcc/tree-ssa-tail-merge.c index a65ff31..a3d5074 100644 --- a/gcc/tree-ssa-tail-merge.c +++ b/gcc/tree-ssa-tail-merge.c @@ -1802,7 +1802,7 @@ tail_merge_optimize (unsigned int todo) if (nr_bbs_removed_total > 0) { - if (MAY_HAVE_DEBUG_STMTS) + if (MAY_HAVE_DEBUG_BIND_STMTS) { calculate_dominance_info (CDI_DOMINATORS); update_debug_stmts (); diff --git a/gcc/tree-ssa-threadedge.c b/gcc/tree-ssa-threadedge.c index 536c471..70675e4 100644 --- a/gcc/tree-ssa-threadedge.c +++ b/gcc/tree-ssa-threadedge.c @@ -692,7 +692,7 @@ simplify_control_stmt_condition_1 (edge e, void propagate_threaded_block_debug_into (basic_block dest, basic_block src) { - if (!MAY_HAVE_DEBUG_STMTS) + if (!MAY_HAVE_DEBUG_BIND_STMTS) return; if (!single_pred_p (dest)) diff --git a/gcc/tree-ssa.c b/gcc/tree-ssa.c index 8b6da96..151f544 100644 --- a/gcc/tree-ssa.c +++ b/gcc/tree-ssa.c @@ -220,7 +220,7 @@ flush_pending_stmts (edge e) void gimple_replace_ssa_lhs (gimple *stmt, tree nlhs) { - if (MAY_HAVE_DEBUG_STMTS) + if (MAY_HAVE_DEBUG_BIND_STMTS) { tree lhs = gimple_get_lhs (stmt); @@ -242,7 +242,7 @@ gimple_replace_ssa_lhs (gimple *stmt, tree nlhs) tree target_for_debug_bind (tree var) { - if (!MAY_HAVE_DEBUG_STMTS) + if (!MAY_HAVE_DEBUG_BIND_STMTS) return NULL_TREE; if (TREE_CODE (var) == SSA_NAME) @@ -307,7 +307,7 @@ insert_debug_temp_for_var_def (gimple_stmt_iterator *gsi, tree var) int usecount = 0; tree value = NULL; - if (!MAY_HAVE_DEBUG_STMTS) + if (!MAY_HAVE_DEBUG_BIND_STMTS) return; /* If this name has already been registered for replacement, do nothing @@ -495,7 +495,7 @@ insert_debug_temps_for_defs (gimple_stmt_iterator *gsi) ssa_op_iter op_iter; def_operand_p def_p; - if (!MAY_HAVE_DEBUG_STMTS) + if (!MAY_HAVE_DEBUG_BIND_STMTS) return; stmt = gsi_stmt (*gsi); @@ -521,7 +521,7 @@ reset_debug_uses (gimple *stmt) imm_use_iterator imm_iter; gimple *use_stmt; - if (!MAY_HAVE_DEBUG_STMTS) + if (!MAY_HAVE_DEBUG_BIND_STMTS) return; FOR_EACH_PHI_OR_STMT_DEF (def_p, stmt, op_iter, SSA_OP_DEF) diff --git a/gcc/tree-ssanames.c b/gcc/tree-ssanames.c index 5c96075..4318adc 100644 --- a/gcc/tree-ssanames.c +++ b/gcc/tree-ssanames.c @@ -562,7 +562,7 @@ release_ssa_name_fn (struct function *fn, tree var) int saved_ssa_name_version = SSA_NAME_VERSION (var); use_operand_p imm = &(SSA_NAME_IMM_USE_NODE (var)); - if (MAY_HAVE_DEBUG_STMTS) + if (MAY_HAVE_DEBUG_BIND_STMTS) insert_debug_temp_for_var_def (NULL, var); if (flag_checking) diff --git a/gcc/tree-vect-loop-manip.c b/gcc/tree-vect-loop-manip.c index 5787d53..20d1962 100644 --- a/gcc/tree-vect-loop-manip.c +++ b/gcc/tree-vect-loop-manip.c @@ -194,7 +194,7 @@ adjust_debug_stmts_now (adjust_info *ai) static void adjust_vec_debug_stmts (void) { - if (!MAY_HAVE_DEBUG_STMTS) + if (!MAY_HAVE_DEBUG_BIND_STMTS) return; gcc_assert (adjust_vec.exists ()); @@ -216,7 +216,7 @@ adjust_debug_stmts (tree from, tree to, basic_block bb) { adjust_info ai; - if (MAY_HAVE_DEBUG_STMTS + if (MAY_HAVE_DEBUG_BIND_STMTS && TREE_CODE (from) == SSA_NAME && ! SSA_NAME_IS_DEFAULT_DEF (from) && ! virtual_operand_p (from)) @@ -244,7 +244,7 @@ adjust_phi_and_debug_stmts (gimple *update_phi, edge e, tree new_def) SET_PHI_ARG_DEF (update_phi, e->dest_idx, new_def); - if (MAY_HAVE_DEBUG_STMTS) + if (MAY_HAVE_DEBUG_BIND_STMTS) adjust_debug_stmts (orig_def, PHI_RESULT (update_phi), gimple_bb (update_phi)); } @@ -1685,7 +1685,7 @@ vect_do_peeling (loop_vec_info loop_vinfo, tree niters, tree nitersm1, create_lcssa_for_virtual_phi (loop); update_ssa (TODO_update_ssa_only_virtuals); - if (MAY_HAVE_DEBUG_STMTS) + if (MAY_HAVE_DEBUG_BIND_STMTS) { gcc_assert (!adjust_vec.exists ()); adjust_vec.create (32); diff --git a/gcc/tree-vect-loop.c b/gcc/tree-vect-loop.c index bf49e26..07f666e 100644 --- a/gcc/tree-vect-loop.c +++ b/gcc/tree-vect-loop.c @@ -7386,7 +7386,7 @@ vect_transform_loop (loop_vec_info loop_vinfo) if (!stmt_info) continue; - if (MAY_HAVE_DEBUG_STMTS && !STMT_VINFO_LIVE_P (stmt_info)) + if (MAY_HAVE_DEBUG_BIND_STMTS && !STMT_VINFO_LIVE_P (stmt_info)) vect_loop_kill_debug_uses (loop, phi); if (!STMT_VINFO_RELEVANT_P (stmt_info) @@ -7449,7 +7449,7 @@ vect_transform_loop (loop_vec_info loop_vinfo) continue; } - if (MAY_HAVE_DEBUG_STMTS && !STMT_VINFO_LIVE_P (stmt_info)) + if (MAY_HAVE_DEBUG_BIND_STMTS && !STMT_VINFO_LIVE_P (stmt_info)) vect_loop_kill_debug_uses (loop, stmt); if (!STMT_VINFO_RELEVANT_P (stmt_info) diff --git a/gcc/tree.h b/gcc/tree.h index caa4a69..2e8b3e9 100644 --- a/gcc/tree.h +++ b/gcc/tree.h @@ -1126,8 +1126,14 @@ extern void omp_clause_range_check_failed (const_tree, const char *, int, #define VL_EXP_OPERAND_LENGTH(NODE) \ ((int)TREE_INT_CST_LOW (VL_EXP_CHECK (NODE)->exp.operands[0])) +/* Nonzero if gimple_debug_nonbind_marker_p() may possibly hold. */ +#define MAY_HAVE_DEBUG_MARKER_STMTS 0 /* debug_nonbind_markers_p */ +/* Nonzero if gimple_debug_bind_p() (and thus + gimple_debug_source_bind_p()) may possibly hold. */ +#define MAY_HAVE_DEBUG_BIND_STMTS flag_var_tracking_assignments /* Nonzero if is_gimple_debug() may possibly hold. */ -#define MAY_HAVE_DEBUG_STMTS (flag_var_tracking_assignments) +#define MAY_HAVE_DEBUG_STMTS \ + (MAY_HAVE_DEBUG_MARKER_STMTS || MAY_HAVE_DEBUG_BIND_STMTS) /* In a LOOP_EXPR node. */ #define LOOP_EXPR_BODY(NODE) TREE_OPERAND_CHECK_CODE (NODE, LOOP_EXPR, 0) diff --git a/gcc/valtrack.c b/gcc/valtrack.c index 38af3f0..8d864c9 100644 --- a/gcc/valtrack.c +++ b/gcc/valtrack.c @@ -211,7 +211,7 @@ propagate_for_debug (rtx_insn *insn, rtx_insn *last, rtx dest, rtx src, { insn = next; next = NEXT_INSN (insn); - if (DEBUG_INSN_P (insn)) + if (DEBUG_BIND_INSN_P (insn)) { loc = simplify_replace_fn_rtx (INSN_VAR_LOCATION_LOC (insn), dest, propagate_for_debug_subst, &p); diff --git a/gcc/var-tracking.c b/gcc/var-tracking.c index 51e519a..43fc71a 100644 --- a/gcc/var-tracking.c +++ b/gcc/var-tracking.c @@ -1118,7 +1118,7 @@ adjust_mems (rtx loc, const_rtx old_rtx, void *data) if (tem == NULL_RTX) tem = gen_rtx_raw_SUBREG (GET_MODE (loc), addr, SUBREG_BYTE (loc)); finish_subreg: - if (MAY_HAVE_DEBUG_INSNS + if (MAY_HAVE_DEBUG_BIND_INSNS && GET_CODE (tem) == SUBREG && (GET_CODE (SUBREG_REG (tem)) == PLUS || GET_CODE (SUBREG_REG (tem)) == MINUS @@ -1330,7 +1330,7 @@ dv_onepart_p (decl_or_value dv) { tree decl; - if (!MAY_HAVE_DEBUG_INSNS) + if (!MAY_HAVE_DEBUG_BIND_INSNS) return NOT_ONEPART; if (dv_is_value_p (dv)) @@ -4854,7 +4854,7 @@ dataflow_set_clear_at_call (dataflow_set *set, rtx_insn *call_insn) EXECUTE_IF_SET_IN_HARD_REG_SET (invalidated_regs, 0, r, hrsi) var_regno_delete (set, r); - if (MAY_HAVE_DEBUG_INSNS) + if (MAY_HAVE_DEBUG_BIND_INSNS) { set->traversed_vars = set->vars; shared_hash_htab (set->vars) @@ -5528,7 +5528,7 @@ use_type (rtx loc, struct count_use_info *cui, machine_mode *modep) variable names such as VALUEs (never happens) or DEBUG_EXPRs (only happens in the presence of debug insns). */ - && (!MAY_HAVE_DEBUG_INSNS + && (!MAY_HAVE_DEBUG_BIND_INSNS || !rtx_debug_expr_p (XEXP (loc, 0)))) return MO_USE; else @@ -6693,7 +6693,7 @@ compute_bb_dataflow (basic_block bb) dataflow_set_copy (&old_out, out); dataflow_set_copy (out, in); - if (MAY_HAVE_DEBUG_INSNS) + if (MAY_HAVE_DEBUG_BIND_INSNS) local_get_addr_cache = new hash_map; FOR_EACH_VEC_ELT (VTI (bb)->mos, i, mo) @@ -6975,7 +6975,7 @@ compute_bb_dataflow (basic_block bb) } } - if (MAY_HAVE_DEBUG_INSNS) + if (MAY_HAVE_DEBUG_BIND_INSNS) { delete local_get_addr_cache; local_get_addr_cache = NULL; @@ -7062,7 +7062,7 @@ vt_find_locations (void) else oldinsz = oldoutsz = 0; - if (MAY_HAVE_DEBUG_INSNS) + if (MAY_HAVE_DEBUG_BIND_INSNS) { dataflow_set *in = &VTI (bb)->in, *first_out = NULL; bool first = true, adjust = false; @@ -7123,7 +7123,7 @@ vt_find_locations (void) if (htabmax && htabsz > htabmax) { - if (MAY_HAVE_DEBUG_INSNS) + if (MAY_HAVE_DEBUG_BIND_INSNS) inform (DECL_SOURCE_LOCATION (cfun->decl), "variable tracking size limit exceeded with " "-fvar-tracking-assignments, retrying without"); @@ -7183,7 +7183,7 @@ vt_find_locations (void) } } - if (success && MAY_HAVE_DEBUG_INSNS) + if (success && MAY_HAVE_DEBUG_BIND_INSNS) FOR_EACH_BB_FN (bb, cfun) gcc_assert (VTI (bb)->flooded); @@ -8572,7 +8572,7 @@ vt_expand_loc (rtx loc, variable_table_type *vars) struct expand_loc_callback_data data; rtx result; - if (!MAY_HAVE_DEBUG_INSNS) + if (!MAY_HAVE_DEBUG_BIND_INSNS) return loc; INIT_ELCD (data, vars); @@ -9007,7 +9007,7 @@ emit_notes_for_changes (rtx_insn *insn, enum emit_note_where where, if (!changed_variables->elements ()) return; - if (MAY_HAVE_DEBUG_INSNS) + if (MAY_HAVE_DEBUG_BIND_INSNS) process_changed_values (htab); data.insn = insn; @@ -9491,10 +9491,8 @@ vt_emit_notes (void) delete_variable_part). */ emit_notes = true; - if (MAY_HAVE_DEBUG_INSNS) - { - dropped_values = new variable_table_type (cselib_get_next_uid () * 2); - } + if (MAY_HAVE_DEBUG_BIND_INSNS) + dropped_values = new variable_table_type (cselib_get_next_uid () * 2); dataflow_set_init (&cur); @@ -9504,13 +9502,13 @@ vt_emit_notes (void) subsequent basic blocks. */ emit_notes_for_differences (BB_HEAD (bb), &cur, &VTI (bb)->in); - if (MAY_HAVE_DEBUG_INSNS) + if (MAY_HAVE_DEBUG_BIND_INSNS) local_get_addr_cache = new hash_map; /* Emit the notes for the changes in the basic block itself. */ emit_notes_in_bb (bb, &cur); - if (MAY_HAVE_DEBUG_INSNS) + if (MAY_HAVE_DEBUG_BIND_INSNS) delete local_get_addr_cache; local_get_addr_cache = NULL; @@ -9526,7 +9524,7 @@ vt_emit_notes (void) dataflow_set_destroy (&cur); - if (MAY_HAVE_DEBUG_INSNS) + if (MAY_HAVE_DEBUG_BIND_INSNS) delete dropped_values; dropped_values = NULL; @@ -9886,7 +9884,7 @@ vt_init_cfa_base (void) cfa_base_rtx = NULL_RTX; return; } - if (!MAY_HAVE_DEBUG_INSNS) + if (!MAY_HAVE_DEBUG_BIND_INSNS) return; /* Tell alias analysis that cfa_base_rtx should share @@ -9928,7 +9926,7 @@ vt_initialize (void) VTI (bb)->permp = NULL; } - if (MAY_HAVE_DEBUG_INSNS) + if (MAY_HAVE_DEBUG_BIND_INSNS) { cselib_init (CSELIB_RECORD_MEMORY | CSELIB_PRESERVE_CONSTANTS); scratch_regs = BITMAP_ALLOC (NULL); @@ -9941,7 +9939,7 @@ vt_initialize (void) global_get_addr_cache = NULL; } - if (MAY_HAVE_DEBUG_INSNS) + if (MAY_HAVE_DEBUG_BIND_INSNS) { rtx reg, expr; int ofst; @@ -10071,7 +10069,7 @@ vt_initialize (void) HOST_WIDE_INT pre, post = 0; basic_block first_bb, last_bb; - if (MAY_HAVE_DEBUG_INSNS) + if (MAY_HAVE_DEBUG_BIND_INSNS) { cselib_record_sets_hook = add_with_sets; if (dump_file && (dump_flags & TDF_DETAILS)) @@ -10122,7 +10120,7 @@ vt_initialize (void) cselib_hook_called = false; adjust_insn (bb, insn); - if (MAY_HAVE_DEBUG_INSNS) + if (MAY_HAVE_DEBUG_BIND_INSNS) { if (CALL_P (insn)) prepare_call_arguments (bb, insn); @@ -10157,7 +10155,7 @@ vt_initialize (void) vt_init_cfa_base (); hard_frame_pointer_adjustment = fp_cfa_offset; /* Disassociate sp from fp now. */ - if (MAY_HAVE_DEBUG_INSNS) + if (MAY_HAVE_DEBUG_BIND_INSNS) { cselib_val *v; cselib_invalidate_rtx (stack_pointer_rtx); @@ -10177,7 +10175,7 @@ vt_initialize (void) bb = last_bb; - if (MAY_HAVE_DEBUG_INSNS) + if (MAY_HAVE_DEBUG_BIND_INSNS) { cselib_preserve_only_values (); cselib_reset_table (cselib_get_next_uid ()); @@ -10276,7 +10274,7 @@ vt_finalize (void) location_chain_pool.release (); shared_hash_pool.release (); - if (MAY_HAVE_DEBUG_INSNS) + if (MAY_HAVE_DEBUG_BIND_INSNS) { if (global_get_addr_cache) delete global_get_addr_cache; From patchwork Sat Sep 30 09:08:21 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Alexandre Oliva X-Patchwork-Id: 820193 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (mailfrom) smtp.mailfrom=gcc.gnu.org (client-ip=209.132.180.131; helo=sourceware.org; envelope-from=gcc-patches-return-463265-incoming=patchwork.ozlabs.org@gcc.gnu.org; receiver=) Authentication-Results: ozlabs.org; dkim=pass (1024-bit key; unprotected) header.d=gcc.gnu.org header.i=@gcc.gnu.org header.b="Vt9VsNtj"; dkim-atps=neutral Received: from sourceware.org (server1.sourceware.org [209.132.180.131]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 3y42k61XXtz9t3f for ; Sat, 30 Sep 2017 19:11:58 +1000 (AEST) DomainKey-Signature: a=rsa-sha1; c=nofws; d=gcc.gnu.org; h=list-id :list-unsubscribe:list-archive:list-post:list-help:sender:from :to:cc:subject:date:message-id:in-reply-to:references; q=dns; s= default; b=ojy0S2uLu6a5/RmF96RO5nl21siRDO9c6VlxGcppBq1fsbB+XoTn9 x0IEd3pV4KcrjgUnYPReBe2MoGOKkQID2WTQVc5Rm0rXEfh5VE1SH2qXHs9P141U yAOUwNZyMGC/Pztu3Q8GkWgxnsBXeY37KzpkgueW8g1ryQ5tz5kY4w= DKIM-Signature: v=1; a=rsa-sha1; c=relaxed; d=gcc.gnu.org; h=list-id :list-unsubscribe:list-archive:list-post:list-help:sender:from :to:cc:subject:date:message-id:in-reply-to:references; s= default; bh=wNgcVZ+E3wFxlfNE93PVpf+elro=; b=Vt9VsNtjXrXvmvuKqUKg 3iGCo6eYEc4ARrU0HdtXDiV8Mt88j0QbDMkLS/lDhdiIWK1ue2VIMGB0Xf3uOxpE aaL7Yozuo0lEJpR+QmaD2NJB5McB94HNrr1GpciGuAcx5Yibh8hz0mtobjELRCez XuV4lvBr0OZ/rtzSH4I5GQ4= Received: (qmail 64955 invoked by alias); 30 Sep 2017 09:09:59 -0000 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 Received: (qmail 64877 invoked by uid 89); 30 Sep 2017 09:09:59 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-26.9 required=5.0 tests=BAYES_00, GIT_PATCH_0, GIT_PATCH_1, GIT_PATCH_2, GIT_PATCH_3, RP_MATCHES_RCVD, SPF_HELO_PASS autolearn=ham version=3.3.2 spammy=slim, hurt, Below, retaining X-HELO: mx1.redhat.com Received: from mx1.redhat.com (HELO mx1.redhat.com) (209.132.183.28) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Sat, 30 Sep 2017 09:09:51 +0000 Received: from smtp.corp.redhat.com (int-mx05.intmail.prod.int.phx2.redhat.com [10.5.11.15]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 41D3881DE2; Sat, 30 Sep 2017 09:09:50 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.3.2 mx1.redhat.com 41D3881DE2 Authentication-Results: ext-mx01.extmail.prod.ext.phx2.redhat.com; dmarc=none (p=none dis=none) header.from=redhat.com Authentication-Results: ext-mx01.extmail.prod.ext.phx2.redhat.com; spf=fail smtp.mailfrom=aoliva@redhat.com Received: from freie.home (ovpn04.gateway.prod.ext.phx2.redhat.com [10.5.9.4]) by smtp.corp.redhat.com (Postfix) with ESMTPS id 8643D17107; Sat, 30 Sep 2017 09:09:49 +0000 (UTC) Received: from frit.home (frit.home [172.31.160.7]) by freie.home (8.15.2/8.15.2) with ESMTP id v8U98pIU022010; Sat, 30 Sep 2017 06:09:16 -0300 From: Alexandre Oliva To: Richard Biener Cc: GCC Patches , Alexandre Oliva Subject: [PATCH 3/9] [SFN] not-quite-boilerplate changes in preparation to introduce nonbind markers Date: Sat, 30 Sep 2017 06:08:21 -0300 Message-Id: <20170930090827.6604-3-aoliva@redhat.com> In-Reply-To: References: This patch adjusts numerous parts of the compiler that would malfunction should they find debug markers at points where they may be introduced. The changes purport to allow the compiler to pass bootstrap-debug-lean (-fcompare-debug in stage3) at various optimization levels, as well as bootstrap-debug-lib (-fcompare-debug for target libraries), even after the compiler is changed so that debug markers are introduced in code streams at spots where earlier debug stmts, insns and notes wouldn't normally appear. This patch depends on an earlier SFN boilerplate patch, and on another SFN patch that introduces new RTL insn-walking functions. for gcc/ChangeLog * cfgcleanup.c (delete_unreachable_blocks): Use alternate block removal order if MAY_HAVE_DEBUG_BIND_INSNS. * cfgexpand.c (label_rtx_for_bb): Skip debug insns. * cfgrtl.c (try_redirect_by_replacing_jump): Skip debug insns. (rtl_tidy_fallthru_edge): Likewise. (rtl_verify_fallthru): Likewise. (rtl_verify_bb_layout): Likewise. (skip_insns_after_block): Likewise. (duplicate_insn_chain): Use DEBUG_BIND_INSN_P. * dwarf2out.c: Include print-rtl.h. (dwarf2out_next_real_insn): New. (dwarf2out_var_location): Call it. Disregard begin stmt markers. Dump debug binds in asm comments. * gimple-iterator.c (gimple_find_edge_insert_loc): Skip debug stmts. * gimple-iterator.h (gsi_start_bb_nondebug): Remove; adjust callers to use gsi_start_nondebug_bb instead. (gsi_after_labels): Skip gimple debug stmts. (gsi_start_nondebug): New. * gimple-low.c (gimple_seq_may_fallthru): Take last nondebug stmt. * gimple.h (gimple_seq_last_nondebug_stmt): New. * gimplify.c (last_stmt_in_scope): Skip debug stmts. (collect_fallthrough_labels): Likewise. (should_warn_for_implicit_fallthrough): Likewise. (warn_implicit_fallthrough_r): Likewise. (expand_FALLTHROUGH_r): Likewise. * graphite-isl-ast-to-gimple.c (gsi_insert_earliest): Adjust. (rename_uses): Skip nonbind markers. * graphite-scop-detection.c (trivially_empty_bb_p): Call is_gimple_debug in test. * haifa-sched.c (sched_extend_bb): Skip debug insns. * ipa-icf-gimple.c (func_checker::compare_bb): Adjust. * jump.c (clean_barriers): Skip debug insns. * omp-expand.c (expand_parallel_call): Skip debug insns. (expand_cilk_for_call): Likewise. (expand_task_call): Likewise. (remove_exit_barrier): Likewise. (expand_omp_taskreg): Likewise. (expand_omp_for_init_counts): Likewise. (expand_omp_for_generic): Likewise. (expand_omp_for_static_nochunk): Likewise. (expand_omp_for_static_chunk): Likewise. (expand_cilk_for): Likewise. (expand_omp_simd): Likewise. (expand_omp_taskloop_for_outer): Likewise. (expand_omp_taskloop_for_inner): Likewise. (expand_oacc_for): Likewise. (expand_omp_sections): Likewise. (expand_omp_single): Likewise. (expand_omp_synch): Likewise. (expand_omp_atomic_load): Likewise. (expand_omp_atomic_store): Likewise. (expand_omp_atomic_fetch_op): Likewise. (expand_omp_atomic_pipeline): Likewise. (expand_omp_atomic_mutex): Likewise. (expand_omp_target): Likewise. (grid_expand_omp_for_loop): Likewise. (grid_expand_target_grid_body): Likewise. (build_omp_regions_1): Likewise. * omp-low.c (check_combined_parallel): Skip debug stmts. * postreload.c (fixup_debug_insns): Skip nonbind debug insns. * regcprop.c (find_oldest_value_reg): Ensure REGNO is not a pseudo. * tree-cfg.c (make_blobs_1): Skip debug stmts. (make_edges): Likewise. (cleanup_dead_labels): Likewise. (gimple_can_merge_blocks_p): Likewise. (stmt_starts_bb_p): Likewise. (gimple_block_label): Likewise. (gimple_redirect_edge_and_branch): Likewise. * tree-cfgcleanup.c (remove_forwarder_block): Rearrange skipping of debug stmts. (execute_cleanup_cfg_post_optimizing): Dump enumerated decls with TDF_SLIM. * tree-pretty-print (print_declaration): Omit initializer in slim dumps. * tree-ssa-dce.c (mark_stmt_if_obviously_necessary): Mark begin stmt markers. (eliminate_unnecessary_stmts): Stabilize block removal order. * tree-ssa-tail-merge.c (find_duplicate): Skip debug stmts. * var-tracking.c (get_first_insn): New. (vt_emit_notes): Call it. (vt_initialize): Walk any insns before the first BB. (delete_debug_insns): Likewise. --- gcc/cfgbuild.c | 1 + gcc/cfgcleanup.c | 12 +-- gcc/cfgexpand.c | 24 +++++- gcc/cfgrtl.c | 18 +++-- gcc/dwarf2out.c | 38 ++++++++- gcc/gimple-iterator.c | 24 +++++- gcc/gimple-iterator.h | 46 ++++++----- gcc/gimple-low.c | 2 +- gcc/gimple.h | 16 ++++ gcc/gimplify.c | 21 ++--- gcc/graphite-isl-ast-to-gimple.c | 7 +- gcc/graphite-scop-detection.c | 2 +- gcc/haifa-sched.c | 2 +- gcc/ipa-icf-gimple.c | 4 +- gcc/jump.c | 2 +- gcc/omp-expand.c | 161 ++++++++++++++++++++------------------- gcc/omp-low.c | 2 + gcc/postreload.c | 2 +- gcc/regcprop.c | 2 + gcc/tree-cfg.c | 52 +++++++++++-- gcc/tree-cfgcleanup.c | 31 +++----- gcc/tree-pretty-print.c | 5 +- gcc/tree-ssa-dce.c | 6 +- gcc/tree-ssa-tail-merge.c | 4 +- gcc/var-tracking.c | 54 ++++++++++++- 25 files changed, 365 insertions(+), 173 deletions(-) diff --git a/gcc/cfgbuild.c b/gcc/cfgbuild.c index 76c21d7..a2e467c 100644 --- a/gcc/cfgbuild.c +++ b/gcc/cfgbuild.c @@ -475,6 +475,7 @@ find_bb_boundaries (basic_block bb) if (debug_insn && code != CODE_LABEL && code != BARRIER) prev = PREV_INSN (debug_insn); fallthru = split_block (bb, prev); + if (flow_transfer_insn) { BB_END (bb) = flow_transfer_insn; diff --git a/gcc/cfgcleanup.c b/gcc/cfgcleanup.c index 365c971..be88fdd 100644 --- a/gcc/cfgcleanup.c +++ b/gcc/cfgcleanup.c @@ -3060,13 +3060,13 @@ delete_unreachable_blocks (void) find_unreachable_blocks (); - /* When we're in GIMPLE mode and there may be debug insns, we should - delete blocks in reverse dominator order, so as to get a chance - to substitute all released DEFs into debug stmts. If we don't - have dominators information, walking blocks backward gets us a - better chance of retaining most debug information than + /* When we're in GIMPLE mode and there may be debug bind insns, we + should delete blocks in reverse dominator order, so as to get a + chance to substitute all released DEFs into debug bind stmts. If + we don't have dominators information, walking blocks backward + gets us a better chance of retaining most debug information than otherwise. */ - if (MAY_HAVE_DEBUG_INSNS && current_ir_type () == IR_GIMPLE + if (MAY_HAVE_DEBUG_BIND_INSNS && current_ir_type () == IR_GIMPLE && dom_info_available_p (CDI_DOMINATORS)) { for (b = EXIT_BLOCK_PTR_FOR_FN (cfun)->prev_bb; diff --git a/gcc/cfgexpand.c b/gcc/cfgexpand.c index cb866aa..5a46b5e 100644 --- a/gcc/cfgexpand.c +++ b/gcc/cfgexpand.c @@ -2319,6 +2319,9 @@ label_rtx_for_bb (basic_block bb ATTRIBUTE_UNUSED) { glabel *lab_stmt; + if (is_gimple_debug (gsi_stmt (gsi))) + continue; + lab_stmt = dyn_cast (gsi_stmt (gsi)); if (!lab_stmt) break; @@ -5432,7 +5435,7 @@ expand_gimple_basic_block (basic_block bb, bool disable_tail_calls) gimple_stmt_iterator gsi; gimple_seq stmts; gimple *stmt = NULL; - rtx_note *note; + rtx_note *note = NULL; rtx_insn *last; edge e; edge_iterator ei; @@ -5473,18 +5476,26 @@ expand_gimple_basic_block (basic_block bb, bool disable_tail_calls) } } - gsi = gsi_start (stmts); + gsi = gsi_start_nondebug (stmts); if (!gsi_end_p (gsi)) { stmt = gsi_stmt (gsi); if (gimple_code (stmt) != GIMPLE_LABEL) stmt = NULL; } + gsi = gsi_start (stmts); + gimple *label_stmt = stmt; rtx_code_label **elt = lab_rtx_for_bb->get (bb); - if (stmt || elt) + if (stmt) + /* We'll get to it in the loop below, and get back to + emit_label_and_note then. */ + ; + else if (stmt || elt) { + emit_label_and_note: + gcc_checking_assert (!note); last = get_last_insn (); if (stmt) @@ -5499,6 +5510,7 @@ expand_gimple_basic_block (basic_block bb, bool disable_tail_calls) BB_HEAD (bb) = NEXT_INSN (last); if (NOTE_P (BB_HEAD (bb))) BB_HEAD (bb) = NEXT_INSN (BB_HEAD (bb)); + gcc_assert (LABEL_P (BB_HEAD (bb))); note = emit_note_after (NOTE_INSN_BASIC_BLOCK, BB_HEAD (bb)); maybe_dump_rtl_for_gimple_stmt (stmt, last); @@ -5506,7 +5518,8 @@ expand_gimple_basic_block (basic_block bb, bool disable_tail_calls) else BB_HEAD (bb) = note = emit_note (NOTE_INSN_BASIC_BLOCK); - NOTE_BASIC_BLOCK (note) = bb; + if (note) + NOTE_BASIC_BLOCK (note) = bb; for (; !gsi_end_p (gsi); gsi_next (&gsi)) { @@ -5514,6 +5527,9 @@ expand_gimple_basic_block (basic_block bb, bool disable_tail_calls) stmt = gsi_stmt (gsi); + if (stmt == label_stmt) + goto emit_label_and_note; + /* If this statement is a non-debug one, and we generate debug insns, then this one might be the last real use of a TERed SSA_NAME, but where there are still some debug uses further diff --git a/gcc/cfgrtl.c b/gcc/cfgrtl.c index bce56b4..d43e38c 100644 --- a/gcc/cfgrtl.c +++ b/gcc/cfgrtl.c @@ -1117,7 +1117,7 @@ try_redirect_by_replacing_jump (edge e, basic_block target, bool in_cfglayout) if (tablejump_p (insn, &label, &table)) delete_insn_chain (label, table, false); - barrier = next_nonnote_insn (BB_END (src)); + barrier = next_nonnote_nondebug_insn (BB_END (src)); if (!barrier || !BARRIER_P (barrier)) emit_barrier_after (BB_END (src)); else @@ -1753,7 +1753,7 @@ rtl_tidy_fallthru_edge (edge e) the head of block C and assert that we really do fall through. */ for (q = NEXT_INSN (BB_END (b)); q != BB_HEAD (c); q = NEXT_INSN (q)) - if (INSN_P (q)) + if (NONDEBUG_INSN_P (q)) return; /* Remove what will soon cease being the jump insn from the source block. @@ -2894,7 +2894,7 @@ rtl_verify_fallthru (void) else for (insn = NEXT_INSN (BB_END (e->src)); insn != BB_HEAD (e->dest); insn = NEXT_INSN (insn)) - if (BARRIER_P (insn) || INSN_P (insn)) + if (BARRIER_P (insn) || NONDEBUG_INSN_P (insn)) { error ("verify_flow_info: Incorrect fallthru %i->%i", e->src->index, e->dest->index); @@ -2916,7 +2916,7 @@ rtl_verify_bb_layout (void) { basic_block bb; int err = 0; - rtx_insn *x; + rtx_insn *x, *y; int num_bb_notes; rtx_insn * const rtx_first = get_insns (); basic_block last_bb_seen = ENTRY_BLOCK_PTR_FOR_FN (cfun), curr_bb = NULL; @@ -2943,6 +2943,7 @@ rtl_verify_bb_layout (void) { case BARRIER: case NOTE: + case DEBUG_INSN: break; case CODE_LABEL: @@ -2961,7 +2962,8 @@ rtl_verify_bb_layout (void) if (JUMP_P (x) && returnjump_p (x) && ! condjump_p (x) - && ! (next_nonnote_insn (x) && BARRIER_P (next_nonnote_insn (x)))) + && ! ((y = next_nonnote_nondebug_insn (x)) + && BARRIER_P (y))) fatal_insn ("return not followed by barrier", x); if (curr_bb && x == BB_END (curr_bb)) @@ -3382,6 +3384,9 @@ skip_insns_after_block (basic_block bb) last_insn = insn; continue; + case DEBUG_INSN: + continue; + case NOTE: switch (NOTE_KIND (insn)) { @@ -4135,7 +4140,8 @@ duplicate_insn_chain (rtx_insn *from, rtx_insn *to) { case DEBUG_INSN: /* Don't duplicate label debug insns. */ - if (TREE_CODE (INSN_VAR_LOCATION_DECL (insn)) == LABEL_DECL) + if (DEBUG_BIND_INSN_P (insn) + && TREE_CODE (INSN_VAR_LOCATION_DECL (insn)) == LABEL_DECL) break; /* FALLTHRU */ case INSN: diff --git a/gcc/dwarf2out.c b/gcc/dwarf2out.c index e97ceb6..f4e5947 100644 --- a/gcc/dwarf2out.c +++ b/gcc/dwarf2out.c @@ -83,6 +83,7 @@ along with GCC; see the file COPYING3. If not see #include "toplev.h" #include "md5.h" #include "tree-pretty-print.h" +#include "print-rtl.h" #include "debug.h" #include "common/common-target.h" #include "langhooks.h" @@ -26144,6 +26145,22 @@ static bool maybe_at_text_label_p = true; /* One above highest N where .LVLN label might be equal to .Ltext0 label. */ static unsigned int first_loclabel_num_not_at_text_label; +/* Look ahead for a real insn, or for a begin stmt marker. */ + +static rtx_insn * +dwarf2out_next_real_insn (rtx_insn *loc_note) +{ + rtx_insn *next_real = NEXT_INSN (loc_note); + + while (next_real) + if (INSN_P (next_real)) + break; + else + next_real = NEXT_INSN (next_real); + + return next_real; +} + /* Called by the final INSN scan whenever we see a var location. We use it to drop labels in the right places, and throw the location in our lookup table. */ @@ -26192,7 +26209,7 @@ dwarf2out_var_location (rtx_insn *loc_note) loc_note = NULL; var_loc_p = false; - next_real = next_real_insn (call_insn); + next_real = dwarf2out_next_real_insn (call_insn); next_note = NULL; cached_next_real_insn = NULL; goto create_label; @@ -26222,11 +26239,12 @@ dwarf2out_var_location (rtx_insn *loc_note) || next_note->deleted () || ! NOTE_P (next_note) || (NOTE_KIND (next_note) != NOTE_INSN_VAR_LOCATION + && NOTE_KIND (next_note) != NOTE_INSN_BEGIN_STMT && NOTE_KIND (next_note) != NOTE_INSN_CALL_ARG_LOCATION)) next_note = NULL; if (! next_real) - next_real = next_real_insn (loc_note); + next_real = dwarf2out_next_real_insn (loc_note); if (next_note) { @@ -26385,6 +26403,22 @@ create_label: newloc->label = last_postcall_label; } + if (var_loc_p && flag_debug_asm) + { + const char *name = NULL, *sep = " => ", *patstr = NULL; + if (decl && DECL_NAME (decl)) + name = IDENTIFIER_POINTER (DECL_NAME (decl)); + if (NOTE_VAR_LOCATION_LOC (loc_note)) + patstr = str_pattern_slim (NOTE_VAR_LOCATION_LOC (loc_note)); + else + { + sep = " "; + patstr = "RESET"; + } + fprintf (asm_out_file, "\t%s DEBUG %s%s%s\n", ASM_COMMENT_START, + name, sep, patstr); + } + last_var_location_insn = next_real; last_in_cold_section_p = in_cold_section_p; } diff --git a/gcc/gimple-iterator.c b/gcc/gimple-iterator.c index 3b74cc5..fb75f99 100644 --- a/gcc/gimple-iterator.c +++ b/gcc/gimple-iterator.c @@ -744,9 +744,13 @@ gimple_find_edge_insert_loc (edge e, gimple_stmt_iterator *gsi, if (gsi_end_p (*gsi)) return true; - /* Make sure we insert after any leading labels. */ + /* Make sure we insert after any leading labels. We have to + skip debug stmts before or among them, though. We didn't + have to skip debug stmts after the last label, but it + shouldn't hurt if we do. */ tmp = gsi_stmt (*gsi); - while (gimple_code (tmp) == GIMPLE_LABEL) + while (gimple_code (tmp) == GIMPLE_LABEL + || is_gimple_debug (tmp)) { gsi_next (gsi); if (gsi_end_p (*gsi)) @@ -776,7 +780,21 @@ gimple_find_edge_insert_loc (edge e, gimple_stmt_iterator *gsi, return true; tmp = gsi_stmt (*gsi); - if (!stmt_ends_bb_p (tmp)) + if (is_gimple_debug (tmp)) + { + gimple_stmt_iterator si = *gsi; + gsi_prev_nondebug (&si); + if (!gsi_end_p (si)) + tmp = gsi_stmt (si); + /* If we don't have a BB-ending nondebug stmt, we want to + insert after the trailing debug stmts. Otherwise, we may + insert before the BB-ending nondebug stmt, or split the + edge. */ + if (!stmt_ends_bb_p (tmp)) + return true; + *gsi = si; + } + else if (!stmt_ends_bb_p (tmp)) return true; switch (gimple_code (tmp)) diff --git a/gcc/gimple-iterator.h b/gcc/gimple-iterator.h index 70f18be..167edc1 100644 --- a/gcc/gimple-iterator.h +++ b/gcc/gimple-iterator.h @@ -212,29 +212,28 @@ gsi_stmt (gimple_stmt_iterator i) return i.ptr; } -/* Return a new iterator pointing to the first non-debug statement - in basic block BB. */ - -static inline gimple_stmt_iterator -gsi_start_bb_nondebug (basic_block bb) -{ - gimple_stmt_iterator gsi = gsi_start_bb (bb); - while (!gsi_end_p (gsi) && is_gimple_debug (gsi_stmt (gsi))) - gsi_next (&gsi); - - return gsi; -} - -/* Return a block statement iterator that points to the first non-label - statement in block BB. */ +/* Return a block statement iterator that points to the first + non-label statement in block BB. Skip debug stmts only if they + precede labels. */ static inline gimple_stmt_iterator gsi_after_labels (basic_block bb) { gimple_stmt_iterator gsi = gsi_start_bb (bb); - while (!gsi_end_p (gsi) && gimple_code (gsi_stmt (gsi)) == GIMPLE_LABEL) - gsi_next (&gsi); + for (gimple_stmt_iterator gskip = gsi; + !gsi_end_p (gskip); ) + { + if (is_gimple_debug (gsi_stmt (gskip))) + gsi_next (&gskip); + else if (gimple_code (gsi_stmt (gskip)) == GIMPLE_LABEL) + { + gsi_next (&gskip); + gsi = gskip; + } + else + break; + } return gsi; } @@ -264,6 +263,19 @@ gsi_prev_nondebug (gimple_stmt_iterator *i) } /* Return a new iterator pointing to the first non-debug statement in + SEQ. */ + +static inline gimple_stmt_iterator +gsi_start_nondebug (gimple_seq seq) +{ + gimple_stmt_iterator gsi = gsi_start (seq); + if (!gsi_end_p (gsi) && is_gimple_debug (gsi_stmt (gsi))) + gsi_next_nondebug (&gsi); + + return gsi; +} + +/* Return a new iterator pointing to the first non-debug statement in basic block BB. */ static inline gimple_stmt_iterator diff --git a/gcc/gimple-low.c b/gcc/gimple-low.c index 4ea6c35..22db61b 100644 --- a/gcc/gimple-low.c +++ b/gcc/gimple-low.c @@ -645,7 +645,7 @@ gimple_stmt_may_fallthru (gimple *stmt) bool gimple_seq_may_fallthru (gimple_seq seq) { - return gimple_stmt_may_fallthru (gimple_seq_last_stmt (seq)); + return gimple_stmt_may_fallthru (gimple_seq_last_nondebug_stmt (seq)); } diff --git a/gcc/gimple.h b/gcc/gimple.h index 1783e11..8f289ac 100644 --- a/gcc/gimple.h +++ b/gcc/gimple.h @@ -4582,6 +4582,22 @@ is_gimple_debug (const gimple *gs) return gimple_code (gs) == GIMPLE_DEBUG; } + +/* Return the last nondebug statement in GIMPLE sequence S. */ + +static inline gimple * +gimple_seq_last_nondebug_stmt (gimple_seq s) +{ + gimple_seq_node n; + for (n = gimple_seq_last (s); + n && is_gimple_debug (n); + n = n->prev) + if (n->prev == s) + return NULL; + return n; +} + + /* Return true if S is a GIMPLE_DEBUG BIND statement. */ static inline bool diff --git a/gcc/gimplify.c b/gcc/gimplify.c index c3fd6ac..e9dffc3 100644 --- a/gcc/gimplify.c +++ b/gcc/gimplify.c @@ -1855,7 +1855,7 @@ case_label_p (const vec *cases, tree label) return false; } -/* Find the last statement in a scope STMT. */ +/* Find the last nondebug statement in a scope STMT. */ static gimple * last_stmt_in_scope (gimple *stmt) @@ -1868,27 +1868,30 @@ last_stmt_in_scope (gimple *stmt) case GIMPLE_BIND: { gbind *bind = as_a (stmt); - stmt = gimple_seq_last_stmt (gimple_bind_body (bind)); + stmt = gimple_seq_last_nondebug_stmt (gimple_bind_body (bind)); return last_stmt_in_scope (stmt); } case GIMPLE_TRY: { gtry *try_stmt = as_a (stmt); - stmt = gimple_seq_last_stmt (gimple_try_eval (try_stmt)); + stmt = gimple_seq_last_nondebug_stmt (gimple_try_eval (try_stmt)); gimple *last_eval = last_stmt_in_scope (stmt); if (gimple_stmt_may_fallthru (last_eval) && (last_eval == NULL || !gimple_call_internal_p (last_eval, IFN_FALLTHROUGH)) && gimple_try_kind (try_stmt) == GIMPLE_TRY_FINALLY) { - stmt = gimple_seq_last_stmt (gimple_try_cleanup (try_stmt)); + stmt = gimple_seq_last_nondebug_stmt (gimple_try_cleanup (try_stmt)); return last_stmt_in_scope (stmt); } else return last_eval; } + case GIMPLE_DEBUG: + gcc_unreachable (); + default: return stmt; } @@ -1992,7 +1995,7 @@ collect_fallthrough_labels (gimple_stmt_iterator *gsi_p, } else if (gimple_call_internal_p (gsi_stmt (*gsi_p), IFN_ASAN_MARK)) ; - else + else if (!is_gimple_debug (gsi_stmt (*gsi_p))) prev = gsi_stmt (*gsi_p); gsi_next (gsi_p); } @@ -2029,7 +2032,7 @@ should_warn_for_implicit_fallthrough (gimple_stmt_iterator *gsi_p, tree label) && gimple_code (gsi_stmt (gsi)) == GIMPLE_LABEL && (l = gimple_label_label (as_a (gsi_stmt (gsi)))) && !case_label_p (&gimplify_ctxp->case_labels, l)) - gsi_next (&gsi); + gsi_next_nondebug (&gsi); if (gsi_end_p (gsi) || gimple_code (gsi_stmt (gsi)) != GIMPLE_LABEL) return false; } @@ -2042,7 +2045,7 @@ should_warn_for_implicit_fallthrough (gimple_stmt_iterator *gsi_p, tree label) while (!gsi_end_p (gsi) && (gimple_code (gsi_stmt (gsi)) == GIMPLE_LABEL || gimple_code (gsi_stmt (gsi)) == GIMPLE_PREDICT)) - gsi_next (&gsi); + gsi_next_nondebug (&gsi); /* { ... something; default:; } */ if (gsi_end_p (gsi) @@ -2089,7 +2092,7 @@ warn_implicit_fallthrough_r (gimple_stmt_iterator *gsi_p, bool *handled_ops_p, /* Found a label. Skip all immediately following labels. */ while (!gsi_end_p (*gsi_p) && gimple_code (gsi_stmt (*gsi_p)) == GIMPLE_LABEL) - gsi_next (gsi_p); + gsi_next_nondebug (gsi_p); /* There might be no more statements. */ if (gsi_end_p (*gsi_p)) @@ -2230,7 +2233,7 @@ expand_FALLTHROUGH_r (gimple_stmt_iterator *gsi_p, bool *handled_ops_p, break; } } - else + else if (!is_gimple_debug (stmt)) /* Something other than a label. That's not expected. */ break; gsi_next (&gsi2); diff --git a/gcc/graphite-isl-ast-to-gimple.c b/gcc/graphite-isl-ast-to-gimple.c index 820e14e..3e3d5531 100644 --- a/gcc/graphite-isl-ast-to-gimple.c +++ b/gcc/graphite-isl-ast-to-gimple.c @@ -1252,7 +1252,7 @@ gsi_insert_earliest (gimple_seq seq) FOR_EACH_VEC_ELT (stmts, i, use_stmt) { gcc_assert (gimple_code (use_stmt) != GIMPLE_PHI); - gimple_stmt_iterator gsi_def_stmt = gsi_start_bb_nondebug (begin_bb); + gimple_stmt_iterator gsi_def_stmt = gsi_start_nondebug_bb (begin_bb); use_operand_p use_p; ssa_op_iter op_iter; @@ -1284,7 +1284,7 @@ gsi_insert_earliest (gimple_seq seq) else if (gimple_code (gsi_stmt (gsi_def_stmt)) == GIMPLE_PHI) { gimple_stmt_iterator bsi - = gsi_start_bb_nondebug (gsi_bb (gsi_def_stmt)); + = gsi_start_nondebug_bb (gsi_bb (gsi_def_stmt)); /* Insert right after the PHI statements. */ gsi_insert_before (&bsi, use_stmt, GSI_NEW_STMT); } @@ -1567,7 +1567,8 @@ rename_uses (gimple *copy, gimple_stmt_iterator *gsi_tgt, basic_block old_bb, { if (gimple_debug_bind_p (copy)) gimple_debug_bind_reset_value (copy); - else if (gimple_debug_source_bind_p (copy)) + else if (gimple_debug_source_bind_p (copy) + || gimple_debug_nonbind_marker_p (copy)) return false; else gcc_unreachable (); diff --git a/gcc/graphite-scop-detection.c b/gcc/graphite-scop-detection.c index b374ee1..23da9cc 100644 --- a/gcc/graphite-scop-detection.c +++ b/gcc/graphite-scop-detection.c @@ -262,7 +262,7 @@ trivially_empty_bb_p (basic_block bb) gimple_stmt_iterator gsi; for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi)) - if (gimple_code (gsi_stmt (gsi)) != GIMPLE_DEBUG + if (!is_gimple_debug (gsi_stmt (gsi)) && gimple_code (gsi_stmt (gsi)) != GIMPLE_LABEL) return false; diff --git a/gcc/haifa-sched.c b/gcc/haifa-sched.c index 34cc46b..e99aa69 100644 --- a/gcc/haifa-sched.c +++ b/gcc/haifa-sched.c @@ -8160,7 +8160,7 @@ sched_extend_bb (void) || (!NOTE_P (insn) && !LABEL_P (insn) /* Don't emit a NOTE if it would end up before a BARRIER. */ - && !BARRIER_P (NEXT_INSN (end)))) + && !BARRIER_P (next_nondebug_insn (end)))) { rtx_note *note = emit_note_after (NOTE_INSN_DELETED, end); /* Make note appear outside BB. */ diff --git a/gcc/ipa-icf-gimple.c b/gcc/ipa-icf-gimple.c index b40dd865..be8c709 100644 --- a/gcc/ipa-icf-gimple.c +++ b/gcc/ipa-icf-gimple.c @@ -640,8 +640,8 @@ func_checker::compare_bb (sem_bb *bb1, sem_bb *bb2) gimple_stmt_iterator gsi1, gsi2; gimple *s1, *s2; - gsi1 = gsi_start_bb_nondebug (bb1->bb); - gsi2 = gsi_start_bb_nondebug (bb2->bb); + gsi1 = gsi_start_nondebug_bb (bb1->bb); + gsi2 = gsi_start_nondebug_bb (bb2->bb); while (!gsi_end_p (gsi1)) { diff --git a/gcc/jump.c b/gcc/jump.c index fc4b434..e60a6c6 100644 --- a/gcc/jump.c +++ b/gcc/jump.c @@ -123,7 +123,7 @@ cleanup_barriers (void) { if (BARRIER_P (insn)) { - rtx_insn *prev = prev_nonnote_insn (insn); + rtx_insn *prev = prev_nonnote_nondebug_insn (insn); if (!prev) continue; diff --git a/gcc/omp-expand.c b/gcc/omp-expand.c index 4bdcf19..fe25b83 100644 --- a/gcc/omp-expand.c +++ b/gcc/omp-expand.c @@ -659,7 +659,7 @@ expand_parallel_call (struct omp_region *region, basic_block bb, false, GSI_CONTINUE_LINKING); } - gsi = gsi_last_bb (bb); + gsi = gsi_last_nondebug_bb (bb); t = gimple_omp_parallel_data_arg (entry_stmt); if (t == NULL) t1 = null_pointer_node; @@ -710,7 +710,7 @@ expand_cilk_for_call (basic_block bb, gomp_parallel *entry_stmt, gcc_assert (count != NULL_TREE); count = OMP_CLAUSE_OPERAND (count, 0); - gsi = gsi_last_bb (bb); + gsi = gsi_last_nondebug_bb (bb); t = gimple_omp_parallel_data_arg (entry_stmt); if (t == NULL) t1 = null_pointer_node; @@ -836,7 +836,7 @@ expand_task_call (struct omp_region *region, basic_block bb, else priority = integer_zero_node; - gsi = gsi_last_bb (bb); + gsi = gsi_last_nondebug_bb (bb); tree t = gimple_omp_task_data_arg (entry_stmt); if (t == NULL) t2 = null_pointer_node; @@ -913,15 +913,15 @@ remove_exit_barrier (struct omp_region *region) statements that can appear in between are extremely limited -- no memory operations at all. Here, we allow nothing at all, so the only thing we allow to precede this GIMPLE_OMP_RETURN is a label. */ - gsi = gsi_last_bb (exit_bb); + gsi = gsi_last_nondebug_bb (exit_bb); gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_RETURN); - gsi_prev (&gsi); + gsi_prev_nondebug (&gsi); if (!gsi_end_p (gsi) && gimple_code (gsi_stmt (gsi)) != GIMPLE_LABEL) return; FOR_EACH_EDGE (e, ei, exit_bb->preds) { - gsi = gsi_last_bb (e->src); + gsi = gsi_last_nondebug_bb (e->src); if (gsi_end_p (gsi)) continue; stmt = gsi_stmt (gsi); @@ -1148,7 +1148,7 @@ expand_omp_taskreg (struct omp_region *region) entry_succ_e = single_succ_edge (entry_bb); - gsi = gsi_last_bb (entry_bb); + gsi = gsi_last_nondebug_bb (entry_bb); gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_PARALLEL || gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_TASK); gsi_remove (&gsi, true); @@ -1261,7 +1261,7 @@ expand_omp_taskreg (struct omp_region *region) /* Split ENTRY_BB at GIMPLE_OMP_PARALLEL or GIMPLE_OMP_TASK, so that it can be moved to the child function. */ - gsi = gsi_last_bb (entry_bb); + gsi = gsi_last_nondebug_bb (entry_bb); stmt = gsi_stmt (gsi); gcc_assert (stmt && (gimple_code (stmt) == GIMPLE_OMP_PARALLEL || gimple_code (stmt) == GIMPLE_OMP_TASK)); @@ -1277,7 +1277,7 @@ expand_omp_taskreg (struct omp_region *region) gcc_assert (e2->dest == region->exit); remove_edge (BRANCH_EDGE (entry_bb)); set_immediate_dominator (CDI_DOMINATORS, e2->dest, e->src); - gsi = gsi_last_bb (region->exit); + gsi = gsi_last_nondebug_bb (region->exit); gcc_assert (!gsi_end_p (gsi) && gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_RETURN); gsi_remove (&gsi, true); @@ -1286,7 +1286,7 @@ expand_omp_taskreg (struct omp_region *region) /* Convert GIMPLE_OMP_{RETURN,CONTINUE} into a RETURN_EXPR. */ if (exit_bb) { - gsi = gsi_last_bb (exit_bb); + gsi = gsi_last_nondebug_bb (exit_bb); gcc_assert (!gsi_end_p (gsi) && (gimple_code (gsi_stmt (gsi)) == (e2 ? GIMPLE_OMP_CONTINUE : GIMPLE_OMP_RETURN))); @@ -1748,7 +1748,7 @@ expand_omp_for_init_counts (struct omp_for_data *fd, gimple_stmt_iterator *gsi, if (l2_dom_bb == NULL) l2_dom_bb = entry_bb; entry_bb = e->dest; - *gsi = gsi_last_bb (entry_bb); + *gsi = gsi_last_nondebug_bb (entry_bb); } if (POINTER_TYPE_P (itype)) @@ -2553,7 +2553,7 @@ expand_omp_for_generic (struct omp_region *region, l3_bb = BRANCH_EDGE (entry_bb)->dest; exit_bb = region->exit; - gsi = gsi_last_bb (entry_bb); + gsi = gsi_last_nondebug_bb (entry_bb); gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR); if (fd->ordered @@ -2583,7 +2583,7 @@ expand_omp_for_generic (struct omp_region *region, e = split_block (entry_bb, gsi_stmt (gsi)); entry_bb = e->dest; make_edge (zero_iter1_bb, entry_bb, EDGE_FALLTHRU); - gsi = gsi_last_bb (entry_bb); + gsi = gsi_last_nondebug_bb (entry_bb); set_immediate_dominator (CDI_DOMINATORS, entry_bb, get_immediate_dominator (CDI_DOMINATORS, zero_iter1_bb)); @@ -2604,7 +2604,7 @@ expand_omp_for_generic (struct omp_region *region, e = split_block (entry_bb, gsi_stmt (gsi)); entry_bb = e->dest; make_edge (zero_iter2_bb, entry_bb, EDGE_FALLTHRU); - gsi = gsi_last_bb (entry_bb); + gsi = gsi_last_nondebug_bb (entry_bb); set_immediate_dominator (CDI_DOMINATORS, entry_bb, get_immediate_dominator (CDI_DOMINATORS, zero_iter2_bb)); @@ -3022,7 +3022,7 @@ expand_omp_for_generic (struct omp_region *region, { /* Code to control the increment and predicate for the sequential loop goes in the CONT_BB. */ - gsi = gsi_last_bb (cont_bb); + gsi = gsi_last_nondebug_bb (cont_bb); gomp_continue *cont_stmt = as_a (gsi_stmt (gsi)); gcc_assert (gimple_code (cont_stmt) == GIMPLE_OMP_CONTINUE); vmain = gimple_omp_continue_control_use (cont_stmt); @@ -3088,7 +3088,7 @@ expand_omp_for_generic (struct omp_region *region, } /* Add the loop cleanup function. */ - gsi = gsi_last_bb (exit_bb); + gsi = gsi_last_nondebug_bb (exit_bb); if (gimple_omp_return_nowait_p (gsi_stmt (gsi))) t = builtin_decl_explicit (BUILT_IN_GOMP_LOOP_END_NOWAIT); else if (gimple_omp_return_lhs (gsi_stmt (gsi))) @@ -3308,7 +3308,7 @@ expand_omp_for_static_nochunk (struct omp_region *region, exit_bb = region->exit; /* Iteration space partitioning goes in ENTRY_BB. */ - gsi = gsi_last_bb (entry_bb); + gsi = gsi_last_nondebug_bb (entry_bb); gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR); if (fd->collapse > 1) @@ -3440,7 +3440,7 @@ expand_omp_for_static_nochunk (struct omp_region *region, gsi_insert_before (&gsi, cond_stmt, GSI_SAME_STMT); second_bb = split_block (entry_bb, cond_stmt)->dest; - gsi = gsi_last_bb (second_bb); + gsi = gsi_last_nondebug_bb (second_bb); gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR); gsi_insert_before (&gsi, gimple_build_assign (tt, build_int_cst (itype, 0)), @@ -3450,7 +3450,7 @@ expand_omp_for_static_nochunk (struct omp_region *region, gsi_insert_before (&gsi, assign_stmt, GSI_SAME_STMT); third_bb = split_block (second_bb, assign_stmt)->dest; - gsi = gsi_last_bb (third_bb); + gsi = gsi_last_nondebug_bb (third_bb); gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR); t = build2 (MULT_EXPR, itype, q, threadid); @@ -3592,7 +3592,7 @@ expand_omp_for_static_nochunk (struct omp_region *region, { /* The code controlling the sequential loop replaces the GIMPLE_OMP_CONTINUE. */ - gsi = gsi_last_bb (cont_bb); + gsi = gsi_last_nondebug_bb (cont_bb); gomp_continue *cont_stmt = as_a (gsi_stmt (gsi)); gcc_assert (gimple_code (cont_stmt) == GIMPLE_OMP_CONTINUE); vmain = gimple_omp_continue_control_use (cont_stmt); @@ -3625,7 +3625,7 @@ expand_omp_for_static_nochunk (struct omp_region *region, } /* Replace the GIMPLE_OMP_RETURN with a barrier, or nothing. */ - gsi = gsi_last_bb (exit_bb); + gsi = gsi_last_nondebug_bb (exit_bb); if (!gimple_omp_return_nowait_p (gsi_stmt (gsi))) { t = gimple_omp_return_lhs (gsi_stmt (gsi)); @@ -3792,7 +3792,7 @@ expand_omp_for_static_chunk (struct omp_region *region, exit_bb = region->exit; /* Trip and adjustment setup goes in ENTRY_BB. */ - gsi = gsi_last_bb (entry_bb); + gsi = gsi_last_nondebug_bb (entry_bb); gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR); if (fd->collapse > 1) @@ -4098,7 +4098,7 @@ expand_omp_for_static_chunk (struct omp_region *region, { /* The code controlling the sequential loop goes in CONT_BB, replacing the GIMPLE_OMP_CONTINUE. */ - gsi = gsi_last_bb (cont_bb); + gsi = gsi_last_nondebug_bb (cont_bb); gomp_continue *cont_stmt = as_a (gsi_stmt (gsi)); vmain = gimple_omp_continue_control_use (cont_stmt); vback = gimple_omp_continue_control_def (cont_stmt); @@ -4142,7 +4142,7 @@ expand_omp_for_static_chunk (struct omp_region *region, } /* Replace the GIMPLE_OMP_RETURN with a barrier, or nothing. */ - gsi = gsi_last_bb (exit_bb); + gsi = gsi_last_nondebug_bb (exit_bb); if (!gimple_omp_return_nowait_p (gsi_stmt (gsi))) { t = gimple_omp_return_lhs (gsi_stmt (gsi)); @@ -4353,7 +4353,7 @@ expand_cilk_for (struct omp_region *region, struct omp_for_data *fd) basic_block exit_bb = region->exit; basic_block l2_dom_bb = NULL; - gimple_stmt_iterator gsi = gsi_last_bb (entry_bb); + gimple_stmt_iterator gsi = gsi_last_nondebug_bb (entry_bb); /* Below statements until the "tree high_val = ..." are pseudo statements used to pass information to be used by expand_omp_taskreg. @@ -4398,7 +4398,7 @@ expand_cilk_for (struct omp_region *region, struct omp_for_data *fd) if (!broken_loop) { /* Code to control the increment goes in the CONT_BB. */ - gsi = gsi_last_bb (cont_bb); + gsi = gsi_last_nondebug_bb (cont_bb); stmt = gsi_stmt (gsi); gcc_assert (gimple_code (stmt) == GIMPLE_OMP_CONTINUE); stmt = gimple_build_assign (ind_var, PLUS_EXPR, ind_var, @@ -4428,7 +4428,7 @@ expand_cilk_for (struct omp_region *region, struct omp_for_data *fd) gsi_insert_before (&gsi, stmt, GSI_SAME_STMT); /* Remove GIMPLE_OMP_RETURN. */ - gsi = gsi_last_bb (exit_bb); + gsi = gsi_last_nondebug_bb (exit_bb); gsi_remove (&gsi, true); /* Connect the new blocks. */ @@ -4602,7 +4602,7 @@ expand_omp_simd (struct omp_region *region, struct omp_for_data *fd) exit_bb = region->exit; l2_dom_bb = NULL; - gsi = gsi_last_bb (entry_bb); + gsi = gsi_last_nondebug_bb (entry_bb); gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR); /* Not needed in SSA form right now. */ @@ -4697,7 +4697,7 @@ expand_omp_simd (struct omp_region *region, struct omp_for_data *fd) if (!broken_loop) { /* Code to control the increment goes in the CONT_BB. */ - gsi = gsi_last_bb (cont_bb); + gsi = gsi_last_nondebug_bb (cont_bb); stmt = gsi_stmt (gsi); gcc_assert (gimple_code (stmt) == GIMPLE_OMP_CONTINUE); @@ -4795,7 +4795,7 @@ expand_omp_simd (struct omp_region *region, struct omp_for_data *fd) } /* Remove GIMPLE_OMP_RETURN. */ - gsi = gsi_last_bb (exit_bb); + gsi = gsi_last_nondebug_bb (exit_bb); gsi_remove (&gsi, true); /* Connect the new blocks. */ @@ -4921,7 +4921,7 @@ expand_omp_taskloop_for_outer (struct omp_region *region, gcc_assert (BRANCH_EDGE (entry_bb)->dest == FALLTHRU_EDGE (cont_bb)->dest); exit_bb = region->exit; - gsi = gsi_last_bb (entry_bb); + gsi = gsi_last_nondebug_bb (entry_bb); gimple *for_stmt = gsi_stmt (gsi); gcc_assert (gimple_code (for_stmt) == GIMPLE_OMP_FOR); if (fd->collapse > 1) @@ -5022,10 +5022,10 @@ expand_omp_taskloop_for_outer (struct omp_region *region, gsi = gsi_for_stmt (for_stmt); gsi_remove (&gsi, true); - gsi = gsi_last_bb (cont_bb); + gsi = gsi_last_nondebug_bb (cont_bb); gsi_remove (&gsi, true); - gsi = gsi_last_bb (exit_bb); + gsi = gsi_last_nondebug_bb (exit_bb); gsi_remove (&gsi, true); FALLTHRU_EDGE (entry_bb)->probability = profile_probability::always (); @@ -5099,7 +5099,7 @@ expand_omp_taskloop_for_inner (struct omp_region *region, exit_bb = region->exit; /* Iteration space partitioning goes in ENTRY_BB. */ - gsi = gsi_last_bb (entry_bb); + gsi = gsi_last_nondebug_bb (entry_bb); gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR); if (fd->collapse > 1) @@ -5178,7 +5178,7 @@ expand_omp_taskloop_for_inner (struct omp_region *region, { /* The code controlling the sequential loop replaces the GIMPLE_OMP_CONTINUE. */ - gsi = gsi_last_bb (cont_bb); + gsi = gsi_last_nondebug_bb (cont_bb); gomp_continue *cont_stmt = as_a (gsi_stmt (gsi)); gcc_assert (gimple_code (cont_stmt) == GIMPLE_OMP_CONTINUE); vmain = gimple_omp_continue_control_use (cont_stmt); @@ -5215,7 +5215,7 @@ expand_omp_taskloop_for_inner (struct omp_region *region, gsi_remove (&gsi, true); /* Remove the GIMPLE_OMP_RETURN statement. */ - gsi = gsi_last_bb (exit_bb); + gsi = gsi_last_nondebug_bb (exit_bb); gsi_remove (&gsi, true); FALLTHRU_EDGE (entry_bb)->probability = profile_probability::always (); @@ -5398,7 +5398,7 @@ expand_oacc_for (struct omp_region *region, struct omp_for_data *fd) entry_bb = split->src; /* Chunk setup goes at end of entry_bb, replacing the omp_for. */ - gsi = gsi_last_bb (entry_bb); + gsi = gsi_last_nondebug_bb (entry_bb); gomp_for *for_stmt = as_a (gsi_stmt (gsi)); loc = gimple_location (for_stmt); @@ -5525,7 +5525,7 @@ expand_oacc_for (struct omp_region *region, struct omp_for_data *fd) if (gimple_in_ssa_p (cfun)) { - gsi = gsi_last_bb (cont_bb); + gsi = gsi_last_nondebug_bb (cont_bb); gomp_continue *cont_stmt = as_a (gsi_stmt (gsi)); offset = gimple_omp_continue_control_use (cont_stmt); @@ -5649,7 +5649,7 @@ expand_oacc_for (struct omp_region *region, struct omp_for_data *fd) occur, especially when noreturn routines are involved. */ if (cont_bb) { - gsi = gsi_last_bb (cont_bb); + gsi = gsi_last_nondebug_bb (cont_bb); gomp_continue *cont_stmt = as_a (gsi_stmt (gsi)); loc = gimple_location (cont_stmt); @@ -5738,7 +5738,7 @@ expand_oacc_for (struct omp_region *region, struct omp_for_data *fd) } } - gsi = gsi_last_bb (exit_bb); + gsi = gsi_last_nondebug_bb (exit_bb); gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_RETURN); loc = gimple_location (gsi_stmt (gsi)); @@ -5965,7 +5965,7 @@ expand_omp_sections (struct omp_region *region) len = EDGE_COUNT (l0_bb->succs); gcc_assert (len > 0); e = EDGE_SUCC (l0_bb, len - 1); - si = gsi_last_bb (e->dest); + si = gsi_last_nondebug_bb (e->dest); l2 = NULL_TREE; if (gsi_end_p (si) || gimple_code (gsi_stmt (si)) != GIMPLE_OMP_SECTION) @@ -5973,7 +5973,7 @@ expand_omp_sections (struct omp_region *region) else FOR_EACH_EDGE (e, ei, l0_bb->succs) { - si = gsi_last_bb (e->dest); + si = gsi_last_nondebug_bb (e->dest); if (gsi_end_p (si) || gimple_code (gsi_stmt (si)) != GIMPLE_OMP_SECTION) { @@ -5998,7 +5998,7 @@ expand_omp_sections (struct omp_region *region) /* The call to GOMP_sections_start goes in ENTRY_BB, replacing the GIMPLE_OMP_SECTIONS statement. */ - si = gsi_last_bb (entry_bb); + si = gsi_last_nondebug_bb (entry_bb); sections_stmt = as_a (gsi_stmt (si)); gcc_assert (gimple_code (sections_stmt) == GIMPLE_OMP_SECTIONS); vin = gimple_omp_sections_control (sections_stmt); @@ -6022,7 +6022,7 @@ expand_omp_sections (struct omp_region *region) /* The switch() statement replacing GIMPLE_OMP_SECTIONS_SWITCH goes in L0_BB. */ - switch_si = gsi_last_bb (l0_bb); + switch_si = gsi_last_nondebug_bb (l0_bb); gcc_assert (gimple_code (gsi_stmt (switch_si)) == GIMPLE_OMP_SECTIONS_SWITCH); if (exit_reachable) { @@ -6064,7 +6064,7 @@ expand_omp_sections (struct omp_region *region) u = build_case_label (u, NULL, t); label_vec.quick_push (u); - si = gsi_last_bb (s_entry_bb); + si = gsi_last_nondebug_bb (s_entry_bb); gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_SECTION); gcc_assert (i < len || gimple_omp_section_last_p (gsi_stmt (si))); gsi_remove (&si, true); @@ -6073,7 +6073,7 @@ expand_omp_sections (struct omp_region *region) if (s_exit_bb == NULL) continue; - si = gsi_last_bb (s_exit_bb); + si = gsi_last_nondebug_bb (s_exit_bb); gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_RETURN); gsi_remove (&si, true); @@ -6099,7 +6099,7 @@ expand_omp_sections (struct omp_region *region) tree bfn_decl; /* Code to get the next section goes in L1_BB. */ - si = gsi_last_bb (l1_bb); + si = gsi_last_nondebug_bb (l1_bb); gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_CONTINUE); bfn_decl = builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_NEXT); @@ -6112,7 +6112,7 @@ expand_omp_sections (struct omp_region *region) } /* Cleanup function replaces GIMPLE_OMP_RETURN in EXIT_BB. */ - si = gsi_last_bb (l2_bb); + si = gsi_last_nondebug_bb (l2_bb); if (gimple_omp_return_nowait_p (gsi_stmt (si))) t = builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_END_NOWAIT); else if (gimple_omp_return_lhs (gsi_stmt (si))) @@ -6140,12 +6140,12 @@ expand_omp_single (struct omp_region *region) entry_bb = region->entry; exit_bb = region->exit; - si = gsi_last_bb (entry_bb); + si = gsi_last_nondebug_bb (entry_bb); gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_SINGLE); gsi_remove (&si, true); single_succ_edge (entry_bb)->flags = EDGE_FALLTHRU; - si = gsi_last_bb (exit_bb); + si = gsi_last_nondebug_bb (exit_bb); if (!gimple_omp_return_nowait_p (gsi_stmt (si))) { tree t = gimple_omp_return_lhs (gsi_stmt (si)); @@ -6168,7 +6168,7 @@ expand_omp_synch (struct omp_region *region) entry_bb = region->entry; exit_bb = region->exit; - si = gsi_last_bb (entry_bb); + si = gsi_last_nondebug_bb (entry_bb); gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_SINGLE || gimple_code (gsi_stmt (si)) == GIMPLE_OMP_MASTER || gimple_code (gsi_stmt (si)) == GIMPLE_OMP_TASKGROUP @@ -6180,7 +6180,7 @@ expand_omp_synch (struct omp_region *region) if (exit_bb) { - si = gsi_last_bb (exit_bb); + si = gsi_last_nondebug_bb (exit_bb); gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_RETURN); gsi_remove (&si, true); single_succ_edge (exit_bb)->flags = EDGE_FALLTHRU; @@ -6201,7 +6201,7 @@ expand_omp_atomic_load (basic_block load_bb, tree addr, gimple *stmt; tree decl, call, type, itype; - gsi = gsi_last_bb (load_bb); + gsi = gsi_last_nondebug_bb (load_bb); stmt = gsi_stmt (gsi); gcc_assert (gimple_code (stmt) == GIMPLE_OMP_ATOMIC_LOAD); loc = gimple_location (stmt); @@ -6231,7 +6231,7 @@ expand_omp_atomic_load (basic_block load_bb, tree addr, gsi_remove (&gsi, true); store_bb = single_succ (load_bb); - gsi = gsi_last_bb (store_bb); + gsi = gsi_last_nondebug_bb (store_bb); gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_ATOMIC_STORE); gsi_remove (&gsi, true); @@ -6257,14 +6257,14 @@ expand_omp_atomic_store (basic_block load_bb, tree addr, machine_mode imode; bool exchange; - gsi = gsi_last_bb (load_bb); + gsi = gsi_last_nondebug_bb (load_bb); stmt = gsi_stmt (gsi); gcc_assert (gimple_code (stmt) == GIMPLE_OMP_ATOMIC_LOAD); /* If the load value is needed, then this isn't a store but an exchange. */ exchange = gimple_omp_atomic_need_value_p (stmt); - gsi = gsi_last_bb (store_bb); + gsi = gsi_last_nondebug_bb (store_bb); stmt = gsi_stmt (gsi); gcc_assert (gimple_code (stmt) == GIMPLE_OMP_ATOMIC_STORE); loc = gimple_location (stmt); @@ -6309,7 +6309,7 @@ expand_omp_atomic_store (basic_block load_bb, tree addr, gsi_remove (&gsi, true); /* Remove the GIMPLE_OMP_ATOMIC_LOAD that we verified above. */ - gsi = gsi_last_bb (load_bb); + gsi = gsi_last_nondebug_bb (load_bb); gsi_remove (&gsi, true); if (gimple_in_ssa_p (cfun)) @@ -6356,10 +6356,17 @@ expand_omp_atomic_fetch_op (basic_block load_bb, gsi = gsi_after_labels (store_bb); stmt = gsi_stmt (gsi); + if (is_gimple_debug (stmt)) + { + gsi_next_nondebug (&gsi); + if (gsi_end_p (gsi)) + return false; + stmt = gsi_stmt (gsi); + } loc = gimple_location (stmt); if (!is_gimple_assign (stmt)) return false; - gsi_next (&gsi); + gsi_next_nondebug (&gsi); if (gimple_code (gsi_stmt (gsi)) != GIMPLE_OMP_ATOMIC_STORE) return false; need_new = gimple_omp_atomic_need_value_p (gsi_stmt (gsi)); @@ -6423,7 +6430,7 @@ expand_omp_atomic_fetch_op (basic_block load_bb, if (!can_compare_and_swap_p (imode, true) || !can_atomic_load_p (imode)) return false; - gsi = gsi_last_bb (load_bb); + gsi = gsi_last_nondebug_bb (load_bb); gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_ATOMIC_LOAD); /* OpenMP does not imply any barrier-like semantics on its atomic ops. @@ -6446,10 +6453,10 @@ expand_omp_atomic_fetch_op (basic_block load_bb, force_gimple_operand_gsi (&gsi, call, true, NULL_TREE, true, GSI_SAME_STMT); gsi_remove (&gsi, true); - gsi = gsi_last_bb (store_bb); + gsi = gsi_last_nondebug_bb (store_bb); gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_ATOMIC_STORE); gsi_remove (&gsi, true); - gsi = gsi_last_bb (store_bb); + gsi = gsi_last_nondebug_bb (store_bb); stmt = gsi_stmt (gsi); gsi_remove (&gsi, true); @@ -6502,7 +6509,7 @@ expand_omp_atomic_pipeline (basic_block load_bb, basic_block store_bb, return false; /* Load the initial value, replacing the GIMPLE_OMP_ATOMIC_LOAD. */ - si = gsi_last_bb (load_bb); + si = gsi_last_nondebug_bb (load_bb); gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_ATOMIC_LOAD); /* For floating-point values, we'll need to view-convert them to integers @@ -6582,7 +6589,7 @@ expand_omp_atomic_pipeline (basic_block load_bb, basic_block store_bb, } gsi_remove (&si, true); - si = gsi_last_bb (store_bb); + si = gsi_last_nondebug_bb (store_bb); gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_ATOMIC_STORE); if (iaddr == addr) @@ -6685,7 +6692,7 @@ expand_omp_atomic_mutex (basic_block load_bb, basic_block store_bb, gassign *stmt; tree t; - si = gsi_last_bb (load_bb); + si = gsi_last_nondebug_bb (load_bb); gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_ATOMIC_LOAD); t = builtin_decl_explicit (BUILT_IN_GOMP_ATOMIC_START); @@ -6696,7 +6703,7 @@ expand_omp_atomic_mutex (basic_block load_bb, basic_block store_bb, gsi_insert_before (&si, stmt, GSI_SAME_STMT); gsi_remove (&si, true); - si = gsi_last_bb (store_bb); + si = gsi_last_nondebug_bb (store_bb); gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_ATOMIC_STORE); stmt = gimple_build_assign (build_simple_mem_ref (unshare_expr (addr)), @@ -7195,7 +7202,7 @@ expand_omp_target (struct omp_region *region) /* Split ENTRY_BB at GIMPLE_*, so that it can be moved to the child function. */ - gsi = gsi_last_bb (entry_bb); + gsi = gsi_last_nondebug_bb (entry_bb); stmt = gsi_stmt (gsi); gcc_assert (stmt && gimple_code (stmt) == gimple_code (entry_stmt)); @@ -7207,7 +7214,7 @@ expand_omp_target (struct omp_region *region) /* Convert GIMPLE_OMP_RETURN into a RETURN_EXPR. */ if (exit_bb) { - gsi = gsi_last_bb (exit_bb); + gsi = gsi_last_nondebug_bb (exit_bb); gcc_assert (!gsi_end_p (gsi) && gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_RETURN); stmt = gimple_build_return (NULL); @@ -7389,7 +7396,7 @@ expand_omp_target (struct omp_region *region) e = split_block_after_labels (new_bb); else { - gsi = gsi_last_bb (new_bb); + gsi = gsi_last_nondebug_bb (new_bb); gsi_prev (&gsi); e = split_block (new_bb, gsi_stmt (gsi)); } @@ -7424,11 +7431,11 @@ expand_omp_target (struct omp_region *region) make_edge (else_bb, new_bb, EDGE_FALLTHRU); device = tmp_var; - gsi = gsi_last_bb (new_bb); + gsi = gsi_last_nondebug_bb (new_bb); } else { - gsi = gsi_last_bb (new_bb); + gsi = gsi_last_nondebug_bb (new_bb); device = force_gimple_operand_gsi (&gsi, device, true, NULL_TREE, true, GSI_SAME_STMT); } @@ -7572,7 +7579,7 @@ expand_omp_target (struct omp_region *region) } if (data_region && region->exit) { - gsi = gsi_last_bb (region->exit); + gsi = gsi_last_nondebug_bb (region->exit); g = gsi_stmt (gsi); gcc_assert (g && gimple_code (g) == GIMPLE_OMP_RETURN); gsi_remove (&gsi, true); @@ -7653,17 +7660,17 @@ grid_expand_omp_for_loop (struct omp_region *kfor, bool intra_group) gsi_insert_before (&gsi, assign_stmt, GSI_SAME_STMT); } /* Remove the omp for statement. */ - gsi = gsi_last_bb (kfor->entry); + gsi = gsi_last_nondebug_bb (kfor->entry); gsi_remove (&gsi, true); /* Remove the GIMPLE_OMP_CONTINUE statement. */ - gsi = gsi_last_bb (kfor->cont); + gsi = gsi_last_nondebug_bb (kfor->cont); gcc_assert (!gsi_end_p (gsi) && gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_CONTINUE); gsi_remove (&gsi, true); /* Replace the GIMPLE_OMP_RETURN with a barrier, if necessary. */ - gsi = gsi_last_bb (kfor->exit); + gsi = gsi_last_nondebug_bb (kfor->exit); gcc_assert (!gsi_end_p (gsi) && gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_RETURN); if (intra_group) @@ -7807,11 +7814,11 @@ grid_expand_target_grid_body (struct omp_region *target) grid_expand_omp_for_loop (kfor, false); /* Remove the omp for statement. */ - gimple_stmt_iterator gsi = gsi_last_bb (gpukernel->entry); + gimple_stmt_iterator gsi = gsi_last_nondebug_bb (gpukernel->entry); gsi_remove (&gsi, true); /* Replace the GIMPLE_OMP_RETURN at the end of the kernel region with a real return. */ - gsi = gsi_last_bb (gpukernel->exit); + gsi = gsi_last_nondebug_bb (gpukernel->exit); gcc_assert (!gsi_end_p (gsi) && gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_RETURN); gimple *ret_stmt = gimple_build_return (NULL); @@ -7995,7 +8002,7 @@ build_omp_regions_1 (basic_block bb, struct omp_region *parent, gimple *stmt; basic_block son; - gsi = gsi_last_bb (bb); + gsi = gsi_last_nondebug_bb (bb); if (!gsi_end_p (gsi) && is_gimple_omp (gsi_stmt (gsi))) { struct omp_region *region; diff --git a/gcc/omp-low.c b/gcc/omp-low.c index 8ed8f7c..8852798 100644 --- a/gcc/omp-low.c +++ b/gcc/omp-low.c @@ -7023,6 +7023,8 @@ check_combined_parallel (gimple_stmt_iterator *gsi_p, { WALK_SUBSTMTS; + case GIMPLE_DEBUG: + break; case GIMPLE_OMP_FOR: case GIMPLE_OMP_SECTIONS: *info = *info == 0 ? 1 : -1; diff --git a/gcc/postreload.c b/gcc/postreload.c index 000ed34..8e4a8190 100644 --- a/gcc/postreload.c +++ b/gcc/postreload.c @@ -836,7 +836,7 @@ fixup_debug_insns (rtx reg, rtx replacement, rtx_insn *from, rtx_insn *to) { rtx t; - if (!DEBUG_INSN_P (insn)) + if (!DEBUG_BIND_INSN_P (insn)) continue; t = INSN_VAR_LOCATION_LOC (insn); diff --git a/gcc/regcprop.c b/gcc/regcprop.c index 0ce64d7..ee9b119 100644 --- a/gcc/regcprop.c +++ b/gcc/regcprop.c @@ -433,6 +433,8 @@ find_oldest_value_reg (enum reg_class cl, rtx reg, struct value_data *vd) machine_mode mode = GET_MODE (reg); unsigned int i; + gcc_assert (regno < FIRST_PSEUDO_REGISTER); + /* If we are accessing REG in some mode other that what we set it in, make sure that the replacement is valid. In particular, consider (set (reg:DI r11) (...)) diff --git a/gcc/tree-cfg.c b/gcc/tree-cfg.c index dc9ce3c..1796850 100644 --- a/gcc/tree-cfg.c +++ b/gcc/tree-cfg.c @@ -545,14 +545,22 @@ make_blocks_1 (gimple_seq seq, basic_block bb) { gimple_stmt_iterator i = gsi_start (seq); gimple *stmt = NULL; + gimple *prev_stmt = NULL; bool start_new_block = true; bool first_stmt_of_seq = true; while (!gsi_end_p (i)) { - gimple *prev_stmt; - - prev_stmt = stmt; + /* PREV_STMT should only be set to a debug stmt if the debug + stmt is before nondebug stmts. Once stmt reaches a nondebug + nonlabel, prev_stmt will be set to it, so that + stmt_starts_bb_p will know to start a new block if a label is + found. However, if stmt was a label after debug stmts only, + keep the label in prev_stmt even if we find further debug + stmts, for there may be other labels after them, and they + should land in the same block. */ + if (!prev_stmt || !stmt || !is_gimple_debug (stmt)) + prev_stmt = stmt; stmt = gsi_stmt (i); if (stmt && is_gimple_call (stmt)) @@ -567,6 +575,7 @@ make_blocks_1 (gimple_seq seq, basic_block bb) gsi_split_seq_before (&i, &seq); bb = create_basic_block (seq, bb); start_new_block = false; + prev_stmt = NULL; } /* Now add STMT to BB and create the subgraphs for special statement @@ -980,7 +989,11 @@ make_edges (void) tree target; if (!label_stmt) - break; + { + if (is_gimple_debug (gsi_stmt (gsi))) + continue; + break; + } target = gimple_label_label (label_stmt); @@ -1495,6 +1508,9 @@ cleanup_dead_labels (void) for (i = gsi_start_bb (bb); !gsi_end_p (i); gsi_next (&i)) { + if (is_gimple_debug (gsi_stmt (i))) + continue; + tree label; glabel *label_stmt = dyn_cast (gsi_stmt (i)); @@ -1655,6 +1671,12 @@ cleanup_dead_labels (void) for (i = gsi_start_bb (bb); !gsi_end_p (i); ) { + if (is_gimple_debug (gsi_stmt (i))) + { + gsi_next (&i); + continue; + } + tree label; glabel *label_stmt = dyn_cast (gsi_stmt (i)); @@ -1823,6 +1845,8 @@ gimple_can_merge_blocks_p (basic_block a, basic_block b) gsi_next (&gsi)) { tree lab; + if (is_gimple_debug (gsi_stmt (gsi))) + continue; glabel *label_stmt = dyn_cast (gsi_stmt (gsi)); if (!label_stmt) break; @@ -2625,6 +2649,13 @@ stmt_starts_bb_p (gimple *stmt, gimple *prev_stmt) if (stmt == NULL) return false; + /* PREV_STMT is only set to a debug stmt if the debug stmt is before + any nondebug stmts in the block. We don't want to start another + block in this case: the debug stmt will already have started the + one STMT would start if we weren't outputting debug stmts. */ + if (prev_stmt && is_gimple_debug (prev_stmt)) + return false; + /* Labels start a new basic block only if the preceding statement wasn't a label of the same type. This prevents the creation of consecutive blocks that have nothing but a single label. */ @@ -5444,6 +5475,10 @@ gimple_verify_flow_info (void) for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi)) { tree label; + + if (is_gimple_debug (gsi_stmt (gsi))) + continue; + gimple *prev_stmt = stmt; stmt = gsi_stmt (gsi); @@ -5513,7 +5548,7 @@ gimple_verify_flow_info (void) } } - gsi = gsi_last_bb (bb); + gsi = gsi_last_nondebug_bb (bb); if (gsi_end_p (gsi)) continue; @@ -5768,8 +5803,10 @@ gimple_block_label (basic_block bb) tree label; glabel *stmt; - for (i = s; !gsi_end_p (i); first = false, gsi_next (&i)) + for (i = s; !gsi_end_p (i); gsi_next (&i)) { + if (is_gimple_debug (gsi_stmt (i))) + continue; stmt = dyn_cast (gsi_stmt (i)); if (!stmt) break; @@ -5780,6 +5817,7 @@ gimple_block_label (basic_block bb) gsi_move_before (&i, &s); return label; } + first = false; } label = create_artificial_label (UNKNOWN_LOCATION); @@ -5855,7 +5893,7 @@ gimple_redirect_edge_and_branch (edge e, basic_block dest) return ret; } - gsi = gsi_last_bb (bb); + gsi = gsi_last_nondebug_bb (bb); stmt = gsi_end_p (gsi) ? NULL : gsi_stmt (gsi); switch (stmt ? gimple_code (stmt) : GIMPLE_ERROR_MARK) diff --git a/gcc/tree-cfgcleanup.c b/gcc/tree-cfgcleanup.c index a7053d7..3c4d573 100644 --- a/gcc/tree-cfgcleanup.c +++ b/gcc/tree-cfgcleanup.c @@ -555,13 +555,13 @@ remove_forwarder_block (basic_block bb) { tree decl; label = gsi_stmt (gsi); - if (is_gimple_debug (label)) - break; - decl = gimple_label_label (as_a (label)); - if (EH_LANDING_PAD_NR (decl) != 0 - || DECL_NONLOCAL (decl) - || FORCED_LABEL (decl) - || !DECL_ARTIFICIAL (decl)) + if (is_gimple_debug (label) + ? can_move_debug_stmts + : ((decl = gimple_label_label (as_a (label))), + EH_LANDING_PAD_NR (decl) != 0 + || DECL_NONLOCAL (decl) + || FORCED_LABEL (decl) + || !DECL_ARTIFICIAL (decl))) { gsi_remove (&gsi, false); gsi_insert_before (&gsi_to, label, GSI_SAME_STMT); @@ -570,20 +570,6 @@ remove_forwarder_block (basic_block bb) gsi_next (&gsi); } - /* Move debug statements if the destination has a single predecessor. */ - if (can_move_debug_stmts) - { - gsi_to = gsi_after_labels (dest); - for (gsi = gsi_after_labels (bb); !gsi_end_p (gsi); ) - { - gimple *debug = gsi_stmt (gsi); - if (!is_gimple_debug (debug)) - break; - gsi_remove (&gsi, false); - gsi_insert_before (&gsi_to, debug, GSI_SAME_STMT); - } - } - bitmap_set_bit (cfgcleanup_altered_bbs, dest->index); /* Update the dominators. */ @@ -1285,7 +1271,8 @@ execute_cleanup_cfg_post_optimizing (void) flag_dump_noaddr = flag_dump_unnumbered = 1; fprintf (final_output, "\n"); - dump_enumerated_decls (final_output, dump_flags | TDF_NOUID); + dump_enumerated_decls (final_output, + dump_flags | TDF_SLIM | TDF_NOUID); flag_dump_noaddr = save_noaddr; flag_dump_unnumbered = save_unnumbered; if (fclose (final_output)) diff --git a/gcc/tree-pretty-print.c b/gcc/tree-pretty-print.c index 14c7caa..1fe3e63 100644 --- a/gcc/tree-pretty-print.c +++ b/gcc/tree-pretty-print.c @@ -3386,7 +3386,10 @@ print_declaration (pretty_printer *pp, tree t, int spc, dump_flags_t flags) pp_space (pp); pp_equal (pp); pp_space (pp); - dump_generic_node (pp, DECL_INITIAL (t), spc, flags, false); + if (!(flags & TDF_SLIM)) + dump_generic_node (pp, DECL_INITIAL (t), spc, flags, false); + else + pp_string (pp, "<<< omitted >>>"); } } diff --git a/gcc/tree-ssa-dce.c b/gcc/tree-ssa-dce.c index f60670f..28cf643 100644 --- a/gcc/tree-ssa-dce.c +++ b/gcc/tree-ssa-dce.c @@ -257,7 +257,8 @@ mark_stmt_if_obviously_necessary (gimple *stmt, bool aggressive) easily locate the debug temp bind stmt for a use thereof, would could refrain from marking all debug temps here, and mark them only if they're used. */ - if (!gimple_debug_bind_p (stmt) + if (gimple_debug_nonbind_marker_p (stmt) + || !gimple_debug_bind_p (stmt) || gimple_debug_bind_has_value_p (stmt) || TREE_CODE (gimple_debug_bind_get_var (stmt)) != DEBUG_EXPR_DECL) mark_stmt_necessary (stmt, false); @@ -1448,8 +1449,7 @@ eliminate_unnecessary_stmts (void) dominate others. Walking backwards, this should be the common case. ??? Do we need to recompute dominators because of cfg_altered? */ - if (!MAY_HAVE_DEBUG_STMTS - || !first_dom_son (CDI_DOMINATORS, bb)) + if (!first_dom_son (CDI_DOMINATORS, bb)) delete_basic_block (bb); else { diff --git a/gcc/tree-ssa-tail-merge.c b/gcc/tree-ssa-tail-merge.c index a3d5074..01b8821 100644 --- a/gcc/tree-ssa-tail-merge.c +++ b/gcc/tree-ssa-tail-merge.c @@ -1295,14 +1295,14 @@ find_duplicate (same_succ *same_succ, basic_block bb1, basic_block bb2) tree label = gimple_label_label (as_a (gsi_stmt (gsi1))); if (DECL_NONLOCAL (label) || FORCED_LABEL (label)) return; - gsi_prev (&gsi1); + gsi_prev_nondebug (&gsi1); } while (!gsi_end_p (gsi2) && gimple_code (gsi_stmt (gsi2)) == GIMPLE_LABEL) { tree label = gimple_label_label (as_a (gsi_stmt (gsi2))); if (DECL_NONLOCAL (label) || FORCED_LABEL (label)) return; - gsi_prev (&gsi2); + gsi_prev_nondebug (&gsi2); } if (!(gsi_end_p (gsi1) && gsi_end_p (gsi2))) return; diff --git a/gcc/var-tracking.c b/gcc/var-tracking.c index 43fc71a..974b4ea 100644 --- a/gcc/var-tracking.c +++ b/gcc/var-tracking.c @@ -9472,6 +9472,24 @@ emit_notes_in_bb (basic_block bb, dataflow_set *set) } } +/* Return BB's head, unless BB is the block that succeeds ENTRY_BLOCK, + in which case it searches back from BB's head for the very first + insn. Use [get_first_insn (bb), BB_HEAD (bb->next_bb)[ as a range + to iterate over all insns of a function while iterating over its + BBs. */ + +static rtx_insn * +get_first_insn (basic_block bb) +{ + rtx_insn *insn = BB_HEAD (bb); + + if (bb->prev_bb == ENTRY_BLOCK_PTR_FOR_FN (cfun)) + while (rtx_insn *prev = PREV_INSN (insn)) + insn = prev; + + return insn; +} + /* Emit notes for the whole function. */ static void @@ -9500,7 +9518,8 @@ vt_emit_notes (void) { /* Emit the notes for changes of variable locations between two subsequent basic blocks. */ - emit_notes_for_differences (BB_HEAD (bb), &cur, &VTI (bb)->in); + emit_notes_for_differences (get_first_insn (bb), + &cur, &VTI (bb)->in); if (MAY_HAVE_DEBUG_BIND_INSNS) local_get_addr_cache = new hash_map; @@ -10096,11 +10115,34 @@ vt_initialize (void) { HOST_WIDE_INT offset = VTI (bb)->out.stack_adjust; VTI (bb)->out.stack_adjust = VTI (bb)->in.stack_adjust; - for (insn = BB_HEAD (bb); insn != NEXT_INSN (BB_END (bb)); - insn = NEXT_INSN (insn)) + + /* If we are walking the first basic block, walk any HEADER + insns that might be before it too. Unfortunately, + BB_HEADER and BB_FOOTER are not set while we run this + pass. */ + insn = get_first_insn (bb); + for (rtx_insn *next; + insn != BB_HEAD (bb->next_bb) + ? next = NEXT_INSN (insn), true : false; + insn = next) { if (INSN_P (insn)) { + basic_block save_bb = BLOCK_FOR_INSN (insn); + if (!BLOCK_FOR_INSN (insn)) + { + BLOCK_FOR_INSN (insn) = bb; + gcc_assert (DEBUG_INSN_P (insn)); + /* Reset debug insns between basic blocks. + Their location is not reliable, because they + were probably not maintained up to date. */ + if (DEBUG_BIND_INSN_P (insn)) + INSN_VAR_LOCATION_LOC (insn) + = gen_rtx_UNKNOWN_VAR_LOC (); + } + else + gcc_assert (BLOCK_FOR_INSN (insn) == bb); + if (!frame_pointer_needed) { insn_stack_adjust_offset_pre_post (insn, &pre, &post); @@ -10168,6 +10210,7 @@ vt_initialize (void) } } } + BLOCK_FOR_INSN (insn) = save_bb; } } gcc_assert (offset == VTI (bb)->out.stack_adjust); @@ -10208,7 +10251,10 @@ delete_debug_insns (void) FOR_EACH_BB_FN (bb, cfun) { - FOR_BB_INSNS_SAFE (bb, insn, next) + for (insn = get_first_insn (bb); + insn != BB_HEAD (bb->next_bb) + ? next = NEXT_INSN (insn), true : false; + insn = next) if (DEBUG_INSN_P (insn)) { tree decl = INSN_VAR_LOCATION_DECL (insn); From patchwork Sat Sep 30 09:08:22 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Alexandre Oliva X-Patchwork-Id: 820192 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (mailfrom) smtp.mailfrom=gcc.gnu.org (client-ip=209.132.180.131; helo=sourceware.org; envelope-from=gcc-patches-return-463264-incoming=patchwork.ozlabs.org@gcc.gnu.org; receiver=) Authentication-Results: ozlabs.org; dkim=pass (1024-bit key; unprotected) header.d=gcc.gnu.org header.i=@gcc.gnu.org header.b="nGlTjG1y"; dkim-atps=neutral Received: from sourceware.org (server1.sourceware.org [209.132.180.131]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 3y42jX0s7Nz9t2h for ; Sat, 30 Sep 2017 19:11:27 +1000 (AEST) DomainKey-Signature: a=rsa-sha1; c=nofws; d=gcc.gnu.org; h=list-id :list-unsubscribe:list-archive:list-post:list-help:sender:from :to:cc:subject:date:message-id:in-reply-to:references; q=dns; s= default; b=xJqAhJ7h+xjRmiQjt+6wUs+cJx6cxj7IbSAdDQISdkMQCj+MD5Sr1 3v9QlBLezhC98o475kh6IQXFIOsl1QcH8ZR764ZLsdAfAV1pFFzJ1Xu6xnKL0uLo whYB4s7BuYEDqIJaoYNQ4+d7W9sC2B7HhIgaEnaEVuFmf7dlrdoJwA= DKIM-Signature: v=1; a=rsa-sha1; c=relaxed; d=gcc.gnu.org; h=list-id :list-unsubscribe:list-archive:list-post:list-help:sender:from :to:cc:subject:date:message-id:in-reply-to:references; s= default; bh=ro8/fvaULNKkbifpVbF9GbK+Dfg=; b=nGlTjG1y9OUr8pL48vWv fkU012yjuDDfN8hwvuukaALCjJVdgJLQ7yiIKQZTL74Zw1U5qURVW7qgiJ2eRV7J dVW/SOlty4P37APYGjSaeCQpLSZWc6EkegzYqsY8X4c+AZdxwI5WB4OnlYoI3WI8 aSRdd194mIo3/gKKQHCzrRY= Received: (qmail 64729 invoked by alias); 30 Sep 2017 09:09:58 -0000 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 Received: (qmail 64344 invoked by uid 89); 30 Sep 2017 09:09:53 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-25.9 required=5.0 tests=BAYES_00, GIT_PATCH_0, GIT_PATCH_1, GIT_PATCH_2, GIT_PATCH_3, KAM_LAZY_DOMAIN_SECURITY, RP_MATCHES_RCVD, SPF_HELO_PASS autolearn=ham version=3.3.2 spammy=ok, ultimately, arms X-HELO: mx1.redhat.com Received: from mx1.redhat.com (HELO mx1.redhat.com) (209.132.183.28) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Sat, 30 Sep 2017 09:09:44 +0000 Received: from smtp.corp.redhat.com (int-mx03.intmail.prod.int.phx2.redhat.com [10.5.11.13]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id C97D9C04AC41; Sat, 30 Sep 2017 09:09:42 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.3.2 mx1.redhat.com C97D9C04AC41 Authentication-Results: ext-mx07.extmail.prod.ext.phx2.redhat.com; dmarc=none (p=none dis=none) header.from=redhat.com Authentication-Results: ext-mx07.extmail.prod.ext.phx2.redhat.com; spf=fail smtp.mailfrom=aoliva@redhat.com Received: from freie.home (ovpn04.gateway.prod.ext.phx2.redhat.com [10.5.9.4]) by smtp.corp.redhat.com (Postfix) with ESMTPS id E90DF6062F; Sat, 30 Sep 2017 09:09:41 +0000 (UTC) Received: from frit.home (frit.home [172.31.160.7]) by freie.home (8.15.2/8.15.2) with ESMTP id v8U98pIV022010; Sat, 30 Sep 2017 06:09:17 -0300 From: Alexandre Oliva To: Richard Biener Cc: GCC Patches , Alexandre Oliva Subject: [PATCH 4/9] [SFN] introduce statement frontier notes, still disabled Date: Sat, 30 Sep 2017 06:08:22 -0300 Message-Id: <20170930090827.6604-4-aoliva@redhat.com> In-Reply-To: References: This patch completes the infrastructure for the introduction of statement frontiers in C-family languages. It brings in all the code remaining code needed to introduce and transform begin stmt trees, gimple stmts, insns and notes, and ultimately use them to generate the is_stmt column in DWARF2+ line number tables/programs, however none of it is activated: the option that would do so will be introduced in a subsequent patch. This patch depends on an earlier patch with not-quite-boilerplate changes towards SFN. for gcc/c-family/ChangeLog * c-semantics.c (pop_stmt_list): Move begin stmt marker into subsequent statement list. for gcc/c/ChangeLog * c-objc-common.h (LANG_HOOKS_EMITS_BEGIN_STMT): Redefine as true. * c-parser.c (add_debug_begin_stmt): New. (c_parser_declaration_or_fndef): Call it. (c_parser_compound_statement_nostart): Likewise. (c_parser_statement_after_labels): Likewise. * c-typeck (c_finish_stmt_expr): Skip begin stmts markers. for gcc/cp/ChangeLog * constexpr.c (build_data_member_initialization): Skip begin stmt markers. (check_constexpr_ctor_body_1): Likewise. (build_constexpr_constructor_member_initializers): Likewise. (constexpr_fn_retval): Likewise. (cxx_eval_statement_list): Likewise. (potential_constant_expression_1): Likewise. * cp-array-notation.c (stmt_location): New. (cp_expand_cond_array_notations): Use it. * cp-objcp-common.h (LANG_HOOKS_EMITS_BEGIN_STMT): Redefine as true. * parser.c (add_debug_begin_stmt): New. (cp_parser_statement): Call it. * pt.c (tsubst_copy): Handle begin stmt markers. for gcc/ChangeLog * cfgexpand.c (expand_gimple_basic_block): Handle begin stmt markers. Integrate source bind into debug stmt expand loop. (pass_expand::execute): Check debug marker limit. Avoid deep TER and expand debug locations for debug bind insns only. * cse.c (insn_live_p): Keep nonbind markers and debug bindings followed by them. * df-scan.c (df_insn_delete): Accept out-of-block debug insn. * final.c (reemit_insn_block_notes): Take current block from nonbind markers. Declare note where it's first set. (final_scan_insn): Handle begin stmt notes. Emit is_stmt according to begin stmt markers if enabled. (notice_source_line): Handle nonbind markers. Fail if their location is unknown or that of builtins. (rest_of_handle_final): Convert begin stmt markers to notes if var-tracking didn't run. (rest_of_clean_state): Skip begin stmt markers. * gimple-pretty-print.c (dump_gimple_debug): Handle begin stmt markers. * function.c (allocate_struct_function): Set begin_stmt_markers. * function.h (struct function): Add debug_marker_count counter and debug_nonbind_markers flag. * gimple-iterator.c (gsi_remove): Adjust debug_marker_count. * gimple-low.c (lower_function_body): Adjust debug_nonbind_markers. (lower_stmt): Drop or skip gimple debug stmts. (lower_try_catch): Skip debug stmts. * gimple.c (gimple_build_debug_begin_stmt): New. (gimple_copy): Increment debug_marker_count if copying one. * gimple.h (gimple_build_debug_begin_stmt): Declare. * gimplify.c (rexpr_location): New. (rexpr_has_location): New. (warn_switch_unreachable_r): Handle gimple debug stmts. (shortcut_cond_r): Call expr_location. (find_goto): New. (find_goto_label): New. (shortcut_cond_expr): Call expr_has_location, expr_location, and find_goto_label. (gimplify_cond_expr): Call find_goto_label, expr_has_location, and expr_location. (gimplify_expr): Handle begin stmt markers. Reject debug expr decls. * langhooks-def.h (LANG_HOOKS_EMITS_BEGIN_STMT): New. Add to... (LANG_HOOKS_INITIALIZER): ... this. * langhooks.h (struct lang_hooks): Add emits_begin_stmt. * lra-contraints.c (inherit_reload_reg): Tolerate between-blocks debug insns. (update_ebb_live_info): Skip debug insn markers. * lra.c (debug_insn_static_data): Rename to... (debug_bind_static_data): ... this. (debug_marker_static_data): New. (lra_set_insn_recog_data): Select one of the above depending on debug insn kind. (lra_update_isn_regno_info): Don't assume debug insns have freqs. (push_insns): Skip debug insns. * lto-streamer-in.c (input_function): Drop debug stmts depending on active options. Adjust debug_nonbind_markers. * params.def (PARAM_MAX_DEBUG_MARKER_COUNT): New. * print-rtl.c (rtx_writer::print_rtx_operand_code_0): Handle begin stmt marker notes. (print_insn): Likewise. * recog.c (extract_insn): Recognize rtl for debug markers. * rtl.def (DEBUG_MARKER): New. * tree-inline.c: Include params.h. (remap_gimple_stmt): Handle nonbind markers. (maybe_move_debug_stmts_to_successors): Likewise. (copy_debug_stmt): Likewise. * tree-iterator.c (append_to_statement_list_1): Append begin stmt markers regardless of no side effects. (tsi_link_before): Don't update container's side effects when adding a begin stmt marker. (tsi_link_after): Likewise. (expr_first): Skip begin stmt markers. (expr_last): Likewise. * tree-pretty-print (dump_generic_node): Handle begin stmt markers. * tree-ssa-threadedge.c (propagate_threaded_block_debug_info): Disregard nonbind markers. * tree.c (make_node_stat): Don't set side effects for begin stmt markers. (build1_stat): Likewise. * tree.def (DEBUG_BEGIN_STMT): New. * tree.h (GOTO_DESTINATION): Require a GOTO_EXPR. * var-tracking.c (delete_debug_insns): Renamed to... (delete_vta_debug_insns): ... this. (reemit_marker_as_note): New. (vt_initialize): Reemit markers. (delete_vta_debug_insns): Likewise. (vt_debug_insns_local): Reemit or delete markers. (variable_tracking_main_1): Likewise. * doc/generic.texi (DEBUG_BEGIN_STMT): Document. * doc/gimple.texi (gimple_debug_begin_stmt_p): New. (gimple_debug_nonbind_marker_p): New. (gimple_build_debug_bind): Adjust. (gimple_build_debug_begin_stmt): New. * doc/invoke.texi (max-debug-marker-count): New param. * doc/rtl.texi (debug_implicit_ptr, entry_value): New. (debug_parameter_ref, debug_marker): New. (NOTE_INSN_BEGIN_STMT): New. (DEBUG_INSN): Describe begin stmt markers. --- gcc/c-family/c-semantics.c | 21 ++++++ gcc/c/c-objc-common.h | 2 + gcc/c/c-parser.c | 20 ++++++ gcc/c/c-typeck.c | 8 ++- gcc/cfgexpand.c | 113 +++++++++++++++++--------------- gcc/cp/constexpr.c | 11 ++++ gcc/cp/cp-array-notation.c | 37 +++++++++-- gcc/cp/cp-objcp-common.h | 2 + gcc/cp/parser.c | 14 ++++ gcc/cp/pt.c | 6 ++ gcc/cse.c | 7 ++ gcc/df-scan.c | 2 +- gcc/doc/generic.texi | 5 ++ gcc/doc/gimple.texi | 24 ++++++- gcc/doc/invoke.texi | 7 ++ gcc/doc/rtl.texi | 53 ++++++++++++--- gcc/final.c | 89 +++++++++++++++++++------ gcc/function.c | 6 ++ gcc/function.h | 10 +++ gcc/gimple-iterator.c | 4 ++ gcc/gimple-low.c | 29 +++++++++ gcc/gimple-pretty-print.c | 7 ++ gcc/gimple.c | 24 +++++++ gcc/gimple.h | 1 + gcc/gimplify.c | 158 +++++++++++++++++++++++++++++++++++---------- gcc/langhooks-def.h | 2 + gcc/langhooks.h | 3 + gcc/lra-constraints.c | 10 ++- gcc/lra.c | 36 +++++++++-- gcc/lto-streamer-in.c | 12 +++- gcc/params.def | 9 +++ gcc/print-rtl.c | 24 +++++++ gcc/recog.c | 1 + gcc/rtl.def | 3 + gcc/tree-inline.c | 31 ++++++++- gcc/tree-iterator.c | 48 +++++++++++--- gcc/tree-pretty-print.c | 4 ++ gcc/tree-ssa-threadedge.c | 25 ++++--- gcc/tree.c | 8 ++- gcc/tree.def | 3 + gcc/tree.h | 2 +- gcc/var-tracking.c | 70 +++++++++++++++++--- 42 files changed, 793 insertions(+), 158 deletions(-) diff --git a/gcc/c-family/c-semantics.c b/gcc/c-family/c-semantics.c index 3ceb714..cd872d8 100644 --- a/gcc/c-family/c-semantics.c +++ b/gcc/c-family/c-semantics.c @@ -76,6 +76,27 @@ pop_stmt_list (tree t) free_stmt_list (t); t = u; } + /* If the statement list contained a debug begin stmt and a + statement list, move the debug begin stmt into the statement + list and return it. */ + else if (!tsi_end_p (i) + && TREE_CODE (tsi_stmt (i)) == DEBUG_BEGIN_STMT) + { + u = tsi_stmt (i); + tsi_next (&i); + if (tsi_one_before_end_p (i) + && TREE_CODE (tsi_stmt (i)) == STATEMENT_LIST) + { + tree l = tsi_stmt (i); + tsi_prev (&i); + tsi_delink (&i); + tsi_delink (&i); + i = tsi_start (l); + free_stmt_list (t); + t = l; + tsi_link_before (&i, u, TSI_SAME_STMT); + } + } } return t; diff --git a/gcc/c/c-objc-common.h b/gcc/c/c-objc-common.h index bee06e9..27ceabc 100644 --- a/gcc/c/c-objc-common.h +++ b/gcc/c/c-objc-common.h @@ -60,6 +60,8 @@ along with GCC; see the file COPYING3. If not see #define LANG_HOOKS_BUILTIN_FUNCTION c_builtin_function #undef LANG_HOOKS_BUILTIN_FUNCTION_EXT_SCOPE #define LANG_HOOKS_BUILTIN_FUNCTION_EXT_SCOPE c_builtin_function_ext_scope +#undef LANG_HOOKS_EMITS_BEGIN_STMT +#define LANG_HOOKS_EMITS_BEGIN_STMT true /* Attribute hooks. */ #undef LANG_HOOKS_COMMON_ATTRIBUTE_TABLE diff --git a/gcc/c/c-parser.c b/gcc/c/c-parser.c index a36397b..aa70c91 100644 --- a/gcc/c/c-parser.c +++ b/gcc/c/c-parser.c @@ -1640,6 +1640,19 @@ c_parser_external_declaration (c_parser *parser) static void c_finish_omp_declare_simd (c_parser *, tree, tree, vec); static void c_finish_oacc_routine (struct oacc_routine_data *, tree, bool); +/* Build and add a DEBUG_BEGIN_STMT statement with location LOC. */ + +static void +add_debug_begin_stmt (location_t loc) +{ + if (!MAY_HAVE_DEBUG_MARKER_STMTS) + return; + + tree stmt = build0 (DEBUG_BEGIN_STMT, void_type_node); + SET_EXPR_LOCATION (stmt, loc); + add_stmt (stmt); +} + /* Parse a declaration or function definition (C90 6.5, 6.7.1, C99 6.7, 6.9.1, C11 6.7, 6.9.1). If FNDEF_OK is true, a function definition is accepted; otherwise (old-style parameter declarations) only other @@ -1740,6 +1753,8 @@ c_parser_declaration_or_fndef (c_parser *parser, bool fndef_ok, bool diagnosed_no_specs = false; location_t here = c_parser_peek_token (parser)->location; + add_debug_begin_stmt (c_parser_peek_token (parser)->location); + if (static_assert_ok && c_parser_next_token_is_keyword (parser, RID_STATIC_ASSERT)) { @@ -4949,6 +4964,7 @@ c_parser_compound_statement_nostart (c_parser *parser) location_t label_loc = UNKNOWN_LOCATION; /* Quiet warning. */ if (c_parser_next_token_is (parser, CPP_CLOSE_BRACE)) { + add_debug_begin_stmt (c_parser_peek_token (parser)->location); c_parser_consume_token (parser); return; } @@ -5403,6 +5419,10 @@ c_parser_statement_after_labels (c_parser *parser, bool *if_p, parser->in_if_block = false; if (if_p != NULL) *if_p = false; + + if (c_parser_peek_token (parser)->type != CPP_OPEN_BRACE) + add_debug_begin_stmt (loc); + switch (c_parser_peek_token (parser)->type) { case CPP_OPEN_BRACE: diff --git a/gcc/c/c-typeck.c b/gcc/c/c-typeck.c index 73e7460..33bd4b8 100644 --- a/gcc/c/c-typeck.c +++ b/gcc/c/c-typeck.c @@ -10740,6 +10740,10 @@ c_finish_stmt_expr (location_t loc, tree body) } else i = tsi_last (last); + if (TREE_CODE (tsi_stmt (i)) == DEBUG_BEGIN_STMT) + do + tsi_prev (&i); + while (TREE_CODE (tsi_stmt (i)) == DEBUG_BEGIN_STMT); last_p = tsi_stmt_ptr (i); last = *last_p; } @@ -10759,7 +10763,9 @@ c_finish_stmt_expr (location_t loc, tree body) /* In the case that the BIND_EXPR is not necessary, return the expression out from inside it. */ - if (last == BIND_EXPR_BODY (body) + if ((last == BIND_EXPR_BODY (body) + /* Skip nested debug stmts. */ + || last == expr_first (BIND_EXPR_BODY (body))) && BIND_EXPR_VARS (body) == NULL) { /* Even if this looks constant, do not allow it in a constant diff --git a/gcc/cfgexpand.c b/gcc/cfgexpand.c index 5a46b5e..c854ffd 100644 --- a/gcc/cfgexpand.c +++ b/gcc/cfgexpand.c @@ -5635,39 +5635,68 @@ expand_gimple_basic_block (basic_block bb, bool disable_tail_calls) if (new_bb) return new_bb; } - else if (gimple_debug_bind_p (stmt)) + else if (is_gimple_debug (stmt)) { location_t sloc = curr_insn_location (); gimple_stmt_iterator nsi = gsi; for (;;) { - tree var = gimple_debug_bind_get_var (stmt); - tree value; - rtx val; + tree var; + tree value = NULL_TREE; + rtx val = NULL_RTX; machine_mode mode; - if (TREE_CODE (var) != DEBUG_EXPR_DECL - && TREE_CODE (var) != LABEL_DECL - && !target_for_debug_bind (var)) - goto delink_debug_stmt; + if (!gimple_debug_nonbind_marker_p (stmt)) + { + if (gimple_debug_bind_p (stmt)) + { + var = gimple_debug_bind_get_var (stmt); - if (gimple_debug_bind_has_value_p (stmt)) - value = gimple_debug_bind_get_value (stmt); - else - value = NULL_TREE; + if (TREE_CODE (var) != DEBUG_EXPR_DECL + && TREE_CODE (var) != LABEL_DECL + && !target_for_debug_bind (var)) + goto delink_debug_stmt; - last = get_last_insn (); + if (DECL_P (var)) + mode = DECL_MODE (var); + else + mode = TYPE_MODE (TREE_TYPE (var)); - set_curr_insn_location (gimple_location (stmt)); + if (gimple_debug_bind_has_value_p (stmt)) + value = gimple_debug_bind_get_value (stmt); + + val = gen_rtx_VAR_LOCATION + (mode, var, (rtx)value, VAR_INIT_STATUS_INITIALIZED); + } + else if (gimple_debug_source_bind_p (stmt)) + { + var = gimple_debug_source_bind_get_var (stmt); + + value = gimple_debug_source_bind_get_value (stmt); + + mode = DECL_MODE (var); - if (DECL_P (var)) - mode = DECL_MODE (var); + val = gen_rtx_VAR_LOCATION (mode, var, (rtx)value, + VAR_INIT_STATUS_UNINITIALIZED); + } + else + gcc_unreachable (); + } + /* If this function was first compiled with markers + enabled, but they're now disable (e.g. LTO), drop + them on the floor. */ + else if (gimple_debug_nonbind_marker_p (stmt) + && !MAY_HAVE_DEBUG_MARKER_INSNS) + goto delink_debug_stmt; + else if (gimple_debug_begin_stmt_p (stmt)) + val = gen_rtx_DEBUG_MARKER (VOIDmode); else - mode = TYPE_MODE (TREE_TYPE (var)); + gcc_unreachable (); - val = gen_rtx_VAR_LOCATION - (mode, var, (rtx)value, VAR_INIT_STATUS_INITIALIZED); + last = get_last_insn (); + + set_curr_insn_location (gimple_location (stmt)); emit_debug_insn (val); @@ -5675,9 +5704,14 @@ expand_gimple_basic_block (basic_block bb, bool disable_tail_calls) { /* We can't dump the insn with a TREE where an RTX is expected. */ - PAT_VAR_LOCATION_LOC (val) = const0_rtx; + if (GET_CODE (val) == VAR_LOCATION) + { + gcc_checking_assert (PAT_VAR_LOCATION_LOC (val) == (rtx)value); + PAT_VAR_LOCATION_LOC (val) = const0_rtx; + } maybe_dump_rtl_for_gimple_stmt (stmt, last); - PAT_VAR_LOCATION_LOC (val) = (rtx)value; + if (GET_CODE (val) == VAR_LOCATION) + PAT_VAR_LOCATION_LOC (val) = (rtx)value; } delink_debug_stmt: @@ -5693,42 +5727,12 @@ expand_gimple_basic_block (basic_block bb, bool disable_tail_calls) if (gsi_end_p (nsi)) break; stmt = gsi_stmt (nsi); - if (!gimple_debug_bind_p (stmt)) + if (!is_gimple_debug (stmt)) break; } set_curr_insn_location (sloc); } - else if (gimple_debug_source_bind_p (stmt)) - { - location_t sloc = curr_insn_location (); - tree var = gimple_debug_source_bind_get_var (stmt); - tree value = gimple_debug_source_bind_get_value (stmt); - rtx val; - machine_mode mode; - - last = get_last_insn (); - - set_curr_insn_location (gimple_location (stmt)); - - mode = DECL_MODE (var); - - val = gen_rtx_VAR_LOCATION (mode, var, (rtx)value, - VAR_INIT_STATUS_UNINITIALIZED); - - emit_debug_insn (val); - - if (dump_file && (dump_flags & TDF_DETAILS)) - { - /* We can't dump the insn with a TREE where an RTX - is expected. */ - PAT_VAR_LOCATION_LOC (val) = const0_rtx; - maybe_dump_rtl_for_gimple_stmt (stmt, last); - PAT_VAR_LOCATION_LOC (val) = (rtx)value; - } - - set_curr_insn_location (sloc); - } else { gcall *call_stmt = dyn_cast (stmt); @@ -6367,6 +6371,11 @@ pass_expand::execute (function *fun) FOR_EACH_EDGE (e, ei, ENTRY_BLOCK_PTR_FOR_FN (fun)->succs) e->flags &= ~EDGE_EXECUTABLE; + /* If the function has too many markers, drop them while expanding. */ + if (cfun->debug_marker_count + >= PARAM_VALUE (PARAM_MAX_DEBUG_MARKER_COUNT)) + cfun->debug_nonbind_markers = false; + lab_rtx_for_bb = new hash_map; FOR_BB_BETWEEN (bb, init_block->next_bb, EXIT_BLOCK_PTR_FOR_FN (fun), next_bb) diff --git a/gcc/cp/constexpr.c b/gcc/cp/constexpr.c index a89ee49..f9209ac 100644 --- a/gcc/cp/constexpr.c +++ b/gcc/cp/constexpr.c @@ -306,6 +306,9 @@ build_data_member_initialization (tree t, vec **vec) tree_stmt_iterator i; for (i = tsi_start (t); !tsi_end_p (i); tsi_next (&i)) { + if (TREE_CODE (tsi_stmt (i)) == DEBUG_BEGIN_STMT) + /* ??? Can we retain this information somehow? */ + continue; if (! build_data_member_initialization (tsi_stmt (i), vec)) return false; } @@ -448,6 +451,7 @@ check_constexpr_ctor_body_1 (tree last, tree list) case USING_STMT: case STATIC_ASSERT: + case DEBUG_BEGIN_STMT: return true; default: @@ -586,6 +590,9 @@ build_constexpr_constructor_member_initializers (tree type, tree body) tree_stmt_iterator i; for (i = tsi_start (body); !tsi_end_p (i); tsi_next (&i)) { + if (TREE_CODE (tsi_stmt (i)) == DEBUG_BEGIN_STMT) + /* ??? Can we retain this information somehow? */ + continue; ok = build_data_member_initialization (tsi_stmt (i), &vec); if (!ok) break; @@ -673,6 +680,7 @@ constexpr_fn_retval (tree body) return constexpr_fn_retval (BIND_EXPR_BODY (body)); case USING_STMT: + case DEBUG_BEGIN_STMT: return NULL_TREE; default: @@ -3783,6 +3791,8 @@ cxx_eval_statement_list (const constexpr_ctx *ctx, tree t, for (i = tsi_start (t); !tsi_end_p (i); tsi_next (&i)) { tree stmt = tsi_stmt (i); + if (TREE_CODE (stmt) == DEBUG_BEGIN_STMT) + continue; r = cxx_eval_constant_expression (ctx, stmt, false, non_constant_p, overflow_p, jump_target); @@ -5119,6 +5129,7 @@ potential_constant_expression_1 (tree t, bool want_rval, bool strict, bool now, case CONTINUE_STMT: case REQUIRES_EXPR: case STATIC_ASSERT: + case DEBUG_BEGIN_STMT: return true; case PARM_DECL: diff --git a/gcc/cp/cp-array-notation.c b/gcc/cp/cp-array-notation.c index 31be7d6..17f0b35c 100644 --- a/gcc/cp/cp-array-notation.c +++ b/gcc/cp/cp-array-notation.c @@ -780,6 +780,31 @@ error: return error_mark_node; } +/* Return a location associated with stmt. If it is an expresion, + that's the expression's location. If it is a STATEMENT_LIST, + instead of no location, use expr_first to skip any debug stmts and + take the location of the first nondebug stmt found. */ + +static location_t +stmt_location (tree stmt) +{ + location_t loc = UNKNOWN_LOCATION; + + if (!stmt) + return loc; + + loc = EXPR_LOCATION (stmt); + + if (loc != UNKNOWN_LOCATION || TREE_CODE (stmt) != STATEMENT_LIST) + return loc; + + stmt = expr_first (stmt); + if (stmt) + loc = EXPR_LOCATION (stmt); + + return loc; +} + /* Helper function for expand_conditonal_array_notations. Encloses the conditional statement passed in ORIG_STMT with a loop around it and replaces the condition in STMT with a ARRAY_REF tree-node to the array. @@ -835,10 +860,12 @@ cp_expand_cond_array_notations (tree orig_stmt) tree cond = IF_COND (orig_stmt); if (!find_rank (EXPR_LOCATION (cond), cond, cond, true, &cond_rank) || (yes_expr - && !find_rank (EXPR_LOCATION (yes_expr), yes_expr, yes_expr, true, + && !find_rank (stmt_location (yes_expr), + yes_expr, yes_expr, true, &yes_rank)) || (no_expr - && !find_rank (EXPR_LOCATION (no_expr), no_expr, no_expr, true, + && !find_rank (stmt_location (no_expr), + no_expr, no_expr, true, &no_rank))) return error_mark_node; @@ -847,13 +874,15 @@ cp_expand_cond_array_notations (tree orig_stmt) return orig_stmt; else if (cond_rank != yes_rank && yes_rank != 0) { - error_at (EXPR_LOCATION (yes_expr), "rank mismatch with controlling" + error_at (stmt_location (yes_expr), + "rank mismatch with controlling" " expression of parent if-statement"); return error_mark_node; } else if (cond_rank != no_rank && no_rank != 0) { - error_at (EXPR_LOCATION (no_expr), "rank mismatch with controlling " + error_at (stmt_location (no_expr), + "rank mismatch with controlling " "expression of parent if-statement"); return error_mark_node; } diff --git a/gcc/cp/cp-objcp-common.h b/gcc/cp/cp-objcp-common.h index 3e4cc9c5..c1c82b6 100644 --- a/gcc/cp/cp-objcp-common.h +++ b/gcc/cp/cp-objcp-common.h @@ -105,6 +105,8 @@ extern void cp_register_dumps (gcc::dump_manager *); #define LANG_HOOKS_MISSING_NORETURN_OK_P cp_missing_noreturn_ok_p #undef LANG_HOOKS_BLOCK_MAY_FALLTHRU #define LANG_HOOKS_BLOCK_MAY_FALLTHRU cxx_block_may_fallthru +#undef LANG_HOOKS_EMITS_BEGIN_STMT +#define LANG_HOOKS_EMITS_BEGIN_STMT true /* Attribute hooks. */ #undef LANG_HOOKS_COMMON_ATTRIBUTE_TABLE diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c index 6e817cb..1b31182 100644 --- a/gcc/cp/parser.c +++ b/gcc/cp/parser.c @@ -10661,6 +10661,19 @@ cp_parser_lambda_body (cp_parser* parser, tree lambda_expr) /* Statements [gram.stmt.stmt] */ +/* Build and add a DEBUG_BEGIN_STMT statement with location LOC. */ + +static void +add_debug_begin_stmt (location_t loc) +{ + if (!MAY_HAVE_DEBUG_MARKER_STMTS) + return; + + tree stmt = build0 (DEBUG_BEGIN_STMT, void_type_node); + SET_EXPR_LOCATION (stmt, loc); + add_stmt (stmt); +} + /* Parse a statement. statement: @@ -10736,6 +10749,7 @@ cp_parser_statement (cp_parser* parser, tree in_statement_expr, token = cp_lexer_peek_token (parser->lexer); /* Remember the location of the first token in the statement. */ statement_location = token->location; + add_debug_begin_stmt (statement_location); /* If this is a keyword, then that will often determine what kind of statement we have. */ if (token->type == CPP_KEYWORD) diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c index c29c779..4714b53 100644 --- a/gcc/cp/pt.c +++ b/gcc/cp/pt.c @@ -15289,6 +15289,12 @@ tsubst_copy (tree t, tree args, tsubst_flags_t complain, tree in_decl) case PREDICT_EXPR: return t; + case DEBUG_BEGIN_STMT: + /* ??? There's no point in copying it for now, but maybe some + day it will contain more information, such as a pointer back + to the containing function, inlined copy or so. */ + return t; + default: /* We shouldn't get here, but keep going if !flag_checking. */ if (flag_checking) diff --git a/gcc/cse.c b/gcc/cse.c index d1577a6..bb9b317 100644 --- a/gcc/cse.c +++ b/gcc/cse.c @@ -6967,11 +6967,18 @@ insn_live_p (rtx_insn *insn, int *counts) { rtx_insn *next; + if (DEBUG_MARKER_INSN_P (insn)) + return true; + for (next = NEXT_INSN (insn); next; next = NEXT_INSN (next)) if (NOTE_P (next)) continue; else if (!DEBUG_INSN_P (next)) return true; + /* If we find an inspection point, such as a debug begin stmt, + we want to keep the earlier debug insn. */ + else if (DEBUG_MARKER_INSN_P (next)) + return true; else if (INSN_VAR_LOCATION_DECL (insn) == INSN_VAR_LOCATION_DECL (next)) return false; diff --git a/gcc/df-scan.c b/gcc/df-scan.c index 8ab3d71..429dab8 100644 --- a/gcc/df-scan.c +++ b/gcc/df-scan.c @@ -945,7 +945,7 @@ df_insn_delete (rtx_insn *insn) In any case, we expect BB to be non-NULL at least up to register allocation, so disallow a non-NULL BB up to there. Not perfect but better than nothing... */ - gcc_checking_assert (bb != NULL || reload_completed); + gcc_checking_assert (bb != NULL || DEBUG_INSN_P (insn) || reload_completed); df_grow_bb_info (df_scan); df_grow_reg_info (); diff --git a/gcc/doc/generic.texi b/gcc/doc/generic.texi index a51cfd6e..a13bce9 100644 --- a/gcc/doc/generic.texi +++ b/gcc/doc/generic.texi @@ -1930,6 +1930,11 @@ case 2 ... 5: The first value will be @code{CASE_LOW}, while the second will be @code{CASE_HIGH}. +@item DEBUG_BEGIN_STMT + +Marks the beginning of a source statement, for purposes of debug +information generation. + @end table diff --git a/gcc/doc/gimple.texi b/gcc/doc/gimple.texi index 635abd39..6c9c4789 100644 --- a/gcc/doc/gimple.texi +++ b/gcc/doc/gimple.texi @@ -831,6 +831,16 @@ expression to a variable. Return true if g is any of the OpenMP codes. @end deftypefn +@deftypefn {GIMPLE function} gimple_debug_begin_stmt_p (gimple g) +Return true if g is a @code{GIMPLE_DEBUG} that marks the beginning of +a source statement. +@end deftypefn + +@deftypefn {GIMPLE function} gimple_debug_nonbind_marker_p (gimple g) +Return true if g is a @code{GIMPLE_DEBUG} that marks a program location, +without any variable binding. +@end deftypefn + @node Manipulating GIMPLE statements @section Manipulating GIMPLE statements @cindex Manipulating GIMPLE statements @@ -1528,10 +1538,11 @@ Set the conditional @code{COND_STMT} to be of the form 'if (1 == 1)'. @subsection @code{GIMPLE_DEBUG} @cindex @code{GIMPLE_DEBUG} @cindex @code{GIMPLE_DEBUG_BIND} +@cindex @code{GIMPLE_DEBUG_BEGIN_STMT} @deftypefn {GIMPLE function} gdebug *gimple_build_debug_bind (tree var, @ tree value, gimple stmt) -Build a @code{GIMPLE_DEBUG} statement with @code{GIMPLE_DEBUG_BIND} of +Build a @code{GIMPLE_DEBUG} statement with @code{GIMPLE_DEBUG_BIND} @code{subcode}. The effect of this statement is to tell debug information generation machinery that the value of user variable @code{var} is given by @code{value} at that point, and to remain with @@ -1602,6 +1613,17 @@ Return @code{TRUE} if @code{stmt} binds a user variable to a value, and @code{FALSE} if it unbinds the variable. @end deftypefn +@deftypefn {GIMPLE function} gimple gimple_build_debug_begin_stmt (tree block, location_t location) +Build a @code{GIMPLE_DEBUG} statement with +@code{GIMPLE_DEBUG_BEGIN_STMT} @code{subcode}. The effect of this +statement is to tell debug information generation machinery that the +user statement at the given @code{location} and @code{block} starts at +the point at which the statement is inserted. The intent is that side +effects (e.g. variable bindings) of all prior user statements are +observable, and that none of the side effects of subsequent user +statements are. +@end deftypefn + @node @code{GIMPLE_EH_FILTER} @subsection @code{GIMPLE_EH_FILTER} @cindex @code{GIMPLE_EH_FILTER} diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi index f862b7f..108d730 100644 --- a/gcc/doc/invoke.texi +++ b/gcc/doc/invoke.texi @@ -10480,6 +10480,13 @@ debug information may end up not being used; setting this higher may enable the compiler to find more complex debug expressions, but compile time and memory use may grow. The default is 12. +@item max-debug-marker-count +Sets a threshold on the number of debug markers (e.g. begin stmt +markers) to avoid complexity explosion at inlining or expanding to RTL. +If a function has more such gimple stmts than the set limit, such stmts +will be dropped from the inlined copy of a function, and from its RTL +expansion. The default is 100000. + @item min-nondebug-insn-uid Use uids starting at this parameter for nondebug insns. The range below the parameter is reserved exclusively for debug insns created by diff --git a/gcc/doc/rtl.texi b/gcc/doc/rtl.texi index 3b2b247..888ab02 100644 --- a/gcc/doc/rtl.texi +++ b/gcc/doc/rtl.texi @@ -3413,6 +3413,25 @@ Stands for the value bound to the @code{DEBUG_EXPR_DECL} @var{decl}, that points back to it, within value expressions in @code{VAR_LOCATION} nodes. +@findex debug_implicit_ptr +@item (debug_implicit_ptr:@var{mode} @var{decl}) +Stands for the location of a @var{decl} that is no longer addressable. + +@findex entry_value +@item (entry_value:@var{mode} @var{decl}) +Stands for the value a @var{decl} had at the entry point of the +containing function. + +@findex debug_parameter_ref +@item (debug_parameter_ref:@var{mode} @var{decl}) +Refers to a parameter that was completely optimized out. + +@findex debug_marker +@item (debug_marker:@var{mode}) +Marks a program location. With @code{VOIDmode}, it stands for the +beginning of a statement, a recommended inspection point logically after +all prior side effects, and before any subsequent side effects. + @end table @node Insns @@ -3689,6 +3708,12 @@ can be computed by evaluating the RTL expression from that static point in the program up to the next such note for the same user variable. +@findex NOTE_INSN_BEGIN_STMT +@item NOTE_INSN_BEGIN_STMT +This note is used to generate @code{is_stmt} markers in line number +debuggign information. It indicates the beginning of a user +statement. + @end table These codes are printed symbolically when they appear in debugging dumps. @@ -3706,15 +3731,25 @@ binds a user variable tree to an RTL representation of the it stands for the value bound to the corresponding @code{DEBUG_EXPR_DECL}. -Throughout optimization passes, binding information is kept in -pseudo-instruction form, so that, unlike notes, it gets the same -treatment and adjustments that regular instructions would. It is the -variable tracking pass that turns these pseudo-instructions into var -location notes, analyzing control flow, value equivalences and changes -to registers and memory referenced in value expressions, propagating -the values of debug temporaries and determining expressions that can -be used to compute the value of each user variable at as many points -(ranges, actually) in the program as possible. +@code{GIMPLE_DEBUG_BEGIN_STMT} is expanded to RTL as a @code{DEBUG_INSN} +with a @code{VOIDmode} @code{DEBUG_MARKER} @code{PATTERN}. These +@code{DEBUG_INSN}s, that do not carry @code{VAR_LOCATION} information, +just @code{DEBUG_MARKER}s, can be detected by testing +@code{DEBUG_MARKER_INSN_P}, whereas those that do can be recognized as +@code{DEBUG_BIND_INSN_P}. + +Throughout optimization passes, @code{DEBUG_INSN}s are not reordered +with respect to each other, particularly during scheduling. Binding +information is kept in pseudo-instruction form, so that, unlike notes, +it gets the same treatment and adjustments that regular instructions +would. It is the variable tracking pass that turns these +pseudo-instructions into @code{NOTE_INSN_VAR_LOCATION} and +@code{NOTE_INSN_BEGIN_STMT} notes, +analyzing control flow, value equivalences and changes to registers and +memory referenced in value expressions, propagating the values of debug +temporaries and determining expressions that can be used to compute the +value of each user variable at as many points (ranges, actually) in the +program as possible. Unlike @code{NOTE_INSN_VAR_LOCATION}, the value expression in an @code{INSN_VAR_LOCATION} denotes a value at that specific point in the diff --git a/gcc/final.c b/gcc/final.c index eff2ee6..49cfbfb 100644 --- a/gcc/final.c +++ b/gcc/final.c @@ -1646,7 +1646,6 @@ reemit_insn_block_notes (void) { tree cur_block = DECL_INITIAL (cfun->decl); rtx_insn *insn; - rtx_note *note; insn = get_insns (); for (; insn; insn = NEXT_INSN (insn)) @@ -1654,17 +1653,29 @@ reemit_insn_block_notes (void) tree this_block; /* Prevent lexical blocks from straddling section boundaries. */ - if (NOTE_P (insn) && NOTE_KIND (insn) == NOTE_INSN_SWITCH_TEXT_SECTIONS) - { - for (tree s = cur_block; s != DECL_INITIAL (cfun->decl); - s = BLOCK_SUPERCONTEXT (s)) - { - rtx_note *note = emit_note_before (NOTE_INSN_BLOCK_END, insn); - NOTE_BLOCK (note) = s; - note = emit_note_after (NOTE_INSN_BLOCK_BEG, insn); - NOTE_BLOCK (note) = s; - } - } + if (NOTE_P (insn)) + switch (NOTE_KIND (insn)) + { + case NOTE_INSN_SWITCH_TEXT_SECTIONS: + { + for (tree s = cur_block; s != DECL_INITIAL (cfun->decl); + s = BLOCK_SUPERCONTEXT (s)) + { + rtx_note *note = emit_note_before (NOTE_INSN_BLOCK_END, insn); + NOTE_BLOCK (note) = s; + note = emit_note_after (NOTE_INSN_BLOCK_BEG, insn); + NOTE_BLOCK (note) = s; + } + } + break; + + case NOTE_INSN_BEGIN_STMT: + this_block = LOCATION_BLOCK (NOTE_MARKER_LOCATION (insn)); + goto set_cur_block_to_this_block; + + default: + continue; + } if (!active_insn_p (insn)) continue; @@ -1685,6 +1696,7 @@ reemit_insn_block_notes (void) this_block = choose_inner_scope (this_block, insn_scope (body->insn (i))); } + set_cur_block_to_this_block: if (! this_block) { if (INSN_LOCATION (insn) == UNKNOWN_LOCATION) @@ -1701,7 +1713,7 @@ reemit_insn_block_notes (void) } /* change_scope emits before the insn, not after. */ - note = emit_note (NOTE_INSN_DELETED); + rtx_note *note = emit_note (NOTE_INSN_DELETED); change_scope (note, cur_block, DECL_INITIAL (cfun->decl)); delete_insn (note); @@ -2404,6 +2416,17 @@ final_scan_insn (rtx_insn *insn, FILE *file, int optimize_p ATTRIBUTE_UNUSED, debug_hooks->var_location (insn); break; + case NOTE_INSN_BEGIN_STMT: + gcc_checking_assert (cfun->debug_nonbind_markers); + if (!DECL_IGNORED_P (current_function_decl) + && notice_source_line (insn, NULL)) + { + (*debug_hooks->source_line) (last_linenum, last_columnnum, + last_filename, last_discriminator, + true); + } + break; + default: gcc_unreachable (); break; @@ -2490,7 +2513,15 @@ final_scan_insn (rtx_insn *insn, FILE *file, int optimize_p ATTRIBUTE_UNUSED, rtx body = PATTERN (insn); int insn_code_number; const char *templ; - bool is_stmt; + bool is_stmt, *is_stmt_p; + + if (MAY_HAVE_DEBUG_MARKER_INSNS && cfun->debug_nonbind_markers) + { + is_stmt = false; + is_stmt_p = NULL; + } + else + is_stmt_p = &is_stmt; /* Reset this early so it is correct for ASM statements. */ current_insn_predicate = NULL_RTX; @@ -2593,7 +2624,7 @@ final_scan_insn (rtx_insn *insn, FILE *file, int optimize_p ATTRIBUTE_UNUSED, /* Output this line note if it is the first or the last line note in a row. */ if (!DECL_IGNORED_P (current_function_decl) - && notice_source_line (insn, &is_stmt)) + && notice_source_line (insn, is_stmt_p)) { if (flag_verbose_asm) asm_show_source (last_filename, last_linenum); @@ -3086,7 +3117,22 @@ notice_source_line (rtx_insn *insn, bool *is_stmt) const char *filename; int linenum, columnnum; - if (override_filename) + if (NOTE_MARKER_P (insn)) + { + location_t loc = NOTE_MARKER_LOCATION (insn); + expanded_location xloc = expand_location (loc); + if (xloc.line == 0) + { + gcc_checking_assert (LOCATION_LOCUS (loc) == UNKNOWN_LOCATION + || LOCATION_LOCUS (loc) == BUILTINS_LOCATION); + return false; + } + filename = xloc.file; + linenum = xloc.line; + columnnum = xloc.column; + force_source_line = true; + } + else if (override_filename) { filename = override_filename; linenum = override_linenum; @@ -3119,7 +3165,8 @@ notice_source_line (rtx_insn *insn, bool *is_stmt) last_linenum = linenum; last_columnnum = columnnum; last_discriminator = discriminator; - *is_stmt = true; + if (is_stmt) + *is_stmt = true; high_block_linenum = MAX (last_linenum, high_block_linenum); high_function_linenum = MAX (last_linenum, high_function_linenum); return true; @@ -3131,7 +3178,8 @@ notice_source_line (rtx_insn *insn, bool *is_stmt) output the line table entry with is_stmt false so the debugger does not treat this as a breakpoint location. */ last_discriminator = discriminator; - *is_stmt = false; + if (is_stmt) + *is_stmt = false; return true; } @@ -4483,6 +4531,10 @@ rest_of_handle_final (void) { const char *fnname = get_fnname_from_decl (current_function_decl); + /* Turn debug markers into notes. */ + if (!MAY_HAVE_DEBUG_BIND_INSNS && MAY_HAVE_DEBUG_MARKER_INSNS) + variable_tracking_main (); + assemble_start_function (current_function_decl, fnname); final_start_function (get_insns (), asm_out_file, optimize); final (get_insns (), asm_out_file, optimize); @@ -4670,6 +4722,7 @@ rest_of_clean_state (void) if (final_output && (!NOTE_P (insn) || (NOTE_KIND (insn) != NOTE_INSN_VAR_LOCATION + && NOTE_KIND (insn) != NOTE_INSN_BEGIN_STMT && NOTE_KIND (insn) != NOTE_INSN_CALL_ARG_LOCATION && NOTE_KIND (insn) != NOTE_INSN_BLOCK_BEG && NOTE_KIND (insn) != NOTE_INSN_BLOCK_END diff --git a/gcc/function.c b/gcc/function.c index ae61d3d..468dc9a 100644 --- a/gcc/function.c +++ b/gcc/function.c @@ -4933,6 +4933,12 @@ allocate_struct_function (tree fndecl, bool abstract_p) if (!profile_flag && !flag_instrument_function_entry_exit) DECL_NO_INSTRUMENT_FUNCTION_ENTRY_EXIT (fndecl) = 1; } + + /* Don't enable begin stmt markers if var-tracking at assignments is + disabled. The markers make little sense without the variable + binding annotations among them. */ + cfun->debug_nonbind_markers = lang_hooks.emits_begin_stmt + && MAY_HAVE_DEBUG_MARKER_STMTS; } /* This is like allocate_struct_function, but pushes a new cfun for FNDECL diff --git a/gcc/function.h b/gcc/function.h index 76434cd..1186116 100644 --- a/gcc/function.h +++ b/gcc/function.h @@ -284,6 +284,12 @@ struct GTY(()) function { /* Last statement uid. */ int last_stmt_uid; + /* Debug marker counter. Count begin stmt markers. We don't have + to keep it exact, it's more of a rough estimate to enable us to + decide whether they are too many to copy during inlining, or when + expanding to RTL. */ + int debug_marker_count; + /* Function sequence number for profiling, debugging, etc. */ int funcdef_no; @@ -387,6 +393,10 @@ struct GTY(()) function { /* Set when the tail call has been identified. */ unsigned int tail_call_marked : 1; + + /* Set when the function was compiled with generation of debug + (begin stmt, inline entry, ...) markers enabled. */ + unsigned int debug_nonbind_markers : 1; }; /* Add the decl D to the local_decls list of FUN. */ diff --git a/gcc/gimple-iterator.c b/gcc/gimple-iterator.c index fb75f99..2359760 100644 --- a/gcc/gimple-iterator.c +++ b/gcc/gimple-iterator.c @@ -573,6 +573,10 @@ gsi_remove (gimple_stmt_iterator *i, bool remove_permanently) if (remove_permanently) { + if (gimple_debug_nonbind_marker_p (stmt)) + /* We don't need this to be exact, but try to keep it at least + close. */ + cfun->debug_marker_count--; require_eh_edge_purge = remove_stmt_from_eh_lp (stmt); gimple_remove_stmt_histograms (cfun, stmt); } diff --git a/gcc/gimple-low.c b/gcc/gimple-low.c index 22db61b..95f3f45 100644 --- a/gcc/gimple-low.c +++ b/gcc/gimple-low.c @@ -110,6 +110,17 @@ lower_function_body (void) i = gsi_last (lowered_body); + /* If we had begin stmt markers from e.g. PCH, but this compilation + doesn't want them, lower_stmt will have cleaned them up; we can + now clear the flag that indicates we had them. */ + if (!MAY_HAVE_DEBUG_MARKER_STMTS && cfun->debug_nonbind_markers) + { + /* This counter needs not be exact, but before lowering it will + most certainly be. */ + gcc_assert (cfun->debug_marker_count == 0); + cfun->debug_nonbind_markers = false; + } + /* If the function falls off the end, we need a null return statement. If we've already got one in the return_statements vector, we don't need to do anything special. Otherwise build one by hand. */ @@ -296,6 +307,20 @@ lower_stmt (gimple_stmt_iterator *gsi, struct lower_data *data) } break; + case GIMPLE_DEBUG: + gcc_checking_assert (cfun->debug_nonbind_markers); + /* We can't possibly have debug bind stmts before lowering, we + first emit them when entering SSA. */ + gcc_checking_assert (gimple_debug_nonbind_marker_p (stmt)); + /* Propagate fallthruness. */ + /* If the function (e.g. from PCH) had debug stmts, but they're + disabled for this compilation, remove them. */ + if (!MAY_HAVE_DEBUG_MARKER_STMTS) + gsi_remove (gsi, true); + else + gsi_next (gsi); + return; + case GIMPLE_NOP: case GIMPLE_ASM: case GIMPLE_ASSIGN: @@ -503,6 +528,10 @@ lower_try_catch (gimple_stmt_iterator *gsi, struct lower_data *data) cannot_fallthru = false; break; + case GIMPLE_DEBUG: + gcc_checking_assert (gimple_debug_begin_stmt_p (stmt)); + break; + default: /* This case represents statements to be executed when an exception occurs. Those statements are implicitly followed diff --git a/gcc/gimple-pretty-print.c b/gcc/gimple-pretty-print.c index ed8e51c..2702854 100644 --- a/gcc/gimple-pretty-print.c +++ b/gcc/gimple-pretty-print.c @@ -1370,6 +1370,13 @@ dump_gimple_debug (pretty_printer *buffer, gdebug *gs, int spc, gimple_debug_source_bind_get_value (gs)); break; + case GIMPLE_DEBUG_BEGIN_STMT: + if (flags & TDF_RAW) + dump_gimple_fmt (buffer, spc, flags, "%G BEGIN_STMT", gs); + else + dump_gimple_fmt (buffer, spc, flags, "# DEBUG BEGIN_STMT"); + break; + default: gcc_unreachable (); } diff --git a/gcc/gimple.c b/gcc/gimple.c index c4e6f81..dc9aa79 100644 --- a/gcc/gimple.c +++ b/gcc/gimple.c @@ -836,6 +836,27 @@ gimple_build_debug_source_bind (tree var, tree value, } +/* Build a new GIMPLE_DEBUG_BEGIN_STMT statement in BLOCK at + LOCATION. */ + +gdebug * +gimple_build_debug_begin_stmt (tree block, location_t location + MEM_STAT_DECL) +{ + gdebug *p + = as_a ( + gimple_build_with_ops_stat (GIMPLE_DEBUG, + (unsigned)GIMPLE_DEBUG_BEGIN_STMT, 0 + PASS_MEM_STAT)); + + gimple_set_location (p, location); + gimple_set_block (p, block); + cfun->debug_marker_count++; + + return p; +} + + /* Build a GIMPLE_OMP_CRITICAL statement. BODY is the sequence of statements for which only one thread can execute. @@ -1874,6 +1895,9 @@ gimple_copy (gimple *stmt) gimple_set_modified (copy, true); } + if (gimple_debug_nonbind_marker_p (stmt)) + cfun->debug_marker_count++; + return copy; } diff --git a/gcc/gimple.h b/gcc/gimple.h index 8f289ac..68cd34f 100644 --- a/gcc/gimple.h +++ b/gcc/gimple.h @@ -1454,6 +1454,7 @@ gswitch *gimple_build_switch (tree, tree, vec ); geh_dispatch *gimple_build_eh_dispatch (int); gdebug *gimple_build_debug_bind (tree, tree, gimple * CXX_MEM_STAT_INFO); gdebug *gimple_build_debug_source_bind (tree, tree, gimple * CXX_MEM_STAT_INFO); +gdebug *gimple_build_debug_begin_stmt (tree, location_t CXX_MEM_STAT_INFO); gomp_critical *gimple_build_omp_critical (gimple_seq, tree, tree); gomp_for *gimple_build_omp_for (gimple_seq, int, tree, size_t, gimple_seq); gomp_parallel *gimple_build_omp_parallel (gimple_seq, tree, tree, tree); diff --git a/gcc/gimplify.c b/gcc/gimplify.c index e9dffc3..6c80a81 100644 --- a/gcc/gimplify.c +++ b/gcc/gimplify.c @@ -982,6 +982,48 @@ unshare_expr_without_location (tree expr) walk_tree (&expr, prune_expr_location, NULL, NULL); return expr; } + +/* Return the EXPR_LOCATION of EXPR, if it (maybe recursively) has + one, OR_ELSE otherwise. The location of a STATEMENT_LISTs + comprising at least one DEBUG_BEGIN_STMT followed by exactly one + EXPR is the location of the EXPR. */ + +static location_t +rexpr_location (tree expr, location_t or_else = UNKNOWN_LOCATION) +{ + if (!expr) + return or_else; + + if (EXPR_HAS_LOCATION (expr)) + return EXPR_LOCATION (expr); + + if (TREE_CODE (expr) != STATEMENT_LIST) + return or_else; + + tree_stmt_iterator i = tsi_start (expr); + + bool found = false; + while (!tsi_end_p (i) && TREE_CODE (tsi_stmt (i)) == DEBUG_BEGIN_STMT) + { + found = true; + tsi_next (&i); + } + + if (!found || !tsi_one_before_end_p (i)) + return or_else; + + return rexpr_location (tsi_stmt (i), or_else); +} + +/* Return TRUE iff EXPR (maybe recursively) has a location; see + rexpr_location for the potential recursion. */ + +static inline bool +rexpr_has_location (tree expr) +{ + return rexpr_location (expr) != UNKNOWN_LOCATION; +} + /* WRAPPER is a code such as BIND_EXPR or CLEANUP_POINT_EXPR which can both contain statements and have a value. Assign its value to a temporary @@ -1772,6 +1814,13 @@ warn_switch_unreachable_r (gimple_stmt_iterator *gsi_p, bool *handled_ops_p, /* Walk the sub-statements. */ *handled_ops_p = false; break; + + case GIMPLE_DEBUG: + /* Ignore these. We may generate them before declarations that + are never executed. If there's something to warn about, + there will be non-debug stmts too, and we'll catch those. */ + break; + case GIMPLE_CALL: if (gimple_call_internal_p (stmt, IFN_ASAN_MARK)) { @@ -3441,7 +3490,7 @@ shortcut_cond_r (tree pred, tree *true_label_p, tree *false_label_p, append_to_statement_list (t, &expr); /* Set the source location of the && on the second 'if'. */ - new_locus = EXPR_HAS_LOCATION (pred) ? EXPR_LOCATION (pred) : locus; + new_locus = rexpr_location (pred, locus); t = shortcut_cond_r (TREE_OPERAND (pred, 1), true_label_p, false_label_p, new_locus); append_to_statement_list (t, &expr); @@ -3464,7 +3513,7 @@ shortcut_cond_r (tree pred, tree *true_label_p, tree *false_label_p, append_to_statement_list (t, &expr); /* Set the source location of the || on the second 'if'. */ - new_locus = EXPR_HAS_LOCATION (pred) ? EXPR_LOCATION (pred) : locus; + new_locus = rexpr_location (pred, locus); t = shortcut_cond_r (TREE_OPERAND (pred, 1), true_label_p, false_label_p, new_locus); append_to_statement_list (t, &expr); @@ -3486,7 +3535,7 @@ shortcut_cond_r (tree pred, tree *true_label_p, tree *false_label_p, /* Keep the original source location on the first 'if'. Set the source location of the ? on the second 'if'. */ - new_locus = EXPR_HAS_LOCATION (pred) ? EXPR_LOCATION (pred) : locus; + new_locus = rexpr_location (pred, locus); expr = build3 (COND_EXPR, void_type_node, TREE_OPERAND (pred, 0), shortcut_cond_r (TREE_OPERAND (pred, 1), true_label_p, false_label_p, locus), @@ -3510,6 +3559,45 @@ shortcut_cond_r (tree pred, tree *true_label_p, tree *false_label_p, return expr; } +/* If EXPR is a GOTO_EXPR, return it. If it is a STATEMENT_LIST, skip + any of its leading DEBUG_BEGIN_STMTS and recurse on the subsequent + statement, if it is the last one. Otherwise, return NULL. */ + +static tree +find_goto (tree expr) +{ + if (!expr) + return NULL_TREE; + + if (TREE_CODE (expr) == GOTO_EXPR) + return expr; + + if (TREE_CODE (expr) != STATEMENT_LIST) + return NULL_TREE; + + tree_stmt_iterator i = tsi_start (expr); + + while (!tsi_end_p (i) && TREE_CODE (tsi_stmt (i)) == DEBUG_BEGIN_STMT) + tsi_next (&i); + + if (!tsi_one_before_end_p (i)) + return NULL_TREE; + + return find_goto (tsi_stmt (i)); +} + +/* Same as find_goto, except that it returns NULL if the destination + is not a LABEL_DECL. */ + +static inline tree +find_goto_label (tree expr) +{ + tree dest = find_goto (expr); + if (dest && TREE_CODE (GOTO_DESTINATION (dest)) == LABEL_DECL) + return dest; + return NULL_TREE; +} + /* Given a conditional expression EXPR with short-circuit boolean predicates using TRUTH_ANDIF_EXPR or TRUTH_ORIF_EXPR, break the predicate apart into the equivalent sequence of conditionals. */ @@ -3540,8 +3628,8 @@ shortcut_cond_expr (tree expr) location_t locus = EXPR_LOC_OR_LOC (expr, input_location); TREE_OPERAND (expr, 0) = TREE_OPERAND (pred, 1); /* Set the source location of the && on the second 'if'. */ - if (EXPR_HAS_LOCATION (pred)) - SET_EXPR_LOCATION (expr, EXPR_LOCATION (pred)); + if (rexpr_has_location (pred)) + SET_EXPR_LOCATION (expr, rexpr_location (pred)); then_ = shortcut_cond_expr (expr); then_se = then_ && TREE_SIDE_EFFECTS (then_); pred = TREE_OPERAND (pred, 0); @@ -3562,8 +3650,8 @@ shortcut_cond_expr (tree expr) location_t locus = EXPR_LOC_OR_LOC (expr, input_location); TREE_OPERAND (expr, 0) = TREE_OPERAND (pred, 1); /* Set the source location of the || on the second 'if'. */ - if (EXPR_HAS_LOCATION (pred)) - SET_EXPR_LOCATION (expr, EXPR_LOCATION (pred)); + if (rexpr_has_location (pred)) + SET_EXPR_LOCATION (expr, rexpr_location (pred)); else_ = shortcut_cond_expr (expr); else_se = else_ && TREE_SIDE_EFFECTS (else_); pred = TREE_OPERAND (pred, 0); @@ -3590,20 +3678,16 @@ shortcut_cond_expr (tree expr) /* If our arms just jump somewhere, hijack those labels so we don't generate jumps to jumps. */ - if (then_ - && TREE_CODE (then_) == GOTO_EXPR - && TREE_CODE (GOTO_DESTINATION (then_)) == LABEL_DECL) + if (tree then_goto = find_goto_label (then_)) { - true_label = GOTO_DESTINATION (then_); + true_label = GOTO_DESTINATION (then_goto); then_ = NULL; then_se = false; } - if (else_ - && TREE_CODE (else_) == GOTO_EXPR - && TREE_CODE (GOTO_DESTINATION (else_)) == LABEL_DECL) + if (tree else_goto = find_goto_label (else_)) { - false_label = GOTO_DESTINATION (else_); + false_label = GOTO_DESTINATION (else_goto); else_ = NULL; else_se = false; } @@ -3667,8 +3751,8 @@ shortcut_cond_expr (tree expr) { tree last = expr_last (expr); t = build_and_jump (&end_label); - if (EXPR_HAS_LOCATION (last)) - SET_EXPR_LOCATION (t, EXPR_LOCATION (last)); + if (rexpr_has_location (last)) + SET_EXPR_LOCATION (t, rexpr_location (last)); append_to_statement_list (t, &expr); } if (emit_false) @@ -3961,39 +4045,35 @@ gimplify_cond_expr (tree *expr_p, gimple_seq *pre_p, fallback_t fallback) gimple_push_condition (); have_then_clause_p = have_else_clause_p = false; - if (TREE_OPERAND (expr, 1) != NULL - && TREE_CODE (TREE_OPERAND (expr, 1)) == GOTO_EXPR - && TREE_CODE (GOTO_DESTINATION (TREE_OPERAND (expr, 1))) == LABEL_DECL - && (DECL_CONTEXT (GOTO_DESTINATION (TREE_OPERAND (expr, 1))) - == current_function_decl) + label_true = find_goto_label (TREE_OPERAND (expr, 1)); + if (label_true + && DECL_CONTEXT (GOTO_DESTINATION (label_true)) == current_function_decl /* For -O0 avoid this optimization if the COND_EXPR and GOTO_EXPR have different locations, otherwise we end up with incorrect location information on the branches. */ && (optimize || !EXPR_HAS_LOCATION (expr) - || !EXPR_HAS_LOCATION (TREE_OPERAND (expr, 1)) - || EXPR_LOCATION (expr) == EXPR_LOCATION (TREE_OPERAND (expr, 1)))) + || !rexpr_has_location (label_true) + || EXPR_LOCATION (expr) == rexpr_location (label_true))) { - label_true = GOTO_DESTINATION (TREE_OPERAND (expr, 1)); have_then_clause_p = true; + label_true = GOTO_DESTINATION (label_true); } else label_true = create_artificial_label (UNKNOWN_LOCATION); - if (TREE_OPERAND (expr, 2) != NULL - && TREE_CODE (TREE_OPERAND (expr, 2)) == GOTO_EXPR - && TREE_CODE (GOTO_DESTINATION (TREE_OPERAND (expr, 2))) == LABEL_DECL - && (DECL_CONTEXT (GOTO_DESTINATION (TREE_OPERAND (expr, 2))) - == current_function_decl) + label_false = find_goto_label (TREE_OPERAND (expr, 2)); + if (label_false + && DECL_CONTEXT (GOTO_DESTINATION (label_false)) == current_function_decl /* For -O0 avoid this optimization if the COND_EXPR and GOTO_EXPR have different locations, otherwise we end up with incorrect location information on the branches. */ && (optimize || !EXPR_HAS_LOCATION (expr) - || !EXPR_HAS_LOCATION (TREE_OPERAND (expr, 2)) - || EXPR_LOCATION (expr) == EXPR_LOCATION (TREE_OPERAND (expr, 2)))) + || !rexpr_has_location (label_false) + || EXPR_LOCATION (expr) == rexpr_location (label_false))) { - label_false = GOTO_DESTINATION (TREE_OPERAND (expr, 2)); have_else_clause_p = true; + label_false = GOTO_DESTINATION (label_false); } else label_false = create_artificial_label (UNKNOWN_LOCATION); @@ -11789,6 +11869,18 @@ gimplify_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p, ret = GS_ALL_DONE; break; + case DEBUG_EXPR_DECL: + gcc_unreachable (); + + case DEBUG_BEGIN_STMT: + gimplify_seq_add_stmt (pre_p, + gimple_build_debug_begin_stmt + (TREE_BLOCK (*expr_p), + EXPR_LOCATION (*expr_p))); + ret = GS_ALL_DONE; + *expr_p = NULL; + break; + case SSA_NAME: /* Allow callbacks into the gimplifier during optimization. */ ret = GS_ALL_DONE; diff --git a/gcc/langhooks-def.h b/gcc/langhooks-def.h index 61b081b..a3f02b2 100644 --- a/gcc/langhooks-def.h +++ b/gcc/langhooks-def.h @@ -130,6 +130,7 @@ extern int lhd_type_dwarf_attribute (const_tree, int); #define LANG_HOOKS_EH_USE_CXA_END_CLEANUP false #define LANG_HOOKS_DEEP_UNSHARING false #define LANG_HOOKS_CUSTOM_FUNCTION_DESCRIPTORS false +#define LANG_HOOKS_EMITS_BEGIN_STMT false #define LANG_HOOKS_RUN_LANG_SELFTESTS lhd_do_nothing #define LANG_HOOKS_GET_SUBSTRING_LOCATION lhd_get_substring_location @@ -343,6 +344,7 @@ extern void lhd_end_section (void); LANG_HOOKS_EH_USE_CXA_END_CLEANUP, \ LANG_HOOKS_DEEP_UNSHARING, \ LANG_HOOKS_CUSTOM_FUNCTION_DESCRIPTORS, \ + LANG_HOOKS_EMITS_BEGIN_STMT, \ LANG_HOOKS_RUN_LANG_SELFTESTS, \ LANG_HOOKS_GET_SUBSTRING_LOCATION \ } diff --git a/gcc/langhooks.h b/gcc/langhooks.h index b0c9829..3493ff3 100644 --- a/gcc/langhooks.h +++ b/gcc/langhooks.h @@ -528,6 +528,9 @@ struct lang_hooks instead of trampolines. */ bool custom_function_descriptors; + /* True if this language emits begin stmt notes. */ + bool emits_begin_stmt; + /* Run all lang-specific selftests. */ void (*run_lang_selftests) (void); diff --git a/gcc/lra-constraints.c b/gcc/lra-constraints.c index 4734c072..47527b0 100644 --- a/gcc/lra-constraints.c +++ b/gcc/lra-constraints.c @@ -5253,10 +5253,11 @@ inherit_reload_reg (bool def_p, int original_regno, lra_update_insn_regno_info (as_a (usage_insn)); if (lra_dump_file != NULL) { + basic_block bb = BLOCK_FOR_INSN (usage_insn); fprintf (lra_dump_file, " Inheritance reuse change %d->%d (bb%d):\n", original_regno, REGNO (new_reg), - BLOCK_FOR_INSN (usage_insn)->index); + bb ? bb->index : -1); dump_insn_slim (lra_dump_file, as_a (usage_insn)); } } @@ -5796,6 +5797,13 @@ update_ebb_live_info (rtx_insn *head, rtx_insn *tail) if (NOTE_P (curr_insn) && NOTE_KIND (curr_insn) != NOTE_INSN_BASIC_BLOCK) continue; curr_bb = BLOCK_FOR_INSN (curr_insn); + if (!curr_bb) + { + gcc_assert (DEBUG_INSN_P (curr_insn)); + if (DEBUG_MARKER_INSN_P (curr_insn)) + continue; + curr_bb = prev_bb; + } if (curr_bb != prev_bb) { if (prev_bb != NULL) diff --git a/gcc/lra.c b/gcc/lra.c index 9037495..ac99d5e 100644 --- a/gcc/lra.c +++ b/gcc/lra.c @@ -602,9 +602,9 @@ static struct lra_operand_data debug_operand_data = }; /* The following data are used as static insn data for all debug - insns. If structure lra_static_insn_data is changed, the + bind insns. If structure lra_static_insn_data is changed, the initializer should be changed too. */ -static struct lra_static_insn_data debug_insn_static_data = +static struct lra_static_insn_data debug_bind_static_data = { &debug_operand_data, 0, /* Duplication operands #. */ @@ -618,6 +618,22 @@ static struct lra_static_insn_data debug_insn_static_data = NULL /* Descriptions of operands in alternatives. */ }; +/* The following data are used as static insn data for all debug + marker insns. If structure lra_static_insn_data is changed, the + initializer should be changed too. */ +static struct lra_static_insn_data debug_marker_static_data = + { + &debug_operand_data, + 0, /* Duplication operands #. */ + -1, /* Commutative operand #. */ + 0, /* Operands #. There isn't any operand. */ + 0, /* Duplications #. */ + 0, /* Alternatives #. We are not interesting in alternatives + because we does not proceed debug_insns for reloads. */ + NULL, /* Hard registers referenced in machine description. */ + NULL /* Descriptions of operands in alternatives. */ + }; + /* Called once per compiler work to initialize some LRA data related to insns. */ static void @@ -949,12 +965,20 @@ lra_set_insn_recog_data (rtx_insn *insn) data->regs = NULL; if (DEBUG_INSN_P (insn)) { - data->insn_static_data = &debug_insn_static_data; data->dup_loc = NULL; data->arg_hard_regs = NULL; data->preferred_alternatives = ALL_ALTERNATIVES; - data->operand_loc = XNEWVEC (rtx *, 1); - data->operand_loc[0] = &INSN_VAR_LOCATION_LOC (insn); + if (DEBUG_BIND_INSN_P (insn)) + { + data->insn_static_data = &debug_bind_static_data; + data->operand_loc = XNEWVEC (rtx *, 1); + data->operand_loc[0] = &INSN_VAR_LOCATION_LOC (insn); + } + else if (DEBUG_MARKER_INSN_P (insn)) + { + data->insn_static_data = &debug_marker_static_data; + data->operand_loc = NULL; + } return data; } if (icode < 0) @@ -1600,7 +1624,7 @@ lra_update_insn_regno_info (rtx_insn *insn) return; data = lra_get_insn_recog_data (insn); static_data = data->insn_static_data; - freq = get_insn_freq (insn); + freq = NONDEBUG_INSN_P (insn) ? get_insn_freq (insn) : 0; invalidate_insn_data_regno_info (data, insn, freq); uid = INSN_UID (insn); for (i = static_data->n_operands - 1; i >= 0; i--) diff --git a/gcc/lto-streamer-in.c b/gcc/lto-streamer-in.c index 51d9a7b..37fa14e 100644 --- a/gcc/lto-streamer-in.c +++ b/gcc/lto-streamer-in.c @@ -1130,7 +1130,10 @@ input_function (tree fn_decl, struct data_in *data_in, Similarly remove all IFN_*SAN_* internal calls */ if (!flag_wpa) { - if (!MAY_HAVE_DEBUG_STMTS && is_gimple_debug (stmt)) + if (is_gimple_debug (stmt) + && (gimple_debug_nonbind_marker_p (stmt) + ? !MAY_HAVE_DEBUG_MARKER_STMTS + : !MAY_HAVE_DEBUG_BIND_STMTS)) remove = true; if (is_gimple_call (stmt) && gimple_call_internal_p (stmt)) @@ -1184,6 +1187,13 @@ input_function (tree fn_decl, struct data_in *data_in, { gsi_next (&bsi); stmts[gimple_uid (stmt)] = stmt; + + /* Remember that the input function has begin stmt + markers, so that we know to expect them when emitting + debug info. */ + if (!cfun->debug_nonbind_markers + && gimple_debug_nonbind_marker_p (stmt)) + cfun->debug_nonbind_markers = true; } } } diff --git a/gcc/params.def b/gcc/params.def index 136f927..9f63e63 100644 --- a/gcc/params.def +++ b/gcc/params.def @@ -963,6 +963,15 @@ DEFPARAM (PARAM_MAX_VARTRACK_REVERSE_OP_SIZE, "Max. size of loc list for which reverse ops should be added.", 50, 0, 0) +/* Set a threshold to discard debug markers (e.g. debug begin stmt + markers) when expanding a function to RTL, or inlining it into + another function. */ + +DEFPARAM (PARAM_MAX_DEBUG_MARKER_COUNT, + "max-debug-marker-count", + "Max. count of debug markers to expand or inline.", + 100000, 0, 0) + /* Set minimum insn uid for non-debug insns. */ DEFPARAM (PARAM_MIN_NONDEBUG_INSN_UID, diff --git a/gcc/print-rtl.c b/gcc/print-rtl.c index 79ec463..0d36a42 100644 --- a/gcc/print-rtl.c +++ b/gcc/print-rtl.c @@ -258,6 +258,16 @@ rtx_writer::print_rtx_operand_code_0 (const_rtx in_rtx ATTRIBUTE_UNUSED, fputc ('\t', m_outfile); break; + case NOTE_INSN_BEGIN_STMT: +#ifndef GENERATOR_FILE + { + expanded_location xloc + = expand_location (NOTE_MARKER_LOCATION (in_rtx)); + fprintf (m_outfile, " %s:%i", xloc.file, xloc.line); + } +#endif + break; + default: break; } @@ -1791,6 +1801,20 @@ print_insn (pretty_printer *pp, const rtx_insn *x, int verbose) case DEBUG_INSN: { + if (DEBUG_MARKER_INSN_P (x)) + { + switch (INSN_DEBUG_MARKER_KIND (x)) + { + case NOTE_INSN_BEGIN_STMT: + pp_string (pp, "debug begin stmt marker"); + break; + + default: + gcc_unreachable (); + } + break; + } + const char *name = "?"; if (DECL_P (INSN_VAR_LOCATION_DECL (x))) diff --git a/gcc/recog.c b/gcc/recog.c index cfce029..566425d 100644 --- a/gcc/recog.c +++ b/gcc/recog.c @@ -2251,6 +2251,7 @@ extract_insn (rtx_insn *insn) case ADDR_VEC: case ADDR_DIFF_VEC: case VAR_LOCATION: + case DEBUG_MARKER: return; case SET: diff --git a/gcc/rtl.def b/gcc/rtl.def index 4c2607a..ccdaa82 100644 --- a/gcc/rtl.def +++ b/gcc/rtl.def @@ -761,6 +761,9 @@ DEF_RTL_EXPR(ENTRY_VALUE, "entry_value", "0", RTX_OBJ) been optimized away completely. */ DEF_RTL_EXPR(DEBUG_PARAMETER_REF, "debug_parameter_ref", "t", RTX_OBJ) +/* Used in marker DEBUG_INSNs to avoid being recognized as an insn. */ +DEF_RTL_EXPR(DEBUG_MARKER, "debug_marker", "", RTX_OBJ) + /* All expressions from this point forward appear only in machine descriptions. */ #ifdef GENERATOR_FILE diff --git a/gcc/tree-inline.c b/gcc/tree-inline.c index a142488..a99e975 100644 --- a/gcc/tree-inline.c +++ b/gcc/tree-inline.c @@ -53,6 +53,7 @@ along with GCC; see the file COPYING3. If not see #include "tree-ssa.h" #include "except.h" #include "debug.h" +#include "params.h" #include "value-prof.h" #include "cfgloop.h" #include "builtins.h" @@ -1354,7 +1355,9 @@ remap_gimple_stmt (gimple *stmt, copy_body_data *id) gimple_seq stmts = NULL; if (is_gimple_debug (stmt) - && !opt_for_fn (id->dst_fn, flag_var_tracking_assignments)) + && (gimple_debug_nonbind_marker_p (stmt) + ? !DECL_STRUCT_FUNCTION (id->dst_fn)->debug_nonbind_markers + : !opt_for_fn (id->dst_fn, flag_var_tracking_assignments))) return stmts; /* Begin by recognizing trees that we'll completely rewrite for the @@ -1637,6 +1640,20 @@ remap_gimple_stmt (gimple *stmt, copy_body_data *id) gimple_seq_add_stmt (&stmts, copy); return stmts; } + if (gimple_debug_nonbind_marker_p (stmt)) + { + /* If the inlined function has too many debug markers, + don't copy them. */ + if (id->src_cfun->debug_marker_count + > PARAM_VALUE (PARAM_MAX_DEBUG_MARKER_COUNT)) + return stmts; + + gdebug *copy = as_a (gimple_copy (stmt)); + id->debug_stmts.safe_push (copy); + gimple_seq_add_stmt (&stmts, copy); + return stmts; + } + gcc_checking_assert (!is_gimple_debug (stmt)); /* Create a new deep copy of the statement. */ copy = gimple_copy (stmt); @@ -1732,7 +1749,8 @@ remap_gimple_stmt (gimple *stmt, copy_body_data *id) gimple_set_block (copy, *n); } - if (gimple_debug_bind_p (copy) || gimple_debug_source_bind_p (copy)) + if (gimple_debug_bind_p (copy) || gimple_debug_source_bind_p (copy) + || gimple_debug_nonbind_marker_p (copy)) { gimple_seq_add_stmt (&stmts, copy); return stmts; @@ -2606,6 +2624,8 @@ maybe_move_debug_stmts_to_successors (copy_body_data *id, basic_block new_bb) value = gimple_debug_source_bind_get_value (stmt); new_stmt = gimple_build_debug_source_bind (var, value, stmt); } + else if (gimple_debug_nonbind_marker_p (stmt)) + new_stmt = as_a (gimple_copy (stmt)); else gcc_unreachable (); gsi_insert_before (&dsi, new_stmt, GSI_SAME_STMT); @@ -2922,6 +2942,9 @@ copy_debug_stmt (gdebug *stmt, copy_body_data *id) gimple_set_block (stmt, n ? *n : id->block); } + if (gimple_debug_nonbind_marker_p (stmt)) + return; + /* Remap all the operands in COPY. */ memset (&wi, 0, sizeof (wi)); wi.info = id; @@ -2930,8 +2953,10 @@ copy_debug_stmt (gdebug *stmt, copy_body_data *id) if (gimple_debug_source_bind_p (stmt)) t = gimple_debug_source_bind_get_var (stmt); - else + else if (gimple_debug_bind_p (stmt)) t = gimple_debug_bind_get_var (stmt); + else + gcc_unreachable (); if (TREE_CODE (t) == PARM_DECL && id->debug_map && (n = id->debug_map->get (t))) diff --git a/gcc/tree-iterator.c b/gcc/tree-iterator.c index c485413..10e510d 100644 --- a/gcc/tree-iterator.c +++ b/gcc/tree-iterator.c @@ -89,7 +89,7 @@ append_to_statement_list_1 (tree t, tree *list_p) void append_to_statement_list (tree t, tree *list_p) { - if (t && TREE_SIDE_EFFECTS (t)) + if (t && (TREE_SIDE_EFFECTS (t) || TREE_CODE (t) == DEBUG_BEGIN_STMT)) append_to_statement_list_1 (t, list_p); } @@ -137,7 +137,8 @@ tsi_link_before (tree_stmt_iterator *i, tree t, enum tsi_iterator_update mode) tail = head; } - TREE_SIDE_EFFECTS (i->container) = 1; + if (TREE_CODE (t) != DEBUG_BEGIN_STMT) + TREE_SIDE_EFFECTS (i->container) = 1; cur = i->ptr; @@ -213,7 +214,8 @@ tsi_link_after (tree_stmt_iterator *i, tree t, enum tsi_iterator_update mode) tail = head; } - TREE_SIDE_EFFECTS (i->container) = 1; + if (TREE_CODE (t) != DEBUG_BEGIN_STMT) + TREE_SIDE_EFFECTS (i->container) = 1; cur = i->ptr; @@ -279,8 +281,9 @@ tsi_delink (tree_stmt_iterator *i) i->ptr = next; } -/* Return the first expression in a sequence of COMPOUND_EXPRs, - or in a STATEMENT_LIST. */ +/* Return the first expression in a sequence of COMPOUND_EXPRs, or in + a STATEMENT_LIST, disregarding DEBUG_BEGIN_STMTs, recursing into a + STATEMENT_LIST if that's the first non-DEBUG_BEGIN_STMT. */ tree expr_first (tree expr) @@ -291,7 +294,20 @@ expr_first (tree expr) if (TREE_CODE (expr) == STATEMENT_LIST) { struct tree_statement_list_node *n = STATEMENT_LIST_HEAD (expr); - return n ? n->stmt : NULL_TREE; + if (!n) + return NULL_TREE; + while (TREE_CODE (n->stmt) == DEBUG_BEGIN_STMT) + { + n = n->next; + if (!n) + return NULL_TREE; + } + /* If the first non-debug stmt is not a statement list, we + already know it's what we're looking for. */ + if (TREE_CODE (n->stmt) != STATEMENT_LIST) + return n->stmt; + + return expr_first (n->stmt); } while (TREE_CODE (expr) == COMPOUND_EXPR) @@ -300,8 +316,9 @@ expr_first (tree expr) return expr; } -/* Return the last expression in a sequence of COMPOUND_EXPRs, - or in a STATEMENT_LIST. */ +/* Return the last expression in a sequence of COMPOUND_EXPRs, or in a + STATEMENT_LIST, disregarding DEBUG_BEGIN_STMTs, recursing into a + STATEMENT_LIST if that's the last non-DEBUG_BEGIN_STMT. */ tree expr_last (tree expr) @@ -312,7 +329,20 @@ expr_last (tree expr) if (TREE_CODE (expr) == STATEMENT_LIST) { struct tree_statement_list_node *n = STATEMENT_LIST_TAIL (expr); - return n ? n->stmt : NULL_TREE; + if (!n) + return NULL_TREE; + while (TREE_CODE (n->stmt) == DEBUG_BEGIN_STMT) + { + n = n->prev; + if (!n) + return NULL_TREE; + } + /* If the last non-debug stmt is not a statement list, we + already know it's what we're looking for. */ + if (TREE_CODE (n->stmt) != STATEMENT_LIST) + return n->stmt; + + return expr_last (n->stmt); } while (TREE_CODE (expr) == COMPOUND_EXPR) diff --git a/gcc/tree-pretty-print.c b/gcc/tree-pretty-print.c index 1fe3e63..22c6667 100644 --- a/gcc/tree-pretty-print.c +++ b/gcc/tree-pretty-print.c @@ -3291,6 +3291,10 @@ dump_generic_node (pretty_printer *pp, tree node, int spc, dump_flags_t flags, pp_string (pp, "_Cilk_sync"); break; + case DEBUG_BEGIN_STMT: + pp_string (pp, "# DEBUG BEGIN STMT"); + break; + default: NIY; } diff --git a/gcc/tree-ssa-threadedge.c b/gcc/tree-ssa-threadedge.c index 70675e4..91793bf 100644 --- a/gcc/tree-ssa-threadedge.c +++ b/gcc/tree-ssa-threadedge.c @@ -712,6 +712,8 @@ propagate_threaded_block_debug_into (basic_block dest, basic_block src) gimple *stmt = gsi_stmt (si); if (!is_gimple_debug (stmt)) break; + if (gimple_debug_nonbind_marker_p (stmt)) + continue; i++; } @@ -739,6 +741,8 @@ propagate_threaded_block_debug_into (basic_block dest, basic_block src) var = gimple_debug_bind_get_var (stmt); else if (gimple_debug_source_bind_p (stmt)) var = gimple_debug_source_bind_get_var (stmt); + else if (gimple_debug_nonbind_marker_p (stmt)) + continue; else gcc_unreachable (); @@ -766,17 +770,23 @@ propagate_threaded_block_debug_into (basic_block dest, basic_block src) var = gimple_debug_bind_get_var (stmt); else if (gimple_debug_source_bind_p (stmt)) var = gimple_debug_source_bind_get_var (stmt); + else if (gimple_debug_nonbind_marker_p (stmt)) + continue; else gcc_unreachable (); - /* Discard debug bind overlaps. ??? Unlike stmts from src, + /* Discard debug bind overlaps. Unlike stmts from src, copied into a new block that will precede BB, debug bind stmts in bypassed BBs may actually be discarded if - they're overwritten by subsequent debug bind stmts, which - might be a problem once we introduce stmt frontier notes - or somesuch. Adding `&& bb == src' to the condition - below will preserve all potentially relevant debug - notes. */ + they're overwritten by subsequent debug bind stmts. We + want to copy binds for all modified variables, so that we + retain a bind to the shared def if there is one, or to a + newly introduced PHI node if there is one. Our bind will + end up reset if the value is dead, but that implies the + variable couldn't have survived, so it's fine. We are + not actually running the code that performed the binds at + this point, we're just adding binds so that they survive + the new confluence, so markers should not be copied. */ if (vars && vars->add (var)) continue; else if (!vars) @@ -787,8 +797,7 @@ propagate_threaded_block_debug_into (basic_block dest, basic_block src) break; if (i >= 0) continue; - - if (fewvars.length () < (unsigned) alloc_count) + else if (fewvars.length () < (unsigned) alloc_count) fewvars.quick_push (var); else { diff --git a/gcc/tree.c b/gcc/tree.c index e379940..30cadd7 100644 --- a/gcc/tree.c +++ b/gcc/tree.c @@ -1015,7 +1015,8 @@ make_node (enum tree_code code MEM_STAT_DECL) switch (type) { case tcc_statement: - TREE_SIDE_EFFECTS (t) = 1; + if (code != DEBUG_BEGIN_STMT) + TREE_SIDE_EFFECTS (t) = 1; break; case tcc_declaration: @@ -4412,7 +4413,10 @@ build1 (enum tree_code code, tree type, tree node MEM_STAT_DECL) } if (TREE_CODE_CLASS (code) == tcc_statement) - TREE_SIDE_EFFECTS (t) = 1; + { + if (code != DEBUG_BEGIN_STMT) + TREE_SIDE_EFFECTS (t) = 1; + } else switch (code) { case VA_ARG_EXPR: diff --git a/gcc/tree.def b/gcc/tree.def index 9f80c4d..e30e950 100644 --- a/gcc/tree.def +++ b/gcc/tree.def @@ -382,6 +382,9 @@ DEFTREECODE (RESULT_DECL, "result_decl", tcc_declaration, 0) DEBUG stmts. */ DEFTREECODE (DEBUG_EXPR_DECL, "debug_expr_decl", tcc_declaration, 0) +/* A stmt that marks the beginning of a source statement. */ +DEFTREECODE (DEBUG_BEGIN_STMT, "debug_begin_stmt", tcc_statement, 0) + /* A namespace declaration. Namespaces appear in DECL_CONTEXT of other _DECLs, providing a hierarchy of names. */ DEFTREECODE (NAMESPACE_DECL, "namespace_decl", tcc_declaration, 0) diff --git a/gcc/tree.h b/gcc/tree.h index 2e8b3e9..62a85ea 100644 --- a/gcc/tree.h +++ b/gcc/tree.h @@ -1225,7 +1225,7 @@ extern void protected_set_expr_location (tree, location_t); /* GOTO_EXPR accessor. This gives access to the label associated with a goto statement. */ -#define GOTO_DESTINATION(NODE) TREE_OPERAND ((NODE), 0) +#define GOTO_DESTINATION(NODE) TREE_OPERAND (GOTO_EXPR_CHECK (NODE), 0) /* ASM_EXPR accessors. ASM_STRING returns a STRING_CST for the instruction (e.g., "mov x, y"). ASM_OUTPUTS, ASM_INPUTS, and diff --git a/gcc/var-tracking.c b/gcc/var-tracking.c index 974b4ea..d3850af 100644 --- a/gcc/var-tracking.c +++ b/gcc/var-tracking.c @@ -9919,6 +9919,36 @@ vt_init_cfa_base (void) cselib_preserve_cfa_base_value (val, REGNO (cfa_base_rtx)); } +/* Reemit INSN, a MARKER_DEBUG_INSN, as a note. */ + +static rtx_insn * +reemit_marker_as_note (rtx_insn *insn, basic_block *bb) +{ + gcc_checking_assert (DEBUG_MARKER_INSN_P (insn)); + + enum insn_note kind = INSN_DEBUG_MARKER_KIND (insn); + + switch (kind) + { + case NOTE_INSN_BEGIN_STMT: + { + rtx_insn *note = NULL; + if (cfun->debug_nonbind_markers) + { + note = emit_note_before (kind, insn); + NOTE_MARKER_LOCATION (note) = INSN_LOCATION (insn); + if (bb) + BLOCK_FOR_INSN (note) = *bb; + } + delete_insn (insn); + return note; + } + + default: + gcc_unreachable (); + } +} + /* Allocate and initialize the data structures for variable tracking and parse the RTL to get the micro operations. */ @@ -10162,6 +10192,12 @@ vt_initialize (void) cselib_hook_called = false; adjust_insn (bb, insn); + if (DEBUG_MARKER_INSN_P (insn)) + { + insn = reemit_marker_as_note (insn, &save_bb); + continue; + } + if (MAY_HAVE_DEBUG_BIND_INSNS) { if (CALL_P (insn)) @@ -10238,10 +10274,11 @@ vt_initialize (void) static int debug_label_num = 1; -/* Get rid of all debug insns from the insn stream. */ +/* Remove from the insn stream all debug insns used for variable + tracking at assignments. */ static void -delete_debug_insns (void) +delete_vta_debug_insns (void) { basic_block bb; rtx_insn *insn, *next; @@ -10257,6 +10294,12 @@ delete_debug_insns (void) insn = next) if (DEBUG_INSN_P (insn)) { + if (DEBUG_MARKER_INSN_P (insn)) + { + insn = reemit_marker_as_note (insn, NULL); + continue; + } + tree decl = INSN_VAR_LOCATION_DECL (insn); if (TREE_CODE (decl) == LABEL_DECL && DECL_NAME (decl) @@ -10282,10 +10325,13 @@ delete_debug_insns (void) handled as well.. */ static void -vt_debug_insns_local (bool skipped ATTRIBUTE_UNUSED) +vt_debug_insns_local (bool skipped) { - /* ??? Just skip it all for now. */ - delete_debug_insns (); + /* ??? Just skip it all for now. If we skipped the global pass, + arrange for stmt markers to be dropped as well. */ + if (skipped) + cfun->debug_nonbind_markers = 0; + delete_vta_debug_insns (); } /* Free the data structures needed for variable tracking. */ @@ -10350,15 +10396,21 @@ variable_tracking_main_1 (void) { bool success; - if (flag_var_tracking_assignments < 0 + /* We won't be called as a separate pass if flag_var_tracking is not + set, but final may call us to turn debug markers into notes. */ + if ((!flag_var_tracking && MAY_HAVE_DEBUG_INSNS) + || flag_var_tracking_assignments < 0 /* Var-tracking right now assumes the IR doesn't contain any pseudos at this point. */ || targetm.no_register_allocation) { - delete_debug_insns (); + delete_vta_debug_insns (); return 0; } + if (!flag_var_tracking) + return 0; + if (n_basic_blocks_for_fn (cfun) > 500 && n_edges_for_fn (cfun) / n_basic_blocks_for_fn (cfun) >= 20) { @@ -10380,7 +10432,9 @@ variable_tracking_main_1 (void) { vt_finalize (); - delete_debug_insns (); + cfun->debug_nonbind_markers = 0; + + delete_vta_debug_insns (); /* This is later restored by our caller. */ flag_var_tracking_assignments = 0; From patchwork Sat Sep 30 09:08:23 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Alexandre Oliva X-Patchwork-Id: 820190 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (mailfrom) smtp.mailfrom=gcc.gnu.org (client-ip=209.132.180.131; helo=sourceware.org; envelope-from=gcc-patches-return-463262-incoming=patchwork.ozlabs.org@gcc.gnu.org; receiver=) Authentication-Results: ozlabs.org; dkim=pass (1024-bit key; unprotected) header.d=gcc.gnu.org header.i=@gcc.gnu.org header.b="fLq4spkw"; dkim-atps=neutral Received: from sourceware.org (server1.sourceware.org [209.132.180.131]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 3y42hW7444z9t2h for ; Sat, 30 Sep 2017 19:10:35 +1000 (AEST) DomainKey-Signature: a=rsa-sha1; c=nofws; d=gcc.gnu.org; h=list-id :list-unsubscribe:list-archive:list-post:list-help:sender:from :to:cc:subject:date:message-id:in-reply-to:references; q=dns; s= default; b=bZbBepBNXChh31+Vo46uUelzVF4/DssEnj4Gysnsg+h2fZKUlbmRJ W/yh8rHwncOC9vYcRFF6+JsUibXF1x5hgiWZaCMOF6oo1P9SqnVIGfNG9Prw/epm 9KHDeBnLWVBVlqkU33y9wJLZH6QrLyWl3DXN529aF+Dcp/1TMd+1so= DKIM-Signature: v=1; a=rsa-sha1; c=relaxed; d=gcc.gnu.org; h=list-id :list-unsubscribe:list-archive:list-post:list-help:sender:from :to:cc:subject:date:message-id:in-reply-to:references; s= default; bh=6i2mgSORBi9M+2zOHXchNkXSakI=; b=fLq4spkwGiNjZnf/vG4+ qRv8yBnYzyJdQrxvY5rhVax/LhZAiJrO9VLHYYX7bOlUSsMUtPJRgfkkLIz/Y0v1 j+fpwVsGglXO+bDkk03EmoIPJBt+Jh70P349cPmh14KiUPRNLl4opLJohmFIeFF8 J9BRCOMnYQd7a8dTKfxKcNM= Received: (qmail 63903 invoked by alias); 30 Sep 2017 09:09:47 -0000 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 Received: (qmail 63884 invoked by uid 89); 30 Sep 2017 09:09:47 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-26.9 required=5.0 tests=BAYES_00, GIT_PATCH_0, GIT_PATCH_1, GIT_PATCH_2, GIT_PATCH_3, RP_MATCHES_RCVD, SPF_HELO_PASS autolearn=ham version=3.3.2 spammy=selective, progressive, Activate, stabs X-HELO: mx1.redhat.com Received: from mx1.redhat.com (HELO mx1.redhat.com) (209.132.183.28) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Sat, 30 Sep 2017 09:09:46 +0000 Received: from smtp.corp.redhat.com (int-mx04.intmail.prod.int.phx2.redhat.com [10.5.11.14]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 06A21883BE; Sat, 30 Sep 2017 09:09:45 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.3.2 mx1.redhat.com 06A21883BE Authentication-Results: ext-mx02.extmail.prod.ext.phx2.redhat.com; dmarc=none (p=none dis=none) header.from=redhat.com Authentication-Results: ext-mx02.extmail.prod.ext.phx2.redhat.com; spf=fail smtp.mailfrom=aoliva@redhat.com Received: from freie.home (ovpn04.gateway.prod.ext.phx2.redhat.com [10.5.9.4]) by smtp.corp.redhat.com (Postfix) with ESMTPS id 5CA32612B1; Sat, 30 Sep 2017 09:09:44 +0000 (UTC) Received: from frit.home (frit.home [172.31.160.7]) by freie.home (8.15.2/8.15.2) with ESMTP id v8U98pIW022010; Sat, 30 Sep 2017 06:09:19 -0300 From: Alexandre Oliva To: Richard Biener Cc: GCC Patches , Alexandre Oliva Subject: [PATCH 5/9] [SFN] Introduce -gstatement-frontiers option, enable debug markers Date: Sat, 30 Sep 2017 06:08:23 -0300 Message-Id: <20170930090827.6604-5-aoliva@redhat.com> In-Reply-To: References: Introduce a command line option to enable statement frontiers, enabled by default in optimized builds with DWARF2+ debug information. This patch depends on an earlier patch that completed the infrastructure for debug markers, and on another patch that turns -g into a negatable option prefix. gcc/ChangeLog * common.opt (gstatement-frontiers): New, setting debug_nonbind_markers_p. * rtl.h (MAY_HAVE_DEBUG_MARKER_INSNS): Activate. * toplev.c (process_options): Autodetect value for debug statement frontiers option. * tree.h (MAY_HAVE_DEBUG_MARKER_STMTS): Activate. * doc/invoke.texi (gstatement-frontiers, gno-statement-frontiers): New. --- gcc/common.opt | 4 ++++ gcc/doc/invoke.texi | 12 ++++++++++++ gcc/rtl.h | 2 +- gcc/toplev.c | 4 ++++ gcc/tree.h | 2 +- 5 files changed, 22 insertions(+), 2 deletions(-) diff --git a/gcc/common.opt b/gcc/common.opt index dfde6ad..a12c11c 100644 --- a/gcc/common.opt +++ b/gcc/common.opt @@ -2889,6 +2889,10 @@ gstabs+ Common Driver JoinedOrMissing Negative(gvms) Generate debug information in extended STABS format. +gstatement-frontiers +Common Driver Var(debug_nonbind_markers_p) Init(2) +Emit progressive recommended breakpoint locations. + gstrict-dwarf Common Driver Report Var(dwarf_strict) Init(0) Don't emit DWARF additions beyond selected version. diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi index 108d730..85e41e4 100644 --- a/gcc/doc/invoke.texi +++ b/gcc/doc/invoke.texi @@ -346,6 +346,7 @@ Objective-C and Objective-C++ Dialects}. -ggdb -grecord-gcc-switches -gno-record-gcc-switches @gol -gstabs -gstabs+ -gstrict-dwarf -gno-strict-dwarf @gol -gcolumn-info -gno-column-info @gol +-gstatement-frontiers -gno-statement-frontiers @gol -gvms -gxcoff -gxcoff+ -gz@r{[}=@var{type}@r{]} @gol -fdebug-prefix-map=@var{old}=@var{new} -fdebug-types-section @gol -fno-eliminate-unused-debug-types @gol @@ -7040,6 +7041,17 @@ Emit location column information into DWARF debugging information, rather than just file and line. This option is disabled by default. +@item -gstatement-frontiers +@item -gno-statement-frontiers +@opindex gstatement-frontiers +@opindex gno-statement-frontiers +This option causes GCC to create markers in the internal representation +at the beginning of statements, and to keep them roughly in place +throughout compilation, using them to guide the output of @code{is_stmt} +markers in the line number table. This is enabled by default when +compiling with optimization (@option{-Os}, @option{-O}, @option{-O2}, +@dots{}), and outputting DWARF 2 debug information at the normal level. + @item -gz@r{[}=@var{type}@r{]} @opindex gz Produce compressed debug sections in DWARF format, if that is supported. diff --git a/gcc/rtl.h b/gcc/rtl.h index c79a277..a0c27fc 100644 --- a/gcc/rtl.h +++ b/gcc/rtl.h @@ -816,7 +816,7 @@ struct GTY(()) rtvec_def { #define NONDEBUG_INSN_P(X) (INSN_P (X) && !DEBUG_INSN_P (X)) /* Nonzero if DEBUG_MARKER_INSN_P may possibly hold. */ -#define MAY_HAVE_DEBUG_MARKER_INSNS 0 /* debug_nonbind_markers_p */ +#define MAY_HAVE_DEBUG_MARKER_INSNS debug_nonbind_markers_p /* Nonzero if DEBUG_BIND_INSN_P may possibly hold. */ #define MAY_HAVE_DEBUG_BIND_INSNS flag_var_tracking_assignments /* Nonzero if DEBUG_INSN_P may possibly hold. */ diff --git a/gcc/toplev.c b/gcc/toplev.c index bee79d3..0ef46da 100644 --- a/gcc/toplev.c +++ b/gcc/toplev.c @@ -1514,6 +1514,10 @@ process_options (void) warning_at (UNKNOWN_LOCATION, 0, "var-tracking-assignments changes selective scheduling"); + if (debug_nonbind_markers_p == AUTODETECT_VALUE) + debug_nonbind_markers_p = optimize && debug_info_level >= DINFO_LEVEL_NORMAL + && (write_symbols == DWARF2_DEBUG || write_symbols == VMS_AND_DWARF2_DEBUG); + if (flag_tree_cselim == AUTODETECT_VALUE) { if (HAVE_conditional_move) diff --git a/gcc/tree.h b/gcc/tree.h index 62a85ea..8c3bda1 100644 --- a/gcc/tree.h +++ b/gcc/tree.h @@ -1127,7 +1127,7 @@ extern void omp_clause_range_check_failed (const_tree, const char *, int, ((int)TREE_INT_CST_LOW (VL_EXP_CHECK (NODE)->exp.operands[0])) /* Nonzero if gimple_debug_nonbind_marker_p() may possibly hold. */ -#define MAY_HAVE_DEBUG_MARKER_STMTS 0 /* debug_nonbind_markers_p */ +#define MAY_HAVE_DEBUG_MARKER_STMTS debug_nonbind_markers_p /* Nonzero if gimple_debug_bind_p() (and thus gimple_debug_source_bind_p()) may possibly hold. */ #define MAY_HAVE_DEBUG_BIND_STMTS flag_var_tracking_assignments From patchwork Sat Sep 30 09:08:24 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Alexandre Oliva X-Patchwork-Id: 820191 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (mailfrom) smtp.mailfrom=gcc.gnu.org (client-ip=209.132.180.131; helo=sourceware.org; envelope-from=gcc-patches-return-463263-incoming=patchwork.ozlabs.org@gcc.gnu.org; receiver=) Authentication-Results: ozlabs.org; dkim=pass (1024-bit key; unprotected) header.d=gcc.gnu.org header.i=@gcc.gnu.org header.b="h5z2Bhgw"; dkim-atps=neutral Received: from sourceware.org (server1.sourceware.org [209.132.180.131]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 3y42j03KZ9z9t2h for ; Sat, 30 Sep 2017 19:11:00 +1000 (AEST) DomainKey-Signature: a=rsa-sha1; c=nofws; d=gcc.gnu.org; h=list-id :list-unsubscribe:list-archive:list-post:list-help:sender:from :to:cc:subject:date:message-id:in-reply-to:references; q=dns; s= default; b=cjMzuWMLzsntvp6ptYQ5YkPOyJum8Zrn7f3YhrW/QEctUZB8EuCOZ LiYFHTHx+DIcrs6m13jc9Os/Lsp64gP3h/Gm62nWOhGZM9ADc9xT3a4pZ6K1pYBp VaUFvhG93+FUHlJwX5n0yfBOplXD3tehmoKwsKFYektsMyhoj6O73c= DKIM-Signature: v=1; a=rsa-sha1; c=relaxed; d=gcc.gnu.org; h=list-id :list-unsubscribe:list-archive:list-post:list-help:sender:from :to:cc:subject:date:message-id:in-reply-to:references; s= default; bh=MGsAzh3e039XSi/asKhpfU/Y7yw=; b=h5z2BhgwyU//7ZXpaFxo YwCSwMBy5C6hMi+XTIQd1ReWdzgjBcktmg6i2zLajrN/LHMUnKJnLjjehC9eorjd vUowX6A77q20g0U3w5o7S74iRnw2BEGVTZaj5sjyDkxIfj485u8nWaIXXDuM5qDB YspH3Egd+8AvYMP2MXFWzlQ= Received: (qmail 64678 invoked by alias); 30 Sep 2017 09:09:57 -0000 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 Received: (qmail 64469 invoked by uid 89); 30 Sep 2017 09:09:55 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-26.9 required=5.0 tests=BAYES_00, GIT_PATCH_0, GIT_PATCH_1, GIT_PATCH_2, GIT_PATCH_3, RP_MATCHES_RCVD, SPF_HELO_PASS autolearn=ham version=3.3.2 spammy=clarity, whatnot, pac, borrowed X-HELO: mx1.redhat.com Received: from mx1.redhat.com (HELO mx1.redhat.com) (209.132.183.28) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Sat, 30 Sep 2017 09:09:53 +0000 Received: from smtp.corp.redhat.com (int-mx01.intmail.prod.int.phx2.redhat.com [10.5.11.11]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 290CF883A5; Sat, 30 Sep 2017 09:09:52 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.3.2 mx1.redhat.com 290CF883A5 Authentication-Results: ext-mx02.extmail.prod.ext.phx2.redhat.com; dmarc=none (p=none dis=none) header.from=redhat.com Authentication-Results: ext-mx02.extmail.prod.ext.phx2.redhat.com; spf=fail smtp.mailfrom=aoliva@redhat.com Received: from freie.home (ovpn04.gateway.prod.ext.phx2.redhat.com [10.5.9.4]) by smtp.corp.redhat.com (Postfix) with ESMTPS id D508A197E9; Sat, 30 Sep 2017 09:09:51 +0000 (UTC) Received: from frit.home (frit.home [172.31.160.7]) by freie.home (8.15.2/8.15.2) with ESMTP id v8U98pIX022010; Sat, 30 Sep 2017 06:09:21 -0300 From: Alexandre Oliva To: Richard Biener Cc: GCC Patches , Alexandre Oliva Subject: [PATCH 6/9] [LVU] Allow final_start_function to skip initial insns Date: Sat, 30 Sep 2017 06:08:24 -0300 Message-Id: <20170930090827.6604-6-aoliva@redhat.com> In-Reply-To: References: This API change will enable final_start_function() to "consume" initial insns, and choose the first insn to be passed to final(). Many ports call final_start_function() and final() when creating thunks and whatnot, so they needed adjusting. for gcc/ChangeLog * output.h (final_start_function): Adjust. * final.c (final_start_function): Take pointer to FIRST. (rest_of_handle_final): Adjust. * config/aarch64/aarch64.c (aarch64_output_mi_thunk): Adjust. * config/alpha/alpha.c (alpha_output_mi_thunk_osf): Likewise. * config/arm/arm.c (arm_thumb1_mi_thunk): Likewise. (arm32_output_mi_thunk): Likewise. * config/cris/cris.c (cris_asm_output_mi_thunk): Likewise. * config/i386/i386.c (ix86_code_end): Likewise. (x86_output_mi_thunk): Likewise. * config/ia64/ia64.c (ia64_output_mi_thunk): Likewise. * config/m68k/m68k.c (m68k_output_mi_thunk): Likewise. * config/microblaze/microblaze.c (microblaze_asm_output_mi_thunk): Likewise. * config/mips/mips.c (mips_output_mi_thunk): Likewise. * config/nds32/nds32.c (nds32_asm_output_mi_thunk): Likewise. * config/nios2/nios2.c (nios2_asm_output_mi_thunk): Likewise. * config/pa/pa.c (pa_asm_output_mi_thunk): Likewise. * config/rs6000/rs6000.c (rs6000_output_mi_thunk): Likewise. (rs6000_code_end): Likewise. * config/s390/s390.c (s390_output_mi_thunk): Likewise. * config/sh/sh.c (sh_output_mi_thunk): Likewise. * config/sparc/sparc.c (sparc_output_mi_thunk): Likewise. * config/spu/spu.c (spu_output_mi_thunk): Likewise. * config/tilegx/tilegx.c (tilegx_output_mi_thunk): Likewise. * config/tilepro/tilepro.c (tilepro_asm_output_mi_thunk): Likewise. --- gcc/config/aarch64/aarch64.c | 2 +- gcc/config/alpha/alpha.c | 2 +- gcc/config/arm/arm.c | 5 +++-- gcc/config/cris/cris.c | 3 ++- gcc/config/i386/i386.c | 5 +++-- gcc/config/ia64/ia64.c | 2 +- gcc/config/m68k/m68k.c | 2 +- gcc/config/microblaze/microblaze.c | 2 +- gcc/config/mips/mips.c | 2 +- gcc/config/nds32/nds32.c | 3 ++- gcc/config/nios2/nios2.c | 2 +- gcc/config/pa/pa.c | 3 ++- gcc/config/rs6000/rs6000.c | 5 +++-- gcc/config/s390/s390.c | 3 ++- gcc/config/sh/sh.c | 2 +- gcc/config/sparc/sparc.c | 2 +- gcc/config/spu/spu.c | 3 ++- gcc/config/tilegx/tilegx.c | 2 +- gcc/config/tilepro/tilepro.c | 2 +- gcc/final.c | 9 ++++++--- gcc/output.h | 2 +- 21 files changed, 37 insertions(+), 26 deletions(-) diff --git a/gcc/config/aarch64/aarch64.c b/gcc/config/aarch64/aarch64.c index 23f5aff..73872dd 100644 --- a/gcc/config/aarch64/aarch64.c +++ b/gcc/config/aarch64/aarch64.c @@ -3961,7 +3961,7 @@ aarch64_output_mi_thunk (FILE *file, tree thunk ATTRIBUTE_UNUSED, insn = get_insns (); shorten_branches (insn); - final_start_function (insn, file, 1); + final_start_function (&insn, file, 1); final (insn, file, 1); final_end_function (); diff --git a/gcc/config/alpha/alpha.c b/gcc/config/alpha/alpha.c index 41f3e3a..56b6f04 100644 --- a/gcc/config/alpha/alpha.c +++ b/gcc/config/alpha/alpha.c @@ -8480,7 +8480,7 @@ alpha_output_mi_thunk_osf (FILE *file, tree thunk_fndecl ATTRIBUTE_UNUSED, assemble_start_function and assemble_end_function. */ insn = get_insns (); shorten_branches (insn); - final_start_function (insn, file, 1); + final_start_function (&insn, file, 1); final (insn, file, 1); final_end_function (); } diff --git a/gcc/config/arm/arm.c b/gcc/config/arm/arm.c index 4cddf3b..9301d58 100644 --- a/gcc/config/arm/arm.c +++ b/gcc/config/arm/arm.c @@ -26410,7 +26410,8 @@ arm_thumb1_mi_thunk (FILE *file, tree, HOST_WIDE_INT delta, if (mi_delta < 0) mi_delta = - mi_delta; - final_start_function (emit_barrier (), file, 1); + rtx_insn *first = emit_barrier (); + final_start_function (&first, file, 1); if (TARGET_THUMB1) { @@ -26587,7 +26588,7 @@ arm32_output_mi_thunk (FILE *file, tree, HOST_WIDE_INT delta, insn = get_insns (); shorten_branches (insn); - final_start_function (insn, file, 1); + final_start_function (&insn, file, 1); final (insn, file, 1); final_end_function (); diff --git a/gcc/config/cris/cris.c b/gcc/config/cris/cris.c index fe80a27..3581d2d 100644 --- a/gcc/config/cris/cris.c +++ b/gcc/config/cris/cris.c @@ -2755,7 +2755,8 @@ cris_asm_output_mi_thunk (FILE *stream, tree funcdecl) { /* Make sure unwind info is emitted for the thunk if needed. */ - final_start_function (emit_barrier (), stream, 1); + rtx_insn *first = emit_barrier (); + final_start_function (&first, stream, 1); if (delta > 0) fprintf (stream, "\tadd%s " HOST_WIDE_INT_PRINT_DEC ",$%s\n", diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c index 98fb1ce..d4d9490 100644 --- a/gcc/config/i386/i386.c +++ b/gcc/config/i386/i386.c @@ -12499,8 +12499,9 @@ ix86_code_end (void) emitting it directly; tell them we're a thunk, if they care. */ cfun->is_thunk = true; first_function_block_is_cold = false; + rtx_insn *first = emit_barrier (); /* Make sure unwind info is emitted for the thunk if needed. */ - final_start_function (emit_barrier (), asm_out_file, 1); + final_start_function (&first, asm_out_file, 1); /* Pad stack IP move with 4 instructions (two NOPs count as one instruction). */ @@ -43001,7 +43002,7 @@ x86_output_mi_thunk (FILE *file, tree, HOST_WIDE_INT delta, Note that use_thunk calls assemble_start_function et al. */ insn = get_insns (); shorten_branches (insn); - final_start_function (insn, file, 1); + final_start_function (&insn, file, 1); final (insn, file, 1); final_end_function (); } diff --git a/gcc/config/ia64/ia64.c b/gcc/config/ia64/ia64.c index fce3006..a94ab67 100644 --- a/gcc/config/ia64/ia64.c +++ b/gcc/config/ia64/ia64.c @@ -11035,7 +11035,7 @@ ia64_output_mi_thunk (FILE *file, tree thunk ATTRIBUTE_UNUSED, emit_all_insn_group_barriers (NULL); insn = get_insns (); shorten_branches (insn); - final_start_function (insn, file, 1); + final_start_function (&insn, file, 1); final (insn, file, 1); final_end_function (); diff --git a/gcc/config/m68k/m68k.c b/gcc/config/m68k/m68k.c index cd2e15e..48b9c4a 100644 --- a/gcc/config/m68k/m68k.c +++ b/gcc/config/m68k/m68k.c @@ -5142,7 +5142,7 @@ m68k_output_mi_thunk (FILE *file, tree thunk ATTRIBUTE_UNUSED, /* Run just enough of rest_of_compilation. */ insn = get_insns (); split_all_insns_noflow (); - final_start_function (insn, file, 1); + final_start_function (&insn, file, 1); final (insn, file, 1); final_end_function (); diff --git a/gcc/config/microblaze/microblaze.c b/gcc/config/microblaze/microblaze.c index 53ca016..4ebe023 100644 --- a/gcc/config/microblaze/microblaze.c +++ b/gcc/config/microblaze/microblaze.c @@ -3257,7 +3257,7 @@ microblaze_asm_output_mi_thunk (FILE *file, tree thunk_fndecl ATTRIBUTE_UNUSED, "borrowed" from rs6000.c. */ insn = get_insns (); shorten_branches (insn); - final_start_function (insn, file, 1); + final_start_function (&insn, file, 1); final (insn, file, 1); final_end_function (); diff --git a/gcc/config/mips/mips.c b/gcc/config/mips/mips.c index 4133375..d1f7bd8 100644 --- a/gcc/config/mips/mips.c +++ b/gcc/config/mips/mips.c @@ -19394,7 +19394,7 @@ mips_output_mi_thunk (FILE *file, tree thunk_fndecl ATTRIBUTE_UNUSED, split_all_insns_noflow (); mips16_lay_out_constants (true); shorten_branches (insn); - final_start_function (insn, file, 1); + final_start_function (&insn, file, 1); final (insn, file, 1); final_end_function (); diff --git a/gcc/config/nds32/nds32.c b/gcc/config/nds32/nds32.c index 65095ff..f6d5f06 100644 --- a/gcc/config/nds32/nds32.c +++ b/gcc/config/nds32/nds32.c @@ -1633,7 +1633,8 @@ nds32_asm_output_mi_thunk (FILE *file, tree thunk ATTRIBUTE_UNUSED, int this_regno; /* Make sure unwind info is emitted for the thunk if needed. */ - final_start_function (emit_barrier (), file, 1); + rtx_insn *first = emit_barrier (); + final_start_function (&first, file, 1); this_regno = (aggregate_value_p (TREE_TYPE (TREE_TYPE (function)), function) ? 1 diff --git a/gcc/config/nios2/nios2.c b/gcc/config/nios2/nios2.c index 2602605..6ab2c24 100644 --- a/gcc/config/nios2/nios2.c +++ b/gcc/config/nios2/nios2.c @@ -4061,7 +4061,7 @@ nios2_asm_output_mi_thunk (FILE *file, tree thunk_fndecl ATTRIBUTE_UNUSED, assemble_start_function and assemble_end_function. */ insn = get_insns (); shorten_branches (insn); - final_start_function (insn, file, 1); + final_start_function (&insn, file, 1); final (insn, file, 1); final_end_function (); diff --git a/gcc/config/pa/pa.c b/gcc/config/pa/pa.c index 5e945fc..418a017 100644 --- a/gcc/config/pa/pa.c +++ b/gcc/config/pa/pa.c @@ -8404,7 +8404,8 @@ pa_asm_output_mi_thunk (FILE *file, tree thunk_fndecl, HOST_WIDE_INT delta, xoperands[1] = XEXP (DECL_RTL (thunk_fndecl), 0); xoperands[2] = GEN_INT (delta); - final_start_function (emit_barrier (), file, 1); + rtx_insn *first = emit_barrier (); + final_start_function (&first, file, 1); /* Output the thunk. We know that the function is in the same translation unit (i.e., the same space) as the thunk, and that diff --git a/gcc/config/rs6000/rs6000.c b/gcc/config/rs6000/rs6000.c index 1e794a0..cf1a7bf 100644 --- a/gcc/config/rs6000/rs6000.c +++ b/gcc/config/rs6000/rs6000.c @@ -29699,7 +29699,7 @@ rs6000_output_mi_thunk (FILE *file, tree thunk_fndecl ATTRIBUTE_UNUSED, assemble_start_function and assemble_end_function. */ insn = get_insns (); shorten_branches (insn); - final_start_function (insn, file, 1); + final_start_function (&insn, file, 1); final (insn, file, 1); final_end_function (); @@ -38165,7 +38165,8 @@ rs6000_code_end (void) init_function_start (decl); first_function_block_is_cold = false; /* Make sure unwind info is emitted for the thunk if needed. */ - final_start_function (emit_barrier (), asm_out_file, 1); + rtx_insn *first = emit_barrier (); + final_start_function (&first, asm_out_file, 1); fputs ("\tblr\n", asm_out_file); diff --git a/gcc/config/s390/s390.c b/gcc/config/s390/s390.c index 52a82df..0bea709 100644 --- a/gcc/config/s390/s390.c +++ b/gcc/config/s390/s390.c @@ -13202,7 +13202,8 @@ s390_output_mi_thunk (FILE *file, tree thunk ATTRIBUTE_UNUSED, int nonlocal = 0; /* Make sure unwind info is emitted for the thunk if needed. */ - final_start_function (emit_barrier (), file, 1); + rtx_insn *first = emit_barrier (); + final_start_function (&first, file, 1); /* Operand 0 is the target function. */ op[0] = XEXP (DECL_RTL (function), 0); diff --git a/gcc/config/sh/sh.c b/gcc/config/sh/sh.c index 3c6d525..284fb81 100644 --- a/gcc/config/sh/sh.c +++ b/gcc/config/sh/sh.c @@ -10936,7 +10936,7 @@ sh_output_mi_thunk (FILE *file, tree thunk_fndecl ATTRIBUTE_UNUSED, sh_reorg (); shorten_branches (insns); - final_start_function (insns, file, 1); + final_start_function (&insns, file, 1); final (insns, file, 1); final_end_function (); diff --git a/gcc/config/sparc/sparc.c b/gcc/config/sparc/sparc.c index d3f002d..9432a66 100644 --- a/gcc/config/sparc/sparc.c +++ b/gcc/config/sparc/sparc.c @@ -12140,7 +12140,7 @@ sparc_output_mi_thunk (FILE *file, tree thunk_fndecl ATTRIBUTE_UNUSED, assemble_start_function and assemble_end_function. */ insn = get_insns (); shorten_branches (insn); - final_start_function (insn, file, 1); + final_start_function (&insn, file, 1); final (insn, file, 1); final_end_function (); diff --git a/gcc/config/spu/spu.c b/gcc/config/spu/spu.c index b9af9a9..d22cf3e 100644 --- a/gcc/config/spu/spu.c +++ b/gcc/config/spu/spu.c @@ -7045,7 +7045,8 @@ spu_output_mi_thunk (FILE *file, tree thunk ATTRIBUTE_UNUSED, rtx op[8]; /* Make sure unwind info is emitted for the thunk if needed. */ - final_start_function (emit_barrier (), file, 1); + rtx_insn *insn = emit_barrier (); + final_start_function (&insn, file, 1); /* Operand 0 is the target function. */ op[0] = XEXP (DECL_RTL (function), 0); diff --git a/gcc/config/tilegx/tilegx.c b/gcc/config/tilegx/tilegx.c index 63fe340..861577eca 100644 --- a/gcc/config/tilegx/tilegx.c +++ b/gcc/config/tilegx/tilegx.c @@ -4998,7 +4998,7 @@ tilegx_output_mi_thunk (FILE *file, tree thunk_fndecl ATTRIBUTE_UNUSED, */ insn = get_insns (); shorten_branches (insn); - final_start_function (insn, file, 1); + final_start_function (&insn, file, 1); final (insn, file, 1); final_end_function (); diff --git a/gcc/config/tilepro/tilepro.c b/gcc/config/tilepro/tilepro.c index ee9bc0a..e261400 100644 --- a/gcc/config/tilepro/tilepro.c +++ b/gcc/config/tilepro/tilepro.c @@ -4421,7 +4421,7 @@ tilepro_asm_output_mi_thunk (FILE *file, tree thunk_fndecl ATTRIBUTE_UNUSED, */ insn = get_insns (); shorten_branches (insn); - final_start_function (insn, file, 1); + final_start_function (&insn, file, 1); final (insn, file, 1); final_end_function (); diff --git a/gcc/final.c b/gcc/final.c index 49cfbfb..d2b8523d 100644 --- a/gcc/final.c +++ b/gcc/final.c @@ -1763,9 +1763,11 @@ get_some_local_dynamic_name () test and compare insns. */ void -final_start_function (rtx_insn *first, FILE *file, +final_start_function (rtx_insn **firstp, FILE *file, int optimize_p ATTRIBUTE_UNUSED) { + rtx_insn *first = *firstp; + block_depth = 0; this_is_asm_operands = 0; @@ -4536,8 +4538,9 @@ rest_of_handle_final (void) variable_tracking_main (); assemble_start_function (current_function_decl, fnname); - final_start_function (get_insns (), asm_out_file, optimize); - final (get_insns (), asm_out_file, optimize); + rtx_insn *first = get_insns (); + final_start_function (&first, asm_out_file, optimize); + final (first, asm_out_file, optimize); if (flag_ipa_ra && !lookup_attribute ("noipa", DECL_ATTRIBUTES (current_function_decl))) collect_fn_hard_reg_usage (); diff --git a/gcc/output.h b/gcc/output.h index e98a911..62a405d 100644 --- a/gcc/output.h +++ b/gcc/output.h @@ -59,7 +59,7 @@ const char *get_some_local_dynamic_name (); for the new function. The label for the function and associated assembler pseudo-ops have already been output in `assemble_start_function'. */ -extern void final_start_function (rtx_insn *, FILE *, int); +extern void final_start_function (rtx_insn **, FILE *, int); /* Output assembler code for the end of a function. For clarity, args are same as those of `final_start_function' From patchwork Sat Sep 30 09:08:25 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Alexandre Oliva X-Patchwork-Id: 820197 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (mailfrom) smtp.mailfrom=gcc.gnu.org (client-ip=209.132.180.131; helo=sourceware.org; envelope-from=gcc-patches-return-463268-incoming=patchwork.ozlabs.org@gcc.gnu.org; receiver=) Authentication-Results: ozlabs.org; dkim=pass (1024-bit key; unprotected) header.d=gcc.gnu.org header.i=@gcc.gnu.org header.b="kdVjR5a5"; dkim-atps=neutral Received: from sourceware.org (server1.sourceware.org [209.132.180.131]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 3y42lf6tKGz9t2h for ; Sat, 30 Sep 2017 19:13:18 +1000 (AEST) DomainKey-Signature: a=rsa-sha1; c=nofws; d=gcc.gnu.org; h=list-id :list-unsubscribe:list-archive:list-post:list-help:sender:from :to:cc:subject:date:message-id:in-reply-to:references; q=dns; s= default; b=YV4KnTIvFFyefqF9zFkSuT75wkrYClSvDQd6OVOunkNJ0A3Ag06sf EdzOTZT6P/d2Xm1u7gC6iQTRJWIjcNxz4hR8/TDdRochoMv6pR2RJlj2N8KZuwgt U1SzFHUsCfQQ40Zzx+VZQufFrb26Fwjomt8EvV9mg4b1TQTfuBmuPs= DKIM-Signature: v=1; a=rsa-sha1; c=relaxed; d=gcc.gnu.org; h=list-id :list-unsubscribe:list-archive:list-post:list-help:sender:from :to:cc:subject:date:message-id:in-reply-to:references; s= default; bh=F5WUAR7t+1/kVAei/CYnujh1nig=; b=kdVjR5a5lu/2GG6ROp3N srfG8qtzsT8K/OQlDiof5PPmYXa44N9o7lmFqyvQriG223nGPu4wkgcum5RG0t+Q mwYMFQ7lnFv6+OEZtdZaiZI0gylO2kgc3Wv6B+hau8Htld+00kiFuV85PwA3ABoQ k4uFiiSjP2fWQt0DWnYAX2Q= Received: (qmail 66584 invoked by alias); 30 Sep 2017 09:10:18 -0000 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 Received: (qmail 66535 invoked by uid 89); 30 Sep 2017 09:10:18 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-25.9 required=5.0 tests=BAYES_00, GIT_PATCH_0, GIT_PATCH_1, GIT_PATCH_2, GIT_PATCH_3, KAM_LAZY_DOMAIN_SECURITY, RP_MATCHES_RCVD, SPF_HELO_PASS autolearn=ham version=3.3.2 spammy= X-HELO: mx1.redhat.com Received: from mx1.redhat.com (HELO mx1.redhat.com) (209.132.183.28) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Sat, 30 Sep 2017 09:10:06 +0000 Received: from smtp.corp.redhat.com (int-mx01.intmail.prod.int.phx2.redhat.com [10.5.11.11]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 842C481DE6; Sat, 30 Sep 2017 09:10:04 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.3.2 mx1.redhat.com 842C481DE6 Authentication-Results: ext-mx01.extmail.prod.ext.phx2.redhat.com; dmarc=none (p=none dis=none) header.from=redhat.com Authentication-Results: ext-mx01.extmail.prod.ext.phx2.redhat.com; spf=fail smtp.mailfrom=aoliva@redhat.com Received: from freie.home (ovpn04.gateway.prod.ext.phx2.redhat.com [10.5.9.4]) by smtp.corp.redhat.com (Postfix) with ESMTPS id F05E2197F3; Sat, 30 Sep 2017 09:10:02 +0000 (UTC) Received: from frit.home (frit.home [172.31.160.7]) by freie.home (8.15.2/8.15.2) with ESMTP id v8U98pIY022010; Sat, 30 Sep 2017 06:09:29 -0300 From: Alexandre Oliva To: Richard Biener Cc: GCC Patches , Alexandre Oliva Subject: [PATCH 7/9] [LVU] Introduce location views Date: Sat, 30 Sep 2017 06:08:25 -0300 Message-Id: <20170930090827.6604-7-aoliva@redhat.com> In-Reply-To: References: This patch introduces an option to enable the generation of location views along with location lists. The exact format depends on the DWARF version: it can be a separate attribute (DW_AT_GNU_locviews) or (DW_LLE_view_pair) entries in DWARF5+ loclists. Line number tables are also affected. If the assembler is found, at compiler build time, to support .loc views, we use them and assembler-computed view labels, otherwise we output compiler-generated line number programs with conservatively-computed view labels. In either case, we output view information next to line number changes when verbose assembly output is requested. This patch requires an LVU patch that modifies the exported API of final_scan_insn. It also expects the entire SFN patchset to be installed first, although SFN is not a requirement for LVU. for include/ChangeLog * dwarf2.def (DW_AT_GNU_locviews): New. * dwarf2.h (enum dwarf_location_list_entry_type): Add DW_LLE_GNU_view_pair. (DW_LLE_view_pair): Define. for gcc/ChangeLog * common.opt (gvariable-location-views): New. * config.in: Rebuilt. * configure: Rebuilt. * configure.ac: Test assembler for view support. * dwarf2asm.c (dw2_asm_output_symname_uleb128): New. * dwarf2asm.h (dw2_asm_output_symname_uleb128): Declare. * dwarf2out.c (var_loc_view): New typedef. (struct dw_loc_list_struct): Add vl_symbol, vbegin, vend. (dwarf2out_locviews_in_attribute): New. (dwarf2out_locviews_in_loclist): New. (dw_val_equal_p): Compare val_view_list of dw_val_class_view_lists. (enum dw_line_info_opcode): Add LI_adv_address. (struct dw_line_info_table): Add view. (RESET_NEXT_VIEW, RESETTING_VIEW_P): New macros. (DWARF2_ASM_VIEW_DEBUG_INFO): Define default. (zero_view_p): New variable. (ZERO_VIEW_P): New macro. (output_asm_line_debug_info): New. (struct var_loc_node): Add view. (add_AT_view_list, AT_loc_list): New. (add_var_loc_to_decl): Add view param. Test it against last. (new_loc_list): Add view params. Record them. (AT_loc_list_ptr): Handle loc and view lists. (view_list_to_loc_list_val_node): New. (print_dw_val): Handle dw_val_class_view_list. (size_of_die): Likewise. (value_format): Likewise. (loc_list_has_views): New. (gen_llsym): Set vl_symbol too. (maybe_gen_llsym, skip_loc_list_entry): New. (dwarf2out_maybe_output_loclist_view_pair): New. (output_loc_list): Output view list or entries too. (output_view_list_offset): New. (output_die): Handle dw_val_class_view_list. (output_dwarf_version): New. (output_compilation_unit_header): Use it. (output_skeleton_debug_sections): Likewise. (output_rnglists, output_line_info): Likewise. (output_pubnames, output_aranges): Update version comments. (output_one_line_info_table): Output view numbers in asm comments. (dw_loc_list): Determine current endview, pass it to new_loc_list. Call maybe_gen_llsym. (loc_list_from_tree_1): Adjust. (add_AT_location_description): Create view list attribute if needed, check it's absent otherwise. (convert_cfa_to_fb_loc_list): Adjust. (maybe_emit_file): Call output_asm_line_debug_info for test. (dwarf2out_var_location): Reset views as needed. Precompute add_var_loc_to_decl args. Call get_attr_min_length only if we have the attribute. Set view. (new_line_info_table): Reset next view. (set_cur_line_info_table): Call output_asm_line_debug_info for test. (dwarf2out_source_line): Likewise. Output view resets and labels to the assembler, or select appropriate line info opcodes. (prune_unused_types_walk_attribs): Handle dw_val_class_view_list. (optimize_string_length): Catch it. Adjust. (resolve_addr): Copy vl_symbol along with ll_symbol. Handle dw_val_class_view_list, and remove it if no longer needed. (hash_loc_list): Hash view numbers. (loc_list_hasher::equal): Compare them. (optimize_location_lists): Check whether a view list symbol is needed, and whether the locview attribute is present, and whether they match. Remove the locview attribute if no longer needed. (index_location_lists): Call skip_loc_list_entry for test. (dwarf2out_finish): Call output_asm_line_debug_info for test. Use output_dwarf_version. * dwarf2out.h (enum dw_val_class): Add dw_val_class_view_list. (struct dw_val_node): Add val_view_list. * final.c: Include langhooks.h. (SEEN_NEXT_VIEW): New. (set_next_view_needed): New. (clear_next_view_needed): New. (maybe_output_next_view): New. (final_start_function): Rename to... (final_start_function_1): ... this. Take pointer to FIRST, add SEEN parameter. Emit param bindings in the initial view. (final_start_function): Reintroduce SEEN-less interface. (final): Rename to... (final_1): ... this. Take SEEN parameter. Output final pending next view at the end. (final): Reintroduce seen-less interface. (final_scan_insn): Output pending next view before switching sections or ending a block. Mark the next view as needed when outputting variable locations. Notify debug backend of section changes, and of location view changes. (rest_of_handle_final): Adjust. * opts.c (common_handle_option): Accept -gdwarf version 6. * toplev.c (process_options): Autodetect value for debug variable location views option. * doc/invoke.texi (gvariable-location-views): New. (gno-variable-location-views): New. --- gcc/common.opt | 4 + gcc/config.in | 6 + gcc/configure | 46 ++++ gcc/configure.ac | 18 +- gcc/doc/invoke.texi | 19 ++ gcc/dwarf2asm.c | 25 ++ gcc/dwarf2asm.h | 4 + gcc/dwarf2out.c | 646 ++++++++++++++++++++++++++++++++++++++++++++++------ gcc/dwarf2out.h | 4 +- gcc/final.c | 125 +++++++++- gcc/opts.c | 2 +- gcc/toplev.c | 8 + include/dwarf2.def | 1 + include/dwarf2.h | 8 + 14 files changed, 834 insertions(+), 82 deletions(-) diff --git a/gcc/common.opt b/gcc/common.opt index a12c11c..5bfcd4b 100644 --- a/gcc/common.opt +++ b/gcc/common.opt @@ -2901,6 +2901,10 @@ gtoggle Common Driver Report Var(flag_gtoggle) Toggle debug information generation. +gvariable-location-views +Common Driver Var(debug_variable_location_views) Init(2) +Augment variable location lists with progressive views. + gvms Common Driver JoinedOrMissing Negative(gxcoff) Generate debug information in VMS format. diff --git a/gcc/config.in b/gcc/config.in index 89d7108..8c33967 100644 --- a/gcc/config.in +++ b/gcc/config.in @@ -358,6 +358,12 @@ #endif +/* Define if your assembler supports views in dwarf2 .loc directives. */ +#ifndef USED_FOR_TARGET +#undef HAVE_AS_DWARF2_DEBUG_VIEW +#endif + + /* Define if your assembler supports the R_PPC64_ENTRY relocation. */ #ifndef USED_FOR_TARGET #undef HAVE_AS_ENTRY_MARKERS diff --git a/gcc/configure b/gcc/configure index 13f97cd..6484f6a 100755 --- a/gcc/configure +++ b/gcc/configure @@ -27756,6 +27756,52 @@ $as_echo "$gcc_cv_as_dwarf2_file_buggy" >&6; } $as_echo "#define HAVE_AS_DWARF2_DEBUG_LINE 1" >>confdefs.h + + if test $gcc_cv_as_leb128 = yes; then + conftest_s="\ + .file 1 \"conftest.s\" + .loc 1 3 0 view .LVU1 + $insn + .data + .uleb128 .LVU1 + .uleb128 .LVU1 +" + { $as_echo "$as_me:${as_lineno-$LINENO}: checking assembler for dwarf2 debug_view support" >&5 +$as_echo_n "checking assembler for dwarf2 debug_view support... " >&6; } +if test "${gcc_cv_as_dwarf2_debug_view+set}" = set; then : + $as_echo_n "(cached) " >&6 +else + gcc_cv_as_dwarf2_debug_view=no + if test $in_tree_gas = yes; then + if test $in_tree_gas_is_elf = yes \ + && test $gcc_cv_gas_vers -ge `expr \( \( 2 \* 1000 \) + 27 \) \* 1000 + 0` + then gcc_cv_as_dwarf2_debug_view=yes +fi + elif test x$gcc_cv_as != x; then + $as_echo "$conftest_s" > conftest.s + if { ac_try='$gcc_cv_as $gcc_cv_as_flags -o conftest.o conftest.s >&5' + { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_try\""; } >&5 + (eval $ac_try) 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; } + then + gcc_cv_as_dwarf2_debug_view=yes + else + echo "configure: failed program was" >&5 + cat conftest.s >&5 + fi + rm -f conftest.o conftest.s + fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $gcc_cv_as_dwarf2_debug_view" >&5 +$as_echo "$gcc_cv_as_dwarf2_debug_view" >&6; } +if test $gcc_cv_as_dwarf2_debug_view = yes; then + +$as_echo "#define HAVE_AS_DWARF2_DEBUG_VIEW 1" >>confdefs.h + +fi + fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking assembler for --gdwarf2 option" >&5 diff --git a/gcc/configure.ac b/gcc/configure.ac index 8271138..ba37496 100644 --- a/gcc/configure.ac +++ b/gcc/configure.ac @@ -4847,9 +4847,25 @@ if test x"$insn" != x; then if test $gcc_cv_as_dwarf2_debug_line = yes \ && test $gcc_cv_as_dwarf2_file_buggy = no; then - AC_DEFINE(HAVE_AS_DWARF2_DEBUG_LINE, 1, + AC_DEFINE(HAVE_AS_DWARF2_DEBUG_LINE, 1, [Define if your assembler supports dwarf2 .file/.loc directives, and preserves file table indices exactly as given.]) + + if test $gcc_cv_as_leb128 = yes; then + conftest_s="\ + .file 1 \"conftest.s\" + .loc 1 3 0 view .LVU1 + $insn + .data + .uleb128 .LVU1 + .uleb128 .LVU1 +" + gcc_GAS_CHECK_FEATURE([dwarf2 debug_view support], + gcc_cv_as_dwarf2_debug_view, + [elf,2,27,0],,[$conftest_s],, + [AC_DEFINE(HAVE_AS_DWARF2_DEBUG_VIEW, 1, + [Define if your assembler supports views in dwarf2 .loc directives.])]) + fi fi gcc_GAS_CHECK_FEATURE([--gdwarf2 option], diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi index 85e41e4..7fb40d5 100644 --- a/gcc/doc/invoke.texi +++ b/gcc/doc/invoke.texi @@ -347,6 +347,7 @@ Objective-C and Objective-C++ Dialects}. -gstabs -gstabs+ -gstrict-dwarf -gno-strict-dwarf @gol -gcolumn-info -gno-column-info @gol -gstatement-frontiers -gno-statement-frontiers @gol +-gvariable-location-views -gno-variable-location-views @gol -gvms -gxcoff -gxcoff+ -gz@r{[}=@var{type}@r{]} @gol -fdebug-prefix-map=@var{old}=@var{new} -fdebug-types-section @gol -fno-eliminate-unused-debug-types @gol @@ -7052,6 +7053,24 @@ markers in the line number table. This is enabled by default when compiling with optimization (@option{-Os}, @option{-O}, @option{-O2}, @dots{}), and outputting DWARF 2 debug information at the normal level. +@item -gvariable-location-views +@item -gno-variable-location-views +@opindex gvariable-location-views +@opindex gno-variable-location-views +Augment variable location lists with progressive view numbers implied +from the line number table. This enables debug information consumers to +inspect state at certain points of the program, even if no instructions +associated with the corresponding source locations are present at that +point. If the assembler lacks support for view numbers in line number +tables, this will cause the compiler to emit the line number table, +which generally makes them somewhat less compact. The augmented line +number tables and location lists are fully backward-compatible, so they +can be consumed by debug information consumers that are not aware of +these augmentations, but they won't derive any benefit from them either. +This is enabled by default when outputting DWARF 2 debug information at +the normal level, as long as @code{-fvar-tracking-assignments} is +enabled and @code{-gstrict-dwarf} is not. + @item -gz@r{[}=@var{type}@r{]} @opindex gz Produce compressed debug sections in DWARF format, if that is supported. diff --git a/gcc/dwarf2asm.c b/gcc/dwarf2asm.c index 8e3e86f..f19e6d6 100644 --- a/gcc/dwarf2asm.c +++ b/gcc/dwarf2asm.c @@ -768,6 +768,31 @@ dw2_asm_output_data_sleb128 (HOST_WIDE_INT value, } void +dw2_asm_output_symname_uleb128 (const char *lab1 ATTRIBUTE_UNUSED, + const char *comment, ...) +{ + va_list ap; + + va_start (ap, comment); + +#ifdef HAVE_AS_LEB128 + fputs ("\t.uleb128 ", asm_out_file); + assemble_name (asm_out_file, lab1); +#else + gcc_unreachable (); +#endif + + if (flag_debug_asm && comment) + { + fprintf (asm_out_file, "\t%s ", ASM_COMMENT_START); + vfprintf (asm_out_file, comment, ap); + } + fputc ('\n', asm_out_file); + + va_end (ap); +} + +void dw2_asm_output_delta_uleb128 (const char *lab1 ATTRIBUTE_UNUSED, const char *lab2 ATTRIBUTE_UNUSED, const char *comment, ...) diff --git a/gcc/dwarf2asm.h b/gcc/dwarf2asm.h index 7fc87a0..d8370df 100644 --- a/gcc/dwarf2asm.h +++ b/gcc/dwarf2asm.h @@ -70,6 +70,10 @@ extern void dw2_asm_output_data_sleb128 (HOST_WIDE_INT, const char *, ...) ATTRIBUTE_NULL_PRINTF_2; +extern void dw2_asm_output_symname_uleb128 (const char *, + const char *, ...) + ATTRIBUTE_NULL_PRINTF_2; + extern void dw2_asm_output_delta_uleb128 (const char *, const char *, const char *, ...) ATTRIBUTE_NULL_PRINTF_3; diff --git a/gcc/dwarf2out.c b/gcc/dwarf2out.c index f4e5947..6b19c4a 100644 --- a/gcc/dwarf2out.c +++ b/gcc/dwarf2out.c @@ -1276,6 +1276,8 @@ struct GTY((for_user)) addr_table_entry { GTY ((desc ("%1.kind"))) addr; }; +typedef unsigned int var_loc_view; + /* Location lists are ranges + location descriptions for that range, so you can track variables that are in different places over their entire life. */ @@ -1285,9 +1287,11 @@ typedef struct GTY(()) dw_loc_list_struct { addr_table_entry *begin_entry; const char *end; /* Label for end of range */ char *ll_symbol; /* Label for beginning of location list. - Only on head of list */ + Only on head of list. */ + char *vl_symbol; /* Label for beginning of view list. Ditto. */ const char *section; /* Section this loclist is relative to */ dw_loc_descr_ref expr; + var_loc_view vbegin, vend; hashval_t hash; /* True if all addresses in this and subsequent lists are known to be resolved. */ @@ -1324,6 +1328,31 @@ dwarf_stack_op_name (unsigned int op) return "OP_"; } +/* Return TRUE iff we're to output location view lists as a separate + attribute next to the location lists, as an extension compatible + with DWARF 2 and above. */ + +static inline bool +dwarf2out_locviews_in_attribute () +{ + return debug_variable_location_views + && dwarf_version <= 5; +} + +/* Return TRUE iff we're to output location view lists as part of the + location lists, as proposed for standardization after DWARF 5. */ + +static inline bool +dwarf2out_locviews_in_loclist () +{ +#ifndef DW_LLE_view_pair + return false; +#else + return debug_variable_location_views + && dwarf_version >= 6; +#endif +} + /* Return a pointer to a newly allocated location description. Location descriptions are simple expression terms that can be strung together to form more complicated location (address) descriptions. */ @@ -1399,6 +1428,8 @@ dw_val_equal_p (dw_val_node *a, dw_val_node *b) return a->v.val_loc == b->v.val_loc; case dw_val_class_loc_list: return a->v.val_loc_list == b->v.val_loc_list; + case dw_val_class_view_list: + return a->v.val_view_list == b->v.val_view_list; case dw_val_class_die_ref: return a->v.val_die_ref.die == b->v.val_die_ref.die; case dw_val_class_fde_ref: @@ -2844,7 +2875,15 @@ enum dw_line_info_opcode { LI_set_epilogue_begin, /* Emit a DW_LNE_set_discriminator. */ - LI_set_discriminator + LI_set_discriminator, + + /* Output a Fixed Advance PC; the target PC is the label index; the + base PC is the previous LI_adv_address or LI_set_address entry. + We only use this when emitting debug views without assembler + support, at explicit user request. Ideally, we should only use + it when the offset might be zero but we can't tell: it's the only + way to maybe change the PC without resetting the view number. */ + LI_adv_address }; typedef struct GTY(()) dw_line_info_struct { @@ -2866,6 +2905,25 @@ struct GTY(()) dw_line_info_table { bool is_stmt; bool in_use; + /* This denotes the NEXT view number. + + If it is 0, it is known that the NEXT view will be the first view + at the given PC. + + If it is -1, we've advanced PC but we haven't emitted a line location yet, + so we shouldn't use this view number. + + The meaning of other nonzero values depends on whether we're + computing views internally or leaving it for the assembler to do + so. If we're emitting them internally, view denotes the view + number since the last known advance of PC. If we're leaving it + for the assembler, it denotes the LVU label number that we're + going to ask the assembler to assign. */ + var_loc_view view; + +#define RESET_NEXT_VIEW(x) ((x) = (var_loc_view)0) +#define RESETTING_VIEW_P(x) ((x) == (var_loc_view)0) + vec *entries; }; @@ -3067,6 +3125,41 @@ skeleton_chain_node; #endif #endif +/* Use assembler views in line directives if available. */ +#ifndef DWARF2_ASM_VIEW_DEBUG_INFO +#ifdef HAVE_AS_DWARF2_DEBUG_VIEW +#define DWARF2_ASM_VIEW_DEBUG_INFO 1 +#else +#define DWARF2_ASM_VIEW_DEBUG_INFO 0 +#endif +#endif + +/* A bit is set in ZERO_VIEW_P if we are using the assembler-supported + view computation, and it is refers to a view identifier for which + will not emit a label because it is known to map to a view number + zero. We won't allocate the bitmap if we're not using assembler + support for location views, but we have to make the variable + visible for GGC and for code that will be optimized out for lack of + support but that's still parsed and compiled. We could abstract it + out with macros, but it's not worth it. */ +static GTY(()) bitmap zero_view_p; + +/* Evaluate to TRUE iff N is known to identify the first location view + at its PC. When not using assembler location view computation, + that must be view number zero. Otherwise, ZERO_VIEW_P is allocated + and views label numbers recorded in it are the ones known to be + zero. */ +#define ZERO_VIEW_P(N) (zero_view_p \ + ? bitmap_bit_p (zero_view_p, (N)) \ + : (N) == 0) + +static bool +output_asm_line_debug_info (void) +{ + return DWARF2_ASM_VIEW_DEBUG_INFO + || (DWARF2_ASM_LINE_DEBUG_INFO && !debug_variable_location_views); +} + /* Minimum line offset in a special line info. opcode. This value was chosen to give a reasonable range of values. */ #define DWARF_LINE_BASE -10 @@ -3176,6 +3269,7 @@ struct GTY ((chain_next ("%h.next"))) var_loc_node { rtx GTY (()) loc; const char * GTY (()) label; struct var_loc_node * GTY (()) next; + var_loc_view view; }; /* Variable location list. */ @@ -3384,6 +3478,8 @@ static inline dw_loc_descr_ref AT_loc (dw_attr_node *); static void add_AT_loc_list (dw_die_ref, enum dwarf_attribute, dw_loc_list_ref); static inline dw_loc_list_ref AT_loc_list (dw_attr_node *); +static void add_AT_view_list (dw_die_ref, enum dwarf_attribute); +static inline dw_loc_list_ref AT_loc_list (dw_attr_node *); static addr_table_entry *add_addr_table_entry (void *, enum ate_kind); static void remove_addr_table_entry (addr_table_entry *); static void add_AT_addr (dw_die_ref, enum dwarf_attribute, rtx, bool); @@ -3420,7 +3516,7 @@ static void equate_type_number_to_die (tree, dw_die_ref); static dw_die_ref lookup_decl_die (tree); static var_loc_list *lookup_decl_loc (const_tree); static void equate_decl_number_to_die (tree, dw_die_ref); -static struct var_loc_node *add_var_loc_to_decl (tree, rtx, const char *); +static struct var_loc_node *add_var_loc_to_decl (tree, rtx, const char *, var_loc_view); static void print_spaces (FILE *); static void print_die (dw_die_ref, FILE *); static void loc_checksum (dw_loc_descr_ref, struct md5_ctx *); @@ -3620,8 +3716,8 @@ static void gen_tagged_type_die (tree, dw_die_ref, enum debug_info_usage); static void gen_type_die_with_usage (tree, dw_die_ref, enum debug_info_usage); static void splice_child_die (dw_die_ref, dw_die_ref); static int file_info_cmp (const void *, const void *); -static dw_loc_list_ref new_loc_list (dw_loc_descr_ref, const char *, - const char *, const char *); +static dw_loc_list_ref new_loc_list (dw_loc_descr_ref, const char *, var_loc_view, + const char *, var_loc_view, const char *); static void output_loc_list (dw_loc_list_ref); static char *gen_internal_sym (const char *); static bool want_pubnames (void); @@ -4617,11 +4713,55 @@ AT_loc_list (dw_attr_node *a) return a->dw_attr_val.v.val_loc_list; } +static inline void +add_AT_view_list (dw_die_ref die, enum dwarf_attribute attr_kind) +{ + dw_attr_node attr; + + if (XCOFF_DEBUGGING_INFO && !HAVE_XCOFF_DWARF_EXTRAS) + return; + + attr.dw_attr = attr_kind; + attr.dw_attr_val.val_class = dw_val_class_view_list; + attr.dw_attr_val.val_entry = NULL; + attr.dw_attr_val.v.val_view_list = die; + add_dwarf_attr (die, &attr); + gcc_checking_assert (get_AT (die, DW_AT_location)); + gcc_assert (have_location_lists); +} + static inline dw_loc_list_ref * AT_loc_list_ptr (dw_attr_node *a) { - gcc_assert (a && AT_class (a) == dw_val_class_loc_list); - return &a->dw_attr_val.v.val_loc_list; + gcc_assert (a); + switch (AT_class (a)) + { + case dw_val_class_loc_list: + return &a->dw_attr_val.v.val_loc_list; + case dw_val_class_view_list: + { + dw_attr_node *l; + l = get_AT (a->dw_attr_val.v.val_view_list, DW_AT_location); + if (!l) + return NULL; + gcc_checking_assert (l + 1 == a); + return AT_loc_list_ptr (l); + } + default: + gcc_unreachable (); + } +} + +static inline dw_val_node * +view_list_to_loc_list_val_node (dw_val_node *val) +{ + gcc_assert (val->val_class == dw_val_class_view_list); + dw_attr_node *loc = get_AT (val->v.val_view_list, DW_AT_location); + if (!loc) + return NULL; + gcc_checking_assert (&(loc + 1)->dw_attr_val == val); + gcc_assert (AT_class (loc) == dw_val_class_loc_list); + return &loc->dw_attr_val; } struct addr_hasher : ggc_ptr_hash @@ -5884,7 +6024,7 @@ adjust_piece_list (rtx *dest, rtx *src, rtx *inner, /* Add a variable location node to the linked list for DECL. */ static struct var_loc_node * -add_var_loc_to_decl (tree decl, rtx loc_note, const char *label) +add_var_loc_to_decl (tree decl, rtx loc_note, const char *label, var_loc_view view) { unsigned int decl_id; var_loc_list *temp; @@ -5975,7 +6115,7 @@ add_var_loc_to_decl (tree decl, rtx loc_note, const char *label) /* TEMP->LAST here is either pointer to the last but one or last element in the chained list, LAST is pointer to the last element. */ - if (label && strcmp (last->label, label) == 0) + if (label && strcmp (last->label, label) == 0 && last->view == view) { /* For SRA optimized variables if there weren't any real insns since last note, just modify the last node. */ @@ -5991,7 +6131,7 @@ add_var_loc_to_decl (tree decl, rtx loc_note, const char *label) temp->last->next = NULL; unused = last; last = temp->last; - gcc_assert (strcmp (last->label, label) != 0); + gcc_assert (strcmp (last->label, label) != 0 || last->view != view); } else { @@ -6126,6 +6266,12 @@ print_dw_val (dw_val_node *val, bool recurse, FILE *outfile) fprintf (outfile, "location list -> label:%s", val->v.val_loc_list->ll_symbol); break; + case dw_val_class_view_list: + val = view_list_to_loc_list_val_node (val); + fprintf (outfile, "location list with views -> labels:%s and %s", + val->v.val_loc_list->ll_symbol, + val->v.val_loc_list->vl_symbol); + break; case dw_val_class_range_list: fprintf (outfile, "range list"); break; @@ -8990,6 +9136,7 @@ size_of_die (dw_die_ref die) } break; case dw_val_class_loc_list: + case dw_val_class_view_list: if (dwarf_split_debug_info && dwarf_version >= 5) { gcc_assert (AT_loc_list (a)->num_assigned); @@ -9361,6 +9508,7 @@ value_format (dw_attr_node *a) gcc_unreachable (); } case dw_val_class_loc_list: + case dw_val_class_view_list: if (dwarf_split_debug_info && dwarf_version >= 5 && AT_loc_list (a)->num_assigned) @@ -9635,7 +9783,8 @@ output_abbrev_section (void) expression. */ static inline dw_loc_list_ref -new_loc_list (dw_loc_descr_ref expr, const char *begin, const char *end, +new_loc_list (dw_loc_descr_ref expr, const char *begin, var_loc_view vbegin, + const char *end, var_loc_view vend, const char *section) { dw_loc_list_ref retlist = ggc_cleared_alloc (); @@ -9645,10 +9794,28 @@ new_loc_list (dw_loc_descr_ref expr, const char *begin, const char *end, retlist->end = end; retlist->expr = expr; retlist->section = section; + retlist->vbegin = vbegin; + retlist->vend = vend; return retlist; } +/* Return true iff there's any nonzero view number in the loc list. */ + +static bool +loc_list_has_views (dw_loc_list_ref list) +{ + if (!debug_variable_location_views) + return false; + + for (dw_loc_list_ref loc = list; + loc != NULL; loc = loc->dw_loc_next) + if (!ZERO_VIEW_P (loc->vbegin) || !ZERO_VIEW_P (loc->vend)) + return true; + + return false; +} + /* Generate a new internal symbol for this location list node, if it hasn't got one yet. */ @@ -9657,6 +9824,99 @@ gen_llsym (dw_loc_list_ref list) { gcc_assert (!list->ll_symbol); list->ll_symbol = gen_internal_sym ("LLST"); + + if (!loc_list_has_views (list)) + return; + + if (dwarf2out_locviews_in_attribute ()) + { + /* Use the same label_num for the view list. */ + label_num--; + list->vl_symbol = gen_internal_sym ("LVUS"); + } + else + list->vl_symbol = list->ll_symbol; +} + +/* Generate a symbol for the list, but only if we really want to emit + it as a list. */ + +static inline void +maybe_gen_llsym (dw_loc_list_ref list) +{ + if (!list || (!list->dw_loc_next && !loc_list_has_views (list))) + return; + + gen_llsym (list); +} + +/* Determine whether or not to skip loc_list entry CURR. If we're not + to skip it, and SIZEP is non-null, store the size of CURR->expr's + representation in *SIZEP. */ + +static bool +skip_loc_list_entry (dw_loc_list_ref curr, unsigned long *sizep = 0) +{ + /* Don't output an entry that starts and ends at the same address. */ + if (strcmp (curr->begin, curr->end) == 0 + && curr->vbegin == curr->vend && !curr->force) + return true; + + unsigned long size = size_of_locs (curr->expr); + + /* If the expression is too large, drop it on the floor. We could + perhaps put it into DW_TAG_dwarf_procedure and refer to that + in the expression, but >= 64KB expressions for a single value + in a single range are unlikely very useful. */ + if (dwarf_version < 5 && size > 0xffff) + return true; + + if (sizep) + *sizep = size; + + return false; +} + +/* Output a view pair loclist entry for CURR, if it requires one. */ + +static void +dwarf2out_maybe_output_loclist_view_pair (dw_loc_list_ref curr) +{ + if (!dwarf2out_locviews_in_loclist ()) + return; + + if (ZERO_VIEW_P (curr->vbegin) && ZERO_VIEW_P (curr->vend)) + return; + +#ifdef DW_LLE_view_pair + dw2_asm_output_data (1, DW_LLE_view_pair, + "DW_LLE_view_pair"); + +# if DWARF2_ASM_VIEW_DEBUG_INFO + if (ZERO_VIEW_P (curr->vbegin)) + dw2_asm_output_data_uleb128 (0, "Location view begin"); + else + { + char label[MAX_ARTIFICIAL_LABEL_BYTES]; + ASM_GENERATE_INTERNAL_LABEL (label, "LVU", curr->vbegin); + dw2_asm_output_symname_uleb128 (label, "Location view begin"); + } + + if (ZERO_VIEW_P (curr->vend)) + dw2_asm_output_data_uleb128 (0, "Location view end"); + else + { + char label[MAX_ARTIFICIAL_LABEL_BYTES]; + ASM_GENERATE_INTERNAL_LABEL (label, "LVU", curr->vend); + dw2_asm_output_symname_uleb128 (label, "Location view end"); + } +# else /* !DWARF2_ASM_VIEW_DEBUG_INFO */ + dw2_asm_output_data_uleb128 (curr->vbegin, "Location view begin"); + dw2_asm_output_data_uleb128 (curr->vend, "Location view end"); +# endif /* DWARF2_ASM_VIEW_DEBUG_INFO */ +#endif /* DW_LLE_view_pair */ + + return; } /* Output the location list given to us. */ @@ -9664,34 +9924,85 @@ gen_llsym (dw_loc_list_ref list) static void output_loc_list (dw_loc_list_ref list_head) { + int vcount = 0, lcount = 0; + if (list_head->emitted) return; list_head->emitted = true; + if (list_head->vl_symbol && dwarf2out_locviews_in_attribute ()) + { + ASM_OUTPUT_LABEL (asm_out_file, list_head->vl_symbol); + + for (dw_loc_list_ref curr = list_head; curr != NULL; + curr = curr->dw_loc_next) + { + if (skip_loc_list_entry (curr)) + continue; + + vcount++; + + /* ?? dwarf_split_debug_info? */ +#if DWARF2_ASM_VIEW_DEBUG_INFO + char label[MAX_ARTIFICIAL_LABEL_BYTES]; + + if (!ZERO_VIEW_P (curr->vbegin)) + { + ASM_GENERATE_INTERNAL_LABEL (label, "LVU", curr->vbegin); + dw2_asm_output_symname_uleb128 (label, + "View list begin (%s)", + list_head->vl_symbol); + } + else + dw2_asm_output_data_uleb128 (0, + "View list begin (%s)", + list_head->vl_symbol); + + if (!ZERO_VIEW_P (curr->vend)) + { + ASM_GENERATE_INTERNAL_LABEL (label, "LVU", curr->vend); + dw2_asm_output_symname_uleb128 (label, + "View list end (%s)", + list_head->vl_symbol); + } + else + dw2_asm_output_data_uleb128 (0, + "View list end (%s)", + list_head->vl_symbol); +#else /* !DWARF2_ASM_VIEW_DEBUG_INFO */ + dw2_asm_output_data_uleb128 (curr->vbegin, + "View list begin (%s)", + list_head->vl_symbol); + dw2_asm_output_data_uleb128 (curr->vend, + "View list end (%s)", + list_head->vl_symbol); +#endif + } + } + ASM_OUTPUT_LABEL (asm_out_file, list_head->ll_symbol); - dw_loc_list_ref curr = list_head; const char *last_section = NULL; const char *base_label = NULL; /* Walk the location list, and output each range + expression. */ - for (curr = list_head; curr != NULL; curr = curr->dw_loc_next) + for (dw_loc_list_ref curr = list_head; curr != NULL; + curr = curr->dw_loc_next) { unsigned long size; - /* Don't output an entry that starts and ends at the same address. */ - if (strcmp (curr->begin, curr->end) == 0 && !curr->force) - continue; - size = size_of_locs (curr->expr); - /* If the expression is too large, drop it on the floor. We could - perhaps put it into DW_TAG_dwarf_procedure and refer to that - in the expression, but >= 64KB expressions for a single value - in a single range are unlikely very useful. */ - if (dwarf_version < 5 && size > 0xffff) + + /* Skip this entry? If we skip it here, we must skip it in the + view list above as well. */ + if (skip_loc_list_entry (curr, &size)) continue; + + lcount++; + if (dwarf_version >= 5) { if (dwarf_split_debug_info) { + dwarf2out_maybe_output_loclist_view_pair (curr); /* For -gsplit-dwarf, emit DW_LLE_starx_length, which has uleb128 index into .debug_addr and uleb128 length. */ dw2_asm_output_data (1, DW_LLE_startx_length, @@ -9709,6 +10020,7 @@ output_loc_list (dw_loc_list_ref list_head) } else if (!have_multiple_function_sections && HAVE_AS_LEB128) { + dwarf2out_maybe_output_loclist_view_pair (curr); /* If all code is in .text section, the base address is already provided by the CU attributes. Use DW_LLE_offset_pair where both addresses are uleb128 encoded @@ -9759,6 +10071,7 @@ output_loc_list (dw_loc_list_ref list_head) length. */ if (last_section == NULL) { + dwarf2out_maybe_output_loclist_view_pair (curr); dw2_asm_output_data (1, DW_LLE_start_length, "DW_LLE_start_length (%s)", list_head->ll_symbol); @@ -9773,6 +10086,7 @@ output_loc_list (dw_loc_list_ref list_head) DW_LLE_base_address. */ else { + dwarf2out_maybe_output_loclist_view_pair (curr); dw2_asm_output_data (1, DW_LLE_offset_pair, "DW_LLE_offset_pair (%s)", list_head->ll_symbol); @@ -9788,6 +10102,7 @@ output_loc_list (dw_loc_list_ref list_head) DW_LLE_start_end with a pair of absolute addresses. */ else { + dwarf2out_maybe_output_loclist_view_pair (curr); dw2_asm_output_data (1, DW_LLE_start_end, "DW_LLE_start_end (%s)", list_head->ll_symbol); @@ -9866,6 +10181,9 @@ output_loc_list (dw_loc_list_ref list_head) "Location list terminator end (%s)", list_head->ll_symbol); } + + gcc_assert (!list_head->vl_symbol + || vcount == lcount * (dwarf2out_locviews_in_attribute () ? 1 : 0)); } /* Output a range_list offset into the .debug_ranges or .debug_rnglists @@ -9930,6 +10248,22 @@ output_loc_list_offset (dw_attr_node *a) "%s", dwarf_attr_name (a->dw_attr)); } +/* Output the offset into the debug_loc section. */ + +static void +output_view_list_offset (dw_attr_node *a) +{ + char *sym = (*AT_loc_list_ptr (a))->vl_symbol; + + gcc_assert (sym); + if (dwarf_split_debug_info) + dw2_asm_output_delta (DWARF_OFFSET_SIZE, sym, loc_section_label, + "%s", dwarf_attr_name (a->dw_attr)); + else + dw2_asm_output_offset (DWARF_OFFSET_SIZE, sym, debug_loc_section, + "%s", dwarf_attr_name (a->dw_attr)); +} + /* Output an attribute's index or value appropriately. */ static void @@ -10155,6 +10489,10 @@ output_die (dw_die_ref die) output_loc_list_offset (a); break; + case dw_val_class_view_list: + output_view_list_offset (a); + break; + case dw_val_class_die_ref: if (AT_ref_external (a)) { @@ -10339,6 +10677,28 @@ output_die (dw_die_ref die) (unsigned long) die->die_offset); } +/* Output the dwarf version number. */ + +static void +output_dwarf_version () +{ + /* ??? For now, if -gdwarf-6 is specified, we output version 5 with + views in loclist. That will change eventually. */ + if (dwarf_version == 6) + { + static bool once; + if (!once) + { + warning (0, + "-gdwarf-6 is output as version 5 with incompatibilities"); + once = true; + } + dw2_asm_output_data (2, 5, "DWARF version number"); + } + else + dw2_asm_output_data (2, dwarf_version, "DWARF version number"); +} + /* Output the compilation unit that appears at the beginning of the .debug_info section, and precedes the DIE descriptions. */ @@ -10355,7 +10715,7 @@ output_compilation_unit_header (enum dwarf_unit_type ut) "Length of Compilation Unit Info"); } - dw2_asm_output_data (2, dwarf_version, "DWARF version number"); + output_dwarf_version (); if (dwarf_version >= 5) { const char *name; @@ -10567,7 +10927,7 @@ output_skeleton_debug_sections (dw_die_ref comp_unit, - DWARF_INITIAL_LENGTH_SIZE + size_of_die (comp_unit), "Length of Compilation Unit Info"); - dw2_asm_output_data (2, dwarf_version, "DWARF version number"); + output_dwarf_version (); if (dwarf_version >= 5) { dw2_asm_output_data (1, DW_UT_skeleton, "DW_UT_skeleton"); @@ -10866,7 +11226,7 @@ output_pubnames (vec *names) } /* Version number for pubnames/pubtypes is independent of dwarf version. */ - dw2_asm_output_data (2, 2, "DWARF Version"); + dw2_asm_output_data (2, 2, "DWARF pubnames/pubtypes version"); if (dwarf_split_debug_info) dw2_asm_output_offset (DWARF_OFFSET_SIZE, debug_skeleton_info_section_label, @@ -10948,7 +11308,7 @@ output_aranges (void) } /* Version number for aranges is still 2, even up to DWARF5. */ - dw2_asm_output_data (2, 2, "DWARF Version"); + dw2_asm_output_data (2, 2, "DWARF aranges version"); if (dwarf_split_debug_info) dw2_asm_output_offset (DWARF_OFFSET_SIZE, debug_skeleton_info_section_label, debug_skeleton_info_section, @@ -11209,7 +11569,7 @@ output_rnglists (void) dw2_asm_output_delta (DWARF_OFFSET_SIZE, l2, l1, "Length of Range Lists"); ASM_OUTPUT_LABEL (asm_out_file, l1); - dw2_asm_output_data (2, dwarf_version, "DWARF Version"); + output_dwarf_version (); dw2_asm_output_data (1, DWARF2_ADDR_SIZE, "Address Size"); dw2_asm_output_data (1, 0, "Segment Size"); /* Emit the offset table only for -gsplit-dwarf. If we don't care @@ -11843,8 +12203,11 @@ output_one_line_info_table (dw_line_info_table *table) char line_label[MAX_ARTIFICIAL_LABEL_BYTES]; unsigned int current_line = 1; bool current_is_stmt = DWARF_LINE_DEFAULT_IS_STMT_START; - dw_line_info_entry *ent; + dw_line_info_entry *ent, *prev_addr; size_t i; + unsigned int view; + + view = 0; FOR_EACH_VEC_SAFE_ELT (table->entries, i, ent) { @@ -11859,14 +12222,36 @@ output_one_line_info_table (dw_line_info_table *table) to determine when it is safe to use DW_LNS_fixed_advance_pc. */ ASM_GENERATE_INTERNAL_LABEL (line_label, LINE_CODE_LABEL, ent->val); + view = 0; + /* This can handle any delta. This takes 4+DWARF2_ADDR_SIZE bytes. */ - dw2_asm_output_data (1, 0, "set address %s", line_label); + dw2_asm_output_data (1, 0, "set address %s%s", line_label, + debug_variable_location_views + ? ", reset view to 0" : ""); dw2_asm_output_data_uleb128 (1 + DWARF2_ADDR_SIZE, NULL); dw2_asm_output_data (1, DW_LNE_set_address, NULL); dw2_asm_output_addr (DWARF2_ADDR_SIZE, line_label, NULL); + + prev_addr = ent; break; + case LI_adv_address: + { + ASM_GENERATE_INTERNAL_LABEL (line_label, LINE_CODE_LABEL, ent->val); + char prev_label[MAX_ARTIFICIAL_LABEL_BYTES]; + ASM_GENERATE_INTERNAL_LABEL (prev_label, LINE_CODE_LABEL, prev_addr->val); + + view++; + + dw2_asm_output_data (1, DW_LNS_fixed_advance_pc, "fixed advance PC, increment view to %i", view); + dw2_asm_output_delta (2, line_label, prev_label, + "from %s to %s", prev_label, line_label); + + prev_addr = ent; + break; + } + case LI_set_line: if (ent->val == current_line) { @@ -11974,7 +12359,7 @@ output_line_info (bool prologue_only) ASM_OUTPUT_LABEL (asm_out_file, l1); - dw2_asm_output_data (2, dwarf_version, "DWARF Version"); + output_dwarf_version (); if (dwarf_version >= 5) { dw2_asm_output_data (1, DWARF2_ADDR_SIZE, "Address Size"); @@ -16298,6 +16683,7 @@ static dw_loc_list_ref dw_loc_list (var_loc_list *loc_list, tree decl, int want_address) { const char *endname, *secname; + var_loc_view endview; rtx varloc; enum var_init_status initialized; struct var_loc_node *node; @@ -16353,24 +16739,27 @@ dw_loc_list (var_loc_list *loc_list, tree decl, int want_address) && current_function_decl) { endname = cfun->fde->dw_fde_end; + endview = 0; range_across_switch = true; } /* The variable has a location between NODE->LABEL and NODE->NEXT->LABEL. */ else if (node->next) - endname = node->next->label; + endname = node->next->label, endview = node->next->view; /* If the variable has a location at the last label it keeps its location until the end of function. */ else if (!current_function_decl) - endname = text_end_label; + endname = text_end_label, endview = 0; else { ASM_GENERATE_INTERNAL_LABEL (label_id, FUNC_END_LABEL, current_function_funcdef_no); endname = ggc_strdup (label_id); + endview = 0; } - *listp = new_loc_list (descr, node->label, endname, secname); + *listp = new_loc_list (descr, node->label, node->view, + endname, endview, secname); if (TREE_CODE (decl) == PARM_DECL && node == loc_list->first && NOTE_P (node->loc) @@ -16393,12 +16782,12 @@ dw_loc_list (var_loc_list *loc_list, tree decl, int want_address) /* The variable has a location between NODE->LABEL and NODE->NEXT->LABEL. */ if (node->next) - endname = node->next->label; + endname = node->next->label, endview = node->next->view; else - endname = cfun->fde->dw_fde_second_end; + endname = cfun->fde->dw_fde_second_end, endview = 0; *listp = new_loc_list (descr, - cfun->fde->dw_fde_second_begin, - endname, secname); + cfun->fde->dw_fde_second_begin, 0, + endname, endview, secname); listp = &(*listp)->dw_loc_next; } } @@ -16410,8 +16799,7 @@ dw_loc_list (var_loc_list *loc_list, tree decl, int want_address) representable, we don't want to pretend a single entry that was applies to the entire scope in which the variable is available. */ - if (list && loc_list->first->next) - gen_llsym (list); + maybe_gen_llsym (list); return list; } @@ -17231,7 +17619,7 @@ loc_list_from_tree_1 (tree loc, int want_address, { if (dwarf_version >= 3 || !dwarf_strict) return new_loc_list (new_loc_descr (DW_OP_push_object_address, 0, 0), - NULL, NULL, NULL); + NULL, 0, NULL, 0, NULL); else return NULL; } @@ -18044,7 +18432,7 @@ loc_list_from_tree_1 (tree loc, int want_address, add_loc_descr_to_each (list_ret, new_loc_descr (op, size, 0)); } if (ret) - list_ret = new_loc_list (ret, NULL, NULL, NULL); + list_ret = new_loc_list (ret, NULL, 0, NULL, 0, NULL); return list_ret; } @@ -18368,12 +18756,25 @@ static inline void add_AT_location_description (dw_die_ref die, enum dwarf_attribute attr_kind, dw_loc_list_ref descr) { + bool check_no_locviews = true; if (descr == 0) return; if (single_element_loc_list_p (descr)) add_AT_loc (die, attr_kind, descr->expr); else - add_AT_loc_list (die, attr_kind, descr); + { + add_AT_loc_list (die, attr_kind, descr); + gcc_assert (descr->ll_symbol); + if (attr_kind == DW_AT_location && descr->vl_symbol + && dwarf2out_locviews_in_attribute ()) + { + add_AT_view_list (die, DW_AT_GNU_locviews); + check_no_locviews = false; + } + } + + if (check_no_locviews) + gcc_assert (!get_AT (die, DW_AT_GNU_locviews)); } /* Add DW_AT_accessibility attribute to DIE if needed. */ @@ -19557,7 +19958,7 @@ convert_cfa_to_fb_loc_list (HOST_WIDE_INT offset) /* If the first partition contained no CFI adjustments, the CIE opcodes apply to the whole first partition. */ *list_tail = new_loc_list (build_cfa_loc (&last_cfa, offset), - fde->dw_fde_begin, fde->dw_fde_end, section); + fde->dw_fde_begin, 0, fde->dw_fde_end, 0, section); list_tail =&(*list_tail)->dw_loc_next; start_label = last_label = fde->dw_fde_second_begin; } @@ -19573,7 +19974,7 @@ convert_cfa_to_fb_loc_list (HOST_WIDE_INT offset) if (!cfa_equal_p (&last_cfa, &next_cfa)) { *list_tail = new_loc_list (build_cfa_loc (&last_cfa, offset), - start_label, last_label, section); + start_label, 0, last_label, 0, section); list_tail = &(*list_tail)->dw_loc_next; last_cfa = next_cfa; @@ -19595,14 +19996,14 @@ convert_cfa_to_fb_loc_list (HOST_WIDE_INT offset) if (!cfa_equal_p (&last_cfa, &next_cfa)) { *list_tail = new_loc_list (build_cfa_loc (&last_cfa, offset), - start_label, last_label, section); + start_label, 0, last_label, 0, section); list_tail = &(*list_tail)->dw_loc_next; last_cfa = next_cfa; start_label = last_label; } *list_tail = new_loc_list (build_cfa_loc (&last_cfa, offset), - start_label, fde->dw_fde_end, section); + start_label, 0, fde->dw_fde_end, 0, section); list_tail = &(*list_tail)->dw_loc_next; start_label = last_label = fde->dw_fde_second_begin; } @@ -19611,19 +20012,18 @@ convert_cfa_to_fb_loc_list (HOST_WIDE_INT offset) if (!cfa_equal_p (&last_cfa, &next_cfa)) { *list_tail = new_loc_list (build_cfa_loc (&last_cfa, offset), - start_label, last_label, section); + start_label, 0, last_label, 0, section); list_tail = &(*list_tail)->dw_loc_next; start_label = last_label; } *list_tail = new_loc_list (build_cfa_loc (&next_cfa, offset), - start_label, + start_label, 0, fde->dw_fde_second_begin - ? fde->dw_fde_second_end : fde->dw_fde_end, + ? fde->dw_fde_second_end : fde->dw_fde_end, 0, section); - if (list && list->dw_loc_next) - gen_llsym (list); + maybe_gen_llsym (list); return list; } @@ -25984,7 +26384,7 @@ maybe_emit_file (struct dwarf_file_data * fd) fd->emitted_number = 1; last_emitted_file = fd; - if (DWARF2_ASM_LINE_DEBUG_INFO) + if (output_asm_line_debug_info ()) { fprintf (asm_out_file, "\t.file %u ", fd->emitted_number); output_quoted_string (asm_out_file, @@ -26178,11 +26578,13 @@ dwarf2out_var_location (rtx_insn *loc_note) static rtx_insn *expected_next_loc_note; tree decl; bool var_loc_p; + var_loc_view view = 0; if (!NOTE_P (loc_note)) { if (CALL_P (loc_note)) { + RESET_NEXT_VIEW (cur_line_info_table->view); call_site_count++; if (SIBLING_CALL_P (loc_note)) tail_call_site_count++; @@ -26216,6 +26618,18 @@ dwarf2out_var_location (rtx_insn *loc_note) } } } + else if (!debug_variable_location_views) + gcc_unreachable (); + else if (JUMP_TABLE_DATA_P (loc_note)) + RESET_NEXT_VIEW (cur_line_info_table->view); + else if (GET_CODE (loc_note) == USE + || GET_CODE (loc_note) == CLOBBER + || GET_CODE (loc_note) == ASM_INPUT + || asm_noperands (loc_note) >= 0) + ; + else if (get_attr_min_length (loc_note) > 0) + RESET_NEXT_VIEW (cur_line_info_table->view); + return; } @@ -26279,10 +26693,11 @@ create_label: if (var_loc_p) { + const char *label = NOTE_DURING_CALL_P (loc_note) + ? last_postcall_label : last_label; + view = cur_line_info_table->view; decl = NOTE_VAR_LOCATION_DECL (loc_note); - newloc = add_var_loc_to_decl (decl, loc_note, - NOTE_DURING_CALL_P (loc_note) - ? last_postcall_label : last_label); + newloc = add_var_loc_to_decl (decl, loc_note, label, view); if (newloc == NULL) return; } @@ -26323,8 +26738,8 @@ create_label: else if (GET_CODE (body) == ASM_INPUT || asm_noperands (body) >= 0) continue; -#ifdef HAVE_attr_length - else if (get_attr_min_length (insn) == 0) +#ifdef HAVE_ATTR_length /* ??? We don't include insn-attr.h. */ + else if (HAVE_ATTR_length && get_attr_min_length (insn) == 0) continue; #endif else @@ -26392,7 +26807,10 @@ create_label: call_arg_loc_last = ca_loc; } else if (loc_note != NULL_RTX && !NOTE_DURING_CALL_P (loc_note)) - newloc->label = last_label; + { + newloc->label = last_label; + newloc->view = view; + } else { if (!last_postcall_label) @@ -26401,6 +26819,7 @@ create_label: last_postcall_label = ggc_strdup (loclabel); } newloc->label = last_postcall_label; + newloc->view = view; } if (var_loc_p && flag_debug_asm) @@ -26467,6 +26886,7 @@ new_line_info_table (void) table->file_num = 1; table->line_num = 1; table->is_stmt = DWARF_LINE_DEFAULT_IS_STMT_START; + RESET_NEXT_VIEW (table->view); return table; } @@ -26515,7 +26935,7 @@ set_cur_line_info_table (section *sec) vec_safe_push (separate_line_info, table); } - if (DWARF2_ASM_LINE_DEBUG_INFO) + if (output_asm_line_debug_info ()) table->is_stmt = (cur_line_info_table ? cur_line_info_table->is_stmt : DWARF_LINE_DEFAULT_IS_STMT_START); @@ -26696,7 +27116,7 @@ dwarf2out_source_line (unsigned int line, unsigned int column, filename, line); } - if (DWARF2_ASM_LINE_DEBUG_INFO) + if (output_asm_line_debug_info ()) { /* Emit the .loc directive understood by GNU as. */ /* "\t.loc %u %u 0 is_stmt %u discriminator %u", @@ -26719,6 +27139,33 @@ dwarf2out_source_line (unsigned int line, unsigned int column, fputs (" discriminator ", asm_out_file); fprint_ul (asm_out_file, (unsigned long) discriminator); } + if (debug_variable_location_views) + { + static var_loc_view lvugid; + if (!lvugid) + { + gcc_assert (!zero_view_p); + zero_view_p = BITMAP_GGC_ALLOC (); + bitmap_set_bit (zero_view_p, 0); + } + if (RESETTING_VIEW_P (table->view)) + { + if (!table->in_use) + fputs (" view -0", asm_out_file); + else + fputs (" view 0", asm_out_file); + bitmap_set_bit (zero_view_p, lvugid); + table->view = ++lvugid; + } + else + { + fputs (" view ", asm_out_file); + char label[MAX_ARTIFICIAL_LABEL_BYTES]; + ASM_GENERATE_INTERNAL_LABEL (label, "LVU", table->view); + assemble_name (asm_out_file, label); + table->view = ++lvugid; + } + } putc ('\n', asm_out_file); } else @@ -26727,7 +27174,19 @@ dwarf2out_source_line (unsigned int line, unsigned int column, targetm.asm_out.internal_label (asm_out_file, LINE_CODE_LABEL, label_num); - push_dw_line_info_entry (table, LI_set_address, label_num); + if (debug_variable_location_views && table->view) + push_dw_line_info_entry (table, LI_adv_address, label_num); + else + push_dw_line_info_entry (table, LI_set_address, label_num); + if (debug_variable_location_views) + { + if (flag_debug_asm) + fprintf (asm_out_file, "\t%s view %s%d\n", + ASM_COMMENT_START, + table->in_use ? "" : "-", + table->view); + table->view++; + } if (file_num != table->file_num) push_dw_line_info_entry (table, LI_set_file, file_num); if (discriminator != table->discrim_num) @@ -27402,9 +27861,10 @@ init_sections_and_labels (bool early_lto_debug) SECTION_DEBUG, NULL); debug_str_section = get_section (DEBUG_STR_SECTION, DEBUG_STR_SECTION_FLAGS, NULL); - if (!dwarf_split_debug_info && !DWARF2_ASM_LINE_DEBUG_INFO) + if (!dwarf_split_debug_info && !output_asm_line_debug_info ()) debug_line_str_section = get_section (DEBUG_LINE_STR_SECTION, DEBUG_STR_SECTION_FLAGS, NULL); + debug_ranges_section = get_section (dwarf_version >= 5 ? DEBUG_RNGLISTS_SECTION : DEBUG_RANGES_SECTION, @@ -27783,6 +28243,11 @@ prune_unused_types_walk_attribs (dw_die_ref die) prune_unused_types_walk_loc_descr (list->expr); break; + case dw_val_class_view_list: + /* This points to a loc_list in another attribute, so it's + already covered. */ + break; + case dw_val_class_die_ref: /* A reference to another DIE. Make sure that it will get emitted. @@ -28882,6 +29347,8 @@ optimize_string_length (dw_attr_node *a) if (d->expr && non_dwarf_expression (d->expr)) non_dwarf_expr = true; break; + case dw_val_class_view_list: + gcc_unreachable (); case dw_val_class_loc: lv = AT_loc (av); if (lv == NULL) @@ -28926,7 +29393,7 @@ optimize_string_length (dw_attr_node *a) lv = copy_deref_exprloc (d->expr); if (lv) { - *p = new_loc_list (lv, d->begin, d->end, d->section); + *p = new_loc_list (lv, d->begin, d->vbegin, d->end, d->vend, d->section); p = &(*p)->dw_loc_next; } else if (!dwarf_strict && d->expr) @@ -28996,6 +29463,7 @@ resolve_addr (dw_die_ref die) { gcc_assert (!next->ll_symbol); next->ll_symbol = (*curr)->ll_symbol; + next->vl_symbol = (*curr)->vl_symbol; } if (dwarf_split_debug_info) remove_loc_list_addr_table_entries (l); @@ -29021,6 +29489,21 @@ resolve_addr (dw_die_ref die) ix--; } break; + case dw_val_class_view_list: + { + gcc_checking_assert (a->dw_attr == DW_AT_GNU_locviews); + gcc_checking_assert (dwarf2out_locviews_in_attribute ()); + dw_val_node *llnode + = view_list_to_loc_list_val_node (&a->dw_attr_val); + /* If we no longer have a loclist, or it no longer needs + views, drop this attribute. */ + if (!llnode || !llnode->v.val_loc_list->vl_symbol) + { + remove_AT (die, a->dw_attr); + ix--; + } + break; + } case dw_val_class_loc: { dw_loc_descr_ref l = AT_loc (a); @@ -29417,6 +29900,8 @@ hash_loc_list (dw_loc_list_ref list_head) { hstate.add (curr->begin, strlen (curr->begin) + 1); hstate.add (curr->end, strlen (curr->end) + 1); + hstate.add_object (curr->vbegin); + hstate.add_object (curr->vend); if (curr->section) hstate.add (curr->section, strlen (curr->section) + 1); hash_locs (curr->expr, hstate); @@ -29638,6 +30123,7 @@ loc_list_hasher::equal (const dw_loc_list_struct *a, || strcmp (a->end, b->end) != 0 || (a->section == NULL) != (b->section == NULL) || (a->section && strcmp (a->section, b->section) != 0) + || a->vbegin != b->vbegin || a->vend != b->vend || !compare_locs (a->expr, b->expr)) break; return a == NULL && b == NULL; @@ -29656,6 +30142,8 @@ optimize_location_lists_1 (dw_die_ref die, loc_list_hash_type *htab) dw_attr_node *a; unsigned ix; dw_loc_list_struct **slot; + bool drop_locviews = false; + bool has_locviews = false; FOR_EACH_VEC_SAFE_ELT (die->die_attr, ix, a) if (AT_class (a) == dw_val_class_loc_list) @@ -29666,11 +30154,33 @@ optimize_location_lists_1 (dw_die_ref die, loc_list_hash_type *htab) hash_loc_list (list); slot = htab->find_slot_with_hash (list, list->hash, INSERT); if (*slot == NULL) - *slot = list; + { + *slot = list; + if (loc_list_has_views (list)) + gcc_assert (list->vl_symbol); + else if (list->vl_symbol) + { + drop_locviews = true; + list->vl_symbol = NULL; + } + } else - a->dw_attr_val.v.val_loc_list = *slot; + { + if (list->vl_symbol && !(*slot)->vl_symbol) + drop_locviews = true; + a->dw_attr_val.v.val_loc_list = *slot; + } + } + else if (AT_class (a) == dw_val_class_view_list) + { + gcc_checking_assert (a->dw_attr == DW_AT_GNU_locviews); + has_locviews = true; } + + if (drop_locviews && has_locviews) + remove_AT (die, DW_AT_GNU_locviews); + FOR_EACH_CHILD (die, c, optimize_location_lists_1 (c, htab)); } @@ -29695,7 +30205,7 @@ index_location_lists (dw_die_ref die) /* Don't index an entry that has already been indexed or won't be output. */ if (curr->begin_entry != NULL - || (strcmp (curr->begin, curr->end) == 0 && !curr->force)) + || skip_loc_list_entry (curr)) continue; curr->begin_entry @@ -30119,7 +30629,7 @@ dwarf2out_finish (const char *) dw2_asm_output_delta (DWARF_OFFSET_SIZE, l2, l1, "Length of Location Lists"); ASM_OUTPUT_LABEL (asm_out_file, l1); - dw2_asm_output_data (2, dwarf_version, "DWARF Version"); + output_dwarf_version (); dw2_asm_output_data (1, DWARF2_ADDR_SIZE, "Address Size"); dw2_asm_output_data (1, 0, "Segment Size"); dw2_asm_output_data (4, dwarf_split_debug_info ? loc_list_idx : 0, @@ -30178,7 +30688,7 @@ dwarf2out_finish (const char *) used by the debug_info section are marked as 'used'. */ switch_to_section (debug_line_section); ASM_OUTPUT_LABEL (asm_out_file, debug_line_section_label); - if (! DWARF2_ASM_LINE_DEBUG_INFO) + if (! output_asm_line_debug_info ()) output_line_info (false); if (dwarf_split_debug_info && info_section_emitted) diff --git a/gcc/dwarf2out.h b/gcc/dwarf2out.h index 9402473..a7653ce 100644 --- a/gcc/dwarf2out.h +++ b/gcc/dwarf2out.h @@ -157,7 +157,8 @@ enum dw_val_class dw_val_class_discr_list, dw_val_class_const_implicit, dw_val_class_unsigned_const_implicit, - dw_val_class_file_implicit + dw_val_class_file_implicit, + dw_val_class_view_list }; /* Describe a floating point constant value, or a vector constant value. */ @@ -200,6 +201,7 @@ struct GTY(()) dw_val_node { rtx GTY ((tag ("dw_val_class_addr"))) val_addr; unsigned HOST_WIDE_INT GTY ((tag ("dw_val_class_offset"))) val_offset; dw_loc_list_ref GTY ((tag ("dw_val_class_loc_list"))) val_loc_list; + dw_die_ref GTY ((tag ("dw_val_class_view_list"))) val_view_list; dw_loc_descr_ref GTY ((tag ("dw_val_class_loc"))) val_loc; HOST_WIDE_INT GTY ((default)) val_int; unsigned HOST_WIDE_INT diff --git a/gcc/final.c b/gcc/final.c index d2b8523d..c52c950 100644 --- a/gcc/final.c +++ b/gcc/final.c @@ -81,6 +81,7 @@ along with GCC; see the file COPYING3. If not see #include "asan.h" #include "rtl-iter.h" #include "print-rtl.h" +#include "langhooks.h" #ifdef XCOFF_DEBUGGING_INFO #include "xcoffout.h" /* Needed for external data declarations. */ @@ -112,6 +113,7 @@ along with GCC; see the file COPYING3. If not see /* Bitflags used by final_scan_insn. */ #define SEEN_NOTE 1 #define SEEN_EMITTED 2 +#define SEEN_NEXT_VIEW 4 /* Last insn processed by final_scan_insn. */ static rtx_insn *debug_insn; @@ -1752,6 +1754,44 @@ get_some_local_dynamic_name () return 0; } +/* Arrange for us to emit a source location note before any further + real insns or section changes, by setting the SEEN_NEXT_VIEW bit in + *SEEN, as long as we are keeping track of location views. The bit + indicates we have referenced the next view at the current PC, so we + have to emit it. This should be called next to the var_location + debug hook. */ + +static inline void +set_next_view_needed (int *seen) +{ + if (debug_variable_location_views) + *seen |= SEEN_NEXT_VIEW; +} + +/* Clear the flag in *SEEN indicating we need to emit the next view. + This should be called next to the source_line debug hook. */ + +static inline void +clear_next_view_needed (int *seen) +{ + *seen &= ~SEEN_NEXT_VIEW; +} + +/* Test whether we have a pending request to emit the next view in + *SEEN, and emit it if needed, clearing the request bit. */ + +static inline void +maybe_output_next_view (int *seen) +{ + if ((*seen & SEEN_NEXT_VIEW) != 0) + { + clear_next_view_needed (seen); + (*debug_hooks->source_line) (last_linenum, last_columnnum, + last_filename, last_discriminator, + false); + } +} + /* Output assembler code for the start of a function, and initialize some of the variables in this file for the new function. The label for the function and associated @@ -1759,12 +1799,15 @@ get_some_local_dynamic_name () FIRST is the first insn of the rtl for the function being compiled. FILE is the file to write assembler code to. + SEEN should be initially set to zero, and it may be updated to + indicate we have references to the next location view, that would + require us to emit it at the current PC. OPTIMIZE_P is nonzero if we should eliminate redundant test and compare insns. */ -void -final_start_function (rtx_insn **firstp, FILE *file, - int optimize_p ATTRIBUTE_UNUSED) +static void +final_start_function_1 (rtx_insn **firstp, FILE *file, int *seen, + int optimize_p ATTRIBUTE_UNUSED) { rtx_insn *first = *firstp; @@ -1785,7 +1828,28 @@ final_start_function (rtx_insn **firstp, FILE *file, asan_function_start (); if (!DECL_IGNORED_P (current_function_decl)) - debug_hooks->begin_prologue (last_linenum, last_columnnum, last_filename); + { + /* Emit param bindings (before the first begin_stmt) in the + initial view. We don't test whether the DECLs are + PARM_DECLs: the assumption is that there will be a + NOTE_INSN_BEGIN_STMT marker before any non-parameter + NOTE_INSN_VAR_LOCATION. It's ok if the marker is not there, + we'll just have more variable locations bound in the initial + view, which is consistent with their being bound without any + code that would give them a value. */ + if (debug_variable_location_views) + { + rtx_insn *insn; + for (insn = first; + insn && GET_CODE (insn) == NOTE + && NOTE_KIND (insn) == NOTE_INSN_VAR_LOCATION; + insn = NEXT_INSN (insn)) + final_scan_insn (insn, file, 0, 0, seen); + *firstp = insn; + } + debug_hooks->begin_prologue (last_linenum, last_columnnum, + last_filename); + } if (!dwarf2_debug_info_emitted_p (current_function_decl)) dwarf2out_begin_prologue (0, 0, NULL); @@ -1860,6 +1924,17 @@ final_start_function (rtx_insn **firstp, FILE *file, profile_after_prologue (file); } +/* This is an exported final_start_function_1, callable without SEEN. */ + +void +final_start_function (rtx_insn **firstp, FILE *file, + int optimize_p ATTRIBUTE_UNUSED) +{ + int seen = 0; + final_start_function_1 (firstp, file, &seen, optimize_p); + gcc_assert (seen == 0); +} + static void profile_after_prologue (FILE *file ATTRIBUTE_UNUSED) { @@ -1991,11 +2066,10 @@ dump_basic_block_info (FILE *file, rtx_insn *insn, basic_block *start_to_bb, /* Output assembler code for some insns: all or part of a function. For description of args, see `final_start_function', above. */ -void -final (rtx_insn *first, FILE *file, int optimize_p) +static void +final_1 (rtx_insn *first, FILE *file, int seen, int optimize_p) { rtx_insn *insn, *next; - int seen = 0; /* Used for -dA dump. */ basic_block *start_to_bb = NULL; @@ -2062,6 +2136,8 @@ final (rtx_insn *first, FILE *file, int optimize_p) insn = final_scan_insn (insn, file, optimize_p, 0, &seen); } + maybe_output_next_view (&seen); + if (flag_debug_asm) { free (start_to_bb); @@ -2078,6 +2154,14 @@ final (rtx_insn *first, FILE *file, int optimize_p) delete_insn (insn); } } + +/* This is an exported final_1, callable without SEEN. */ + +void +final (rtx_insn *first, FILE *file, int optimize_p) +{ + final_1 (first, file, 0, optimize_p); +} const char * get_insn_template (int code, rtx insn) @@ -2218,6 +2302,8 @@ final_scan_insn (rtx_insn *insn, FILE *file, int optimize_p ATTRIBUTE_UNUSED, break; case NOTE_INSN_SWITCH_TEXT_SECTIONS: + maybe_output_next_view (seen); + in_cold_section_p = !in_cold_section_p; if (dwarf2out_do_frame ()) @@ -2358,6 +2444,8 @@ final_scan_insn (rtx_insn *insn, FILE *file, int optimize_p ATTRIBUTE_UNUSED, break; case NOTE_INSN_BLOCK_END: + maybe_output_next_view (seen); + if (debug_info_level == DINFO_LEVEL_NORMAL || debug_info_level == DINFO_LEVEL_VERBOSE || write_symbols == DWARF2_DEBUG @@ -2415,7 +2503,10 @@ final_scan_insn (rtx_insn *insn, FILE *file, int optimize_p ATTRIBUTE_UNUSED, case NOTE_INSN_VAR_LOCATION: case NOTE_INSN_CALL_ARG_LOCATION: if (!DECL_IGNORED_P (current_function_decl)) - debug_hooks->var_location (insn); + { + debug_hooks->var_location (insn); + set_next_view_needed (seen); + } break; case NOTE_INSN_BEGIN_STMT: @@ -2426,6 +2517,7 @@ final_scan_insn (rtx_insn *insn, FILE *file, int optimize_p ATTRIBUTE_UNUSED, (*debug_hooks->source_line) (last_linenum, last_columnnum, last_filename, last_discriminator, true); + clear_next_view_needed (seen); } break; @@ -2621,6 +2713,10 @@ final_scan_insn (rtx_insn *insn, FILE *file, int optimize_p ATTRIBUTE_UNUSED, switch_to_section (current_function_section ()); + if (debug_variable_location_views + && !DECL_IGNORED_P (current_function_decl)) + debug_hooks->var_location (insn); + break; } /* Output this line note if it is the first or the last line @@ -2633,7 +2729,12 @@ final_scan_insn (rtx_insn *insn, FILE *file, int optimize_p ATTRIBUTE_UNUSED, (*debug_hooks->source_line) (last_linenum, last_columnnum, last_filename, last_discriminator, is_stmt); + clear_next_view_needed (seen); } + else + maybe_output_next_view (seen); + + gcc_checking_assert (!DEBUG_INSN_P (insn)); if (GET_CODE (body) == PARALLEL && GET_CODE (XVECEXP (body, 0, 0)) == ASM_INPUT) @@ -3100,7 +3201,8 @@ final_scan_insn (rtx_insn *insn, FILE *file, int optimize_p ATTRIBUTE_UNUSED, /* Let the debug info back-end know about this call. We do this only after the instruction has been emitted because labels that may be created to reference the call instruction must appear after it. */ - if (call_insn != NULL && !DECL_IGNORED_P (current_function_decl)) + if ((debug_variable_location_views || call_insn != NULL) + && !DECL_IGNORED_P (current_function_decl)) debug_hooks->var_location (insn); current_output_insn = debug_insn = 0; @@ -4539,8 +4641,9 @@ rest_of_handle_final (void) assemble_start_function (current_function_decl, fnname); rtx_insn *first = get_insns (); - final_start_function (&first, asm_out_file, optimize); - final (first, asm_out_file, optimize); + int seen = 0; + final_start_function_1 (&first, asm_out_file, &seen, optimize); + final_1 (first, asm_out_file, seen, optimize); if (flag_ipa_ra && !lookup_attribute ("noipa", DECL_ATTRIBUTES (current_function_decl))) collect_fn_hard_reg_usage (); diff --git a/gcc/opts.c b/gcc/opts.c index 5aa5d06..179a20b 100644 --- a/gcc/opts.c +++ b/gcc/opts.c @@ -2367,7 +2367,7 @@ common_handle_option (struct gcc_options *opts, /* FALLTHRU */ case OPT_gdwarf_: - if (value < 2 || value > 5) + if (value < 2 || value > 6) error_at (loc, "dwarf version %d is not supported", value); else opts->x_dwarf_version = value; diff --git a/gcc/toplev.c b/gcc/toplev.c index 0ef46da..25d46b5 100644 --- a/gcc/toplev.c +++ b/gcc/toplev.c @@ -1518,6 +1518,14 @@ process_options (void) debug_nonbind_markers_p = optimize && debug_info_level >= DINFO_LEVEL_NORMAL && (write_symbols == DWARF2_DEBUG || write_symbols == VMS_AND_DWARF2_DEBUG); + if (debug_variable_location_views == AUTODETECT_VALUE) + { + debug_variable_location_views = flag_var_tracking + && debug_info_level >= DINFO_LEVEL_NORMAL + && (write_symbols == DWARF2_DEBUG || write_symbols == VMS_AND_DWARF2_DEBUG) + && !dwarf_strict; + } + if (flag_tree_cselim == AUTODETECT_VALUE) { if (HAVE_conditional_move) diff --git a/include/dwarf2.def b/include/dwarf2.def index 2a3b23f..f3fa400 100644 --- a/include/dwarf2.def +++ b/include/dwarf2.def @@ -443,6 +443,7 @@ DW_AT (DW_AT_GNU_pubtypes, 0x2135) /* Attribute for discriminator. See http://gcc.gnu.org/wiki/Discriminator */ DW_AT (DW_AT_GNU_discriminator, 0x2136) +DW_AT (DW_AT_GNU_locviews, 0x2137) /* VMS extensions. */ DW_AT (DW_AT_VMS_rtnbeg_pd_address, 0x2201) /* GNAT extensions. */ diff --git a/include/dwarf2.h b/include/dwarf2.h index a2e022d..fd76d82 100644 --- a/include/dwarf2.h +++ b/include/dwarf2.h @@ -298,6 +298,14 @@ enum dwarf_location_list_entry_type DW_LLE_start_end = 0x07, DW_LLE_start_length = 0x08, + /* + has the proposal for now; only available to list members. + + A (possibly updated) copy of the proposal is available at + . */ + DW_LLE_GNU_view_pair = 0x09, +#define DW_LLE_view_pair DW_LLE_GNU_view_pair + /* Former extension for Fission. See http://gcc.gnu.org/wiki/DebugFission. */ DW_LLE_GNU_end_of_list_entry = 0x00, From patchwork Sat Sep 30 09:08:26 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Alexandre Oliva X-Patchwork-Id: 820194 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (mailfrom) smtp.mailfrom=gcc.gnu.org (client-ip=209.132.180.131; helo=sourceware.org; envelope-from=gcc-patches-return-463266-incoming=patchwork.ozlabs.org@gcc.gnu.org; receiver=) Authentication-Results: ozlabs.org; dkim=pass (1024-bit key; unprotected) header.d=gcc.gnu.org header.i=@gcc.gnu.org header.b="vISQmfk2"; dkim-atps=neutral Received: from sourceware.org (server1.sourceware.org [209.132.180.131]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 3y42kR3PyVz9t2h for ; Sat, 30 Sep 2017 19:12:15 +1000 (AEST) DomainKey-Signature: a=rsa-sha1; c=nofws; d=gcc.gnu.org; h=list-id :list-unsubscribe:list-archive:list-post:list-help:sender:from :to:cc:subject:date:message-id:in-reply-to:references; q=dns; s= default; b=ZR1xQN6JVfO+mdiCTsUseQo2agon6lpQFRJN3Nc5wQMfWEE8VJXsf 707+Dpnnnmzwe9UjCquAiBRhru+d31/lJWZm6QnKjq8vCz6f/KE17BkP3+1jV7wL n/a7JxY+xTDIeuw5Rw+OOWDO62Vvvl2a7WzXe1lt/FbOPbgpVJZoug= DKIM-Signature: v=1; a=rsa-sha1; c=relaxed; d=gcc.gnu.org; h=list-id :list-unsubscribe:list-archive:list-post:list-help:sender:from :to:cc:subject:date:message-id:in-reply-to:references; s= default; bh=zuKCH2jOizi7zuUCSIov3Gs68Rg=; b=vISQmfk2yeMVlWmW5FgH Df687dz8RqEg8mS5nicNNNNYNeZBc7MJTGo01RjJhsG0FjKFkv0yNy/FXj15elHF Q8LWpWwU7to4N/ORN0JUqBXmbamVQvnxzLC5bFUe+hxkAgVjf8M5omFDnDZcpEo8 i58DB9i4usjKpnUWiqlBmaI= Received: (qmail 65017 invoked by alias); 30 Sep 2017 09:10:00 -0000 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 Received: (qmail 64952 invoked by uid 89); 30 Sep 2017 09:09:59 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-25.9 required=5.0 tests=BAYES_00, GIT_PATCH_0, GIT_PATCH_1, GIT_PATCH_2, GIT_PATCH_3, KAM_LAZY_DOMAIN_SECURITY, RP_MATCHES_RCVD, SPF_HELO_PASS autolearn=ham version=3.3.2 spammy=27737 X-HELO: mx1.redhat.com Received: from mx1.redhat.com (HELO mx1.redhat.com) (209.132.183.28) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Sat, 30 Sep 2017 09:09:58 +0000 Received: from smtp.corp.redhat.com (int-mx01.intmail.prod.int.phx2.redhat.com [10.5.11.11]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id E149A4E334; Sat, 30 Sep 2017 09:09:56 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.3.2 mx1.redhat.com E149A4E334 Authentication-Results: ext-mx09.extmail.prod.ext.phx2.redhat.com; dmarc=none (p=none dis=none) header.from=redhat.com Authentication-Results: ext-mx09.extmail.prod.ext.phx2.redhat.com; spf=fail smtp.mailfrom=aoliva@redhat.com Received: from freie.home (ovpn04.gateway.prod.ext.phx2.redhat.com [10.5.9.4]) by smtp.corp.redhat.com (Postfix) with ESMTPS id 9FE25189BB; Sat, 30 Sep 2017 09:09:56 +0000 (UTC) Received: from frit.home (frit.home [172.31.160.7]) by freie.home (8.15.2/8.15.2) with ESMTP id v8U98pIZ022010; Sat, 30 Sep 2017 06:09:31 -0300 From: Alexandre Oliva To: Richard Biener Cc: GCC Patches , Alexandre Oliva Subject: [PATCH 8/9] [IEPM] Introduce debug hook for inline entry point markers Date: Sat, 30 Sep 2017 06:08:26 -0300 Message-Id: <20170930090827.6604-8-aoliva@redhat.com> In-Reply-To: References: The inline_entry hook will be given a definition in a later patch. for gcc/ChangeLog * debug.h (gcc_debug_hooks): Add inline_entry. * dbxout.c (dbx_debug_hooks, xcoff_debug_hooks): Likewise. * debug.c (do_nothing_debug_hooks): Likewise. * sdbout.c (sdb_debug_hooks): Likewise. * vmsdbgout.c (vmsdbg_debug_hooks): Likewise. * dwarf2out.c (dwarf2_debug_hooks): Likewise. (dwarf2_lineno_debug_hooks): Likewise. --- gcc/dbxout.c | 2 ++ gcc/debug.c | 1 + gcc/debug.h | 3 +++ gcc/dwarf2out.c | 2 ++ gcc/sdbout.c | 1 + gcc/vmsdbgout.c | 1 + 6 files changed, 10 insertions(+) diff --git a/gcc/dbxout.c b/gcc/dbxout.c index ea7c97c..6ba0471 100644 --- a/gcc/dbxout.c +++ b/gcc/dbxout.c @@ -379,6 +379,7 @@ const struct gcc_debug_hooks dbx_debug_hooks = debug_nothing_rtx_code_label, /* label */ dbxout_handle_pch, /* handle_pch */ debug_nothing_rtx_insn, /* var_location */ + debug_nothing_tree, /* inline_entry */ debug_nothing_tree, /* size_function */ debug_nothing_void, /* switch_text_section */ debug_nothing_tree_tree, /* set_name */ @@ -421,6 +422,7 @@ const struct gcc_debug_hooks xcoff_debug_hooks = debug_nothing_rtx_code_label, /* label */ dbxout_handle_pch, /* handle_pch */ debug_nothing_rtx_insn, /* var_location */ + debug_nothing_tree, /* inline_entry */ debug_nothing_tree, /* size_function */ debug_nothing_void, /* switch_text_section */ debug_nothing_tree_tree, /* set_name */ diff --git a/gcc/debug.c b/gcc/debug.c index 4db94c3..c0bc667 100644 --- a/gcc/debug.c +++ b/gcc/debug.c @@ -55,6 +55,7 @@ const struct gcc_debug_hooks do_nothing_debug_hooks = debug_nothing_rtx_code_label, /* label */ debug_nothing_int, /* handle_pch */ debug_nothing_rtx_insn, /* var_location */ + debug_nothing_tree, /* inline_entry */ debug_nothing_tree, /* size_function */ debug_nothing_void, /* switch_text_section */ debug_nothing_tree_tree, /* set_name */ diff --git a/gcc/debug.h b/gcc/debug.h index 915420b..8c888b6 100644 --- a/gcc/debug.h +++ b/gcc/debug.h @@ -176,6 +176,9 @@ struct gcc_debug_hooks /* Called from final_scan_insn for any NOTE_INSN_VAR_LOCATION note. */ void (* var_location) (rtx_insn *); + /* Called from final_scan_insn for any NOTE_INSN_INLINE_ENTRY note. */ + void (* inline_entry) (tree block); + /* Called from finalize_size_functions for size functions so that their body can be encoded in the debug info to describe the layout of variable-length structures. */ diff --git a/gcc/dwarf2out.c b/gcc/dwarf2out.c index 6b19c4a..f435b5a 100644 --- a/gcc/dwarf2out.c +++ b/gcc/dwarf2out.c @@ -2773,6 +2773,7 @@ const struct gcc_debug_hooks dwarf2_debug_hooks = debug_nothing_rtx_code_label, /* label */ debug_nothing_int, /* handle_pch */ dwarf2out_var_location, + debug_nothing_tree, /* inline_entry */ dwarf2out_size_function, /* size_function */ dwarf2out_switch_text_section, dwarf2out_set_name, @@ -2813,6 +2814,7 @@ const struct gcc_debug_hooks dwarf2_lineno_debug_hooks = debug_nothing_rtx_code_label, /* label */ debug_nothing_int, /* handle_pch */ debug_nothing_rtx_insn, /* var_location */ + debug_nothing_tree, /* inline_entry */ debug_nothing_tree, /* size_function */ debug_nothing_void, /* switch_text_section */ debug_nothing_tree_tree, /* set_name */ diff --git a/gcc/sdbout.c b/gcc/sdbout.c index acd25a3..ba64432 100644 --- a/gcc/sdbout.c +++ b/gcc/sdbout.c @@ -309,6 +309,7 @@ const struct gcc_debug_hooks sdb_debug_hooks = sdbout_label, /* label */ debug_nothing_int, /* handle_pch */ debug_nothing_rtx_insn, /* var_location */ + debug_nothing_tree, /* inline_entry */ debug_nothing_tree, /* size_function */ debug_nothing_void, /* switch_text_section */ debug_nothing_tree_tree, /* set_name */ diff --git a/gcc/vmsdbgout.c b/gcc/vmsdbgout.c index 580dd28..83ba2ae 100644 --- a/gcc/vmsdbgout.c +++ b/gcc/vmsdbgout.c @@ -205,6 +205,7 @@ const struct gcc_debug_hooks vmsdbg_debug_hooks debug_nothing_rtx_code_label, /* label */ debug_nothing_int, /* handle_pch */ debug_nothing_rtx_insn, /* var_location */ + debug_nothing_tree, /* inline_entry */ debug_nothing_tree, /* size_function */ debug_nothing_void, /* switch_text_section */ debug_nothing_tree_tree, /* set_name */ From patchwork Sat Sep 30 09:08:27 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Alexandre Oliva X-Patchwork-Id: 820196 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (mailfrom) smtp.mailfrom=gcc.gnu.org (client-ip=209.132.180.131; helo=sourceware.org; envelope-from=gcc-patches-return-463267-incoming=patchwork.ozlabs.org@gcc.gnu.org; receiver=) Authentication-Results: ozlabs.org; dkim=pass (1024-bit key; unprotected) header.d=gcc.gnu.org header.i=@gcc.gnu.org header.b="Z7PJxBpX"; dkim-atps=neutral Received: from sourceware.org (server1.sourceware.org [209.132.180.131]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 3y42kt0GRZz9t2h for ; Sat, 30 Sep 2017 19:12:37 +1000 (AEST) DomainKey-Signature: a=rsa-sha1; c=nofws; d=gcc.gnu.org; h=list-id :list-unsubscribe:list-archive:list-post:list-help:sender:from :to:cc:subject:date:message-id:in-reply-to:references; q=dns; s= default; b=nQzo8jiZHzZBLr8lv5sUrjtC5z83IucFhfyVstvIjFX53K3F38VEA ssWmsUL11yNjEmLKykkqAr4KEbJh4au2rnknEKc9+dJpKuC2ucAkRgzkYSRQA824 JVy9jPt8wKQZJVL/H8AUgqozsXivgj5PctWJFn2jejbX/li5uEk9W4= DKIM-Signature: v=1; a=rsa-sha1; c=relaxed; d=gcc.gnu.org; h=list-id :list-unsubscribe:list-archive:list-post:list-help:sender:from :to:cc:subject:date:message-id:in-reply-to:references; s= default; bh=hc2VC87Di0qGg4Sf+KEc9zqNwc4=; b=Z7PJxBpX+RKSOqEcxCl2 5cgTPHQeIRtpWVL9hDsMPSBuMaJc/tyFhRo18c1/NdUgf3/aFl2xqrbFWg6B7qq4 PdEpmedpydgMgYtAL5KpTNxA16t6iZWIWt212xi/Curr9hjj5A6fjZp6jo/Ip0GI +R0Rm2io1CQ+vq+ATPEElxA= Received: (qmail 66068 invoked by alias); 30 Sep 2017 09:10:11 -0000 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 Received: (qmail 66024 invoked by uid 89); 30 Sep 2017 09:10:11 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-26.9 required=5.0 tests=BAYES_00, GIT_PATCH_0, GIT_PATCH_1, GIT_PATCH_2, GIT_PATCH_3, RP_MATCHES_RCVD, SPF_HELO_PASS autolearn=ham version=3.3.2 spammy= X-HELO: mx1.redhat.com Received: from mx1.redhat.com (HELO mx1.redhat.com) (209.132.183.28) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Sat, 30 Sep 2017 09:10:05 +0000 Received: from smtp.corp.redhat.com (int-mx05.intmail.prod.int.phx2.redhat.com [10.5.11.15]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 249DD883B8; Sat, 30 Sep 2017 09:10:04 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.3.2 mx1.redhat.com 249DD883B8 Authentication-Results: ext-mx02.extmail.prod.ext.phx2.redhat.com; dmarc=none (p=none dis=none) header.from=redhat.com Authentication-Results: ext-mx02.extmail.prod.ext.phx2.redhat.com; spf=fail smtp.mailfrom=aoliva@redhat.com Received: from freie.home (ovpn04.gateway.prod.ext.phx2.redhat.com [10.5.9.4]) by smtp.corp.redhat.com (Postfix) with ESMTPS id 9C1DA18628; Sat, 30 Sep 2017 09:10:02 +0000 (UTC) Received: from frit.home (frit.home [172.31.160.7]) by freie.home (8.15.2/8.15.2) with ESMTP id v8U98pIa022010; Sat, 30 Sep 2017 06:09:34 -0300 From: Alexandre Oliva To: Richard Biener Cc: GCC Patches , Alexandre Oliva Subject: [PATCH 9/9] [IEPM] Introduce inline entry point markers Date: Sat, 30 Sep 2017 06:08:27 -0300 Message-Id: <20170930090827.6604-9-aoliva@redhat.com> In-Reply-To: References: Output DW_AT_entry_pc based on markers. Introduce DW_AT_GNU_entry_view as a DWARF extension. If views are enabled are we're not in strict compliance mode, output DW_AT_GNU_entry_view if it might be nonzero. This patch depends on SFN and LVU patchsets, and on the IEPM patch that introduces the inline_entry debug hook. for include/ChangeLog * dwarf2.def (DW_AT_GNU_entry_view): New. for gcc/ChangeLog * cfgexpand.c (expand_gimple_basic_block): Handle inline entry markers. * dwarf2out.c (dwarf2_debug_hooks): Enable inline_entry hook. (BLOCK_INLINE_ENTRY_LABEL): New. (dwarf2out_var_location): Disregard inline entry markers. (inline_entry_data): New struct. (inline_entry_data_hasher): New hashtable type. (inline_entry_data_hasher::hash): New. (inline_entry_data_hasher::equal): New. (inline_entry_data_table): New variable. (add_high_low_attributes): Add DW_AT_entry_pc and DW_AT_GNU_entry_view attributes if a pending entry is found in inline_entry_data_table. Add old entry_pc attribute only if debug nonbinding markers are disabled. (gen_inlined_subroutine_die): Set BLOCK_DIE if nonbinding markers are enabled. (block_within_block_p, dwarf2out_inline_entry): New. (dwarf2out_finish): Check that no entries remained in inline_entry_data_table. * final.c (reemit_insn_block_notes): Handle inline entry notes. (final_scan_insn, notice_source_line): Likewise. (rest_of_clean_state): Skip inline entry markers. * gimple-pretty-print.c (dump_gimple_debug): Handle inline entry markers. * gimple.c (gimple_build_debug_inline_entry): New. * gimple.h (enum gimple_debug_subcode): Add GIMPLE_DEBUG_INLINE_ENTRY. (gimple_build_debug_inline_entry): Declare. (gimple_debug_inline_entry_p): New. (gimple_debug_nonbind_marker_p): Adjust. * insn-notes.def (INLINE_ENTRY): New. * print-rtl.c (rtx_writer::print_rtx_operand_code_0): Handle inline entry marker notes. (print_insn): Likewise. * rtl.h (NOTE_MARKER_P): Add INLINE_ENTRY support. (INSN_DEBUG_MARKER_KIND): Likewise. * tree-inline.c (expand_call_inline): Build and insert debug_inline_entry stmt. * tree-ssa-live.c (remove_unused_scope_block_p): Preserve inline entry blocks early, if nonbind markers are enabled. (dump_scope_block): Dump fragment info. * var-tracking.c (reemit_marker_as_note): Handle inline entry note. * doc/gimple.texi (gimple_debug_inline_entry_p): New. (gimple_build_debug_inline_entry): New. * doc/invoke.texi (gstatement-frontiers, gno-statement-frontiers): Enable/disable inline entry points too. * doc/rtl.texi (NOTE_INSN_INLINE_ENTRY): New. (DEBUG_INSN): Describe inline entry markers. --- gcc/cfgexpand.c | 9 +++ gcc/doc/gimple.texi | 18 +++++ gcc/doc/rtl.texi | 24 ++++-- gcc/dwarf2out.c | 186 +++++++++++++++++++++++++++++++++++++++++++++- gcc/final.c | 26 +++++++ gcc/gimple-pretty-print.c | 13 ++++ gcc/gimple.c | 21 ++++++ gcc/gimple.h | 18 ++++- gcc/insn-notes.def | 4 + gcc/print-rtl.c | 5 ++ gcc/rtl.h | 5 +- gcc/tree-inline.c | 7 ++ gcc/tree-ssa-live.c | 27 +++++-- gcc/var-tracking.c | 1 + include/dwarf2.def | 1 + 15 files changed, 349 insertions(+), 16 deletions(-) diff --git a/gcc/cfgexpand.c b/gcc/cfgexpand.c index c854ffd..8ccdafd 100644 --- a/gcc/cfgexpand.c +++ b/gcc/cfgexpand.c @@ -5691,6 +5691,15 @@ expand_gimple_basic_block (basic_block bb, bool disable_tail_calls) goto delink_debug_stmt; else if (gimple_debug_begin_stmt_p (stmt)) val = gen_rtx_DEBUG_MARKER (VOIDmode); + else if (gimple_debug_inline_entry_p (stmt)) + { + tree block = gimple_block (stmt); + + if (block) + val = gen_rtx_DEBUG_MARKER (BLKmode); + else + goto delink_debug_stmt; + } else gcc_unreachable (); diff --git a/gcc/doc/gimple.texi b/gcc/doc/gimple.texi index 6c9c4789..af39d75 100644 --- a/gcc/doc/gimple.texi +++ b/gcc/doc/gimple.texi @@ -836,6 +836,11 @@ Return true if g is a @code{GIMPLE_DEBUG} that marks the beginning of a source statement. @end deftypefn +@deftypefn {GIMPLE function} gimple_debug_inline_entry_p (gimple g) +Return true if g is a @code{GIMPLE_DEBUG} that marks the entry +point of an inlined function. +@end deftypefn + @deftypefn {GIMPLE function} gimple_debug_nonbind_marker_p (gimple g) Return true if g is a @code{GIMPLE_DEBUG} that marks a program location, without any variable binding. @@ -1539,6 +1544,7 @@ Set the conditional @code{COND_STMT} to be of the form 'if (1 == 1)'. @cindex @code{GIMPLE_DEBUG} @cindex @code{GIMPLE_DEBUG_BIND} @cindex @code{GIMPLE_DEBUG_BEGIN_STMT} +@cindex @code{GIMPLE_DEBUG_INLINE_ENTRY} @deftypefn {GIMPLE function} gdebug *gimple_build_debug_bind (tree var, @ tree value, gimple stmt) @@ -1624,6 +1630,18 @@ observable, and that none of the side effects of subsequent user statements are. @end deftypefn +@deftypefn {GIMPLE function} gimple gimple_build_debug_inline_entry (tree block, location_t location) +Build a @code{GIMPLE_DEBUG} statement with +@code{GIMPLE_DEBUG_INLINE_ENTRY} @code{subcode}. The effect of this +statement is to tell debug information generation machinery that a +function call at @code{location} underwent inline substitution, that +@code{block} is the enclosing lexical block created for the +substitution, and that at the point of the program in which the stmt is +inserted, all parameters for the inlined function are bound to the +respective arguments, and none of the side effects of its stmts are +observable. +@end deftypefn + @node @code{GIMPLE_EH_FILTER} @subsection @code{GIMPLE_EH_FILTER} @cindex @code{GIMPLE_EH_FILTER} diff --git a/gcc/doc/rtl.texi b/gcc/doc/rtl.texi index 888ab02..a2f6e7a 100644 --- a/gcc/doc/rtl.texi +++ b/gcc/doc/rtl.texi @@ -3430,7 +3430,10 @@ Refers to a parameter that was completely optimized out. @item (debug_marker:@var{mode}) Marks a program location. With @code{VOIDmode}, it stands for the beginning of a statement, a recommended inspection point logically after -all prior side effects, and before any subsequent side effects. +all prior side effects, and before any subsequent side effects. With +@code{BLKmode}, it indicates an inline entry point: the lexical block +encoded in the @code{INSN_LOCATION} is the enclosing block that encloses +the inlined function. @end table @@ -3714,6 +3717,13 @@ This note is used to generate @code{is_stmt} markers in line number debuggign information. It indicates the beginning of a user statement. +@findex NOTE_INSN_INLINE_ENTRY +@item NOTE_INSN_INLINE_ENTRY +This note is used to generate @code{entry_pc} for inlined subroutines in +debugging information. It indicates an inspection point at which all +arguments for the inlined function have been bound, and before its first +statement. + @end table These codes are printed symbolically when they appear in debugging dumps. @@ -3731,8 +3741,12 @@ binds a user variable tree to an RTL representation of the it stands for the value bound to the corresponding @code{DEBUG_EXPR_DECL}. -@code{GIMPLE_DEBUG_BEGIN_STMT} is expanded to RTL as a @code{DEBUG_INSN} -with a @code{VOIDmode} @code{DEBUG_MARKER} @code{PATTERN}. These +@code{GIMPLE_DEBUG_BEGIN_STMT} and @code{GIMPLE_DEBUG_INLINE_ENTRY} are +expanded to RTL as a @code{DEBUG_INSN} with a @code{DEBUG_MARKER} +@code{PATTERN}; the difference is the RTL mode: the former's +@code{DEBUG_MARKER} is @code{VOIDmode}, whereas the latter is +@code{BLKmode}; information about the inlined function can be taken from +the lexical block encoded in the @code{INSN_LOCATION}. These @code{DEBUG_INSN}s, that do not carry @code{VAR_LOCATION} information, just @code{DEBUG_MARKER}s, can be detected by testing @code{DEBUG_MARKER_INSN_P}, whereas those that do can be recognized as @@ -3743,8 +3757,8 @@ with respect to each other, particularly during scheduling. Binding information is kept in pseudo-instruction form, so that, unlike notes, it gets the same treatment and adjustments that regular instructions would. It is the variable tracking pass that turns these -pseudo-instructions into @code{NOTE_INSN_VAR_LOCATION} and -@code{NOTE_INSN_BEGIN_STMT} notes, +pseudo-instructions into @code{NOTE_INSN_VAR_LOCATION}, +@code{NOTE_INSN_BEGIN_STMT} and @code{NOTE_INSN_INLINE_ENTRY} notes, analyzing control flow, value equivalences and changes to registers and memory referenced in value expressions, propagating the values of debug temporaries and determining expressions that can be used to compute the diff --git a/gcc/dwarf2out.c b/gcc/dwarf2out.c index f435b5a..ed7a85a 100644 --- a/gcc/dwarf2out.c +++ b/gcc/dwarf2out.c @@ -2720,6 +2720,7 @@ static void dwarf2out_imported_module_or_decl_1 (tree, tree, tree, dw_die_ref); static void dwarf2out_abstract_function (tree); static void dwarf2out_var_location (rtx_insn *); +static void dwarf2out_inline_entry (tree); static void dwarf2out_size_function (tree); static void dwarf2out_begin_function (tree); static void dwarf2out_end_function (unsigned int); @@ -2773,7 +2774,7 @@ const struct gcc_debug_hooks dwarf2_debug_hooks = debug_nothing_rtx_code_label, /* label */ debug_nothing_int, /* handle_pch */ dwarf2out_var_location, - debug_nothing_tree, /* inline_entry */ + dwarf2out_inline_entry, /* inline_entry */ dwarf2out_size_function, /* size_function */ dwarf2out_switch_text_section, dwarf2out_set_name, @@ -4011,6 +4012,9 @@ static char ranges_base_label[2 * MAX_ARTIFICIAL_LABEL_BYTES]; #ifndef BLOCK_BEGIN_LABEL #define BLOCK_BEGIN_LABEL "LBB" #endif +#ifndef BLOCK_INLINE_ENTRY_LABEL +#define BLOCK_INLINE_ENTRY_LABEL "LBI" +#endif #ifndef BLOCK_END_LABEL #define BLOCK_END_LABEL "LBE" #endif @@ -23004,6 +23008,48 @@ block_die_hasher::equal (die_struct *x, die_struct *y) return x->decl_id == y->decl_id && x->die_parent == y->die_parent; } +/* Hold information about markers for inlined entry points. */ +struct GTY ((for_user)) inline_entry_data +{ + /* The block that's the inlined_function_outer_scope for an inlined + function. */ + tree block; + + /* The label at the inlined entry point. */ + const char *label_pfx; + unsigned int label_num; + + /* The view number to be used as the inlined entry point. */ + var_loc_view view; +}; + +struct inline_entry_data_hasher : ggc_ptr_hash +{ + typedef tree compare_type; + static inline hashval_t hash (const inline_entry_data *); + static inline bool equal (const inline_entry_data *, const_tree); +}; + +/* Hash table routines for inline_entry_data. */ + +inline hashval_t +inline_entry_data_hasher::hash (const inline_entry_data *data) +{ + return htab_hash_pointer (data->block); +} + +inline bool +inline_entry_data_hasher::equal (const inline_entry_data *data, + const_tree block) +{ + return data->block == block; +} + +/* Inlined entry points pending DIE creation in this compilation unit. */ + +static GTY(()) hash_table *inline_entry_data_table; + + /* Return TRUE if DECL, which may have been previously generated as OLD_DIE, is a candidate for a DW_AT_specification. DECLARATION is true if decl (or its origin) is either an extern declaration or a @@ -23458,6 +23504,42 @@ add_high_low_attributes (tree stmt, dw_die_ref die) { char label[MAX_ARTIFICIAL_LABEL_BYTES]; + if (inline_entry_data **iedp + = !inline_entry_data_table ? NULL + : inline_entry_data_table->find_slot_with_hash (stmt, + htab_hash_pointer (stmt), + NO_INSERT)) + { + inline_entry_data *ied = *iedp; + gcc_assert (MAY_HAVE_DEBUG_MARKER_INSNS); + gcc_assert (inlined_function_outer_scope_p (stmt)); + ASM_GENERATE_INTERNAL_LABEL (label, ied->label_pfx, ied->label_num); + add_AT_lbl_id (die, DW_AT_entry_pc, label); + + if (debug_variable_location_views && !ZERO_VIEW_P (ied->view)) + { + if (!output_asm_line_debug_info ()) + add_AT_unsigned (die, DW_AT_GNU_entry_view, ied->view); + else + { + ASM_GENERATE_INTERNAL_LABEL (label, "LVU", ied->view); + /* FIXME: this will resolve to a small number. Could we + possibly emit smaller data? Ideally we'd emit a + uleb128, but that would make the size of DIEs + impossible for the compiler to compute, since it's + the assembler that computes the value of the view + label in this case. Ideally, we'd have a single form + encompassing both the address and the view, and + indirecting them through a table might make things + easier, but even that would be more wasteful, + space-wise, than what we have now. */ + add_AT_lbl_id (die, DW_AT_GNU_entry_view, label); + } + } + + inline_entry_data_table->clear_slot (iedp); + } + if (BLOCK_FRAGMENT_CHAIN (stmt) && (dwarf_version >= 3 || !dwarf_strict)) { @@ -23465,7 +23547,7 @@ add_high_low_attributes (tree stmt, dw_die_ref die) dw_die_ref pdie; dw_attr_node *attr = NULL; - if (inlined_function_outer_scope_p (stmt)) + if (!MAY_HAVE_DEBUG_MARKER_INSNS && inlined_function_outer_scope_p (stmt)) { ASM_GENERATE_INTERNAL_LABEL (label, BLOCK_BEGIN_LABEL, BLOCK_NUMBER (stmt)); @@ -23630,7 +23712,7 @@ gen_inlined_subroutine_die (tree stmt, dw_die_ref context_die) dw_die_ref subr_die = new_die (DW_TAG_inlined_subroutine, context_die, stmt); - if (call_arg_locations) + if (call_arg_locations || MAY_HAVE_DEBUG_MARKER_INSNS) BLOCK_DIE (stmt) = subr_die; add_abstract_origin_attribute (subr_die, decl); if (TREE_ASM_WRITTEN (stmt)) @@ -26656,6 +26738,7 @@ dwarf2out_var_location (rtx_insn *loc_note) || ! NOTE_P (next_note) || (NOTE_KIND (next_note) != NOTE_INSN_VAR_LOCATION && NOTE_KIND (next_note) != NOTE_INSN_BEGIN_STMT + && NOTE_KIND (next_note) != NOTE_INSN_INLINE_ENTRY && NOTE_KIND (next_note) != NOTE_INSN_CALL_ARG_LOCATION)) next_note = NULL; @@ -26844,6 +26927,100 @@ create_label: last_in_cold_section_p = in_cold_section_p; } +/* Check whether BLOCK, a lexical block, is nested within OUTER, or is + OUTER itself. */ +static bool +block_within_block_p (tree block, tree outer) +{ + if (block == outer) + return true; + + /* Quickly check that OUTER is up BLOCK's supercontext chain. */ + for (tree context = BLOCK_SUPERCONTEXT (block); + context != outer; + context = BLOCK_SUPERCONTEXT (context)) + if (!context || TREE_CODE (context) != BLOCK) + return false; + + /* Now check that each block is actually referenced by its + parent. */ + for (tree context = BLOCK_SUPERCONTEXT (block); ; + context = BLOCK_SUPERCONTEXT (context)) + { + if (BLOCK_FRAGMENT_ORIGIN (context)) + { + gcc_assert (!BLOCK_SUBBLOCKS (context)); + context = BLOCK_FRAGMENT_ORIGIN (context); + } + for (tree sub = BLOCK_SUBBLOCKS (context); + sub != block; + sub = BLOCK_CHAIN (sub)) + if (!sub) + return false; + if (context == outer) + return true; + else + block = context; + } +} + +/* Called during final while assembling the marker of the entry point + for an inlined function. */ + +static void +dwarf2out_inline_entry (tree block) +{ + gcc_assert (DECL_P (block_ultimate_origin (block))); + + gcc_checking_assert (block_within_block_p (block, + DECL_INITIAL + (current_function_decl))); + + gcc_assert (inlined_function_outer_scope_p (block)); + gcc_assert (!BLOCK_DIE (block)); + + /* If we can't represent it, don't bother. */ + if (!(dwarf_version >= 3 || !dwarf_strict)) + return; + + if (BLOCK_FRAGMENT_ORIGIN (block)) + block = BLOCK_FRAGMENT_ORIGIN (block); + /* Can the entry point ever not be at the beginning of an + unfragmented lexical block? */ + else if (!(BLOCK_FRAGMENT_CHAIN (block) + || (cur_line_info_table + && !ZERO_VIEW_P (cur_line_info_table->view)))) + return; + + if (!inline_entry_data_table) + inline_entry_data_table + = hash_table::create_ggc (10); + + + inline_entry_data **iedp + = inline_entry_data_table->find_slot_with_hash (block, + htab_hash_pointer (block), + INSERT); + if (*iedp) + /* ??? Ideally, we'd record all entry points for the same inlined + function (some may have been duplicated by e.g. unrolling), but + we have no way to represent that ATM. */ + return; + + inline_entry_data *ied = *iedp = ggc_cleared_alloc (); + ied->block = block; + ied->label_pfx = BLOCK_INLINE_ENTRY_LABEL; + ied->label_num = BLOCK_NUMBER (block); + if (cur_line_info_table) + ied->view = cur_line_info_table->view; + + char label[MAX_ARTIFICIAL_LABEL_BYTES]; + + ASM_GENERATE_INTERNAL_LABEL (label, BLOCK_INLINE_ENTRY_LABEL, + BLOCK_NUMBER (block)); + ASM_OUTPUT_LABEL (asm_out_file, label); +} + /* Called from finalize_size_functions for size functions so that their body can be encoded in the debug info to describe the layout of variable-length structures. */ @@ -30315,6 +30492,9 @@ dwarf2out_finish (const char *) /* Flush out any latecomers to the limbo party. */ flush_limbo_die_list (); + if (inline_entry_data_table) + gcc_assert (inline_entry_data_table->elements () == 0); + if (flag_checking) { verify_die (comp_unit_die ()); diff --git a/gcc/final.c b/gcc/final.c index c52c950..6c3a73b 100644 --- a/gcc/final.c +++ b/gcc/final.c @@ -1672,6 +1672,7 @@ reemit_insn_block_notes (void) break; case NOTE_INSN_BEGIN_STMT: + case NOTE_INSN_INLINE_ENTRY: this_block = LOCATION_BLOCK (NOTE_MARKER_LOCATION (insn)); goto set_cur_block_to_this_block; @@ -2514,6 +2515,7 @@ final_scan_insn (rtx_insn *insn, FILE *file, int optimize_p ATTRIBUTE_UNUSED, if (!DECL_IGNORED_P (current_function_decl) && notice_source_line (insn, NULL)) { + output_source_line: (*debug_hooks->source_line) (last_linenum, last_columnnum, last_filename, last_discriminator, true); @@ -2521,6 +2523,18 @@ final_scan_insn (rtx_insn *insn, FILE *file, int optimize_p ATTRIBUTE_UNUSED, } break; + case NOTE_INSN_INLINE_ENTRY: + gcc_checking_assert (cfun->debug_nonbind_markers); + if (!DECL_IGNORED_P (current_function_decl)) + { + if (!notice_source_line (insn, NULL)) + break; + (*debug_hooks->inline_entry) (LOCATION_BLOCK + (NOTE_MARKER_LOCATION (insn))); + goto output_source_line; + } + break; + default: gcc_unreachable (); break; @@ -3224,6 +3238,17 @@ notice_source_line (rtx_insn *insn, bool *is_stmt) if (NOTE_MARKER_P (insn)) { location_t loc = NOTE_MARKER_LOCATION (insn); + /* The inline entry markers (gimple, insn, note) carry the + location of the call, because that's what we want to carry + during compilation, but the location we want to output in + debug information for the inline entry point is the location + of the function itself. */ + if (NOTE_KIND (insn) == NOTE_INSN_INLINE_ENTRY) + { + tree block = LOCATION_BLOCK (loc); + tree fn = block_ultimate_origin (block); + loc = DECL_SOURCE_LOCATION (fn); + } expanded_location xloc = expand_location (loc); if (xloc.line == 0) { @@ -4829,6 +4854,7 @@ rest_of_clean_state (void) && (!NOTE_P (insn) || (NOTE_KIND (insn) != NOTE_INSN_VAR_LOCATION && NOTE_KIND (insn) != NOTE_INSN_BEGIN_STMT + && NOTE_KIND (insn) != NOTE_INSN_INLINE_ENTRY && NOTE_KIND (insn) != NOTE_INSN_CALL_ARG_LOCATION && NOTE_KIND (insn) != NOTE_INSN_BLOCK_BEG && NOTE_KIND (insn) != NOTE_INSN_BLOCK_END diff --git a/gcc/gimple-pretty-print.c b/gcc/gimple-pretty-print.c index 2702854..7c9c754 100644 --- a/gcc/gimple-pretty-print.c +++ b/gcc/gimple-pretty-print.c @@ -1377,6 +1377,19 @@ dump_gimple_debug (pretty_printer *buffer, gdebug *gs, int spc, dump_gimple_fmt (buffer, spc, flags, "# DEBUG BEGIN_STMT"); break; + case GIMPLE_DEBUG_INLINE_ENTRY: + if (flags & TDF_RAW) + dump_gimple_fmt (buffer, spc, flags, "%G INLINE_ENTRY %T", gs, + gimple_block (gs) + ? block_ultimate_origin (gimple_block (gs)) + : NULL_TREE); + else + dump_gimple_fmt (buffer, spc, flags, "# DEBUG INLINE_ENTRY %T", + gimple_block (gs) + ? block_ultimate_origin (gimple_block (gs)) + : NULL_TREE); + break; + default: gcc_unreachable (); } diff --git a/gcc/gimple.c b/gcc/gimple.c index dc9aa79..01ddc65 100644 --- a/gcc/gimple.c +++ b/gcc/gimple.c @@ -857,6 +857,27 @@ gimple_build_debug_begin_stmt (tree block, location_t location } +/* Build a new GIMPLE_DEBUG_INLINE_ENTRY statement in BLOCK at + LOCATION. The BLOCK links to the inlined function. */ + +gdebug * +gimple_build_debug_inline_entry (tree block, location_t location + MEM_STAT_DECL) +{ + gdebug *p + = as_a ( + gimple_build_with_ops_stat (GIMPLE_DEBUG, + (unsigned)GIMPLE_DEBUG_INLINE_ENTRY, 0 + PASS_MEM_STAT)); + + gimple_set_location (p, location); + gimple_set_block (p, block); + cfun->debug_marker_count++; + + return p; +} + + /* Build a GIMPLE_OMP_CRITICAL statement. BODY is the sequence of statements for which only one thread can execute. diff --git a/gcc/gimple.h b/gcc/gimple.h index 68cd34f..909807f 100644 --- a/gcc/gimple.h +++ b/gcc/gimple.h @@ -203,7 +203,8 @@ enum gf_mask { enum gimple_debug_subcode { GIMPLE_DEBUG_BIND = 0, GIMPLE_DEBUG_SOURCE_BIND = 1, - GIMPLE_DEBUG_BEGIN_STMT = 2 + GIMPLE_DEBUG_BEGIN_STMT = 2, + GIMPLE_DEBUG_INLINE_ENTRY = 3 }; /* Masks for selecting a pass local flag (PLF) to work on. These @@ -1455,6 +1456,7 @@ geh_dispatch *gimple_build_eh_dispatch (int); gdebug *gimple_build_debug_bind (tree, tree, gimple * CXX_MEM_STAT_INFO); gdebug *gimple_build_debug_source_bind (tree, tree, gimple * CXX_MEM_STAT_INFO); gdebug *gimple_build_debug_begin_stmt (tree, location_t CXX_MEM_STAT_INFO); +gdebug *gimple_build_debug_inline_entry (tree, location_t CXX_MEM_STAT_INFO); gomp_critical *gimple_build_omp_critical (gimple_seq, tree, tree); gomp_for *gimple_build_omp_for (gimple_seq, int, tree, size_t, gimple_seq); gomp_parallel *gimple_build_omp_parallel (gimple_seq, tree, tree, tree); @@ -4766,13 +4768,25 @@ gimple_debug_begin_stmt_p (const gimple *s) return false; } +/* Return true if S is a GIMPLE_DEBUG INLINE_ENTRY statement. */ + +static inline bool +gimple_debug_inline_entry_p (const gimple *s) +{ + if (is_gimple_debug (s)) + return s->subcode == GIMPLE_DEBUG_INLINE_ENTRY; + + return false; +} + /* Return true if S is a GIMPLE_DEBUG non-binding marker statement. */ static inline bool gimple_debug_nonbind_marker_p (const gimple *s) { if (is_gimple_debug (s)) - return s->subcode == GIMPLE_DEBUG_BEGIN_STMT; + return s->subcode == GIMPLE_DEBUG_BEGIN_STMT + || s->subcode == GIMPLE_DEBUG_INLINE_ENTRY; return false; } diff --git a/gcc/insn-notes.def b/gcc/insn-notes.def index 960487b..252e957 100644 --- a/gcc/insn-notes.def +++ b/gcc/insn-notes.def @@ -71,6 +71,10 @@ INSN_NOTE (CALL_ARG_LOCATION) /* The beginning of a statement. */ INSN_NOTE (BEGIN_STMT) +/* The entry point for an inlined function. Its NOTE_BLOCK references + the lexical block whose abstract origin is the inlined function. */ +INSN_NOTE (INLINE_ENTRY) + /* Record the struct for the following basic block. Uses NOTE_BASIC_BLOCK. FIXME: Redundant with the basic block pointer now included in every insn. NOTE: If there's no CFG anymore, in other words, diff --git a/gcc/print-rtl.c b/gcc/print-rtl.c index 0d36a42..cca8798 100644 --- a/gcc/print-rtl.c +++ b/gcc/print-rtl.c @@ -259,6 +259,7 @@ rtx_writer::print_rtx_operand_code_0 (const_rtx in_rtx ATTRIBUTE_UNUSED, break; case NOTE_INSN_BEGIN_STMT: + case NOTE_INSN_INLINE_ENTRY: #ifndef GENERATOR_FILE { expanded_location xloc @@ -1809,6 +1810,10 @@ print_insn (pretty_printer *pp, const rtx_insn *x, int verbose) pp_string (pp, "debug begin stmt marker"); break; + case NOTE_INSN_INLINE_ENTRY: + pp_string (pp, "debug inline entry marker"); + break; + default: gcc_unreachable (); } diff --git a/gcc/rtl.h b/gcc/rtl.h index a0c27fc..cd177c7 100644 --- a/gcc/rtl.h +++ b/gcc/rtl.h @@ -1625,7 +1625,8 @@ extern const char * const reg_note_name[]; for which NOTE_MARKER_LOCATION can be used. */ #define NOTE_MARKER_P(INSN) \ (NOTE_P (INSN) && \ - (NOTE_KIND (INSN) == NOTE_INSN_BEGIN_STMT)) + (NOTE_KIND (INSN) == NOTE_INSN_BEGIN_STMT \ + || NOTE_KIND (INSN) == NOTE_INSN_INLINE_ENTRY)) /* Variable declaration and the location of a variable. */ #define PAT_VAR_LOCATION_DECL(PAT) (XCTREE ((PAT), 0, VAR_LOCATION)) @@ -1663,6 +1664,8 @@ extern const char * const reg_note_name[]; (GET_CODE (PATTERN (INSN)) == DEBUG_MARKER \ ? (GET_MODE (PATTERN (INSN)) == VOIDmode \ ? NOTE_INSN_BEGIN_STMT \ + : GET_MODE (PATTERN (INSN)) == BLKmode \ + ? NOTE_INSN_INLINE_ENTRY \ : (enum insn_note)-1) \ : (enum insn_note)-1) diff --git a/gcc/tree-inline.c b/gcc/tree-inline.c index a99e975..41b4fd9 100644 --- a/gcc/tree-inline.c +++ b/gcc/tree-inline.c @@ -4704,6 +4704,13 @@ expand_call_inline (basic_block bb, gimple *stmt, copy_body_data *id) GSI_NEW_STMT); } initialize_inlined_parameters (id, stmt, fn, bb); + if (debug_nonbind_markers_p && id->block + && inlined_function_outer_scope_p (id->block)) + { + gimple_stmt_iterator si = gsi_last_bb (bb); + gsi_insert_after (&si, gimple_build_debug_inline_entry + (id->block, input_location), GSI_NEW_STMT); + } if (DECL_INITIAL (fn)) { diff --git a/gcc/tree-ssa-live.c b/gcc/tree-ssa-live.c index 8738fe2..734d15d 100644 --- a/gcc/tree-ssa-live.c +++ b/gcc/tree-ssa-live.c @@ -520,6 +520,11 @@ remove_unused_scope_block_p (tree scope, bool in_ctor_dtor_block) else if (!BLOCK_SUPERCONTEXT (scope) || TREE_CODE (BLOCK_SUPERCONTEXT (scope)) == FUNCTION_DECL) unused = false; + /* Preserve the block, it is referenced by at least the inline + entry point marker. */ + else if (debug_nonbind_markers_p + && inlined_function_outer_scope_p (scope)) + unused = false; /* Innermost blocks with no live variables nor statements can be always eliminated. */ else if (!nsubblocks) @@ -548,11 +553,13 @@ remove_unused_scope_block_p (tree scope, bool in_ctor_dtor_block) } else if (BLOCK_VARS (scope) || BLOCK_NUM_NONLOCALIZED_VARS (scope)) unused = false; - /* See if this block is important for representation of inlined function. - Inlined functions are always represented by block with - block_ultimate_origin being set to FUNCTION_DECL and DECL_SOURCE_LOCATION - set... */ - else if (inlined_function_outer_scope_p (scope)) + /* See if this block is important for representation of inlined + function. Inlined functions are always represented by block + with block_ultimate_origin being set to FUNCTION_DECL and + DECL_SOURCE_LOCATION set, unless they expand to nothing... But + see above for the case of statement frontiers. */ + else if (!debug_nonbind_markers_p + && inlined_function_outer_scope_p (scope)) unused = false; else /* Verfify that only blocks with source location set @@ -640,6 +647,16 @@ dump_scope_block (FILE *file, int indent, tree scope, dump_flags_t flags) fprintf (file, "#%i", BLOCK_NUMBER (origin)); } } + if (BLOCK_FRAGMENT_ORIGIN (scope)) + fprintf (file, " Fragment of : #%i", + BLOCK_NUMBER (BLOCK_FRAGMENT_ORIGIN (scope))); + else if (BLOCK_FRAGMENT_CHAIN (scope)) + { + fprintf (file, " Fragment chain :"); + for (t = BLOCK_FRAGMENT_CHAIN (scope); t ; + t = BLOCK_FRAGMENT_CHAIN (t)) + fprintf (file, " #%i", BLOCK_NUMBER (t)); + } fprintf (file, " \n"); for (var = BLOCK_VARS (scope); var; var = DECL_CHAIN (var)) { diff --git a/gcc/var-tracking.c b/gcc/var-tracking.c index d3850af..21ffe57 100644 --- a/gcc/var-tracking.c +++ b/gcc/var-tracking.c @@ -9931,6 +9931,7 @@ reemit_marker_as_note (rtx_insn *insn, basic_block *bb) switch (kind) { case NOTE_INSN_BEGIN_STMT: + case NOTE_INSN_INLINE_ENTRY: { rtx_insn *note = NULL; if (cfun->debug_nonbind_markers) diff --git a/include/dwarf2.def b/include/dwarf2.def index f3fa400..8e731a3 100644 --- a/include/dwarf2.def +++ b/include/dwarf2.def @@ -444,6 +444,7 @@ DW_AT (DW_AT_GNU_pubtypes, 0x2135) See http://gcc.gnu.org/wiki/Discriminator */ DW_AT (DW_AT_GNU_discriminator, 0x2136) DW_AT (DW_AT_GNU_locviews, 0x2137) +DW_AT (DW_AT_GNU_entry_view, 0x2138) /* VMS extensions. */ DW_AT (DW_AT_VMS_rtnbeg_pd_address, 0x2201) /* GNAT extensions. */