* [PATCH 1/3] RFC: Add a mode in which debug stmts participate in codegen
2019-06-23 13:51 [PATCH 0/3] RFC: Let debug stmts influence codegen at -Og Richard Sandiford
@ 2019-06-23 13:52 ` Richard Sandiford
2019-06-23 13:53 ` [PATCH 0/3] RFC: Keep debug values live for -Og Richard Sandiford
` (5 subsequent siblings)
6 siblings, 0 replies; 12+ messages in thread
From: Richard Sandiford @ 2019-06-23 13:52 UTC (permalink / raw)
To: gcc-patches
This patch adds a mode in which debug stmts and debug insns are
explicitly allowed to affect codegen. In particular:
- uses in debug binds become first-class uses, acting like uses in
executable code
- the use of DEBUG_EXPR_DECLs is banned. If we want to refer to
a temporary value in debug binds, we need to calculate the value
with executable code instead
The idea is that this mode can then take the quality of the debug
experience into account when optimising. The flipside is that it needs
to generate debug insns even if -g isn't passed, so that -g continues
to have no effect on codegen. (That shouldn't be a significant problem
though. There's not much point using this mode unless you intend to
use -g most/all of the time, so the compile-time impact without -g
shouldn't be important.)
The patch calls stmts and insns "tangible" stmts/insns if they can
effect codegen and "shadow" stmts/insns otherwise. A new global,
flag_tangible_debug, controls which category debug binds fall into.
They're tangible stmts/insns for the new mode and shadow stmts/insns
otherwise. (Despite the name, flag_tangible_debug is just an internal
flag, there's no -ftangible-debug option.)
The main part of the patch involves replacing tests for debug/nondebug
with tests for shadow/tangible where appropriate. The patch is far
from complete; it just handles the cases needed by -Og and -O1g
bootstraps (see later patch for -O1g).
On its own the mode doesn't help many cases, although the patch includes
one token test. The patch is really just adding infrastructure for
later patches.
I added FIXMEs to rtlanal.c with the intention of renaming the
functions in a separate patch.
2019-06-23 Richard Sandiford <richard.sandiford@arm.com>
config/
* bootstrap-Og.mk: New file.
gcc/
* common.opt (flag_tangible_debug): New variable.
* opts.c (default_options_optimization): Initialize it as appropriate
for each -O option.
* toplev.c (process_options): Don't test for -g when choosing the
default flag_var_tracking setting for flag_tangible_debug.
* tree.h (MAY_HAVE_SHADOW_DEBUG_BIND_STMTS): New macro.
* gimple.h (tangible_stmt_p): New function.
* tree-ssa-scopedtables.c: Include options.h.
* rtl.h (MAY_HAVE_SHADOW_DEBUG_BIND_INSNS): New macro.
(tangible_insn_p, shadow_insn_p): New functions.
* tree.c (make_node): Forbid the use of DEBUG_DECL_EXPR
when flag_tangible_debug.
* tree-ssa.c (insert_debug_temp_for_var_def): Don't handle debug
uses of SSA_NAMEs here if flag_tangible_debug.
* tree-ssanames.c (release_ssa_name_fn): Likewise.
* ssa-iterators.h (has_zero_uses): Don't skip tangible debug insns.
(has_single_use, single_imm_use): Likewise.
(num_imm_uses): Test MAY_HAVE_SHADOW_DEBUG_BIND_STMTS instead of
MAY_HAVE_DEBUG_BIND_STMTS when deciding whether to ignore uses
in debug bind statements.
* tree-ssa-operands.c (single_imm_use_1): Don't skip tangible
debug stmts.
* emit-rtl.c (next_nondebug_insn, prev_nondebug_insn)
(next_nonnote_nondebug_insn, next_nonnote_nondebug_insn_bb)
(prev_nonnote_nondebug_insn, prev_nonnote_nondebug_insn_bb)
(next_real_nondebug_insn, prev_real_nondebug_insn): Don't skip
over tangible debug insns. Add FIXME note that the functions
should be renamed accordingly.
(emit_pattern_after, emit_pattern_before): Replace "skip_debug_insns"
parameter with "skip_shadow_insns".
* cfgexpand.c (avoid_deep_ter_for_debug): For flag_tangible_debug,
use the same depth limit as avoid_complex_debug_insns and undo
the replacement when the depth is reached.
(expand_debug_locations): Don't call avoid_complex_debug_insns.
(expand_gimple_basic_block): Change the condition
under which debug uses can occur after the last "real" use of a
TER variable from MAY_HAVE_DEBUG_BIND_STMTS to
MAY_HAVE_SHADOW_DEBUG_BIND_STMTS. Don't delink uses of tangible
debug stmts here.
* combine.c (find_single_use, create_log_links, combine_instructions):
(try_combine, distribute_notes, distribute_links): Handle tangible
debug insns like normal insns. Make special handling of debug uses
conditional on MAY_HAVE_SHADOW_DEBUG_BIND_INSNS rather than
MAY_HAVE_DEBUG_BIND_INSNS.
(make_more_copies): Test NONJUMP_INSN_P rather than NONDEBUG_INSN_P.
(cant_combine_insn_p): Explain why we still test NONDEBUG_INSN_P.
* cse.c (try_back_substitute_reg, cse_extended_basic_block)
(count_reg_usage, delete_trivially_dead_insns): Handle tangible
debug insns like normal insns. Make special handling of debug uses
conditional on MAY_HAVE_SHADOW_DEBUG_BIND_INSNS rather than
MAY_HAVE_DEBUG_BIND_INSN.
* dce.c (reset_unmarked_insns_debug_uses, prescan_insns_for_dce)
(mark_reg_dependencies, rest_of_handle_ud_dce, word_dce_process_block)
(dce_process_block): Likewise.
* df-problems.c (df_lr_bb_local_compute, df_word_lr_bb_local_compute)
(df_set_note, df_note_bb_compute, df_simulate_uses): Likewise.
(df_simulate_one_insn_backwards, can_move_insns_across): Likewise.
* df-scan.c (df_install_ref_incremental, df_insn_delete): Likewise.
(df_insn_rescan): Likewise.
* dse.c (scan_insn): Likewise.
* init-regs.c (initialize_uninitialized_regs): Likewise.
* ira-build.c (create_bb_allocnos): Likewise.
* ira-conflicts.c (add_copies): Likewise.
* ira-lives.c (find_call_crossed_cheap_reg): Likewise.
(process_bb_node_lives): Likewise.
* ira.c (memref_used_between_p, def_dominates_uses, update_equiv_regs)
(combine_and_move_insns, build_insn_chain, find_moveable_pseudos)
(split_live_ranges_for_shrink_wrap): Likewise.
* lra-constraints.c (add_next_usage_insn, inherit_reload_reg)
(split_reg, update_ebb_live_info, get_last_insertion_point)
(remove_inheritance_pseudos, inherit_in_ebb): Likewise.
(delete_move_and_clobber): Likewise.
* lra-lives.c (process_bb_lives): Likewise.
* lra-remat.c (create_cands, calculate_local_reg_remat_bb_data)
(do_remat): Likewise.
* lra.c (new_insn_reg, invalidate_insn_data_regno_info): Likewise.
(update_inc_notes): Likewise.
(lra_update_insn_regno_info): Likewise. Assert that the frequency
is always zero for debug insns. Call get_insn_freq for all insns.
(get_insn_freq): Return zero for debug insns.
* reg-stack.c (convert_regs_1): Handle REG_DEAD notes on tangible
debug insns.
* regstat.c (regstat_init_n_sets_and_refs, regstat_bb_compute_ri)
(regstat_bb_compute_calls_crossed): Handle tangible debug insns
like normal insns. Make special handling of debug uses conditional
on MAY_HAVE_SHADOW_DEBUG_BIND_INSNS rather than
MAY_HAVE_DEBUG_BIND_INSNS.
* rtlanal.c (reg_used_between_p): Likewise.
* shrink-wrap.c (move_insn_for_shrink_wrap, prepare_shrink_wrap)
(try_shrink_wrapping): Likewise.
* tree-cfg.c (first_stmt, last_stmt, gimple_empty_block_p): Likewise.
* tree-cfgcleanup.c (tree_forwarder_block_p): Return false for
tangible debug stmts.
* tree-inline.c (remap_ssa_name): Don't handle debug bind uses
specially if flag_tangible_debug.
(remap_decl): Add comment.
(copy_edges_for_bb): Handle tangible debug stmts like normal stmts.
* tree-into-ssa.c (mark_def_sites, rewrite_debug_stmt_uses)
(rewrite_stmt, rewrite_update_stmt, mark_use_interesting): Likewise.
* tree-ssa-coalesce.c (build_ssa_conflict_graph): Likewise.
(create_coalesce_list_for_region): Remove redundant is_gimple_debug
test.
* tree-ssa-dce.c (replace_with_debug_bind_p): New function, split
out from...
(remove_dead_stmt): ... here.
(mark_stmt_necessary): Add tangible debug stmts to the worklist.
If a statement would be converted into a tangible debug stmt rather
than deleted, add it to the worklist even if it isn't necessary.
(mark_stmt_if_obviously_necessary): Handle tangible debug stmts
like normal stmts. Make special handling of debug uses conditional
on MAY_HAVE_SHADOW_DEBUG_BIND_STMTS rather than
MAY_HAVE_DEBUG_BIND_STMTS.
(eliminate_unnecessary_stmts): Likewise.
* tree-ssa-live.c (remove_unused_locals): Likewise.
(set_var_live_on_entry): Likewise.
* tree-ssa-loop-ivopts.c (find_interesting_uses): Likewise.
(remove_unused_ivs): Likewise.
* tree-ssa-loop-manip.c (find_uses_to_rename_stmt): Likewise.
(find_uses_to_rename_def, check_loop_closed_ssa_def): Likewise.
* tree-ssa-sink.c (all_immediate_uses_same_place): Likewise.
(nearest_common_dominator_of_uses): Likewise.
(statement_sink_location): Likewise.
* tree-ssa-ter.c (find_replaceable_in_bb): Likewise.
gcc/fortran/
* trans-types.c (gfc_get_array_descr_info): Locally set
flag_tangible_debug to false when creating a dummy DEBUG_EXPR_DECL.
gcc/testsuite/
* c-c++-common/guality/Og-dead-1.c: New test.
* gcc.dg/guality/guality.exp: Use a reduced set of options for tests
starting with -Og.
* g++.dg/guality/guality.exp: Likewise.
Index: config/bootstrap-Og.mk
===================================================================
--- /dev/null 2019-06-14 15:59:19.298479944 +0100
+++ config/bootstrap-Og.mk 2019-06-23 14:48:44.491065092 +0100
@@ -0,0 +1,1 @@
+BOOT_CFLAGS := -Og $(filter-out -O%, $(BOOT_CFLAGS))
Index: gcc/common.opt
===================================================================
--- gcc/common.opt 2019-06-23 14:48:15.000000000 +0100
+++ gcc/common.opt 2019-06-23 14:48:44.495065059 +0100
@@ -39,6 +39,12 @@ int optimize_debug
Variable
int optimize_fast
+; True if debug bind stmts and insns are allowed to have an effect on code
+; generation and be treated for code-generation purposes in a similar way
+; to function calls.
+Variable
+bool flag_tangible_debug = false
+
; True if this is the lto front end. This is used to disable gimple
; generation and lowering passes that are normally run on the output
; of a front end. These passes must be bypassed for lto since they
Index: gcc/opts.c
===================================================================
--- gcc/opts.c 2019-06-23 14:48:15.000000000 +0100
+++ gcc/opts.c 2019-06-23 14:48:44.507064959 +0100
@@ -591,12 +591,7 @@ default_options_optimization (struct gcc
{
case OPT_O:
if (*opt->arg == '\0')
- {
- opts->x_optimize = 1;
- opts->x_optimize_size = 0;
- opts->x_optimize_fast = 0;
- opts->x_optimize_debug = 0;
- }
+ opts->x_optimize = 1;
else
{
const int optimize_val = integral_argument (opt->arg);
@@ -608,11 +603,12 @@ default_options_optimization (struct gcc
opts->x_optimize = optimize_val;
if ((unsigned int) opts->x_optimize > 255)
opts->x_optimize = 255;
- opts->x_optimize_size = 0;
- opts->x_optimize_fast = 0;
- opts->x_optimize_debug = 0;
}
}
+ opts->x_optimize_size = 0;
+ opts->x_optimize_fast = 0;
+ opts->x_optimize_debug = 0;
+ opts->x_flag_tangible_debug = 0;
break;
case OPT_Os:
@@ -622,6 +618,7 @@ default_options_optimization (struct gcc
opts->x_optimize = 2;
opts->x_optimize_fast = 0;
opts->x_optimize_debug = 0;
+ opts->x_flag_tangible_debug = 0;
break;
case OPT_Ofast:
@@ -630,6 +627,7 @@ default_options_optimization (struct gcc
opts->x_optimize = 3;
opts->x_optimize_fast = 1;
opts->x_optimize_debug = 0;
+ opts->x_flag_tangible_debug = 0;
break;
case OPT_Og:
@@ -638,6 +636,7 @@ default_options_optimization (struct gcc
opts->x_optimize = 1;
opts->x_optimize_fast = 0;
opts->x_optimize_debug = 1;
+ opts->x_flag_tangible_debug = 1;
break;
case OPT_fopenacc:
Index: gcc/toplev.c
===================================================================
--- gcc/toplev.c 2019-06-23 14:48:15.000000000 +0100
+++ gcc/toplev.c 2019-06-23 14:48:44.511064925 +0100
@@ -1537,8 +1537,12 @@ process_options (void)
/* We know which debug output will be used so we can set flag_var_tracking
and flag_var_tracking_uninit if the user has not specified them. */
- if (debug_info_level < DINFO_LEVEL_NORMAL
- || debug_hooks->var_location == do_nothing_debug_hooks.var_location)
+ if ((debug_info_level < DINFO_LEVEL_NORMAL
+ || debug_hooks->var_location == do_nothing_debug_hooks.var_location)
+ /* If we're treating debug binds as "tangible", we need to generate
+ them even if we're not going to emit debug info, so that we get
+ the same code with and without debugging enabled. */
+ && !flag_tangible_debug)
{
if (flag_var_tracking == 1
|| flag_var_tracking_uninit == 1)
Index: gcc/tree.h
===================================================================
--- gcc/tree.h 2019-06-23 14:48:15.000000000 +0100
+++ gcc/tree.h 2019-06-23 14:48:44.519064858 +0100
@@ -1150,6 +1150,10 @@ #define MAY_HAVE_DEBUG_MARKER_STMTS debu
/* 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 in addition, such debug bind statements are shadow
+ statements. */
+#define MAY_HAVE_SHADOW_DEBUG_BIND_STMTS \
+ (MAY_HAVE_DEBUG_BIND_STMTS && !flag_tangible_debug)
/* Nonzero if is_gimple_debug() may possibly hold. */
#define MAY_HAVE_DEBUG_STMTS \
(MAY_HAVE_DEBUG_MARKER_STMTS || MAY_HAVE_DEBUG_BIND_STMTS)
Index: gcc/gimple.h
===================================================================
--- gcc/gimple.h 2019-06-23 14:48:15.000000000 +0100
+++ gcc/gimple.h 2019-06-23 14:48:44.503064992 +0100
@@ -4842,6 +4842,17 @@ gimple_debug_nonbind_marker_p (const gim
return false;
}
+/* Return true if S participates in and has an effect on code generation. */
+
+static inline bool
+tangible_stmt_p (const gimple *s)
+{
+ return (!is_gimple_debug (s)
+ || (flag_tangible_debug
+ && (s->subcode == GIMPLE_DEBUG_BIND
+ || s->subcode == GIMPLE_DEBUG_SOURCE_BIND)));
+}
+
/* Return the line number for EXPR, or return -1 if we have no line
number information for it. */
static inline int
Index: gcc/tree-ssa-scopedtables.c
===================================================================
--- gcc/tree-ssa-scopedtables.c 2019-06-23 14:48:15.000000000 +0100
+++ gcc/tree-ssa-scopedtables.c 2019-06-23 14:48:44.515064892 +0100
@@ -20,6 +20,7 @@ Software Foundation; either version 3, o
#include "config.h"
#include "system.h"
#include "coretypes.h"
+#include "options.h"
#include "function.h"
#include "basic-block.h"
#include "tree.h"
Index: gcc/rtl.h
===================================================================
--- gcc/rtl.h 2019-06-23 14:48:15.000000000 +0100
+++ gcc/rtl.h 2019-06-23 14:48:44.507064959 +0100
@@ -846,6 +846,9 @@ #define NONDEBUG_INSN_P(X) (NONJUMP_INSN
#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 in addition, such DEBUG_BIND_INSNs are shadow instructions. */
+#define MAY_HAVE_SHADOW_DEBUG_BIND_INSNS \
+ (MAY_HAVE_DEBUG_BIND_INSNS && !flag_tangible_debug)
/* Nonzero if DEBUG_INSN_P may possibly hold. */
#define MAY_HAVE_DEBUG_INSNS \
(MAY_HAVE_DEBUG_MARKER_INSNS || MAY_HAVE_DEBUG_BIND_INSNS)
@@ -1760,6 +1763,20 @@ #define DEBUG_IMPLICIT_PTR_DECL(RTX) XCT
/* PARM_DECL DEBUG_PARAMETER_REF references. */
#define DEBUG_PARAMETER_REF_DECL(RTX) XCTREE (RTX, 0, DEBUG_PARAMETER_REF)
+/* True if X is an insn that affects or takes part in code generation. */
+inline bool
+tangible_insn_p (const_rtx x)
+{
+ return NONDEBUG_INSN_P (x) || (DEBUG_BIND_INSN_P (x) && flag_tangible_debug);
+}
+
+/* True if X is an insn that must never affect code generation. */
+inline bool
+shadow_insn_p (const_rtx x)
+{
+ return DEBUG_INSN_P (x) && (!DEBUG_BIND_INSN_P (x) || !flag_tangible_debug);
+}
+
/* Codes that appear in the NOTE_KIND field for kinds of notes
that are not line numbers. These codes are all negative.
Index: gcc/tree.c
===================================================================
--- gcc/tree.c 2019-06-23 14:48:15.000000000 +0100
+++ gcc/tree.c 2019-06-23 14:48:44.519064858 +0100
@@ -1043,6 +1043,11 @@ make_node (enum tree_code code MEM_STAT_
enum tree_code_class type = TREE_CODE_CLASS (code);
size_t length = tree_code_size (code);
+ /* We must never create DEBUG_EXPR_DECLs when debug stmts are tangible.
+ If we want to create temporaries, we should do so using executable
+ code. */
+ gcc_checking_assert (code != DEBUG_EXPR_DECL || !flag_tangible_debug);
+
record_node_allocation_statistics (code, length);
t = ggc_alloc_cleared_tree_node_stat (length PASS_MEM_STAT);
Index: gcc/tree-ssa.c
===================================================================
--- gcc/tree-ssa.c 2019-06-23 14:48:15.000000000 +0100
+++ gcc/tree-ssa.c 2019-06-23 14:48:44.515064892 +0100
@@ -310,6 +310,12 @@ insert_debug_temp_for_var_def (gimple_st
if (!MAY_HAVE_DEBUG_BIND_STMTS)
return;
+ /* Uses in debug stmts are first-class uses for flag_tangible_debug,
+ so the caller must take them into account in the same way as for
+ executable code. */
+ if (flag_tangible_debug)
+ return;
+
/* If this name has already been registered for replacement, do nothing
as anything that uses this name isn't in SSA form. */
if (name_registered_for_update_p (var))
Index: gcc/tree-ssanames.c
===================================================================
--- gcc/tree-ssanames.c 2019-06-23 14:48:15.000000000 +0100
+++ gcc/tree-ssanames.c 2019-06-23 14:48:44.515064892 +0100
@@ -598,7 +598,7 @@ release_ssa_name_fn (struct function *fn
int saved_ssa_name_version = SSA_NAME_VERSION (var);
use_operand_p imm = &(SSA_NAME_IMM_USE_NODE (var));
- if (MAY_HAVE_DEBUG_BIND_STMTS)
+ if (MAY_HAVE_SHADOW_DEBUG_BIND_STMTS)
insert_debug_temp_for_var_def (NULL, var);
if (flag_checking)
Index: gcc/ssa-iterators.h
===================================================================
--- gcc/ssa-iterators.h 2019-06-23 14:48:15.000000000 +0100
+++ gcc/ssa-iterators.h 2019-06-23 14:48:44.511064925 +0100
@@ -387,7 +387,7 @@ has_zero_uses (const_tree var)
const ssa_use_operand_t *ptr;
for (ptr = head->next; ptr != head; ptr = ptr->next)
- if (USE_STMT (ptr) && !is_gimple_debug (USE_STMT (ptr)))
+ if (USE_STMT (ptr) && tangible_stmt_p (USE_STMT (ptr)))
return false;
return true;
@@ -402,7 +402,7 @@ has_single_use (const_tree var)
bool single = false;
for (ptr = head->next; ptr != head; ptr = ptr->next)
- if (USE_STMT(ptr) && !is_gimple_debug (USE_STMT (ptr)))
+ if (USE_STMT (ptr) && tangible_stmt_p (USE_STMT (ptr)))
{
if (single)
return false;
@@ -432,7 +432,7 @@ single_imm_use (const_tree var, use_oper
/* If there's a single use, check that it's not a debug stmt. */
if (ptr == ptr->next->next)
{
- if (USE_STMT (ptr->next) && !is_gimple_debug (USE_STMT (ptr->next)))
+ if (USE_STMT (ptr->next) && tangible_stmt_p (USE_STMT (ptr->next)))
{
*use_p = ptr->next;
*stmt = ptr->next->loc.stmt;
@@ -453,7 +453,7 @@ num_imm_uses (const_tree var)
const ssa_use_operand_t *ptr;
unsigned int num = 0;
- if (!MAY_HAVE_DEBUG_BIND_STMTS)
+ if (!MAY_HAVE_SHADOW_DEBUG_BIND_STMTS)
{
for (ptr = start->next; ptr != start; ptr = ptr->next)
if (USE_STMT (ptr))
Index: gcc/tree-ssa-operands.c
===================================================================
--- gcc/tree-ssa-operands.c 2019-06-23 14:48:15.000000000 +0100
+++ gcc/tree-ssa-operands.c 2019-06-23 14:48:44.515064892 +0100
@@ -1330,7 +1330,7 @@ single_imm_use_1 (const ssa_use_operand_
ssa_use_operand_t *ptr, *single_use = 0;
for (ptr = head->next; ptr != head; ptr = ptr->next)
- if (USE_STMT(ptr) && !is_gimple_debug (USE_STMT (ptr)))
+ if (USE_STMT (ptr) && tangible_stmt_p (USE_STMT (ptr)))
{
if (single_use)
{
Index: gcc/emit-rtl.c
===================================================================
--- gcc/emit-rtl.c 2019-06-23 14:48:15.000000000 +0100
+++ gcc/emit-rtl.c 2019-06-23 14:48:44.503064992 +0100
@@ -3500,13 +3500,14 @@ next_nonnote_insn (rtx_insn *insn)
/* Return the next insn after INSN that is not a DEBUG_INSN. This
routine does not look inside SEQUENCEs. */
+/* FIXME: Rename. */
rtx_insn *
next_nondebug_insn (rtx_insn *insn)
{
while (insn)
{
insn = NEXT_INSN (insn);
- if (insn == 0 || !DEBUG_INSN_P (insn))
+ if (insn == 0 || !shadow_insn_p (insn))
break;
}
@@ -3532,13 +3533,14 @@ prev_nonnote_insn (rtx_insn *insn)
/* Return the previous insn before INSN that is not a DEBUG_INSN.
This routine does not look inside SEQUENCEs. */
+/* FIXME: Rename. */
rtx_insn *
prev_nondebug_insn (rtx_insn *insn)
{
while (insn)
{
insn = PREV_INSN (insn);
- if (insn == 0 || !DEBUG_INSN_P (insn))
+ if (insn == 0 || !shadow_insn_p (insn))
break;
}
@@ -3548,13 +3550,14 @@ prev_nondebug_insn (rtx_insn *insn)
/* Return the next insn after INSN that is not a NOTE nor DEBUG_INSN.
This routine does not look inside SEQUENCEs. */
+/* FIXME: Rename. */
rtx_insn *
next_nonnote_nondebug_insn (rtx_insn *insn)
{
while (insn)
{
insn = NEXT_INSN (insn);
- if (insn == 0 || (!NOTE_P (insn) && !DEBUG_INSN_P (insn)))
+ if (insn == 0 || (!NOTE_P (insn) && !shadow_insn_p (insn)))
break;
}
@@ -3565,6 +3568,7 @@ next_nonnote_nondebug_insn (rtx_insn *in
but stop the search before we enter another basic block. This
routine does not look inside SEQUENCEs. */
+/* FIXME: Rename. */
rtx_insn *
next_nonnote_nondebug_insn_bb (rtx_insn *insn)
{
@@ -3573,7 +3577,7 @@ next_nonnote_nondebug_insn_bb (rtx_insn
insn = NEXT_INSN (insn);
if (insn == 0)
break;
- if (DEBUG_INSN_P (insn))
+ if (shadow_insn_p (insn))
continue;
if (!NOTE_P (insn))
break;
@@ -3587,13 +3591,14 @@ next_nonnote_nondebug_insn_bb (rtx_insn
/* Return the previous insn before INSN that is not a NOTE nor DEBUG_INSN.
This routine does not look inside SEQUENCEs. */
+/* FIXME: Rename. */
rtx_insn *
prev_nonnote_nondebug_insn (rtx_insn *insn)
{
while (insn)
{
insn = PREV_INSN (insn);
- if (insn == 0 || (!NOTE_P (insn) && !DEBUG_INSN_P (insn)))
+ if (insn == 0 || (!NOTE_P (insn) && !shadow_insn_p (insn)))
break;
}
@@ -3604,6 +3609,7 @@ prev_nonnote_nondebug_insn (rtx_insn *in
DEBUG_INSN, but stop the search before we enter another basic
block. This routine does not look inside SEQUENCEs. */
+/* FIXME: Rename. */
rtx_insn *
prev_nonnote_nondebug_insn_bb (rtx_insn *insn)
{
@@ -3612,7 +3618,7 @@ prev_nonnote_nondebug_insn_bb (rtx_insn
insn = PREV_INSN (insn);
if (insn == 0)
break;
- if (DEBUG_INSN_P (insn))
+ if (shadow_insn_p (insn))
continue;
if (!NOTE_P (insn))
break;
@@ -3661,6 +3667,7 @@ prev_real_insn (rtx_insn *insn)
or 0, if there is none. This routine does not look inside
SEQUENCEs. */
+/* FIXME: Rename. */
rtx_insn *
next_real_nondebug_insn (rtx uncast_insn)
{
@@ -3669,7 +3676,7 @@ next_real_nondebug_insn (rtx uncast_insn
while (insn)
{
insn = NEXT_INSN (insn);
- if (insn == 0 || NONDEBUG_INSN_P (insn))
+ if (insn == 0 || tangible_insn_p (insn))
break;
}
@@ -3680,13 +3687,14 @@ next_real_nondebug_insn (rtx uncast_insn
or 0, if there is none. This routine does not look inside
SEQUENCEs. */
+/* FIXME: Rename. */
rtx_insn *
prev_real_nondebug_insn (rtx_insn *insn)
{
while (insn)
{
insn = PREV_INSN (insn);
- if (insn == 0 || NONDEBUG_INSN_P (insn))
+ if (insn == 0 || tangible_insn_p (insn))
break;
}
@@ -4884,17 +4892,17 @@ emit_pattern_after_setloc (rtx pattern,
}
/* Insert PATTERN after AFTER. MAKE_RAW indicates how to turn PATTERN
- into a real insn. SKIP_DEBUG_INSNS indicates whether to insert after
- any DEBUG_INSNs. */
+ into a real insn. SKIP_SHADOW_INSNS indicates whether to insert after
+ any shadow insns. */
static rtx_insn *
-emit_pattern_after (rtx pattern, rtx_insn *after, bool skip_debug_insns,
+emit_pattern_after (rtx pattern, rtx_insn *after, bool skip_shadow_insns,
rtx_insn *(*make_raw) (rtx))
{
rtx_insn *prev = after;
- if (skip_debug_insns)
- while (DEBUG_INSN_P (prev))
+ if (skip_shadow_insns)
+ while (shadow_insn_p (prev))
prev = PREV_INSN (prev);
if (INSN_P (prev))
@@ -4997,18 +5005,18 @@ emit_pattern_before_setloc (rtx pattern,
}
/* Insert PATTERN before BEFORE. MAKE_RAW indicates how to turn PATTERN
- into a real insn. SKIP_DEBUG_INSNS indicates whether to insert
- before any DEBUG_INSNs. INSNP indicates if PATTERN is meant for an
+ into a real insn. SKIP_SHADOW_INSNS indicates whether to insert
+ before any shadow insns. INSNP indicates if PATTERN is meant for an
INSN as opposed to a JUMP_INSN, CALL_INSN, etc. */
static rtx_insn *
-emit_pattern_before (rtx pattern, rtx_insn *before, bool skip_debug_insns,
+emit_pattern_before (rtx pattern, rtx_insn *before, bool skip_shadow_insns,
bool insnp, rtx_insn *(*make_raw) (rtx))
{
rtx_insn *next = before;
- if (skip_debug_insns)
- while (DEBUG_INSN_P (next))
+ if (skip_shadow_insns)
+ while (shadow_insn_p (next))
next = PREV_INSN (next);
if (INSN_P (next))
Index: gcc/cfgexpand.c
===================================================================
--- gcc/cfgexpand.c 2019-06-23 14:48:15.000000000 +0100
+++ gcc/cfgexpand.c 2019-06-23 14:48:44.491065092 +0100
@@ -4162,7 +4162,14 @@ avoid_deep_ter_for_debug (gimple *stmt,
gimple *g = get_gimple_for_ssa_name (use);
if (g == NULL)
continue;
- if (depth > 6 && !stmt_ends_bb_p (g))
+ /* Use the same depth as avoid_complex_debug_insns for
+ flag_tangible_debug, since we want to enforce it here instead.
+ Also avoid folding any reads from memory, and instead force the
+ result of the read to be available in executable code. */
+ if (flag_tangible_debug
+ && (depth >= 4 || gimple_vuse (g)))
+ bitmap_clear_bit (SA.values, SSA_NAME_VERSION (use));
+ else if (depth > 6 && !stmt_ends_bb_p (g))
{
if (deep_ter_debug_map == NULL)
deep_ter_debug_map = new hash_map<tree, tree>;
@@ -5479,9 +5486,16 @@ expand_debug_locations (void)
}
INSN_VAR_LOCATION_LOC (insn) = val;
- prev_insn = PREV_INSN (insn);
- for (insn2 = insn; insn2 != prev_insn; insn2 = PREV_INSN (insn2))
- avoid_complex_debug_insns (insn2, &INSN_VAR_LOCATION_LOC (insn2), 0);
+ /* Rely on avoid_deep_ter_for_debug for flag_tangible_debug. */
+ if (!flag_tangible_debug)
+ {
+ prev_insn = PREV_INSN (insn);
+ for (insn2 = insn; insn2 != prev_insn; insn2 = PREV_INSN (insn2))
+ {
+ rtx *loc = &INSN_VAR_LOCATION_LOC (insn2);
+ avoid_complex_debug_insns (insn2, loc, 0);
+ }
+ }
}
flag_strict_aliasing = save_strict_alias;
@@ -5683,7 +5697,7 @@ expand_gimple_basic_block (basic_block b
a_2 = ...
#DEBUG ... => #D1
*/
- if (MAY_HAVE_DEBUG_BIND_INSNS
+ if (MAY_HAVE_SHADOW_DEBUG_BIND_INSNS
&& SA.values
&& !is_gimple_debug (stmt))
{
@@ -5854,11 +5868,18 @@ expand_gimple_basic_block (basic_block b
delink_debug_stmt:
/* In order not to generate too many debug temporaries,
- we delink all uses of debug statements we already expanded.
- Therefore debug statements between definition and real
- use of TERed SSA names will continue to use the SSA name,
- and not be replaced with debug temps. */
- delink_stmt_imm_use (stmt);
+ we delink all uses of shadow debug statements we
+ already expanded. Therefore shadow debug statements
+ between the definition and real use of TERed SSA names
+ will continue to use the SSA name, and not be replaced
+ with debug temps.
+
+ Uses in tangible debug stmts are first-class uses,
+ so we shouldn't remove them prematurely. In particular,
+ we don't want an SSA name to appear to have zero uses
+ if it is actually used by tangible debug stmts. */
+ if (!flag_tangible_debug)
+ delink_stmt_imm_use (stmt);
gsi = nsi;
gsi_next (&nsi);
Index: gcc/combine.c
===================================================================
--- gcc/combine.c 2019-06-23 14:48:15.000000000 +0100
+++ gcc/combine.c 2019-06-23 14:48:44.495065059 +0100
@@ -686,7 +686,7 @@ find_single_use (rtx dest, rtx_insn *ins
for (next = NEXT_INSN (insn);
next && BLOCK_FOR_INSN (next) == bb;
next = NEXT_INSN (next))
- if (NONDEBUG_INSN_P (next) && dead_or_set_p (next, dest))
+ if (tangible_insn_p (next) && dead_or_set_p (next, dest))
{
FOR_EACH_LOG_LINK (link, next)
if (link->insn == insn && link->regno == REGNO (dest))
@@ -1072,7 +1072,7 @@ create_log_links (void)
{
FOR_BB_INSNS_REVERSE (bb, insn)
{
- if (!NONDEBUG_INSN_P (insn))
+ if (!tangible_insn_p (insn))
continue;
/* Log links are created only once. */
@@ -1161,7 +1161,7 @@ combine_instructions (rtx_insn *f, unsig
int new_direct_jump_p = 0;
- for (first = f; first && !NONDEBUG_INSN_P (first); )
+ for (first = f; first && !tangible_insn_p (first); )
first = NEXT_INSN (first);
if (!first)
return 0;
@@ -1279,11 +1279,11 @@ combine_instructions (rtx_insn *f, unsig
insn = next ? next : NEXT_INSN (insn))
{
next = 0;
- if (!NONDEBUG_INSN_P (insn))
+ if (!tangible_insn_p (insn))
continue;
while (last_combined_insn
- && (!NONDEBUG_INSN_P (last_combined_insn)
+ && (!tangible_insn_p (last_combined_insn)
|| last_combined_insn->deleted ()))
last_combined_insn = PREV_INSN (last_combined_insn);
if (last_combined_insn == NULL_RTX
@@ -2336,7 +2336,12 @@ cant_combine_insn_p (rtx_insn *insn)
/* If this isn't really an insn, we can't do anything.
This can occur when flow deletes an insn that it has merged into an
- auto-increment address. */
+ auto-increment address.
+
+ Also, prevent combines into tangible debug insns for now, since we
+ don't have any equivalent of recog to keep the result simple and sane.
+ Combine would be useful on debug insns if that changed, in which case
+ the condition should be !tangible_insn_p instead. */
if (!NONDEBUG_INSN_P (insn))
return 1;
@@ -3847,7 +3852,7 @@ try_combine (rtx_insn *i3, rtx_insn *i2,
/* *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_BIND_INSNS)
+ if (MAY_HAVE_SHADOW_DEBUG_BIND_INSNS)
i2src = copy_rtx (i2src);
else
i2src = NULL;
@@ -4221,7 +4226,7 @@ try_combine (rtx_insn *i3, rtx_insn *i2,
return 0;
}
- if (MAY_HAVE_DEBUG_BIND_INSNS)
+ if (MAY_HAVE_SHADOW_DEBUG_BIND_INSNS)
{
struct undo *undo;
@@ -4366,7 +4371,7 @@ try_combine (rtx_insn *i3, rtx_insn *i2,
for (rtx_insn *insn = NEXT_INSN (i3);
!done
&& insn
- && NONDEBUG_INSN_P (insn)
+ && tangible_insn_p (insn)
&& BLOCK_FOR_INSN (insn) == this_basic_block;
insn = NEXT_INSN (insn))
{
@@ -4512,7 +4517,7 @@ try_combine (rtx_insn *i3, rtx_insn *i2,
&& (this_basic_block->next_bb == EXIT_BLOCK_PTR_FOR_FN (cfun)
|| BB_HEAD (this_basic_block) != temp_insn);
temp_insn = NEXT_INSN (temp_insn))
- if (temp_insn != i3 && NONDEBUG_INSN_P (temp_insn))
+ if (temp_insn != i3 && tangible_insn_p (temp_insn))
FOR_EACH_LOG_LINK (link, temp_insn)
if (link->insn == i2)
link->insn = i3;
@@ -4536,7 +4541,7 @@ try_combine (rtx_insn *i3, rtx_insn *i2,
if (newi2pat)
{
- if (MAY_HAVE_DEBUG_BIND_INSNS && i2scratch)
+ if (MAY_HAVE_SHADOW_DEBUG_BIND_INSNS && i2scratch)
propagate_for_debug (i2, last_combined_insn, i2dest, i2src,
this_basic_block);
INSN_CODE (i2) = i2_code_number;
@@ -4544,7 +4549,7 @@ try_combine (rtx_insn *i3, rtx_insn *i2,
}
else
{
- if (MAY_HAVE_DEBUG_BIND_INSNS && i2src)
+ if (MAY_HAVE_SHADOW_DEBUG_BIND_INSNS && i2src)
propagate_for_debug (i2, last_combined_insn, i2dest, i2src,
this_basic_block);
SET_INSN_DELETED (i2);
@@ -4554,7 +4559,7 @@ try_combine (rtx_insn *i3, rtx_insn *i2,
{
LOG_LINKS (i1) = NULL;
REG_NOTES (i1) = 0;
- if (MAY_HAVE_DEBUG_BIND_INSNS)
+ if (MAY_HAVE_SHADOW_DEBUG_BIND_INSNS)
propagate_for_debug (i1, last_combined_insn, i1dest, i1src,
this_basic_block);
SET_INSN_DELETED (i1);
@@ -4564,7 +4569,7 @@ try_combine (rtx_insn *i3, rtx_insn *i2,
{
LOG_LINKS (i0) = NULL;
REG_NOTES (i0) = 0;
- if (MAY_HAVE_DEBUG_BIND_INSNS)
+ if (MAY_HAVE_SHADOW_DEBUG_BIND_INSNS)
propagate_for_debug (i0, last_combined_insn, i0dest, i0src,
this_basic_block);
SET_INSN_DELETED (i0);
@@ -14603,7 +14608,7 @@ distribute_notes (rtx notes, rtx_insn *f
for (tem_insn = PREV_INSN (tem_insn); place == 0; tem_insn = PREV_INSN (tem_insn))
{
- if (!NONDEBUG_INSN_P (tem_insn))
+ if (!tangible_insn_p (tem_insn))
{
if (tem_insn == BB_HEAD (bb))
break;
@@ -14805,7 +14810,7 @@ distribute_notes (rtx notes, rtx_insn *f
for (tem_insn = PREV_INSN (place); ;
tem_insn = PREV_INSN (tem_insn))
{
- if (!NONDEBUG_INSN_P (tem_insn))
+ if (!tangible_insn_p (tem_insn))
{
if (tem_insn == BB_HEAD (bb))
break;
@@ -14931,7 +14936,7 @@ distribute_links (struct insn_link *link
(insn && (this_basic_block->next_bb == EXIT_BLOCK_PTR_FOR_FN (cfun)
|| BB_HEAD (this_basic_block->next_bb) != insn));
insn = NEXT_INSN (insn))
- if (DEBUG_INSN_P (insn))
+ if (!tangible_insn_p (insn))
continue;
else if (INSN_P (insn) && reg_overlap_mentioned_p (reg, PATTERN (insn)))
{
@@ -15025,7 +15030,7 @@ make_more_copies (void)
FOR_BB_INSNS (bb, insn)
{
- if (!NONDEBUG_INSN_P (insn))
+ if (!NONJUMP_INSN_P (insn))
continue;
rtx set = single_set (insn);
Index: gcc/cse.c
===================================================================
--- gcc/cse.c 2019-06-23 14:48:15.000000000 +0100
+++ gcc/cse.c 2019-06-23 14:48:44.499065025 +0100
@@ -4243,7 +4243,7 @@ try_back_substitute_reg (rtx set, rtx_in
{
prev = PREV_INSN (prev);
}
- while (prev != bb_head && (NOTE_P (prev) || DEBUG_INSN_P (prev)));
+ while (prev != bb_head && (NOTE_P (prev) || shadow_insn_p (prev)));
/* Do not swap the registers around if the previous instruction
attaches a REG_EQUIV note to REG1.
@@ -6639,7 +6639,7 @@ cse_extended_basic_block (struct cse_bas
FIXME: This is a real kludge and needs to be done some other
way. */
- if (NONDEBUG_INSN_P (insn)
+ if (tangible_insn_p (insn)
&& num_insns++ > PARAM_VALUE (PARAM_MAX_CSE_INSNS))
{
flush_hash_table ();
@@ -6916,6 +6916,8 @@ count_reg_usage (rtx x, int *counts, rtx
return;
case DEBUG_INSN:
+ if (tangible_insn_p (x))
+ count_reg_usage (INSN_VAR_LOCATION_LOC (x), counts, NULL_RTX, incr);
return;
case CALL_INSN:
@@ -7148,7 +7150,7 @@ delete_trivially_dead_insns (rtx_insn *i
timevar_push (TV_DELETE_TRIVIALLY_DEAD);
/* First count the number of times each register is used. */
- if (MAY_HAVE_DEBUG_BIND_INSNS)
+ if (MAY_HAVE_SHADOW_DEBUG_BIND_INSNS)
{
counts = XCNEWVEC (int, nreg * 3);
for (insn = insns; insn; insn = NEXT_INSN (insn))
@@ -7209,7 +7211,7 @@ delete_trivially_dead_insns (rtx_insn *i
if (! live_insn && dbg_cnt (delete_trivial_dead))
{
- if (DEBUG_INSN_P (insn))
+ if (shadow_insn_p (insn))
{
if (DEBUG_BIND_INSN_P (insn))
count_reg_usage (INSN_VAR_LOCATION_LOC (insn), counts + nreg,
@@ -7218,7 +7220,7 @@ delete_trivially_dead_insns (rtx_insn *i
else
{
rtx set;
- if (MAY_HAVE_DEBUG_BIND_INSNS
+ if (MAY_HAVE_SHADOW_DEBUG_BIND_INSNS
&& (set = single_set (insn)) != NULL_RTX
&& is_dead_reg (SET_DEST (set), counts)
/* Used at least once in some DEBUG_INSN. */
@@ -7258,7 +7260,7 @@ delete_trivially_dead_insns (rtx_insn *i
}
}
- if (MAY_HAVE_DEBUG_BIND_INSNS)
+ if (MAY_HAVE_SHADOW_DEBUG_BIND_INSNS)
{
for (insn = get_last_insn (); insn; insn = PREV_INSN (insn))
if (DEBUG_BIND_INSN_P (insn))
Index: gcc/dce.c
===================================================================
--- gcc/dce.c 2019-06-23 14:48:15.000000000 +0100
+++ gcc/dce.c 2019-06-23 14:48:44.499065025 +0100
@@ -552,6 +552,7 @@ reset_unmarked_insns_debug_uses (void)
{
df_ref use;
+ gcc_assert (shadow_insn_p (insn));
FOR_EACH_INSN_USE (use, insn)
{
struct df_link *defs;
@@ -684,7 +685,7 @@ prescan_insns_for_dce (bool fast)
FOR_EACH_BB_FN (bb, cfun)
{
FOR_BB_INSNS_REVERSE_SAFE (bb, insn, prev)
- if (NONDEBUG_INSN_P (insn))
+ if (tangible_insn_p (insn))
{
/* Don't mark argument stores now. They will be marked
if needed when the associated CALL is marked. */
@@ -737,7 +738,7 @@ mark_reg_dependencies (rtx_insn *insn)
struct df_link *defs;
df_ref use;
- if (DEBUG_INSN_P (insn))
+ if (shadow_insn_p (insn))
return;
FOR_EACH_INSN_USE (use, insn)
@@ -820,7 +821,7 @@ rest_of_handle_ud_dce (void)
}
worklist.release ();
- if (MAY_HAVE_DEBUG_BIND_INSNS)
+ if (MAY_HAVE_SHADOW_DEBUG_BIND_INSNS)
reset_unmarked_insns_debug_uses ();
/* Before any insns are deleted, we must remove the chains since
@@ -919,7 +920,7 @@ word_dce_process_block (basic_block bb,
dead_debug_local_init (&debug, NULL, global_debug);
FOR_BB_INSNS_REVERSE (bb, insn)
- if (DEBUG_INSN_P (insn))
+ if (shadow_insn_p (insn))
{
df_ref use;
FOR_EACH_INSN_USE (use, insn)
@@ -1020,7 +1021,7 @@ dce_process_block (basic_block bb, bool
dead_debug_local_init (&debug, NULL, global_debug);
FOR_BB_INSNS_REVERSE (bb, insn)
- if (DEBUG_INSN_P (insn))
+ if (shadow_insn_p (insn))
{
df_ref use;
FOR_EACH_INSN_USE (use, insn)
Index: gcc/df-problems.c
===================================================================
--- gcc/df-problems.c 2019-06-23 14:48:15.000000000 +0100
+++ gcc/df-problems.c 2019-06-23 14:48:44.499065025 +0100
@@ -835,7 +835,7 @@ df_lr_bb_local_compute (unsigned int bb_
FOR_BB_INSNS_REVERSE (bb, insn)
{
- if (!NONDEBUG_INSN_P (insn))
+ if (!tangible_insn_p (insn))
continue;
df_insn_info *insn_info = DF_INSN_INFO_GET (insn);
@@ -2863,7 +2863,7 @@ df_word_lr_bb_local_compute (unsigned in
FOR_BB_INSNS_REVERSE (bb, insn)
{
- if (!NONDEBUG_INSN_P (insn))
+ if (!tangible_insn_p (insn))
continue;
df_insn_info *insn_info = DF_INSN_INFO_GET (insn);
@@ -3245,7 +3245,7 @@ df_remove_dead_eq_notes (rtx_insn *insn,
static inline void
df_set_note (enum reg_note note_type, rtx_insn *insn, rtx reg)
{
- gcc_checking_assert (!DEBUG_INSN_P (insn));
+ gcc_checking_assert (tangible_insn_p (insn));
add_reg_note (insn, note_type, reg);
}
@@ -3502,9 +3502,9 @@ df_note_bb_compute (unsigned int bb_inde
df_insn_info *insn_info = DF_INSN_INFO_GET (insn);
df_mw_hardreg *mw;
- int debug_insn;
+ int shadow_insn;
- debug_insn = DEBUG_INSN_P (insn);
+ shadow_insn = shadow_insn_p (insn);
bitmap_clear (do_not_gen);
df_remove_dead_and_unused_notes (insn);
@@ -3570,21 +3570,21 @@ df_note_bb_compute (unsigned int bb_inde
if (DF_MWS_REG_USE_P (mw)
&& !df_ignore_stack_reg (mw->start_regno))
{
- bool really_add_notes = debug_insn != 0;
+ bool really_add_notes = shadow_insn != 0;
df_set_dead_notes_for_mw (insn, mw, live, do_not_gen,
artificial_uses,
&really_add_notes);
if (really_add_notes)
- debug_insn = -1;
+ shadow_insn = -1;
}
FOR_EACH_INSN_INFO_USE (use, insn_info)
{
unsigned int uregno = DF_REF_REGNO (use);
- if (REG_DEAD_DEBUGGING && dump_file && !debug_insn)
+ if (REG_DEAD_DEBUGGING && dump_file && !shadow_insn)
{
fprintf (dump_file, " regular looking at use ");
df_ref_debug (use, dump_file);
@@ -3592,9 +3592,9 @@ df_note_bb_compute (unsigned int bb_inde
if (!bitmap_bit_p (live, uregno))
{
- if (debug_insn)
+ if (shadow_insn)
{
- if (debug_insn > 0)
+ if (shadow_insn > 0)
{
/* We won't add REG_UNUSED or REG_DEAD notes for
these, so we don't have to mess with them in
@@ -3630,7 +3630,7 @@ df_note_bb_compute (unsigned int bb_inde
df_remove_dead_eq_notes (insn, live);
- if (debug_insn == -1)
+ if (shadow_insn == -1)
{
/* ??? We could probably do better here, replacing dead
registers with their definitions. */
@@ -3808,7 +3808,7 @@ df_simulate_uses (rtx_insn *insn, bitmap
{
df_ref use;
- if (DEBUG_INSN_P (insn))
+ if (!tangible_insn_p (insn))
return;
FOR_EACH_INSN_USE (use, insn)
@@ -3867,7 +3867,7 @@ df_simulate_initialize_backwards (basic_
void
df_simulate_one_insn_backwards (basic_block bb, rtx_insn *insn, bitmap live)
{
- if (!NONDEBUG_INSN_P (insn))
+ if (!tangible_insn_p (insn))
return;
df_simulate_defs (insn, live);
@@ -4068,9 +4068,9 @@ can_move_insns_across (rtx_insn *from, r
*pmove_upto = NULL;
/* Find real bounds, ignoring debug insns. */
- while (!NONDEBUG_INSN_P (from) && from != to)
+ while (!tangible_insn_p (from) && from != to)
from = NEXT_INSN (from);
- while (!NONDEBUG_INSN_P (to) && from != to)
+ while (!tangible_insn_p (to) && from != to)
to = PREV_INSN (to);
for (insn = across_to; ; insn = next)
@@ -4088,7 +4088,7 @@ can_move_insns_across (rtx_insn *from, r
mem_sets_in_across |= MEMREF_VOLATILE;
}
}
- if (NONDEBUG_INSN_P (insn))
+ if (tangible_insn_p (insn))
{
if (volatile_insn_p (PATTERN (insn)))
return false;
@@ -4125,7 +4125,7 @@ can_move_insns_across (rtx_insn *from, r
df_simulate_initialize_backwards (merge_bb, test_use);
for (insn = across_to; ; insn = next)
{
- if (NONDEBUG_INSN_P (insn))
+ if (tangible_insn_p (insn))
{
df_simulate_find_defs (insn, test_set);
df_simulate_defs (insn, test_use);
@@ -4147,7 +4147,7 @@ can_move_insns_across (rtx_insn *from, r
break;
if (NOTE_P (insn) && NOTE_KIND (insn) == NOTE_INSN_EPILOGUE_BEG)
break;
- if (NONDEBUG_INSN_P (insn))
+ if (tangible_insn_p (insn))
{
if (may_trap_or_fault_p (PATTERN (insn))
&& (trapping_insns_in_across
@@ -4230,7 +4230,7 @@ can_move_insns_across (rtx_insn *from, r
bitmap_and_into (local_merge_live, merge_set);
for (;;)
{
- if (NONDEBUG_INSN_P (insn))
+ if (tangible_insn_p (insn))
{
if (!bitmap_intersect_p (test_set, local_merge_live)
&& (!HAVE_cc0 || !sets_cc0_p (insn)))
Index: gcc/df-scan.c
===================================================================
--- gcc/df-scan.c 2019-06-23 14:48:15.000000000 +0100
+++ gcc/df-scan.c 2019-06-23 14:48:44.499065025 +0100
@@ -681,7 +681,7 @@ df_install_ref_incremental (df_ref ref)
/* By adding the ref directly, df_insn_rescan my not find any
differences even though the block will have changed. So we need
to mark the block dirty ourselves. */
- if (!DEBUG_INSN_P (DF_REF_INSN (ref)))
+ if (tangible_insn_p (DF_REF_INSN (ref)))
df_set_bb_dirty (bb);
}
@@ -956,7 +956,7 @@ df_insn_delete (rtx_insn *insn)
rescanning time and the mark would blow up.
DEBUG_INSNs do not make a block's data flow solution dirty (at
worst the LUIDs are no longer contiguous). */
- if (bb != NULL && NONDEBUG_INSN_P (insn))
+ if (bb != NULL && tangible_insn_p (insn))
df_set_bb_dirty (bb);
/* The client has deferred rescanning. */
@@ -1090,7 +1090,7 @@ df_insn_rescan (rtx_insn *insn)
}
df_refs_add_to_chains (&collection_rec, bb, insn, copy_all);
- if (!DEBUG_INSN_P (insn))
+ if (tangible_insn_p (insn))
df_set_bb_dirty (bb);
return true;
Index: gcc/dse.c
===================================================================
--- gcc/dse.c 2019-06-23 14:48:15.000000000 +0100
+++ gcc/dse.c 2019-06-23 14:48:44.499065025 +0100
@@ -2415,7 +2415,8 @@ scan_insn (bb_info_t bb_info, rtx_insn *
if (DEBUG_INSN_P (insn))
{
insn_info->cannot_delete = true;
- return;
+ if (shadow_insn_p (insn))
+ return;
}
/* Look at all of the uses in the insn. */
Index: gcc/init-regs.c
===================================================================
--- gcc/init-regs.c 2019-06-23 14:48:15.000000000 +0100
+++ gcc/init-regs.c 2019-06-23 14:48:44.503064992 +0100
@@ -68,7 +68,7 @@ initialize_uninitialized_regs (void)
FOR_BB_INSNS (bb, insn)
{
df_ref use;
- if (!NONDEBUG_INSN_P (insn))
+ if (!tangible_insn_p (insn))
continue;
FOR_EACH_INSN_USE (use, insn)
Index: gcc/ira-build.c
===================================================================
--- gcc/ira-build.c 2019-06-23 14:48:15.000000000 +0100
+++ gcc/ira-build.c 2019-06-23 14:48:44.503064992 +0100
@@ -1919,7 +1919,7 @@ create_bb_allocnos (ira_loop_tree_node_t
curr_bb = bb = bb_node->bb;
ira_assert (bb != NULL);
FOR_BB_INSNS_REVERSE (bb, insn)
- if (NONDEBUG_INSN_P (insn))
+ if (tangible_insn_p (insn))
create_insn_allocnos (PATTERN (insn), NULL, false);
/* It might be a allocno living through from one subloop to
another. */
Index: gcc/ira-conflicts.c
===================================================================
--- gcc/ira-conflicts.c 2019-06-23 14:48:15.000000000 +0100
+++ gcc/ira-conflicts.c 2019-06-23 14:48:44.503064992 +0100
@@ -427,7 +427,7 @@ add_copies (ira_loop_tree_node_t loop_tr
if (bb == NULL)
return;
FOR_BB_INSNS (bb, insn)
- if (NONDEBUG_INSN_P (insn))
+ if (tangible_insn_p (insn))
add_insn_allocno_copies (insn);
}
Index: gcc/ira-lives.c
===================================================================
--- gcc/ira-lives.c 2019-06-23 14:48:15.000000000 +0100
+++ gcc/ira-lives.c 2019-06-23 14:48:44.503064992 +0100
@@ -1025,7 +1025,7 @@ find_call_crossed_cheap_reg (rtx_insn *i
while (prev && !(INSN_P (prev)
&& BLOCK_FOR_INSN (prev) != bb))
{
- if (NONDEBUG_INSN_P (prev))
+ if (tangible_insn_p (prev))
{
rtx set = single_set (prev);
@@ -1178,7 +1178,7 @@ process_bb_node_lives (ira_loop_tree_nod
df_ref def, use;
bool call_p;
- if (!NONDEBUG_INSN_P (insn))
+ if (!tangible_insn_p (insn))
continue;
if (internal_flag_ira_verbose > 2 && ira_dump_file != NULL)
Index: gcc/ira.c
===================================================================
--- gcc/ira.c 2019-06-23 14:48:15.000000000 +0100
+++ gcc/ira.c 2019-06-23 14:48:44.507064959 +0100
@@ -3262,7 +3262,7 @@ memref_used_between_p (rtx memref, rtx_i
insn && insn != NEXT_INSN (end);
insn = NEXT_INSN (insn))
{
- if (!NONDEBUG_INSN_P (insn))
+ if (!tangible_insn_p (insn))
continue;
if (memref_referenced_p (memref, PATTERN (insn), false))
@@ -3378,7 +3378,7 @@ def_dominates_uses (int regno)
if (use_info)
{
rtx_insn *use_insn = DF_REF_INSN (use);
- if (!DEBUG_INSN_P (use_insn))
+ if (tangible_insn_p (use_insn))
{
basic_block use_bb = BLOCK_FOR_INSN (use_insn);
if (use_bb != def_bb
@@ -3413,7 +3413,7 @@ update_equiv_regs (void)
prevent access beyond allocated memory for paradoxical memory subreg. */
FOR_EACH_BB_FN (bb, cfun)
FOR_BB_INSNS (bb, insn)
- if (NONDEBUG_INSN_P (insn))
+ if (tangible_insn_p (insn))
set_paradoxical_subreg (insn);
/* Scan the insns and find which registers have equivalences. Do this
@@ -3759,7 +3759,7 @@ combine_and_move_insns (void)
use = DF_REF_NEXT_REG (use))
if (DF_REF_INSN_INFO (use))
{
- if (DEBUG_INSN_P (DF_REF_INSN (use)))
+ if (!tangible_insn_p (DF_REF_INSN (use)))
continue;
gcc_assert (!use_insn);
use_insn = DF_REF_INSN (use);
@@ -3890,7 +3890,7 @@ combine_and_move_insns (void)
}
/* Last pass - adjust debug insns referencing cleared regs. */
- if (MAY_HAVE_DEBUG_BIND_INSNS)
+ if (MAY_HAVE_SHADOW_DEBUG_BIND_INSNS)
for (rtx_insn *insn = get_insns (); insn; insn = NEXT_INSN (insn))
if (DEBUG_BIND_INSN_P (insn))
{
@@ -4288,7 +4288,7 @@ build_insn_chain (void)
bitmap_and_compl_into (live_relevant_regs, elim_regset);
bitmap_copy (&c->live_throughout, live_relevant_regs);
- if (NONDEBUG_INSN_P (insn))
+ if (tangible_insn_p (insn))
FOR_EACH_INSN_INFO_USE (use, insn_info)
{
unsigned int regno = DF_REF_REGNO (use);
@@ -4587,7 +4587,7 @@ find_moveable_pseudos (void)
bitmap_clear (used);
bitmap_clear (set);
FOR_BB_INSNS (bb, insn)
- if (NONDEBUG_INSN_P (insn))
+ if (tangible_insn_p (insn))
{
df_insn_info *insn_info = DF_INSN_INFO_GET (insn);
df_ref def, use;
@@ -4633,7 +4633,7 @@ find_moveable_pseudos (void)
rtx_insn *insn;
FOR_BB_INSNS (bb, insn)
- if (NONDEBUG_INSN_P (insn))
+ if (tangible_insn_p (insn))
{
df_insn_info *insn_info = DF_INSN_INFO_GET (insn);
rtx_insn *def_insn;
@@ -4687,7 +4687,7 @@ find_moveable_pseudos (void)
break;
}
insn = DF_REF_INSN (use);
- if (DEBUG_INSN_P (insn))
+ if (!tangible_insn_p (insn))
continue;
if (BLOCK_FOR_INSN (insn) != BLOCK_FOR_INSN (def_insn))
all_local = false;
@@ -5043,7 +5043,7 @@ split_live_ranges_for_shrink_wrap (void)
rtx_insn *uin = DF_REF_INSN (use);
next = DF_REF_NEXT_REG (use);
- if (DEBUG_INSN_P (uin))
+ if (!tangible_insn_p (uin))
continue;
basic_block ubb = BLOCK_FOR_INSN (uin);
Index: gcc/lra-constraints.c
===================================================================
--- gcc/lra-constraints.c 2019-06-23 14:48:15.000000000 +0100
+++ gcc/lra-constraints.c 2019-06-23 14:48:44.507064959 +0100
@@ -5186,7 +5186,7 @@ add_next_usage_insn (int regno, rtx_insn
if (usage_insns[regno].check == curr_usage_insns_check
&& (next_usage_insns = usage_insns[regno].insns) != NULL_RTX
- && DEBUG_INSN_P (insn))
+ && shadow_insn_p (insn))
{
/* Check that we did not add the debug insn yet. */
if (next_usage_insns != insn
@@ -5195,7 +5195,7 @@ add_next_usage_insn (int regno, rtx_insn
usage_insns[regno].insns = gen_rtx_INSN_LIST (VOIDmode, insn,
next_usage_insns);
}
- else if (NONDEBUG_INSN_P (insn))
+ else if (tangible_insn_p (insn))
setup_next_usage_insn (regno, insn, reloads_num, false);
else
usage_insns[regno].check = 0;
@@ -5385,13 +5385,13 @@ inherit_reload_reg (bool def_p, int orig
if (GET_CODE (next_usage_insns) != INSN_LIST)
{
usage_insn = next_usage_insns;
- lra_assert (NONDEBUG_INSN_P (usage_insn));
+ lra_assert (tangible_insn_p (usage_insn));
next_usage_insns = NULL;
}
else
{
usage_insn = XEXP (next_usage_insns, 0);
- lra_assert (DEBUG_INSN_P (usage_insn));
+ lra_assert (shadow_insn_p (usage_insn));
next_usage_insns = XEXP (next_usage_insns, 1);
}
lra_substitute_pseudo (&usage_insn, original_regno, new_reg, false,
@@ -5727,7 +5727,7 @@ split_reg (bool before_p, int original_r
break;
}
usage_insn = XEXP (next_usage_insns, 0);
- lra_assert (DEBUG_INSN_P (usage_insn));
+ lra_assert (shadow_insn_p (usage_insn));
next_usage_insns = XEXP (next_usage_insns, 1);
lra_substitute_pseudo (&usage_insn, original_regno, new_reg, false,
true);
@@ -5740,7 +5740,7 @@ split_reg (bool before_p, int original_r
}
}
}
- lra_assert (NOTE_P (usage_insn) || NONDEBUG_INSN_P (usage_insn));
+ lra_assert (NOTE_P (usage_insn) || tangible_insn_p (usage_insn));
lra_assert (usage_insn != insn || (after_p && before_p));
lra_process_new_insns (as_a <rtx_insn *> (usage_insn),
after_p ? NULL : restore,
@@ -6052,7 +6052,7 @@ update_ebb_live_info (rtx_insn *head, rt
prev_bb = curr_bb;
bitmap_and (&live_regs, &check_only_regs, df_get_live_out (curr_bb));
}
- if (! NONDEBUG_INSN_P (curr_insn))
+ if (! tangible_insn_p (curr_insn))
continue;
curr_id = lra_get_insn_recog_data (curr_insn);
curr_static_id = curr_id->insn_static_data;
@@ -6148,7 +6148,7 @@ get_last_insertion_point (basic_block bb
rtx_insn *insn;
FOR_BB_INSNS_REVERSE (bb, insn)
- if (NONDEBUG_INSN_P (insn) || NOTE_INSN_BASIC_BLOCK_P (insn))
+ if (tangible_insn_p (insn) || NOTE_INSN_BASIC_BLOCK_P (insn))
return insn;
gcc_unreachable ();
}
@@ -6490,7 +6490,7 @@ inherit_in_ebb (rtx_insn *head, rtx_insn
if (usage_insns[src_regno].check == curr_usage_insns_check
&& (next_usage_insns
= usage_insns[src_regno].insns) != NULL_RTX
- && NONDEBUG_INSN_P (curr_insn))
+ && tangible_insn_p (curr_insn))
add_to_inherit (src_regno, next_usage_insns);
else if (usage_insns[src_regno].check
!= -(int) INSN_UID (curr_insn))
@@ -6506,7 +6506,7 @@ inherit_in_ebb (rtx_insn *head, rtx_insn
before_p = (JUMP_P (curr_insn)
|| (CALL_P (curr_insn) && reg->type == OP_IN));
- if (NONDEBUG_INSN_P (curr_insn)
+ if (tangible_insn_p (curr_insn)
&& (! JUMP_P (curr_insn) || reg->type == OP_IN)
&& split_if_necessary (src_regno, reg->biggest_mode,
potential_reload_hard_regs,
@@ -6520,7 +6520,7 @@ inherit_in_ebb (rtx_insn *head, rtx_insn
if (before_p)
use_insn = PREV_INSN (curr_insn);
}
- if (NONDEBUG_INSN_P (curr_insn))
+ if (tangible_insn_p (curr_insn))
{
if (src_regno < FIRST_PSEUDO_REGISTER)
add_to_hard_reg_set (&live_hard_regs,
@@ -6557,8 +6557,7 @@ inherit_in_ebb (rtx_insn *head, rtx_insn
setup_next_usage_insn (src_regno, curr_insn, reloads_num, false);
}
}
- if (update_reloads_num_p
- && NONDEBUG_INSN_P (curr_insn) && curr_set != NULL_RTX)
+ if (update_reloads_num_p && curr_set != NULL_RTX)
{
int regno = -1;
if ((REG_P (SET_DEST (curr_set))
@@ -6577,6 +6576,7 @@ inherit_in_ebb (rtx_insn *head, rtx_insn
reg_class_contents[cl]);
}
}
+ /* Debug insns never set registers, regardless of tangibility. */
if (NONDEBUG_INSN_P (curr_insn))
{
int regno;
@@ -6763,7 +6763,7 @@ delete_move_and_clobber (rtx_insn *insn,
lra_set_insn_deleted (insn);
lra_assert (dregno >= 0);
- if (prev_insn != NULL && NONDEBUG_INSN_P (prev_insn)
+ if (prev_insn != NULL && NONJUMP_INSN_P (prev_insn)
&& GET_CODE (PATTERN (prev_insn)) == CLOBBER
&& dregno == get_regno (XEXP (PATTERN (prev_insn), 0)))
lra_set_insn_deleted (prev_insn);
@@ -6810,7 +6810,7 @@ remove_inheritance_pseudos (bitmap remov
continue;
done_p = false;
sregno = dregno = -1;
- if (change_p && NONDEBUG_INSN_P (curr_insn)
+ if (change_p && NONJUMP_INSN_P (curr_insn)
&& (set = single_set (curr_insn)) != NULL_RTX)
{
dregno = get_regno (SET_DEST (set));
@@ -6887,7 +6887,7 @@ remove_inheritance_pseudos (bitmap remov
change the current insn onto:
original_pseudo <- inherit_or_split_pseudo2. */
for (prev_insn = PREV_INSN (curr_insn);
- prev_insn != NULL_RTX && ! NONDEBUG_INSN_P (prev_insn);
+ prev_insn != NULL_RTX && ! tangible_insn_p (prev_insn);
prev_insn = PREV_INSN (prev_insn))
;
if (prev_insn != NULL_RTX && BLOCK_FOR_INSN (prev_insn) == bb
@@ -6969,7 +6969,7 @@ remove_inheritance_pseudos (bitmap remov
kept_regs_p = true;
}
}
- if (NONDEBUG_INSN_P (curr_insn) && kept_regs_p)
+ if (tangible_insn_p (curr_insn) && kept_regs_p)
{
/* The instruction has changed since the previous
constraints pass. */
Index: gcc/lra-lives.c
===================================================================
--- gcc/lra-lives.c 2019-06-23 14:48:15.000000000 +0100
+++ gcc/lra-lives.c 2019-06-23 14:48:44.507064959 +0100
@@ -703,7 +703,7 @@ process_bb_lives (basic_block bb, int &c
rtx set;
struct lra_insn_reg *reg, *hr;
- if (!NONDEBUG_INSN_P (curr_insn))
+ if (!tangible_insn_p (curr_insn))
continue;
curr_id = lra_get_insn_recog_data (curr_insn);
Index: gcc/lra-remat.c
===================================================================
--- gcc/lra-remat.c 2019-06-23 14:48:15.000000000 +0100
+++ gcc/lra-remat.c 2019-06-23 14:48:44.507064959 +0100
@@ -444,7 +444,7 @@ create_cands (void)
/* Create candidates. */
regno_potential_cand = XCNEWVEC (struct potential_cand, max_reg_num ());
for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
- if (NONDEBUG_INSN_P (insn))
+ if (tangible_insn_p (insn))
{
lra_insn_recog_data_t id = lra_get_insn_recog_data (insn);
int keep_regno = -1;
@@ -646,7 +646,7 @@ calculate_local_reg_remat_bb_data (void)
FOR_EACH_BB_FN (bb, cfun)
FOR_BB_INSNS (bb, insn)
- if (NONDEBUG_INSN_P (insn))
+ if (tangible_insn_p (insn))
set_bb_regs (bb, insn);
}
@@ -1080,7 +1080,7 @@ do_remat (void)
bitmap_copy (active_cands, avail_cands);
FOR_BB_INSNS (bb, insn)
{
- if (!NONDEBUG_INSN_P (insn))
+ if (!tangible_insn_p (insn))
continue;
lra_insn_recog_data_t id = lra_get_insn_recog_data (insn);
Index: gcc/lra.c
===================================================================
--- gcc/lra.c 2019-06-23 14:48:15.000000000 +0100
+++ gcc/lra.c 2019-06-23 14:48:44.507064959 +0100
@@ -552,7 +552,7 @@ new_insn_reg (rtx_insn *insn, int regno,
lra_insn_reg *ir = lra_insn_reg_pool.allocate ();
ir->type = type;
ir->biggest_mode = mode;
- if (NONDEBUG_INSN_P (insn)
+ if (tangible_insn_p (insn)
&& partial_subreg_p (lra_reg_info[regno].biggest_mode, mode))
lra_reg_info[regno].biggest_mode = mode;
ir->subreg_p = subreg_p;
@@ -1576,6 +1576,8 @@ add_regs_to_insn_regno_info (lra_insn_re
static int
get_insn_freq (rtx_insn *insn)
{
+ if (DEBUG_INSN_P (insn))
+ return 0;
basic_block bb = BLOCK_FOR_INSN (insn);
gcc_checking_assert (bb != NULL);
@@ -1589,19 +1591,19 @@ invalidate_insn_data_regno_info (lra_ins
int freq)
{
int uid;
- bool debug_p;
unsigned int i;
struct lra_insn_reg *ir, *next_ir;
uid = INSN_UID (insn);
- debug_p = DEBUG_INSN_P (insn);
+ bool shadow_p = shadow_insn_p (insn);
+ gcc_assert (!DEBUG_INSN_P (insn) || freq == 0);
for (ir = data->regs; ir != NULL; ir = next_ir)
{
i = ir->regno;
next_ir = ir->next;
lra_insn_reg_pool.remove (ir);
bitmap_clear_bit (&lra_reg_info[i].insn_bitmap, uid);
- if (i >= FIRST_PSEUDO_REGISTER && ! debug_p)
+ if (i >= FIRST_PSEUDO_REGISTER && ! shadow_p)
{
lra_reg_info[i].nrefs--;
lra_reg_info[i].freq -= freq;
@@ -1651,7 +1653,7 @@ lra_update_insn_regno_info (rtx_insn *in
return;
data = lra_get_insn_recog_data (insn);
static_data = data->insn_static_data;
- freq = NONDEBUG_INSN_P (insn) ? get_insn_freq (insn) : 0;
+ freq = get_insn_freq (insn);
invalidate_insn_data_regno_info (data, insn, freq);
for (i = static_data->n_operands - 1; i >= 0; i--)
add_regs_to_insn_regno_info (data, *data->operand_loc[i], insn,
@@ -1679,7 +1681,7 @@ lra_update_insn_regno_info (rtx_insn *in
add_regs_to_insn_regno_info (data, XEXP (XEXP (link, 0), 0), insn,
code == USE ? OP_IN : OP_OUT, false, 0);
}
- if (NONDEBUG_INSN_P (insn))
+ if (tangible_insn_p (insn))
setup_insn_reg_info (data, freq);
}
@@ -2306,7 +2308,7 @@ update_inc_notes (void)
FOR_EACH_BB_FN (bb, cfun)
FOR_BB_INSNS (bb, insn)
- if (NONDEBUG_INSN_P (insn))
+ if (tangible_insn_p (insn))
{
pnote = ®_NOTES (insn);
while (*pnote != 0)
Index: gcc/reg-stack.c
===================================================================
--- gcc/reg-stack.c 2019-06-23 14:48:15.000000000 +0100
+++ gcc/reg-stack.c 2019-06-23 14:48:44.507064959 +0100
@@ -3059,12 +3059,23 @@ convert_regs_1 (basic_block block)
{
subst_all_stack_regs_in_debug_insn (insn, ®stack);
- /* Nothing must ever die at a debug insn. If something
- is referenced in it that becomes dead, it should have
- died before and the reference in the debug insn
- should have been removed so as to avoid changing code
- generation. */
- gcc_assert (!find_reg_note (insn, REG_DEAD, NULL));
+ for (rtx note = REG_NOTES (insn); note; note = XEXP (note, 1))
+ if (REG_NOTE_KIND (note) == REG_DEAD)
+ {
+ /* Registers must never die at a shadow insn. If something
+ is referenced in it that becomes dead, it should have
+ died before and the reference in the shadow insn
+ should have been removed so as to avoid changing code
+ generation. */
+ gcc_assert (!shadow_insn_p (insn));
+ rtx reg = XEXP (note, 0);
+ if (STACK_REG_P (reg))
+ {
+ gcc_assert (TEST_HARD_REG_BIT (regstack.reg_set,
+ REGNO (reg)));
+ emit_pop_insn (insn, ®stack, reg, EMIT_AFTER);
+ }
+ }
}
}
else if (stack_regs_mentioned (insn)
Index: gcc/regstat.c
===================================================================
--- gcc/regstat.c 2019-06-23 14:48:15.000000000 +0100
+++ gcc/regstat.c 2019-06-23 14:48:44.507064959 +0100
@@ -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_BIND_INSNS)
+ if (MAY_HAVE_SHADOW_DEBUG_BIND_INSNS)
for (i = 0; i < max_regno; i++)
{
int use_count;
@@ -141,7 +141,7 @@ regstat_bb_compute_ri (basic_block bb, b
bitmap_iterator bi;
rtx link;
- if (!NONDEBUG_INSN_P (insn))
+ if (!tangible_insn_p (insn))
continue;
link = REG_NOTES (insn);
@@ -327,7 +327,7 @@ regstat_bb_compute_calls_crossed (unsign
struct df_insn_info *insn_info = DF_INSN_INFO_GET (insn);
unsigned int regno;
- if (!NONDEBUG_INSN_P (insn))
+ if (!tangible_insn_p (insn))
continue;
/* Process the defs. */
Index: gcc/rtlanal.c
===================================================================
--- gcc/rtlanal.c 2019-06-23 14:48:15.000000000 +0100
+++ gcc/rtlanal.c 2019-06-23 14:48:44.511064925 +0100
@@ -1127,7 +1127,7 @@ reg_used_between_p (const_rtx reg, const
return 0;
for (insn = NEXT_INSN (from_insn); insn != to_insn; insn = NEXT_INSN (insn))
- if (NONDEBUG_INSN_P (insn)
+ if (tangible_insn_p (insn)
&& (reg_overlap_mentioned_p (reg, PATTERN (insn))
|| (CALL_P (insn) && find_reg_fusage (insn, USE, reg))))
return 1;
Index: gcc/shrink-wrap.c
===================================================================
--- gcc/shrink-wrap.c 2019-06-23 14:48:15.000000000 +0100
+++ gcc/shrink-wrap.c 2019-06-23 14:48:44.511064925 +0100
@@ -309,7 +309,7 @@ move_insn_for_shrink_wrap (basic_block b
move it as far as we can. */
do
{
- if (MAY_HAVE_DEBUG_BIND_INSNS)
+ if (MAY_HAVE_SHADOW_DEBUG_BIND_INSNS)
{
FOR_BB_INSNS_REVERSE (bb, dinsn)
if (DEBUG_BIND_INSN_P (dinsn))
@@ -456,7 +456,7 @@ prepare_shrink_wrap (basic_block entry_b
CLEAR_HARD_REG_SET (defs);
FOR_BB_INSNS_REVERSE_SAFE (entry_block, insn, curr)
- if (NONDEBUG_INSN_P (insn)
+ if (tangible_insn_p (insn)
&& !move_insn_for_shrink_wrap (entry_block, insn, uses, defs,
&split_p, &debug))
{
@@ -682,7 +682,7 @@ try_shrink_wrapping (edge *entry_edge, r
CLEAR_HARD_REG_SET (prologue_clobbered);
CLEAR_HARD_REG_SET (prologue_used);
for (rtx_insn *insn = prologue_seq; insn; insn = NEXT_INSN (insn))
- if (NONDEBUG_INSN_P (insn))
+ if (tangible_insn_p (insn))
{
HARD_REG_SET this_used;
CLEAR_HARD_REG_SET (this_used);
@@ -731,7 +731,7 @@ try_shrink_wrapping (edge *entry_edge, r
{
rtx_insn *insn;
FOR_BB_INSNS (bb, insn)
- if (NONDEBUG_INSN_P (insn)
+ if (tangible_insn_p (insn)
&& requires_stack_frame_p (insn, prologue_used,
set_up_by_prologue.set))
{
Index: gcc/tree-cfg.c
===================================================================
--- gcc/tree-cfg.c 2019-06-23 14:48:15.000000000 +0100
+++ gcc/tree-cfg.c 2019-06-23 14:48:44.511064925 +0100
@@ -2796,7 +2796,7 @@ first_stmt (basic_block bb)
gimple_stmt_iterator i = gsi_start_bb (bb);
gimple *stmt = NULL;
- while (!gsi_end_p (i) && is_gimple_debug ((stmt = gsi_stmt (i))))
+ while (!gsi_end_p (i) && !tangible_stmt_p ((stmt = gsi_stmt (i))))
{
gsi_next (&i);
stmt = NULL;
@@ -2823,7 +2823,7 @@ last_stmt (basic_block bb)
gimple_stmt_iterator i = gsi_last_bb (bb);
gimple *stmt = NULL;
- while (!gsi_end_p (i) && is_gimple_debug ((stmt = gsi_stmt (i))))
+ while (!gsi_end_p (i) && !tangible_stmt_p ((stmt = gsi_stmt (i))))
{
gsi_prev (&i);
stmt = NULL;
@@ -6114,7 +6114,7 @@ gimple_empty_block_p (basic_block bb)
while (!gsi_end_p (gsi))
{
gimple *stmt = gsi_stmt (gsi);
- if (is_gimple_debug (stmt))
+ if (!tangible_stmt_p (stmt))
;
else if (gimple_code (stmt) == GIMPLE_NOP
|| gimple_code (stmt) == GIMPLE_PREDICT)
Index: gcc/tree-cfgcleanup.c
===================================================================
--- gcc/tree-cfgcleanup.c 2019-06-23 14:48:15.000000000 +0100
+++ gcc/tree-cfgcleanup.c 2019-06-23 14:48:44.511064925 +0100
@@ -377,6 +377,8 @@ tree_forwarder_block_p (basic_block bb,
/* ??? For now, hope there's a corresponding debug
assignment at the destination. */
case GIMPLE_DEBUG:
+ if (tangible_stmt_p (stmt))
+ return false;
break;
default:
Index: gcc/tree-inline.c
===================================================================
--- gcc/tree-inline.c 2019-06-23 14:48:15.000000000 +0100
+++ gcc/tree-inline.c 2019-06-23 14:48:44.511064925 +0100
@@ -194,7 +194,7 @@ remap_ssa_name (tree name, copy_body_dat
if (n)
return unshare_expr (*n);
- if (processing_debug_stmt)
+ if (processing_debug_stmt && !flag_tangible_debug)
{
if (SSA_NAME_IS_DEFAULT_DEF (name)
&& TREE_CODE (SSA_NAME_VAR (name)) == PARM_DECL
@@ -344,6 +344,9 @@ remap_decl (tree decl, copy_body_data *i
n = id->decl_map->get (decl);
+ /* This applies even for flag_tangible_debug. If the executable code
+ doesn't do anything with the decl, we should reset the debug stmt
+ rather than make it refer to an uninitialized decl. */
if (!n && processing_debug_stmt)
{
processing_debug_stmt = -1;
@@ -2447,7 +2450,7 @@ copy_edges_for_bb (basic_block bb, profi
{
if (!gsi_end_p (si))
{
- while (!gsi_end_p (si) && is_gimple_debug (gsi_stmt (si)))
+ while (!gsi_end_p (si) && !tangible_stmt_p (gsi_stmt (si)))
gsi_next (&si);
if (gsi_end_p (si))
need_debug_cleanup = true;
Index: gcc/tree-into-ssa.c
===================================================================
--- gcc/tree-into-ssa.c 2019-06-23 14:48:15.000000000 +0100
+++ gcc/tree-into-ssa.c 2019-06-23 14:48:44.511064925 +0100
@@ -652,7 +652,7 @@ mark_def_sites (basic_block bb, gimple *
set_register_defs (stmt, false);
set_rewrite_uses (stmt, false);
- if (is_gimple_debug (stmt))
+ if (!tangible_stmt_p (stmt))
{
FOR_EACH_SSA_USE_OPERAND (use_p, stmt, iter, SSA_OP_USE)
{
@@ -1257,6 +1257,7 @@ rewrite_debug_stmt_uses (gimple *stmt)
if (TREE_CODE (var) == PARM_DECL
&& single_succ_p (ENTRY_BLOCK_PTR_FOR_FN (cfun)))
{
+ gcc_assert (!flag_tangible_debug);
gimple_stmt_iterator gsi
=
gsi_after_labels (single_succ (ENTRY_BLOCK_PTR_FOR_FN (cfun)));
@@ -1367,7 +1368,7 @@ rewrite_stmt (gimple_stmt_iterator *si)
/* Step 1. Rewrite USES in the statement. */
if (rewrite_uses_p (stmt))
{
- if (is_gimple_debug (stmt))
+ if (!tangible_stmt_p (stmt))
rewrite_debug_stmt_uses (stmt);
else
FOR_EACH_SSA_USE_OPERAND (use_p, stmt, iter, SSA_OP_ALL_USES)
@@ -2006,7 +2007,7 @@ rewrite_update_stmt (gimple *stmt, gimpl
symbol is marked for renaming. */
if (rewrite_uses_p (stmt))
{
- if (is_gimple_debug (stmt))
+ if (!tangible_stmt_p (stmt))
{
bool failed = false;
@@ -2572,7 +2573,7 @@ mark_use_interesting (tree var, gimple *
{
set_rewrite_uses (stmt, true);
- if (is_gimple_debug (stmt))
+ if (!tangible_stmt_p (stmt))
return;
}
Index: gcc/tree-ssa-coalesce.c
===================================================================
--- gcc/tree-ssa-coalesce.c 2019-06-23 14:48:15.000000000 +0100
+++ gcc/tree-ssa-coalesce.c 2019-06-23 14:48:44.515064892 +0100
@@ -910,7 +910,7 @@ build_ssa_conflict_graph (tree_live_info
&& TREE_CODE (rhs1) == SSA_NAME)
live_track_clear_var (live, rhs1);
}
- else if (is_gimple_debug (stmt))
+ else if (!tangible_stmt_p (stmt))
continue;
/* For stmts with more than one SSA_NAME definition pretend all the
@@ -1090,9 +1090,6 @@ create_coalesce_list_for_region (var_map
{
stmt = gsi_stmt (gsi);
- if (is_gimple_debug (stmt))
- continue;
-
/* Check for copy coalesces. */
switch (gimple_code (stmt))
{
Index: gcc/tree-ssa-dce.c
===================================================================
--- gcc/tree-ssa-dce.c 2019-06-23 14:48:15.000000000 +0100
+++ gcc/tree-ssa-dce.c 2019-06-23 14:48:44.515064892 +0100
@@ -114,6 +114,26 @@ #define STMT_NECESSARY GF_PLF_1
/* When non-NULL holds map from basic block index into the postorder. */
static int *bb_postorder;
+/* Return true if we'll turn STMT into a debug bind if it turns out
+ to be dead. */
+
+static bool
+replace_with_debug_bind_p (gimple *stmt)
+{
+ gcc_checking_assert (MAY_HAVE_DEBUG_BIND_STMTS);
+ if (gimple_assign_single_p (stmt)
+ && is_gimple_val (gimple_assign_rhs1 (stmt)))
+ {
+ tree lhs = gimple_assign_lhs (stmt);
+ if ((VAR_P (lhs) || TREE_CODE (lhs) == PARM_DECL)
+ && !DECL_IGNORED_P (lhs)
+ && is_gimple_reg_type (TREE_TYPE (lhs))
+ && !is_global_var (lhs)
+ && !DECL_HAS_VALUE_EXPR_P (lhs))
+ return true;
+ }
+ return false;
+}
/* If STMT is not already marked necessary, mark it, and add it to the
worklist if ADD_TO_WORKLIST is true. */
@@ -136,7 +156,7 @@ mark_stmt_necessary (gimple *stmt, bool
gimple_set_plf (stmt, STMT_NECESSARY, true);
if (add_to_worklist)
worklist.safe_push (stmt);
- if (add_to_worklist && bb_contains_live_stmts && !is_gimple_debug (stmt))
+ if (add_to_worklist && bb_contains_live_stmts && tangible_stmt_p (stmt))
bitmap_set_bit (bb_contains_live_stmts, gimple_bb (stmt)->index);
}
@@ -270,7 +290,7 @@ mark_stmt_if_obviously_necessary (gimple
|| !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);
+ mark_stmt_necessary (stmt, tangible_stmt_p (stmt));
return;
case GIMPLE_GOTO:
@@ -311,6 +331,17 @@ mark_stmt_if_obviously_necessary (gimple
return;
}
+ /* If debug stmts are tangible, and if we'd replace the stmt with a
+ debug stmt when deleting it, make sure that its operands are
+ available even then. */
+ if (MAY_HAVE_DEBUG_BIND_STMTS
+ && flag_tangible_debug
+ && replace_with_debug_bind_p (stmt))
+ {
+ worklist.safe_push (stmt);
+ return;
+ }
+
return;
}
@@ -1072,22 +1103,12 @@ remove_dead_stmt (gimple_stmt_iterator *
/* If this is a store into a variable that is being optimized away,
add a debug bind stmt if possible. */
- if (MAY_HAVE_DEBUG_BIND_STMTS
- && gimple_assign_single_p (stmt)
- && is_gimple_val (gimple_assign_rhs1 (stmt)))
+ if (MAY_HAVE_DEBUG_BIND_STMTS && replace_with_debug_bind_p (stmt))
{
tree lhs = gimple_assign_lhs (stmt);
- if ((VAR_P (lhs) || TREE_CODE (lhs) == PARM_DECL)
- && !DECL_IGNORED_P (lhs)
- && is_gimple_reg_type (TREE_TYPE (lhs))
- && !is_global_var (lhs)
- && !DECL_HAS_VALUE_EXPR_P (lhs))
- {
- tree rhs = gimple_assign_rhs1 (stmt);
- gdebug *note
- = gimple_build_debug_bind (lhs, unshare_expr (rhs), stmt);
- gsi_insert_after (i, note, GSI_SAME_STMT);
- }
+ tree rhs = gimple_assign_rhs1 (stmt);
+ gdebug *note = gimple_build_debug_bind (lhs, unshare_expr (rhs), stmt);
+ gsi_insert_after (i, note, GSI_SAME_STMT);
}
unlink_stmt_vdef (stmt);
@@ -1299,7 +1320,7 @@ eliminate_unnecessary_stmts (void)
continue;
}
}
- if (!is_gimple_debug (stmt))
+ if (tangible_stmt_p (stmt))
something_changed = true;
remove_dead_stmt (&gsi, bb, to_remove_edges);
continue;
Index: gcc/tree-ssa-live.c
===================================================================
--- gcc/tree-ssa-live.c 2019-06-23 14:48:15.000000000 +0100
+++ gcc/tree-ssa-live.c 2019-06-23 14:48:44.515064892 +0100
@@ -762,7 +762,7 @@ remove_unused_locals (void)
entry point marker as used, this would be a good spot to
do it. If the block is not otherwise used, the stmt will
be cleaned up in clean_unused_block_pointer. */
- if (is_gimple_debug (stmt))
+ if (!tangible_stmt_p (stmt))
continue;
if (gimple_clobber_p (stmt))
@@ -1083,9 +1083,7 @@ set_var_live_on_entry (tree ssa_name, tr
if (e->src != def_bb && region_contains_p (live->map, e->src))
add_block = e->src;
}
- else if (is_gimple_debug (use_stmt))
- continue;
- else
+ else if (tangible_stmt_p (use_stmt))
{
/* If its not defined in this block, its live on entry. */
basic_block use_bb = gimple_bb (use_stmt);
Index: gcc/tree-ssa-loop-ivopts.c
===================================================================
--- gcc/tree-ssa-loop-ivopts.c 2019-06-23 14:48:15.000000000 +0100
+++ gcc/tree-ssa-loop-ivopts.c 2019-06-23 14:48:44.515064892 +0100
@@ -2701,7 +2701,7 @@ find_interesting_uses (struct ivopts_dat
for (bsi = gsi_start_phis (bb); !gsi_end_p (bsi); gsi_next (&bsi))
find_interesting_uses_stmt (data, gsi_stmt (bsi));
for (bsi = gsi_start_bb (bb); !gsi_end_p (bsi); gsi_next (&bsi))
- if (!is_gimple_debug (gsi_stmt (bsi)))
+ if (tangible_stmt_p (gsi_stmt (bsi)))
find_interesting_uses_stmt (data, gsi_stmt (bsi));
}
free (body);
@@ -7308,7 +7308,7 @@ remove_unused_ivs (struct ivopts_data *d
tree def = info->iv->ssa_name;
- if (MAY_HAVE_DEBUG_BIND_STMTS && SSA_NAME_DEF_STMT (def))
+ if (MAY_HAVE_SHADOW_DEBUG_BIND_STMTS && SSA_NAME_DEF_STMT (def))
{
imm_use_iterator imm_iter;
use_operand_p use_p;
Index: gcc/tree-ssa-loop-manip.c
===================================================================
--- gcc/tree-ssa-loop-manip.c 2019-06-23 14:48:15.000000000 +0100
+++ gcc/tree-ssa-loop-manip.c 2019-06-23 14:48:44.515064892 +0100
@@ -409,7 +409,7 @@ find_uses_to_rename_stmt (gimple *stmt,
tree var;
basic_block bb = gimple_bb (stmt);
- if (is_gimple_debug (stmt))
+ if (!tangible_stmt_p (stmt))
return;
/* FOR_EACH_SSA_TREE_OPERAND iterator does not allows SSA_OP_VIRTUAL_USES
@@ -494,7 +494,7 @@ find_uses_to_rename_def (tree def, bitma
FOR_EACH_IMM_USE_STMT (use_stmt, imm_iter, def)
{
- if (is_gimple_debug (use_stmt))
+ if (!tangible_stmt_p (use_stmt))
continue;
basic_block use_bb = gimple_bb (use_stmt);
@@ -699,7 +699,7 @@ check_loop_closed_ssa_def (basic_block d
imm_use_iterator iterator;
FOR_EACH_IMM_USE_FAST (use_p, iterator, def)
{
- if (is_gimple_debug (USE_STMT (use_p)))
+ if (!tangible_stmt_p (USE_STMT (use_p)))
continue;
basic_block use_bb = gimple_bb (USE_STMT (use_p));
Index: gcc/tree-ssa-sink.c
===================================================================
--- gcc/tree-ssa-sink.c 2019-06-23 14:48:15.000000000 +0100
+++ gcc/tree-ssa-sink.c 2019-06-23 14:48:44.515064892 +0100
@@ -110,7 +110,7 @@ all_immediate_uses_same_place (def_opera
gimple *firstuse = NULL;
FOR_EACH_IMM_USE_FAST (use_p, imm_iter, var)
{
- if (is_gimple_debug (USE_STMT (use_p)))
+ if (!tangible_stmt_p (USE_STMT (use_p)))
continue;
if (firstuse == NULL)
firstuse = USE_STMT (use_p);
@@ -146,7 +146,7 @@ nearest_common_dominator_of_uses (def_op
useblock = gimple_phi_arg_edge (phi, idx)->src;
}
- else if (is_gimple_debug (usestmt))
+ else if (!tangible_stmt_p (usestmt))
{
*debug_stmts = true;
continue;
@@ -425,7 +425,7 @@ statement_sink_location (gimple *stmt, b
{
FOR_EACH_IMM_USE_FAST (one_use, imm_iter, DEF_FROM_PTR (def_p))
{
- if (is_gimple_debug (USE_STMT (one_use)))
+ if (!tangible_stmt_p (USE_STMT (one_use)))
continue;
break;
}
Index: gcc/tree-ssa-ter.c
===================================================================
--- gcc/tree-ssa-ter.c 2019-06-23 14:48:15.000000000 +0100
+++ gcc/tree-ssa-ter.c 2019-06-23 14:48:44.515064892 +0100
@@ -585,7 +585,7 @@ find_replaceable_in_bb (temp_expr_table
{
stmt = gsi_stmt (bsi);
- if (is_gimple_debug (stmt))
+ if (!tangible_stmt_p (stmt))
continue;
stmt_replaceable = ter_is_replaceable_p (stmt);
Index: gcc/fortran/trans-types.c
===================================================================
--- gcc/fortran/trans-types.c 2019-06-23 14:48:15.000000000 +0100
+++ gcc/fortran/trans-types.c 2019-06-23 14:48:44.503064992 +0100
@@ -3373,7 +3373,13 @@ gfc_get_array_descr_info (const_tree typ
base_decl = GFC_TYPE_ARRAY_BASE_DECL (type, indirect);
if (!base_decl)
{
+ /* This DEBUG_EXPR_DECL is just a dummy decl that has the nice
+ property of not affecting the DECL_UIDs of real decls. It's
+ therefore OK to create it even for flag_tangible_debug. */
+ bool save_flag_tangible_debug = flag_tangible_debug;
+ flag_tangible_debug = false;
base_decl = make_node (DEBUG_EXPR_DECL);
+ flag_tangible_debug = save_flag_tangible_debug;
DECL_ARTIFICIAL (base_decl) = 1;
TREE_TYPE (base_decl) = indirect ? build_pointer_type (ptype) : ptype;
SET_DECL_MODE (base_decl, TYPE_MODE (TREE_TYPE (base_decl)));
Index: gcc/testsuite/c-c++-common/guality/Og-dead-1.c
===================================================================
--- /dev/null 2019-06-14 15:59:19.298479944 +0100
+++ gcc/testsuite/c-c++-common/guality/Og-dead-1.c 2019-06-23 14:48:44.511064925 +0100
@@ -0,0 +1,19 @@
+/* { dg-do run } */
+/* { dg-options "-g" } */
+
+int x = 42;
+
+void __attribute__ ((noipa))
+foo (int *ptr)
+{
+ int c = *ptr;
+ ptr[0] = 1;
+ int a = c;
+ ptr[1] = 2; /* { dg-final { gdb-test . a "42" } } */
+}
+
+int
+main (void)
+{
+ foo (&x);
+}
Index: gcc/testsuite/gcc.dg/guality/guality.exp
===================================================================
--- gcc/testsuite/gcc.dg/guality/guality.exp 2019-06-23 14:48:36.315133217 +0100
+++ gcc/testsuite/gcc.dg/guality/guality.exp 2019-06-23 14:48:44.511064925 +0100
@@ -81,8 +81,22 @@ if {[check_guality "
return 0;
}
"] || 1} {
- gcc-dg-runtest [lsort [glob $srcdir/$subdir/*.c]] "" ""
- gcc-dg-runtest [lsort [glob $srcdir/c-c++-common/guality/*.c]] "" "-Wc++-compat"
+ set general [list]
+ set Og [list]
+ foreach file [lsort [glob $srcdir/c-c++-common/guality/*.c]] {
+ switch -glob -- [file tail $file] {
+ Og-* { lappend Og $file }
+ * { lappend general $file }
+ }
+ }
+
+ gcc-dg-runtest [lsort [glob $srcdir/$subdir/*.c]] "" ""
+ gcc-dg-runtest $general "" "-Wc++-compat"
+ set-torture-options \
+ [list "-O0" "-Og"] \
+ [list {}] \
+ [list "-Og -flto"]
+ gcc-dg-runtest $Og "" "-Wc++-compat"
}
if [info exists guality_gdb_name] {
Index: gcc/testsuite/g++.dg/guality/guality.exp
===================================================================
--- gcc/testsuite/g++.dg/guality/guality.exp 2019-06-23 14:48:36.315133217 +0100
+++ gcc/testsuite/g++.dg/guality/guality.exp 2019-06-23 14:48:44.511064925 +0100
@@ -66,8 +66,22 @@ if {[check_guality "
return 0;
}
"] || 1} {
- gcc-dg-runtest [lsort [glob $srcdir/$subdir/*.C]] "" ""
- gcc-dg-runtest [lsort [glob $srcdir/c-c++-common/guality/*.c]] "" ""
+ set general [list]
+ set Og [list]
+ foreach file [lsort [glob $srcdir/c-c++-common/guality/*.c]] {
+ switch -glob -- [file tail $file] {
+ Og-* { lappend Og $file }
+ * { lappend general $file }
+ }
+ }
+
+ gcc-dg-runtest [lsort [glob $srcdir/$subdir/*.C]] "" ""
+ gcc-dg-runtest $general "" ""
+ set-torture-options \
+ [list "-O0" "-Og"] \
+ [list {}] \
+ [list "-Og -flto"]
+ gcc-dg-runtest $Og "" ""
}
if [info exists guality_gdb_name] {
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCH 0/3] RFC: Keep debug values live for -Og
2019-06-23 13:51 [PATCH 0/3] RFC: Let debug stmts influence codegen at -Og Richard Sandiford
2019-06-23 13:52 ` [PATCH 1/3] RFC: Add a mode in which debug stmts participate in codegen Richard Sandiford
@ 2019-06-23 13:53 ` Richard Sandiford
2019-06-23 13:53 ` [PATCH 3/3] RFC: Add -O1g Richard Sandiford
` (4 subsequent siblings)
6 siblings, 0 replies; 12+ messages in thread
From: Richard Sandiford @ 2019-06-23 13:53 UTC (permalink / raw)
To: gcc-patches
This patch tries to make sure that, when optimising at -Og, the gimple
IL has appropriate debug information for the whole of a variable's scope.
It does the same for parameters in functions that always return (but still
misses cases in functions that don't return -- a TODO for later).
The idea is to emit a debug stmt that uses each gimple register "var"
when it goes out of scope. With the new "tangible" debug stmts, this
forces SSA renaming of "var" for its entire lifetime, even after the
last real use. This in turn means that we should enter rtl in a state
where, at any given point in a variable's scope, there is a single
dominating debug bind insn for it.
A side-effect of this is that a variable that is in-scope but
uninitialised and unused will give "0" rather than "<optimized out>"
(where the zero is guaranteed by init-regs). E.g. for functions like:
static inline void
get_conflict_and_start_profitable_regs (ira_allocno_t a, bool retry_p,
HARD_REG_SET *conflict_regs,
HARD_REG_SET *start_profitable_regs)
{
int i, nwords;
ira_object_t obj;
nwords = ALLOCNO_NUM_OBJECTS (a);
for (i = 0; i < nwords; i++)
{
obj = ALLOCNO_OBJECT (a, i);
COPY_HARD_REG_SET (conflict_regs[i],
OBJECT_TOTAL_CONFLICT_HARD_REGS (obj));
}
if (retry_p)
{
COPY_HARD_REG_SET (*start_profitable_regs,
reg_class_contents[ALLOCNO_CLASS (a)]);
AND_COMPL_HARD_REG_SET (*start_profitable_regs,
ira_prohibited_class_mode_regs
[ALLOCNO_CLASS (a)][ALLOCNO_MODE (a)]);
}
else
COPY_HARD_REG_SET (*start_profitable_regs,
ALLOCNO_COLOR_DATA (a)->profitable_hard_regs);
}
it is still possible to print "obj" after the loop. If nwords is <= 0
(which it never is in practice), "obj" would print as zero.
IMO this isn't wrong debug info, because the value that we print for
"obj" is the value that a printf at that location would print, even in
the uninitialised/zero case. And this kind of for loop is very common:
the program in practice guarantees that the loop executes at least once,
and thus guarantees that "obj" has a useful value, but the compiler
doesn't know that.
The patch uses debug insns of the form:
# DEBUG NULL => var
to keep "var" live. Binding to null seemed better than binding to "var",
which is about to go out of scope and doesn't actually change value here.
Binding to null also means that we can delete the stmt if no longer has
any SSA uses (e.g. due to fwprop). Most of the patch is just adding
support for null debug bind vars.
Although this should ensure we have good-quality debug info for gimple
registers when entering rtl, it doesn't guarantee that the value bound
in a debug bind insn remains live for as long as the debug bind is in effect.
That's a separate patch.
It's also possible that rtl cfg manipulations could break the original
property of having one dominating debug bind at each point. That too
is a separate patch. It probably makes sense to fix both of these
problems immediately before IRA.
The patch fixes the referenced PRs. In particular, the backtrace for
PR78685 is now:
#0 call_debugger (x=x@entry=3) at pr78685.c:6
#1 ... in apply_lambda (fun=fun@entry=1, args=args@entry=2, count=count@entry=3) at pr78685.c:14
#2 ... in main (argc=1, argv=0x<addr>) at pr78685.c:22
instead of:
#0 call_debugger (x=3) at pr78685.c:6
#1 ... in apply_lambda (fun=1, args=2, count=<optimized out>) at pr78685.c:14
#2 ... in main (argc=<optimized out>, argv=<optimized out>) at pr78685.c:22
2019-06-23 Richard Sandiford <richard.sandiford@arm.com>
gcc/
PR debug/78685
PR debug/88730
* gimplify.c (gimplify_keep_decl_live): New function.
(gimplify_bind_expr, gimplify_return_expr): Use it.
* function.c (gimplify_parameters): Add debug stmts for parameters
if flag_tangible_debug.
* var-tracking.c (use_type): Drop debug binds with null variables.
(delete_vta_debug_insn): Likewise.
* gimple-low.c (lower_stmt): Allow debug binds too.
* cfgexpand.c (expand_debug_locations): Handle null debug bind vars.
(expand_gimple_basic_block): Likewise.
* cfgrtl.c (duplicate_insn_chain): Likewise.
* cse.c (insn_live_p): Likewise.
* omp-simd-clone.c (ipa_simd_modify_function_body): Likewise.
* print-rtl.c (rtx_writer::print_rtx, print_insn): Likewise.
* tree-cfg.c (make_blocks_1, stmt_starts_bb_p): Handle tangible
debug stmts like normal stmts.
(make_blocks): Check for marker stmts rather than asserting for them.
(gimple_duplicate_bb): Handle null debug bind vars.
* tree-inline.c (maybe_move_debug_stmts_to_successors): Likewise.
(copy_debug_stmt): Likewise.
* tree-parloops.c (separate_decls_in_region_debug): Likewise.
* tree-ssa-threadedge.c (propagate_threaded_block_debug_into):
Likewise.
* tree-ssa-dce.c (eliminate_unnecessary_stmts): Likewise.
(mark_stmt_if_obviously_necessary): Likewise. Allow debug binds
with null variables to be deleted if they no longer have any
SSA uses.
gcc/testsuite/
* c-c++-common/guality/Og-keep-alive-1.c: New test.
* c-c++-common/guality/Og-pr88730.c: Likewise.
Index: gcc/gimplify.c
===================================================================
--- gcc/gimplify.c 2019-06-18 09:35:54.925869432 +0100
+++ gcc/gimplify.c 2019-06-23 14:48:55.226975633 +0100
@@ -1300,6 +1300,28 @@ asan_poison_variables (hash_set<tree> *v
}
}
+/* If DECL is a parameter or variable that we're going to rewrite into
+ SSA form, emit a "# DEBUG NULL => DECL" statement to make it live at
+ the end of SEQ, which is the point at which DECL dies. This is only
+ valid for flag_tangible_debug.
+
+ Doing this ensures that we have an SSA name definition of DECL
+ throughout its lifetime, which as a side-effect ensures that a debug
+ binding for T is always available throughout its lifetime. We can
+ then try to optimize away the SSA names, but only if doing so doesn't
+ compromise the debug bindings. */
+
+static void
+gimplify_keep_decl_live (gimple_seq *seq, tree decl)
+{
+ gcc_assert (MAY_HAVE_DEBUG_BIND_STMTS && flag_tangible_debug);
+ if (is_gimple_reg (decl) && target_for_debug_bind (decl))
+ {
+ gdebug *debug = gimple_build_debug_bind (NULL_TREE, decl, NULL);
+ gimplify_seq_add_stmt (seq, debug);
+ }
+}
+
/* Gimplify a BIND_EXPR. Just voidify and recurse. */
static enum gimplify_status
@@ -1434,6 +1456,11 @@ gimplify_bind_expr (tree *expr_p, gimple
&& !is_global_var (t)
&& DECL_CONTEXT (t) == current_function_decl)
{
+ if (MAY_HAVE_DEBUG_BIND_INSNS && flag_tangible_debug)
+ /* Ensure that the variable's value is available for debug
+ purposes throughout its lifetime. */
+ gimplify_keep_decl_live (&cleanup, t);
+
if (!DECL_HARD_REGISTER (t)
&& !TREE_THIS_VOLATILE (t)
&& !DECL_HAS_VALUE_EXPR_P (t)
@@ -1629,6 +1656,14 @@ gimplify_return_expr (tree stmt, gimple_
gimplify_and_add (TREE_OPERAND (stmt, 0), pre_p);
+ if (MAY_HAVE_DEBUG_BIND_STMTS && flag_tangible_debug)
+ /* If we're going to rewrite a parameter into SSA form, ensure that
+ the parameter's value is available for debug purposes throughout
+ its lifetime. */
+ for (tree decl = DECL_ARGUMENTS (current_function_decl);
+ decl; decl = DECL_CHAIN (decl))
+ gimplify_keep_decl_live (pre_p, decl);
+
maybe_add_early_return_predict_stmt (pre_p);
ret = gimple_build_return (result);
gimple_set_no_warning (ret, TREE_NO_WARNING (stmt));
Index: gcc/function.c
===================================================================
--- gcc/function.c 2019-06-21 15:37:49.635878948 +0100
+++ gcc/function.c 2019-06-23 14:48:55.222975666 +0100
@@ -3906,6 +3906,17 @@ gimplify_parameters (gimple_seq *cleanup
DECL_HAS_VALUE_EXPR_P (parm) = 1;
}
}
+ if (flag_tangible_debug
+ && is_gimple_reg (parm)
+ && target_for_debug_bind (parm))
+ {
+ /* This will be rewritten during SSA renaming to
+ "# DEBUG parm => parm_N(D)". In functions that return,
+ the return statements have partnering "# DEBUG NULL => parm_M",
+ statements. */
+ gdebug *debug = gimple_build_debug_bind (parm, parm, NULL);
+ gimple_seq_add_stmt_without_update (&stmts, debug);
+ }
}
fnargs.release ();
Index: gcc/var-tracking.c
===================================================================
--- gcc/var-tracking.c 2019-06-07 08:39:43.686343024 +0100
+++ gcc/var-tracking.c 2019-06-23 14:48:55.234975566 +0100
@@ -5508,7 +5508,10 @@ use_type (rtx loc, struct count_use_info
{
if (GET_CODE (loc) == VAR_LOCATION)
{
- if (track_expr_p (PAT_VAR_LOCATION_DECL (loc), false))
+ /* The point of debug binds with no variable is to keep values
+ live until this pass runs. We can drop them here. */
+ if (PAT_VAR_LOCATION_DECL (loc)
+ && track_expr_p (PAT_VAR_LOCATION_DECL (loc), false))
{
rtx ploc = PAT_VAR_LOCATION_LOC (loc);
if (! VAR_LOC_UNKNOWN_P (ploc))
@@ -10315,7 +10318,8 @@ delete_vta_debug_insn (rtx_insn *insn)
}
tree decl = INSN_VAR_LOCATION_DECL (insn);
- if (TREE_CODE (decl) == LABEL_DECL
+ if (decl
+ && TREE_CODE (decl) == LABEL_DECL
&& DECL_NAME (decl)
&& !DECL_RTL_SET_P (decl))
{
Index: gcc/gimple-low.c
===================================================================
--- gcc/gimple-low.c 2019-06-18 09:35:54.121876078 +0100
+++ gcc/gimple-low.c 2019-06-23 14:48:55.222975666 +0100
@@ -309,18 +309,25 @@ lower_stmt (gimple_stmt_iterator *gsi, s
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;
+ {
+ bool keep_p;
+ if (gimple_debug_nonbind_marker_p (stmt))
+ {
+ gcc_assert (cfun->debug_nonbind_markers);
+ keep_p = MAY_HAVE_DEBUG_MARKER_STMTS;
+ }
+ else if (gimple_debug_bind_p (stmt)
+ || gimple_debug_source_bind_p (stmt))
+ keep_p = MAY_HAVE_DEBUG_BIND_STMTS;
+ else
+ gcc_unreachable ();
+
+ if (keep_p)
+ gsi_next (gsi);
+ else
+ gsi_remove (gsi, true);
+ return;
+ }
case GIMPLE_NOP:
case GIMPLE_ASM:
Index: gcc/cfgexpand.c
===================================================================
--- gcc/cfgexpand.c 2019-06-23 14:48:44.491065092 +0100
+++ gcc/cfgexpand.c 2019-06-23 14:48:55.222975666 +0100
@@ -5455,6 +5455,7 @@ expand_debug_locations (void)
being defined in this DEBUG_INSN. */
else if (deep_ter_debug_map && TREE_CODE (value) == SSA_NAME)
{
+ gcc_assert (INSN_VAR_LOCATION_DECL (insn));
tree *slot = deep_ter_debug_map->get (value);
if (slot)
{
@@ -5796,19 +5797,22 @@ expand_gimple_basic_block (basic_block b
{
var = gimple_debug_bind_get_var (stmt);
- if (TREE_CODE (var) != DEBUG_EXPR_DECL
+ if (var
+ && TREE_CODE (var) != DEBUG_EXPR_DECL
&& TREE_CODE (var) != LABEL_DECL
&& !target_for_debug_bind (var))
goto delink_debug_stmt;
- if (DECL_P (var))
+ if (gimple_debug_bind_has_value_p (stmt))
+ value = gimple_debug_bind_get_value (stmt);
+
+ if (!var)
+ mode = TYPE_MODE (TREE_TYPE (value));
+ else if (DECL_P (var))
mode = DECL_MODE (var);
else
mode = TYPE_MODE (TREE_TYPE (var));
- 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);
}
Index: gcc/cfgrtl.c
===================================================================
--- gcc/cfgrtl.c 2019-06-07 08:39:43.690343015 +0100
+++ gcc/cfgrtl.c 2019-06-23 14:48:55.222975666 +0100
@@ -4185,6 +4185,7 @@ duplicate_insn_chain (rtx_insn *from, rt
case DEBUG_INSN:
/* Don't duplicate label debug insns. */
if (DEBUG_BIND_INSN_P (insn)
+ && INSN_VAR_LOCATION_DECL (insn)
&& TREE_CODE (INSN_VAR_LOCATION_DECL (insn)) == LABEL_DECL)
break;
/* FALLTHRU */
Index: gcc/cse.c
===================================================================
--- gcc/cse.c 2019-06-23 14:48:44.499065025 +0100
+++ gcc/cse.c 2019-06-23 14:48:55.222975666 +0100
@@ -7068,6 +7068,8 @@ insn_live_p (rtx_insn *insn, int *counts
we want to keep the earlier debug insn. */
else if (DEBUG_MARKER_INSN_P (next))
return true;
+ else if (!INSN_VAR_LOCATION_DECL (insn))
+ return true;
else if (INSN_VAR_LOCATION_DECL (insn) == INSN_VAR_LOCATION_DECL (next))
return false;
Index: gcc/omp-simd-clone.c
===================================================================
--- gcc/omp-simd-clone.c 2019-03-18 12:24:58.391436179 +0000
+++ gcc/omp-simd-clone.c 2019-06-23 14:48:55.226975633 +0100
@@ -1073,6 +1073,7 @@ ipa_simd_modify_function_body (struct cg
vectorized loops doesn't work too well, so don't bother for
now. */
if ((gimple_debug_bind_p (stmt)
+ && gimple_debug_bind_get_var (stmt)
&& !DECL_P (gimple_debug_bind_get_var (stmt)))
|| (gimple_debug_source_bind_p (stmt)
&& !DECL_P (gimple_debug_source_bind_get_var (stmt))))
Index: gcc/print-rtl.c
===================================================================
--- gcc/print-rtl.c 2019-06-07 08:39:59.000000000 +0100
+++ gcc/print-rtl.c 2019-06-23 14:48:55.226975633 +0100
@@ -861,7 +861,9 @@ rtx_writer::print_rtx (const_rtx in_rtx)
#ifndef GENERATOR_FILE
if (GET_CODE (in_rtx) == VAR_LOCATION)
{
- if (TREE_CODE (PAT_VAR_LOCATION_DECL (in_rtx)) == STRING_CST)
+ if (!PAT_VAR_LOCATION_DECL (in_rtx))
+ fputs (" <none>", m_outfile);
+ else if (TREE_CODE (PAT_VAR_LOCATION_DECL (in_rtx)) == STRING_CST)
fputs (" <debug string placeholder>", m_outfile);
else
print_mem_expr (m_outfile, PAT_VAR_LOCATION_DECL (in_rtx));
@@ -1914,7 +1916,8 @@ print_insn (pretty_printer *pp, const rt
const char *name = "?";
char idbuf[32];
- if (DECL_P (INSN_VAR_LOCATION_DECL (x)))
+ if (INSN_VAR_LOCATION_DECL (x)
+ && DECL_P (INSN_VAR_LOCATION_DECL (x)))
{
tree id = DECL_NAME (INSN_VAR_LOCATION_DECL (x));
if (id)
Index: gcc/tree-cfg.c
===================================================================
--- gcc/tree-cfg.c 2019-06-23 14:48:44.511064925 +0100
+++ gcc/tree-cfg.c 2019-06-23 14:48:55.230975600 +0100
@@ -524,15 +524,15 @@ make_blocks_1 (gimple_seq seq, basic_blo
while (!gsi_end_p (i))
{
- /* PREV_STMT should only be set to a debug stmt if the debug
- stmt is before nondebug stmts. Once stmt reaches a nondebug
+ /* PREV_STMT should only be set to a shadow stmt if the shadow
+ stmt is before tangible stmts. Once stmt reaches a tangible
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
+ found. However, if stmt was a label after shadow stmts only,
+ keep the label in prev_stmt even if we find further shadow
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))
+ if (!prev_stmt || !stmt || tangible_stmt_p (stmt))
prev_stmt = stmt;
stmt = gsi_stmt (i);
@@ -633,9 +633,8 @@ make_blocks (gimple_seq seq)
continue;
/* Move the debug stmt at I after LABEL. */
- if (is_gimple_debug (stmt))
+ if (gimple_debug_nonbind_marker_p (stmt))
{
- gcc_assert (gimple_debug_nonbind_marker_p (stmt));
/* As STMT is removed, I advances to the stmt after
STMT, so the gsi_prev in the for "increment"
expression gets us to the stmt we're to visit after
@@ -2705,11 +2704,11 @@ stmt_starts_bb_p (gimple *stmt, gimple *
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))
+ /* PREV_STMT is only set to a shadow stmt if the shadow stmt is before
+ any tangible stmts in the block. We don't want to start another
+ block in this case: the shadow stmt will already have started the
+ one STMT would start if we weren't outputting shadow stmts. */
+ if (prev_stmt && !tangible_stmt_p (prev_stmt))
return false;
/* Labels start a new basic block only if the preceding statement
@@ -6196,6 +6195,7 @@ gimple_duplicate_bb (basic_block bb, cop
/* Don't duplicate label debug stmts. */
if (gimple_debug_bind_p (stmt)
+ && gimple_debug_bind_get_var (stmt)
&& TREE_CODE (gimple_debug_bind_get_var (stmt))
== LABEL_DECL)
continue;
Index: gcc/tree-inline.c
===================================================================
--- gcc/tree-inline.c 2019-06-23 14:48:44.511064925 +0100
+++ gcc/tree-inline.c 2019-06-23 14:48:55.230975600 +0100
@@ -2760,8 +2760,10 @@ maybe_move_debug_stmts_to_successors (co
value = unshare_expr (value);
new_stmt = gimple_build_debug_bind (var, value, stmt);
}
- else
+ else if (var)
new_stmt = gimple_build_debug_bind (var, NULL_TREE, NULL);
+ else
+ continue;
}
else if (gimple_debug_source_bind_p (stmt))
{
@@ -3060,16 +3062,19 @@ copy_debug_stmt (gdebug *stmt, copy_body
else
gcc_unreachable ();
- if (TREE_CODE (t) == PARM_DECL && id->debug_map
- && (n = id->debug_map->get (t)))
+ if (t)
{
- gcc_assert (VAR_P (*n));
- t = *n;
+ if (TREE_CODE (t) == PARM_DECL && id->debug_map
+ && (n = id->debug_map->get (t)))
+ {
+ gcc_assert (VAR_P (*n));
+ t = *n;
+ }
+ else if (VAR_P (t) && !is_global_var (t) && !id->decl_map->get (t))
+ /* T is a non-localized variable. */;
+ else
+ walk_tree (&t, remap_gimple_op_r, &wi, NULL);
}
- else if (VAR_P (t) && !is_global_var (t) && !id->decl_map->get (t))
- /* T is a non-localized variable. */;
- else
- walk_tree (&t, remap_gimple_op_r, &wi, NULL);
if (gimple_debug_bind_p (stmt))
{
Index: gcc/tree-parloops.c
===================================================================
--- gcc/tree-parloops.c 2019-06-18 09:35:54.197875448 +0100
+++ gcc/tree-parloops.c 2019-06-23 14:48:55.230975600 +0100
@@ -950,23 +950,27 @@ separate_decls_in_region_debug (gimple *
name_to_copy_elt **slot;
int_tree_map *dslot;
+ /* FIXME */
if (gimple_debug_bind_p (stmt))
var = gimple_debug_bind_get_var (stmt);
else if (gimple_debug_source_bind_p (stmt))
var = gimple_debug_source_bind_get_var (stmt);
else
return true;
- if (TREE_CODE (var) == DEBUG_EXPR_DECL || TREE_CODE (var) == LABEL_DECL)
- return true;
- gcc_assert (DECL_P (var) && SSA_VAR_P (var));
- ielt.uid = DECL_UID (var);
- dslot = decl_copies->find_slot_with_hash (ielt, ielt.uid, NO_INSERT);
- if (!dslot)
- return true;
- if (gimple_debug_bind_p (stmt))
- gimple_debug_bind_set_var (stmt, dslot->to);
- else if (gimple_debug_source_bind_p (stmt))
- gimple_debug_source_bind_set_var (stmt, dslot->to);
+ if (var)
+ {
+ if (TREE_CODE (var) == DEBUG_EXPR_DECL || TREE_CODE (var) == LABEL_DECL)
+ return true;
+ gcc_assert (DECL_P (var) && SSA_VAR_P (var));
+ ielt.uid = DECL_UID (var);
+ dslot = decl_copies->find_slot_with_hash (ielt, ielt.uid, NO_INSERT);
+ if (!dslot)
+ return true;
+ if (gimple_debug_bind_p (stmt))
+ gimple_debug_bind_set_var (stmt, dslot->to);
+ else if (gimple_debug_source_bind_p (stmt))
+ gimple_debug_source_bind_set_var (stmt, dslot->to);
+ }
FOR_EACH_PHI_OR_STMT_USE (use, stmt, oi, SSA_OP_USE)
{
Index: gcc/tree-ssa-threadedge.c
===================================================================
--- gcc/tree-ssa-threadedge.c 2019-06-18 09:35:55.505864640 +0100
+++ gcc/tree-ssa-threadedge.c 2019-06-23 14:48:55.234975566 +0100
@@ -803,10 +803,13 @@ propagate_threaded_block_debug_into (bas
else
gcc_unreachable ();
- if (vars)
- vars->add (var);
- else
- fewvars.quick_push (var);
+ if (var)
+ {
+ if (vars)
+ vars->add (var);
+ else
+ fewvars.quick_push (var);
+ }
}
basic_block bb = dest;
@@ -844,9 +847,9 @@ propagate_threaded_block_debug_into (bas
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))
+ if (var && vars && vars->add (var))
continue;
- else if (!vars)
+ if (var && !vars)
{
int i = fewvars.length ();
while (i--)
Index: gcc/tree-ssa-dce.c
===================================================================
--- gcc/tree-ssa-dce.c 2019-06-23 14:48:44.515064892 +0100
+++ gcc/tree-ssa-dce.c 2019-06-23 14:48:55.230975600 +0100
@@ -282,15 +282,26 @@ mark_stmt_if_obviously_necessary (gimple
}
case GIMPLE_DEBUG:
- /* Debug temps without a value are not useful. ??? If we could
- 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_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, tangible_stmt_p (stmt));
+ if (gimple_debug_bind_p (stmt))
+ {
+ tree var = gimple_debug_bind_get_var (stmt);
+
+ /* Debug temps without a value are not useful. ??? If we could
+ 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 (var
+ && TREE_CODE (var) == DEBUG_EXPR_DECL
+ && !gimple_debug_bind_has_value_p (stmt))
+ return;
+
+ /* "# DEBUG NULL => foo" only exists to keep foo live till this
+ point (and initially to force SSA renaming). Drop it if it
+ no longer has any effect. */
+ if (!var && !gimple_use_ops (stmt))
+ return;
+ }
+ mark_stmt_necessary (stmt, tangible_stmt_p (stmt));
return;
case GIMPLE_GOTO:
@@ -1399,7 +1410,8 @@ eliminate_unnecessary_stmts (void)
non-DEBUG_EXPR_DECL variable in a series of
debug-bind stmts. */
tree var = gimple_debug_bind_get_var (stmt);
- if (TREE_CODE (var) != DEBUG_EXPR_DECL
+ if (var
+ && TREE_CODE (var) != DEBUG_EXPR_DECL
&& !bitmap_set_bit (debug_seen, DECL_UID (var)))
remove_dead_stmt (&gsi, bb, to_remove_edges);
continue;
Index: gcc/testsuite/c-c++-common/guality/Og-keep-alive-1.c
===================================================================
--- /dev/null 2019-06-14 15:59:19.298479944 +0100
+++ gcc/testsuite/c-c++-common/guality/Og-keep-alive-1.c 2019-06-23 14:48:55.226975633 +0100
@@ -0,0 +1,30 @@
+/* { dg-do run } */
+/* { dg-options "-g" } */
+
+#include "../../gcc.dg/nop.h"
+
+int __attribute__ ((noipa))
+f (int a)
+{
+ int b, c;
+ if (a < 10)
+ {
+ b = 3;
+ c = b + a;
+ }
+ else
+ {
+ b = 2;
+ c = b - a;
+ }
+ asm volatile (NOP); /* { dg-final { gdb-test . "a" "10" } } */
+ /* { dg-final { gdb-test .-1 "b" "2" } } */
+ /* { dg-final { gdb-test .-2 "c" "-8" } } */
+ return c;
+}
+
+int
+main (void)
+{
+ f (10);
+}
Index: gcc/testsuite/c-c++-common/guality/Og-pr88730.c
===================================================================
--- /dev/null 2019-06-14 15:59:19.298479944 +0100
+++ gcc/testsuite/c-c++-common/guality/Og-pr88730.c 2019-06-23 14:48:55.226975633 +0100
@@ -0,0 +1,16 @@
+/* { dg-do run } */
+/* { dg-options "-g" } */
+
+#include "../../gcc.dg/nop.h"
+
+int a;
+int main() {
+ int b, j;
+ b = 0;
+ for (; b < 1; b++) {
+ j = 0;
+ for (; j < 5; j++)
+ ;
+ }
+ asm volatile (NOP); /* { dg-final { gdb-test . "j" "5" } } */
+}
^ permalink raw reply [flat|nested] 12+ messages in thread