public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
* [PATCH 0/3] RFC: Let debug stmts influence codegen at -Og
@ 2019-06-23 13:51 Richard Sandiford
  2019-06-23 13:52 ` [PATCH 1/3] RFC: Add a mode in which debug stmts participate in codegen Richard Sandiford
                   ` (6 more replies)
  0 siblings, 7 replies; 12+ messages in thread
From: Richard Sandiford @ 2019-06-23 13:51 UTC (permalink / raw)
  To: gcc-patches

-Og is documented as:

  @option{-Og} should be the optimization
  level of choice for the standard edit-compile-debug cycle, offering
  a reasonable level of optimization while maintaining fast compilation
  and a good debugging experience.  It is a better choice than @option{-O0}
  for producing debuggable code because some compiler passes
  that collect debug information are disabled at @option{-O0}.

One of the things hampering that is that, as for the "normal" -O* flags,
the code produced by -Og -g must be the same as the code produced
without any debug IL at all.  There are many cases in which that makes
it impossible to stop useful values from being optimised out of the
debug info, either because the value simply isn't available at runtime
at the point that the debugger needs it, or because of limitations in
the debug representation.  (E.g. pointers to external data are dropped
from debug info because the relocations wouldn't be honoured.)

I think it would be better to flip things around so that the debug IL
is always present when optimising at -Og, and then allow the debug IL
to influence codegen at -Og.  This still honours the -fcompare-debug
principle, and the compile speed of -Og without -g doesn't seem very
important.

This series therefore adds a mode in which debug stmts and debug insns
are present even without -g and are explicitly allowed to affect codegen.
In particular, when this mode is active:

- 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

This needs a new term to distinguish stmts/insns that affect codegen
from those that don't.  I couldn't think of one that I was really
happy with, but possibilities included:

    tangible/shadow
    manifest/hidden
    foreground/background
    reactive/inert
    active/dormant   (but "active insn" already means something else)
    peppy/sullen

The series uses tangible/shadow.  There's a new global flag_tangible_debug
that controls whether debug insns are "tangible" insns (for the new mode)
or "shadow" insns (for normal optimisation).  -Og enables the new mode
while the other optimisation levels leave it off.  (Despite the name,
the new variable is just an internal flag, there's no -ftangible-debug
option.)

The first patch adds the infrastructure but doesn't improve the debug
experience much on its own.

As an example of one thing we can do with the new mode, the second patch
ensures that the gimple IL has debug info for each is_gimple_reg variable
throughout the variable's lifetime.  This fixes a couple of the PRs in
the -Og meta-bug and from spot-testing seems to ensure that far fewer
values are optimised out.

Also, the new mode is mostly orthogonal to the optimisation level
(although it would in effect disable optimisations like loop
vectorisation, until we have a way of representing debug info for
vectorised loops).  The third patch therefore adds an -O1g option
that optimises more heavily than -Og but provides a better debug
experience than -O1.

I think -O2g would make sense too, and would be a viable option
for people who want to deploy relatively heavily optimised binaries
without compromising the debug experience too much.

Other possible follow-ons for the new mode include:

- Make sure that tangible debug stmts never read memory or take
  an address.  (This is so that addressability and vops depend
  only on non-debug insns.)

- Fall back on expanding real code if expand_debug_expr fails.

- Force debug insns to be simple enough for dwarf2out (e.g. no external
  or TLS symbols).  This could be done by having a validation step for
  debug insns, like we already do for normal insns.

- Prevent the removal of dead stores if it would lead to wrong debug info.
  (Maybe under control of an option?)

To get an idea of the runtime cost, I tried compiling tree-into-ssa.ii
at -O2 -g with various --enable-checking=yes builds of cc1plus:

                            time taken
cc1plus compiled with -O0:     100.00%   (baseline)
cc1plus compiled with old -Og:  30.94%
cc1plus compiled with new -Og:  31.82%
cc1plus compiled with -O1g:     28.22%
cc1plus compiled with -O1:      26.72%
cc1plus compiled with -O2:      25.15%

So there is a noticeable but small performance cost to the new mode.

To get an idea of the compile-time impact, I tried compiling
tree-into-ssa.ii at various optimisation levels, all using the
same --enable-checking=release bootstrap build:

                              time taken
tree-into-ssa.ii with -O0 -g:     100.0%  (baseline)
tree-into-ssa.ii with old -Og -g: 180.6%
tree-into-ssa.ii with new -Og -g: 198.2%
tree-into-ssa.ii with -O1g -g:    237.1%
tree-into-ssa.ii with -O1 -g:     211.8%
tree-into-ssa.ii with -O2 -g:     331.5%

So there's definitely a bit of a compile-time hit.  I haven't yet looked
at how easy it would be to fix.

What do you think?  Is it worth pursuing this further?

Of course, even if we do do this, it's still important that the debug
info for things like -O2 -g is as good as it can be.  I just think some
of the open bugs against -Og fundamentally can't be fixed properly while
-Og remains a cut-down version of -O1.

Thanks,
Richard

^ permalink raw reply	[flat|nested] 12+ messages in thread

* [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 = &REG_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, &regstack);
 
-	      /* 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, &regstack, 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

* [PATCH 3/3] RFC: Add -O1g
  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 ` [PATCH 0/3] RFC: Keep debug values live for -Og Richard Sandiford
@ 2019-06-23 13:53 ` Richard Sandiford
  2019-06-24 12:24 ` [PATCH 0/3] RFC: Let debug stmts influence codegen at -Og Richard Biener
                   ` (3 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 adds an option called -O1g, a half-way house between
-Og and -O1 in terms of both performance and debuggability.


2019-06-23  Richard Sandiford  <richard.sandiford@arm.com>

config/
	* bootstrap-O1g.mk: New file.

gcc/
	* common.opt (O1g): New option.
	* doc/invoke.texi: Document it.
	* opts.c (default_options_optimization): Handle it.
	(common_handle_option): Likewise.

gcc/testsuite/
	* g++.dg/guality/guality.exp: Add "-O1g -g" to the list of options
	to try for Og-* tests.
	* gcc.dg/guality/guality.exp: Likewise.
	* gcc.dg/sso/sso.exp (SSO_TORTURE_OPTIONS): Add "-O1g -g".
	* gnat.dg/sso/sso.exp (SSO_TORTURE_OPTIONS): Likewise.
	* lib/c-torture.exp (TORTURE_OPTIONS): Likewise.

Index: config/bootstrap-O1g.mk
===================================================================
--- /dev/null	2019-06-14 15:59:19.298479944 +0100
+++ config/bootstrap-O1g.mk	2019-06-23 14:48:59.302941670 +0100
@@ -0,0 +1,1 @@
+BOOT_CFLAGS := -O1g $(filter-out -O%, $(BOOT_CFLAGS))
Index: gcc/common.opt
===================================================================
--- gcc/common.opt	2019-06-23 14:48:44.495065059 +0100
+++ gcc/common.opt	2019-06-23 14:48:59.302941670 +0100
@@ -487,6 +487,9 @@ Og
 Common Optimization
 Optimize for debugging experience rather than speed or size.
 
+O1g
+Common Optimization
+
 Q
 Driver
 
Index: gcc/doc/invoke.texi
===================================================================
--- gcc/doc/invoke.texi	2019-06-18 09:35:52.089892867 +0100
+++ gcc/doc/invoke.texi	2019-06-23 14:48:59.314941570 +0100
@@ -8403,6 +8403,19 @@ optimization flags except for those that
 -fmove-loop-invariants  -fssa-phiopt @gol
 -ftree-bit-ccp  -ftree-pta  -ftree-sra}
 
+@item -O1g
+@opindex O1g
+Perform the same optimizations as @option{-O1}, but take the debug
+experience into consideration when optimizing.  In particular, try to
+make sure that the values of simple variables are printable at any
+point during their scope.
+
+This option is a compromise between @option{-Og} and @option{-O1}.
+The code it produces is generally faster than the code that
+@option{-Og} produces, but not as fast as the code that @option{-O1}
+produces.  In contrast, the code that @option{-O1g} produces should be
+easier to debug than code that @option{-O1} produces, but might not be
+as easy to debug as the code that @option{-Og} produces.
 @end table
 
 If you use multiple @option{-O} options, with or without level numbers,
Index: gcc/opts.c
===================================================================
--- gcc/opts.c	2019-06-23 14:48:44.507064959 +0100
+++ gcc/opts.c	2019-06-23 14:48:59.314941570 +0100
@@ -639,6 +639,14 @@ default_options_optimization (struct gcc
 	  opts->x_flag_tangible_debug = 1;
 	  break;
 
+	case OPT_O1g:
+	  opts->x_optimize_size = 0;
+	  opts->x_optimize = 1;
+	  opts->x_optimize_fast = 0;
+	  opts->x_optimize_debug = 0;
+	  opts->x_flag_tangible_debug = 1;
+	  break;
+
 	case OPT_fopenacc:
 	  if (opt->value)
 	    openacc_mode = true;
@@ -2323,6 +2331,7 @@ common_handle_option (struct gcc_options
     case OPT_Os:
     case OPT_Ofast:
     case OPT_Og:
+    case OPT_O1g:
       /* Currently handled in a prescan.  */
       break;
 
Index: gcc/testsuite/g++.dg/guality/guality.exp
===================================================================
--- gcc/testsuite/g++.dg/guality/guality.exp	2019-06-23 14:48:44.511064925 +0100
+++ gcc/testsuite/g++.dg/guality/guality.exp	2019-06-23 14:48:59.314941570 +0100
@@ -78,9 +78,9 @@ if {[check_guality "
     gcc-dg-runtest [lsort [glob $srcdir/$subdir/*.C]] "" ""
     gcc-dg-runtest $general "" ""
     set-torture-options \
-      [list "-O0" "-Og"] \
+      [list "-O0" "-Og" "-O1g"] \
       [list {}] \
-      [list "-Og -flto"]
+      [list "-Og -flto" "-O1g -flto"]
     gcc-dg-runtest $Og "" ""
 }
 
Index: gcc/testsuite/gcc.dg/guality/guality.exp
===================================================================
--- gcc/testsuite/gcc.dg/guality/guality.exp	2019-06-23 14:48:44.511064925 +0100
+++ gcc/testsuite/gcc.dg/guality/guality.exp	2019-06-23 14:48:59.314941570 +0100
@@ -93,9 +93,9 @@ if {[check_guality "
     gcc-dg-runtest [lsort [glob $srcdir/$subdir/*.c]] "" ""
     gcc-dg-runtest $general "" "-Wc++-compat"
     set-torture-options \
-      [list "-O0" "-Og"] \
+      [list "-O0" "-Og" "-O1g"] \
       [list {}] \
-      [list "-Og -flto"]
+      [list "-Og -flto" "-O1g -flto"]
     gcc-dg-runtest $Og "" "-Wc++-compat"
 }
 
Index: gcc/testsuite/gcc.dg/sso/sso.exp
===================================================================
--- gcc/testsuite/gcc.dg/sso/sso.exp	2019-03-08 18:15:04.412863081 +0000
+++ gcc/testsuite/gcc.dg/sso/sso.exp	2019-06-23 14:48:59.314941570 +0100
@@ -32,7 +32,8 @@ set SSO_TORTURE_OPTIONS [list \
 	{ -O2 } \
 	{ -O3 -finline-functions } \
 	{ -Os } \
-	{ -Og -g } ]
+	{ -Og -g } \
+	{ -O1g -g } ]
 
 set-torture-options $SSO_TORTURE_OPTIONS
 
Index: gcc/testsuite/gnat.dg/sso/sso.exp
===================================================================
--- gcc/testsuite/gnat.dg/sso/sso.exp	2019-03-08 18:14:54.692900030 +0000
+++ gcc/testsuite/gnat.dg/sso/sso.exp	2019-06-23 14:48:59.314941570 +0100
@@ -28,7 +28,8 @@ set SSO_TORTURE_OPTIONS [list \
 	{ -O2 } \
 	{ -O3 -finline-functions } \
 	{ -Os } \
-	{ -Og -g } ]
+	{ -Og -g } \
+	{ -O1g -g } ]
 
 set-torture-options $SSO_TORTURE_OPTIONS
 
Index: gcc/testsuite/lib/c-torture.exp
===================================================================
--- gcc/testsuite/lib/c-torture.exp	2019-03-08 18:14:42.504946361 +0000
+++ gcc/testsuite/lib/c-torture.exp	2019-06-23 14:48:59.314941570 +0100
@@ -56,7 +56,8 @@ if [info exists TORTURE_OPTIONS] {
 	{ -O3 -fomit-frame-pointer -funroll-loops -fpeel-loops -ftracer -finline-functions } \
 	{ -O3 -g } \
 	{ -Os } \
-	{ -Og -g } ]
+	{ -Og -g } \
+	{ -O1g -g } ]
 
     if [check_effective_target_lto] {
         # When having plugin test both slim and fat LTO and plugin/nonplugin

^ 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

* Re: [PATCH 0/3] RFC: Let debug stmts influence codegen at -Og
  2019-06-23 13:51 [PATCH 0/3] RFC: Let debug stmts influence codegen at -Og Richard Sandiford
                   ` (2 preceding siblings ...)
  2019-06-23 13:53 ` [PATCH 3/3] RFC: Add -O1g Richard Sandiford
@ 2019-06-24 12:24 ` Richard Biener
  2019-06-24 12:50   ` Richard Sandiford
  2019-06-24 14:14 ` Segher Boessenkool
                   ` (2 subsequent siblings)
  6 siblings, 1 reply; 12+ messages in thread
From: Richard Biener @ 2019-06-24 12:24 UTC (permalink / raw)
  To: GCC Patches, Richard Sandiford

On Sun, Jun 23, 2019 at 3:51 PM Richard Sandiford
<richard.sandiford@arm.com> wrote:
>
> -Og is documented as:
>
>   @option{-Og} should be the optimization
>   level of choice for the standard edit-compile-debug cycle, offering
>   a reasonable level of optimization while maintaining fast compilation
>   and a good debugging experience.  It is a better choice than @option{-O0}
>   for producing debuggable code because some compiler passes
>   that collect debug information are disabled at @option{-O0}.
>
> One of the things hampering that is that, as for the "normal" -O* flags,
> the code produced by -Og -g must be the same as the code produced
> without any debug IL at all.  There are many cases in which that makes
> it impossible to stop useful values from being optimised out of the
> debug info, either because the value simply isn't available at runtime
> at the point that the debugger needs it, or because of limitations in
> the debug representation.  (E.g. pointers to external data are dropped
> from debug info because the relocations wouldn't be honoured.)
>
> I think it would be better to flip things around so that the debug IL
> is always present when optimising at -Og, and then allow the debug IL
> to influence codegen at -Og.  This still honours the -fcompare-debug
> principle, and the compile speed of -Og without -g doesn't seem very
> important.

Just to note it's also a common user misconception that -Og enables
debug-info ...

> This series therefore adds a mode in which debug stmts and debug insns
> are present even without -g and are explicitly allowed to affect codegen.
> In particular, when this mode is active:
>
> - 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
>
> This needs a new term to distinguish stmts/insns that affect codegen
> from those that don't.  I couldn't think of one that I was really
> happy with, but possibilities included:
>
>     tangible/shadow
>     manifest/hidden
>     foreground/background
>     reactive/inert
>     active/dormant   (but "active insn" already means something else)
>     peppy/sullen
>
> The series uses tangible/shadow.  There's a new global flag_tangible_debug
> that controls whether debug insns are "tangible" insns (for the new mode)
> or "shadow" insns (for normal optimisation).  -Og enables the new mode
> while the other optimisation levels leave it off.  (Despite the name,
> the new variable is just an internal flag, there's no -ftangible-debug
> option.)
>
> The first patch adds the infrastructure but doesn't improve the debug
> experience much on its own.
>
> As an example of one thing we can do with the new mode, the second patch
> ensures that the gimple IL has debug info for each is_gimple_reg variable
> throughout the variable's lifetime.  This fixes a couple of the PRs in
> the -Og meta-bug and from spot-testing seems to ensure that far fewer
> values are optimised out.
>
> Also, the new mode is mostly orthogonal to the optimisation level
> (although it would in effect disable optimisations like loop
> vectorisation, until we have a way of representing debug info for
> vectorised loops).  The third patch therefore adds an -O1g option
> that optimises more heavily than -Og but provides a better debug
> experience than -O1.
>
> I think -O2g would make sense too, and would be a viable option
> for people who want to deploy relatively heavily optimised binaries
> without compromising the debug experience too much.
>
> Other possible follow-ons for the new mode include:
>
> - Make sure that tangible debug stmts never read memory or take
>   an address.  (This is so that addressability and vops depend
>   only on non-debug insns.)
>
> - Fall back on expanding real code if expand_debug_expr fails.
>
> - Force debug insns to be simple enough for dwarf2out (e.g. no external
>   or TLS symbols).  This could be done by having a validation step for
>   debug insns, like we already do for normal insns.
>
> - Prevent the removal of dead stores if it would lead to wrong debug info.
>   (Maybe under control of an option?)
>
> To get an idea of the runtime cost, I tried compiling tree-into-ssa.ii
> at -O2 -g with various --enable-checking=yes builds of cc1plus:
>
>                             time taken
> cc1plus compiled with -O0:     100.00%   (baseline)
> cc1plus compiled with old -Og:  30.94%

is this -Og -g or just -Og?  I suppose all numbers are with -g enabled?

> cc1plus compiled with new -Og:  31.82%
> cc1plus compiled with -O1g:     28.22%
> cc1plus compiled with -O1:      26.72%
> cc1plus compiled with -O2:      25.15%
>
> So there is a noticeable but small performance cost to the new mode.
>
> To get an idea of the compile-time impact, I tried compiling
> tree-into-ssa.ii at various optimisation levels, all using the
> same --enable-checking=release bootstrap build:
>
>                               time taken
> tree-into-ssa.ii with -O0 -g:     100.0%  (baseline)
> tree-into-ssa.ii with old -Og -g: 180.6%
> tree-into-ssa.ii with new -Og -g: 198.2%
> tree-into-ssa.ii with -O1g -g:    237.1%
> tree-into-ssa.ii with -O1 -g:     211.8%
> tree-into-ssa.ii with -O2 -g:     331.5%
>
> So there's definitely a bit of a compile-time hit.  I haven't yet looked
> at how easy it would be to fix.
>
> What do you think?  Is it worth pursuing this further?
>
> Of course, even if we do do this, it's still important that the debug
> info for things like -O2 -g is as good as it can be.  I just think some
> of the open bugs against -Og fundamentally can't be fixed properly while
> -Og remains a cut-down version of -O1.

Thanks for doing this experiment.  I'm not sure extra complication
is welcome (but didn't look into the patch(es) yet...).

My original motivation for -Og -g was to provide -O0 -g compile-time
at -O1 runtime with better debuggability than -O0 -g (mainly because
that doesn't enable var-tracking).  Of course that failed completely ;)

I somewhat like the idea that -ONg forces debug info generation
(but not necessarily output without -g) and thus we can take debug-stmts
into account.  I suppose you're simply keying on optimize_debug here.

Richard.

> Thanks,
> Richard

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [PATCH 0/3] RFC: Let debug stmts influence codegen at -Og
  2019-06-24 12:24 ` [PATCH 0/3] RFC: Let debug stmts influence codegen at -Og Richard Biener
@ 2019-06-24 12:50   ` Richard Sandiford
  0 siblings, 0 replies; 12+ messages in thread
From: Richard Sandiford @ 2019-06-24 12:50 UTC (permalink / raw)
  To: Richard Biener; +Cc: GCC Patches

Richard Biener <richard.guenther@gmail.com> writes:
> On Sun, Jun 23, 2019 at 3:51 PM Richard Sandiford
> <richard.sandiford@arm.com> wrote:
>> To get an idea of the runtime cost, I tried compiling tree-into-ssa.ii
>> at -O2 -g with various --enable-checking=yes builds of cc1plus:
>>
>>                             time taken
>> cc1plus compiled with -O0:     100.00%   (baseline)
>> cc1plus compiled with old -Og:  30.94%
>
> is this -Og -g or just -Og?  I suppose all numbers are with -g enabled?

Yeah, all with -g enabled.  But these were the options used to build
cc1plus, whereas the timings are for running it.  So -g shouldn't make
a difference.

>> cc1plus compiled with new -Og:  31.82%
>> cc1plus compiled with -O1g:     28.22%
>> cc1plus compiled with -O1:      26.72%
>> cc1plus compiled with -O2:      25.15%
>>
>> So there is a noticeable but small performance cost to the new mode.
>>
>> To get an idea of the compile-time impact, I tried compiling
>> tree-into-ssa.ii at various optimisation levels, all using the
>> same --enable-checking=release bootstrap build:
>>
>>                               time taken
>> tree-into-ssa.ii with -O0 -g:     100.0%  (baseline)
>> tree-into-ssa.ii with old -Og -g: 180.6%
>> tree-into-ssa.ii with new -Og -g: 198.2%
>> tree-into-ssa.ii with -O1g -g:    237.1%
>> tree-into-ssa.ii with -O1 -g:     211.8%
>> tree-into-ssa.ii with -O2 -g:     331.5%
>>
>> So there's definitely a bit of a compile-time hit.  I haven't yet looked
>> at how easy it would be to fix.
>>
>> What do you think?  Is it worth pursuing this further?
>>
>> Of course, even if we do do this, it's still important that the debug
>> info for things like -O2 -g is as good as it can be.  I just think some
>> of the open bugs against -Og fundamentally can't be fixed properly while
>> -Og remains a cut-down version of -O1.
>
> Thanks for doing this experiment.  I'm not sure extra complication
> is welcome (but didn't look into the patch(es) yet...).

OK.  The complication is in having (to think about) a new pair of
conditions that might be relevant: tangible/shadow instead of
nondebug/debug.  But almost all the changes involve replacing the
latter with the former rather than adding new checks.  Hopefully once
the whole sourcebase has been converted, the check would become second
nature.  (But patch 1 doesn't convert the whole sourcebase.)

> My original motivation for -Og -g was to provide -O0 -g compile-time
> at -O1 runtime with better debuggability than -O0 -g (mainly because
> that doesn't enable var-tracking).  Of course that failed completely ;)

We fall short on the compile-time side, but being able to get a reasonable
debugging experience with code that runs 3 times faster than -O0 is still
a pretty nice feature. :-)

> I somewhat like the idea that -ONg forces debug info generation
> (but not necessarily output without -g) and thus we can take debug-stmts
> into account.  I suppose you're simply keying on optimize_debug here.

I wondered about doing it that way, but in the end added a new internal
variable instead (flag_tangible_debug, but not backed by a real -f option).
optimize_debug mostly disables optimisations, and whether we want to do
that for -ONg felt like a separate question from whether we should take
debug stmts into account.

Thanks,
Richard

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [PATCH 0/3] RFC: Let debug stmts influence codegen at -Og
  2019-06-23 13:51 [PATCH 0/3] RFC: Let debug stmts influence codegen at -Og Richard Sandiford
                   ` (3 preceding siblings ...)
  2019-06-24 12:24 ` [PATCH 0/3] RFC: Let debug stmts influence codegen at -Og Richard Biener
@ 2019-06-24 14:14 ` Segher Boessenkool
  2019-06-24 14:22   ` Richard Sandiford
  2019-06-24 14:28 ` Jakub Jelinek
  2019-06-26  8:38 ` [PATCH 0/3] RFC: Let debug stmts influence codegen@-Og Jonathan Wakely
  6 siblings, 1 reply; 12+ messages in thread
From: Segher Boessenkool @ 2019-06-24 14:14 UTC (permalink / raw)
  To: gcc-patches, richard.sandiford

Hi!

What does -O1g do with OPT_LEVELS_1_PLUS_NOT_DEBUG, is it enabled or
not there?  Maybe that name needs to change, with your patches?  It is
currently documented as

    /* -O1 (and not -Og) optimizations.  */


Segher

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [PATCH 0/3] RFC: Let debug stmts influence codegen at -Og
  2019-06-24 14:14 ` Segher Boessenkool
@ 2019-06-24 14:22   ` Richard Sandiford
  0 siblings, 0 replies; 12+ messages in thread
From: Richard Sandiford @ 2019-06-24 14:22 UTC (permalink / raw)
  To: Segher Boessenkool; +Cc: gcc-patches

Segher Boessenkool <segher@kernel.crashing.org> writes:
> Hi!
>
> What does -O1g do with OPT_LEVELS_1_PLUS_NOT_DEBUG, is it enabled or
> not there?  Maybe that name needs to change, with your patches?  It is
> currently documented as
>
>     /* -O1 (and not -Og) optimizations.  */

Yeah, comment should change to be:

    /* -O1 and -O1g (but not -Og) optimizations.  */

Richard

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [PATCH 0/3] RFC: Let debug stmts influence codegen at -Og
  2019-06-23 13:51 [PATCH 0/3] RFC: Let debug stmts influence codegen at -Og Richard Sandiford
                   ` (4 preceding siblings ...)
  2019-06-24 14:14 ` Segher Boessenkool
@ 2019-06-24 14:28 ` Jakub Jelinek
  2019-06-24 14:36   ` Segher Boessenkool
  2019-06-26  8:38 ` [PATCH 0/3] RFC: Let debug stmts influence codegen@-Og Jonathan Wakely
  6 siblings, 1 reply; 12+ messages in thread
From: Jakub Jelinek @ 2019-06-24 14:28 UTC (permalink / raw)
  To: gcc-patches, richard.sandiford

On Sun, Jun 23, 2019 at 02:51:06PM +0100, Richard Sandiford wrote:
> What do you think?  Is it worth pursuing this further?

Wouldn't it be more useful to just force all automatic variables to be
used at the end of their corresponding scope?  That is IMHO the main issue
with -Og debugging, VTA is a best effort, if we can express a variable with
some expression, nice, but if there is no expression nor memory nor register
that holds the value, we are out of luck.  Could be some magic stmt like
gimple_clobber or ifn or something similar, which would make sure that at
least until expansion to RTL we force those vars to be live in either a
register or memory.
I'm afraid having different modes, one in which debug stmts can't and one
where they can affect code generation might be a maintainance nightmare.

	Jakub

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [PATCH 0/3] RFC: Let debug stmts influence codegen at -Og
  2019-06-24 14:28 ` Jakub Jelinek
@ 2019-06-24 14:36   ` Segher Boessenkool
  2019-06-24 16:10     ` Richard Sandiford
  0 siblings, 1 reply; 12+ messages in thread
From: Segher Boessenkool @ 2019-06-24 14:36 UTC (permalink / raw)
  To: Jakub Jelinek; +Cc: gcc-patches, richard.sandiford

On Mon, Jun 24, 2019 at 04:28:34PM +0200, Jakub Jelinek wrote:
> On Sun, Jun 23, 2019 at 02:51:06PM +0100, Richard Sandiford wrote:
> > What do you think?  Is it worth pursuing this further?
> 
> Wouldn't it be more useful to just force all automatic variables to be
> used at the end of their corresponding scope?  That is IMHO the main issue
> with -Og debugging, VTA is a best effort, if we can express a variable with
> some expression, nice, but if there is no expression nor memory nor register
> that holds the value, we are out of luck.  Could be some magic stmt like
> gimple_clobber or ifn or something similar, which would make sure that at
> least until expansion to RTL we force those vars to be live in either a
> register or memory.
> I'm afraid having different modes, one in which debug stmts can't and one
> where they can affect code generation might be a maintainance nightmare.

This is pretty much exactly what USE in RTL is?  Maybe use a similar name
in Gimple?


Segher

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [PATCH 0/3] RFC: Let debug stmts influence codegen at -Og
  2019-06-24 14:36   ` Segher Boessenkool
@ 2019-06-24 16:10     ` Richard Sandiford
  0 siblings, 0 replies; 12+ messages in thread
From: Richard Sandiford @ 2019-06-24 16:10 UTC (permalink / raw)
  To: Segher Boessenkool; +Cc: Jakub Jelinek, gcc-patches

Segher Boessenkool <segher@kernel.crashing.org> writes:
> On Mon, Jun 24, 2019 at 04:28:34PM +0200, Jakub Jelinek wrote:
>> On Sun, Jun 23, 2019 at 02:51:06PM +0100, Richard Sandiford wrote:
>> > What do you think?  Is it worth pursuing this further?
>> 
>> Wouldn't it be more useful to just force all automatic variables to be
>> used at the end of their corresponding scope?

This is what patch 2 does FWIW.

>> That is IMHO the main issue
>> with -Og debugging, VTA is a best effort, if we can express a variable with
>> some expression, nice, but if there is no expression nor memory nor register
>> that holds the value, we are out of luck.  Could be some magic stmt like
>> gimple_clobber or ifn or something similar, which would make sure that at
>> least until expansion to RTL we force those vars to be live in either a
>> register or memory.
>> I'm afraid having different modes, one in which debug stmts can't and one
>> where they can affect code generation might be a maintainance nightmare.

Very few places need to check for the mode explicitly.  Most code just
uses a new test instead of (rather than on top of) is_gimple_debug/
NONDEBUG_INSN_P.

The vast majority of the existing tests for is_gimple_debug aren't
interested in the debug contents of a debug stmt.  They're just
interested in whether the stmt is allowed to affect codegen.  With this
series that becomes a new predicate in its own right.  We then only use
is_gimple_debug if we want to process the contents of a debug insn in a
particular way, just like we only test for gimple calls or assignments
when we're interested in their contents.

Old habits die hard of course, so there'd definitely be a period while
people instinctively use is_gimple_debug/NONDEBUG_INSN_P instead of
the new test.

> This is pretty much exactly what USE in RTL is?  Maybe use a similar name
> in Gimple?

Yeah, I wondered about doing it that way, but one problem with USE is
that it isn't clear why the USE is there or what the ordering constraints
on it are.  Here we want the same rules as for normal debug stmts
(as modified by patch 1).

Also, if the final value ends up being constant, it's fine to propagate
that value into the debug stmt that marks the end of the scope.
I'm not sure it's valid to propagate constants into a use.

But the rtl side of patch 2 (using debug insns instead of USEs)
is only a small change.  The main part of it is on the gimple side.
Unless we prevent all user values from becoming gimple registers
and being rewritten into SSA, we'd still need something like the gimple
side of patch 2 to ensure that there's sufficient tracking of the variable.

Thanks,
Richard

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [PATCH 0/3] RFC: Let debug stmts influence codegen@-Og
  2019-06-23 13:51 [PATCH 0/3] RFC: Let debug stmts influence codegen at -Og Richard Sandiford
                   ` (5 preceding siblings ...)
  2019-06-24 14:28 ` Jakub Jelinek
@ 2019-06-26  8:38 ` Jonathan Wakely
  6 siblings, 0 replies; 12+ messages in thread
From: Jonathan Wakely @ 2019-06-26  8:38 UTC (permalink / raw)
  To: gcc-patches, richard.sandiford

On 23/06/19 14:51 +0100, Richard Sandiford wrote:
>Also, the new mode is mostly orthogonal to the optimisation level
>(although it would in effect disable optimisations like loop
>vectorisation, until we have a way of representing debug info for
>vectorised loops).  The third patch therefore adds an -O1g option
>that optimises more heavily than -Og but provides a better debug
>experience than -O1.

I think it would be confusing to have -O and -O1 mean the same, but
-Og and -O1g mean something different.

Maybe another name could avoid that, e.g. appending +g to signify the
new modes, so -O+g and -O1+g would mean the same thing.

>I think -O2g would make sense too, and would be a viable option
>for people who want to deploy relatively heavily optimised binaries
>without compromising the debug experience too much.

Which would be -O2+g using the naming scheme above.

If the mode is orthogonal to optimisation level I think this is
clearer, because you can have +g appended to any level, -Os+g, maybe
even -Og+g ;-)

^ permalink raw reply	[flat|nested] 12+ messages in thread

end of thread, other threads:[~2019-06-26  8:38 UTC | newest]

Thread overview: 12+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
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 ` [PATCH 0/3] RFC: Keep debug values live for -Og Richard Sandiford
2019-06-23 13:53 ` [PATCH 3/3] RFC: Add -O1g Richard Sandiford
2019-06-24 12:24 ` [PATCH 0/3] RFC: Let debug stmts influence codegen at -Og Richard Biener
2019-06-24 12:50   ` Richard Sandiford
2019-06-24 14:14 ` Segher Boessenkool
2019-06-24 14:22   ` Richard Sandiford
2019-06-24 14:28 ` Jakub Jelinek
2019-06-24 14:36   ` Segher Boessenkool
2019-06-24 16:10     ` Richard Sandiford
2019-06-26  8:38 ` [PATCH 0/3] RFC: Let debug stmts influence codegen@-Og Jonathan Wakely

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).