This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: Statement Frontier Notes, Location Views, and Inlined Entry Point Markers (was: Re: Introduce Statement Frontier Notes and Location Views)


..
On Fri, Aug 18, 2017 at 11:20 PM, Alexandre Oliva <aoliva@redhat.com> wrote:
> On Jul 13, 2017, Alexandre Oliva <aoliva@redhat.com> wrote:
>
>> On Jul  5, 2017, Alexandre Oliva <aoliva@redhat.com> wrote:
>>> This patch implements statement frontier notes and location views,
>>> concepts originally proposed in the GCC Summit back in 2010.  See
>>> https://people.redhat.com/aoliva/papers/sfn/ for details on the
>>> original design.
>
>> There's a newer blog post about these features that provides further
>> context and motivation.
>> https://developers.redhat.com/blog/2017/07/11/statement-frontier-notes-and-location-views/#more-437095
>
>
>> I wonder if it would be useful to break up the patch into smaller
>> pieces, for purposes of review.  The changes are mostly interdependent,
>> though it is possible to break it up into major features, say one patch
>> introducing statement frontier notes, one or more patches fixing new
>> -fcompare-debug failures, and one patch introducing location views.  The
>> changes are largely split up like that in the aoliva/SFN branch, though
>> I don't think it would be appropriate to install these changes as such a
>> sequence of patches, though, because I don't think it's adequate to have
>> known regressions, even if temporarily, and the initial SFN patch,
>> without the subsequent -fcompare-debug fixes, would do just that.
>
>> Thoughts?  Advice?
>
> Here's a refreshed/retested/improved version of the patchset.  It
> changes the representation of debug begin stmt insns, and introduces
> inlined entry point markers, combining them into nonbind markers
> (earlier debug stmts, insns and notes all bind decls besides just
> marking a point in the program).  All the changes are visible in smaller
> (but not consolidated) logical changes in the GIT branch aoliva/SFN.
> FWIW, I'm speaking about this project at the upcoming GNU Tools Cauldron.
>
>
> This was successfully regstrapped (before a few cosmetic changes; almost
> done with them too) on x86_64-linux-gnu and i686-linux-gnu; I'm
> repeating the test plan described in the original patch, retained at the
> end of the patch description.  Ok to install?
>
>
> ----
>
> This patch implements statement frontier notes and location views,
> concepts originally proposed in the GCC Summit back in 2010.  See
> https://people.redhat.com/aoliva/papers/sfn/ for details on the
> original design.  It also introduces markers for entry points of
> inlined functions as a variation of statement frontier markers.
>
> Statement Frontier Notes are implemented very much as described in the
> original paper.  Early in compilation (when both optimization and
> debug info are enabled), we emit markers denoting the beginning of
> each source-level statement (currently supported languages are those
> in the C and C++ families; parsers of other languages have to be
> adjusted to emit frontier markers).  These markers are initially
> emitted as trees, lowered to gimple debug stmts, expanded to debug
> insns, and finally converted to notes.  Throughout compilation, they
> remain in place, just like VTA's debug stmts and insns, and as such
> they provide reliable for the generation of DWARF's is_stmt flag in
> line number tables.  This flag indicates recommended breakpoints.
>
> Alas, because of optimization, such recommended breakpoints may pile
> up at instructions associated with different line numbers.  Debug
> information consumers had no way to distinguish the multiple source
> program states that all map to the same executable instruction.
>
> Location views introduce a means for the compiler to name and refer to
> such overlapping states, so that variable location lists can indicate
> which of multiple states at the same instruction starts or ends each
> range, and debug information consumers can then stop at the desired
> state and inspect variables at it.
>
> The naming of overlapping source program states is introduced by means
> of a reinterpretation of line number programs, so no additional
> encoding is necessary.  The line number programs can still be emitted
> internally by GCC or by an assembler, through ".loc" directives.  If
> GCC finds the assembler to support "view" labels at configure time, it
> will rely on the assembler for line number generation in compilations
> that have location views enabled.  Otherwise, it will resort to
> internally-generated line number programs.  A patch about to be
> contributed to binutils will add support for "view" labels in ".loc"
> directives to the assembler.
>
> Location views are NOT emitted as proposed in the original paper.
> Location lists have been significantly revamped in DWARF5, and we have
> a proposal for DWARF6 that extends them with location views (see
> dwarf6-sfn-lvu.txt in the same papers/sfn/ directory mentioned above).
> Since location lists are not extensible in DWARF, for DWARF<=5 we emit
> them as a separate list, as proposed in the original paper, but
> pointed to by a DW_AT_GNU_locviews attribute rather than just having
> its presence indicated by a flag.  With -gdwarf-6, we emit DWARF5
> (warning that this is the version we're using, in spite of the
> option), with loclists extended as proposed for DWARF6.
>
>
> Inlined entry points could already be represented with DW_AT_entry_pc
> for inlined subroutines, but we didn't always ensure it was at the
> exact place.  With statement frontier notes infrastructure, we emit a
> marker right after binding the incoming arguments, before entering the
> inlined blocks.  We can then emit DW_AT_entry_pc, and also
> DW_AT_entry_view, if the entry point is at a nonzero view number, if
> we it does not seem that they coincide with DW_AT_low_pc.
>
> In some cases, the inlined entry point is replicated within a
> function, say by loop unrolling, or by other forms of basic block
> duplication.  There is no way to represent such replicated entry
> points, unfortunately, but we are investigating the possibilities of
> accomplishing that through further DWARF extensions.
>
>
> Statement Frontier Notes makes is_stmt generation more precise and
> predictable, no matter how much instructions are shuffled by
> optimization.  This feature is enabled by default in optimized builds,
> when emitting DWARF2+ debug information at normal or higher level.  It
> can be explicitly enabled in any other situations with
> -gstatement-frontiers, or disabled with -gno-statement-frontiers.
> This also enables inlined entry point markers.
>
> Location views, in turn, avoid regressions when a recommended
> breakpoint is one of multiple states at the same instruction.  This
> feature is enabled by default in var-tracking compilations, when
> emitting non-strict DWARF2+ debug information at normal or higher
> level.  It can be explicitly enabled with -gvariable-location-views,
> or disabled with -gno-variable-location-views.
>
> Combined, these two features make it more likely that there is a
> usable inspection point for every statement, and that single stepping
> can reliably advance to a subsequent statement, instead of bouncing to
> earlier statements, as we used to do in optimized programs.  They also
> make room for such advanced features as single-stepping from one
> source statement to another and inspecting changes to variables, even
> when no executable instructions separate the recommended breakpoints
> for these two states.
>
>
> Besides implementing these new features, the patch contains multiple
> fixes for -fcompare-debug errors detected at various optimization
> levels, arising mainly from the introduction of begin stmt and inlined
> entry point markers.

Can you try to split those out?

>  Earlier debug position markers (namely stmts,
> insns and notes) are now referred as bind debug markers, since they
> all bind a declaration to an expression, whereas the newly-introduced
> ones are now referenced as nonbind markers.
>
>
> This patch was tested at multiple optimization levels and
> configurations, such as:
>
> - with or without assembler support for loc views
>
> - default (bootstrap-O2), bootstrap-O1 and bootstrap-O3
>
> - -O0 -g -fcompare-debug=-gstatement-frontiers in stage4
>
> - bootstrap-debug-lean bootstrap-debug-lib to exercise -fcompare-debug
>   for stage3, target libs, and tests
>

Few comments (mostly on middle-end, non-RTL stuff, leaving the rest
to others):

+gno-statement-frontiers
+Common Driver RejectNegative Var(debug_nonbind_markers_p, 0) Init(2)
+Don't enforce progressive recommended breakpoint locations.
+
+gstatement-frontiers
+Common Driver RejectNegative Var(debug_nonbind_markers_p, 1)
+Emit progressive recommended breakpoint locations.

others get away with a single flag and Init(-1).  That is, -gstatement-frontiers
should set it to 1 already and -gno- to 0.  Why do you need the explicit
entry for gno-..?

   for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
-    if (DEBUG_INSN_P (insn))
+    if (BIND_DEBUG_INSN_P (insn))
       {

DEBUG_BIND_INSN_P?  GIMPLE has gimple_debug_bind_p ...

+  /* If the function has too many markers, drop them while expanding.  */
+  if (cfun->debug_marker_count
+      >= PARAM_VALUE (PARAM_MAX_DEBUG_MARKER_COUNT))
+    cfun->debug_nonbind_markers = false;
+

if they are not a problem up until here why care now?  That said,
what's the number
of markers per GIMPLE stmt for optimized builds of tramp3d-v4.cpp?  [it has
around 10 original function calls per generated assembler line]
Would a better option be to condense multiple adjacent notes to a single one?
That way we'd have a natural bound as fallback.

I expect heavily abstracted C++ to blow up GIMPLE IL considerably that way...

Did you see what these do to memory/compile-time use with a LTO bootstrap?

+      if (MARKER_DEBUG_INSN_P (insn))
+       return true;
+

DEBUG_MARKER_INSN_P

+/* Return the next insn after INSN that is not a DEBUG_INSN.  This
+   routine does not look inside SEQUENCEs.  */

 rtx_insn *
-next_nonnote_insn_bb (rtx_insn *insn)
+next_nondebug_insn (rtx_insn *insn)
 {
   while (insn)
     {

sometimes I hate unified diffs ....  this and the part following is
unreadable.

@@ -573,6 +573,8 @@ gsi_remove (gimple_stmt_iterator *i, bool
remove_permanently)

   if (remove_permanently)
     {
+      if (gimple_debug_nonbind_marker_p (stmt))
+       cfun->debug_marker_count--;
       require_eh_edge_purge = remove_stmt_from_eh_lp (stmt);
       gimple_remove_stmt_histograms (cfun, stmt);
     }

hmm, you're now relying on remove_permanently to tell the truth.
I do remember ggc_free ()ing the gimple here doesn't work.

+  gdebug *p
+    = as_a <gdebug *> (
+        gimple_build_with_ops_stat (GIMPLE_DEBUG,
+                                   (unsigned)GIMPLE_DEBUG_BEGIN_STMT, 0
+                                   PASS_MEM_STAT));

heh, we need a gimple_build <gdebug> (....) abstraction to make all this
nicer (well, probably overkill, just used in internal gimple.c)

Reading the patch both BEGIN_STMT and INLINE_ENTRY are just
free-floating notes in GIMPLE to be not re-ordered.  This means
they could use gimple as base instead of gimple_statement_with_ops, no?
Saving two pointers or nearly half size?  Could it also hold a vector of
locations so we can optimize adjacent stmt-start stmts, maybe even
also cover the inline thing?  We'd have a maximum of 1 such stmt
per other stmt in GIMPLE (and also RTL?).

+static location_t
+expr_location (tree expr, location_t or_else = UNKNOWN_LOCATION)
+{
...
+static inline bool
+expr_has_location (tree expr)
...

_please_ do not just use lower-case names for sth subtly different
from their upper-case part...

It would be nice to split out some of the mechanical changes, like
function renaming or gsi_last_bb to gsi_last_nondebug_bb for example
to shrink the parts that need "real" review.  I'll happily ack those split
out parts quickly.

+         else if (gimple_debug_nonbind_marker_p (stmt))
+           {
+             new_stmt = as_a <gdebug *> (gimple_copy (stmt));
+           }

extra braces

Skimmed over the whole patch now, I think it looks reasonably ok.
Let's get rid of the noise and acks from the DWARF people.

Btw, just asking as I helped to get the GIMPLE FE in, did you
consider adding GIMPLE FE support for the various debug stmts
we then have?  First thing would be arriving at a syntax I guess.
__DEBUG x = ...; for binds, __STMT; __INLINE; for the other two?
Not sure how to express they encode some location though...
(binds have no location, right?)

Thanks,
Richard.

>
> for  include/ChangeLog
>
>         * dwarf2.def (DW_AT_GNU_locviews, DW_AT_GNU_entry_view): New.
>         * dwarf2.h (enum dwarf_location_list_entry_type): Add
>         DW_LLE_GNU_view_pair.
>         (DW_LLE_view_pair): Define.
>
> for  gcc/ChangeLog
>
>         * cfgbuild.c (find_bb_boundaries): Skip debug insns.
>         * cfgexpand.c (label_rtx_for_bb): Likewise.
>         (expand_gimple_basic_block): Likewise.  Handle begin stmt and
>         inline entry markers.
>         (expand_debug_locations): Handle bind debug insns only.
>         (pass_expand::execute): Check debug marker limit.
>         * cfgrtl.c (try_redirect_by_replacing_jump): Skip debug insns.
>         (rtl_tidy_fallthru_edge): Likewise.
>         (get_last_bb_insn): Likewise.
>         (rtl_verify_fallthru): Likewise.
>         (rtl_verify_bb_layout): Likewise.
>         (skip_insns_after_block): Likewise.
>         (duplicate_insn_chain): Use BIND_DEBUG_INSN_P.
>         * common.opt (gstatement-frontiers): New, setting
>         debug_nonbind_markers_p.
>         (gvariable-location-views): New.
>         * config.in: Rebuilt.
>         * config/aarch64/aarch64.c (aarch64_output_mi_thunk): Adjust.
>         * config/alpha/alpha.c (alpha_output_mi_thunk_osf): Likewise.
>         * config/arm/arm.c (arm_thumb1_mi_thunk): Likewise.
>         (arm32_output_mi_thunk): Likewise.
>         * config/cris/cris.c (cris_asm_output_mi_thunk): Likewise.
>         * config/i386/i386.c (ix86_code_end): Likewise.
>         (x86_output_mi_thunk): Likewise.
>         * config/ia64/ia64.c (ia64_output_mi_thunk): Likewise.
>         * config/m68k/m68k.c (m68k_output_mi_thunk): Likewise.
>         * config/microblaze/microblaze.c (microblaze_asm_output_mi_thunk):
>         Likewise.
>         * config/mips/mips.c (mips_output_mi_thunk): Likewise.
>         * config/nds32/nds32.c (nds32_asm_output_mi_thunk): Likewise.
>         * config/nios2/nios2.c (nios2_asm_output_mi_thunk): Likewise.
>         * config/pa/pa.c (pa_asm_output_mi_thunk): Likewise.
>         * config/rs6000/rs6000.c (rs6000_output_mi_thunk): Likewise.
>         (rs6000_code_end): Likewise.
>         * config/s390/s390.c (s390_output_mi_thunk): Likewise.
>         * config/sh/sh.c (sh_output_mi_thunk): Likewise.
>         * config/sparc/sparc.c (sparc_output_mi_thunk): Likewise.
>         * config/spu/spu.c (spu_output_mi_thunk): Likewise.
>         * config/tilegx/tilegx.c (tilegx_output_mi_thunk): Likewise.
>         * config/tilepro/tilepro.c (tilepro_asm_output_mi_thunk): Likewise.
>         * configure: Rebuilt.
>         * configure.ac: Test assembler for view support.
>         * cse.c (insn_live_p): Keep nonbind markers and debug bindings
>         followed by them.
>         (delete_trivially_dead_insns): Handle debug bindings.
>         * debug.h (gcc_debug_hooks): Add inline_entry.
>         * dbxout.c (dbx_debug_hooks, xcoff_debug_hooks): Likewise.
>         * debug.c (do_nothing_debug_hooks): Likewise.
>         * sdbout.c (sdb_debug_hooks): Likewise.
>         * vmsdbgout.c (vmsdbg_debug_hooks): Likewise.
>         * df-scan.c (df_insn_delete): Accept out-of-block debug insn.
>         * doc/generic.texi (DEBUG_BEGIN_STMT): Document.
>         * doc/gimple.texi (gimple_debug_begin_stmt_p): New.
>         (gimple_build_debug_bind): Adjust.
>         (gimple_build_debug_begin_stmt): New.
>         * doc/invoke.texi (gstatement-frontiers, gno-statement-frontiers): New.
>         (gvariable-location-views, gno-variable-location-views): New.
>         (max-debug-marker-count): New param.
>         * doc/rtl.texi (NOTE_INSN_BEGIN_STMT): New.
>         (DEBUG_INSN): Describe begin stmt markers.
>         * dwarf2asm.c (dw2_asm_output_symname_uleb128): New.
>         * dwarf2asm.h (dw2_asm_output_symname_uleb128): Declare.
>         * dwarf2out.c: Include print-rtl.h.
>         (var_loc_view): New typedef.
>         (struct dw_loc_list_struct): Add vl_symbol, vbegin, vend.
>         (dwarf2out_locviews_in_attribute): New.
>         (dwarf2out_locviews_in_loclist): New.
>         (dw_val_equal_p): Compare val_view_list of dw_val_class_view_lists.
>         (dwarf2_debug_hooks, dwarf2_lineno_debug_hooks): Add
>         inline_entry.
>         (BLOCK_INLINE_ENTRY_LABEL): New.
>         (enum dw_line_info_opcode): Add LI_adv_address.
>         (struct dw_line_info_table): Add view.
>         (RESET_NEXT_VIEW, RESETTING_VIEW_P): New macros.
>         (DWARF2_ASM_VIEW_DEBUG_INFO): Define default.
>         (zero_view_p): New variable.
>         (ZERO_VIEW_P): New macro.
>         (output_asm_line_debug_info): New.
>         (struct var_loc_node): Add view.
>         (add_AT_view_list, AT_loc_list): New.
>         (add_var_loc_to_decl): Add view param.  Test it against last.
>         (new_loc_list): Add view params.  Record them.
>         (AT_loc_list_ptr): Handle loc and view lists.
>         (view_list_to_loc_list_val_node): New.
>         (print_dw_val): Handle dw_val_class_view_list.
>         (size_of_die): Likewise.
>         (value_format): Likewise.
>         (loc_list_has_views): New.
>         (gen_llsym): Set vl_symbol too.
>         (maybe_gen_llsym, skip_loc_list_entry): New.
>         (dwarf2out_maybe_output_loclist_view_pair): New.
>         (output_loc_list): Output view list or entries too.
>         (output_view_list_offset): New.
>         (output_die): Handle dw_val_class_view_list.
>         (output_dwarf_version): New.
>         (output_compilation_unit_header): Use it.
>         (output_skeleton_debug_sections): Likewise.
>         (output_rnglists, output_line_info): Likewise.
>         (output_pubnames, output_aranges): Update version comments.
>         (output_one_line_info_table): Output view numbers in asm comments.
>         (dw_loc_list): Determine current endview, pass it to new_loc_list.
>         Call maybe_gen_llsym.
>         (loc_list_from_tree_1): Adjust.
>         (add_AT_location_description): Create view list attribute if
>         needed, check it's absent otherwise.
>         (convert_cfa_to_fb_loc_list): Adjust.
>         (inline_entry_data): New struct.
>         (inline_entry_data_hasher): New hashtable type.
>         (inline_entry_data_hasher::hash): New.
>         (inline_entry_data_hasher::equal): New.
>         (inline_entry_data_table): New variable.
>         (add_high_low_attributes): Add DW_AT_entry_pc and
>         DW_AT_GNU_entry_view attributes if a pending entry is found
>         in inline_entry_data_table.  Add old entry_pc attribute only
>         if debug nonbinding markers are disabled.
>         (gen_inlined_subroutine_die): Set BLOCK_DIE if nonbinding
>         markers are enabled.
>         (maybe_emit_file): Call output_asm_line_debug_info for test.
>         (dwarf2out_next_real_insn): New.
>         (dwarf2out_var_location): Call it.  Reset views as needed.  Disregard
>         begin stmt and inline entry markers.  Precompute
>         add_var_loc_to_decl args.  Call get_attr_min_length only if we
>         have the attribute.  Set view.  Dump debug binds in asm comments.
>         (block_within_block_p, dwarf2out_inline_entry): New.
>         (new_line_info_table): Reset next view.
>         (set_cur_line_info_table): Call output_asm_line_debug_info for test.
>         (dwarf2out_source_line): Likewise.  Output view resets and labels to
>         the assembler, or select appropriate line info opcodes.
>         (prune_unused_types_walk_attribs): Handle dw_val_class_view_list.
>         (optimize_string_length): Catch it.  Adjust.
>         (resolve_addr): Copy vl_symbol along with ll_symbol.  Handle
>         dw_val_class_view_list, and remove it if no longer needed.
>         (hash_loc_list): Hash view numbers.
>         (loc_list_hasher::equal): Compare them.
>         (optimize_location_lists): Check whether a view list symbol is
>         needed, and whether the locview attribute is present, and
>         whether they match.  Remove the locview attribute if no longer
>         needed.
>         (index_location_lists): Call skip_loc_list_entry for test.
>         (dwarf2out_finish): Call output_asm_line_debug_info for test.
>         Check that no entries remained in inline_entry_data_table.
>         Use output_dwarf_version.
>         * dwarf2out.h (enum dw_val_class): Add dw_val_class_view_list.
>         (struct dw_val_node): Add val_view_list.
>         * emit-rtl.c (next_nondebug_insn, prev_nondebug_insn): Reorder.
>         (next_nonnote_nondebug_insn, prev_nonnote_nondebug_insn): Reorder.
>         (next_nonnote_nondebug_insn_bb): New.
>         (prev_nonnote_nondebug_insn_bb): New.
>         (prev_nonnote_insn_bb, next_nonnote_insn_bb): Remove.
>         * final.c: Include langhooks.h.
>         (SEEN_NEXT_VIEW): New.
>         (reemit_insn_block_notes): Take current block from nonbind
>         markers.  Declare note where it's first set.
>         (set_next_view_needed): New.
>         (clear_next_view_needed): New.
>         (maybe_output_next_view): New.
>         (final_start_function): Rename to...
>         (final_start_function_1): ... this.  Take pointer to FIRST,
>         add SEEN parameter.  Emit param bindings in the initial view.
>         (final_start_function): Reintroduce SEEN-less interface.
>         (final): Rename to...
>         (final_1): ... this.  Take SEEN parameter.  Output final pending
>         next view at the end.
>         (final): Reintroduce seen-less interface.
>         (final_scan_insn): Output pending next view before switching
>         sections or ending a block.  Mark the next view as needed when
>         outputting variable locations.  Handle begin stmt and inline
>         entry markers.  Emit is_stmt according to begin stmt markers
>         if enabled.  Notify debug backend of section changes, and of
>         location view changes.
>         (notify_source_line): Handle nonbind markers.  Fail if their
>         location is unknown or that of builtins.
>         (rest_of_handle_final): Convert begin stmt markers to notes if
>         var-tracking didn't run.  Adjust.
>         (rest_of_clean_state): Skip begin stmt and inline entry markers.
>         * function.c (instantiate_virtual_regs): Skip debug markers,
>         adjust handling of debug binds.
>         (allocate_struct_function): Set begin_stmt_markers.
>         * function.h (struct function): Add debug_marker_count counter
>         and debug_nonbind_markers flag.
>         * gimple-iterator.c (gsi_remove): Adjust debug_marker_count.
>         (gimple_find_edge_insert_loc): Skip gimple debug stmts.
>         * gimple-iterator.h (gsi_start_bb_nondebug): Remove; adjust
>         callers to use gsi_start_nondebug_bb instead.
>         (gsi_after_labels): Skip gimple debug stmts.
>         (gsi_start_nondebug): New.
>         * gimple-low.c (lower_function_body): Adjust
>         debug_nonbind_markers.
>         (lower_stmt): Drop or skip gimple debug stmts.
>         (lower_try_catch): Skip debug stmts.
>         (gimple_seq_may_fallthru): Take last nondebug stmt.
>         * gimple-pretty-print.c (dump_gimple_debug): Handle begin stmt
>         and inline entry markers.
>         * gimple.c (gimple_build_debug_begin_stmt): New.
>         (gimple_build_debug_inline_entry): New.
>         (gimple_copy): Increment debug_marker_count if copying one.
>         * gimple.h (enum gimple_debug_subcode): Add
>         GIMPLE_DEBUG_BEGIN_STMT and GIMPLE_DEBUG_INLINE_ENTRY.
>         (gimple_build_debug_begin_stmt): Declare.
>         (gimple_build_debug_inline_entry): Declare.
>         (gimple_seq_last_nondebug_stmt): New.
>         (gimple_debug_begin_stmt_p): New.
>         (gimple_debug_inline_entry_p): New.
>         (gimple_debug_nonbind_marker_p): New.
>         * gimplify.c (expr_location): New.
>         (expr_has_location): New.
>         (warn_switch_unreachable_r): Handle gimple debug stmts.
>         (last_stmt_in_scope): Skip debug stmts.
>         (collect_fallthrough_labels): Likewise.
>         (should_warn_for_implicit_fallthrough): Likewise.
>         (warn_implicit_fallthrough_r): Likewise.
>         (expand_FALLTHROUGH_r): Likewise.
>         (shortcut_cond_r): Call expr_location.
>         (find_goto): New.
>         (find_goto_label): New.
>         (shortcut_cond_expr): Call expr_has_location, expr_location, and
>         find_goto_label.
>         (gimplify_cond_expr): Call find_goto_label, expr_has_location, and
>         expr_location.
>         (gimplify_expr): Handle begin stmt markers.  Reject debug expr decls.
>         * graphite-isl-ast-to-gimple.c (gsi_insert_earliest): Adjust.
>         (rename_uses): Skip nonbind markers.
>         * graphite-scop-detection.c (trivially_empty_bb_p): Call
>         is_gimple_debug in test.
>         * haifa-sched.c (sched_extend_bb): Skip debug insns.
>         * insn-notes.def (BEGIN_STMT, INLINE_ENTRY): New.
>         * ipa-icf-gimple.c (func_checker::compare_bb): Adjust.
>         * ira.c (combine_and_move_insns): Adjust bind debug insns only.
>         * jump.c (clean_barriers): Skip debug insns.
>         * langhooks-def.h (LANG_HOOKS_EMITS_BEGIN_STMT): New.  Add to...
>         (LANG_HOOKS_INITIALIZER): ... this.
>         * langhooks.h (struct lang_hooks): Add emits_begin_stmt.
>         * loop-unroll.c (apply_opt_in_copies): Adjust tests on bind
>         debug insns.
>         * lra-contraints.c (inherit_reload_reg): Tolerate between-blocks
>         debug insns.
>         (update_ebb_live_info): Skip debug insn markers.
>         * lra.c (debug_insn_static_data): Rename to...
>         (debug_bind_static_data): ... this.
>         (debug_marker_static_data): New.
>         (lra_set_insn_recog_data): Select one of the above depending
>         on debug insn kind.
>         (lra_update_isn_regno_info): Don't assume debug insns have
>         freqs.
>         (push_insns): Skip debug insns.
>         * lto-streamer-in.c (input_function): Adjust
>         debug_nonbind_markers.
>         * omp-expand.c (expand_parallel_call): Skip debug insns.
>         (expand_cilk_for_call): Likewise.
>         (expand_task_call): Likewise.
>         (remove_exit_barrier): Likewise.
>         (expand_omp_taskreg): Likewise.
>         (expand_omp_for_init_counts): Likewise.
>         (expand_omp_for_generic): Likewise.
>         (expand_omp_for_static_nochunk): Likewise.
>         (expand_omp_for_static_chunk): Likewise.
>         (expand_cilk_for): Likewise.
>         (expand_omp_simd): Likewise.
>         (expand_omp_taskloop_for_outer): Likewise.
>         (expand_omp_taskloop_for_inner): Likewise.
>         (expand_oacc_for): Likewise.
>         (expand_omp_sections): Likewise.
>         (expand_omp_single): Likewise.
>         (expand_omp_synch): Likewise.
>         (expand_omp_atomic_load): Likewise.
>         (expand_omp_atomic_store): Likewise.
>         (expand_omp_atomic_fetch_op): Likewise.
>         (expand_omp_atomic_pipeline): Likewise.
>         (expand_omp_atomic_mutex): Likewise.
>         (expand_omp_target): Likewise.
>         (grid_expand_omp_for_loop): Likewise.
>         (grid_expand_target_grid_body): Likewise.
>         (build_omp_regions_1): Likewise.
>         * omp-low.c (check_combined_parallel): Skip debug stmts.
>         * opts.c (common_handle_option): Accept -gdwarf version 6.
>         * output.h (final_start_function): Adjust.
>         * params.def (PARAM_MAX_DEBUG_MARKER_COUNT): New.
>         * postreload.c (fixup_debug_insns): Skip nonbind debug insns.
>         * print-rtl.c (rtx_writer::print_rtx_operand_code_0): Handle
>         begin stmt and inline entry marker notes.
>         (print_insn): Likewise.
>         * recog.c (extract_insn): Recognize rtl for begin stmt and
>         inline entry markers.
>         * reg-stack.c (convert_regs_1): Use BIND_DEBUG_INSN_P.
>         * regrename.c (build_def_use): Likewise.
>         * regcprop.c (copyprop_hardreg_forward_1): Likewise.
>         (find_oldest_value_reg): Ensure REGNO is not a pseudo.
>         * rtl.def (BEGIN_STMT_MARKER, LEXICAL_BLOCK): New.
>         * rtl.h (MAY_HAVE_DEBUG_INSNS): Check debug_nonbind_markers_p.
>         (NOTE_MARKER_LOCATION): New.
>         (BIND_DEBUG_INSN_P, MARKER_DEBUG_INSN_P): New.
>         (INSN_DEBUG_MARKER_KIND): New.
>         (INSN_VAR_LOCATION): Check for VAR_LOCATION.
>         (INSN_VAR_LOCATION_PTR): New.
>         (LEXICAL_BLOCK_TREE): New.
>         (prev_nonnote_insn_bb, next_nonnote_insn_bb): Remove decls.
>         (prev_nonnote_nondebug_insn_bb): Declare.
>         (next_nonnote_nondebug_insn_bb): Declare.
>         * toplev.c (process_options): Autodetect value for debug statement
>         frontiers and debug variable location views.
>         * tree-cfg.c (make_blobs_1): Skip debug stmts.
>         (make_edges): Likewise.
>         (cleanup_dead_labels): Likewise.
>         (gimple_can_merge_blocks_p): Likewise.
>         (stmt_starts_bb_p): Likewise.
>         (gimple_block_label): Likewise.
>         (gimple_redirect_edge_and_branch): Likewise.
>         * tree-cfgcleanup.c (remove_forwarder_block): Rearrange skipping
>         of debug stmts.
>         (execute_cleanup_cfg_post_optimizing): Dump enumerated decls with
>         TDF_SLIM.
>         * tree-inline.c: Include params.h.
>         (remap_gimple_stmt): Handle nonbind markers.
>         (maybe_move_debug_stmts_to_successors): Likewise.
>         (copy_debug_stmt): Likewise.
>         (expand_call_inline): Build and insert debug_inline_entry stmt.
>         * tree-iterator.c (append_to_statement_list_1): Append begin stmt
>         markers regardless of no side effects.
>         (tsi_link_before): Don't update container's side effects when adding
>         a begin stmt marker.
>         (tsi_link_after): Likewise.
>         (expr_first): Skip begin stmt markers.
>         (expr_last): Likewise.
>         * tree-pretty-print (dump_generic_node): Hnadle begin stmt markers.
>         (print_declaration): Omit initializer in slim dumps.
>         * tree-ssa-dce.c (mark_stmt_if_obviously_necessary): Mark begin stmt
>         markers.
>         (eliminate_unnecessary_stmts): Stabilize block removal order.
>         * tree-ssa-live.c (remove_unused_scope_block_p): Preserve
>         inline entry blocks early, if nonbind markers are enabled.
>         (dump_scope_block): Dump fragment info.
>         * tree-ssa-tail-merge.c (find_duplicate): Skip debug stmts.
>         * tree-ssa-threadedge.c (propagate_threaded_block_debug_info): Handle
>         nonbind markers.
>         * tree.c (make_node_stat): Don't set side effects for begin stmt
>         markers.
>         (build1_stat): Likewise.
>         * tree.def (DEBUG_BEGIN_STMT): New.
>         * tree.h (MAY_HAVE_DEBUG_STMTS): Check debug_nonbind_markers_p.
>         (GOTO_DESTINATION): Require a GOTO_EXPR.
>         * valtrack.c (propagate_for_debug): Use BIND_DEBUG_INSN_P.
>         * var-tracking.c (get_first_insn): New.
>         (vt_emit_notes): Call it.
>         (reemit_marker_as_note): New.
>         (vt_initialize): Reemit markers.  Walk any insns before the first BB.
>         (delete_debug_insns): Renamed to...
>         (delete_vta_debug_insns): ... this.  Likewise.
>         (vt_debug_insns_local): Reemit or delete markers.
>         (variable_tracking_main_1): Likewise.
>
> for  gcc/c-family/ChangeLog
>
>         * c-semantics.c (pop_stmt_list): Move begin stmt marker into
>         subsequent statement list.
>
> for  gcc/c/ChangeLog
>
>         * c-objc-common.h (LANG_HOOKS_EMITS_BEGIN_STMT): Redefine as true.
>         * c-parser.c (add_debug_begin_stmt): New.
>         (c_parser_declaration_or_fndef): Call it.
>         (c_parser_compound_statement_nostart): Likewise.
>         (c_parser_statement_after_labels): Likewise.
>         * c-typeck (c_finish_stmt_expr): Skip begin stmts markers.
>
> for  gcc/cp/ChangeLog
>
>         * constexpr.c (build_data_member_initialization): Skip begin stmt
>         markers.
>         (check_constexpr_ctor_body_1): Likewise.
>         (build_constexpr_constructor_member_initializers): Likewise.
>         (constexpr_fn_retval): Likewise.
>         (cxx_eval_statement_list): Likewise.
>         (potential_constant_expression_1): Likewise.
>         * cp-array-notation.c (stmt_location): New.
>         (cp_expand_cond_array_notations): Use it.
>         * cp-objcp-common.h (LANG_HOOKS_EMITS_BEGIN_STMT): Redefine as true.
>         * parser.c (add_debug_begin_stmt): New.
>         (cp_parser_statement): Call it.
>         * pt.c (tsubst_copy): Handle begin stmt markers.
> ---
>  gcc/c-family/c-semantics.c         |   21 +
>  gcc/c/c-objc-common.h              |    2
>  gcc/c/c-parser.c                   |   20 +
>  gcc/c/c-typeck.c                   |    8
>  gcc/cfgbuild.c                     |   14 +
>  gcc/cfgexpand.c                    |  154 ++++--
>  gcc/cfgrtl.c                       |   22 +
>  gcc/common.opt                     |   16 +
>  gcc/config.in                      |    6
>  gcc/config/aarch64/aarch64.c       |    2
>  gcc/config/alpha/alpha.c           |    2
>  gcc/config/arm/arm.c               |    5
>  gcc/config/cris/cris.c             |    3
>  gcc/config/i386/i386.c             |    5
>  gcc/config/ia64/ia64.c             |    2
>  gcc/config/m68k/m68k.c             |    2
>  gcc/config/microblaze/microblaze.c |    2
>  gcc/config/mips/mips.c             |    2
>  gcc/config/nds32/nds32.c           |    3
>  gcc/config/nios2/nios2.c           |    2
>  gcc/config/pa/pa.c                 |    3
>  gcc/config/rs6000/rs6000.c         |    5
>  gcc/config/s390/s390.c             |    3
>  gcc/config/sh/sh.c                 |    2
>  gcc/config/sparc/sparc.c           |    2
>  gcc/config/spu/spu.c               |    3
>  gcc/config/tilegx/tilegx.c         |    2
>  gcc/config/tilepro/tilepro.c       |    2
>  gcc/configure                      |   46 ++
>  gcc/configure.ac                   |   18 +
>  gcc/cp/constexpr.c                 |   11
>  gcc/cp/cp-array-notation.c         |   37 +-
>  gcc/cp/cp-objcp-common.h           |    2
>  gcc/cp/parser.c                    |   14 +
>  gcc/cp/pt.c                        |    6
>  gcc/cse.c                          |   11
>  gcc/dbxout.c                       |    2
>  gcc/debug.c                        |    1
>  gcc/debug.h                        |    3
>  gcc/df-scan.c                      |    2
>  gcc/doc/generic.texi               |    5
>  gcc/doc/gimple.texi                |   16 +
>  gcc/doc/invoke.texi                |   46 ++
>  gcc/doc/rtl.texi                   |   33 +
>  gcc/dwarf2asm.c                    |   25 +
>  gcc/dwarf2asm.h                    |    4
>  gcc/dwarf2out.c                    |  869 +++++++++++++++++++++++++++++++++---
>  gcc/dwarf2out.h                    |    4
>  gcc/emit-rtl.c                     |   69 ++-
>  gcc/final.c                        |  236 +++++++++-
>  gcc/function.c                     |   13 -
>  gcc/function.h                     |   10
>  gcc/gimple-iterator.c              |   26 +
>  gcc/gimple-iterator.h              |   46 +-
>  gcc/gimple-low.c                   |   28 +
>  gcc/gimple-pretty-print.c          |   20 +
>  gcc/gimple.c                       |   45 ++
>  gcc/gimple.h                       |   62 ++-
>  gcc/gimplify.c                     |  179 ++++++-
>  gcc/graphite-isl-ast-to-gimple.c   |    7
>  gcc/graphite-scop-detection.c      |    2
>  gcc/haifa-sched.c                  |    2
>  gcc/insn-notes.def                 |    7
>  gcc/ipa-icf-gimple.c               |    4
>  gcc/ira.c                          |    2
>  gcc/jump.c                         |    2
>  gcc/langhooks-def.h                |    2
>  gcc/langhooks.h                    |    3
>  gcc/loop-unroll.c                  |    6
>  gcc/lra-constraints.c              |   10
>  gcc/lra.c                          |   38 +-
>  gcc/lto-streamer-in.c              |    7
>  gcc/omp-expand.c                   |  161 +++----
>  gcc/omp-low.c                      |    2
>  gcc/opts.c                         |    2
>  gcc/output.h                       |    2
>  gcc/params.def                     |    9
>  gcc/postreload.c                   |    2
>  gcc/print-rtl.c                    |   29 +
>  gcc/recog.c                        |    2
>  gcc/reg-stack.c                    |    4
>  gcc/regcprop.c                     |    4
>  gcc/regrename.c                    |    2
>  gcc/rtl.def                        |    6
>  gcc/rtl.h                          |   45 ++
>  gcc/sdbout.c                       |    1
>  gcc/toplev.c                       |   12
>  gcc/tree-cfg.c                     |   52 ++
>  gcc/tree-cfgcleanup.c              |   31 -
>  gcc/tree-inline.c                  |   41 ++
>  gcc/tree-iterator.c                |   48 ++
>  gcc/tree-pretty-print.c            |    9
>  gcc/tree-ssa-dce.c                 |    6
>  gcc/tree-ssa-live.c                |   27 +
>  gcc/tree-ssa-tail-merge.c          |    4
>  gcc/tree-ssa-threadedge.c          |    8
>  gcc/tree.c                         |    8
>  gcc/tree.def                       |    3
>  gcc/tree.h                         |    5
>  gcc/valtrack.c                     |    2
>  gcc/var-tracking.c                 |  125 +++++
>  gcc/vmsdbgout.c                    |    1
>  include/dwarf2.def                 |    2
>  include/dwarf2.h                   |    8
>  104 files changed, 2467 insertions(+), 492 deletions(-)
>
> diff --git a/gcc/c-family/c-semantics.c b/gcc/c-family/c-semantics.c
> index 3ceb714..cd872d8 100644
> --- a/gcc/c-family/c-semantics.c
> +++ b/gcc/c-family/c-semantics.c
> @@ -76,6 +76,27 @@ pop_stmt_list (tree t)
>           free_stmt_list (t);
>           t = u;
>         }
> +      /* If the statement list contained a debug begin stmt and a
> +        statement list, move the debug begin stmt into the statement
> +        list and return it.  */
> +      else if (!tsi_end_p (i)
> +              && TREE_CODE (tsi_stmt (i)) == DEBUG_BEGIN_STMT)
> +       {
> +         u = tsi_stmt (i);
> +         tsi_next (&i);
> +         if (tsi_one_before_end_p (i)
> +             && TREE_CODE (tsi_stmt (i)) == STATEMENT_LIST)
> +           {
> +             tree l = tsi_stmt (i);
> +             tsi_prev (&i);
> +             tsi_delink (&i);
> +             tsi_delink (&i);
> +             i = tsi_start (l);
> +             free_stmt_list (t);
> +             t = l;
> +             tsi_link_before (&i, u, TSI_SAME_STMT);
> +           }
> +       }
>      }
>
>    return t;
> diff --git a/gcc/c/c-objc-common.h b/gcc/c/c-objc-common.h
> index bee06e9..27ceabc 100644
> --- a/gcc/c/c-objc-common.h
> +++ b/gcc/c/c-objc-common.h
> @@ -60,6 +60,8 @@ along with GCC; see the file COPYING3.  If not see
>  #define LANG_HOOKS_BUILTIN_FUNCTION c_builtin_function
>  #undef  LANG_HOOKS_BUILTIN_FUNCTION_EXT_SCOPE
>  #define LANG_HOOKS_BUILTIN_FUNCTION_EXT_SCOPE c_builtin_function_ext_scope
> +#undef LANG_HOOKS_EMITS_BEGIN_STMT
> +#define LANG_HOOKS_EMITS_BEGIN_STMT true
>
>  /* Attribute hooks.  */
>  #undef LANG_HOOKS_COMMON_ATTRIBUTE_TABLE
> diff --git a/gcc/c/c-parser.c b/gcc/c/c-parser.c
> index 1402ba6..684bc82 100644
> --- a/gcc/c/c-parser.c
> +++ b/gcc/c/c-parser.c
> @@ -1640,6 +1640,19 @@ c_parser_external_declaration (c_parser *parser)
>  static void c_finish_omp_declare_simd (c_parser *, tree, tree, vec<c_token>);
>  static void c_finish_oacc_routine (struct oacc_routine_data *, tree, bool);
>
> +/* Build and add a DEBUG_BEGIN_STMT statement with location LOC.  */
> +
> +static void
> +add_debug_begin_stmt (location_t loc)
> +{
> +  if (!debug_nonbind_markers_p)
> +    return;
> +
> +  tree stmt = build0 (DEBUG_BEGIN_STMT, void_type_node);
> +  SET_EXPR_LOCATION (stmt, loc);
> +  add_stmt (stmt);
> +}
> +
>  /* Parse a declaration or function definition (C90 6.5, 6.7.1, C99
>     6.7, 6.9.1, C11 6.7, 6.9.1).  If FNDEF_OK is true, a function definition
>     is accepted; otherwise (old-style parameter declarations) only other
> @@ -1740,6 +1753,8 @@ c_parser_declaration_or_fndef (c_parser *parser, bool fndef_ok,
>    bool diagnosed_no_specs = false;
>    location_t here = c_parser_peek_token (parser)->location;
>
> +  add_debug_begin_stmt (c_parser_peek_token (parser)->location);
> +
>    if (static_assert_ok
>        && c_parser_next_token_is_keyword (parser, RID_STATIC_ASSERT))
>      {
> @@ -4949,6 +4964,7 @@ c_parser_compound_statement_nostart (c_parser *parser)
>    location_t label_loc = UNKNOWN_LOCATION;  /* Quiet warning.  */
>    if (c_parser_next_token_is (parser, CPP_CLOSE_BRACE))
>      {
> +      add_debug_begin_stmt (c_parser_peek_token (parser)->location);
>        c_parser_consume_token (parser);
>        return;
>      }
> @@ -5403,6 +5419,10 @@ c_parser_statement_after_labels (c_parser *parser, bool *if_p,
>    parser->in_if_block = false;
>    if (if_p != NULL)
>      *if_p = false;
> +
> +  if (c_parser_peek_token (parser)->type != CPP_OPEN_BRACE)
> +    add_debug_begin_stmt (loc);
> +
>    switch (c_parser_peek_token (parser)->type)
>      {
>      case CPP_OPEN_BRACE:
> diff --git a/gcc/c/c-typeck.c b/gcc/c/c-typeck.c
> index c33601f..d378470 100644
> --- a/gcc/c/c-typeck.c
> +++ b/gcc/c/c-typeck.c
> @@ -10681,6 +10681,10 @@ c_finish_stmt_expr (location_t loc, tree body)
>         }
>        else
>         i = tsi_last (last);
> +      if (TREE_CODE (tsi_stmt (i)) == DEBUG_BEGIN_STMT)
> +       do
> +         tsi_prev (&i);
> +       while (TREE_CODE (tsi_stmt (i)) == DEBUG_BEGIN_STMT);
>        last_p = tsi_stmt_ptr (i);
>        last = *last_p;
>      }
> @@ -10700,7 +10704,9 @@ c_finish_stmt_expr (location_t loc, tree body)
>
>    /* In the case that the BIND_EXPR is not necessary, return the
>       expression out from inside it.  */
> -  if (last == BIND_EXPR_BODY (body)
> +  if ((last == BIND_EXPR_BODY (body)
> +       /* Skip nested debug stmts.  */
> +       || last == expr_first (BIND_EXPR_BODY (body)))
>        && BIND_EXPR_VARS (body) == NULL)
>      {
>        /* Even if this looks constant, do not allow it in a constant
> diff --git a/gcc/cfgbuild.c b/gcc/cfgbuild.c
> index 2fe74c4..dde6c2d 100644
> --- a/gcc/cfgbuild.c
> +++ b/gcc/cfgbuild.c
> @@ -443,6 +443,7 @@ find_bb_boundaries (basic_block bb)
>    rtx_jump_table_data *table;
>    rtx_insn *flow_transfer_insn = NULL;
>    edge fallthru = NULL;
> +  bool only_header_debug_insns_p = true;
>
>    if (insn == BB_END (bb))
>      return;
> @@ -460,6 +461,13 @@ find_bb_boundaries (basic_block bb)
>        if ((flow_transfer_insn || code == CODE_LABEL)
>           && inside_basic_block_p (insn))
>         {
> +         if (only_header_debug_insns_p)
> +           {
> +             gcc_assert (!flow_transfer_insn);
> +             BB_HEAD (bb) = insn;
> +             goto end;
> +           }
> +
>           fallthru = split_block (bb, PREV_INSN (insn));
>           if (flow_transfer_insn)
>             {
> @@ -471,6 +479,7 @@ find_bb_boundaries (basic_block bb)
>                    x = NEXT_INSN (x))
>                 if (!BARRIER_P (x))
>                   set_block_for_insn (x, NULL);
> +             only_header_debug_insns_p = true;
>             }
>
>           bb = fallthru->dest;
> @@ -489,13 +498,16 @@ find_bb_boundaries (basic_block bb)
>              the middle of a BB.  We need to split it in the same manner as
>              if the barrier were preceded by a control_flow_insn_p insn.  */
>           if (!flow_transfer_insn)
> -           flow_transfer_insn = prev_nonnote_insn_bb (insn);
> +           flow_transfer_insn = prev_nonnote_nondebug_insn_bb (insn);
>         }
>
>        if (control_flow_insn_p (insn))
>         flow_transfer_insn = insn;
> +    end:
>        if (insn == end)
>         break;
> +      if (!DEBUG_INSN_P (insn))
> +       only_header_debug_insns_p = false;
>        insn = NEXT_INSN (insn);
>      }
>
> diff --git a/gcc/cfgexpand.c b/gcc/cfgexpand.c
> index 7f0130d..e920639 100644
> --- a/gcc/cfgexpand.c
> +++ b/gcc/cfgexpand.c
> @@ -2319,6 +2319,9 @@ label_rtx_for_bb (basic_block bb ATTRIBUTE_UNUSED)
>      {
>        glabel *lab_stmt;
>
> +      if (is_gimple_debug (gsi_stmt (gsi)))
> +       continue;
> +
>        lab_stmt = dyn_cast <glabel *> (gsi_stmt (gsi));
>        if (!lab_stmt)
>         break;
> @@ -5288,7 +5291,7 @@ expand_debug_locations (void)
>    flag_strict_aliasing = 0;
>
>    for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
> -    if (DEBUG_INSN_P (insn))
> +    if (BIND_DEBUG_INSN_P (insn))
>        {
>         tree value = (tree)INSN_VAR_LOCATION_LOC (insn);
>         rtx val;
> @@ -5435,7 +5438,7 @@ expand_gimple_basic_block (basic_block bb, bool disable_tail_calls)
>    gimple_stmt_iterator gsi;
>    gimple_seq stmts;
>    gimple *stmt = NULL;
> -  rtx_note *note;
> +  rtx_note *note = NULL;
>    rtx_insn *last;
>    edge e;
>    edge_iterator ei;
> @@ -5476,18 +5479,26 @@ expand_gimple_basic_block (basic_block bb, bool disable_tail_calls)
>         }
>      }
>
> -  gsi = gsi_start (stmts);
> +  gsi = gsi_start_nondebug (stmts);
>    if (!gsi_end_p (gsi))
>      {
>        stmt = gsi_stmt (gsi);
>        if (gimple_code (stmt) != GIMPLE_LABEL)
>         stmt = NULL;
>      }
> +  gsi = gsi_start (stmts);
>
> +  gimple *label_stmt = stmt;
>    rtx_code_label **elt = lab_rtx_for_bb->get (bb);
>
> -  if (stmt || elt)
> +  if (stmt)
> +    /* We'll get to it in the loop below, and get back to
> +       emit_label_and_note then.  */
> +    ;
> +  else if (stmt || elt)
>      {
> +    emit_label_and_note:
> +      gcc_checking_assert (!note);
>        last = get_last_insn ();
>
>        if (stmt)
> @@ -5502,6 +5513,7 @@ expand_gimple_basic_block (basic_block bb, bool disable_tail_calls)
>        BB_HEAD (bb) = NEXT_INSN (last);
>        if (NOTE_P (BB_HEAD (bb)))
>         BB_HEAD (bb) = NEXT_INSN (BB_HEAD (bb));
> +      gcc_assert (LABEL_P (BB_HEAD (bb)));
>        note = emit_note_after (NOTE_INSN_BASIC_BLOCK, BB_HEAD (bb));
>
>        maybe_dump_rtl_for_gimple_stmt (stmt, last);
> @@ -5509,7 +5521,8 @@ expand_gimple_basic_block (basic_block bb, bool disable_tail_calls)
>    else
>      BB_HEAD (bb) = note = emit_note (NOTE_INSN_BASIC_BLOCK);
>
> -  NOTE_BASIC_BLOCK (note) = bb;
> +  if (note)
> +    NOTE_BASIC_BLOCK (note) = bb;
>
>    for (; !gsi_end_p (gsi); gsi_next (&gsi))
>      {
> @@ -5517,6 +5530,9 @@ expand_gimple_basic_block (basic_block bb, bool disable_tail_calls)
>
>        stmt = gsi_stmt (gsi);
>
> +      if (stmt == label_stmt)
> +       goto emit_label_and_note;
> +
>        /* If this statement is a non-debug one, and we generate debug
>          insns, then this one might be the last real use of a TERed
>          SSA_NAME, but where there are still some debug uses further
> @@ -5622,39 +5638,89 @@ expand_gimple_basic_block (basic_block bb, bool disable_tail_calls)
>           if (new_bb)
>             return new_bb;
>         }
> -      else if (gimple_debug_bind_p (stmt))
> +      else if (gimple_debug_source_bind_p (stmt))
> +       {
> +         location_t sloc = curr_insn_location ();
> +         tree var = gimple_debug_source_bind_get_var (stmt);
> +         tree value = gimple_debug_source_bind_get_value (stmt);
> +         rtx val;
> +         machine_mode mode;
> +
> +         last = get_last_insn ();
> +
> +         set_curr_insn_location (gimple_location (stmt));
> +
> +         mode = DECL_MODE (var);
> +
> +         val = gen_rtx_VAR_LOCATION (mode, var, (rtx)value,
> +                                     VAR_INIT_STATUS_UNINITIALIZED);
> +
> +         emit_debug_insn (val);
> +
> +         if (dump_file && (dump_flags & TDF_DETAILS))
> +           {
> +             /* We can't dump the insn with a TREE where an RTX
> +                is expected.  */
> +             PAT_VAR_LOCATION_LOC (val) = const0_rtx;
> +             maybe_dump_rtl_for_gimple_stmt (stmt, last);
> +             PAT_VAR_LOCATION_LOC (val) = (rtx)value;
> +           }
> +
> +         set_curr_insn_location (sloc);
> +       }
> +      else if (is_gimple_debug (stmt))
>         {
>           location_t sloc = curr_insn_location ();
>           gimple_stmt_iterator nsi = gsi;
>
>           for (;;)
>             {
> -             tree var = gimple_debug_bind_get_var (stmt);
> -             tree value;
> -             rtx val;
> +             tree var;
> +             tree value = NULL_TREE;
> +             rtx val = NULL_RTX;
>               machine_mode mode;
>
> -             if (TREE_CODE (var) != DEBUG_EXPR_DECL
> -                 && TREE_CODE (var) != LABEL_DECL
> -                 && !target_for_debug_bind (var))
> +             if (gimple_debug_bind_p (stmt))
> +               {
> +                 var = gimple_debug_bind_get_var (stmt);
> +
> +                 if (TREE_CODE (var) != DEBUG_EXPR_DECL
> +                     && TREE_CODE (var) != LABEL_DECL
> +                     && !target_for_debug_bind (var))
> +                   goto delink_debug_stmt;
> +
> +                 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);
> +               }
> +             else if (gimple_debug_nonbind_marker_p (stmt)
> +                      && !cfun->debug_nonbind_markers)
>                 goto delink_debug_stmt;
> +             else if (gimple_debug_begin_stmt_p (stmt))
> +               val = gen_rtx_BEGIN_STMT_MARKER (VOIDmode);
> +             else if (gimple_debug_inline_entry_p (stmt))
> +               {
> +                 tree block = gimple_block (stmt);
>
> -             if (gimple_debug_bind_has_value_p (stmt))
> -               value = gimple_debug_bind_get_value (stmt);
> +                 if (block)
> +                   val = gen_rtx_LEXICAL_BLOCK (VOIDmode, block);
> +                 else
> +                   goto delink_debug_stmt;
> +               }
>               else
> -               value = NULL_TREE;
> +               gcc_unreachable ();
>
>               last = get_last_insn ();
>
>               set_curr_insn_location (gimple_location (stmt));
>
> -             if (DECL_P (var))
> -               mode = DECL_MODE (var);
> -             else
> -               mode = TYPE_MODE (TREE_TYPE (var));
> -
> -             val = gen_rtx_VAR_LOCATION
> -               (mode, var, (rtx)value, VAR_INIT_STATUS_INITIALIZED);
> +             if (!val)
> +               val = gen_rtx_VAR_LOCATION
> +                 (mode, var, (rtx)value, VAR_INIT_STATUS_INITIALIZED);
>
>               emit_debug_insn (val);
>
> @@ -5662,9 +5728,11 @@ expand_gimple_basic_block (basic_block bb, bool disable_tail_calls)
>                 {
>                   /* We can't dump the insn with a TREE where an RTX
>                      is expected.  */
> -                 PAT_VAR_LOCATION_LOC (val) = const0_rtx;
> +                 if (GET_CODE (val) == VAR_LOCATION)
> +                   PAT_VAR_LOCATION_LOC (val) = const0_rtx;
>                   maybe_dump_rtl_for_gimple_stmt (stmt, last);
> -                 PAT_VAR_LOCATION_LOC (val) = (rtx)value;
> +                 if (GET_CODE (val) == VAR_LOCATION)
> +                   PAT_VAR_LOCATION_LOC (val) = (rtx)value;
>                 }
>
>             delink_debug_stmt:
> @@ -5680,42 +5748,13 @@ expand_gimple_basic_block (basic_block bb, bool disable_tail_calls)
>               if (gsi_end_p (nsi))
>                 break;
>               stmt = gsi_stmt (nsi);
> -             if (!gimple_debug_bind_p (stmt))
> +             if (!gimple_debug_bind_p (stmt)
> +                 && !gimple_debug_nonbind_marker_p (stmt))
>                 break;
>             }
>
>           set_curr_insn_location (sloc);
>         }
> -      else if (gimple_debug_source_bind_p (stmt))
> -       {
> -         location_t sloc = curr_insn_location ();
> -         tree var = gimple_debug_source_bind_get_var (stmt);
> -         tree value = gimple_debug_source_bind_get_value (stmt);
> -         rtx val;
> -         machine_mode mode;
> -
> -         last = get_last_insn ();
> -
> -         set_curr_insn_location (gimple_location (stmt));
> -
> -         mode = DECL_MODE (var);
> -
> -         val = gen_rtx_VAR_LOCATION (mode, var, (rtx)value,
> -                                     VAR_INIT_STATUS_UNINITIALIZED);
> -
> -         emit_debug_insn (val);
> -
> -         if (dump_file && (dump_flags & TDF_DETAILS))
> -           {
> -             /* We can't dump the insn with a TREE where an RTX
> -                is expected.  */
> -             PAT_VAR_LOCATION_LOC (val) = const0_rtx;
> -             maybe_dump_rtl_for_gimple_stmt (stmt, last);
> -             PAT_VAR_LOCATION_LOC (val) = (rtx)value;
> -           }
> -
> -         set_curr_insn_location (sloc);
> -       }
>        else
>         {
>           gcall *call_stmt = dyn_cast <gcall *> (stmt);
> @@ -6354,6 +6393,11 @@ pass_expand::execute (function *fun)
>    FOR_EACH_EDGE (e, ei, ENTRY_BLOCK_PTR_FOR_FN (fun)->succs)
>      e->flags &= ~EDGE_EXECUTABLE;
>
> +  /* If the function has too many markers, drop them while expanding.  */
> +  if (cfun->debug_marker_count
> +      >= PARAM_VALUE (PARAM_MAX_DEBUG_MARKER_COUNT))
> +    cfun->debug_nonbind_markers = false;
> +
>    lab_rtx_for_bb = new hash_map<basic_block, rtx_code_label *>;
>    FOR_BB_BETWEEN (bb, init_block->next_bb, EXIT_BLOCK_PTR_FOR_FN (fun),
>                   next_bb)
> diff --git a/gcc/cfgrtl.c b/gcc/cfgrtl.c
> index 6ef47b7..fde4128 100644
> --- a/gcc/cfgrtl.c
> +++ b/gcc/cfgrtl.c
> @@ -1117,7 +1117,7 @@ try_redirect_by_replacing_jump (edge e, basic_block target, bool in_cfglayout)
>        if (tablejump_p (insn, &label, &table))
>         delete_insn_chain (label, table, false);
>
> -      barrier = next_nonnote_insn (BB_END (src));
> +      barrier = next_nonnote_nondebug_insn (BB_END (src));
>        if (!barrier || !BARRIER_P (barrier))
>         emit_barrier_after (BB_END (src));
>        else
> @@ -1753,7 +1753,7 @@ rtl_tidy_fallthru_edge (edge e)
>       the head of block C and assert that we really do fall through.  */
>
>    for (q = NEXT_INSN (BB_END (b)); q != BB_HEAD (c); q = NEXT_INSN (q))
> -    if (INSN_P (q))
> +    if (NONDEBUG_INSN_P (q))
>        return;
>
>    /* Remove what will soon cease being the jump insn from the source block.
> @@ -2274,11 +2274,11 @@ get_last_bb_insn (basic_block bb)
>      end = table;
>
>    /* Include any barriers that may follow the basic block.  */
> -  tmp = next_nonnote_insn_bb (end);
> +  tmp = next_nonnote_nondebug_insn_bb (end);
>    while (tmp && BARRIER_P (tmp))
>      {
>        end = tmp;
> -      tmp = next_nonnote_insn_bb (end);
> +      tmp = next_nonnote_nondebug_insn_bb (end);
>      }
>
>    return end;
> @@ -2894,7 +2894,7 @@ rtl_verify_fallthru (void)
>           else
>             for (insn = NEXT_INSN (BB_END (e->src)); insn != BB_HEAD (e->dest);
>                  insn = NEXT_INSN (insn))
> -             if (BARRIER_P (insn) || INSN_P (insn))
> +             if (BARRIER_P (insn) || NONDEBUG_INSN_P (insn))
>                 {
>                   error ("verify_flow_info: Incorrect fallthru %i->%i",
>                          e->src->index, e->dest->index);
> @@ -2916,7 +2916,7 @@ rtl_verify_bb_layout (void)
>  {
>    basic_block bb;
>    int err = 0;
> -  rtx_insn *x;
> +  rtx_insn *x, *y;
>    int num_bb_notes;
>    rtx_insn * const rtx_first = get_insns ();
>    basic_block last_bb_seen = ENTRY_BLOCK_PTR_FOR_FN (cfun), curr_bb = NULL;
> @@ -2943,6 +2943,7 @@ rtl_verify_bb_layout (void)
>             {
>             case BARRIER:
>             case NOTE:
> +           case DEBUG_INSN:
>               break;
>
>             case CODE_LABEL:
> @@ -2961,7 +2962,8 @@ rtl_verify_bb_layout (void)
>
>        if (JUMP_P (x)
>           && returnjump_p (x) && ! condjump_p (x)
> -         && ! (next_nonnote_insn (x) && BARRIER_P (next_nonnote_insn (x))))
> +         && ! ((y = next_nonnote_nondebug_insn (x))
> +               && BARRIER_P (y)))
>             fatal_insn ("return not followed by barrier", x);
>
>        if (curr_bb && x == BB_END (curr_bb))
> @@ -3382,6 +3384,9 @@ skip_insns_after_block (basic_block bb)
>           last_insn = insn;
>           continue;
>
> +       case DEBUG_INSN:
> +         continue;
> +
>         case NOTE:
>           switch (NOTE_KIND (insn))
>             {
> @@ -4135,7 +4140,8 @@ duplicate_insn_chain (rtx_insn *from, rtx_insn *to)
>         {
>         case DEBUG_INSN:
>           /* Don't duplicate label debug insns.  */
> -         if (TREE_CODE (INSN_VAR_LOCATION_DECL (insn)) == LABEL_DECL)
> +         if (BIND_DEBUG_INSN_P (insn)
> +             && TREE_CODE (INSN_VAR_LOCATION_DECL (insn)) == LABEL_DECL)
>             break;
>           /* FALLTHRU */
>         case INSN:
> diff --git a/gcc/common.opt b/gcc/common.opt
> index 1cb1c83..7d5e5624 100644
> --- a/gcc/common.opt
> +++ b/gcc/common.opt
> @@ -2882,6 +2882,14 @@ gstabs+
>  Common Driver JoinedOrMissing Negative(gvms)
>  Generate debug information in extended STABS format.
>
> +gno-statement-frontiers
> +Common Driver RejectNegative Var(debug_nonbind_markers_p, 0) Init(2)
> +Don't enforce progressive recommended breakpoint locations.
> +
> +gstatement-frontiers
> +Common Driver RejectNegative Var(debug_nonbind_markers_p, 1)
> +Emit progressive recommended breakpoint locations.
> +
>  gno-strict-dwarf
>  Common Driver RejectNegative Var(dwarf_strict,0) Init(0)
>  Emit DWARF additions beyond selected version.
> @@ -2894,6 +2902,14 @@ gtoggle
>  Common Driver Report Var(flag_gtoggle)
>  Toggle debug information generation.
>
> +gno-variable-location-views
> +Common Driver RejectNegative Var(debug_variable_location_views, 0) Init(2)
> +Don't augment variable location lists with progressive views.
> +
> +gvariable-location-views
> +Common Driver RejectNegative Var(debug_variable_location_views, 1)
> +Augment variable location lists with progressive views.
> +
>  gvms
>  Common Driver JoinedOrMissing Negative(gxcoff)
>  Generate debug information in VMS format.
> diff --git a/gcc/config.in b/gcc/config.in
> index 89d7108..8c33967 100644
> --- a/gcc/config.in
> +++ b/gcc/config.in
> @@ -358,6 +358,12 @@
>  #endif
>
>
> +/* Define if your assembler supports views in dwarf2 .loc directives. */
> +#ifndef USED_FOR_TARGET
> +#undef HAVE_AS_DWARF2_DEBUG_VIEW
> +#endif
> +
> +
>  /* Define if your assembler supports the R_PPC64_ENTRY relocation. */
>  #ifndef USED_FOR_TARGET
>  #undef HAVE_AS_ENTRY_MARKERS
> diff --git a/gcc/config/aarch64/aarch64.c b/gcc/config/aarch64/aarch64.c
> index 28c4e0e..51584f5 100644
> --- a/gcc/config/aarch64/aarch64.c
> +++ b/gcc/config/aarch64/aarch64.c
> @@ -3936,7 +3936,7 @@ aarch64_output_mi_thunk (FILE *file, tree thunk ATTRIBUTE_UNUSED,
>
>    insn = get_insns ();
>    shorten_branches (insn);
> -  final_start_function (insn, file, 1);
> +  final_start_function (&insn, file, 1);
>    final (insn, file, 1);
>    final_end_function ();
>
> diff --git a/gcc/config/alpha/alpha.c b/gcc/config/alpha/alpha.c
> index e13c5f9..c158f7a 100644
> --- a/gcc/config/alpha/alpha.c
> +++ b/gcc/config/alpha/alpha.c
> @@ -8461,7 +8461,7 @@ alpha_output_mi_thunk_osf (FILE *file, tree thunk_fndecl ATTRIBUTE_UNUSED,
>       assemble_start_function and assemble_end_function.  */
>    insn = get_insns ();
>    shorten_branches (insn);
> -  final_start_function (insn, file, 1);
> +  final_start_function (&insn, file, 1);
>    final (insn, file, 1);
>    final_end_function ();
>  }
> diff --git a/gcc/config/arm/arm.c b/gcc/config/arm/arm.c
> index fa3e2fa..71a0d2d 100644
> --- a/gcc/config/arm/arm.c
> +++ b/gcc/config/arm/arm.c
> @@ -26357,7 +26357,8 @@ arm_thumb1_mi_thunk (FILE *file, tree, HOST_WIDE_INT delta,
>    if (mi_delta < 0)
>      mi_delta = - mi_delta;
>
> -  final_start_function (emit_barrier (), file, 1);
> +  rtx_insn *first = emit_barrier ();
> +  final_start_function (&first, file, 1);
>
>    if (TARGET_THUMB1)
>      {
> @@ -26534,7 +26535,7 @@ arm32_output_mi_thunk (FILE *file, tree, HOST_WIDE_INT delta,
>
>    insn = get_insns ();
>    shorten_branches (insn);
> -  final_start_function (insn, file, 1);
> +  final_start_function (&insn, file, 1);
>    final (insn, file, 1);
>    final_end_function ();
>
> diff --git a/gcc/config/cris/cris.c b/gcc/config/cris/cris.c
> index b57881a..376c1eb 100644
> --- a/gcc/config/cris/cris.c
> +++ b/gcc/config/cris/cris.c
> @@ -2744,7 +2744,8 @@ cris_asm_output_mi_thunk (FILE *stream,
>                           tree funcdecl)
>  {
>    /* Make sure unwind info is emitted for the thunk if needed.  */
> -  final_start_function (emit_barrier (), stream, 1);
> +  rtx_insn *first = emit_barrier ();
> +  final_start_function (&first, stream, 1);
>
>    if (delta > 0)
>      fprintf (stream, "\tadd%s " HOST_WIDE_INT_PRINT_DEC ",$%s\n",
> diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c
> index 1d88e4f..86320a7 100644
> --- a/gcc/config/i386/i386.c
> +++ b/gcc/config/i386/i386.c
> @@ -12492,8 +12492,9 @@ ix86_code_end (void)
>          emitting it directly; tell them we're a thunk, if they care.  */
>        cfun->is_thunk = true;
>        first_function_block_is_cold = false;
> +      rtx_insn *first = emit_barrier ();
>        /* Make sure unwind info is emitted for the thunk if needed.  */
> -      final_start_function (emit_barrier (), asm_out_file, 1);
> +      final_start_function (&first, asm_out_file, 1);
>
>        /* Pad stack IP move with 4 instructions (two NOPs count
>          as one instruction).  */
> @@ -42615,7 +42616,7 @@ x86_output_mi_thunk (FILE *file, tree, HOST_WIDE_INT delta,
>       Note that use_thunk calls assemble_start_function et al.  */
>    insn = get_insns ();
>    shorten_branches (insn);
> -  final_start_function (insn, file, 1);
> +  final_start_function (&insn, file, 1);
>    final (insn, file, 1);
>    final_end_function ();
>  }
> diff --git a/gcc/config/ia64/ia64.c b/gcc/config/ia64/ia64.c
> index 79c323f..2a05293 100644
> --- a/gcc/config/ia64/ia64.c
> +++ b/gcc/config/ia64/ia64.c
> @@ -10944,7 +10944,7 @@ ia64_output_mi_thunk (FILE *file, tree thunk ATTRIBUTE_UNUSED,
>    emit_all_insn_group_barriers (NULL);
>    insn = get_insns ();
>    shorten_branches (insn);
> -  final_start_function (insn, file, 1);
> +  final_start_function (&insn, file, 1);
>    final (insn, file, 1);
>    final_end_function ();
>
> diff --git a/gcc/config/m68k/m68k.c b/gcc/config/m68k/m68k.c
> index 8972665..3b656c7 100644
> --- a/gcc/config/m68k/m68k.c
> +++ b/gcc/config/m68k/m68k.c
> @@ -5131,7 +5131,7 @@ m68k_output_mi_thunk (FILE *file, tree thunk ATTRIBUTE_UNUSED,
>    /* Run just enough of rest_of_compilation.  */
>    insn = get_insns ();
>    split_all_insns_noflow ();
> -  final_start_function (insn, file, 1);
> +  final_start_function (&insn, file, 1);
>    final (insn, file, 1);
>    final_end_function ();
>
> diff --git a/gcc/config/microblaze/microblaze.c b/gcc/config/microblaze/microblaze.c
> index 2cdd240..9f862292 100644
> --- a/gcc/config/microblaze/microblaze.c
> +++ b/gcc/config/microblaze/microblaze.c
> @@ -3233,7 +3233,7 @@ microblaze_asm_output_mi_thunk (FILE *file, tree thunk_fndecl ATTRIBUTE_UNUSED,
>       "borrowed" from rs6000.c.  */
>    insn = get_insns ();
>    shorten_branches (insn);
> -  final_start_function (insn, file, 1);
> +  final_start_function (&insn, file, 1);
>    final (insn, file, 1);
>    final_end_function ();
>
> diff --git a/gcc/config/mips/mips.c b/gcc/config/mips/mips.c
> index d2737a6..7dcc835 100644
> --- a/gcc/config/mips/mips.c
> +++ b/gcc/config/mips/mips.c
> @@ -19353,7 +19353,7 @@ mips_output_mi_thunk (FILE *file, tree thunk_fndecl ATTRIBUTE_UNUSED,
>    split_all_insns_noflow ();
>    mips16_lay_out_constants (true);
>    shorten_branches (insn);
> -  final_start_function (insn, file, 1);
> +  final_start_function (&insn, file, 1);
>    final (insn, file, 1);
>    final_end_function ();
>
> diff --git a/gcc/config/nds32/nds32.c b/gcc/config/nds32/nds32.c
> index 14310de..478824f 100644
> --- a/gcc/config/nds32/nds32.c
> +++ b/gcc/config/nds32/nds32.c
> @@ -1635,7 +1635,8 @@ nds32_asm_output_mi_thunk (FILE *file, tree thunk ATTRIBUTE_UNUSED,
>    int this_regno;
>
>    /* Make sure unwind info is emitted for the thunk if needed.  */
> -  final_start_function (emit_barrier (), file, 1);
> +  rtx_insn *first = emit_barrier ();
> +  final_start_function (&first, file, 1);
>
>    this_regno = (aggregate_value_p (TREE_TYPE (TREE_TYPE (function)), function)
>                 ? 1
> diff --git a/gcc/config/nios2/nios2.c b/gcc/config/nios2/nios2.c
> index 884b1dc..89600ee 100644
> --- a/gcc/config/nios2/nios2.c
> +++ b/gcc/config/nios2/nios2.c
> @@ -4060,7 +4060,7 @@ nios2_asm_output_mi_thunk (FILE *file, tree thunk_fndecl ATTRIBUTE_UNUSED,
>       assemble_start_function and assemble_end_function.  */
>    insn = get_insns ();
>    shorten_branches (insn);
> -  final_start_function (insn, file, 1);
> +  final_start_function (&insn, file, 1);
>    final (insn, file, 1);
>    final_end_function ();
>
> diff --git a/gcc/config/pa/pa.c b/gcc/config/pa/pa.c
> index 52f76cf..fd28213 100644
> --- a/gcc/config/pa/pa.c
> +++ b/gcc/config/pa/pa.c
> @@ -8379,7 +8379,8 @@ pa_asm_output_mi_thunk (FILE *file, tree thunk_fndecl, HOST_WIDE_INT delta,
>    xoperands[1] = XEXP (DECL_RTL (thunk_fndecl), 0);
>    xoperands[2] = GEN_INT (delta);
>
> -  final_start_function (emit_barrier (), file, 1);
> +  rtx_insn *first = emit_barrier ();
> +  final_start_function (&first, file, 1);
>
>    /* Output the thunk.  We know that the function is in the same
>       translation unit (i.e., the same space) as the thunk, and that
> diff --git a/gcc/config/rs6000/rs6000.c b/gcc/config/rs6000/rs6000.c
> index f9aa13b..298f07a 100644
> --- a/gcc/config/rs6000/rs6000.c
> +++ b/gcc/config/rs6000/rs6000.c
> @@ -29292,7 +29292,7 @@ rs6000_output_mi_thunk (FILE *file, tree thunk_fndecl ATTRIBUTE_UNUSED,
>       assemble_start_function and assemble_end_function.  */
>    insn = get_insns ();
>    shorten_branches (insn);
> -  final_start_function (insn, file, 1);
> +  final_start_function (&insn, file, 1);
>    final (insn, file, 1);
>    final_end_function ();
>
> @@ -37758,7 +37758,8 @@ rs6000_code_end (void)
>    init_function_start (decl);
>    first_function_block_is_cold = false;
>    /* Make sure unwind info is emitted for the thunk if needed.  */
> -  final_start_function (emit_barrier (), asm_out_file, 1);
> +  rtx_insn *first = emit_barrier ();
> +  final_start_function (&first, asm_out_file, 1);
>
>    fputs ("\tblr\n", asm_out_file);
>
> diff --git a/gcc/config/s390/s390.c b/gcc/config/s390/s390.c
> index deced95..ce98673 100644
> --- a/gcc/config/s390/s390.c
> +++ b/gcc/config/s390/s390.c
> @@ -12872,7 +12872,8 @@ s390_output_mi_thunk (FILE *file, tree thunk ATTRIBUTE_UNUSED,
>    int nonlocal = 0;
>
>    /* Make sure unwind info is emitted for the thunk if needed.  */
> -  final_start_function (emit_barrier (), file, 1);
> +  rtx_insn *first = emit_barrier ();
> +  final_start_function (&first, file, 1);
>
>    /* Operand 0 is the target function.  */
>    op[0] = XEXP (DECL_RTL (function), 0);
> diff --git a/gcc/config/sh/sh.c b/gcc/config/sh/sh.c
> index c31776f..875d931 100644
> --- a/gcc/config/sh/sh.c
> +++ b/gcc/config/sh/sh.c
> @@ -10891,7 +10891,7 @@ sh_output_mi_thunk (FILE *file, tree thunk_fndecl ATTRIBUTE_UNUSED,
>
>    sh_reorg ();
>    shorten_branches (insns);
> -  final_start_function (insns, file, 1);
> +  final_start_function (&insns, file, 1);
>    final (insns, file, 1);
>    final_end_function ();
>
> diff --git a/gcc/config/sparc/sparc.c b/gcc/config/sparc/sparc.c
> index d494ecf2..5d92080 100644
> --- a/gcc/config/sparc/sparc.c
> +++ b/gcc/config/sparc/sparc.c
> @@ -12074,7 +12074,7 @@ sparc_output_mi_thunk (FILE *file, tree thunk_fndecl ATTRIBUTE_UNUSED,
>       assemble_start_function and assemble_end_function.  */
>    insn = get_insns ();
>    shorten_branches (insn);
> -  final_start_function (insn, file, 1);
> +  final_start_function (&insn, file, 1);
>    final (insn, file, 1);
>    final_end_function ();
>
> diff --git a/gcc/config/spu/spu.c b/gcc/config/spu/spu.c
> index b6d03d7..e005077 100644
> --- a/gcc/config/spu/spu.c
> +++ b/gcc/config/spu/spu.c
> @@ -7020,7 +7020,8 @@ spu_output_mi_thunk (FILE *file, tree thunk ATTRIBUTE_UNUSED,
>    rtx op[8];
>
>    /* Make sure unwind info is emitted for the thunk if needed.  */
> -  final_start_function (emit_barrier (), file, 1);
> +  rtx_insn *insn = emit_barrier ();
> +  final_start_function (&insn, file, 1);
>
>    /* Operand 0 is the target function.  */
>    op[0] = XEXP (DECL_RTL (function), 0);
> diff --git a/gcc/config/tilegx/tilegx.c b/gcc/config/tilegx/tilegx.c
> index 81559ac..ac4a5ff 100644
> --- a/gcc/config/tilegx/tilegx.c
> +++ b/gcc/config/tilegx/tilegx.c
> @@ -4998,7 +4998,7 @@ tilegx_output_mi_thunk (FILE *file, tree thunk_fndecl ATTRIBUTE_UNUSED,
>     */
>    insn = get_insns ();
>    shorten_branches (insn);
> -  final_start_function (insn, file, 1);
> +  final_start_function (&insn, file, 1);
>    final (insn, file, 1);
>    final_end_function ();
>
> diff --git a/gcc/config/tilepro/tilepro.c b/gcc/config/tilepro/tilepro.c
> index f03f067..34b68b8 100644
> --- a/gcc/config/tilepro/tilepro.c
> +++ b/gcc/config/tilepro/tilepro.c
> @@ -4421,7 +4421,7 @@ tilepro_asm_output_mi_thunk (FILE *file, tree thunk_fndecl ATTRIBUTE_UNUSED,
>     */
>    insn = get_insns ();
>    shorten_branches (insn);
> -  final_start_function (insn, file, 1);
> +  final_start_function (&insn, file, 1);
>    final (insn, file, 1);
>    final_end_function ();
>
> diff --git a/gcc/configure b/gcc/configure
> index 9cee670..da0f277 100755
> --- a/gcc/configure
> +++ b/gcc/configure
> @@ -27756,6 +27756,52 @@ $as_echo "$gcc_cv_as_dwarf2_file_buggy" >&6; }
>
>  $as_echo "#define HAVE_AS_DWARF2_DEBUG_LINE 1" >>confdefs.h
>
> +
> +    if test $gcc_cv_as_leb128 = yes; then
> +       conftest_s="\
> +       .file 1 \"conftest.s\"
> +       .loc 1 3 0 view .LVU1
> +       $insn
> +       .data
> +       .uleb128 .LVU1
> +       .uleb128 .LVU1
> +"
> +       { $as_echo "$as_me:${as_lineno-$LINENO}: checking assembler for dwarf2 debug_view support" >&5
> +$as_echo_n "checking assembler for dwarf2 debug_view support... " >&6; }
> +if test "${gcc_cv_as_dwarf2_debug_view+set}" = set; then :
> +  $as_echo_n "(cached) " >&6
> +else
> +  gcc_cv_as_dwarf2_debug_view=no
> +    if test $in_tree_gas = yes; then
> +    if test $in_tree_gas_is_elf = yes \
> +  && test $gcc_cv_gas_vers -ge `expr \( \( 2 \* 1000 \) + 27 \) \* 1000 + 0`
> +  then gcc_cv_as_dwarf2_debug_view=yes
> +fi
> +  elif test x$gcc_cv_as != x; then
> +    $as_echo "$conftest_s" > conftest.s
> +    if { ac_try='$gcc_cv_as $gcc_cv_as_flags  -o conftest.o conftest.s >&5'
> +  { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_try\""; } >&5
> +  (eval $ac_try) 2>&5
> +  ac_status=$?
> +  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
> +  test $ac_status = 0; }; }
> +    then
> +       gcc_cv_as_dwarf2_debug_view=yes
> +    else
> +      echo "configure: failed program was" >&5
> +      cat conftest.s >&5
> +    fi
> +    rm -f conftest.o conftest.s
> +  fi
> +fi
> +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $gcc_cv_as_dwarf2_debug_view" >&5
> +$as_echo "$gcc_cv_as_dwarf2_debug_view" >&6; }
> +if test $gcc_cv_as_dwarf2_debug_view = yes; then
> +
> +$as_echo "#define HAVE_AS_DWARF2_DEBUG_VIEW 1" >>confdefs.h
> +
> +fi
> +    fi
>   fi
>
>   { $as_echo "$as_me:${as_lineno-$LINENO}: checking assembler for --gdwarf2 option" >&5
> diff --git a/gcc/configure.ac b/gcc/configure.ac
> index 0c0e359..d00ef86 100644
> --- a/gcc/configure.ac
> +++ b/gcc/configure.ac
> @@ -4847,9 +4847,25 @@ if test x"$insn" != x; then
>
>   if test $gcc_cv_as_dwarf2_debug_line = yes \
>   && test $gcc_cv_as_dwarf2_file_buggy = no; then
> -       AC_DEFINE(HAVE_AS_DWARF2_DEBUG_LINE, 1,
> +    AC_DEFINE(HAVE_AS_DWARF2_DEBUG_LINE, 1,
>    [Define if your assembler supports dwarf2 .file/.loc directives,
>     and preserves file table indices exactly as given.])
> +
> +    if test $gcc_cv_as_leb128 = yes; then
> +       conftest_s="\
> +       .file 1 \"conftest.s\"
> +       .loc 1 3 0 view .LVU1
> +       $insn
> +       .data
> +       .uleb128 .LVU1
> +       .uleb128 .LVU1
> +"
> +       gcc_GAS_CHECK_FEATURE([dwarf2 debug_view support],
> +         gcc_cv_as_dwarf2_debug_view,
> +         [elf,2,27,0],,[$conftest_s],,
> +         [AC_DEFINE(HAVE_AS_DWARF2_DEBUG_VIEW, 1,
> +  [Define if your assembler supports views in dwarf2 .loc directives.])])
> +    fi
>   fi
>
>   gcc_GAS_CHECK_FEATURE([--gdwarf2 option],
> diff --git a/gcc/cp/constexpr.c b/gcc/cp/constexpr.c
> index 29ba2c3..c8f1255 100644
> --- a/gcc/cp/constexpr.c
> +++ b/gcc/cp/constexpr.c
> @@ -306,6 +306,9 @@ build_data_member_initialization (tree t, vec<constructor_elt, va_gc> **vec)
>        tree_stmt_iterator i;
>        for (i = tsi_start (t); !tsi_end_p (i); tsi_next (&i))
>         {
> +         if (TREE_CODE (tsi_stmt (i)) == DEBUG_BEGIN_STMT)
> +           /* ??? Can we retain this information somehow?  */
> +           continue;
>           if (! build_data_member_initialization (tsi_stmt (i), vec))
>             return false;
>         }
> @@ -448,6 +451,7 @@ check_constexpr_ctor_body_1 (tree last, tree list)
>
>      case USING_STMT:
>      case STATIC_ASSERT:
> +    case DEBUG_BEGIN_STMT:
>        return true;
>
>      default:
> @@ -586,6 +590,9 @@ build_constexpr_constructor_member_initializers (tree type, tree body)
>        tree_stmt_iterator i;
>        for (i = tsi_start (body); !tsi_end_p (i); tsi_next (&i))
>         {
> +         if (TREE_CODE (tsi_stmt (i)) == DEBUG_BEGIN_STMT)
> +           /* ??? Can we retain this information somehow?  */
> +           continue;
>           ok = build_data_member_initialization (tsi_stmt (i), &vec);
>           if (!ok)
>             break;
> @@ -673,6 +680,7 @@ constexpr_fn_retval (tree body)
>        return constexpr_fn_retval (BIND_EXPR_BODY (body));
>
>      case USING_STMT:
> +    case DEBUG_BEGIN_STMT:
>        return NULL_TREE;
>
>      default:
> @@ -3765,6 +3773,8 @@ cxx_eval_statement_list (const constexpr_ctx *ctx, tree t,
>    for (i = tsi_start (t); !tsi_end_p (i); tsi_next (&i))
>      {
>        tree stmt = tsi_stmt (i);
> +      if (TREE_CODE (stmt) == DEBUG_BEGIN_STMT)
> +       continue;
>        r = cxx_eval_constant_expression (ctx, stmt, false,
>                                         non_constant_p, overflow_p,
>                                         jump_target);
> @@ -5096,6 +5106,7 @@ potential_constant_expression_1 (tree t, bool want_rval, bool strict,
>      case CONTINUE_STMT:
>      case REQUIRES_EXPR:
>      case STATIC_ASSERT:
> +    case DEBUG_BEGIN_STMT:
>        return true;
>
>      case AGGR_INIT_EXPR:
> diff --git a/gcc/cp/cp-array-notation.c b/gcc/cp/cp-array-notation.c
> index 31be7d6..17f0b35c 100644
> --- a/gcc/cp/cp-array-notation.c
> +++ b/gcc/cp/cp-array-notation.c
> @@ -780,6 +780,31 @@ error:
>    return error_mark_node;
>  }
>
> +/* Return a location associated with stmt.  If it is an expresion,
> +   that's the expression's location.  If it is a STATEMENT_LIST,
> +   instead of no location, use expr_first to skip any debug stmts and
> +   take the location of the first nondebug stmt found.  */
> +
> +static location_t
> +stmt_location (tree stmt)
> +{
> +  location_t loc = UNKNOWN_LOCATION;
> +
> +  if (!stmt)
> +    return loc;
> +
> +  loc = EXPR_LOCATION (stmt);
> +
> +  if (loc != UNKNOWN_LOCATION || TREE_CODE (stmt) != STATEMENT_LIST)
> +    return loc;
> +
> +  stmt = expr_first (stmt);
> +  if (stmt)
> +    loc = EXPR_LOCATION (stmt);
> +
> +  return loc;
> +}
> +
>  /* Helper function for expand_conditonal_array_notations.  Encloses the
>     conditional statement passed in ORIG_STMT with a loop around it and
>     replaces the condition in STMT with a ARRAY_REF tree-node to the array.
> @@ -835,10 +860,12 @@ cp_expand_cond_array_notations (tree orig_stmt)
>        tree cond = IF_COND (orig_stmt);
>        if (!find_rank (EXPR_LOCATION (cond), cond, cond, true, &cond_rank)
>           || (yes_expr
> -             && !find_rank (EXPR_LOCATION (yes_expr), yes_expr, yes_expr, true,
> +             && !find_rank (stmt_location (yes_expr),
> +                            yes_expr, yes_expr, true,
>                              &yes_rank))
>           || (no_expr
> -             && !find_rank (EXPR_LOCATION (no_expr), no_expr, no_expr, true,
> +             && !find_rank (stmt_location (no_expr),
> +                            no_expr, no_expr, true,
>                              &no_rank)))
>         return error_mark_node;
>
> @@ -847,13 +874,15 @@ cp_expand_cond_array_notations (tree orig_stmt)
>         return orig_stmt;
>        else if (cond_rank != yes_rank && yes_rank != 0)
>         {
> -         error_at (EXPR_LOCATION (yes_expr), "rank mismatch with controlling"
> +         error_at (stmt_location (yes_expr),
> +                   "rank mismatch with controlling"
>                     " expression of parent if-statement");
>           return error_mark_node;
>         }
>        else if (cond_rank != no_rank && no_rank != 0)
>         {
> -         error_at (EXPR_LOCATION (no_expr), "rank mismatch with controlling "
> +         error_at (stmt_location (no_expr),
> +                   "rank mismatch with controlling "
>                     "expression of parent if-statement");
>           return error_mark_node;
>         }
> diff --git a/gcc/cp/cp-objcp-common.h b/gcc/cp/cp-objcp-common.h
> index 10fcdf3..e98c5c5 100644
> --- a/gcc/cp/cp-objcp-common.h
> +++ b/gcc/cp/cp-objcp-common.h
> @@ -103,6 +103,8 @@ extern void cp_register_dumps (gcc::dump_manager *);
>  #define LANG_HOOKS_MISSING_NORETURN_OK_P cp_missing_noreturn_ok_p
>  #undef LANG_HOOKS_BLOCK_MAY_FALLTHRU
>  #define LANG_HOOKS_BLOCK_MAY_FALLTHRU cxx_block_may_fallthru
> +#undef LANG_HOOKS_EMITS_BEGIN_STMT
> +#define LANG_HOOKS_EMITS_BEGIN_STMT true
>
>  /* Attribute hooks.  */
>  #undef LANG_HOOKS_COMMON_ATTRIBUTE_TABLE
> diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c
> index b849824..a25582e 100644
> --- a/gcc/cp/parser.c
> +++ b/gcc/cp/parser.c
> @@ -10712,6 +10712,19 @@ cp_parser_lambda_body (cp_parser* parser, tree lambda_expr)
>
>  /* Statements [gram.stmt.stmt]  */
>
> +/* Build and add a DEBUG_BEGIN_STMT statement with location LOC.  */
> +
> +static void
> +add_debug_begin_stmt (location_t loc)
> +{
> +  if (!debug_nonbind_markers_p)
> +    return;
> +
> +  tree stmt = build0 (DEBUG_BEGIN_STMT, void_type_node);
> +  SET_EXPR_LOCATION (stmt, loc);
> +  add_stmt (stmt);
> +}
> +
>  /* Parse a statement.
>
>     statement:
> @@ -10787,6 +10800,7 @@ cp_parser_statement (cp_parser* parser, tree in_statement_expr,
>    token = cp_lexer_peek_token (parser->lexer);
>    /* Remember the location of the first token in the statement.  */
>    statement_location = token->location;
> +  add_debug_begin_stmt (statement_location);
>    /* If this is a keyword, then that will often determine what kind of
>       statement we have.  */
>    if (token->type == CPP_KEYWORD)
> diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
> index bf1f75d..ced7ec6 100644
> --- a/gcc/cp/pt.c
> +++ b/gcc/cp/pt.c
> @@ -15120,6 +15120,12 @@ tsubst_copy (tree t, tree args, tsubst_flags_t complain, tree in_decl)
>      case PREDICT_EXPR:
>        return t;
>
> +    case DEBUG_BEGIN_STMT:
> +      /* ??? There's no point in copying it for now, but maybe some
> +        day it will contain more information, such as a pointer back
> +        to the containing function, inlined copy or so.  */
> +      return t;
> +
>      default:
>        /* We shouldn't get here, but keep going if !flag_checking.  */
>        if (flag_checking)
> diff --git a/gcc/cse.c b/gcc/cse.c
> index 6a968d1..c98e3f2 100644
> --- a/gcc/cse.c
> +++ b/gcc/cse.c
> @@ -6953,11 +6953,18 @@ insn_live_p (rtx_insn *insn, int *counts)
>      {
>        rtx_insn *next;
>
> +      if (MARKER_DEBUG_INSN_P (insn))
> +       return true;
> +
>        for (next = NEXT_INSN (insn); next; next = NEXT_INSN (next))
>         if (NOTE_P (next))
>           continue;
>         else if (!DEBUG_INSN_P (next))
>           return true;
> +       /* If we find an inspection point, such as a debug begin stmt,
> +          we want to keep the earlier debug insn.  */
> +       else if (MARKER_DEBUG_INSN_P (next))
> +         return true;
>         else if (INSN_VAR_LOCATION_DECL (insn) == INSN_VAR_LOCATION_DECL (next))
>           return false;
>
> @@ -7044,7 +7051,7 @@ delete_trivially_dead_insns (rtx_insn *insns, int nreg)
>      {
>        counts = XCNEWVEC (int, nreg * 3);
>        for (insn = insns; insn; insn = NEXT_INSN (insn))
> -       if (DEBUG_INSN_P (insn))
> +       if (BIND_DEBUG_INSN_P (insn))
>           count_reg_usage (INSN_VAR_LOCATION_LOC (insn), counts + nreg,
>                            NULL_RTX, 1);
>         else if (INSN_P (insn))
> @@ -7150,7 +7157,7 @@ delete_trivially_dead_insns (rtx_insn *insns, int nreg)
>    if (MAY_HAVE_DEBUG_INSNS)
>      {
>        for (insn = get_last_insn (); insn; insn = PREV_INSN (insn))
> -       if (DEBUG_INSN_P (insn))
> +       if (BIND_DEBUG_INSN_P (insn))
>           {
>             /* If this debug insn references a dead register that wasn't replaced
>                with an DEBUG_EXPR, reset the DEBUG_INSN.  */
> diff --git a/gcc/dbxout.c b/gcc/dbxout.c
> index 3d9268c3..f1c80c5 100644
> --- a/gcc/dbxout.c
> +++ b/gcc/dbxout.c
> @@ -377,6 +377,7 @@ const struct gcc_debug_hooks dbx_debug_hooks =
>    debug_nothing_rtx_code_label,                 /* label */
>    dbxout_handle_pch,                    /* handle_pch */
>    debug_nothing_rtx_insn,               /* var_location */
> +  debug_nothing_tree,                   /* inline_entry */
>    debug_nothing_tree,                   /* size_function */
>    debug_nothing_void,                    /* switch_text_section */
>    debug_nothing_tree_tree,              /* set_name */
> @@ -417,6 +418,7 @@ const struct gcc_debug_hooks xcoff_debug_hooks =
>    debug_nothing_rtx_code_label,                 /* label */
>    dbxout_handle_pch,                    /* handle_pch */
>    debug_nothing_rtx_insn,               /* var_location */
> +  debug_nothing_tree,                   /* inline_entry */
>    debug_nothing_tree,                   /* size_function */
>    debug_nothing_void,                    /* switch_text_section */
>    debug_nothing_tree_tree,              /* set_name */
> diff --git a/gcc/debug.c b/gcc/debug.c
> index d68c30ff..5deec2c 100644
> --- a/gcc/debug.c
> +++ b/gcc/debug.c
> @@ -53,6 +53,7 @@ const struct gcc_debug_hooks do_nothing_debug_hooks =
>    debug_nothing_rtx_code_label,                 /* label */
>    debug_nothing_int,                    /* handle_pch */
>    debug_nothing_rtx_insn,               /* var_location */
> +  debug_nothing_tree,                   /* inline_entry */
>    debug_nothing_tree,                   /* size_function */
>    debug_nothing_void,                    /* switch_text_section */
>    debug_nothing_tree_tree,              /* set_name */
> diff --git a/gcc/debug.h b/gcc/debug.h
> index bfb7221..78bb401 100644
> --- a/gcc/debug.h
> +++ b/gcc/debug.h
> @@ -168,6 +168,9 @@ struct gcc_debug_hooks
>    /* Called from final_scan_insn for any NOTE_INSN_VAR_LOCATION note.  */
>    void (* var_location) (rtx_insn *);
>
> +  /* Called from final_scan_insn for any NOTE_INSN_INLINE_ENTRY note.  */
> +  void (* inline_entry) (tree block);
> +
>    /* Called from finalize_size_functions for size functions so that their body
>       can be encoded in the debug info to describe the layout of variable-length
>       structures.  */
> diff --git a/gcc/df-scan.c b/gcc/df-scan.c
> index dde6d15..a7b04e7 100644
> --- a/gcc/df-scan.c
> +++ b/gcc/df-scan.c
> @@ -945,7 +945,7 @@ df_insn_delete (rtx_insn *insn)
>       In any case, we expect BB to be non-NULL at least up to register
>       allocation, so disallow a non-NULL BB up to there.  Not perfect
>       but better than nothing...  */
> -  gcc_checking_assert (bb != NULL || reload_completed);
> +  gcc_checking_assert (bb != NULL || DEBUG_INSN_P (insn) || reload_completed);
>
>    df_grow_bb_info (df_scan);
>    df_grow_reg_info ();
> diff --git a/gcc/doc/generic.texi b/gcc/doc/generic.texi
> index 874d464..c938be8 100644
> --- a/gcc/doc/generic.texi
> +++ b/gcc/doc/generic.texi
> @@ -1930,6 +1930,11 @@ case 2 ... 5:
>  The first value will be @code{CASE_LOW}, while the second will be
>  @code{CASE_HIGH}.
>
> +@item DEBUG_BEGIN_STMT
> +
> +Marks the beginning of a source statement, for purposes of debug
> +information generation.
> +
>  @end table
>
>
> diff --git a/gcc/doc/gimple.texi b/gcc/doc/gimple.texi
> index 635abd39..8d93e99 100644
> --- a/gcc/doc/gimple.texi
> +++ b/gcc/doc/gimple.texi
> @@ -831,6 +831,11 @@ expression to a variable.
>  Return true if g is any of the OpenMP codes.
>  @end deftypefn
>
> +@deftypefn {GIMPLE function} gimple_debug_begin_stmt_p (gimple g)
> +Return true if g is a @code{GIMPLE_DEBUG} that marks the beginning of
> +a source statement.
> +@end deftypefn
> +
>  @node Manipulating GIMPLE statements
>  @section Manipulating GIMPLE statements
>  @cindex Manipulating GIMPLE statements
> @@ -1528,10 +1533,11 @@ Set the conditional @code{COND_STMT} to be of the form 'if (1 == 1)'.
>  @subsection @code{GIMPLE_DEBUG}
>  @cindex @code{GIMPLE_DEBUG}
>  @cindex @code{GIMPLE_DEBUG_BIND}
> +@cindex @code{GIMPLE_DEBUG_BEGIN_STMT}
>
>  @deftypefn {GIMPLE function} gdebug *gimple_build_debug_bind (tree var, @
>  tree value, gimple stmt)
> -Build a @code{GIMPLE_DEBUG} statement with @code{GIMPLE_DEBUG_BIND} of
> +Build a @code{GIMPLE_DEBUG} statement with @code{GIMPLE_DEBUG_BIND}
>  @code{subcode}.  The effect of this statement is to tell debug
>  information generation machinery that the value of user variable
>  @code{var} is given by @code{value} at that point, and to remain with
> @@ -1602,6 +1608,14 @@ Return @code{TRUE} if @code{stmt} binds a user variable to a value,
>  and @code{FALSE} if it unbinds the variable.
>  @end deftypefn
>
> +@deftypefn {GIMPLE function} gimple gimple_build_debug_begin_stmt (tree block, location_t location)
> +Build a @code{GIMPLE_DEBUG} statement with
> +@code{GIMPLE_DEBUG_BEGIN_STMT} @code{subcode}.  The effect of this
> +statement is to tell debug information generation machinery that the
> +user statement at the given @code{location} and @code{block} starts at
> +the point at which the statement is inserted.
> +@end deftypefn
> +
>  @node @code{GIMPLE_EH_FILTER}
>  @subsection @code{GIMPLE_EH_FILTER}
>  @cindex @code{GIMPLE_EH_FILTER}
> diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi
> index ec29f1d..04b8835 100644
> --- a/gcc/doc/invoke.texi
> +++ b/gcc/doc/invoke.texi
> @@ -344,10 +344,12 @@ Objective-C and Objective-C++ Dialects}.
>  -ggdb  -grecord-gcc-switches  -gno-record-gcc-switches @gol
>  -gstabs  -gstabs+  -gstrict-dwarf  -gno-strict-dwarf @gol
>  -gcolumn-info  -gno-column-info @gol
> --gvms  -gxcoff  -gxcoff+  -gz@r{[}=@var{type}@r{]} @gol
> --fdebug-prefix-map=@var{old}=@var{new}  -fdebug-types-section @gol
> --feliminate-dwarf2-dups  -fno-eliminate-unused-debug-types @gol
> --femit-struct-debug-baseonly  -femit-struct-debug-reduced @gol
> +-gstatement-frontiers  -gno-statement-frontiers @gol
> +-gvariable-location-views  -gno-variable-location-views @gol
> +-gvms  -gxcoff  -gxcoff+ -gz@r{[}=@var{type}@r{]} @gol
> +-fdebug-prefix-map=@var{old}=@var{new} -fdebug-types-section @gol
> +-feliminate-dwarf2-dups -fno-eliminate-unused-debug-types @gol
> +-femit-struct-debug-baseonly -femit-struct-debug-reduced @gol
>  -femit-struct-debug-detailed@r{[}=@var{spec-list}@r{]} @gol
>  -feliminate-unused-debug-symbols  -femit-class-debug-always @gol
>  -fno-merge-debug-strings  -fno-dwarf2-cfi-asm @gol
> @@ -6988,6 +6990,35 @@ Emit location column information into DWARF debugging information, rather
>  than just file and line.
>  This option is disabled by default.
>
> +@item -gstatement-frontiers
> +@item -gno-statement-frontiers
> +@opindex gstatement-frontiers
> +@opindex gno-statement-frontiers
> +This option causes GCC to create markers in the internal representation
> +at the beginning of statements, and to keep them roughly in place
> +throughout compilation, using them to guide the output of @code{is_stmt}
> +markers in the line number table.  This is enabled by default when
> +compiling with optimization (@option{-Os}, @option{-O}, @option{-O2},
> +@dots{}), and outputting DWARF 2 debug information at the normal level.
> +
> +@item -gvariable-location-views
> +@item -gno-variable-location-views
> +@opindex gvariable-location-views
> +@opindex gno-variable-location-views
> +Augment variable location lists with progressive view numbers implied
> +from the line number table.  This enables debug information consumers to
> +inspect state at certain points of the program, even if no instructions
> +associated with the corresponding source locations are present at that
> +point.  If the assembler lacks support for view numbers in line number
> +tables, this will cause the compiler to emit the line number table,
> +which generally makes them somewhat less compact.  The augmented line
> +number tables and location lists are fully backward-compatible, so they
> +can be consumed by debug information consumers that are not aware of
> +these augmentations, but they won't derive any benefit from them either.
> +This is enabled by default when outputting DWARF 2 debug information at
> +the normal level, as long as @code{-fvar-tracking-assignments} is
> +enabled and @code{-gstrict-dwarf} is not.
> +
>  @item -gz@r{[}=@var{type}@r{]}
>  @opindex gz
>  Produce compressed debug sections in DWARF format, if that is supported.
> @@ -10419,6 +10450,13 @@ debug information may end up not being used; setting this higher may
>  enable the compiler to find more complex debug expressions, but compile
>  time and memory use may grow.  The default is 12.
>
> +@item max-debug-marker-count
> +Sets a threshold on the number of debug markers (e.g. begin stmt
> +markers) to avoid complexity explosion at inlining or expanding to RTL.
> +If a function has more such gimple stmts than the set limit, such stmts
> +will be dropped from the inlined copy of a function, and from its RTL
> +expansion.  The default is 100000.
> +
>  @item min-nondebug-insn-uid
>  Use uids starting at this parameter for nondebug insns.  The range below
>  the parameter is reserved exclusively for debug insns created by
> diff --git a/gcc/doc/rtl.texi b/gcc/doc/rtl.texi
> index 6e2799a..2189446 100644
> --- a/gcc/doc/rtl.texi
> +++ b/gcc/doc/rtl.texi
> @@ -3689,6 +3689,12 @@ can be computed by evaluating the RTL expression from that static
>  point in the program up to the next such note for the same user
>  variable.
>
> +@findex NOTE_INSN_BEGIN_STMT
> +@item NOTE_INSN_BEGIN_STMT
> +This note is used to generate @code{is_stmt} markers in line number
> +debuggign information.  It indicates the beginning of a user
> +statement.
> +
>  @end table
>
>  These codes are printed symbolically when they appear in debugging dumps.
> @@ -3704,17 +3710,22 @@ representation of @code{GIMPLE_DEBUG} statements
>  binds a user variable tree to an RTL representation of the
>  @code{value} in the corresponding statement.  A @code{DEBUG_EXPR} in
>  it stands for the value bound to the corresponding
> -@code{DEBUG_EXPR_DECL}.
> -
> -Throughout optimization passes, binding information is kept in
> -pseudo-instruction form, so that, unlike notes, it gets the same
> -treatment and adjustments that regular instructions would.  It is the
> -variable tracking pass that turns these pseudo-instructions into var
> -location notes, analyzing control flow, value equivalences and changes
> -to registers and memory referenced in value expressions, propagating
> -the values of debug temporaries and determining expressions that can
> -be used to compute the value of each user variable at as many points
> -(ranges, actually) in the program as possible.
> +@code{DEBUG_EXPR_DECL}.  A @code{GIMPLE_DEBUG_BEGIN_STMT} is expanded
> +to RTL as a @code{DEBUG_INSN} with a @code{NULL_TREE} in
> +@code{INSN_VAR_LOCATION_DECL}.
> +
> +Throughout optimization passes, @code{DEBUG_INSN}s are not reordered
> +with respect to each other, particularly during scheduling.  Binding
> +information is kept in pseudo-instruction form, so that, unlike notes,
> +it gets the same treatment and adjustments that regular instructions
> +would.  It is the variable tracking pass that turns these
> +pseudo-instructions into @code{NOTE_INSN_VAR_LOCATION} and
> +@code{NOTE_INSN_BEGIN_STMT} notes, analyzing control flow, value
> +equivalences and changes to registers and memory referenced in value
> +expressions, propagating the values of debug temporaries and
> +determining expressions that can be used to compute the value of each
> +user variable at as many points (ranges, actually) in the program as
> +possible.
>
>  Unlike @code{NOTE_INSN_VAR_LOCATION}, the value expression in an
>  @code{INSN_VAR_LOCATION} denotes a value at that specific point in the
> diff --git a/gcc/dwarf2asm.c b/gcc/dwarf2asm.c
> index 8e3e86f..f19e6d6 100644
> --- a/gcc/dwarf2asm.c
> +++ b/gcc/dwarf2asm.c
> @@ -768,6 +768,31 @@ dw2_asm_output_data_sleb128 (HOST_WIDE_INT value,
>  }
>
>  void
> +dw2_asm_output_symname_uleb128 (const char *lab1 ATTRIBUTE_UNUSED,
> +                               const char *comment, ...)
> +{
> +  va_list ap;
> +
> +  va_start (ap, comment);
> +
> +#ifdef HAVE_AS_LEB128
> +  fputs ("\t.uleb128 ", asm_out_file);
> +  assemble_name (asm_out_file, lab1);
> +#else
> +  gcc_unreachable ();
> +#endif
> +
> +  if (flag_debug_asm && comment)
> +    {
> +      fprintf (asm_out_file, "\t%s ", ASM_COMMENT_START);
> +      vfprintf (asm_out_file, comment, ap);
> +    }
> +  fputc ('\n', asm_out_file);
> +
> +  va_end (ap);
> +}
> +
> +void
>  dw2_asm_output_delta_uleb128 (const char *lab1 ATTRIBUTE_UNUSED,
>                               const char *lab2 ATTRIBUTE_UNUSED,
>                               const char *comment, ...)
> diff --git a/gcc/dwarf2asm.h b/gcc/dwarf2asm.h
> index 7fc87a0..d8370df 100644
> --- a/gcc/dwarf2asm.h
> +++ b/gcc/dwarf2asm.h
> @@ -70,6 +70,10 @@ extern void dw2_asm_output_data_sleb128      (HOST_WIDE_INT,
>                                          const char *, ...)
>       ATTRIBUTE_NULL_PRINTF_2;
>
> +extern void dw2_asm_output_symname_uleb128 (const char *,
> +                                           const char *, ...)
> +     ATTRIBUTE_NULL_PRINTF_2;
> +
>  extern void dw2_asm_output_delta_uleb128 (const char *, const char *,
>                                           const char *, ...)
>       ATTRIBUTE_NULL_PRINTF_3;
> diff --git a/gcc/dwarf2out.c b/gcc/dwarf2out.c
> index 917ab9f..cb11c98 100644
> --- a/gcc/dwarf2out.c
> +++ b/gcc/dwarf2out.c
> @@ -83,6 +83,7 @@ along with GCC; see the file COPYING3.  If not see
>  #include "toplev.h"
>  #include "md5.h"
>  #include "tree-pretty-print.h"
> +#include "print-rtl.h"
>  #include "debug.h"
>  #include "common/common-target.h"
>  #include "langhooks.h"
> @@ -1274,6 +1275,8 @@ struct GTY((for_user)) addr_table_entry {
>    GTY ((desc ("%1.kind"))) addr;
>  };
>
> +typedef unsigned int var_loc_view;
> +
>  /* Location lists are ranges + location descriptions for that range,
>     so you can track variables that are in different places over
>     their entire life.  */
> @@ -1283,9 +1286,11 @@ typedef struct GTY(()) dw_loc_list_struct {
>    addr_table_entry *begin_entry;
>    const char *end;  /* Label for end of range */
>    char *ll_symbol; /* Label for beginning of location list.
> -                     Only on head of list */
> +                     Only on head of list.  */
> +  char *vl_symbol; /* Label for beginning of view list.  Ditto.  */
>    const char *section; /* Section this loclist is relative to */
>    dw_loc_descr_ref expr;
> +  var_loc_view vbegin, vend;
>    hashval_t hash;
>    /* True if all addresses in this and subsequent lists are known to be
>       resolved.  */
> @@ -1322,6 +1327,31 @@ dwarf_stack_op_name (unsigned int op)
>    return "OP_<unknown>";
>  }
>
> +/* Return TRUE iff we're to output location view lists as a separate
> +   attribute next to the location lists, as an extension compatible
> +   with DWARF 2 and above.  */
> +
> +static inline bool
> +dwarf2out_locviews_in_attribute ()
> +{
> +  return debug_variable_location_views
> +    && dwarf_version <= 5;
> +}
> +
> +/* Return TRUE iff we're to output location view lists as part of the
> +   location lists, as proposed for standardization after DWARF 5.  */
> +
> +static inline bool
> +dwarf2out_locviews_in_loclist ()
> +{
> +#ifndef DW_LLE_view_pair
> +  return false;
> +#else
> +  return debug_variable_location_views
> +    && dwarf_version >= 6;
> +#endif
> +}
> +
>  /* Return a pointer to a newly allocated location description.  Location
>     descriptions are simple expression terms that can be strung
>     together to form more complicated location (address) descriptions.  */
> @@ -1397,6 +1427,8 @@ dw_val_equal_p (dw_val_node *a, dw_val_node *b)
>        return a->v.val_loc == b->v.val_loc;
>      case dw_val_class_loc_list:
>        return a->v.val_loc_list == b->v.val_loc_list;
> +    case dw_val_class_view_list:
> +      return a->v.val_view_list == b->v.val_view_list;
>      case dw_val_class_die_ref:
>        return a->v.val_die_ref.die == b->v.val_die_ref.die;
>      case dw_val_class_fde_ref:
> @@ -2687,6 +2719,7 @@ static void dwarf2out_imported_module_or_decl_1 (tree, tree, tree,
>                                                  dw_die_ref);
>  static void dwarf2out_abstract_function (tree);
>  static void dwarf2out_var_location (rtx_insn *);
> +static void dwarf2out_inline_entry (tree);
>  static void dwarf2out_size_function (tree);
>  static void dwarf2out_begin_function (tree);
>  static void dwarf2out_end_function (unsigned int);
> @@ -2734,6 +2767,7 @@ const struct gcc_debug_hooks dwarf2_debug_hooks =
>    debug_nothing_rtx_code_label,        /* label */
>    debug_nothing_int,           /* handle_pch */
>    dwarf2out_var_location,
> +  dwarf2out_inline_entry,      /* inline_entry */
>    dwarf2out_size_function,     /* size_function */
>    dwarf2out_switch_text_section,
>    dwarf2out_set_name,
> @@ -2772,6 +2806,7 @@ const struct gcc_debug_hooks dwarf2_lineno_debug_hooks =
>    debug_nothing_rtx_code_label,                 /* label */
>    debug_nothing_int,                    /* handle_pch */
>    debug_nothing_rtx_insn,               /* var_location */
> +  debug_nothing_tree,                   /* inline_entry */
>    debug_nothing_tree,                   /* size_function */
>    debug_nothing_void,                    /* switch_text_section */
>    debug_nothing_tree_tree,              /* set_name */
> @@ -2834,7 +2869,15 @@ enum dw_line_info_opcode {
>    LI_set_epilogue_begin,
>
>    /* Emit a DW_LNE_set_discriminator.  */
> -  LI_set_discriminator
> +  LI_set_discriminator,
> +
> +  /* Output a Fixed Advance PC; the target PC is the label index; the
> +     base PC is the previous LI_adv_address or LI_set_address entry.
> +     We only use this when emitting debug views without assembler
> +     support, at explicit user request.  Ideally, we should only use
> +     it when the offset might be zero but we can't tell: it's the only
> +     way to maybe change the PC without resetting the view number.  */
> +  LI_adv_address
>  };
>
>  typedef struct GTY(()) dw_line_info_struct {
> @@ -2856,6 +2899,25 @@ struct GTY(()) dw_line_info_table {
>    bool is_stmt;
>    bool in_use;
>
> +  /* This denotes the NEXT view number.
> +
> +     If it is 0, it is known that the NEXT view will be the first view
> +     at the given PC.
> +
> +     If it is -1, we've advanced PC but we haven't emitted a line location yet,
> +     so we shouldn't use this view number.
> +
> +     The meaning of other nonzero values depends on whether we're
> +     computing views internally or leaving it for the assembler to do
> +     so.  If we're emitting them internally, view denotes the view
> +     number since the last known advance of PC.  If we're leaving it
> +     for the assembler, it denotes the LVU label number that we're
> +     going to ask the assembler to assign.  */
> +  var_loc_view view;
> +
> +#define RESET_NEXT_VIEW(x) ((x) = (var_loc_view)0)
> +#define RESETTING_VIEW_P(x) ((x) == (var_loc_view)0)
> +
>    vec<dw_line_info_entry, va_gc> *entries;
>  };
>
> @@ -3054,6 +3116,41 @@ skeleton_chain_node;
>  #endif
>  #endif
>
> +/* Use assembler views in line directives if available.  */
> +#ifndef DWARF2_ASM_VIEW_DEBUG_INFO
> +#ifdef HAVE_AS_DWARF2_DEBUG_VIEW
> +#define DWARF2_ASM_VIEW_DEBUG_INFO 1
> +#else
> +#define DWARF2_ASM_VIEW_DEBUG_INFO 0
> +#endif
> +#endif
> +
> +/* A bit is set in ZERO_VIEW_P if we are using the assembler-supported
> +   view computation, and it is refers to a view identifier for which
> +   will not emit a label because it is known to map to a view number
> +   zero.  We won't allocate the bitmap if we're not using assembler
> +   support for location views, but we have to make the variable
> +   visible for GGC and for code that will be optimized out for lack of
> +   support but that's still parsed and compiled.  We could abstract it
> +   out with macros, but it's not worth it.  */
> +static GTY(()) bitmap zero_view_p;
> +
> +/* Evaluate to TRUE iff N is known to identify the first location view
> +   at its PC.  When not using assembler location view computation,
> +   that must be view number zero.  Otherwise, ZERO_VIEW_P is allocated
> +   and views label numbers recorded in it are the ones known to be
> +   zero.  */
> +#define ZERO_VIEW_P(N) (zero_view_p                            \
> +                       ? bitmap_bit_p (zero_view_p, (N))       \
> +                       : (N) == 0)
> +
> +static bool
> +output_asm_line_debug_info (void)
> +{
> +  return DWARF2_ASM_VIEW_DEBUG_INFO
> +    || (DWARF2_ASM_LINE_DEBUG_INFO && !debug_variable_location_views);
> +}
> +
>  /* Minimum line offset in a special line info. opcode.
>     This value was chosen to give a reasonable range of values.  */
>  #define DWARF_LINE_BASE  -10
> @@ -3163,6 +3260,7 @@ struct GTY ((chain_next ("%h.next"))) var_loc_node {
>    rtx GTY (()) loc;
>    const char * GTY (()) label;
>    struct var_loc_node * GTY (()) next;
> +  var_loc_view view;
>  };
>
>  /* Variable location list.  */
> @@ -3371,6 +3469,8 @@ static inline dw_loc_descr_ref AT_loc (dw_attr_node *);
>  static void add_AT_loc_list (dw_die_ref, enum dwarf_attribute,
>                              dw_loc_list_ref);
>  static inline dw_loc_list_ref AT_loc_list (dw_attr_node *);
> +static void add_AT_view_list (dw_die_ref, enum dwarf_attribute);
> +static inline dw_loc_list_ref AT_loc_list (dw_attr_node *);
>  static addr_table_entry *add_addr_table_entry (void *, enum ate_kind);
>  static void remove_addr_table_entry (addr_table_entry *);
>  static void add_AT_addr (dw_die_ref, enum dwarf_attribute, rtx, bool);
> @@ -3407,7 +3507,7 @@ static void equate_type_number_to_die (tree, dw_die_ref);
>  static dw_die_ref lookup_decl_die (tree);
>  static var_loc_list *lookup_decl_loc (const_tree);
>  static void equate_decl_number_to_die (tree, dw_die_ref);
> -static struct var_loc_node *add_var_loc_to_decl (tree, rtx, const char *);
> +static struct var_loc_node *add_var_loc_to_decl (tree, rtx, const char *, var_loc_view);
>  static void print_spaces (FILE *);
>  static void print_die (dw_die_ref, FILE *);
>  static dw_die_ref push_new_compile_unit (dw_die_ref, dw_die_ref);
> @@ -3615,8 +3715,8 @@ static void gen_tagged_type_die (tree, dw_die_ref, enum debug_info_usage);
>  static void gen_type_die_with_usage (tree, dw_die_ref, enum debug_info_usage);
>  static void splice_child_die (dw_die_ref, dw_die_ref);
>  static int file_info_cmp (const void *, const void *);
> -static dw_loc_list_ref new_loc_list (dw_loc_descr_ref, const char *,
> -                                    const char *, const char *);
> +static dw_loc_list_ref new_loc_list (dw_loc_descr_ref, const char *, var_loc_view,
> +                                    const char *, var_loc_view, const char *);
>  static void output_loc_list (dw_loc_list_ref);
>  static char *gen_internal_sym (const char *);
>  static bool want_pubnames (void);
> @@ -3862,6 +3962,9 @@ static char ranges_base_label[2 * MAX_ARTIFICIAL_LABEL_BYTES];
>  #ifndef BLOCK_BEGIN_LABEL
>  #define BLOCK_BEGIN_LABEL      "LBB"
>  #endif
> +#ifndef BLOCK_INLINE_ENTRY_LABEL
> +#define BLOCK_INLINE_ENTRY_LABEL "LBI"
> +#endif
>  #ifndef BLOCK_END_LABEL
>  #define BLOCK_END_LABEL                "LBE"
>  #endif
> @@ -4538,11 +4641,55 @@ AT_loc_list (dw_attr_node *a)
>    return a->dw_attr_val.v.val_loc_list;
>  }
>
> +static inline void
> +add_AT_view_list (dw_die_ref die, enum dwarf_attribute attr_kind)
> +{
> +  dw_attr_node attr;
> +
> +  if (XCOFF_DEBUGGING_INFO && !HAVE_XCOFF_DWARF_EXTRAS)
> +    return;
> +
> +  attr.dw_attr = attr_kind;
> +  attr.dw_attr_val.val_class = dw_val_class_view_list;
> +  attr.dw_attr_val.val_entry = NULL;
> +  attr.dw_attr_val.v.val_view_list = die;
> +  add_dwarf_attr (die, &attr);
> +  gcc_checking_assert (get_AT (die, DW_AT_location));
> +  gcc_assert (have_location_lists);
> +}
> +
>  static inline dw_loc_list_ref *
>  AT_loc_list_ptr (dw_attr_node *a)
>  {
> -  gcc_assert (a && AT_class (a) == dw_val_class_loc_list);
> -  return &a->dw_attr_val.v.val_loc_list;
> +  gcc_assert (a);
> +  switch (AT_class (a))
> +    {
> +    case dw_val_class_loc_list:
> +      return &a->dw_attr_val.v.val_loc_list;
> +    case dw_val_class_view_list:
> +      {
> +       dw_attr_node *l;
> +       l = get_AT (a->dw_attr_val.v.val_view_list, DW_AT_location);
> +       if (!l)
> +         return NULL;
> +       gcc_checking_assert (l + 1 == a);
> +       return AT_loc_list_ptr (l);
> +      }
> +    default:
> +      gcc_unreachable ();
> +    }
> +}
> +
> +static inline dw_val_node *
> +view_list_to_loc_list_val_node (dw_val_node *val)
> +{
> +  gcc_assert (val->val_class == dw_val_class_view_list);
> +  dw_attr_node *loc = get_AT (val->v.val_view_list, DW_AT_location);
> +  if (!loc)
> +    return NULL;
> +  gcc_checking_assert (&(loc + 1)->dw_attr_val == val);
> +  gcc_assert (AT_class (loc) == dw_val_class_loc_list);
> +  return &loc->dw_attr_val;
>  }
>
>  struct addr_hasher : ggc_ptr_hash<addr_table_entry>
> @@ -5604,7 +5751,7 @@ adjust_piece_list (rtx *dest, rtx *src, rtx *inner,
>  /* Add a variable location node to the linked list for DECL.  */
>
>  static struct var_loc_node *
> -add_var_loc_to_decl (tree decl, rtx loc_note, const char *label)
> +add_var_loc_to_decl (tree decl, rtx loc_note, const char *label, var_loc_view view)
>  {
>    unsigned int decl_id;
>    var_loc_list *temp;
> @@ -5695,7 +5842,7 @@ add_var_loc_to_decl (tree decl, rtx loc_note, const char *label)
>        /* TEMP->LAST here is either pointer to the last but one or
>          last element in the chained list, LAST is pointer to the
>          last element.  */
> -      if (label && strcmp (last->label, label) == 0)
> +      if (label && strcmp (last->label, label) == 0 && last->view == view)
>         {
>           /* For SRA optimized variables if there weren't any real
>              insns since last note, just modify the last node.  */
> @@ -5711,7 +5858,7 @@ add_var_loc_to_decl (tree decl, rtx loc_note, const char *label)
>               temp->last->next = NULL;
>               unused = last;
>               last = temp->last;
> -             gcc_assert (strcmp (last->label, label) != 0);
> +             gcc_assert (strcmp (last->label, label) != 0 || last->view != view);
>             }
>           else
>             {
> @@ -5846,6 +5993,12 @@ print_dw_val (dw_val_node *val, bool recurse, FILE *outfile)
>        fprintf (outfile, "location list -> label:%s",
>                val->v.val_loc_list->ll_symbol);
>        break;
> +    case dw_val_class_view_list:
> +      val = view_list_to_loc_list_val_node (val);
> +      fprintf (outfile, "location list with views -> labels:%s and %s",
> +              val->v.val_loc_list->ll_symbol,
> +              val->v.val_loc_list->vl_symbol);
> +      break;
>      case dw_val_class_range_list:
>        fprintf (outfile, "range list");
>        break;
> @@ -8945,6 +9098,7 @@ size_of_die (dw_die_ref die)
>           }
>           break;
>         case dw_val_class_loc_list:
> +       case dw_val_class_view_list:
>           if (dwarf_split_debug_info && dwarf_version >= 5)
>             {
>               gcc_assert (AT_loc_list (a)->num_assigned);
> @@ -9316,6 +9470,7 @@ value_format (dw_attr_node *a)
>           gcc_unreachable ();
>         }
>      case dw_val_class_loc_list:
> +    case dw_val_class_view_list:
>        if (dwarf_split_debug_info
>           && dwarf_version >= 5
>           && AT_loc_list (a)->num_assigned)
> @@ -9611,7 +9766,8 @@ output_die_symbol (dw_die_ref die)
>     expression.  */
>
>  static inline dw_loc_list_ref
> -new_loc_list (dw_loc_descr_ref expr, const char *begin, const char *end,
> +new_loc_list (dw_loc_descr_ref expr, const char *begin, var_loc_view vbegin,
> +             const char *end, var_loc_view vend,
>               const char *section)
>  {
>    dw_loc_list_ref retlist = ggc_cleared_alloc<dw_loc_list_node> ();
> @@ -9621,10 +9777,28 @@ new_loc_list (dw_loc_descr_ref expr, const char *begin, const char *end,
>    retlist->end = end;
>    retlist->expr = expr;
>    retlist->section = section;
> +  retlist->vbegin = vbegin;
> +  retlist->vend = vend;
>
>    return retlist;
>  }
>
> +/* Return true iff there's any nonzero view number in the loc list.  */
> +
> +static bool
> +loc_list_has_views (dw_loc_list_ref list)
> +{
> +  if (!debug_variable_location_views)
> +    return false;
> +
> +  for (dw_loc_list_ref loc = list;
> +       loc != NULL; loc = loc->dw_loc_next)
> +    if (!ZERO_VIEW_P (loc->vbegin) || !ZERO_VIEW_P (loc->vend))
> +      return true;
> +
> +  return false;
> +}
> +
>  /* Generate a new internal symbol for this location list node, if it
>     hasn't got one yet.  */
>
> @@ -9633,6 +9807,99 @@ gen_llsym (dw_loc_list_ref list)
>  {
>    gcc_assert (!list->ll_symbol);
>    list->ll_symbol = gen_internal_sym ("LLST");
> +
> +  if (!loc_list_has_views (list))
> +    return;
> +
> +  if (dwarf2out_locviews_in_attribute ())
> +    {
> +      /* Use the same label_num for the view list.  */
> +      label_num--;
> +      list->vl_symbol = gen_internal_sym ("LVUS");
> +    }
> +  else
> +    list->vl_symbol = list->ll_symbol;
> +}
> +
> +/* Generate a symbol for the list, but only if we really want to emit
> +   it as a list.  */
> +
> +static inline void
> +maybe_gen_llsym (dw_loc_list_ref list)
> +{
> +  if (!list || (!list->dw_loc_next && !loc_list_has_views (list)))
> +    return;
> +
> +  gen_llsym (list);
> +}
> +
> +/* Determine whether or not to skip loc_list entry CURR.  If we're not
> +   to skip it, and SIZEP is non-null, store the size of CURR->expr's
> +   representation in *SIZEP.  */
> +
> +static bool
> +skip_loc_list_entry (dw_loc_list_ref curr, unsigned long *sizep = 0)
> +{
> +  /* Don't output an entry that starts and ends at the same address.  */
> +  if (strcmp (curr->begin, curr->end) == 0
> +      && curr->vbegin == curr->vend && !curr->force)
> +    return true;
> +
> +  unsigned long size = size_of_locs (curr->expr);
> +
> +  /* If the expression is too large, drop it on the floor.  We could
> +     perhaps put it into DW_TAG_dwarf_procedure and refer to that
> +     in the expression, but >= 64KB expressions for a single value
> +     in a single range are unlikely very useful.  */
> +  if (dwarf_version < 5 && size > 0xffff)
> +    return true;
> +
> +  if (sizep)
> +    *sizep = size;
> +
> +  return false;
> +}
> +
> +/* Output a view pair loclist entry for CURR, if it requires one.  */
> +
> +static void
> +dwarf2out_maybe_output_loclist_view_pair (dw_loc_list_ref curr)
> +{
> +  if (!dwarf2out_locviews_in_loclist ())
> +    return;
> +
> +  if (ZERO_VIEW_P (curr->vbegin) && ZERO_VIEW_P (curr->vend))
> +    return;
> +
> +#ifdef DW_LLE_view_pair
> +  dw2_asm_output_data (1, DW_LLE_view_pair,
> +                      "DW_LLE_view_pair");
> +
> +# if DWARF2_ASM_VIEW_DEBUG_INFO
> +  if (ZERO_VIEW_P (curr->vbegin))
> +    dw2_asm_output_data_uleb128 (0, "Location view begin");
> +  else
> +    {
> +      char label[MAX_ARTIFICIAL_LABEL_BYTES];
> +      ASM_GENERATE_INTERNAL_LABEL (label, "LVU", curr->vbegin);
> +      dw2_asm_output_symname_uleb128 (label, "Location view begin");
> +    }
> +
> +  if (ZERO_VIEW_P (curr->vend))
> +    dw2_asm_output_data_uleb128 (0, "Location view end");
> +  else
> +    {
> +      char label[MAX_ARTIFICIAL_LABEL_BYTES];
> +      ASM_GENERATE_INTERNAL_LABEL (label, "LVU", curr->vend);
> +      dw2_asm_output_symname_uleb128 (label, "Location view end");
> +    }
> +# else /* !DWARF2_ASM_VIEW_DEBUG_INFO */
> +  dw2_asm_output_data_uleb128 (curr->vbegin, "Location view begin");
> +  dw2_asm_output_data_uleb128 (curr->vend, "Location view end");
> +# endif /* DWARF2_ASM_VIEW_DEBUG_INFO */
> +#endif /* DW_LLE_view_pair */
> +
> +  return;
>  }
>
>  /* Output the location list given to us.  */
> @@ -9640,34 +9907,85 @@ gen_llsym (dw_loc_list_ref list)
>  static void
>  output_loc_list (dw_loc_list_ref list_head)
>  {
> +  int vcount = 0, lcount = 0;
> +
>    if (list_head->emitted)
>      return;
>    list_head->emitted = true;
>
> +  if (list_head->vl_symbol && dwarf2out_locviews_in_attribute ())
> +    {
> +      ASM_OUTPUT_LABEL (asm_out_file, list_head->vl_symbol);
> +
> +      for (dw_loc_list_ref curr = list_head; curr != NULL;
> +          curr = curr->dw_loc_next)
> +       {
> +         if (skip_loc_list_entry (curr))
> +           continue;
> +
> +         vcount++;
> +
> +         /* ?? dwarf_split_debug_info?  */
> +#if DWARF2_ASM_VIEW_DEBUG_INFO
> +         char label[MAX_ARTIFICIAL_LABEL_BYTES];
> +
> +         if (!ZERO_VIEW_P (curr->vbegin))
> +           {
> +             ASM_GENERATE_INTERNAL_LABEL (label, "LVU", curr->vbegin);
> +             dw2_asm_output_symname_uleb128 (label,
> +                                             "View list begin (%s)",
> +                                             list_head->vl_symbol);
> +           }
> +         else
> +           dw2_asm_output_data_uleb128 (0,
> +                                        "View list begin (%s)",
> +                                        list_head->vl_symbol);
> +
> +         if (!ZERO_VIEW_P (curr->vend))
> +           {
> +             ASM_GENERATE_INTERNAL_LABEL (label, "LVU", curr->vend);
> +             dw2_asm_output_symname_uleb128 (label,
> +                                             "View list end (%s)",
> +                                             list_head->vl_symbol);
> +           }
> +         else
> +           dw2_asm_output_data_uleb128 (0,
> +                                        "View list end (%s)",
> +                                        list_head->vl_symbol);
> +#else /* !DWARF2_ASM_VIEW_DEBUG_INFO */
> +         dw2_asm_output_data_uleb128 (curr->vbegin,
> +                                      "View list begin (%s)",
> +                                      list_head->vl_symbol);
> +         dw2_asm_output_data_uleb128 (curr->vend,
> +                                      "View list end (%s)",
> +                                      list_head->vl_symbol);
> +#endif
> +       }
> +    }
> +
>    ASM_OUTPUT_LABEL (asm_out_file, list_head->ll_symbol);
>
> -  dw_loc_list_ref curr = list_head;
>    const char *last_section = NULL;
>    const char *base_label = NULL;
>
>    /* Walk the location list, and output each range + expression.  */
> -  for (curr = list_head; curr != NULL; curr = curr->dw_loc_next)
> +  for (dw_loc_list_ref curr = list_head; curr != NULL;
> +       curr = curr->dw_loc_next)
>      {
>        unsigned long size;
> -      /* Don't output an entry that starts and ends at the same address.  */
> -      if (strcmp (curr->begin, curr->end) == 0 && !curr->force)
> -       continue;
> -      size = size_of_locs (curr->expr);
> -      /* If the expression is too large, drop it on the floor.  We could
> -        perhaps put it into DW_TAG_dwarf_procedure and refer to that
> -        in the expression, but >= 64KB expressions for a single value
> -        in a single range are unlikely very useful.  */
> -      if (dwarf_version < 5 && size > 0xffff)
> +
> +      /* Skip this entry?  If we skip it here, we must skip it in the
> +        view list above as well. */
> +      if (skip_loc_list_entry (curr, &size))
>         continue;
> +
> +      lcount++;
> +
>        if (dwarf_version >= 5)
>         {
>           if (dwarf_split_debug_info)
>             {
> +             dwarf2out_maybe_output_loclist_view_pair (curr);
>               /* For -gsplit-dwarf, emit DW_LLE_starx_length, which has
>                  uleb128 index into .debug_addr and uleb128 length.  */
>               dw2_asm_output_data (1, DW_LLE_startx_length,
> @@ -9685,6 +10003,7 @@ output_loc_list (dw_loc_list_ref list_head)
>             }
>           else if (!have_multiple_function_sections && HAVE_AS_LEB128)
>             {
> +             dwarf2out_maybe_output_loclist_view_pair (curr);
>               /* If all code is in .text section, the base address is
>                  already provided by the CU attributes.  Use
>                  DW_LLE_offset_pair where both addresses are uleb128 encoded
> @@ -9735,6 +10054,7 @@ output_loc_list (dw_loc_list_ref list_head)
>                  length.  */
>               if (last_section == NULL)
>                 {
> +                 dwarf2out_maybe_output_loclist_view_pair (curr);
>                   dw2_asm_output_data (1, DW_LLE_start_length,
>                                        "DW_LLE_start_length (%s)",
>                                        list_head->ll_symbol);
> @@ -9749,6 +10069,7 @@ output_loc_list (dw_loc_list_ref list_head)
>                  DW_LLE_base_address.  */
>               else
>                 {
> +                 dwarf2out_maybe_output_loclist_view_pair (curr);
>                   dw2_asm_output_data (1, DW_LLE_offset_pair,
>                                        "DW_LLE_offset_pair (%s)",
>                                        list_head->ll_symbol);
> @@ -9764,6 +10085,7 @@ output_loc_list (dw_loc_list_ref list_head)
>              DW_LLE_start_end with a pair of absolute addresses.  */
>           else
>             {
> +             dwarf2out_maybe_output_loclist_view_pair (curr);
>               dw2_asm_output_data (1, DW_LLE_start_end,
>                                    "DW_LLE_start_end (%s)",
>                                    list_head->ll_symbol);
> @@ -9842,6 +10164,9 @@ output_loc_list (dw_loc_list_ref list_head)
>                            "Location list terminator end (%s)",
>                            list_head->ll_symbol);
>      }
> +
> +  gcc_assert (!list_head->vl_symbol
> +             || vcount == lcount * (dwarf2out_locviews_in_attribute () ? 1 : 0));
>  }
>
>  /* Output a range_list offset into the .debug_ranges or .debug_rnglists
> @@ -9906,6 +10231,22 @@ output_loc_list_offset (dw_attr_node *a)
>                           "%s", dwarf_attr_name (a->dw_attr));
>  }
>
> +/* Output the offset into the debug_loc section.  */
> +
> +static void
> +output_view_list_offset (dw_attr_node *a)
> +{
> +  char *sym = (*AT_loc_list_ptr (a))->vl_symbol;
> +
> +  gcc_assert (sym);
> +  if (dwarf_split_debug_info)
> +    dw2_asm_output_delta (DWARF_OFFSET_SIZE, sym, loc_section_label,
> +                          "%s", dwarf_attr_name (a->dw_attr));
> +  else
> +    dw2_asm_output_offset (DWARF_OFFSET_SIZE, sym, debug_loc_section,
> +                           "%s", dwarf_attr_name (a->dw_attr));
> +}
> +
>  /* Output an attribute's index or value appropriately.  */
>
>  static void
> @@ -10136,6 +10477,10 @@ output_die (dw_die_ref die)
>           output_loc_list_offset (a);
>           break;
>
> +       case dw_val_class_view_list:
> +         output_view_list_offset (a);
> +         break;
> +
>         case dw_val_class_die_ref:
>           if (AT_ref_external (a))
>             {
> @@ -10308,6 +10653,28 @@ output_die (dw_die_ref die)
>                          (unsigned long) die->die_offset);
>  }
>
> +/* Output the dwarf version number.  */
> +
> +static void
> +output_dwarf_version ()
> +{
> +  /* ??? For now, if -gdwarf-6 is specified, we output version 5 with
> +     views in loclist.  That will change eventually.  */
> +  if (dwarf_version == 6)
> +    {
> +      static bool once;
> +      if (!once)
> +       {
> +         warning (0,
> +                  "-gdwarf-6 is output as version 5 with incompatibilities");
> +         once = true;
> +       }
> +      dw2_asm_output_data (2, 5, "DWARF version number");
> +    }
> +  else
> +    dw2_asm_output_data (2, dwarf_version, "DWARF version number");
> +}
> +
>  /* Output the compilation unit that appears at the beginning of the
>     .debug_info section, and precedes the DIE descriptions.  */
>
> @@ -10324,7 +10691,7 @@ output_compilation_unit_header (enum dwarf_unit_type ut)
>                            "Length of Compilation Unit Info");
>      }
>
> -  dw2_asm_output_data (2, dwarf_version, "DWARF version number");
> +  output_dwarf_version ();
>    if (dwarf_version >= 5)
>      {
>        const char *name;
> @@ -10513,7 +10880,7 @@ output_skeleton_debug_sections (dw_die_ref comp_unit,
>                         - DWARF_INITIAL_LENGTH_SIZE
>                         + size_of_die (comp_unit),
>                        "Length of Compilation Unit Info");
> -  dw2_asm_output_data (2, dwarf_version, "DWARF version number");
> +  output_dwarf_version ();
>    if (dwarf_version >= 5)
>      {
>        dw2_asm_output_data (1, DW_UT_skeleton, "DW_UT_skeleton");
> @@ -10812,7 +11179,7 @@ output_pubnames (vec<pubname_entry, va_gc> *names)
>      }
>
>    /* Version number for pubnames/pubtypes is independent of dwarf version.  */
> -  dw2_asm_output_data (2, 2, "DWARF Version");
> +  dw2_asm_output_data (2, 2, "DWARF pubnames/pubtypes version");
>
>    if (dwarf_split_debug_info)
>      dw2_asm_output_offset (DWARF_OFFSET_SIZE, debug_skeleton_info_section_label,
> @@ -10894,7 +11261,7 @@ output_aranges (void)
>      }
>
>    /* Version number for aranges is still 2, even up to DWARF5.  */
> -  dw2_asm_output_data (2, 2, "DWARF Version");
> +  dw2_asm_output_data (2, 2, "DWARF aranges version");
>    if (dwarf_split_debug_info)
>      dw2_asm_output_offset (DWARF_OFFSET_SIZE, debug_skeleton_info_section_label,
>                             debug_skeleton_info_section,
> @@ -11155,7 +11522,7 @@ output_rnglists (void)
>    dw2_asm_output_delta (DWARF_OFFSET_SIZE, l2, l1,
>                         "Length of Range Lists");
>    ASM_OUTPUT_LABEL (asm_out_file, l1);
> -  dw2_asm_output_data (2, dwarf_version, "DWARF Version");
> +  output_dwarf_version ();
>    dw2_asm_output_data (1, DWARF2_ADDR_SIZE, "Address Size");
>    dw2_asm_output_data (1, 0, "Segment Size");
>    /* Emit the offset table only for -gsplit-dwarf.  If we don't care
> @@ -11789,8 +12156,11 @@ output_one_line_info_table (dw_line_info_table *table)
>    char line_label[MAX_ARTIFICIAL_LABEL_BYTES];
>    unsigned int current_line = 1;
>    bool current_is_stmt = DWARF_LINE_DEFAULT_IS_STMT_START;
> -  dw_line_info_entry *ent;
> +  dw_line_info_entry *ent, *prev_addr;
>    size_t i;
> +  unsigned int view;
> +
> +  view = 0;
>
>    FOR_EACH_VEC_SAFE_ELT (table->entries, i, ent)
>      {
> @@ -11805,14 +12175,36 @@ output_one_line_info_table (dw_line_info_table *table)
>              to determine when it is safe to use DW_LNS_fixed_advance_pc.  */
>           ASM_GENERATE_INTERNAL_LABEL (line_label, LINE_CODE_LABEL, ent->val);
>
> +         view = 0;
> +
>           /* This can handle any delta.  This takes
>              4+DWARF2_ADDR_SIZE bytes.  */
> -         dw2_asm_output_data (1, 0, "set address %s", line_label);
> +         dw2_asm_output_data (1, 0, "set address %s%s", line_label,
> +                              debug_variable_location_views
> +                              ? ", reset view to 0" : "");
>           dw2_asm_output_data_uleb128 (1 + DWARF2_ADDR_SIZE, NULL);
>           dw2_asm_output_data (1, DW_LNE_set_address, NULL);
>           dw2_asm_output_addr (DWARF2_ADDR_SIZE, line_label, NULL);
> +
> +         prev_addr = ent;
>           break;
>
> +       case LI_adv_address:
> +         {
> +           ASM_GENERATE_INTERNAL_LABEL (line_label, LINE_CODE_LABEL, ent->val);
> +           char prev_label[MAX_ARTIFICIAL_LABEL_BYTES];
> +           ASM_GENERATE_INTERNAL_LABEL (prev_label, LINE_CODE_LABEL, prev_addr->val);
> +
> +           view++;
> +
> +           dw2_asm_output_data (1, DW_LNS_fixed_advance_pc, "fixed advance PC, increment view to %i", view);
> +           dw2_asm_output_delta (2, line_label, prev_label,
> +                                 "from %s to %s", prev_label, line_label);
> +
> +           prev_addr = ent;
> +           break;
> +         }
> +
>         case LI_set_line:
>           if (ent->val == current_line)
>             {
> @@ -11920,7 +12312,7 @@ output_line_info (bool prologue_only)
>
>    ASM_OUTPUT_LABEL (asm_out_file, l1);
>
> -  dw2_asm_output_data (2, dwarf_version, "DWARF Version");
> +  output_dwarf_version ();
>    if (dwarf_version >= 5)
>      {
>        dw2_asm_output_data (1, DWARF2_ADDR_SIZE, "Address Size");
> @@ -16213,6 +16605,7 @@ static dw_loc_list_ref
>  dw_loc_list (var_loc_list *loc_list, tree decl, int want_address)
>  {
>    const char *endname, *secname;
> +  var_loc_view endview;
>    rtx varloc;
>    enum var_init_status initialized;
>    struct var_loc_node *node;
> @@ -16268,24 +16661,27 @@ dw_loc_list (var_loc_list *loc_list, tree decl, int want_address)
>                 && current_function_decl)
>               {
>                 endname = cfun->fde->dw_fde_end;
> +               endview = 0;
>                 range_across_switch = true;
>               }
>             /* The variable has a location between NODE->LABEL and
>                NODE->NEXT->LABEL.  */
>             else if (node->next)
> -             endname = node->next->label;
> +             endname = node->next->label, endview = node->next->view;
>             /* If the variable has a location at the last label
>                it keeps its location until the end of function.  */
>             else if (!current_function_decl)
> -             endname = text_end_label;
> +             endname = text_end_label, endview = 0;
>             else
>               {
>                 ASM_GENERATE_INTERNAL_LABEL (label_id, FUNC_END_LABEL,
>                                              current_function_funcdef_no);
>                 endname = ggc_strdup (label_id);
> +               endview = 0;
>               }
>
> -           *listp = new_loc_list (descr, node->label, endname, secname);
> +           *listp = new_loc_list (descr, node->label, node->view,
> +                                  endname, endview, secname);
>             if (TREE_CODE (decl) == PARM_DECL
>                 && node == loc_list->first
>                 && NOTE_P (node->loc)
> @@ -16308,12 +16704,12 @@ dw_loc_list (var_loc_list *loc_list, tree decl, int want_address)
>                 /* The variable has a location between NODE->LABEL and
>                    NODE->NEXT->LABEL.  */
>                 if (node->next)
> -                 endname = node->next->label;
> +                 endname = node->next->label, endview = node->next->view;
>                 else
> -                 endname = cfun->fde->dw_fde_second_end;
> +                 endname = cfun->fde->dw_fde_second_end, endview = 0;
>                 *listp = new_loc_list (descr,
> -                                      cfun->fde->dw_fde_second_begin,
> -                                      endname, secname);
> +                                      cfun->fde->dw_fde_second_begin, 0,
> +                                      endname, endview, secname);
>                 listp = &(*listp)->dw_loc_next;
>               }
>           }
> @@ -16325,8 +16721,7 @@ dw_loc_list (var_loc_list *loc_list, tree decl, int want_address)
>       representable, we don't want to pretend a single entry that was
>       applies to the entire scope in which the variable is
>       available.  */
> -  if (list && loc_list->first->next)
> -    gen_llsym (list);
> +  maybe_gen_llsym (list);
>
>    return list;
>  }
> @@ -17146,7 +17541,7 @@ loc_list_from_tree_1 (tree loc, int want_address,
>      {
>        if (dwarf_version >= 3 || !dwarf_strict)
>         return new_loc_list (new_loc_descr (DW_OP_push_object_address, 0, 0),
> -                            NULL, NULL, NULL);
> +                            NULL, 0, NULL, 0, NULL);
>        else
>         return NULL;
>      }
> @@ -17959,7 +18354,7 @@ loc_list_from_tree_1 (tree loc, int want_address,
>         add_loc_descr_to_each (list_ret, new_loc_descr (op, size, 0));
>      }
>    if (ret)
> -    list_ret = new_loc_list (ret, NULL, NULL, NULL);
> +    list_ret = new_loc_list (ret, NULL, 0, NULL, 0, NULL);
>
>    return list_ret;
>  }
> @@ -18283,12 +18678,25 @@ static inline void
>  add_AT_location_description (dw_die_ref die, enum dwarf_attribute attr_kind,
>                              dw_loc_list_ref descr)
>  {
> +  bool check_no_locviews = true;
>    if (descr == 0)
>      return;
>    if (single_element_loc_list_p (descr))
>      add_AT_loc (die, attr_kind, descr->expr);
>    else
> -    add_AT_loc_list (die, attr_kind, descr);
> +    {
> +      add_AT_loc_list (die, attr_kind, descr);
> +      gcc_assert (descr->ll_symbol);
> +      if (attr_kind == DW_AT_location && descr->vl_symbol
> +         && dwarf2out_locviews_in_attribute ())
> +       {
> +         add_AT_view_list (die, DW_AT_GNU_locviews);
> +         check_no_locviews = false;
> +       }
> +    }
> +
> +  if (check_no_locviews)
> +    gcc_assert (!get_AT (die, DW_AT_GNU_locviews));
>  }
>
>  /* Add DW_AT_accessibility attribute to DIE if needed.  */
> @@ -19458,7 +19866,7 @@ convert_cfa_to_fb_loc_list (HOST_WIDE_INT offset)
>        /* If the first partition contained no CFI adjustments, the
>          CIE opcodes apply to the whole first partition.  */
>        *list_tail = new_loc_list (build_cfa_loc (&last_cfa, offset),
> -                                fde->dw_fde_begin, fde->dw_fde_end, section);
> +                                fde->dw_fde_begin, 0, fde->dw_fde_end, 0, section);
>        list_tail =&(*list_tail)->dw_loc_next;
>        start_label = last_label = fde->dw_fde_second_begin;
>      }
> @@ -19474,7 +19882,7 @@ convert_cfa_to_fb_loc_list (HOST_WIDE_INT offset)
>           if (!cfa_equal_p (&last_cfa, &next_cfa))
>             {
>               *list_tail = new_loc_list (build_cfa_loc (&last_cfa, offset),
> -                                        start_label, last_label, section);
> +                                        start_label, 0, last_label, 0, section);
>
>               list_tail = &(*list_tail)->dw_loc_next;
>               last_cfa = next_cfa;
> @@ -19496,14 +19904,14 @@ convert_cfa_to_fb_loc_list (HOST_WIDE_INT offset)
>           if (!cfa_equal_p (&last_cfa, &next_cfa))
>             {
>               *list_tail = new_loc_list (build_cfa_loc (&last_cfa, offset),
> -                                        start_label, last_label, section);
> +                                        start_label, 0, last_label, 0, section);
>
>               list_tail = &(*list_tail)->dw_loc_next;
>               last_cfa = next_cfa;
>               start_label = last_label;
>             }
>           *list_tail = new_loc_list (build_cfa_loc (&last_cfa, offset),
> -                                    start_label, fde->dw_fde_end, section);
> +                                    start_label, 0, fde->dw_fde_end, 0, section);
>           list_tail = &(*list_tail)->dw_loc_next;
>           start_label = last_label = fde->dw_fde_second_begin;
>         }
> @@ -19512,19 +19920,18 @@ convert_cfa_to_fb_loc_list (HOST_WIDE_INT offset)
>    if (!cfa_equal_p (&last_cfa, &next_cfa))
>      {
>        *list_tail = new_loc_list (build_cfa_loc (&last_cfa, offset),
> -                                start_label, last_label, section);
> +                                start_label, 0, last_label, 0, section);
>        list_tail = &(*list_tail)->dw_loc_next;
>        start_label = last_label;
>      }
>
>    *list_tail = new_loc_list (build_cfa_loc (&next_cfa, offset),
> -                            start_label,
> +                            start_label, 0,
>                              fde->dw_fde_second_begin
> -                            ? fde->dw_fde_second_end : fde->dw_fde_end,
> +                            ? fde->dw_fde_second_end : fde->dw_fde_end, 0,
>                              section);
>
> -  if (list && list->dw_loc_next)
> -    gen_llsym (list);
> +  maybe_gen_llsym (list);
>
>    return list;
>  }
> @@ -22636,6 +23043,48 @@ block_die_hasher::equal (die_struct *x, die_struct *y)
>    return x->decl_id == y->decl_id && x->die_parent == y->die_parent;
>  }
>
> +/* Hold information about markers for inlined entry points.  */
> +struct GTY ((for_user)) inline_entry_data
> +{
> +  /* The block that's the inlined_function_outer_scope for an inlined
> +     function.  */
> +  tree block;
> +
> +  /* The label at the inlined entry point.  */
> +  const char *label_pfx;
> +  unsigned int label_num;
> +
> +  /* The view number to be used as the inlined entry point.  */
> +  var_loc_view view;
> +};
> +
> +struct inline_entry_data_hasher : ggc_ptr_hash <inline_entry_data>
> +{
> +  typedef tree compare_type;
> +  static inline hashval_t hash (const inline_entry_data *);
> +  static inline bool equal (const inline_entry_data *, const_tree);
> +};
> +
> +/* Hash table routines for inline_entry_data.  */
> +
> +inline hashval_t
> +inline_entry_data_hasher::hash (const inline_entry_data *data)
> +{
> +  return htab_hash_pointer (data->block);
> +}
> +
> +inline bool
> +inline_entry_data_hasher::equal (const inline_entry_data *data,
> +                                const_tree block)
> +{
> +  return data->block == block;
> +}
> +
> +/* Inlined entry points pending DIE creation in this compilation unit.  */
> +
> +static GTY(()) hash_table<inline_entry_data_hasher> *inline_entry_data_table;
> +
> +
>  /* Return TRUE if DECL, which may have been previously generated as
>     OLD_DIE, is a candidate for a DW_AT_specification.  DECLARATION is
>     true if decl (or its origin) is either an extern declaration or a
> @@ -23072,6 +23521,42 @@ add_high_low_attributes (tree stmt, dw_die_ref die)
>  {
>    char label[MAX_ARTIFICIAL_LABEL_BYTES];
>
> +  if (inline_entry_data **iedp
> +      = !inline_entry_data_table ? NULL
> +      : inline_entry_data_table->find_slot_with_hash (stmt,
> +                                                     htab_hash_pointer (stmt),
> +                                                     NO_INSERT))
> +    {
> +      inline_entry_data *ied = *iedp;
> +      gcc_assert (debug_nonbind_markers_p);
> +      gcc_assert (inlined_function_outer_scope_p (stmt));
> +      ASM_GENERATE_INTERNAL_LABEL (label, ied->label_pfx, ied->label_num);
> +      add_AT_lbl_id (die, DW_AT_entry_pc, label);
> +
> +      if (debug_variable_location_views && !ZERO_VIEW_P (ied->view))
> +       {
> +         if (!output_asm_line_debug_info ())
> +           add_AT_unsigned (die, DW_AT_GNU_entry_view, ied->view);
> +         else
> +           {
> +             ASM_GENERATE_INTERNAL_LABEL (label, "LVU", ied->view);
> +             /* FIXME: this will resolve to a small number.  Could we
> +                possibly emit smaller data?  Ideally we'd emit a
> +                uleb128, but that would make the size of DIEs
> +                impossible for the compiler to compute, since it's
> +                the assembler that computes the value of the view
> +                label in this case.  Ideally, we'd have a single form
> +                encompassing both the address and the view, and
> +                indirecting them through a table might make things
> +                easier, but even that would be more wasteful,
> +                space-wise, than what we have now.  */
> +             add_AT_lbl_id (die, DW_AT_GNU_entry_view, label);
> +           }
> +       }
> +
> +      inline_entry_data_table->clear_slot (iedp);
> +    }
> +
>    if (BLOCK_FRAGMENT_CHAIN (stmt)
>        && (dwarf_version >= 3 || !dwarf_strict))
>      {
> @@ -23079,7 +23564,7 @@ add_high_low_attributes (tree stmt, dw_die_ref die)
>        dw_die_ref pdie;
>        dw_attr_node *attr = NULL;
>
> -      if (inlined_function_outer_scope_p (stmt))
> +      if (!debug_nonbind_markers_p && inlined_function_outer_scope_p (stmt))
>         {
>           ASM_GENERATE_INTERNAL_LABEL (label, BLOCK_BEGIN_LABEL,
>                                        BLOCK_NUMBER (stmt));
> @@ -23250,7 +23735,7 @@ gen_inlined_subroutine_die (tree stmt, dw_die_ref context_die)
>        dw_die_ref subr_die
>         = new_die (DW_TAG_inlined_subroutine, context_die, stmt);
>
> -      if (call_arg_locations)
> +      if (call_arg_locations || debug_nonbind_markers_p)
>         BLOCK_DIE (stmt) = subr_die;
>        add_abstract_origin_attribute (subr_die, decl);
>        if (TREE_ASM_WRITTEN (stmt))
> @@ -25922,7 +26407,7 @@ maybe_emit_file (struct dwarf_file_data * fd)
>         fd->emitted_number = 1;
>        last_emitted_file = fd;
>
> -      if (DWARF2_ASM_LINE_DEBUG_INFO)
> +      if (output_asm_line_debug_info ())
>         {
>           fprintf (asm_out_file, "\t.file %u ", fd->emitted_number);
>           output_quoted_string (asm_out_file,
> @@ -26082,6 +26567,22 @@ static bool maybe_at_text_label_p = true;
>  /* One above highest N where .LVLN label might be equal to .Ltext0 label.  */
>  static unsigned int first_loclabel_num_not_at_text_label;
>
> +/* Look ahead for a real insn, or for a begin stmt marker.  */
> +
> +static rtx_insn *
> +dwarf2out_next_real_insn (rtx_insn *loc_note)
> +{
> +  rtx_insn *next_real = NEXT_INSN (loc_note);
> +
> +  while (next_real)
> +    if (INSN_P (next_real))
> +      break;
> +    else
> +      next_real = NEXT_INSN (next_real);
> +
> +  return next_real;
> +}
> +
>  /* Called by the final INSN scan whenever we see a var location.  We
>     use it to drop labels in the right places, and throw the location in
>     our lookup table.  */
> @@ -26099,11 +26600,13 @@ dwarf2out_var_location (rtx_insn *loc_note)
>    static rtx_insn *expected_next_loc_note;
>    tree decl;
>    bool var_loc_p;
> +  var_loc_view view = 0;
>
>    if (!NOTE_P (loc_note))
>      {
>        if (CALL_P (loc_note))
>         {
> +         RESET_NEXT_VIEW (cur_line_info_table->view);
>           call_site_count++;
>           if (SIBLING_CALL_P (loc_note))
>             tail_call_site_count++;
> @@ -26130,13 +26633,25 @@ dwarf2out_var_location (rtx_insn *loc_note)
>                   loc_note = NULL;
>                   var_loc_p = false;
>
> -                 next_real = next_real_insn (call_insn);
> +                 next_real = dwarf2out_next_real_insn (call_insn);
>                   next_note = NULL;
>                   cached_next_real_insn = NULL;
>                   goto create_label;
>                 }
>             }
>         }
> +      else if (!debug_variable_location_views)
> +       gcc_unreachable ();
> +      else if (JUMP_TABLE_DATA_P (loc_note))
> +       RESET_NEXT_VIEW (cur_line_info_table->view);
> +      else if (GET_CODE (loc_note) == USE
> +              || GET_CODE (loc_note) == CLOBBER
> +              || GET_CODE (loc_note) == ASM_INPUT
> +              || asm_noperands (loc_note) >= 0)
> +       ;
> +      else if (get_attr_min_length (loc_note) > 0)
> +       RESET_NEXT_VIEW (cur_line_info_table->view);
> +
>        return;
>      }
>
> @@ -26160,11 +26675,13 @@ dwarf2out_var_location (rtx_insn *loc_note)
>        || next_note->deleted ()
>        || ! NOTE_P (next_note)
>        || (NOTE_KIND (next_note) != NOTE_INSN_VAR_LOCATION
> +         && NOTE_KIND (next_note) != NOTE_INSN_BEGIN_STMT
> +         && NOTE_KIND (next_note) != NOTE_INSN_INLINE_ENTRY
>           && NOTE_KIND (next_note) != NOTE_INSN_CALL_ARG_LOCATION))
>      next_note = NULL;
>
>    if (! next_real)
> -    next_real = next_real_insn (loc_note);
> +    next_real = dwarf2out_next_real_insn (loc_note);
>
>    if (next_note)
>      {
> @@ -26199,10 +26716,11 @@ create_label:
>
>    if (var_loc_p)
>      {
> +      const char *label = NOTE_DURING_CALL_P (loc_note)
> +       ? last_postcall_label : last_label;
> +      view = cur_line_info_table->view;
>        decl = NOTE_VAR_LOCATION_DECL (loc_note);
> -      newloc = add_var_loc_to_decl (decl, loc_note,
> -                                   NOTE_DURING_CALL_P (loc_note)
> -                                   ? last_postcall_label : last_label);
> +      newloc = add_var_loc_to_decl (decl, loc_note, label, view);
>        if (newloc == NULL)
>         return;
>      }
> @@ -26243,8 +26761,8 @@ create_label:
>                 else if (GET_CODE (body) == ASM_INPUT
>                          || asm_noperands (body) >= 0)
>                   continue;
> -#ifdef HAVE_attr_length
> -               else if (get_attr_min_length (insn) == 0)
> +#ifdef HAVE_ATTR_length /* ??? We don't include insn-attr.h.  */
> +               else if (HAVE_ATTR_length && get_attr_min_length (insn) == 0)
>                   continue;
>  #endif
>                 else
> @@ -26312,7 +26830,10 @@ create_label:
>        call_arg_loc_last = ca_loc;
>      }
>    else if (loc_note != NULL_RTX && !NOTE_DURING_CALL_P (loc_note))
> -    newloc->label = last_label;
> +    {
> +      newloc->label = last_label;
> +      newloc->view = view;
> +    }
>    else
>      {
>        if (!last_postcall_label)
> @@ -26321,12 +26842,123 @@ create_label:
>           last_postcall_label = ggc_strdup (loclabel);
>         }
>        newloc->label = last_postcall_label;
> +      newloc->view = view;
> +    }
> +
> +  if (var_loc_p && flag_debug_asm)
> +    {
> +      const char *name = NULL, *sep = " => ", *patstr = NULL;
> +      if (decl && DECL_NAME (decl))
> +       name = IDENTIFIER_POINTER (DECL_NAME (decl));
> +      if (NOTE_VAR_LOCATION_LOC (loc_note))
> +       patstr = str_pattern_slim (NOTE_VAR_LOCATION_LOC (loc_note));
> +      else
> +       {
> +         sep = " ";
> +         patstr = "RESET";
> +       }
> +      fprintf (asm_out_file, "\t%s DEBUG %s%s%s\n", ASM_COMMENT_START,
> +              name, sep, patstr);
>      }
>
>    last_var_location_insn = next_real;
>    last_in_cold_section_p = in_cold_section_p;
>  }
>
> +/* Check whether BLOCK, a lexical block, is nested within OUTER, or is
> +   OUTER itself.  */
> +static bool
> +block_within_block_p (tree block, tree outer)
> +{
> +  if (block == outer)
> +    return true;
> +
> +  /* Quickly check that OUTER is up BLOCK's supercontext chain.  */
> +  for (tree context = BLOCK_SUPERCONTEXT (block);
> +       context != outer;
> +       context = BLOCK_SUPERCONTEXT (context))
> +    if (!context || TREE_CODE (context) != BLOCK)
> +      return false;
> +
> +  /* Now check that each block is actually referenced by its
> +     parent.  */
> +  for (tree context = BLOCK_SUPERCONTEXT (block); ;
> +       context = BLOCK_SUPERCONTEXT (context))
> +    {
> +      if (BLOCK_FRAGMENT_ORIGIN (context))
> +       {
> +         gcc_assert (!BLOCK_SUBBLOCKS (context));
> +         context = BLOCK_FRAGMENT_ORIGIN (context);
> +       }
> +      for (tree sub = BLOCK_SUBBLOCKS (context);
> +          sub != block;
> +          sub = BLOCK_CHAIN (sub))
> +       if (!sub)
> +         return false;
> +      if (context == outer)
> +       return true;
> +      else
> +       block = context;
> +    }
> +}
> +
> +/* Called during final while assembling the marker of the entry point
> +   for an inlined function.  */
> +
> +static void
> +dwarf2out_inline_entry (tree block)
> +{
> +  gcc_assert (DECL_P (block_ultimate_origin (block)));
> +
> +  gcc_checking_assert (block_within_block_p (block,
> +                                            DECL_INITIAL
> +                                            (current_function_decl)));
> +
> +  gcc_assert (inlined_function_outer_scope_p (block));
> +  gcc_assert (!BLOCK_DIE (block));
> +
> +  /* If we can't represent it, don't bother.  */
> +  if (!(dwarf_version >= 3 || !dwarf_strict))
> +    return;
> +
> +  if (BLOCK_FRAGMENT_ORIGIN (block))
> +    block = BLOCK_FRAGMENT_ORIGIN (block);
> +  /* Can the entry point ever not be at the beginning of an
> +     unfragmented lexical block?  */
> +  else if (!(BLOCK_FRAGMENT_CHAIN (block)
> +            || (cur_line_info_table
> +                && !ZERO_VIEW_P (cur_line_info_table->view))))
> +    return;
> +
> +  if (!inline_entry_data_table)
> +    inline_entry_data_table
> +      = hash_table<inline_entry_data_hasher>::create_ggc (10);
> +
> +
> +  inline_entry_data **iedp
> +    = inline_entry_data_table->find_slot_with_hash (block,
> +                                                   htab_hash_pointer (block),
> +                                                   INSERT);
> +  if (*iedp)
> +    /* ??? Ideally, we'd record all entry points for the same inlined
> +       function (some may have been duplicated by e.g. unrolling), but
> +       we have no way to represent that ATM.  */
> +    return;
> +
> +  inline_entry_data *ied = *iedp = ggc_cleared_alloc<inline_entry_data> ();
> +  ied->block = block;
> +  ied->label_pfx = BLOCK_INLINE_ENTRY_LABEL;
> +  ied->label_num = BLOCK_NUMBER (block);
> +  if (cur_line_info_table)
> +    ied->view = cur_line_info_table->view;
> +
> +  char label[MAX_ARTIFICIAL_LABEL_BYTES];
> +
> +  ASM_GENERATE_INTERNAL_LABEL (label, BLOCK_INLINE_ENTRY_LABEL,
> +                              BLOCK_NUMBER (block));
> +  ASM_OUTPUT_LABEL (asm_out_file, label);
> +}
> +
>  /* Called from finalize_size_functions for size functions so that their body
>     can be encoded in the debug info to describe the layout of variable-length
>     structures.  */
> @@ -26371,6 +27003,7 @@ new_line_info_table (void)
>    table->file_num = 1;
>    table->line_num = 1;
>    table->is_stmt = DWARF_LINE_DEFAULT_IS_STMT_START;
> +  RESET_NEXT_VIEW (table->view);
>
>    return table;
>  }
> @@ -26419,7 +27052,7 @@ set_cur_line_info_table (section *sec)
>        vec_safe_push (separate_line_info, table);
>      }
>
> -  if (DWARF2_ASM_LINE_DEBUG_INFO)
> +  if (output_asm_line_debug_info ())
>      table->is_stmt = (cur_line_info_table
>                       ? cur_line_info_table->is_stmt
>                       : DWARF_LINE_DEFAULT_IS_STMT_START);
> @@ -26600,7 +27233,7 @@ dwarf2out_source_line (unsigned int line, unsigned int column,
>                  filename, line);
>      }
>
> -  if (DWARF2_ASM_LINE_DEBUG_INFO)
> +  if (output_asm_line_debug_info ())
>      {
>        /* Emit the .loc directive understood by GNU as.  */
>        /* "\t.loc %u %u 0 is_stmt %u discriminator %u",
> @@ -26626,6 +27259,33 @@ dwarf2out_source_line (unsigned int line, unsigned int column,
>           fputs (" discriminator ", asm_out_file);
>           fprint_ul (asm_out_file, (unsigned long) discriminator);
>         }
> +      if (debug_variable_location_views)
> +       {
> +         static var_loc_view lvugid;
> +         if (!lvugid)
> +           {
> +             gcc_assert (!zero_view_p);
> +             zero_view_p = BITMAP_GGC_ALLOC ();
> +             bitmap_set_bit (zero_view_p, 0);
> +           }
> +         if (RESETTING_VIEW_P (table->view))
> +           {
> +             if (!table->in_use)
> +               fputs (" view -0", asm_out_file);
> +             else
> +               fputs (" view 0", asm_out_file);
> +             bitmap_set_bit (zero_view_p, lvugid);
> +             table->view = ++lvugid;
> +           }
> +         else
> +           {
> +             fputs (" view ", asm_out_file);
> +             char label[MAX_ARTIFICIAL_LABEL_BYTES];
> +             ASM_GENERATE_INTERNAL_LABEL (label, "LVU", table->view);
> +             assemble_name (asm_out_file, label);
> +             table->view = ++lvugid;
> +           }
> +       }
>        putc ('\n', asm_out_file);
>      }
>    else
> @@ -26634,7 +27294,19 @@ dwarf2out_source_line (unsigned int line, unsigned int column,
>
>        targetm.asm_out.internal_label (asm_out_file, LINE_CODE_LABEL, label_num);
>
> -      push_dw_line_info_entry (table, LI_set_address, label_num);
> +      if (debug_variable_location_views && table->view)
> +       push_dw_line_info_entry (table, LI_adv_address, label_num);
> +      else
> +       push_dw_line_info_entry (table, LI_set_address, label_num);
> +      if (debug_variable_location_views)
> +       {
> +         if (flag_debug_asm)
> +           fprintf (asm_out_file, "\t%s view %s%d\n",
> +                    ASM_COMMENT_START,
> +                    table->in_use ? "" : "-",
> +                    table->view);
> +         table->view++;
> +       }
>        if (file_num != table->file_num)
>         push_dw_line_info_entry (table, LI_set_file, file_num);
>        if (discriminator != table->discrim_num)
> @@ -27223,7 +27895,7 @@ init_sections_and_labels (void)
>                                         SECTION_DEBUG, NULL);
>    debug_str_section = get_section (DEBUG_STR_SECTION,
>                                    DEBUG_STR_SECTION_FLAGS, NULL);
> -  if (!dwarf_split_debug_info && !DWARF2_ASM_LINE_DEBUG_INFO)
> +  if (!dwarf_split_debug_info && !output_asm_line_debug_info ())
>      debug_line_str_section = get_section (DEBUG_LINE_STR_SECTION,
>                                           DEBUG_STR_SECTION_FLAGS, NULL);
>
> @@ -27608,6 +28280,11 @@ prune_unused_types_walk_attribs (dw_die_ref die)
>             prune_unused_types_walk_loc_descr (list->expr);
>           break;
>
> +       case dw_val_class_view_list:
> +         /* This points to a loc_list in another attribute, so it's
> +            already covered.  */
> +         break;
> +
>         case dw_val_class_die_ref:
>           /* A reference to another DIE.
>              Make sure that it will get emitted.
> @@ -28707,6 +29384,8 @@ optimize_string_length (dw_attr_node *a)
>         if (d->expr && non_dwarf_expression (d->expr))
>           non_dwarf_expr = true;
>        break;
> +    case dw_val_class_view_list:
> +      gcc_unreachable ();
>      case dw_val_class_loc:
>        lv = AT_loc (av);
>        if (lv == NULL)
> @@ -28751,7 +29430,7 @@ optimize_string_length (dw_attr_node *a)
>           lv = copy_deref_exprloc (d->expr);
>           if (lv)
>             {
> -             *p = new_loc_list (lv, d->begin, d->end, d->section);
> +             *p = new_loc_list (lv, d->begin, d->vbegin, d->end, d->vend, d->section);
>               p = &(*p)->dw_loc_next;
>             }
>           else if (!dwarf_strict && d->expr)
> @@ -28821,6 +29500,7 @@ resolve_addr (dw_die_ref die)
>                       {
>                         gcc_assert (!next->ll_symbol);
>                         next->ll_symbol = (*curr)->ll_symbol;
> +                       next->vl_symbol = (*curr)->vl_symbol;
>                       }
>                      if (dwarf_split_debug_info)
>                        remove_loc_list_addr_table_entries (l);
> @@ -28846,6 +29526,21 @@ resolve_addr (dw_die_ref die)
>             ix--;
>           }
>         break;
> +      case dw_val_class_view_list:
> +       {
> +         gcc_checking_assert (a->dw_attr == DW_AT_GNU_locviews);
> +         gcc_checking_assert (dwarf2out_locviews_in_attribute ());
> +         dw_val_node *llnode
> +           = view_list_to_loc_list_val_node (&a->dw_attr_val);
> +         /* If we no longer have a loclist, or it no longer needs
> +            views, drop this attribute.  */
> +         if (!llnode || !llnode->v.val_loc_list->vl_symbol)
> +           {
> +             remove_AT (die, a->dw_attr);
> +             ix--;
> +           }
> +         break;
> +       }
>        case dw_val_class_loc:
>         {
>           dw_loc_descr_ref l = AT_loc (a);
> @@ -29242,6 +29937,8 @@ hash_loc_list (dw_loc_list_ref list_head)
>      {
>        hstate.add (curr->begin, strlen (curr->begin) + 1);
>        hstate.add (curr->end, strlen (curr->end) + 1);
> +      hstate.add_object (curr->vbegin);
> +      hstate.add_object (curr->vend);
>        if (curr->section)
>         hstate.add (curr->section, strlen (curr->section) + 1);
>        hash_locs (curr->expr, hstate);
> @@ -29463,6 +30160,7 @@ loc_list_hasher::equal (const dw_loc_list_struct *a,
>         || strcmp (a->end, b->end) != 0
>         || (a->section == NULL) != (b->section == NULL)
>         || (a->section && strcmp (a->section, b->section) != 0)
> +       || a->vbegin != b->vbegin || a->vend != b->vend
>         || !compare_locs (a->expr, b->expr))
>        break;
>    return a == NULL && b == NULL;
> @@ -29481,6 +30179,8 @@ optimize_location_lists_1 (dw_die_ref die, loc_list_hash_type *htab)
>    dw_attr_node *a;
>    unsigned ix;
>    dw_loc_list_struct **slot;
> +  bool drop_locviews = false;
> +  bool has_locviews = false;
>
>    FOR_EACH_VEC_SAFE_ELT (die->die_attr, ix, a)
>      if (AT_class (a) == dw_val_class_loc_list)
> @@ -29491,10 +30191,32 @@ optimize_location_lists_1 (dw_die_ref die, loc_list_hash_type *htab)
>         hash_loc_list (list);
>         slot = htab->find_slot_with_hash (list, list->hash, INSERT);
>         if (*slot == NULL)
> -         *slot = list;
> +         {
> +           *slot = list;
> +           if (loc_list_has_views (list))
> +             gcc_assert (list->vl_symbol);
> +           else if (list->vl_symbol)
> +             {
> +               drop_locviews = true;
> +               list->vl_symbol = NULL;
> +             }
> +         }
>         else
> -          a->dw_attr_val.v.val_loc_list = *slot;
> +         {
> +           if (list->vl_symbol && !(*slot)->vl_symbol)
> +             drop_locviews = true;
> +           a->dw_attr_val.v.val_loc_list = *slot;
> +         }
>        }
> +    else if (AT_class (a) == dw_val_class_view_list)
> +      {
> +       gcc_checking_assert (a->dw_attr == DW_AT_GNU_locviews);
> +       has_locviews = true;
> +      }
> +
> +
> +  if (drop_locviews && has_locviews)
> +    remove_AT (die, DW_AT_GNU_locviews);
>
>    FOR_EACH_CHILD (die, c, optimize_location_lists_1 (c, htab));
>  }
> @@ -29520,7 +30242,7 @@ index_location_lists (dw_die_ref die)
>              /* Don't index an entry that has already been indexed
>                 or won't be output.  */
>              if (curr->begin_entry != NULL
> -                || (strcmp (curr->begin, curr->end) == 0 && !curr->force))
> +                || skip_loc_list_entry (curr))
>                continue;
>
>              curr->begin_entry
> @@ -29612,6 +30334,9 @@ dwarf2out_finish (const char *)
>    /* Flush out any latecomers to the limbo party.  */
>    flush_limbo_die_list ();
>
> +  if (inline_entry_data_table)
> +    gcc_assert (inline_entry_data_table->elements () == 0);
> +
>    if (flag_checking)
>      {
>        verify_die (comp_unit_die ());
> @@ -29897,7 +30622,7 @@ dwarf2out_finish (const char *)
>           dw2_asm_output_delta (DWARF_OFFSET_SIZE, l2, l1,
>                             "Length of Location Lists");
>           ASM_OUTPUT_LABEL (asm_out_file, l1);
> -         dw2_asm_output_data (2, dwarf_version, "DWARF Version");
> +         output_dwarf_version ();
>           dw2_asm_output_data (1, DWARF2_ADDR_SIZE, "Address Size");
>           dw2_asm_output_data (1, 0, "Segment Size");
>           dw2_asm_output_data (4, dwarf_split_debug_info ? loc_list_idx : 0,
> @@ -29955,7 +30680,7 @@ dwarf2out_finish (const char *)
>       used by the debug_info section are marked as 'used'.  */
>    switch_to_section (debug_line_section);
>    ASM_OUTPUT_LABEL (asm_out_file, debug_line_section_label);
> -  if (! DWARF2_ASM_LINE_DEBUG_INFO)
> +  if (! output_asm_line_debug_info ())
>      output_line_info (false);
>
>    if (dwarf_split_debug_info && info_section_emitted)
> diff --git a/gcc/dwarf2out.h b/gcc/dwarf2out.h
> index 9402473..a7653ce 100644
> --- a/gcc/dwarf2out.h
> +++ b/gcc/dwarf2out.h
> @@ -157,7 +157,8 @@ enum dw_val_class
>    dw_val_class_discr_list,
>    dw_val_class_const_implicit,
>    dw_val_class_unsigned_const_implicit,
> -  dw_val_class_file_implicit
> +  dw_val_class_file_implicit,
> +  dw_val_class_view_list
>  };
>
>  /* Describe a floating point constant value, or a vector constant value.  */
> @@ -200,6 +201,7 @@ struct GTY(()) dw_val_node {
>        rtx GTY ((tag ("dw_val_class_addr"))) val_addr;
>        unsigned HOST_WIDE_INT GTY ((tag ("dw_val_class_offset"))) val_offset;
>        dw_loc_list_ref GTY ((tag ("dw_val_class_loc_list"))) val_loc_list;
> +      dw_die_ref GTY ((tag ("dw_val_class_view_list"))) val_view_list;
>        dw_loc_descr_ref GTY ((tag ("dw_val_class_loc"))) val_loc;
>        HOST_WIDE_INT GTY ((default)) val_int;
>        unsigned HOST_WIDE_INT
> diff --git a/gcc/emit-rtl.c b/gcc/emit-rtl.c
> index 6951f61..a6efdd8 100644
> --- a/gcc/emit-rtl.c
> +++ b/gcc/emit-rtl.c
> @@ -3346,20 +3346,17 @@ next_nonnote_insn (rtx_insn *insn)
>    return insn;
>  }
>
> -/* Return the next insn after INSN that is not a NOTE, but stop the
> -   search before we enter another basic block.  This routine does not
> -   look inside SEQUENCEs.  */
> +/* Return the next insn after INSN that is not a DEBUG_INSN.  This
> +   routine does not look inside SEQUENCEs.  */
>
>  rtx_insn *
> -next_nonnote_insn_bb (rtx_insn *insn)
> +next_nondebug_insn (rtx_insn *insn)
>  {
>    while (insn)
>      {
>        insn = NEXT_INSN (insn);
> -      if (insn == 0 || !NOTE_P (insn))
> +      if (insn == 0 || !DEBUG_INSN_P (insn))
>         break;
> -      if (NOTE_INSN_BASIC_BLOCK_P (insn))
> -       return NULL;
>      }
>
>    return insn;
> @@ -3381,67 +3378,70 @@ prev_nonnote_insn (rtx_insn *insn)
>    return insn;
>  }
>
> -/* Return the previous insn before INSN that is not a NOTE, but stop
> -   the search before we enter another basic block.  This routine does
> -   not look inside SEQUENCEs.  */
> +/* Return the previous insn before INSN that is not a DEBUG_INSN.
> +   This routine does not look inside SEQUENCEs.  */
>
>  rtx_insn *
> -prev_nonnote_insn_bb (rtx_insn *insn)
> +prev_nondebug_insn (rtx_insn *insn)
>  {
> -
>    while (insn)
>      {
>        insn = PREV_INSN (insn);
> -      if (insn == 0 || !NOTE_P (insn))
> +      if (insn == 0 || !DEBUG_INSN_P (insn))
>         break;
> -      if (NOTE_INSN_BASIC_BLOCK_P (insn))
> -       return NULL;
>      }
>
>    return insn;
>  }
>
> -/* Return the next insn after INSN that is not a DEBUG_INSN.  This
> -   routine does not look inside SEQUENCEs.  */
> +/* Return the next insn after INSN that is not a NOTE nor DEBUG_INSN.
> +   This routine does not look inside SEQUENCEs.  */
>
>  rtx_insn *
> -next_nondebug_insn (rtx_insn *insn)
> +next_nonnote_nondebug_insn (rtx_insn *insn)
>  {
>    while (insn)
>      {
>        insn = NEXT_INSN (insn);
> -      if (insn == 0 || !DEBUG_INSN_P (insn))
> +      if (insn == 0 || (!NOTE_P (insn) && !DEBUG_INSN_P (insn)))
>         break;
>      }
>
>    return insn;
>  }
>
> -/* Return the previous insn before INSN that is not a DEBUG_INSN.
> -   This routine does not look inside SEQUENCEs.  */
> +/* Return the next insn after INSN that is not a NOTE nor DEBUG_INSN,
> +   but stop the search before we enter another basic block.  This
> +   routine does not look inside SEQUENCEs.  */
>
>  rtx_insn *
> -prev_nondebug_insn (rtx_insn *insn)
> +next_nonnote_nondebug_insn_bb (rtx_insn *insn)
>  {
>    while (insn)
>      {
> -      insn = PREV_INSN (insn);
> -      if (insn == 0 || !DEBUG_INSN_P (insn))
> +      insn = NEXT_INSN (insn);
> +      if (insn == 0)
> +       break;
> +      if (DEBUG_INSN_P (insn))
> +       continue;
> +      if (!NOTE_P (insn))
>         break;
> +      if (NOTE_INSN_BASIC_BLOCK_P (insn))
> +       return NULL;
>      }
>
>    return insn;
>  }
>
> -/* Return the next insn after INSN that is not a NOTE nor DEBUG_INSN.
> +/* Return the previous insn before INSN that is not a NOTE nor DEBUG_INSN.
>     This routine does not look inside SEQUENCEs.  */
>
>  rtx_insn *
> -next_nonnote_nondebug_insn (rtx_insn *insn)
> +prev_nonnote_nondebug_insn (rtx_insn *insn)
>  {
>    while (insn)
>      {
> -      insn = NEXT_INSN (insn);
> +      insn = PREV_INSN (insn);
>        if (insn == 0 || (!NOTE_P (insn) && !DEBUG_INSN_P (insn)))
>         break;
>      }
> @@ -3449,17 +3449,24 @@ next_nonnote_nondebug_insn (rtx_insn *insn)
>    return insn;
>  }
>
> -/* Return the previous insn before INSN that is not a NOTE nor DEBUG_INSN.
> -   This routine does not look inside SEQUENCEs.  */
> +/* Return the previous insn before INSN that is not a NOTE nor
> +   DEBUG_INSN, but stop the search before we enter another basic
> +   block.  This routine does not look inside SEQUENCEs.  */
>
>  rtx_insn *
> -prev_nonnote_nondebug_insn (rtx_insn *insn)
> +prev_nonnote_nondebug_insn_bb (rtx_insn *insn)
>  {
>    while (insn)
>      {
>        insn = PREV_INSN (insn);
> -      if (insn == 0 || (!NOTE_P (insn) && !DEBUG_INSN_P (insn)))
> +      if (insn == 0)
>         break;
> +      if (DEBUG_INSN_P (insn))
> +       continue;
> +      if (!NOTE_P (insn))
> +       break;
> +      if (NOTE_INSN_BASIC_BLOCK_P (insn))
> +       return NULL;
>      }
>
>    return insn;
> diff --git a/gcc/final.c b/gcc/final.c
> index ad999f7..cfe615e 100644
> --- a/gcc/final.c
> +++ b/gcc/final.c
> @@ -81,6 +81,7 @@ along with GCC; see the file COPYING3.  If not see
>  #include "asan.h"
>  #include "rtl-iter.h"
>  #include "print-rtl.h"
> +#include "langhooks.h"
>
>  #ifdef XCOFF_DEBUGGING_INFO
>  #include "xcoffout.h"          /* Needed for external data declarations.  */
> @@ -112,6 +113,7 @@ along with GCC; see the file COPYING3.  If not see
>  /* Bitflags used by final_scan_insn.  */
>  #define SEEN_NOTE      1
>  #define SEEN_EMITTED   2
> +#define SEEN_NEXT_VIEW 4
>
>  /* Last insn processed by final_scan_insn.  */
>  static rtx_insn *debug_insn;
> @@ -1653,7 +1655,6 @@ reemit_insn_block_notes (void)
>  {
>    tree cur_block = DECL_INITIAL (cfun->decl);
>    rtx_insn *insn;
> -  rtx_note *note;
>
>    insn = get_insns ();
>    for (; insn; insn = NEXT_INSN (insn))
> @@ -1661,17 +1662,30 @@ reemit_insn_block_notes (void)
>        tree this_block;
>
>        /* Prevent lexical blocks from straddling section boundaries.  */
> -      if (NOTE_P (insn) && NOTE_KIND (insn) == NOTE_INSN_SWITCH_TEXT_SECTIONS)
> -        {
> -          for (tree s = cur_block; s != DECL_INITIAL (cfun->decl);
> -               s = BLOCK_SUPERCONTEXT (s))
> -            {
> -              rtx_note *note = emit_note_before (NOTE_INSN_BLOCK_END, insn);
> -              NOTE_BLOCK (note) = s;
> -              note = emit_note_after (NOTE_INSN_BLOCK_BEG, insn);
> -              NOTE_BLOCK (note) = s;
> -            }
> -        }
> +      if (NOTE_P (insn))
> +       switch (NOTE_KIND (insn))
> +         {
> +         case NOTE_INSN_SWITCH_TEXT_SECTIONS:
> +           {
> +             for (tree s = cur_block; s != DECL_INITIAL (cfun->decl);
> +                  s = BLOCK_SUPERCONTEXT (s))
> +               {
> +                 rtx_note *note = emit_note_before (NOTE_INSN_BLOCK_END, insn);
> +                 NOTE_BLOCK (note) = s;
> +                 note = emit_note_after (NOTE_INSN_BLOCK_BEG, insn);
> +                 NOTE_BLOCK (note) = s;
> +               }
> +           }
> +           break;
> +
> +         case NOTE_INSN_BEGIN_STMT:
> +         case NOTE_INSN_INLINE_ENTRY:
> +           this_block = LOCATION_BLOCK (NOTE_MARKER_LOCATION (insn));
> +           goto set_cur_block_to_this_block;
> +
> +         default:
> +           continue;
> +       }
>
>        if (!active_insn_p (insn))
>          continue;
> @@ -1692,6 +1706,7 @@ reemit_insn_block_notes (void)
>             this_block = choose_inner_scope (this_block,
>                                              insn_scope (body->insn (i)));
>         }
> +    set_cur_block_to_this_block:
>        if (! this_block)
>         {
>           if (INSN_LOCATION (insn) == UNKNOWN_LOCATION)
> @@ -1708,7 +1723,7 @@ reemit_insn_block_notes (void)
>      }
>
>    /* change_scope emits before the insn, not after.  */
> -  note = emit_note (NOTE_INSN_DELETED);
> +  rtx_note *note = emit_note (NOTE_INSN_DELETED);
>    change_scope (note, cur_block, DECL_INITIAL (cfun->decl));
>    delete_insn (note);
>
> @@ -1747,6 +1762,44 @@ get_some_local_dynamic_name ()
>    return 0;
>  }
>
> +/* Arrange for us to emit a source location note before any further
> +   real insns or section changes, by setting the SEEN_NEXT_VIEW bit in
> +   *SEEN, as long as we are keeping track of location views.  The bit
> +   indicates we have referenced the next view at the current PC, so we
> +   have to emit it.  This should be called next to the var_location
> +   debug hook.  */
> +
> +static inline void
> +set_next_view_needed (int *seen)
> +{
> +  if (debug_variable_location_views)
> +    *seen |= SEEN_NEXT_VIEW;
> +}
> +
> +/* Clear the flag in *SEEN indicating we need to emit the next view.
> +   This should be called next to the source_line debug hook.  */
> +
> +static inline void
> +clear_next_view_needed (int *seen)
> +{
> +  *seen &= ~SEEN_NEXT_VIEW;
> +}
> +
> +/* Test whether we have a pending request to emit the next view in
> +   *SEEN, and emit it if needed, clearing the request bit.  */
> +
> +static inline void
> +maybe_output_next_view (int *seen)
> +{
> +  if ((*seen & SEEN_NEXT_VIEW) != 0)
> +    {
> +      clear_next_view_needed (seen);
> +      (*debug_hooks->source_line) (last_linenum, last_columnnum,
> +                                  last_filename, last_discriminator,
> +                                  false);
> +    }
> +}
> +
>  /* Output assembler code for the start of a function,
>     and initialize some of the variables in this file
>     for the new function.  The label for the function and associated
> @@ -1754,13 +1807,18 @@ get_some_local_dynamic_name ()
>
>     FIRST is the first insn of the rtl for the function being compiled.
>     FILE is the file to write assembler code to.
> +   SEEN should be initially set to zero, and it may be updated to
> +   indicate we have references to the next location view, that would
> +   require us to emit it at the current PC.
>     OPTIMIZE_P is nonzero if we should eliminate redundant
>       test and compare insns.  */
>
> -void
> -final_start_function (rtx_insn *first, FILE *file,
> -                     int optimize_p ATTRIBUTE_UNUSED)
> +static void
> +final_start_function_1 (rtx_insn **firstp, FILE *file, int *seen,
> +                       int optimize_p ATTRIBUTE_UNUSED)
>  {
> +  rtx_insn *first = *firstp;
> +
>    block_depth = 0;
>
>    this_is_asm_operands = 0;
> @@ -1778,7 +1836,28 @@ final_start_function (rtx_insn *first, FILE *file,
>      asan_function_start ();
>
>    if (!DECL_IGNORED_P (current_function_decl))
> -    debug_hooks->begin_prologue (last_linenum, last_columnnum, last_filename);
> +    {
> +      /* Emit param bindings (before the first begin_stmt) in the
> +        initial view.  We don't test whether the DECLs are
> +        PARM_DECLs: the assumption is that there will be a
> +        NOTE_INSN_BEGIN_STMT marker before any non-parameter
> +        NOTE_INSN_VAR_LOCATION.  It's ok if the marker is not there,
> +        we'll just have more variable locations bound in the initial
> +        view, which is consistent with their being bound without any
> +        code that would give them a value.  */
> +      if (debug_variable_location_views)
> +       {
> +         rtx_insn *insn;
> +         for (insn = first;
> +              insn && GET_CODE (insn) == NOTE
> +                && NOTE_KIND (insn) == NOTE_INSN_VAR_LOCATION;
> +              insn = NEXT_INSN (insn))
> +           final_scan_insn (insn, file, 0, 0, seen);
> +         *firstp = insn;
> +       }
> +      debug_hooks->begin_prologue (last_linenum, last_columnnum,
> +                                  last_filename);
> +    }
>
>    if (!dwarf2_debug_info_emitted_p (current_function_decl))
>      dwarf2out_begin_prologue (0, 0, NULL);
> @@ -1853,6 +1932,17 @@ final_start_function (rtx_insn *first, FILE *file,
>      profile_after_prologue (file);
>  }
>
> +/* This is an exported final_start_function_1, callable without SEEN.  */
> +
> +void
> +final_start_function (rtx_insn **firstp, FILE *file,
> +                     int optimize_p ATTRIBUTE_UNUSED)
> +{
> +  int seen = 0;
> +  final_start_function_1 (firstp, file, &seen, optimize_p);
> +  gcc_assert (seen == 0);
> +}
> +
>  static void
>  profile_after_prologue (FILE *file ATTRIBUTE_UNUSED)
>  {
> @@ -1984,11 +2074,10 @@ dump_basic_block_info (FILE *file, rtx_insn *insn, basic_block *start_to_bb,
>  /* Output assembler code for some insns: all or part of a function.
>     For description of args, see `final_start_function', above.  */
>
> -void
> -final (rtx_insn *first, FILE *file, int optimize_p)
> +static void
> +final_1 (rtx_insn *first, FILE *file, int seen, int optimize_p)
>  {
>    rtx_insn *insn, *next;
> -  int seen = 0;
>
>    /* Used for -dA dump.  */
>    basic_block *start_to_bb = NULL;
> @@ -2055,6 +2144,8 @@ final (rtx_insn *first, FILE *file, int optimize_p)
>        insn = final_scan_insn (insn, file, optimize_p, 0, &seen);
>      }
>
> +  maybe_output_next_view (&seen);
> +
>    if (flag_debug_asm)
>      {
>        free (start_to_bb);
> @@ -2071,6 +2162,14 @@ final (rtx_insn *first, FILE *file, int optimize_p)
>         delete_insn (insn);
>      }
>  }
> +
> +/* This is an exported final_1, callable without SEEN.  */
> +
> +void
> +final (rtx_insn *first, FILE *file, int optimize_p)
> +{
> +  final_1 (first, file, 0, optimize_p);
> +}
>
>  const char *
>  get_insn_template (int code, rtx insn)
> @@ -2210,6 +2309,8 @@ final_scan_insn (rtx_insn *insn, FILE *file, int optimize_p ATTRIBUTE_UNUSED,
>           break;
>
>         case NOTE_INSN_SWITCH_TEXT_SECTIONS:
> +         maybe_output_next_view (seen);
> +
>           in_cold_section_p = !in_cold_section_p;
>
>           if (dwarf2out_do_frame ())
> @@ -2350,6 +2451,8 @@ final_scan_insn (rtx_insn *insn, FILE *file, int optimize_p ATTRIBUTE_UNUSED,
>           break;
>
>         case NOTE_INSN_BLOCK_END:
> +         maybe_output_next_view (seen);
> +
>           if (debug_info_level == DINFO_LEVEL_NORMAL
>               || debug_info_level == DINFO_LEVEL_VERBOSE
>               || write_symbols == DWARF2_DEBUG
> @@ -2407,7 +2510,35 @@ final_scan_insn (rtx_insn *insn, FILE *file, int optimize_p ATTRIBUTE_UNUSED,
>         case NOTE_INSN_VAR_LOCATION:
>         case NOTE_INSN_CALL_ARG_LOCATION:
>           if (!DECL_IGNORED_P (current_function_decl))
> -           debug_hooks->var_location (insn);
> +           {
> +             debug_hooks->var_location (insn);
> +             set_next_view_needed (seen);
> +           }
> +         break;
> +
> +       case NOTE_INSN_BEGIN_STMT:
> +         gcc_checking_assert (cfun->debug_nonbind_markers);
> +         if (!DECL_IGNORED_P (current_function_decl)
> +             && notice_source_line (insn, NULL))
> +           {
> +           output_source_line:
> +             (*debug_hooks->source_line) (last_linenum, last_columnnum,
> +                                          last_filename, last_discriminator,
> +                                          true);
> +             clear_next_view_needed (seen);
> +           }
> +         break;
> +
> +       case NOTE_INSN_INLINE_ENTRY:
> +         gcc_checking_assert (cfun->debug_nonbind_markers);
> +         if (!DECL_IGNORED_P (current_function_decl))
> +           {
> +             if (!notice_source_line (insn, NULL))
> +               break;
> +             (*debug_hooks->inline_entry) (LOCATION_BLOCK
> +                                           (NOTE_MARKER_LOCATION (insn)));
> +             goto output_source_line;
> +           }
>           break;
>
>         default:
> @@ -2497,7 +2628,15 @@ final_scan_insn (rtx_insn *insn, FILE *file, int optimize_p ATTRIBUTE_UNUSED,
>         rtx body = PATTERN (insn);
>         int insn_code_number;
>         const char *templ;
> -       bool is_stmt;
> +       bool is_stmt, *is_stmt_p;
> +
> +       if (MAY_HAVE_DEBUG_INSNS && cfun->debug_nonbind_markers)
> +         {
> +           is_stmt = false;
> +           is_stmt_p = NULL;
> +         }
> +       else
> +         is_stmt_p = &is_stmt;
>
>         /* Reset this early so it is correct for ASM statements.  */
>         current_insn_predicate = NULL_RTX;
> @@ -2595,19 +2734,28 @@ final_scan_insn (rtx_insn *insn, FILE *file, int optimize_p ATTRIBUTE_UNUSED,
>
>             switch_to_section (current_function_section ());
>
> +           if (debug_variable_location_views
> +               && !DECL_IGNORED_P (current_function_decl))
> +             debug_hooks->var_location (insn);
> +
>             break;
>           }
>         /* Output this line note if it is the first or the last line
>            note in a row.  */
>         if (!DECL_IGNORED_P (current_function_decl)
> -           && notice_source_line (insn, &is_stmt))
> +           && notice_source_line (insn, is_stmt_p))
>           {
>             if (flag_verbose_asm)
>               asm_show_source (last_filename, last_linenum);
>             (*debug_hooks->source_line) (last_linenum, last_columnnum,
>                                          last_filename, last_discriminator,
>                                          is_stmt);
> +           clear_next_view_needed (seen);
>           }
> +       else
> +         maybe_output_next_view (seen);
> +
> +       gcc_checking_assert (!DEBUG_INSN_P (insn));
>
>         if (GET_CODE (body) == PARALLEL
>             && GET_CODE (XVECEXP (body, 0, 0)) == ASM_INPUT)
> @@ -3074,7 +3222,8 @@ final_scan_insn (rtx_insn *insn, FILE *file, int optimize_p ATTRIBUTE_UNUSED,
>         /* Let the debug info back-end know about this call.  We do this only
>            after the instruction has been emitted because labels that may be
>            created to reference the call instruction must appear after it.  */
> -       if (call_insn != NULL && !DECL_IGNORED_P (current_function_decl))
> +       if ((debug_variable_location_views || call_insn != NULL)
> +           && !DECL_IGNORED_P (current_function_decl))
>           debug_hooks->var_location (insn);
>
>         current_output_insn = debug_insn = 0;
> @@ -3093,7 +3242,26 @@ notice_source_line (rtx_insn *insn, bool *is_stmt)
>    const char *filename;
>    int linenum, columnnum;
>
> -  if (override_filename)
> +  if (NOTE_MARKER_P (insn))
> +    {
> +      expanded_location xloc
> +       = expand_location (NOTE_MARKER_LOCATION (insn));
> +      if (xloc.line == 0)
> +       {
> +         gcc_checking_assert ((UNKNOWN_LOCATION
> +                               == LOCATION_LOCUS (NOTE_MARKER_LOCATION
> +                                                  (insn)))
> +                              || (BUILTINS_LOCATION
> +                                  == LOCATION_LOCUS (NOTE_MARKER_LOCATION
> +                                                     (insn))));
> +         return false;
> +       }
> +      filename = xloc.file;
> +      linenum = xloc.line;
> +      columnnum = xloc.column;
> +      force_source_line = true;
> +    }
> +  else if (override_filename)
>      {
>        filename = override_filename;
>        linenum = override_linenum;
> @@ -3126,7 +3294,8 @@ notice_source_line (rtx_insn *insn, bool *is_stmt)
>        last_linenum = linenum;
>        last_columnnum = columnnum;
>        last_discriminator = discriminator;
> -      *is_stmt = true;
> +      if (is_stmt)
> +       *is_stmt = true;
>        high_block_linenum = MAX (last_linenum, high_block_linenum);
>        high_function_linenum = MAX (last_linenum, high_function_linenum);
>        return true;
> @@ -3138,7 +3307,8 @@ notice_source_line (rtx_insn *insn, bool *is_stmt)
>           output the line table entry with is_stmt false so the
>           debugger does not treat this as a breakpoint location.  */
>        last_discriminator = discriminator;
> -      *is_stmt = false;
> +      if (is_stmt)
> +       *is_stmt = false;
>        return true;
>      }
>
> @@ -4491,9 +4661,15 @@ rest_of_handle_final (void)
>  {
>    const char *fnname = get_fnname_from_decl (current_function_decl);
>
> +  /* Turn debug markers into notes.  */
> +  if (!flag_var_tracking && MAY_HAVE_DEBUG_INSNS)
> +    variable_tracking_main ();
> +
>    assemble_start_function (current_function_decl, fnname);
> -  final_start_function (get_insns (), asm_out_file, optimize);
> -  final (get_insns (), asm_out_file, optimize);
> +  rtx_insn *first = get_insns ();
> +  int seen = 0;
> +  final_start_function_1 (&first, asm_out_file, &seen, optimize);
> +  final_1 (first, asm_out_file, seen, optimize);
>    if (flag_ipa_ra
>        && !lookup_attribute ("noipa", DECL_ATTRIBUTES (current_function_decl)))
>      collect_fn_hard_reg_usage ();
> @@ -4678,6 +4854,8 @@ rest_of_clean_state (void)
>        if (final_output
>           && (!NOTE_P (insn) ||
>               (NOTE_KIND (insn) != NOTE_INSN_VAR_LOCATION
> +              && NOTE_KIND (insn) != NOTE_INSN_BEGIN_STMT
> +              && NOTE_KIND (insn) != NOTE_INSN_INLINE_ENTRY
>                && NOTE_KIND (insn) != NOTE_INSN_CALL_ARG_LOCATION
>                && NOTE_KIND (insn) != NOTE_INSN_BLOCK_BEG
>                && NOTE_KIND (insn) != NOTE_INSN_BLOCK_END
> diff --git a/gcc/function.c b/gcc/function.c
> index 20c287b..8de335e 100644
> --- a/gcc/function.c
> +++ b/gcc/function.c
> @@ -1951,10 +1951,11 @@ instantiate_virtual_regs (void)
>            Fortunately, they shouldn't contain virtual registers either.  */
>          if (GET_CODE (PATTERN (insn)) == USE
>             || GET_CODE (PATTERN (insn)) == CLOBBER
> -           || GET_CODE (PATTERN (insn)) == ASM_INPUT)
> +           || GET_CODE (PATTERN (insn)) == ASM_INPUT
> +           || MARKER_DEBUG_INSN_P (insn))
>           continue;
> -       else if (DEBUG_INSN_P (insn))
> -         instantiate_virtual_regs_in_rtx (&INSN_VAR_LOCATION (insn));
> +       else if (BIND_DEBUG_INSN_P (insn))
> +         instantiate_virtual_regs_in_rtx (INSN_VAR_LOCATION_PTR (insn));
>         else
>           instantiate_virtual_regs_in_insn (insn);
>
> @@ -4940,6 +4941,12 @@ allocate_struct_function (tree fndecl, bool abstract_p)
>        if (!profile_flag && !flag_instrument_function_entry_exit)
>         DECL_NO_INSTRUMENT_FUNCTION_ENTRY_EXIT (fndecl) = 1;
>      }
> +
> +  /* Don't enable begin stmt markers if var-tracking at assignments is
> +     disabled.  The markers make little sense without the variable
> +     binding annotations among them.  */
> +  cfun->debug_nonbind_markers = lang_hooks.emits_begin_stmt
> +    && debug_nonbind_markers_p && MAY_HAVE_DEBUG_STMTS;
>  }
>
>  /* This is like allocate_struct_function, but pushes a new cfun for FNDECL
> diff --git a/gcc/function.h b/gcc/function.h
> index 0f34bcd..2c2e622 100644
> --- a/gcc/function.h
> +++ b/gcc/function.h
> @@ -284,6 +284,12 @@ struct GTY(()) function {
>    /* Last statement uid.  */
>    int last_stmt_uid;
>
> +  /* Debug marker counter.  Count begin stmt markers.  We don't have
> +     to keep it exact, it's more of a rough estimate to enable us to
> +     decide whether they are too many to copy during inlining, or when
> +     expanding to RTL.  */
> +  int debug_marker_count;
> +
>    /* Function sequence number for profiling, debugging, etc.  */
>    int funcdef_no;
>
> @@ -387,6 +393,10 @@ struct GTY(()) function {
>
>    /* Set when the tail call has been identified.  */
>    unsigned int tail_call_marked : 1;
> +
> +  /* Set when the function was compiled with generation of debug
> +     (begin stmt, inline entry, ...) markers enabled.  */
> +  unsigned int debug_nonbind_markers : 1;
>  };
>
>  /* Add the decl D to the local_decls list of FUN.  */
> diff --git a/gcc/gimple-iterator.c b/gcc/gimple-iterator.c
> index 3b74cc5..f0d96f9 100644
> --- a/gcc/gimple-iterator.c
> +++ b/gcc/gimple-iterator.c
> @@ -573,6 +573,8 @@ gsi_remove (gimple_stmt_iterator *i, bool remove_permanently)
>
>    if (remove_permanently)
>      {
> +      if (gimple_debug_nonbind_marker_p (stmt))
> +       cfun->debug_marker_count--;
>        require_eh_edge_purge = remove_stmt_from_eh_lp (stmt);
>        gimple_remove_stmt_histograms (cfun, stmt);
>      }
> @@ -744,9 +746,13 @@ gimple_find_edge_insert_loc (edge e, gimple_stmt_iterator *gsi,
>        if (gsi_end_p (*gsi))
>         return true;
>
> -      /* Make sure we insert after any leading labels.  */
> +      /* Make sure we insert after any leading labels.  We have to
> +        skip debug stmts before or among them, though.  We didn't
> +        have to skip debug stmts after the last label, but it
> +        shouldn't hurt if we do.  */
>        tmp = gsi_stmt (*gsi);
> -      while (gimple_code (tmp) == GIMPLE_LABEL)
> +      while (gimple_code (tmp) == GIMPLE_LABEL
> +            || is_gimple_debug (tmp))
>         {
>           gsi_next (gsi);
>           if (gsi_end_p (*gsi))
> @@ -776,7 +782,21 @@ gimple_find_edge_insert_loc (edge e, gimple_stmt_iterator *gsi,
>         return true;
>
>        tmp = gsi_stmt (*gsi);
> -      if (!stmt_ends_bb_p (tmp))
> +      if (is_gimple_debug (tmp))
> +       {
> +         gimple_stmt_iterator si = *gsi;
> +         gsi_prev_nondebug (&si);
> +         if (!gsi_end_p (si))
> +           tmp = gsi_stmt (si);
> +         /* If we don't have a BB-ending nondebug stmt, we want to
> +            insert after the trailing debug stmts.  Otherwise, we may
> +            insert before the BB-ending nondebug stmt, or split the
> +            edge.  */
> +         if (!stmt_ends_bb_p (tmp))
> +           return true;
> +         *gsi = si;
> +       }
> +      else if (!stmt_ends_bb_p (tmp))
>         return true;
>
>        switch (gimple_code (tmp))
> diff --git a/gcc/gimple-iterator.h b/gcc/gimple-iterator.h
> index 70f18be..167edc1 100644
> --- a/gcc/gimple-iterator.h
> +++ b/gcc/gimple-iterator.h
> @@ -212,29 +212,28 @@ gsi_stmt (gimple_stmt_iterator i)
>    return i.ptr;
>  }
>
> -/* Return a new iterator pointing to the first non-debug statement
> -   in basic block BB.  */
> -
> -static inline gimple_stmt_iterator
> -gsi_start_bb_nondebug (basic_block bb)
> -{
> -  gimple_stmt_iterator gsi = gsi_start_bb (bb);
> -  while (!gsi_end_p (gsi) && is_gimple_debug (gsi_stmt (gsi)))
> -    gsi_next (&gsi);
> -
> -  return gsi;
> -}
> -
> -/* Return a block statement iterator that points to the first non-label
> -   statement in block BB.  */
> +/* Return a block statement iterator that points to the first
> +   non-label statement in block BB.  Skip debug stmts only if they
> +   precede labels.  */
>
>  static inline gimple_stmt_iterator
>  gsi_after_labels (basic_block bb)
>  {
>    gimple_stmt_iterator gsi = gsi_start_bb (bb);
>
> -  while (!gsi_end_p (gsi) && gimple_code (gsi_stmt (gsi)) == GIMPLE_LABEL)
> -    gsi_next (&gsi);
> +  for (gimple_stmt_iterator gskip = gsi;
> +       !gsi_end_p (gskip); )
> +    {
> +      if (is_gimple_debug (gsi_stmt (gskip)))
> +       gsi_next (&gskip);
> +      else if (gimple_code (gsi_stmt (gskip)) == GIMPLE_LABEL)
> +       {
> +         gsi_next (&gskip);
> +         gsi = gskip;
> +       }
> +      else
> +       break;
> +    }
>
>    return gsi;
>  }
> @@ -264,6 +263,19 @@ gsi_prev_nondebug (gimple_stmt_iterator *i)
>  }
>
>  /* Return a new iterator pointing to the first non-debug statement in
> +   SEQ.  */
> +
> +static inline gimple_stmt_iterator
> +gsi_start_nondebug (gimple_seq seq)
> +{
> +  gimple_stmt_iterator gsi = gsi_start (seq);
> +  if (!gsi_end_p (gsi) && is_gimple_debug (gsi_stmt (gsi)))
> +    gsi_next_nondebug (&gsi);
> +
> +  return gsi;
> +}
> +
> +/* Return a new iterator pointing to the first non-debug statement in
>     basic block BB.  */
>
>  static inline gimple_stmt_iterator
> diff --git a/gcc/gimple-low.c b/gcc/gimple-low.c
> index 4ea6c35..d74a33f6b 100644
> --- a/gcc/gimple-low.c
> +++ b/gcc/gimple-low.c
> @@ -110,6 +110,17 @@ lower_function_body (void)
>
>    i = gsi_last (lowered_body);
>
> +  /* If we had begin stmt markers from e.g. PCH, but this compilation
> +     doesn't want them, lower_stmt will have cleaned them up; we can
> +     now clear the flag that indicates we had them.  */
> +  if (!MAY_HAVE_DEBUG_STMTS && cfun->debug_nonbind_markers)
> +    {
> +      /* This counter needs not be exact, but before lowering it will
> +        most certainly be.  */
> +      gcc_assert (cfun->debug_marker_count == 0);
> +      cfun->debug_nonbind_markers = false;
> +    }
> +
>    /* If the function falls off the end, we need a null return statement.
>       If we've already got one in the return_statements vector, we don't
>       need to do anything special.  Otherwise build one by hand.  */
> @@ -296,6 +307,17 @@ lower_stmt (gimple_stmt_iterator *gsi, struct lower_data *data)
>        }
>        break;
>
> +    case GIMPLE_DEBUG:
> +      gcc_checking_assert (cfun->debug_nonbind_markers);
> +      /* 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_STMTS)
> +       gsi_remove (gsi, true);
> +      else
> +       gsi_next (gsi);
> +      return;
> +
>      case GIMPLE_NOP:
>      case GIMPLE_ASM:
>      case GIMPLE_ASSIGN:
> @@ -503,6 +525,10 @@ lower_try_catch (gimple_stmt_iterator *gsi, struct lower_data *data)
>         cannot_fallthru = false;
>        break;
>
> +    case GIMPLE_DEBUG:
> +      gcc_checking_assert (gimple_debug_begin_stmt_p (stmt));
> +      break;
> +
>      default:
>        /* This case represents statements to be executed when an
>          exception occurs.  Those statements are implicitly followed
> @@ -645,7 +671,7 @@ gimple_stmt_may_fallthru (gimple *stmt)
>  bool
>  gimple_seq_may_fallthru (gimple_seq seq)
>  {
> -  return gimple_stmt_may_fallthru (gimple_seq_last_stmt (seq));
> +  return gimple_stmt_may_fallthru (gimple_seq_last_nondebug_stmt (seq));
>  }
>
>
> diff --git a/gcc/gimple-pretty-print.c b/gcc/gimple-pretty-print.c
> index ed8e51c..7c9c754 100644
> --- a/gcc/gimple-pretty-print.c
> +++ b/gcc/gimple-pretty-print.c
> @@ -1370,6 +1370,26 @@ dump_gimple_debug (pretty_printer *buffer, gdebug *gs, int spc,
>                          gimple_debug_source_bind_get_value (gs));
>        break;
>
> +    case GIMPLE_DEBUG_BEGIN_STMT:
> +      if (flags & TDF_RAW)
> +       dump_gimple_fmt (buffer, spc, flags, "%G BEGIN_STMT", gs);
> +      else
> +       dump_gimple_fmt (buffer, spc, flags, "# DEBUG BEGIN_STMT");
> +      break;
> +
> +    case GIMPLE_DEBUG_INLINE_ENTRY:
> +      if (flags & TDF_RAW)
> +       dump_gimple_fmt (buffer, spc, flags, "%G INLINE_ENTRY %T", gs,
> +                        gimple_block (gs)
> +                        ? block_ultimate_origin (gimple_block (gs))
> +                        : NULL_TREE);
> +      else
> +       dump_gimple_fmt (buffer, spc, flags, "# DEBUG INLINE_ENTRY %T",
> +                        gimple_block (gs)
> +                        ? block_ultimate_origin (gimple_block (gs))
> +                        : NULL_TREE);
> +      break;
> +
>      default:
>        gcc_unreachable ();
>      }
> diff --git a/gcc/gimple.c b/gcc/gimple.c
> index c4e6f81..71ff292 100644
> --- a/gcc/gimple.c
> +++ b/gcc/gimple.c
> @@ -836,6 +836,48 @@ gimple_build_debug_source_bind (tree var, tree value,
>  }
>
>
> +/* Build a new GIMPLE_DEBUG_BEGIN_STMT statement in BLOCK at
> +   LOCATION.  */
> +
> +gdebug *
> +gimple_build_debug_begin_stmt (tree block, location_t location
> +                                   MEM_STAT_DECL)
> +{
> +  gdebug *p
> +    = as_a <gdebug *> (
> +        gimple_build_with_ops_stat (GIMPLE_DEBUG,
> +                                   (unsigned)GIMPLE_DEBUG_BEGIN_STMT, 0
> +                                   PASS_MEM_STAT));
> +
> +  gimple_set_location (p, location);
> +  gimple_set_block (p, block);
> +  cfun->debug_marker_count++;
> +
> +  return p;
> +}
> +
> +
> +/* Build a new GIMPLE_DEBUG_INLINE_ENTRY statement in BLOCK at
> +   LOCATION.  The BLOCK links to the inlined function.  */
> +
> +gdebug *
> +gimple_build_debug_inline_entry (tree block, location_t location
> +                                     MEM_STAT_DECL)
> +{
> +  gdebug *p
> +    = as_a <gdebug *> (
> +        gimple_build_with_ops_stat (GIMPLE_DEBUG,
> +                                   (unsigned)GIMPLE_DEBUG_INLINE_ENTRY, 0
> +                                   PASS_MEM_STAT));
> +
> +  gimple_set_location (p, location);
> +  gimple_set_block (p, block);
> +  cfun->debug_marker_count++;
> +
> +  return p;
> +}
> +
> +
>  /* Build a GIMPLE_OMP_CRITICAL statement.
>
>     BODY is the sequence of statements for which only one thread can execute.
> @@ -1874,6 +1916,9 @@ gimple_copy (gimple *stmt)
>        gimple_set_modified (copy, true);
>      }
>
> +  if (gimple_debug_begin_stmt_p (stmt))
> +    cfun->debug_marker_count++;
> +
>    return copy;
>  }
>
> diff --git a/gcc/gimple.h b/gcc/gimple.h
> index 6213c49..909807f 100644
> --- a/gcc/gimple.h
> +++ b/gcc/gimple.h
> @@ -198,13 +198,13 @@ enum gf_mask {
>      GF_PREDICT_TAKEN           = 1 << 15
>  };
>
> -/* Currently, there are only two types of gimple debug stmt.  Others are
> -   envisioned, for example, to enable the generation of is_stmt notes
> -   in line number information, to mark sequence points, etc.  This
> -   subcode is to be used to tell them apart.  */
> +/* This subcode tells apart different kinds of stmts that are not used
> +   for codegen, but rather to retain debug information.  */
>  enum gimple_debug_subcode {
>    GIMPLE_DEBUG_BIND = 0,
> -  GIMPLE_DEBUG_SOURCE_BIND = 1
> +  GIMPLE_DEBUG_SOURCE_BIND = 1,
> +  GIMPLE_DEBUG_BEGIN_STMT = 2,
> +  GIMPLE_DEBUG_INLINE_ENTRY = 3
>  };
>
>  /* Masks for selecting a pass local flag (PLF) to work on.  These
> @@ -1455,6 +1455,8 @@ gswitch *gimple_build_switch (tree, tree, vec<tree> );
>  geh_dispatch *gimple_build_eh_dispatch (int);
>  gdebug *gimple_build_debug_bind (tree, tree, gimple * CXX_MEM_STAT_INFO);
>  gdebug *gimple_build_debug_source_bind (tree, tree, gimple * CXX_MEM_STAT_INFO);
> +gdebug *gimple_build_debug_begin_stmt (tree, location_t CXX_MEM_STAT_INFO);
> +gdebug *gimple_build_debug_inline_entry (tree, location_t CXX_MEM_STAT_INFO);
>  gomp_critical *gimple_build_omp_critical (gimple_seq, tree, tree);
>  gomp_for *gimple_build_omp_for (gimple_seq, int, tree, size_t, gimple_seq);
>  gomp_parallel *gimple_build_omp_parallel (gimple_seq, tree, tree, tree);
> @@ -4583,6 +4585,22 @@ is_gimple_debug (const gimple *gs)
>    return gimple_code (gs) == GIMPLE_DEBUG;
>  }
>
> +
> +/* Return the last nondebug statement in GIMPLE sequence S.  */
> +
> +static inline gimple *
> +gimple_seq_last_nondebug_stmt (gimple_seq s)
> +{
> +  gimple_seq_node n;
> +  for (n = gimple_seq_last (s);
> +       n && is_gimple_debug (n);
> +       n = n->prev)
> +    if (n->prev == s)
> +      return NULL;
> +  return n;
> +}
> +
> +
>  /* Return true if S is a GIMPLE_DEBUG BIND statement.  */
>
>  static inline bool
> @@ -4739,6 +4757,40 @@ gimple_debug_source_bind_set_value (gimple *dbg, tree value)
>    gimple_set_op (dbg, 1, value);
>  }
>
> +/* Return true if S is a GIMPLE_DEBUG BEGIN_STMT statement.  */
> +
> +static inline bool
> +gimple_debug_begin_stmt_p (const gimple *s)
> +{
> +  if (is_gimple_debug (s))
> +    return s->subcode == GIMPLE_DEBUG_BEGIN_STMT;
> +
> +  return false;
> +}
> +
> +/* Return true if S is a GIMPLE_DEBUG INLINE_ENTRY statement.  */
> +
> +static inline bool
> +gimple_debug_inline_entry_p (const gimple *s)
> +{
> +  if (is_gimple_debug (s))
> +    return s->subcode == GIMPLE_DEBUG_INLINE_ENTRY;
> +
> +  return false;
> +}
> +
> +/* Return true if S is a GIMPLE_DEBUG non-binding marker statement.  */
> +
> +static inline bool
> +gimple_debug_nonbind_marker_p (const gimple *s)
> +{
> +  if (is_gimple_debug (s))
> +    return s->subcode == GIMPLE_DEBUG_BEGIN_STMT
> +      || s->subcode == GIMPLE_DEBUG_INLINE_ENTRY;
> +
> +  return false;
> +}
> +
>  /* Return the line number for EXPR, or return -1 if we have no line
>     number information for it.  */
>  static inline int
> diff --git a/gcc/gimplify.c b/gcc/gimplify.c
> index 86623e0..9acb4c2 100644
> --- a/gcc/gimplify.c
> +++ b/gcc/gimplify.c
> @@ -982,6 +982,48 @@ unshare_expr_without_location (tree expr)
>      walk_tree (&expr, prune_expr_location, NULL, NULL);
>    return expr;
>  }
> +
> +/* Return the EXPR_LOCATION of EXPR, if it (maybe recursively) has
> +   one, OR_ELSE otherwise.  The location of a STATEMENT_LISTs
> +   comprising at least one DEBUG_BEGIN_STMT followed by exactly one
> +   EXPR is the location of the EXPR.  */
> +
> +static location_t
> +expr_location (tree expr, location_t or_else = UNKNOWN_LOCATION)
> +{
> +  if (!expr)
> +    return or_else;
> +
> +  if (EXPR_HAS_LOCATION (expr))
> +    return EXPR_LOCATION (expr);
> +
> +  if (TREE_CODE (expr) != STATEMENT_LIST)
> +    return or_else;
> +
> +  tree_stmt_iterator i = tsi_start (expr);
> +
> +  bool found = false;
> +  while (!tsi_end_p (i) && TREE_CODE (tsi_stmt (i)) == DEBUG_BEGIN_STMT)
> +    {
> +      found = true;
> +      tsi_next (&i);
> +    }
> +
> +  if (!found || !tsi_one_before_end_p (i))
> +    return or_else;
> +
> +  return expr_location (tsi_stmt (i), or_else);
> +}
> +
> +/* Return TRUE iff EXPR (maybe recursively) has a location; see
> +   expr_location for the potential recursion.  */
> +
> +static inline bool
> +expr_has_location (tree expr)
> +{
> +  return expr_location (expr) != UNKNOWN_LOCATION;
> +}
> +
>
>  /* WRAPPER is a code such as BIND_EXPR or CLEANUP_POINT_EXPR which can both
>     contain statements and have a value.  Assign its value to a temporary
> @@ -1772,6 +1814,13 @@ warn_switch_unreachable_r (gimple_stmt_iterator *gsi_p, bool *handled_ops_p,
>        /* Walk the sub-statements.  */
>        *handled_ops_p = false;
>        break;
> +
> +    case GIMPLE_DEBUG:
> +      /* Ignore these.  We may generate them before declarations that
> +        are never executed.  If there's something to warn about,
> +        there will be non-debug stmts too, and we'll catch those.  */
> +      break;
> +
>      case GIMPLE_CALL:
>        if (gimple_call_internal_p (stmt, IFN_ASAN_MARK))
>         {
> @@ -1855,7 +1904,7 @@ case_label_p (const vec<tree> *cases, tree label)
>    return false;
>  }
>
> -/* Find the last statement in a scope STMT.  */
> +/* Find the last nondebug statement in a scope STMT.  */
>
>  static gimple *
>  last_stmt_in_scope (gimple *stmt)
> @@ -1868,27 +1917,30 @@ last_stmt_in_scope (gimple *stmt)
>      case GIMPLE_BIND:
>        {
>         gbind *bind = as_a <gbind *> (stmt);
> -       stmt = gimple_seq_last_stmt (gimple_bind_body (bind));
> +       stmt = gimple_seq_last_nondebug_stmt (gimple_bind_body (bind));
>         return last_stmt_in_scope (stmt);
>        }
>
>      case GIMPLE_TRY:
>        {
>         gtry *try_stmt = as_a <gtry *> (stmt);
> -       stmt = gimple_seq_last_stmt (gimple_try_eval (try_stmt));
> +       stmt = gimple_seq_last_nondebug_stmt (gimple_try_eval (try_stmt));
>         gimple *last_eval = last_stmt_in_scope (stmt);
>         if (gimple_stmt_may_fallthru (last_eval)
>             && (last_eval == NULL
>                 || !gimple_call_internal_p (last_eval, IFN_FALLTHROUGH))
>             && gimple_try_kind (try_stmt) == GIMPLE_TRY_FINALLY)
>           {
> -           stmt = gimple_seq_last_stmt (gimple_try_cleanup (try_stmt));
> +           stmt = gimple_seq_last_nondebug_stmt (gimple_try_cleanup (try_stmt));
>             return last_stmt_in_scope (stmt);
>           }
>         else
>           return last_eval;
>        }
>
> +    case GIMPLE_DEBUG:
> +      gcc_unreachable ();
> +
>      default:
>        return stmt;
>      }
> @@ -1992,7 +2044,7 @@ collect_fallthrough_labels (gimple_stmt_iterator *gsi_p,
>         }
>        else if (gimple_call_internal_p (gsi_stmt (*gsi_p), IFN_ASAN_MARK))
>         ;
> -      else
> +      else if (!is_gimple_debug (gsi_stmt (*gsi_p)))
>         prev = gsi_stmt (*gsi_p);
>        gsi_next (gsi_p);
>      }
> @@ -2029,7 +2081,7 @@ should_warn_for_implicit_fallthrough (gimple_stmt_iterator *gsi_p, tree label)
>              && gimple_code (gsi_stmt (gsi)) == GIMPLE_LABEL
>              && (l = gimple_label_label (as_a <glabel *> (gsi_stmt (gsi))))
>              && !case_label_p (&gimplify_ctxp->case_labels, l))
> -       gsi_next (&gsi);
> +       gsi_next_nondebug (&gsi);
>        if (gsi_end_p (gsi) || gimple_code (gsi_stmt (gsi)) != GIMPLE_LABEL)
>         return false;
>      }
> @@ -2042,7 +2094,7 @@ should_warn_for_implicit_fallthrough (gimple_stmt_iterator *gsi_p, tree label)
>    while (!gsi_end_p (gsi)
>          && (gimple_code (gsi_stmt (gsi)) == GIMPLE_LABEL
>              || gimple_code (gsi_stmt (gsi)) == GIMPLE_PREDICT))
> -    gsi_next (&gsi);
> +    gsi_next_nondebug (&gsi);
>
>    /* { ... something; default:; } */
>    if (gsi_end_p (gsi)
> @@ -2089,7 +2141,7 @@ warn_implicit_fallthrough_r (gimple_stmt_iterator *gsi_p, bool *handled_ops_p,
>         /* Found a label.  Skip all immediately following labels.  */
>         while (!gsi_end_p (*gsi_p)
>                && gimple_code (gsi_stmt (*gsi_p)) == GIMPLE_LABEL)
> -         gsi_next (gsi_p);
> +         gsi_next_nondebug (gsi_p);
>
>         /* There might be no more statements.  */
>         if (gsi_end_p (*gsi_p))
> @@ -2230,7 +2282,7 @@ expand_FALLTHROUGH_r (gimple_stmt_iterator *gsi_p, bool *handled_ops_p,
>                       break;
>                     }
>                 }
> -             else
> +             else if (!is_gimple_debug (stmt))
>                 /* Something other than a label.  That's not expected.  */
>                 break;
>               gsi_next (&gsi2);
> @@ -3437,7 +3489,7 @@ shortcut_cond_r (tree pred, tree *true_label_p, tree *false_label_p,
>        append_to_statement_list (t, &expr);
>
>        /* Set the source location of the && on the second 'if'.  */
> -      new_locus = EXPR_HAS_LOCATION (pred) ? EXPR_LOCATION (pred) : locus;
> +      new_locus = expr_location (pred, locus);
>        t = shortcut_cond_r (TREE_OPERAND (pred, 1), true_label_p, false_label_p,
>                            new_locus);
>        append_to_statement_list (t, &expr);
> @@ -3460,7 +3512,7 @@ shortcut_cond_r (tree pred, tree *true_label_p, tree *false_label_p,
>        append_to_statement_list (t, &expr);
>
>        /* Set the source location of the || on the second 'if'.  */
> -      new_locus = EXPR_HAS_LOCATION (pred) ? EXPR_LOCATION (pred) : locus;
> +      new_locus = expr_location (pred, locus);
>        t = shortcut_cond_r (TREE_OPERAND (pred, 1), true_label_p, false_label_p,
>                            new_locus);
>        append_to_statement_list (t, &expr);
> @@ -3482,7 +3534,7 @@ shortcut_cond_r (tree pred, tree *true_label_p, tree *false_label_p,
>
>        /* Keep the original source location on the first 'if'.  Set the source
>          location of the ? on the second 'if'.  */
> -      new_locus = EXPR_HAS_LOCATION (pred) ? EXPR_LOCATION (pred) : locus;
> +      new_locus = expr_location (pred, locus);
>        expr = build3 (COND_EXPR, void_type_node, TREE_OPERAND (pred, 0),
>                      shortcut_cond_r (TREE_OPERAND (pred, 1), true_label_p,
>                                       false_label_p, locus),
> @@ -3506,6 +3558,45 @@ shortcut_cond_r (tree pred, tree *true_label_p, tree *false_label_p,
>    return expr;
>  }
>
> +/* If EXPR is a GOTO_EXPR, return it.  If it is a STATEMENT_LIST, skip
> +   any of its leading DEBUG_BEGIN_STMTS and recurse on the subsequent
> +   statement, if it is the last one.  Otherwise, return NULL.  */
> +
> +static tree
> +find_goto (tree expr)
> +{
> +  if (!expr)
> +    return NULL_TREE;
> +
> +  if (TREE_CODE (expr) == GOTO_EXPR)
> +    return expr;
> +
> +  if (TREE_CODE (expr) != STATEMENT_LIST)
> +    return NULL_TREE;
> +
> +  tree_stmt_iterator i = tsi_start (expr);
> +
> +  while (!tsi_end_p (i) && TREE_CODE (tsi_stmt (i)) == DEBUG_BEGIN_STMT)
> +    tsi_next (&i);
> +
> +  if (!tsi_one_before_end_p (i))
> +    return NULL_TREE;
> +
> +  return find_goto (tsi_stmt (i));
> +}
> +
> +/* Same as find_goto, except that it returns NULL if the destination
> +   is not a LABEL_DECL.  */
> +
> +static inline tree
> +find_goto_label (tree expr)
> +{
> +  tree dest = find_goto (expr);
> +  if (dest && TREE_CODE (GOTO_DESTINATION (dest)) == LABEL_DECL)
> +    return dest;
> +  return NULL_TREE;
> +}
> +
>  /* Given a conditional expression EXPR with short-circuit boolean
>     predicates using TRUTH_ANDIF_EXPR or TRUTH_ORIF_EXPR, break the
>     predicate apart into the equivalent sequence of conditionals.  */
> @@ -3536,8 +3627,8 @@ shortcut_cond_expr (tree expr)
>           location_t locus = EXPR_LOC_OR_LOC (expr, input_location);
>           TREE_OPERAND (expr, 0) = TREE_OPERAND (pred, 1);
>           /* Set the source location of the && on the second 'if'.  */
> -         if (EXPR_HAS_LOCATION (pred))
> -           SET_EXPR_LOCATION (expr, EXPR_LOCATION (pred));
> +         if (expr_has_location (pred))
> +           SET_EXPR_LOCATION (expr, expr_location (pred));
>           then_ = shortcut_cond_expr (expr);
>           then_se = then_ && TREE_SIDE_EFFECTS (then_);
>           pred = TREE_OPERAND (pred, 0);
> @@ -3558,8 +3649,8 @@ shortcut_cond_expr (tree expr)
>           location_t locus = EXPR_LOC_OR_LOC (expr, input_location);
>           TREE_OPERAND (expr, 0) = TREE_OPERAND (pred, 1);
>           /* Set the source location of the || on the second 'if'.  */
> -         if (EXPR_HAS_LOCATION (pred))
> -           SET_EXPR_LOCATION (expr, EXPR_LOCATION (pred));
> +         if (expr_has_location (pred))
> +           SET_EXPR_LOCATION (expr, expr_location (pred));
>           else_ = shortcut_cond_expr (expr);
>           else_se = else_ && TREE_SIDE_EFFECTS (else_);
>           pred = TREE_OPERAND (pred, 0);
> @@ -3586,20 +3677,16 @@ shortcut_cond_expr (tree expr)
>    /* If our arms just jump somewhere, hijack those labels so we don't
>       generate jumps to jumps.  */
>
> -  if (then_
> -      && TREE_CODE (then_) == GOTO_EXPR
> -      && TREE_CODE (GOTO_DESTINATION (then_)) == LABEL_DECL)
> +  if (tree then_goto = find_goto_label (then_))
>      {
> -      true_label = GOTO_DESTINATION (then_);
> +      true_label = GOTO_DESTINATION (then_goto);
>        then_ = NULL;
>        then_se = false;
>      }
>
> -  if (else_
> -      && TREE_CODE (else_) == GOTO_EXPR
> -      && TREE_CODE (GOTO_DESTINATION (else_)) == LABEL_DECL)
> +  if (tree else_goto = find_goto_label (else_))
>      {
> -      false_label = GOTO_DESTINATION (else_);
> +      false_label = GOTO_DESTINATION (else_goto);
>        else_ = NULL;
>        else_se = false;
>      }
> @@ -3663,8 +3750,8 @@ shortcut_cond_expr (tree expr)
>         {
>           tree last = expr_last (expr);
>           t = build_and_jump (&end_label);
> -         if (EXPR_HAS_LOCATION (last))
> -           SET_EXPR_LOCATION (t, EXPR_LOCATION (last));
> +         if (expr_has_location (last))
> +           SET_EXPR_LOCATION (t, expr_location (last));
>           append_to_statement_list (t, &expr);
>         }
>        if (emit_false)
> @@ -3957,39 +4044,35 @@ gimplify_cond_expr (tree *expr_p, gimple_seq *pre_p, fallback_t fallback)
>    gimple_push_condition ();
>
>    have_then_clause_p = have_else_clause_p = false;
> -  if (TREE_OPERAND (expr, 1) != NULL
> -      && TREE_CODE (TREE_OPERAND (expr, 1)) == GOTO_EXPR
> -      && TREE_CODE (GOTO_DESTINATION (TREE_OPERAND (expr, 1))) == LABEL_DECL
> -      && (DECL_CONTEXT (GOTO_DESTINATION (TREE_OPERAND (expr, 1)))
> -         == current_function_decl)
> +  label_true = find_goto_label (TREE_OPERAND (expr, 1));
> +  if (label_true
> +      && DECL_CONTEXT (GOTO_DESTINATION (label_true)) == current_function_decl
>        /* For -O0 avoid this optimization if the COND_EXPR and GOTO_EXPR
>          have different locations, otherwise we end up with incorrect
>          location information on the branches.  */
>        && (optimize
>           || !EXPR_HAS_LOCATION (expr)
> -         || !EXPR_HAS_LOCATION (TREE_OPERAND (expr, 1))
> -         || EXPR_LOCATION (expr) == EXPR_LOCATION (TREE_OPERAND (expr, 1))))
> +         || !expr_has_location (label_true)
> +         || EXPR_LOCATION (expr) == expr_location (label_true)))
>      {
> -      label_true = GOTO_DESTINATION (TREE_OPERAND (expr, 1));
>        have_then_clause_p = true;
> +      label_true = GOTO_DESTINATION (label_true);
>      }
>    else
>      label_true = create_artificial_label (UNKNOWN_LOCATION);
> -  if (TREE_OPERAND (expr, 2) != NULL
> -      && TREE_CODE (TREE_OPERAND (expr, 2)) == GOTO_EXPR
> -      && TREE_CODE (GOTO_DESTINATION (TREE_OPERAND (expr, 2))) == LABEL_DECL
> -      && (DECL_CONTEXT (GOTO_DESTINATION (TREE_OPERAND (expr, 2)))
> -         == current_function_decl)
> +  label_false = find_goto_label (TREE_OPERAND (expr, 2));
> +  if (label_false
> +      && DECL_CONTEXT (GOTO_DESTINATION (label_false)) == current_function_decl
>        /* For -O0 avoid this optimization if the COND_EXPR and GOTO_EXPR
>          have different locations, otherwise we end up with incorrect
>          location information on the branches.  */
>        && (optimize
>           || !EXPR_HAS_LOCATION (expr)
> -         || !EXPR_HAS_LOCATION (TREE_OPERAND (expr, 2))
> -         || EXPR_LOCATION (expr) == EXPR_LOCATION (TREE_OPERAND (expr, 2))))
> +         || !expr_has_location (label_false)
> +         || EXPR_LOCATION (expr) == expr_location (label_false)))
>      {
> -      label_false = GOTO_DESTINATION (TREE_OPERAND (expr, 2));
>        have_else_clause_p = true;
> +      label_false = GOTO_DESTINATION (label_false);
>      }
>    else
>      label_false = create_artificial_label (UNKNOWN_LOCATION);
> @@ -11779,6 +11862,18 @@ gimplify_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p,
>           ret = GS_ALL_DONE;
>           break;
>
> +       case DEBUG_EXPR_DECL:
> +         gcc_unreachable ();
> +
> +       case DEBUG_BEGIN_STMT:
> +         gimplify_seq_add_stmt (pre_p,
> +                                gimple_build_debug_begin_stmt
> +                                (TREE_BLOCK (*expr_p),
> +                                 EXPR_LOCATION (*expr_p)));
> +         ret = GS_ALL_DONE;
> +         *expr_p = NULL;
> +         break;
> +
>         case SSA_NAME:
>           /* Allow callbacks into the gimplifier during optimization.  */
>           ret = GS_ALL_DONE;
> diff --git a/gcc/graphite-isl-ast-to-gimple.c b/gcc/graphite-isl-ast-to-gimple.c
> index 5b2bc1c..d7e8861 100644
> --- a/gcc/graphite-isl-ast-to-gimple.c
> +++ b/gcc/graphite-isl-ast-to-gimple.c
> @@ -1331,7 +1331,7 @@ gsi_insert_earliest (gimple_seq seq)
>    FOR_EACH_VEC_ELT (stmts, i, use_stmt)
>      {
>        gcc_assert (gimple_code (use_stmt) != GIMPLE_PHI);
> -      gimple_stmt_iterator gsi_def_stmt = gsi_start_bb_nondebug (begin_bb);
> +      gimple_stmt_iterator gsi_def_stmt = gsi_start_nondebug_bb (begin_bb);
>
>        use_operand_p use_p;
>        ssa_op_iter op_iter;
> @@ -1363,7 +1363,7 @@ gsi_insert_earliest (gimple_seq seq)
>        else if (gimple_code (gsi_stmt (gsi_def_stmt)) == GIMPLE_PHI)
>         {
>           gimple_stmt_iterator bsi
> -           = gsi_start_bb_nondebug (gsi_bb (gsi_def_stmt));
> +           = gsi_start_nondebug_bb (gsi_bb (gsi_def_stmt));
>           /* Insert right after the PHI statements.  */
>           gsi_insert_before (&bsi, use_stmt, GSI_NEW_STMT);
>         }
> @@ -1646,7 +1646,8 @@ rename_uses (gimple *copy, gimple_stmt_iterator *gsi_tgt, basic_block old_bb,
>      {
>        if (gimple_debug_bind_p (copy))
>         gimple_debug_bind_reset_value (copy);
> -      else if (gimple_debug_source_bind_p (copy))
> +      else if (gimple_debug_source_bind_p (copy)
> +              || gimple_debug_nonbind_marker_p (copy))
>         return false;
>        else
>         gcc_unreachable ();
> diff --git a/gcc/graphite-scop-detection.c b/gcc/graphite-scop-detection.c
> index e17d58a..15b15f7 100644
> --- a/gcc/graphite-scop-detection.c
> +++ b/gcc/graphite-scop-detection.c
> @@ -261,7 +261,7 @@ trivially_empty_bb_p (basic_block bb)
>    gimple_stmt_iterator gsi;
>
>    for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
> -    if (gimple_code (gsi_stmt (gsi)) != GIMPLE_DEBUG)
> +    if (!is_gimple_debug (gsi_stmt (gsi)))
>        return false;
>
>    return true;
> diff --git a/gcc/haifa-sched.c b/gcc/haifa-sched.c
> index af0ed27..f9dc774 100644
> --- a/gcc/haifa-sched.c
> +++ b/gcc/haifa-sched.c
> @@ -8160,7 +8160,7 @@ sched_extend_bb (void)
>        || (!NOTE_P (insn)
>           && !LABEL_P (insn)
>           /* Don't emit a NOTE if it would end up before a BARRIER.  */
> -         && !BARRIER_P (NEXT_INSN (end))))
> +         && !BARRIER_P (next_nondebug_insn (end))))
>      {
>        rtx_note *note = emit_note_after (NOTE_INSN_DELETED, end);
>        /* Make note appear outside BB.  */
> diff --git a/gcc/insn-notes.def b/gcc/insn-notes.def
> index f96ce18..252e957 100644
> --- a/gcc/insn-notes.def
> +++ b/gcc/insn-notes.def
> @@ -68,6 +68,13 @@ INSN_NOTE (VAR_LOCATION)
>  /* The values passed to callee.  */
>  INSN_NOTE (CALL_ARG_LOCATION)
>
> +/* The beginning of a statement.  */
> +INSN_NOTE (BEGIN_STMT)
> +
> +/* The entry point for an inlined function.  Its NOTE_BLOCK references
> +   the lexical block whose abstract origin is the inlined function.  */
> +INSN_NOTE (INLINE_ENTRY)
> +
>  /* Record the struct for the following basic block.  Uses
>     NOTE_BASIC_BLOCK.  FIXME: Redundant with the basic block pointer
>     now included in every insn.  NOTE: If there's no CFG anymore, in other words,
> diff --git a/gcc/ipa-icf-gimple.c b/gcc/ipa-icf-gimple.c
> index f44a995..d0c9d78 100644
> --- a/gcc/ipa-icf-gimple.c
> +++ b/gcc/ipa-icf-gimple.c
> @@ -633,8 +633,8 @@ func_checker::compare_bb (sem_bb *bb1, sem_bb *bb2)
>    gimple_stmt_iterator gsi1, gsi2;
>    gimple *s1, *s2;
>
> -  gsi1 = gsi_start_bb_nondebug (bb1->bb);
> -  gsi2 = gsi_start_bb_nondebug (bb2->bb);
> +  gsi1 = gsi_start_nondebug_bb (bb1->bb);
> +  gsi2 = gsi_start_nondebug_bb (bb2->bb);
>
>    while (!gsi_end_p (gsi1))
>      {
> diff --git a/gcc/ira.c b/gcc/ira.c
> index 08a1cc5..0a6d73a 100644
> --- a/gcc/ira.c
> +++ b/gcc/ira.c
> @@ -3844,7 +3844,7 @@ combine_and_move_insns (void)
>        /* Last pass - adjust debug insns referencing cleared regs.  */
>        if (MAY_HAVE_DEBUG_INSNS)
>         for (rtx_insn *insn = get_insns (); insn; insn = NEXT_INSN (insn))
> -         if (DEBUG_INSN_P (insn))
> +         if (BIND_DEBUG_INSN_P (insn))
>             {
>               rtx old_loc = INSN_VAR_LOCATION_LOC (insn);
>               INSN_VAR_LOCATION_LOC (insn)
> diff --git a/gcc/jump.c b/gcc/jump.c
> index fc4b434..e60a6c6 100644
> --- a/gcc/jump.c
> +++ b/gcc/jump.c
> @@ -123,7 +123,7 @@ cleanup_barriers (void)
>      {
>        if (BARRIER_P (insn))
>         {
> -         rtx_insn *prev = prev_nonnote_insn (insn);
> +         rtx_insn *prev = prev_nonnote_nondebug_insn (insn);
>           if (!prev)
>             continue;
>
> diff --git a/gcc/langhooks-def.h b/gcc/langhooks-def.h
> index ea2006c..fa6f247 100644
> --- a/gcc/langhooks-def.h
> +++ b/gcc/langhooks-def.h
> @@ -130,6 +130,7 @@ extern int lhd_type_dwarf_attribute (const_tree, int);
>  #define LANG_HOOKS_EH_USE_CXA_END_CLEANUP      false
>  #define LANG_HOOKS_DEEP_UNSHARING      false
>  #define LANG_HOOKS_CUSTOM_FUNCTION_DESCRIPTORS false
> +#define LANG_HOOKS_EMITS_BEGIN_STMT    false
>  #define LANG_HOOKS_RUN_LANG_SELFTESTS   lhd_do_nothing
>  #define LANG_HOOKS_GET_SUBSTRING_LOCATION lhd_get_substring_location
>
> @@ -341,6 +342,7 @@ extern void lhd_end_section (void);
>    LANG_HOOKS_EH_USE_CXA_END_CLEANUP, \
>    LANG_HOOKS_DEEP_UNSHARING, \
>    LANG_HOOKS_CUSTOM_FUNCTION_DESCRIPTORS, \
> +  LANG_HOOKS_EMITS_BEGIN_STMT, \
>    LANG_HOOKS_RUN_LANG_SELFTESTS, \
>    LANG_HOOKS_GET_SUBSTRING_LOCATION \
>  }
> diff --git a/gcc/langhooks.h b/gcc/langhooks.h
> index 88f6f71..8d91cfc 100644
> --- a/gcc/langhooks.h
> +++ b/gcc/langhooks.h
> @@ -524,6 +524,9 @@ struct lang_hooks
>       instead of trampolines.  */
>    bool custom_function_descriptors;
>
> +  /* True if this language emits begin stmt notes.  */
> +  bool emits_begin_stmt;
> +
>    /* Run all lang-specific selftests.  */
>    void (*run_lang_selftests) (void);
>
> diff --git a/gcc/loop-unroll.c b/gcc/loop-unroll.c
> index 84145bb..01db753 100644
> --- a/gcc/loop-unroll.c
> +++ b/gcc/loop-unroll.c
> @@ -2024,12 +2024,14 @@ apply_opt_in_copies (struct opt_info *opt_info,
>        FOR_BB_INSNS_SAFE (bb, insn, next)
>          {
>           if (!INSN_P (insn)
> -             || (DEBUG_INSN_P (insn)
> +             || (BIND_DEBUG_INSN_P (insn)
> +                 && INSN_VAR_LOCATION_DECL (insn)
>                   && TREE_CODE (INSN_VAR_LOCATION_DECL (insn)) == LABEL_DECL))
>              continue;
>
>           while (!INSN_P (orig_insn)
> -                || (DEBUG_INSN_P (orig_insn)
> +                || (BIND_DEBUG_INSN_P (orig_insn)
> +                    && INSN_VAR_LOCATION_DECL (orig_insn)
>                      && (TREE_CODE (INSN_VAR_LOCATION_DECL (orig_insn))
>                          == LABEL_DECL)))
>              orig_insn = NEXT_INSN (orig_insn);
> diff --git a/gcc/lra-constraints.c b/gcc/lra-constraints.c
> index b1d864f..e70537d 100644
> --- a/gcc/lra-constraints.c
> +++ b/gcc/lra-constraints.c
> @@ -5269,10 +5269,11 @@ inherit_reload_reg (bool def_p, int original_regno,
>        lra_update_insn_regno_info (as_a <rtx_insn *> (usage_insn));
>        if (lra_dump_file != NULL)
>         {
> +         basic_block bb = BLOCK_FOR_INSN (usage_insn);
>           fprintf (lra_dump_file,
>                    "    Inheritance reuse change %d->%d (bb%d):\n",
>                    original_regno, REGNO (new_reg),
> -                  BLOCK_FOR_INSN (usage_insn)->index);
> +                  bb ? bb->index : -1);
>           dump_insn_slim (lra_dump_file, as_a <rtx_insn *> (usage_insn));
>         }
>      }
> @@ -5816,6 +5817,13 @@ update_ebb_live_info (rtx_insn *head, rtx_insn *tail)
>        if (NOTE_P (curr_insn) && NOTE_KIND (curr_insn) != NOTE_INSN_BASIC_BLOCK)
>         continue;
>        curr_bb = BLOCK_FOR_INSN (curr_insn);
> +      if (!curr_bb)
> +       {
> +         gcc_assert (DEBUG_INSN_P (curr_insn));
> +         if (MARKER_DEBUG_INSN_P (curr_insn))
> +           continue;
> +         curr_bb = prev_bb;
> +       }
>        if (curr_bb != prev_bb)
>         {
>           if (prev_bb != NULL)
> diff --git a/gcc/lra.c b/gcc/lra.c
> index 1230b25..64abe54 100644
> --- a/gcc/lra.c
> +++ b/gcc/lra.c
> @@ -602,9 +602,9 @@ static struct lra_operand_data debug_operand_data =
>    };
>
>  /* The following data are used as static insn data for all debug
> -   insns.  If structure lra_static_insn_data is changed, the
> +   bind insns.  If structure lra_static_insn_data is changed, the
>     initializer should be changed too.  */
> -static struct lra_static_insn_data debug_insn_static_data =
> +static struct lra_static_insn_data debug_bind_static_data =
>    {
>      &debug_operand_data,
>      0, /* Duplication operands #.  */
> @@ -618,6 +618,22 @@ static struct lra_static_insn_data debug_insn_static_data =
>      NULL  /* Descriptions of operands in alternatives. */
>    };
>
> +/* The following data are used as static insn data for all debug
> +   marker insns.  If structure lra_static_insn_data is changed, the
> +   initializer should be changed too.  */
> +static struct lra_static_insn_data debug_marker_static_data =
> +  {
> +    &debug_operand_data,
> +    0, /* Duplication operands #.  */
> +    -1, /* Commutative operand #.  */
> +    0, /* Operands #.  There isn't any operand.  */
> +    0, /* Duplications #.  */
> +    0, /* Alternatives #.  We are not interesting in alternatives
> +          because we does not proceed debug_insns for reloads.  */
> +    NULL, /* Hard registers referenced in machine description. */
> +    NULL  /* Descriptions of operands in alternatives. */
> +  };
> +
>  /* Called once per compiler work to initialize some LRA data related
>     to insns.  */
>  static void
> @@ -951,12 +967,20 @@ lra_set_insn_recog_data (rtx_insn *insn)
>    data->regs = NULL;
>    if (DEBUG_INSN_P (insn))
>      {
> -      data->insn_static_data = &debug_insn_static_data;
>        data->dup_loc = NULL;
>        data->arg_hard_regs = NULL;
>        data->preferred_alternatives = ALL_ALTERNATIVES;
> -      data->operand_loc = XNEWVEC (rtx *, 1);
> -      data->operand_loc[0] = &INSN_VAR_LOCATION_LOC (insn);
> +      if (BIND_DEBUG_INSN_P (insn))
> +       {
> +         data->insn_static_data = &debug_bind_static_data;
> +         data->operand_loc = XNEWVEC (rtx *, 1);
> +         data->operand_loc[0] = &INSN_VAR_LOCATION_LOC (insn);
> +       }
> +      else if (MARKER_DEBUG_INSN_P (insn))
> +       {
> +         data->insn_static_data = &debug_marker_static_data;
> +         data->operand_loc = NULL;
> +       }
>        return data;
>      }
>    if (icode < 0)
> @@ -1602,7 +1626,7 @@ lra_update_insn_regno_info (rtx_insn *insn)
>      return;
>    data = lra_get_insn_recog_data (insn);
>    static_data = data->insn_static_data;
> -  freq = get_insn_freq (insn);
> +  freq = NONDEBUG_INSN_P (insn) ? get_insn_freq (insn) : 0;
>    invalidate_insn_data_regno_info (data, insn, freq);
>    uid = INSN_UID (insn);
>    for (i = static_data->n_operands - 1; i >= 0; i--)
> @@ -1812,7 +1836,7 @@ push_insns (rtx_insn *from, rtx_insn *to)
>  static void
>  setup_sp_offset (rtx_insn *from, rtx_insn *last)
>  {
> -  rtx_insn *before = next_nonnote_insn_bb (last);
> +  rtx_insn *before = next_nonnote_nondebug_insn_bb (last);
>    HOST_WIDE_INT offset = (before == NULL_RTX || ! INSN_P (before)
>                           ? 0 : lra_get_insn_recog_data (before)->sp_offset);
>
> diff --git a/gcc/lto-streamer-in.c b/gcc/lto-streamer-in.c
> index 5710e8f..1834df0 100644
> --- a/gcc/lto-streamer-in.c
> +++ b/gcc/lto-streamer-in.c
> @@ -1173,6 +1173,13 @@ input_function (tree fn_decl, struct data_in *data_in,
>             {
>               gsi_next (&bsi);
>               stmts[gimple_uid (stmt)] = stmt;
> +
> +             /* Remember that the input function has begin stmt
> +                markers, so that we know to expect them when emitting
> +                debug info.  */
> +             if (!cfun->debug_nonbind_markers
> +                 && gimple_debug_nonbind_marker_p (stmt))
> +               cfun->debug_nonbind_markers = true;
>             }
>         }
>      }
> diff --git a/gcc/omp-expand.c b/gcc/omp-expand.c
> index ac83ba1..cd6b765 100644
> --- a/gcc/omp-expand.c
> +++ b/gcc/omp-expand.c
> @@ -659,7 +659,7 @@ expand_parallel_call (struct omp_region *region, basic_block bb,
>                                       false, GSI_CONTINUE_LINKING);
>      }
>
> -  gsi = gsi_last_bb (bb);
> +  gsi = gsi_last_nondebug_bb (bb);
>    t = gimple_omp_parallel_data_arg (entry_stmt);
>    if (t == NULL)
>      t1 = null_pointer_node;
> @@ -710,7 +710,7 @@ expand_cilk_for_call (basic_block bb, gomp_parallel *entry_stmt,
>    gcc_assert (count != NULL_TREE);
>    count = OMP_CLAUSE_OPERAND (count, 0);
>
> -  gsi = gsi_last_bb (bb);
> +  gsi = gsi_last_nondebug_bb (bb);
>    t = gimple_omp_parallel_data_arg (entry_stmt);
>    if (t == NULL)
>      t1 = null_pointer_node;
> @@ -836,7 +836,7 @@ expand_task_call (struct omp_region *region, basic_block bb,
>    else
>      priority = integer_zero_node;
>
> -  gsi = gsi_last_bb (bb);
> +  gsi = gsi_last_nondebug_bb (bb);
>    tree t = gimple_omp_task_data_arg (entry_stmt);
>    if (t == NULL)
>      t2 = null_pointer_node;
> @@ -913,15 +913,15 @@ remove_exit_barrier (struct omp_region *region)
>       statements that can appear in between are extremely limited -- no
>       memory operations at all.  Here, we allow nothing at all, so the
>       only thing we allow to precede this GIMPLE_OMP_RETURN is a label.  */
> -  gsi = gsi_last_bb (exit_bb);
> +  gsi = gsi_last_nondebug_bb (exit_bb);
>    gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_RETURN);
> -  gsi_prev (&gsi);
> +  gsi_prev_nondebug (&gsi);
>    if (!gsi_end_p (gsi) && gimple_code (gsi_stmt (gsi)) != GIMPLE_LABEL)
>      return;
>
>    FOR_EACH_EDGE (e, ei, exit_bb->preds)
>      {
> -      gsi = gsi_last_bb (e->src);
> +      gsi = gsi_last_nondebug_bb (e->src);
>        if (gsi_end_p (gsi))
>         continue;
>        stmt = gsi_stmt (gsi);
> @@ -1148,7 +1148,7 @@ expand_omp_taskreg (struct omp_region *region)
>
>        entry_succ_e = single_succ_edge (entry_bb);
>
> -      gsi = gsi_last_bb (entry_bb);
> +      gsi = gsi_last_nondebug_bb (entry_bb);
>        gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_PARALLEL
>                   || gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_TASK);
>        gsi_remove (&gsi, true);
> @@ -1261,7 +1261,7 @@ expand_omp_taskreg (struct omp_region *region)
>
>        /* Split ENTRY_BB at GIMPLE_OMP_PARALLEL or GIMPLE_OMP_TASK,
>          so that it can be moved to the child function.  */
> -      gsi = gsi_last_bb (entry_bb);
> +      gsi = gsi_last_nondebug_bb (entry_bb);
>        stmt = gsi_stmt (gsi);
>        gcc_assert (stmt && (gimple_code (stmt) == GIMPLE_OMP_PARALLEL
>                            || gimple_code (stmt) == GIMPLE_OMP_TASK));
> @@ -1277,7 +1277,7 @@ expand_omp_taskreg (struct omp_region *region)
>           gcc_assert (e2->dest == region->exit);
>           remove_edge (BRANCH_EDGE (entry_bb));
>           set_immediate_dominator (CDI_DOMINATORS, e2->dest, e->src);
> -         gsi = gsi_last_bb (region->exit);
> +         gsi = gsi_last_nondebug_bb (region->exit);
>           gcc_assert (!gsi_end_p (gsi)
>                       && gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_RETURN);
>           gsi_remove (&gsi, true);
> @@ -1286,7 +1286,7 @@ expand_omp_taskreg (struct omp_region *region)
>        /* Convert GIMPLE_OMP_{RETURN,CONTINUE} into a RETURN_EXPR.  */
>        if (exit_bb)
>         {
> -         gsi = gsi_last_bb (exit_bb);
> +         gsi = gsi_last_nondebug_bb (exit_bb);
>           gcc_assert (!gsi_end_p (gsi)
>                       && (gimple_code (gsi_stmt (gsi))
>                           == (e2 ? GIMPLE_OMP_CONTINUE : GIMPLE_OMP_RETURN)));
> @@ -1748,7 +1748,7 @@ expand_omp_for_init_counts (struct omp_for_data *fd, gimple_stmt_iterator *gsi,
>           if (l2_dom_bb == NULL)
>             l2_dom_bb = entry_bb;
>           entry_bb = e->dest;
> -         *gsi = gsi_last_bb (entry_bb);
> +         *gsi = gsi_last_nondebug_bb (entry_bb);
>         }
>
>        if (POINTER_TYPE_P (itype))
> @@ -2553,7 +2553,7 @@ expand_omp_for_generic (struct omp_region *region,
>    l3_bb = BRANCH_EDGE (entry_bb)->dest;
>    exit_bb = region->exit;
>
> -  gsi = gsi_last_bb (entry_bb);
> +  gsi = gsi_last_nondebug_bb (entry_bb);
>
>    gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
>    if (fd->ordered
> @@ -2583,7 +2583,7 @@ expand_omp_for_generic (struct omp_region *region,
>           e = split_block (entry_bb, gsi_stmt (gsi));
>           entry_bb = e->dest;
>           make_edge (zero_iter1_bb, entry_bb, EDGE_FALLTHRU);
> -         gsi = gsi_last_bb (entry_bb);
> +         gsi = gsi_last_nondebug_bb (entry_bb);
>           set_immediate_dominator (CDI_DOMINATORS, entry_bb,
>                                    get_immediate_dominator (CDI_DOMINATORS,
>                                                             zero_iter1_bb));
> @@ -2604,7 +2604,7 @@ expand_omp_for_generic (struct omp_region *region,
>               e = split_block (entry_bb, gsi_stmt (gsi));
>               entry_bb = e->dest;
>               make_edge (zero_iter2_bb, entry_bb, EDGE_FALLTHRU);
> -             gsi = gsi_last_bb (entry_bb);
> +             gsi = gsi_last_nondebug_bb (entry_bb);
>               set_immediate_dominator (CDI_DOMINATORS, entry_bb,
>                                        get_immediate_dominator
>                                          (CDI_DOMINATORS, zero_iter2_bb));
> @@ -3022,7 +3022,7 @@ expand_omp_for_generic (struct omp_region *region,
>      {
>        /* Code to control the increment and predicate for the sequential
>          loop goes in the CONT_BB.  */
> -      gsi = gsi_last_bb (cont_bb);
> +      gsi = gsi_last_nondebug_bb (cont_bb);
>        gomp_continue *cont_stmt = as_a <gomp_continue *> (gsi_stmt (gsi));
>        gcc_assert (gimple_code (cont_stmt) == GIMPLE_OMP_CONTINUE);
>        vmain = gimple_omp_continue_control_use (cont_stmt);
> @@ -3088,7 +3088,7 @@ expand_omp_for_generic (struct omp_region *region,
>      }
>
>    /* Add the loop cleanup function.  */
> -  gsi = gsi_last_bb (exit_bb);
> +  gsi = gsi_last_nondebug_bb (exit_bb);
>    if (gimple_omp_return_nowait_p (gsi_stmt (gsi)))
>      t = builtin_decl_explicit (BUILT_IN_GOMP_LOOP_END_NOWAIT);
>    else if (gimple_omp_return_lhs (gsi_stmt (gsi)))
> @@ -3308,7 +3308,7 @@ expand_omp_for_static_nochunk (struct omp_region *region,
>    exit_bb = region->exit;
>
>    /* Iteration space partitioning goes in ENTRY_BB.  */
> -  gsi = gsi_last_bb (entry_bb);
> +  gsi = gsi_last_nondebug_bb (entry_bb);
>    gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
>
>    if (fd->collapse > 1)
> @@ -3440,7 +3440,7 @@ expand_omp_for_static_nochunk (struct omp_region *region,
>    gsi_insert_before (&gsi, cond_stmt, GSI_SAME_STMT);
>
>    second_bb = split_block (entry_bb, cond_stmt)->dest;
> -  gsi = gsi_last_bb (second_bb);
> +  gsi = gsi_last_nondebug_bb (second_bb);
>    gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
>
>    gsi_insert_before (&gsi, gimple_build_assign (tt, build_int_cst (itype, 0)),
> @@ -3450,7 +3450,7 @@ expand_omp_for_static_nochunk (struct omp_region *region,
>    gsi_insert_before (&gsi, assign_stmt, GSI_SAME_STMT);
>
>    third_bb = split_block (second_bb, assign_stmt)->dest;
> -  gsi = gsi_last_bb (third_bb);
> +  gsi = gsi_last_nondebug_bb (third_bb);
>    gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
>
>    t = build2 (MULT_EXPR, itype, q, threadid);
> @@ -3592,7 +3592,7 @@ expand_omp_for_static_nochunk (struct omp_region *region,
>      {
>        /* The code controlling the sequential loop replaces the
>          GIMPLE_OMP_CONTINUE.  */
> -      gsi = gsi_last_bb (cont_bb);
> +      gsi = gsi_last_nondebug_bb (cont_bb);
>        gomp_continue *cont_stmt = as_a <gomp_continue *> (gsi_stmt (gsi));
>        gcc_assert (gimple_code (cont_stmt) == GIMPLE_OMP_CONTINUE);
>        vmain = gimple_omp_continue_control_use (cont_stmt);
> @@ -3625,7 +3625,7 @@ expand_omp_for_static_nochunk (struct omp_region *region,
>      }
>
>    /* Replace the GIMPLE_OMP_RETURN with a barrier, or nothing.  */
> -  gsi = gsi_last_bb (exit_bb);
> +  gsi = gsi_last_nondebug_bb (exit_bb);
>    if (!gimple_omp_return_nowait_p (gsi_stmt (gsi)))
>      {
>        t = gimple_omp_return_lhs (gsi_stmt (gsi));
> @@ -3792,7 +3792,7 @@ expand_omp_for_static_chunk (struct omp_region *region,
>    exit_bb = region->exit;
>
>    /* Trip and adjustment setup goes in ENTRY_BB.  */
> -  gsi = gsi_last_bb (entry_bb);
> +  gsi = gsi_last_nondebug_bb (entry_bb);
>    gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
>
>    if (fd->collapse > 1)
> @@ -4098,7 +4098,7 @@ expand_omp_for_static_chunk (struct omp_region *region,
>      {
>        /* The code controlling the sequential loop goes in CONT_BB,
>          replacing the GIMPLE_OMP_CONTINUE.  */
> -      gsi = gsi_last_bb (cont_bb);
> +      gsi = gsi_last_nondebug_bb (cont_bb);
>        gomp_continue *cont_stmt = as_a <gomp_continue *> (gsi_stmt (gsi));
>        vmain = gimple_omp_continue_control_use (cont_stmt);
>        vback = gimple_omp_continue_control_def (cont_stmt);
> @@ -4142,7 +4142,7 @@ expand_omp_for_static_chunk (struct omp_region *region,
>      }
>
>    /* Replace the GIMPLE_OMP_RETURN with a barrier, or nothing.  */
> -  gsi = gsi_last_bb (exit_bb);
> +  gsi = gsi_last_nondebug_bb (exit_bb);
>    if (!gimple_omp_return_nowait_p (gsi_stmt (gsi)))
>      {
>        t = gimple_omp_return_lhs (gsi_stmt (gsi));
> @@ -4353,7 +4353,7 @@ expand_cilk_for (struct omp_region *region, struct omp_for_data *fd)
>    basic_block exit_bb = region->exit;
>    basic_block l2_dom_bb = NULL;
>
> -  gimple_stmt_iterator gsi = gsi_last_bb (entry_bb);
> +  gimple_stmt_iterator gsi = gsi_last_nondebug_bb (entry_bb);
>
>    /* Below statements until the "tree high_val = ..." are pseudo statements
>       used to pass information to be used by expand_omp_taskreg.
> @@ -4398,7 +4398,7 @@ expand_cilk_for (struct omp_region *region, struct omp_for_data *fd)
>    if (!broken_loop)
>      {
>        /* Code to control the increment goes in the CONT_BB.  */
> -      gsi = gsi_last_bb (cont_bb);
> +      gsi = gsi_last_nondebug_bb (cont_bb);
>        stmt = gsi_stmt (gsi);
>        gcc_assert (gimple_code (stmt) == GIMPLE_OMP_CONTINUE);
>        stmt = gimple_build_assign (ind_var, PLUS_EXPR, ind_var,
> @@ -4428,7 +4428,7 @@ expand_cilk_for (struct omp_region *region, struct omp_for_data *fd)
>    gsi_insert_before (&gsi, stmt, GSI_SAME_STMT);
>
>    /* Remove GIMPLE_OMP_RETURN.  */
> -  gsi = gsi_last_bb (exit_bb);
> +  gsi = gsi_last_nondebug_bb (exit_bb);
>    gsi_remove (&gsi, true);
>
>    /* Connect the new blocks.  */
> @@ -4602,7 +4602,7 @@ expand_omp_simd (struct omp_region *region, struct omp_for_data *fd)
>    exit_bb = region->exit;
>    l2_dom_bb = NULL;
>
> -  gsi = gsi_last_bb (entry_bb);
> +  gsi = gsi_last_nondebug_bb (entry_bb);
>
>    gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
>    /* Not needed in SSA form right now.  */
> @@ -4697,7 +4697,7 @@ expand_omp_simd (struct omp_region *region, struct omp_for_data *fd)
>    if (!broken_loop)
>      {
>        /* Code to control the increment goes in the CONT_BB.  */
> -      gsi = gsi_last_bb (cont_bb);
> +      gsi = gsi_last_nondebug_bb (cont_bb);
>        stmt = gsi_stmt (gsi);
>        gcc_assert (gimple_code (stmt) == GIMPLE_OMP_CONTINUE);
>
> @@ -4791,7 +4791,7 @@ expand_omp_simd (struct omp_region *region, struct omp_for_data *fd)
>      }
>
>    /* Remove GIMPLE_OMP_RETURN.  */
> -  gsi = gsi_last_bb (exit_bb);
> +  gsi = gsi_last_nondebug_bb (exit_bb);
>    gsi_remove (&gsi, true);
>
>    /* Connect the new blocks.  */
> @@ -4917,7 +4917,7 @@ expand_omp_taskloop_for_outer (struct omp_region *region,
>    gcc_assert (BRANCH_EDGE (entry_bb)->dest == FALLTHRU_EDGE (cont_bb)->dest);
>    exit_bb = region->exit;
>
> -  gsi = gsi_last_bb (entry_bb);
> +  gsi = gsi_last_nondebug_bb (entry_bb);
>    gimple *for_stmt = gsi_stmt (gsi);
>    gcc_assert (gimple_code (for_stmt) == GIMPLE_OMP_FOR);
>    if (fd->collapse > 1)
> @@ -5018,10 +5018,10 @@ expand_omp_taskloop_for_outer (struct omp_region *region,
>    gsi = gsi_for_stmt (for_stmt);
>    gsi_remove (&gsi, true);
>
> -  gsi = gsi_last_bb (cont_bb);
> +  gsi = gsi_last_nondebug_bb (cont_bb);
>    gsi_remove (&gsi, true);
>
> -  gsi = gsi_last_bb (exit_bb);
> +  gsi = gsi_last_nondebug_bb (exit_bb);
>    gsi_remove (&gsi, true);
>
>    FALLTHRU_EDGE (entry_bb)->probability = profile_probability::always ();
> @@ -5095,7 +5095,7 @@ expand_omp_taskloop_for_inner (struct omp_region *region,
>    exit_bb = region->exit;
>
>    /* Iteration space partitioning goes in ENTRY_BB.  */
> -  gsi = gsi_last_bb (entry_bb);
> +  gsi = gsi_last_nondebug_bb (entry_bb);
>    gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
>
>    if (fd->collapse > 1)
> @@ -5174,7 +5174,7 @@ expand_omp_taskloop_for_inner (struct omp_region *region,
>      {
>        /* The code controlling the sequential loop replaces the
>          GIMPLE_OMP_CONTINUE.  */
> -      gsi = gsi_last_bb (cont_bb);
> +      gsi = gsi_last_nondebug_bb (cont_bb);
>        gomp_continue *cont_stmt = as_a <gomp_continue *> (gsi_stmt (gsi));
>        gcc_assert (gimple_code (cont_stmt) == GIMPLE_OMP_CONTINUE);
>        vmain = gimple_omp_continue_control_use (cont_stmt);
> @@ -5211,7 +5211,7 @@ expand_omp_taskloop_for_inner (struct omp_region *region,
>    gsi_remove (&gsi, true);
>
>    /* Remove the GIMPLE_OMP_RETURN statement.  */
> -  gsi = gsi_last_bb (exit_bb);
> +  gsi = gsi_last_nondebug_bb (exit_bb);
>    gsi_remove (&gsi, true);
>
>    FALLTHRU_EDGE (entry_bb)->probability = profile_probability::always ();
> @@ -5394,7 +5394,7 @@ expand_oacc_for (struct omp_region *region, struct omp_for_data *fd)
>    entry_bb = split->src;
>
>    /* Chunk setup goes at end of entry_bb, replacing the omp_for.  */
> -  gsi = gsi_last_bb (entry_bb);
> +  gsi = gsi_last_nondebug_bb (entry_bb);
>    gomp_for *for_stmt = as_a <gomp_for *> (gsi_stmt (gsi));
>    loc = gimple_location (for_stmt);
>
> @@ -5521,7 +5521,7 @@ expand_oacc_for (struct omp_region *region, struct omp_for_data *fd)
>
>    if (gimple_in_ssa_p (cfun))
>      {
> -      gsi = gsi_last_bb (cont_bb);
> +      gsi = gsi_last_nondebug_bb (cont_bb);
>        gomp_continue *cont_stmt = as_a <gomp_continue *> (gsi_stmt (gsi));
>
>        offset = gimple_omp_continue_control_use (cont_stmt);
> @@ -5645,7 +5645,7 @@ expand_oacc_for (struct omp_region *region, struct omp_for_data *fd)
>       occur, especially when noreturn routines are involved.  */
>    if (cont_bb)
>      {
> -      gsi = gsi_last_bb (cont_bb);
> +      gsi = gsi_last_nondebug_bb (cont_bb);
>        gomp_continue *cont_stmt = as_a <gomp_continue *> (gsi_stmt (gsi));
>        loc = gimple_location (cont_stmt);
>
> @@ -5734,7 +5734,7 @@ expand_oacc_for (struct omp_region *region, struct omp_for_data *fd)
>         }
>      }
>
> -  gsi = gsi_last_bb (exit_bb);
> +  gsi = gsi_last_nondebug_bb (exit_bb);
>    gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_RETURN);
>    loc = gimple_location (gsi_stmt (gsi));
>
> @@ -5961,7 +5961,7 @@ expand_omp_sections (struct omp_region *region)
>        len = EDGE_COUNT (l0_bb->succs);
>        gcc_assert (len > 0);
>        e = EDGE_SUCC (l0_bb, len - 1);
> -      si = gsi_last_bb (e->dest);
> +      si = gsi_last_nondebug_bb (e->dest);
>        l2 = NULL_TREE;
>        if (gsi_end_p (si)
>           || gimple_code (gsi_stmt (si)) != GIMPLE_OMP_SECTION)
> @@ -5969,7 +5969,7 @@ expand_omp_sections (struct omp_region *region)
>        else
>         FOR_EACH_EDGE (e, ei, l0_bb->succs)
>           {
> -           si = gsi_last_bb (e->dest);
> +           si = gsi_last_nondebug_bb (e->dest);
>             if (gsi_end_p (si)
>                 || gimple_code (gsi_stmt (si)) != GIMPLE_OMP_SECTION)
>               {
> @@ -5994,7 +5994,7 @@ expand_omp_sections (struct omp_region *region)
>
>    /* The call to GOMP_sections_start goes in ENTRY_BB, replacing the
>       GIMPLE_OMP_SECTIONS statement.  */
> -  si = gsi_last_bb (entry_bb);
> +  si = gsi_last_nondebug_bb (entry_bb);
>    sections_stmt = as_a <gomp_sections *> (gsi_stmt (si));
>    gcc_assert (gimple_code (sections_stmt) == GIMPLE_OMP_SECTIONS);
>    vin = gimple_omp_sections_control (sections_stmt);
> @@ -6018,7 +6018,7 @@ expand_omp_sections (struct omp_region *region)
>
>    /* The switch() statement replacing GIMPLE_OMP_SECTIONS_SWITCH goes in
>       L0_BB.  */
> -  switch_si = gsi_last_bb (l0_bb);
> +  switch_si = gsi_last_nondebug_bb (l0_bb);
>    gcc_assert (gimple_code (gsi_stmt (switch_si)) == GIMPLE_OMP_SECTIONS_SWITCH);
>    if (exit_reachable)
>      {
> @@ -6060,7 +6060,7 @@ expand_omp_sections (struct omp_region *region)
>        u = build_case_label (u, NULL, t);
>        label_vec.quick_push (u);
>
> -      si = gsi_last_bb (s_entry_bb);
> +      si = gsi_last_nondebug_bb (s_entry_bb);
>        gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_SECTION);
>        gcc_assert (i < len || gimple_omp_section_last_p (gsi_stmt (si)));
>        gsi_remove (&si, true);
> @@ -6069,7 +6069,7 @@ expand_omp_sections (struct omp_region *region)
>        if (s_exit_bb == NULL)
>         continue;
>
> -      si = gsi_last_bb (s_exit_bb);
> +      si = gsi_last_nondebug_bb (s_exit_bb);
>        gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_RETURN);
>        gsi_remove (&si, true);
>
> @@ -6095,7 +6095,7 @@ expand_omp_sections (struct omp_region *region)
>        tree bfn_decl;
>
>        /* Code to get the next section goes in L1_BB.  */
> -      si = gsi_last_bb (l1_bb);
> +      si = gsi_last_nondebug_bb (l1_bb);
>        gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_CONTINUE);
>
>        bfn_decl = builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_NEXT);
> @@ -6108,7 +6108,7 @@ expand_omp_sections (struct omp_region *region)
>      }
>
>    /* Cleanup function replaces GIMPLE_OMP_RETURN in EXIT_BB.  */
> -  si = gsi_last_bb (l2_bb);
> +  si = gsi_last_nondebug_bb (l2_bb);
>    if (gimple_omp_return_nowait_p (gsi_stmt (si)))
>      t = builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_END_NOWAIT);
>    else if (gimple_omp_return_lhs (gsi_stmt (si)))
> @@ -6136,12 +6136,12 @@ expand_omp_single (struct omp_region *region)
>    entry_bb = region->entry;
>    exit_bb = region->exit;
>
> -  si = gsi_last_bb (entry_bb);
> +  si = gsi_last_nondebug_bb (entry_bb);
>    gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_SINGLE);
>    gsi_remove (&si, true);
>    single_succ_edge (entry_bb)->flags = EDGE_FALLTHRU;
>
> -  si = gsi_last_bb (exit_bb);
> +  si = gsi_last_nondebug_bb (exit_bb);
>    if (!gimple_omp_return_nowait_p (gsi_stmt (si)))
>      {
>        tree t = gimple_omp_return_lhs (gsi_stmt (si));
> @@ -6164,7 +6164,7 @@ expand_omp_synch (struct omp_region *region)
>    entry_bb = region->entry;
>    exit_bb = region->exit;
>
> -  si = gsi_last_bb (entry_bb);
> +  si = gsi_last_nondebug_bb (entry_bb);
>    gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_SINGLE
>               || gimple_code (gsi_stmt (si)) == GIMPLE_OMP_MASTER
>               || gimple_code (gsi_stmt (si)) == GIMPLE_OMP_TASKGROUP
> @@ -6176,7 +6176,7 @@ expand_omp_synch (struct omp_region *region)
>
>    if (exit_bb)
>      {
> -      si = gsi_last_bb (exit_bb);
> +      si = gsi_last_nondebug_bb (exit_bb);
>        gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_RETURN);
>        gsi_remove (&si, true);
>        single_succ_edge (exit_bb)->flags = EDGE_FALLTHRU;
> @@ -6197,7 +6197,7 @@ expand_omp_atomic_load (basic_block load_bb, tree addr,
>    gimple *stmt;
>    tree decl, call, type, itype;
>
> -  gsi = gsi_last_bb (load_bb);
> +  gsi = gsi_last_nondebug_bb (load_bb);
>    stmt = gsi_stmt (gsi);
>    gcc_assert (gimple_code (stmt) == GIMPLE_OMP_ATOMIC_LOAD);
>    loc = gimple_location (stmt);
> @@ -6227,7 +6227,7 @@ expand_omp_atomic_load (basic_block load_bb, tree addr,
>    gsi_remove (&gsi, true);
>
>    store_bb = single_succ (load_bb);
> -  gsi = gsi_last_bb (store_bb);
> +  gsi = gsi_last_nondebug_bb (store_bb);
>    gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_ATOMIC_STORE);
>    gsi_remove (&gsi, true);
>
> @@ -6253,14 +6253,14 @@ expand_omp_atomic_store (basic_block load_bb, tree addr,
>    machine_mode imode;
>    bool exchange;
>
> -  gsi = gsi_last_bb (load_bb);
> +  gsi = gsi_last_nondebug_bb (load_bb);
>    stmt = gsi_stmt (gsi);
>    gcc_assert (gimple_code (stmt) == GIMPLE_OMP_ATOMIC_LOAD);
>
>    /* If the load value is needed, then this isn't a store but an exchange.  */
>    exchange = gimple_omp_atomic_need_value_p (stmt);
>
> -  gsi = gsi_last_bb (store_bb);
> +  gsi = gsi_last_nondebug_bb (store_bb);
>    stmt = gsi_stmt (gsi);
>    gcc_assert (gimple_code (stmt) == GIMPLE_OMP_ATOMIC_STORE);
>    loc = gimple_location (stmt);
> @@ -6305,7 +6305,7 @@ expand_omp_atomic_store (basic_block load_bb, tree addr,
>    gsi_remove (&gsi, true);
>
>    /* Remove the GIMPLE_OMP_ATOMIC_LOAD that we verified above.  */
> -  gsi = gsi_last_bb (load_bb);
> +  gsi = gsi_last_nondebug_bb (load_bb);
>    gsi_remove (&gsi, true);
>
>    if (gimple_in_ssa_p (cfun))
> @@ -6352,10 +6352,17 @@ expand_omp_atomic_fetch_op (basic_block load_bb,
>
>    gsi = gsi_after_labels (store_bb);
>    stmt = gsi_stmt (gsi);
> +  if (is_gimple_debug (stmt))
> +    {
> +      gsi_next_nondebug (&gsi);
> +      if (gsi_end_p (gsi))
> +       return false;
> +      stmt = gsi_stmt (gsi);
> +    }
>    loc = gimple_location (stmt);
>    if (!is_gimple_assign (stmt))
>      return false;
> -  gsi_next (&gsi);
> +  gsi_next_nondebug (&gsi);
>    if (gimple_code (gsi_stmt (gsi)) != GIMPLE_OMP_ATOMIC_STORE)
>      return false;
>    need_new = gimple_omp_atomic_need_value_p (gsi_stmt (gsi));
> @@ -6419,7 +6426,7 @@ expand_omp_atomic_fetch_op (basic_block load_bb,
>    if (!can_compare_and_swap_p (imode, true) || !can_atomic_load_p (imode))
>      return false;
>
> -  gsi = gsi_last_bb (load_bb);
> +  gsi = gsi_last_nondebug_bb (load_bb);
>    gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_ATOMIC_LOAD);
>
>    /* OpenMP does not imply any barrier-like semantics on its atomic ops.
> @@ -6442,10 +6449,10 @@ expand_omp_atomic_fetch_op (basic_block load_bb,
>    force_gimple_operand_gsi (&gsi, call, true, NULL_TREE, true, GSI_SAME_STMT);
>    gsi_remove (&gsi, true);
>
> -  gsi = gsi_last_bb (store_bb);
> +  gsi = gsi_last_nondebug_bb (store_bb);
>    gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_ATOMIC_STORE);
>    gsi_remove (&gsi, true);
> -  gsi = gsi_last_bb (store_bb);
> +  gsi = gsi_last_nondebug_bb (store_bb);
>    stmt = gsi_stmt (gsi);
>    gsi_remove (&gsi, true);
>
> @@ -6498,7 +6505,7 @@ expand_omp_atomic_pipeline (basic_block load_bb, basic_block store_bb,
>      return false;
>
>    /* Load the initial value, replacing the GIMPLE_OMP_ATOMIC_LOAD.  */
> -  si = gsi_last_bb (load_bb);
> +  si = gsi_last_nondebug_bb (load_bb);
>    gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_ATOMIC_LOAD);
>
>    /* For floating-point values, we'll need to view-convert them to integers
> @@ -6578,7 +6585,7 @@ expand_omp_atomic_pipeline (basic_block load_bb, basic_block store_bb,
>      }
>    gsi_remove (&si, true);
>
> -  si = gsi_last_bb (store_bb);
> +  si = gsi_last_nondebug_bb (store_bb);
>    gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_ATOMIC_STORE);
>
>    if (iaddr == addr)
> @@ -6681,7 +6688,7 @@ expand_omp_atomic_mutex (basic_block load_bb, basic_block store_bb,
>    gassign *stmt;
>    tree t;
>
> -  si = gsi_last_bb (load_bb);
> +  si = gsi_last_nondebug_bb (load_bb);
>    gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_ATOMIC_LOAD);
>
>    t = builtin_decl_explicit (BUILT_IN_GOMP_ATOMIC_START);
> @@ -6692,7 +6699,7 @@ expand_omp_atomic_mutex (basic_block load_bb, basic_block store_bb,
>    gsi_insert_before (&si, stmt, GSI_SAME_STMT);
>    gsi_remove (&si, true);
>
> -  si = gsi_last_bb (store_bb);
> +  si = gsi_last_nondebug_bb (store_bb);
>    gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_ATOMIC_STORE);
>
>    stmt = gimple_build_assign (build_simple_mem_ref (unshare_expr (addr)),
> @@ -7190,7 +7197,7 @@ expand_omp_target (struct omp_region *region)
>
>        /* Split ENTRY_BB at GIMPLE_*,
>          so that it can be moved to the child function.  */
> -      gsi = gsi_last_bb (entry_bb);
> +      gsi = gsi_last_nondebug_bb (entry_bb);
>        stmt = gsi_stmt (gsi);
>        gcc_assert (stmt
>                   && gimple_code (stmt) == gimple_code (entry_stmt));
> @@ -7202,7 +7209,7 @@ expand_omp_target (struct omp_region *region)
>        /* Convert GIMPLE_OMP_RETURN into a RETURN_EXPR.  */
>        if (exit_bb)
>         {
> -         gsi = gsi_last_bb (exit_bb);
> +         gsi = gsi_last_nondebug_bb (exit_bb);
>           gcc_assert (!gsi_end_p (gsi)
>                       && gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_RETURN);
>           stmt = gimple_build_return (NULL);
> @@ -7384,7 +7391,7 @@ expand_omp_target (struct omp_region *region)
>         e = split_block_after_labels (new_bb);
>        else
>         {
> -         gsi = gsi_last_bb (new_bb);
> +         gsi = gsi_last_nondebug_bb (new_bb);
>           gsi_prev (&gsi);
>           e = split_block (new_bb, gsi_stmt (gsi));
>         }
> @@ -7419,11 +7426,11 @@ expand_omp_target (struct omp_region *region)
>        make_edge (else_bb, new_bb, EDGE_FALLTHRU);
>
>        device = tmp_var;
> -      gsi = gsi_last_bb (new_bb);
> +      gsi = gsi_last_nondebug_bb (new_bb);
>      }
>    else
>      {
> -      gsi = gsi_last_bb (new_bb);
> +      gsi = gsi_last_nondebug_bb (new_bb);
>        device = force_gimple_operand_gsi (&gsi, device, true, NULL_TREE,
>                                          true, GSI_SAME_STMT);
>      }
> @@ -7567,7 +7574,7 @@ expand_omp_target (struct omp_region *region)
>      }
>    if (data_region && region->exit)
>      {
> -      gsi = gsi_last_bb (region->exit);
> +      gsi = gsi_last_nondebug_bb (region->exit);
>        g = gsi_stmt (gsi);
>        gcc_assert (g && gimple_code (g) == GIMPLE_OMP_RETURN);
>        gsi_remove (&gsi, true);
> @@ -7648,17 +7655,17 @@ grid_expand_omp_for_loop (struct omp_region *kfor, bool intra_group)
>        gsi_insert_before (&gsi, assign_stmt, GSI_SAME_STMT);
>      }
>    /* Remove the omp for statement.  */
> -  gsi = gsi_last_bb (kfor->entry);
> +  gsi = gsi_last_nondebug_bb (kfor->entry);
>    gsi_remove (&gsi, true);
>
>    /* Remove the GIMPLE_OMP_CONTINUE statement.  */
> -  gsi = gsi_last_bb (kfor->cont);
> +  gsi = gsi_last_nondebug_bb (kfor->cont);
>    gcc_assert (!gsi_end_p (gsi)
>               && gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_CONTINUE);
>    gsi_remove (&gsi, true);
>
>    /* Replace the GIMPLE_OMP_RETURN with a barrier, if necessary.  */
> -  gsi = gsi_last_bb (kfor->exit);
> +  gsi = gsi_last_nondebug_bb (kfor->exit);
>    gcc_assert (!gsi_end_p (gsi)
>               && gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_RETURN);
>    if (intra_group)
> @@ -7802,11 +7809,11 @@ grid_expand_target_grid_body (struct omp_region *target)
>    grid_expand_omp_for_loop (kfor, false);
>
>    /* Remove the omp for statement.  */
> -  gimple_stmt_iterator gsi = gsi_last_bb (gpukernel->entry);
> +  gimple_stmt_iterator gsi = gsi_last_nondebug_bb (gpukernel->entry);
>    gsi_remove (&gsi, true);
>    /* Replace the GIMPLE_OMP_RETURN at the end of the kernel region with a real
>       return.  */
> -  gsi = gsi_last_bb (gpukernel->exit);
> +  gsi = gsi_last_nondebug_bb (gpukernel->exit);
>    gcc_assert (!gsi_end_p (gsi)
>               && gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_RETURN);
>    gimple *ret_stmt = gimple_build_return (NULL);
> @@ -7990,7 +7997,7 @@ build_omp_regions_1 (basic_block bb, struct omp_region *parent,
>    gimple *stmt;
>    basic_block son;
>
> -  gsi = gsi_last_bb (bb);
> +  gsi = gsi_last_nondebug_bb (bb);
>    if (!gsi_end_p (gsi) && is_gimple_omp (gsi_stmt (gsi)))
>      {
>        struct omp_region *region;
> diff --git a/gcc/omp-low.c b/gcc/omp-low.c
> index dffdb77..83f7975 100644
> --- a/gcc/omp-low.c
> +++ b/gcc/omp-low.c
> @@ -7019,6 +7019,8 @@ check_combined_parallel (gimple_stmt_iterator *gsi_p,
>      {
>      WALK_SUBSTMTS;
>
> +    case GIMPLE_DEBUG:
> +      break;
>      case GIMPLE_OMP_FOR:
>      case GIMPLE_OMP_SECTIONS:
>        *info = *info == 0 ? 1 : -1;
> diff --git a/gcc/opts.c b/gcc/opts.c
> index 19e8c7f..dd36835 100644
> --- a/gcc/opts.c
> +++ b/gcc/opts.c
> @@ -2329,7 +2329,7 @@ common_handle_option (struct gcc_options *opts,
>
>        /* FALLTHRU */
>      case OPT_gdwarf_:
> -      if (value < 2 || value > 5)
> +      if (value < 2 || value > 6)
>         error_at (loc, "dwarf version %d is not supported", value);
>        else
>         opts->x_dwarf_version = value;
> diff --git a/gcc/output.h b/gcc/output.h
> index 7a93fa8..278315f 100644
> --- a/gcc/output.h
> +++ b/gcc/output.h
> @@ -59,7 +59,7 @@ const char *get_some_local_dynamic_name ();
>     for the new function.  The label for the function and associated
>     assembler pseudo-ops have already been output in
>     `assemble_start_function'.  */
> -extern void final_start_function (rtx_insn *, FILE *, int);
> +extern void final_start_function (rtx_insn **, FILE *, int);
>
>  /* Output assembler code for the end of a function.
>     For clarity, args are same as those of `final_start_function'
> diff --git a/gcc/params.def b/gcc/params.def
> index 805302b..1d6a494 100644
> --- a/gcc/params.def
> +++ b/gcc/params.def
> @@ -960,6 +960,15 @@ DEFPARAM (PARAM_MAX_VARTRACK_REVERSE_OP_SIZE,
>           "Max. size of loc list for which reverse ops should be added.",
>           50, 0, 0)
>
> +/* Set a threshold to discard debug markers (e.g. debug begin stmt
> +   markers) when expanding a function to RTL, or inlining it into
> +   another function.  */
> +
> +DEFPARAM (PARAM_MAX_DEBUG_MARKER_COUNT,
> +         "max-debug-marker-count",
> +         "Max. count of debug markers to expand or inline.",
> +         100000, 0, 0)
> +
>  /* Set minimum insn uid for non-debug insns.  */
>
>  DEFPARAM (PARAM_MIN_NONDEBUG_INSN_UID,
> diff --git a/gcc/postreload.c b/gcc/postreload.c
> index e721f2f..7476102 100644
> --- a/gcc/postreload.c
> +++ b/gcc/postreload.c
> @@ -839,7 +839,7 @@ fixup_debug_insns (rtx reg, rtx replacement, rtx_insn *from, rtx_insn *to)
>      {
>        rtx t;
>
> -      if (!DEBUG_INSN_P (insn))
> +      if (!BIND_DEBUG_INSN_P (insn))
>         continue;
>
>        t = INSN_VAR_LOCATION_LOC (insn);
> diff --git a/gcc/print-rtl.c b/gcc/print-rtl.c
> index 79ec463..d206831 100644
> --- a/gcc/print-rtl.c
> +++ b/gcc/print-rtl.c
> @@ -258,6 +258,17 @@ rtx_writer::print_rtx_operand_code_0 (const_rtx in_rtx ATTRIBUTE_UNUSED,
>           fputc ('\t', m_outfile);
>           break;
>
> +       case NOTE_INSN_BEGIN_STMT:
> +       case NOTE_INSN_INLINE_ENTRY:
> +#ifndef GENERATOR_FILE
> +         {
> +           expanded_location xloc
> +             = expand_location (NOTE_MARKER_LOCATION (in_rtx));
> +           fprintf (m_outfile, " %s:%i", xloc.file, xloc.line);
> +         }
> +#endif
> +         break;
> +
>         default:
>           break;
>         }
> @@ -1791,6 +1802,24 @@ print_insn (pretty_printer *pp, const rtx_insn *x, int verbose)
>
>      case DEBUG_INSN:
>        {
> +       if (MARKER_DEBUG_INSN_P (x))
> +         {
> +           switch (INSN_DEBUG_MARKER_KIND (x))
> +             {
> +             case NOTE_INSN_BEGIN_STMT:
> +               pp_string (pp, "debug begin stmt marker");
> +               break;
> +
> +             case NOTE_INSN_INLINE_ENTRY:
> +               pp_string (pp, "debug inline entry marker");
> +               break;
> +
> +             default:
> +               gcc_unreachable ();
> +             }
> +           break;
> +         }
> +
>         const char *name = "?";
>
>         if (DECL_P (INSN_VAR_LOCATION_DECL (x)))
> diff --git a/gcc/recog.c b/gcc/recog.c
> index fd4e460..08d1330 100644
> --- a/gcc/recog.c
> +++ b/gcc/recog.c
> @@ -2258,6 +2258,8 @@ extract_insn (rtx_insn *insn)
>      case ADDR_VEC:
>      case ADDR_DIFF_VEC:
>      case VAR_LOCATION:
> +    case BEGIN_STMT_MARKER:
> +    case LEXICAL_BLOCK:
>        return;
>
>      case SET:
> diff --git a/gcc/reg-stack.c b/gcc/reg-stack.c
> index 41ae7e4..097952c 100644
> --- a/gcc/reg-stack.c
> +++ b/gcc/reg-stack.c
> @@ -3028,7 +3028,7 @@ convert_regs_1 (basic_block block)
>
>        /* Don't bother processing unless there is a stack reg
>          mentioned or if it's a CALL_INSN.  */
> -      if (DEBUG_INSN_P (insn))
> +      if (BIND_DEBUG_INSN_P (insn))
>         {
>           if (starting_stack_p)
>             debug_insns_with_starting_stack++;
> @@ -3068,7 +3068,7 @@ convert_regs_1 (basic_block block)
>        for (insn = BB_HEAD (block); debug_insns_with_starting_stack;
>            insn = NEXT_INSN (insn))
>         {
> -         if (!DEBUG_INSN_P (insn))
> +         if (!BIND_DEBUG_INSN_P (insn))
>             continue;
>
>           debug_insns_with_starting_stack--;
> diff --git a/gcc/regcprop.c b/gcc/regcprop.c
> index 367d85a..0bfe691 100644
> --- a/gcc/regcprop.c
> +++ b/gcc/regcprop.c
> @@ -436,6 +436,8 @@ find_oldest_value_reg (enum reg_class cl, rtx reg, struct value_data *vd)
>    machine_mode mode = GET_MODE (reg);
>    unsigned int i;
>
> +  gcc_assert (regno < FIRST_PSEUDO_REGISTER);
> +
>    /* If we are accessing REG in some mode other that what we set it in,
>       make sure that the replacement is valid.  In particular, consider
>         (set (reg:DI r11) (...))
> @@ -763,7 +765,7 @@ copyprop_hardreg_forward_1 (basic_block bb, struct value_data *vd)
>        next = NEXT_INSN (insn);
>        if (!NONDEBUG_INSN_P (insn))
>         {
> -         if (DEBUG_INSN_P (insn))
> +         if (BIND_DEBUG_INSN_P (insn))
>             {
>               rtx loc = INSN_VAR_LOCATION_LOC (insn);
>               if (!VAR_LOC_UNKNOWN_P (loc))
> diff --git a/gcc/regrename.c b/gcc/regrename.c
> index 5803664..bd73b53 100644
> --- a/gcc/regrename.c
> +++ b/gcc/regrename.c
> @@ -1876,7 +1876,7 @@ build_def_use (basic_block bb)
>             if (REG_NOTE_KIND (note) == REG_CFA_RESTORE)
>               scan_rtx (insn, &XEXP (note, 0), NO_REGS, mark_all_read, OP_IN);
>         }
> -      else if (DEBUG_INSN_P (insn)
> +      else if (BIND_DEBUG_INSN_P (insn)
>                && !VAR_LOC_UNKNOWN_P (INSN_VAR_LOCATION_LOC (insn)))
>         {
>           scan_rtx (insn, &INSN_VAR_LOCATION_LOC (insn),
> diff --git a/gcc/rtl.def b/gcc/rtl.def
> index 4c2607a..77047c1 100644
> --- a/gcc/rtl.def
> +++ b/gcc/rtl.def
> @@ -761,6 +761,12 @@ DEF_RTL_EXPR(ENTRY_VALUE, "entry_value", "0", RTX_OBJ)
>     been optimized away completely.  */
>  DEF_RTL_EXPR(DEBUG_PARAMETER_REF, "debug_parameter_ref", "t", RTX_OBJ)
>
> +/* Used in marker DEBUG_INSNs to avoid being recognized as an insn.  */
> +DEF_RTL_EXPR(BEGIN_STMT_MARKER, "begin_stmt_marker", "", RTX_OBJ)
> +
> +/* Used in marker DEBUG_INSNs to refer to a lexical block.  */
> +DEF_RTL_EXPR(LEXICAL_BLOCK, "lexical_block", "t", RTX_OBJ)
> +
>  /* All expressions from this point forward appear only in machine
>     descriptions.  */
>  #ifdef GENERATOR_FILE
> diff --git a/gcc/rtl.h b/gcc/rtl.h
> index 8a68bb1..dd5a74f1 100644
> --- a/gcc/rtl.h
> +++ b/gcc/rtl.h
> @@ -815,7 +815,8 @@ struct GTY(()) rtvec_def {
>  #define NONDEBUG_INSN_P(X) (INSN_P (X) && !DEBUG_INSN_P (X))
>
>  /* Nonzero if DEBUG_INSN_P may possibly hold.  */
> -#define MAY_HAVE_DEBUG_INSNS (flag_var_tracking_assignments)
> +#define MAY_HAVE_DEBUG_INSNS                                   \
> +  (flag_var_tracking_assignments || debug_nonbind_markers_p)
>
>  /* Predicate yielding nonzero iff X is a real insn.  */
>  #define INSN_P(X) \
> @@ -1585,6 +1586,7 @@ extern const char * const reg_note_name[];
>  #define NOTE_EH_HANDLER(INSN)  XCINT (INSN, 3, NOTE)
>  #define NOTE_BASIC_BLOCK(INSN) XCBBDEF (INSN, 3, NOTE)
>  #define NOTE_VAR_LOCATION(INSN)        XCEXP (INSN, 3, NOTE)
> +#define NOTE_MARKER_LOCATION(INSN) XCUINT (INSN, 3, NOTE)
>  #define NOTE_CFI(INSN)         XCCFI (INSN, 3, NOTE)
>  #define NOTE_LABEL_NUMBER(INSN)        XCINT (INSN, 3, NOTE)
>
> @@ -1596,6 +1598,13 @@ extern const char * const reg_note_name[];
>  #define NOTE_INSN_BASIC_BLOCK_P(INSN) \
>    (NOTE_P (INSN) && NOTE_KIND (INSN) == NOTE_INSN_BASIC_BLOCK)
>
> +/* Nonzero if INSN is a debug nonbind marker note,
> +   for which NOTE_MARKER_LOCATION can be used.  */
> +#define NOTE_MARKER_P(INSN)                            \
> +  (NOTE_P (INSN) &&                                    \
> +   (NOTE_KIND (INSN) == NOTE_INSN_BEGIN_STMT           \
> +    || NOTE_KIND (INSN) == NOTE_INSN_INLINE_ENTRY))
> +
>  /* Variable declaration and the location of a variable.  */
>  #define PAT_VAR_LOCATION_DECL(PAT) (XCTREE ((PAT), 0, VAR_LOCATION))
>  #define PAT_VAR_LOCATION_LOC(PAT) (XCEXP ((PAT), 1, VAR_LOCATION))
> @@ -1615,8 +1624,33 @@ extern const char * const reg_note_name[];
>  #define NOTE_VAR_LOCATION_STATUS(NOTE) \
>    PAT_VAR_LOCATION_STATUS (NOTE_VAR_LOCATION (NOTE))
>
> +/* Evaluate to TRUE if INSN is a debug insn that denotes a variable
> +   location/value tracking annotation.  */
> +#define BIND_DEBUG_INSN_P(INSN)                        \
> +  (DEBUG_INSN_P (INSN)                         \
> +   && (GET_CODE (PATTERN (INSN))               \
> +       == VAR_LOCATION))
> +/* Evaluate to TRUE if INSN is a debug insn that denotes a program
> +   source location marker.  */
> +#define MARKER_DEBUG_INSN_P(INSN)              \
> +  (DEBUG_INSN_P (INSN)                         \
> +   && (GET_CODE (PATTERN (INSN))               \
> +       != VAR_LOCATION))
> +/* Evaluate to the marker kind.  Currently the only kind is
> +   BEGIN_STMT.  */
> +#define INSN_DEBUG_MARKER_KIND(INSN)             \
> +  (GET_CODE (PATTERN (INSN)) == BEGIN_STMT_MARKER \
> +   ? NOTE_INSN_BEGIN_STMT                        \
> +   : GET_CODE (PATTERN (INSN)) == LEXICAL_BLOCK          \
> +   ? NOTE_INSN_INLINE_ENTRY                      \
> +   : (enum insn_note)-1)
> +
>  /* The VAR_LOCATION rtx in a DEBUG_INSN.  */
> -#define INSN_VAR_LOCATION(INSN) PATTERN (INSN)
> +#define INSN_VAR_LOCATION(INSN) \
> +  (RTL_FLAG_CHECK1 ("INSN_VAR_LOCATION", PATTERN (INSN), VAR_LOCATION))
> +/* A pointer to the VAR_LOCATION rtx in a DEBUG_INSN.  */
> +#define INSN_VAR_LOCATION_PTR(INSN) \
> +  (&PATTERN (INSN))
>
>  /* Accessors for a tree-expanded var location debug insn.  */
>  #define INSN_VAR_LOCATION_DECL(INSN) \
> @@ -1648,6 +1682,9 @@ extern const char * const reg_note_name[];
>  /* PARM_DECL DEBUG_PARAMETER_REF references.  */
>  #define DEBUG_PARAMETER_REF_DECL(RTX) XCTREE (RTX, 0, DEBUG_PARAMETER_REF)
>
> +/* The lexical block referenced by the LEXICAL_BLOCK RTX.  */
> +#define LEXICAL_BLOCK_TREE(RTX) XCTREE (RTX, 0, LEXICAL_BLOCK)
> +
>  /* Codes that appear in the NOTE_KIND field for kinds of notes
>     that are not line numbers.  These codes are all negative.
>
> @@ -2898,13 +2935,13 @@ extern rtx_call_insn *last_call_insn (void);
>  extern rtx_insn *previous_insn (rtx_insn *);
>  extern rtx_insn *next_insn (rtx_insn *);
>  extern rtx_insn *prev_nonnote_insn (rtx_insn *);
> -extern rtx_insn *prev_nonnote_insn_bb (rtx_insn *);
>  extern rtx_insn *next_nonnote_insn (rtx_insn *);
> -extern rtx_insn *next_nonnote_insn_bb (rtx_insn *);
>  extern rtx_insn *prev_nondebug_insn (rtx_insn *);
>  extern rtx_insn *next_nondebug_insn (rtx_insn *);
>  extern rtx_insn *prev_nonnote_nondebug_insn (rtx_insn *);
> +extern rtx_insn *prev_nonnote_nondebug_insn_bb (rtx_insn *);
>  extern rtx_insn *next_nonnote_nondebug_insn (rtx_insn *);
> +extern rtx_insn *next_nonnote_nondebug_insn_bb (rtx_insn *);
>  extern rtx_insn *prev_real_insn (rtx_insn *);
>  extern rtx_insn *next_real_insn (rtx);
>  extern rtx_insn *prev_active_insn (rtx_insn *);
> diff --git a/gcc/sdbout.c b/gcc/sdbout.c
> index a67f9d6..e21a65d 100644
> --- a/gcc/sdbout.c
> +++ b/gcc/sdbout.c
> @@ -307,6 +307,7 @@ const struct gcc_debug_hooks sdb_debug_hooks =
>    sdbout_label,                                 /* label */
>    debug_nothing_int,                    /* handle_pch */
>    debug_nothing_rtx_insn,               /* var_location */
> +  debug_nothing_tree,                   /* inline_entry */
>    debug_nothing_tree,                   /* size_function */
>    debug_nothing_void,                    /* switch_text_section */
>    debug_nothing_tree_tree,              /* set_name */
> diff --git a/gcc/toplev.c b/gcc/toplev.c
> index d23714c..cf6d3e6 100644
> --- a/gcc/toplev.c
> +++ b/gcc/toplev.c
> @@ -1534,6 +1534,18 @@ process_options (void)
>      warning_at (UNKNOWN_LOCATION, 0,
>                 "var-tracking-assignments changes selective scheduling");
>
> +  if (debug_nonbind_markers_p == AUTODETECT_VALUE)
> +    debug_nonbind_markers_p = optimize && debug_info_level >= DINFO_LEVEL_NORMAL
> +      && (write_symbols == DWARF2_DEBUG || write_symbols == VMS_AND_DWARF2_DEBUG);
> +
> +  if (debug_variable_location_views == AUTODETECT_VALUE)
> +    {
> +      debug_variable_location_views = flag_var_tracking
> +       && debug_info_level >= DINFO_LEVEL_NORMAL
> +       && (write_symbols == DWARF2_DEBUG || write_symbols == VMS_AND_DWARF2_DEBUG)
> +       && !dwarf_strict;
> +    }
> +
>    if (flag_tree_cselim == AUTODETECT_VALUE)
>      {
>        if (HAVE_conditional_move)
> diff --git a/gcc/tree-cfg.c b/gcc/tree-cfg.c
> index f26b12f..3a045d9 100644
> --- a/gcc/tree-cfg.c
> +++ b/gcc/tree-cfg.c
> @@ -545,14 +545,22 @@ make_blocks_1 (gimple_seq seq, basic_block bb)
>  {
>    gimple_stmt_iterator i = gsi_start (seq);
>    gimple *stmt = NULL;
> +  gimple *prev_stmt = NULL;
>    bool start_new_block = true;
>    bool first_stmt_of_seq = true;
>
>    while (!gsi_end_p (i))
>      {
> -      gimple *prev_stmt;
> -
> -      prev_stmt = stmt;
> +      /* PREV_STMT should only be set to a debug stmt if the debug
> +        stmt is before nondebug stmts.  Once stmt reaches a nondebug
> +        nonlabel, prev_stmt will be set to it, so that
> +        stmt_starts_bb_p will know to start a new block if a label is
> +        found.  However, if stmt was a label after debug stmts only,
> +        keep the label in prev_stmt even if we find further debug
> +        stmts, for there may be other labels after them, and they
> +        should land in the same block.  */
> +      if (!prev_stmt || !stmt || !is_gimple_debug (stmt))
> +       prev_stmt = stmt;
>        stmt = gsi_stmt (i);
>
>        if (stmt && is_gimple_call (stmt))
> @@ -567,6 +575,7 @@ make_blocks_1 (gimple_seq seq, basic_block bb)
>             gsi_split_seq_before (&i, &seq);
>           bb = create_basic_block (seq, bb);
>           start_new_block = false;
> +         prev_stmt = NULL;
>         }
>
>        /* Now add STMT to BB and create the subgraphs for special statement
> @@ -980,7 +989,11 @@ make_edges (void)
>               tree target;
>
>               if (!label_stmt)
> -               break;
> +               {
> +                 if (is_gimple_debug (gsi_stmt (gsi)))
> +                   continue;
> +                 break;
> +               }
>
>               target = gimple_label_label (label_stmt);
>
> @@ -1495,6 +1508,9 @@ cleanup_dead_labels (void)
>
>        for (i = gsi_start_bb (bb); !gsi_end_p (i); gsi_next (&i))
>         {
> +         if (is_gimple_debug (gsi_stmt (i)))
> +           continue;
> +
>           tree label;
>           glabel *label_stmt = dyn_cast <glabel *> (gsi_stmt (i));
>
> @@ -1655,6 +1671,12 @@ cleanup_dead_labels (void)
>
>        for (i = gsi_start_bb (bb); !gsi_end_p (i); )
>         {
> +         if (is_gimple_debug (gsi_stmt (i)))
> +           {
> +             gsi_next (&i);
> +             continue;
> +           }
> +
>           tree label;
>           glabel *label_stmt = dyn_cast <glabel *> (gsi_stmt (i));
>
> @@ -1823,6 +1845,8 @@ gimple_can_merge_blocks_p (basic_block a, basic_block b)
>         gsi_next (&gsi))
>      {
>        tree lab;
> +      if (is_gimple_debug (gsi_stmt (gsi)))
> +       continue;
>        glabel *label_stmt = dyn_cast <glabel *> (gsi_stmt (gsi));
>        if (!label_stmt)
>         break;
> @@ -2625,6 +2649,13 @@ stmt_starts_bb_p (gimple *stmt, gimple *prev_stmt)
>    if (stmt == NULL)
>      return false;
>
> +  /* PREV_STMT is only set to a debug stmt if the debug stmt is before
> +     any nondebug stmts in the block.  We don't want to start another
> +     block in this case: the debug stmt will already have started the
> +     one STMT would start if we weren't outputting debug stmts.  */
> +  if (prev_stmt && is_gimple_debug (prev_stmt))
> +    return false;
> +
>    /* Labels start a new basic block only if the preceding statement
>       wasn't a label of the same type.  This prevents the creation of
>       consecutive blocks that have nothing but a single label.  */
> @@ -5357,6 +5388,10 @@ gimple_verify_flow_info (void)
>        for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
>         {
>           tree label;
> +
> +         if (is_gimple_debug (gsi_stmt (gsi)))
> +           continue;
> +
>           gimple *prev_stmt = stmt;
>
>           stmt = gsi_stmt (gsi);
> @@ -5426,7 +5461,7 @@ gimple_verify_flow_info (void)
>             }
>         }
>
> -      gsi = gsi_last_bb (bb);
> +      gsi = gsi_last_nondebug_bb (bb);
>        if (gsi_end_p (gsi))
>         continue;
>
> @@ -5681,8 +5716,10 @@ gimple_block_label (basic_block bb)
>    tree label;
>    glabel *stmt;
>
> -  for (i = s; !gsi_end_p (i); first = false, gsi_next (&i))
> +  for (i = s; !gsi_end_p (i); gsi_next (&i))
>      {
> +      if (is_gimple_debug (gsi_stmt (i)))
> +       continue;
>        stmt = dyn_cast <glabel *> (gsi_stmt (i));
>        if (!stmt)
>         break;
> @@ -5693,6 +5730,7 @@ gimple_block_label (basic_block bb)
>             gsi_move_before (&i, &s);
>           return label;
>         }
> +      first = false;
>      }
>
>    label = create_artificial_label (UNKNOWN_LOCATION);
> @@ -5768,7 +5806,7 @@ gimple_redirect_edge_and_branch (edge e, basic_block dest)
>         return ret;
>      }
>
> -  gsi = gsi_last_bb (bb);
> +  gsi = gsi_last_nondebug_bb (bb);
>    stmt = gsi_end_p (gsi) ? NULL : gsi_stmt (gsi);
>
>    switch (stmt ? gimple_code (stmt) : GIMPLE_ERROR_MARK)
> diff --git a/gcc/tree-cfgcleanup.c b/gcc/tree-cfgcleanup.c
> index c6e5c8d..3ba760f 100644
> --- a/gcc/tree-cfgcleanup.c
> +++ b/gcc/tree-cfgcleanup.c
> @@ -506,13 +506,13 @@ remove_forwarder_block (basic_block bb)
>      {
>        tree decl;
>        label = gsi_stmt (gsi);
> -      if (is_gimple_debug (label))
> -       break;
> -      decl = gimple_label_label (as_a <glabel *> (label));
> -      if (EH_LANDING_PAD_NR (decl) != 0
> -         || DECL_NONLOCAL (decl)
> -         || FORCED_LABEL (decl)
> -         || !DECL_ARTIFICIAL (decl))
> +      if (is_gimple_debug (label)
> +         ? can_move_debug_stmts
> +         : ((decl = gimple_label_label (as_a <glabel *> (label))),
> +            EH_LANDING_PAD_NR (decl) != 0
> +            || DECL_NONLOCAL (decl)
> +            || FORCED_LABEL (decl)
> +            || !DECL_ARTIFICIAL (decl)))
>         {
>           gsi_remove (&gsi, false);
>           gsi_insert_before (&gsi_to, label, GSI_SAME_STMT);
> @@ -521,20 +521,6 @@ remove_forwarder_block (basic_block bb)
>         gsi_next (&gsi);
>      }
>
> -  /* Move debug statements if the destination has a single predecessor.  */
> -  if (can_move_debug_stmts)
> -    {
> -      gsi_to = gsi_after_labels (dest);
> -      for (gsi = gsi_after_labels (bb); !gsi_end_p (gsi); )
> -       {
> -         gimple *debug = gsi_stmt (gsi);
> -         if (!is_gimple_debug (debug))
> -           break;
> -         gsi_remove (&gsi, false);
> -         gsi_insert_before (&gsi_to, debug, GSI_SAME_STMT);
> -       }
> -    }
> -
>    bitmap_set_bit (cfgcleanup_altered_bbs, dest->index);
>
>    /* Update the dominators.  */
> @@ -1236,7 +1222,8 @@ execute_cleanup_cfg_post_optimizing (void)
>
>           flag_dump_noaddr = flag_dump_unnumbered = 1;
>           fprintf (final_output, "\n");
> -         dump_enumerated_decls (final_output, dump_flags | TDF_NOUID);
> +         dump_enumerated_decls (final_output,
> +                                dump_flags | TDF_SLIM | TDF_NOUID);
>           flag_dump_noaddr = save_noaddr;
>           flag_dump_unnumbered = save_unnumbered;
>           if (fclose (final_output))
> diff --git a/gcc/tree-inline.c b/gcc/tree-inline.c
> index affde64..f1c94ac 100644
> --- a/gcc/tree-inline.c
> +++ b/gcc/tree-inline.c
> @@ -53,6 +53,7 @@ along with GCC; see the file COPYING3.  If not see
>  #include "tree-ssa.h"
>  #include "except.h"
>  #include "debug.h"
> +#include "params.h"
>  #include "value-prof.h"
>  #include "cfgloop.h"
>  #include "builtins.h"
> @@ -1347,7 +1348,9 @@ remap_gimple_stmt (gimple *stmt, copy_body_data *id)
>    gimple_seq stmts = NULL;
>
>    if (is_gimple_debug (stmt)
> -      && !opt_for_fn (id->dst_fn, flag_var_tracking_assignments))
> +      && (gimple_debug_nonbind_marker_p (stmt)
> +         ? !cfun->debug_nonbind_markers
> +         : !opt_for_fn (id->dst_fn, flag_var_tracking_assignments)))
>      return stmts;
>
>    /* Begin by recognizing trees that we'll completely rewrite for the
> @@ -1630,6 +1633,20 @@ remap_gimple_stmt (gimple *stmt, copy_body_data *id)
>           gimple_seq_add_stmt (&stmts, copy);
>           return stmts;
>         }
> +      if (gimple_debug_nonbind_marker_p (stmt))
> +       {
> +         /* If the inlined function has too many debug markers,
> +            don't copy them.  */
> +         if (id->src_cfun->debug_marker_count
> +             > PARAM_VALUE (PARAM_MAX_DEBUG_MARKER_COUNT))
> +           return stmts;
> +
> +         gdebug *copy = as_a <gdebug *> (gimple_copy (stmt));
> +         id->debug_stmts.safe_push (copy);
> +         gimple_seq_add_stmt (&stmts, copy);
> +         return stmts;
> +       }
> +      gcc_checking_assert (!is_gimple_debug (stmt));
>
>        /* Create a new deep copy of the statement.  */
>        copy = gimple_copy (stmt);
> @@ -1725,7 +1742,8 @@ remap_gimple_stmt (gimple *stmt, copy_body_data *id)
>        gimple_set_block (copy, *n);
>      }
>
> -  if (gimple_debug_bind_p (copy) || gimple_debug_source_bind_p (copy))
> +  if (gimple_debug_bind_p (copy) || gimple_debug_source_bind_p (copy)
> +      || gimple_debug_nonbind_marker_p (copy))
>      {
>        gimple_seq_add_stmt (&stmts, copy);
>        return stmts;
> @@ -2599,6 +2617,10 @@ maybe_move_debug_stmts_to_successors (copy_body_data *id, basic_block new_bb)
>               value = gimple_debug_source_bind_get_value (stmt);
>               new_stmt = gimple_build_debug_source_bind (var, value, stmt);
>             }
> +         else if (gimple_debug_nonbind_marker_p (stmt))
> +           {
> +             new_stmt = as_a <gdebug *> (gimple_copy (stmt));
> +           }
>           else
>             gcc_unreachable ();
>           gsi_insert_before (&dsi, new_stmt, GSI_SAME_STMT);
> @@ -2915,6 +2937,9 @@ copy_debug_stmt (gdebug *stmt, copy_body_data *id)
>        gimple_set_block (stmt, n ? *n : id->block);
>      }
>
> +  if (gimple_debug_nonbind_marker_p (stmt))
> +    return;
> +
>    /* Remap all the operands in COPY.  */
>    memset (&wi, 0, sizeof (wi));
>    wi.info = id;
> @@ -2923,8 +2948,10 @@ copy_debug_stmt (gdebug *stmt, copy_body_data *id)
>
>    if (gimple_debug_source_bind_p (stmt))
>      t = gimple_debug_source_bind_get_var (stmt);
> -  else
> +  else if (gimple_debug_bind_p (stmt))
>      t = gimple_debug_bind_get_var (stmt);
> +  else
> +    gcc_unreachable ();
>
>    if (TREE_CODE (t) == PARM_DECL && id->debug_map
>        && (n = id->debug_map->get (t)))
> @@ -4672,6 +4699,14 @@ expand_call_inline (basic_block bb, gimple *stmt, copy_body_data *id)
>                         GSI_NEW_STMT);
>      }
>    initialize_inlined_parameters (id, stmt, fn, bb);
> +  if (debug_nonbind_markers_p && id->block
> +      && inlined_function_outer_scope_p (id->block))
> +    {
> +      gimple_stmt_iterator si = gsi_last_bb (bb);
> +      gsi_insert_after (&si, gimple_build_debug_inline_entry
> +                       (id->block, DECL_SOURCE_LOCATION (fn)),
> +                       GSI_NEW_STMT);
> +    }
>
>    if (DECL_INITIAL (fn))
>      {
> diff --git a/gcc/tree-iterator.c b/gcc/tree-iterator.c
> index c485413..10e510d 100644
> --- a/gcc/tree-iterator.c
> +++ b/gcc/tree-iterator.c
> @@ -89,7 +89,7 @@ append_to_statement_list_1 (tree t, tree *list_p)
>  void
>  append_to_statement_list (tree t, tree *list_p)
>  {
> -  if (t && TREE_SIDE_EFFECTS (t))
> +  if (t && (TREE_SIDE_EFFECTS (t) || TREE_CODE (t) == DEBUG_BEGIN_STMT))
>      append_to_statement_list_1 (t, list_p);
>  }
>
> @@ -137,7 +137,8 @@ tsi_link_before (tree_stmt_iterator *i, tree t, enum tsi_iterator_update mode)
>        tail = head;
>      }
>
> -  TREE_SIDE_EFFECTS (i->container) = 1;
> +  if (TREE_CODE (t) != DEBUG_BEGIN_STMT)
> +    TREE_SIDE_EFFECTS (i->container) = 1;
>
>    cur = i->ptr;
>
> @@ -213,7 +214,8 @@ tsi_link_after (tree_stmt_iterator *i, tree t, enum tsi_iterator_update mode)
>        tail = head;
>      }
>
> -  TREE_SIDE_EFFECTS (i->container) = 1;
> +  if (TREE_CODE (t) != DEBUG_BEGIN_STMT)
> +    TREE_SIDE_EFFECTS (i->container) = 1;
>
>    cur = i->ptr;
>
> @@ -279,8 +281,9 @@ tsi_delink (tree_stmt_iterator *i)
>    i->ptr = next;
>  }
>
> -/* Return the first expression in a sequence of COMPOUND_EXPRs,
> -   or in a STATEMENT_LIST.  */
> +/* Return the first expression in a sequence of COMPOUND_EXPRs, or in
> +   a STATEMENT_LIST, disregarding DEBUG_BEGIN_STMTs, recursing into a
> +   STATEMENT_LIST if that's the first non-DEBUG_BEGIN_STMT.  */
>
>  tree
>  expr_first (tree expr)
> @@ -291,7 +294,20 @@ expr_first (tree expr)
>    if (TREE_CODE (expr) == STATEMENT_LIST)
>      {
>        struct tree_statement_list_node *n = STATEMENT_LIST_HEAD (expr);
> -      return n ? n->stmt : NULL_TREE;
> +      if (!n)
> +       return NULL_TREE;
> +      while (TREE_CODE (n->stmt) == DEBUG_BEGIN_STMT)
> +       {
> +         n = n->next;
> +         if (!n)
> +           return NULL_TREE;
> +       }
> +      /* If the first non-debug stmt is not a statement list, we
> +        already know it's what we're looking for.  */
> +      if (TREE_CODE (n->stmt) != STATEMENT_LIST)
> +       return n->stmt;
> +
> +      return expr_first (n->stmt);
>      }
>
>    while (TREE_CODE (expr) == COMPOUND_EXPR)
> @@ -300,8 +316,9 @@ expr_first (tree expr)
>    return expr;
>  }
>
> -/* Return the last expression in a sequence of COMPOUND_EXPRs,
> -   or in a STATEMENT_LIST.  */
> +/* Return the last expression in a sequence of COMPOUND_EXPRs, or in a
> +   STATEMENT_LIST, disregarding DEBUG_BEGIN_STMTs, recursing into a
> +   STATEMENT_LIST if that's the last non-DEBUG_BEGIN_STMT.  */
>
>  tree
>  expr_last (tree expr)
> @@ -312,7 +329,20 @@ expr_last (tree expr)
>    if (TREE_CODE (expr) == STATEMENT_LIST)
>      {
>        struct tree_statement_list_node *n = STATEMENT_LIST_TAIL (expr);
> -      return n ? n->stmt : NULL_TREE;
> +      if (!n)
> +       return NULL_TREE;
> +      while (TREE_CODE (n->stmt) == DEBUG_BEGIN_STMT)
> +       {
> +         n = n->prev;
> +         if (!n)
> +           return NULL_TREE;
> +       }
> +      /* If the last non-debug stmt is not a statement list, we
> +        already know it's what we're looking for.  */
> +      if (TREE_CODE (n->stmt) != STATEMENT_LIST)
> +       return n->stmt;
> +
> +      return expr_last (n->stmt);
>      }
>
>    while (TREE_CODE (expr) == COMPOUND_EXPR)
> diff --git a/gcc/tree-pretty-print.c b/gcc/tree-pretty-print.c
> index c7509af..255f84c 100644
> --- a/gcc/tree-pretty-print.c
> +++ b/gcc/tree-pretty-print.c
> @@ -3291,6 +3291,10 @@ dump_generic_node (pretty_printer *pp, tree node, int spc, dump_flags_t flags,
>        pp_string (pp, "_Cilk_sync");
>        break;
>
> +    case DEBUG_BEGIN_STMT:
> +      pp_string (pp, "# DEBUG BEGIN STMT");
> +      break;
> +
>      default:
>        NIY;
>      }
> @@ -3386,7 +3390,10 @@ print_declaration (pretty_printer *pp, tree t, int spc, dump_flags_t flags)
>           pp_space (pp);
>           pp_equal (pp);
>           pp_space (pp);
> -         dump_generic_node (pp, DECL_INITIAL (t), spc, flags, false);
> +         if (!(flags & TDF_SLIM))
> +           dump_generic_node (pp, DECL_INITIAL (t), spc, flags, false);
> +         else
> +           pp_string (pp, "<<< omitted >>>");
>         }
>      }
>
> diff --git a/gcc/tree-ssa-dce.c b/gcc/tree-ssa-dce.c
> index e62afad..703c359 100644
> --- a/gcc/tree-ssa-dce.c
> +++ b/gcc/tree-ssa-dce.c
> @@ -257,7 +257,8 @@ mark_stmt_if_obviously_necessary (gimple *stmt, bool aggressive)
>          easily locate the debug temp bind stmt for a use thereof,
>          would could refrain from marking all debug temps here, and
>          mark them only if they're used.  */
> -      if (!gimple_debug_bind_p (stmt)
> +      if (gimple_debug_nonbind_marker_p (stmt)
> +         || !gimple_debug_bind_p (stmt)
>           || gimple_debug_bind_has_value_p (stmt)
>           || TREE_CODE (gimple_debug_bind_get_var (stmt)) != DEBUG_EXPR_DECL)
>         mark_stmt_necessary (stmt, false);
> @@ -1448,8 +1449,7 @@ eliminate_unnecessary_stmts (void)
>                      dominate others.  Walking backwards, this should
>                      be the common case.  ??? Do we need to recompute
>                      dominators because of cfg_altered?  */
> -                 if (!MAY_HAVE_DEBUG_STMTS
> -                     || !first_dom_son (CDI_DOMINATORS, bb))
> +                 if (!first_dom_son (CDI_DOMINATORS, bb))
>                     delete_basic_block (bb);
>                   else
>                     {
> diff --git a/gcc/tree-ssa-live.c b/gcc/tree-ssa-live.c
> index 8738fe2..734d15d 100644
> --- a/gcc/tree-ssa-live.c
> +++ b/gcc/tree-ssa-live.c
> @@ -520,6 +520,11 @@ remove_unused_scope_block_p (tree scope, bool in_ctor_dtor_block)
>     else if (!BLOCK_SUPERCONTEXT (scope)
>              || TREE_CODE (BLOCK_SUPERCONTEXT (scope)) == FUNCTION_DECL)
>       unused = false;
> +   /* Preserve the block, it is referenced by at least the inline
> +      entry point marker.  */
> +   else if (debug_nonbind_markers_p
> +           && inlined_function_outer_scope_p (scope))
> +     unused = false;
>     /* Innermost blocks with no live variables nor statements can be always
>        eliminated.  */
>     else if (!nsubblocks)
> @@ -548,11 +553,13 @@ remove_unused_scope_block_p (tree scope, bool in_ctor_dtor_block)
>       }
>     else if (BLOCK_VARS (scope) || BLOCK_NUM_NONLOCALIZED_VARS (scope))
>       unused = false;
> -   /* See if this block is important for representation of inlined function.
> -      Inlined functions are always represented by block with
> -      block_ultimate_origin being set to FUNCTION_DECL and DECL_SOURCE_LOCATION
> -      set...  */
> -   else if (inlined_function_outer_scope_p (scope))
> +   /* See if this block is important for representation of inlined
> +      function.  Inlined functions are always represented by block
> +      with block_ultimate_origin being set to FUNCTION_DECL and
> +      DECL_SOURCE_LOCATION set, unless they expand to nothing...  But
> +      see above for the case of statement frontiers.  */
> +   else if (!debug_nonbind_markers_p
> +           && inlined_function_outer_scope_p (scope))
>       unused = false;
>     else
>     /* Verfify that only blocks with source location set
> @@ -640,6 +647,16 @@ dump_scope_block (FILE *file, int indent, tree scope, dump_flags_t flags)
>             fprintf (file, "#%i", BLOCK_NUMBER (origin));
>         }
>      }
> +  if (BLOCK_FRAGMENT_ORIGIN (scope))
> +    fprintf (file, " Fragment of : #%i",
> +            BLOCK_NUMBER (BLOCK_FRAGMENT_ORIGIN (scope)));
> +  else if (BLOCK_FRAGMENT_CHAIN (scope))
> +    {
> +      fprintf (file, " Fragment chain :");
> +      for (t = BLOCK_FRAGMENT_CHAIN (scope); t ;
> +          t = BLOCK_FRAGMENT_CHAIN (t))
> +       fprintf (file, " #%i", BLOCK_NUMBER (t));
> +    }
>    fprintf (file, " \n");
>    for (var = BLOCK_VARS (scope); var; var = DECL_CHAIN (var))
>      {
> diff --git a/gcc/tree-ssa-tail-merge.c b/gcc/tree-ssa-tail-merge.c
> index a65ff31..6771606 100644
> --- a/gcc/tree-ssa-tail-merge.c
> +++ b/gcc/tree-ssa-tail-merge.c
> @@ -1295,14 +1295,14 @@ find_duplicate (same_succ *same_succ, basic_block bb1, basic_block bb2)
>        tree label = gimple_label_label (as_a <glabel *> (gsi_stmt (gsi1)));
>        if (DECL_NONLOCAL (label) || FORCED_LABEL (label))
>         return;
> -      gsi_prev (&gsi1);
> +      gsi_prev_nondebug (&gsi1);
>      }
>    while (!gsi_end_p (gsi2) && gimple_code (gsi_stmt (gsi2)) == GIMPLE_LABEL)
>      {
>        tree label = gimple_label_label (as_a <glabel *> (gsi_stmt (gsi2)));
>        if (DECL_NONLOCAL (label) || FORCED_LABEL (label))
>         return;
> -      gsi_prev (&gsi2);
> +      gsi_prev_nondebug (&gsi2);
>      }
>    if (!(gsi_end_p (gsi1) && gsi_end_p (gsi2)))
>      return;
> diff --git a/gcc/tree-ssa-threadedge.c b/gcc/tree-ssa-threadedge.c
> index 536c471..1c221e2 100644
> --- a/gcc/tree-ssa-threadedge.c
> +++ b/gcc/tree-ssa-threadedge.c
> @@ -739,6 +739,8 @@ propagate_threaded_block_debug_into (basic_block dest, basic_block src)
>         var = gimple_debug_bind_get_var (stmt);
>        else if (gimple_debug_source_bind_p (stmt))
>         var = gimple_debug_source_bind_get_var (stmt);
> +      else if (gimple_debug_nonbind_marker_p (stmt))
> +       continue;
>        else
>         gcc_unreachable ();
>
> @@ -766,6 +768,8 @@ propagate_threaded_block_debug_into (basic_block dest, basic_block src)
>             var = gimple_debug_bind_get_var (stmt);
>           else if (gimple_debug_source_bind_p (stmt))
>             var = gimple_debug_source_bind_get_var (stmt);
> +         else if (gimple_debug_nonbind_marker_p (stmt))
> +           var = NULL;
>           else
>             gcc_unreachable ();
>
> @@ -777,7 +781,9 @@ propagate_threaded_block_debug_into (basic_block dest, basic_block src)
>              or somesuch.  Adding `&& bb == src' to the condition
>              below will preserve all potentially relevant debug
>              notes.  */
> -         if (vars && vars->add (var))
> +         if (!var)
> +           /* Just copy the stmt.  */;
> +         else if (vars && vars->add (var))
>             continue;
>           else if (!vars)
>             {
> diff --git a/gcc/tree.c b/gcc/tree.c
> index c493edd5..5e98e46 100644
> --- a/gcc/tree.c
> +++ b/gcc/tree.c
> @@ -1013,7 +1013,8 @@ make_node (enum tree_code code MEM_STAT_DECL)
>    switch (type)
>      {
>      case tcc_statement:
> -      TREE_SIDE_EFFECTS (t) = 1;
> +      if (code != DEBUG_BEGIN_STMT)
> +       TREE_SIDE_EFFECTS (t) = 1;
>        break;
>
>      case tcc_declaration:
> @@ -4405,7 +4406,10 @@ build1 (enum tree_code code, tree type, tree node MEM_STAT_DECL)
>      }
>
>    if (TREE_CODE_CLASS (code) == tcc_statement)
> -    TREE_SIDE_EFFECTS (t) = 1;
> +    {
> +      if (code != DEBUG_BEGIN_STMT)
> +       TREE_SIDE_EFFECTS (t) = 1;
> +    }
>    else switch (code)
>      {
>      case VA_ARG_EXPR:
> diff --git a/gcc/tree.def b/gcc/tree.def
> index 9f80c4d..e30e950 100644
> --- a/gcc/tree.def
> +++ b/gcc/tree.def
> @@ -382,6 +382,9 @@ DEFTREECODE (RESULT_DECL, "result_decl", tcc_declaration, 0)
>     DEBUG stmts.  */
>  DEFTREECODE (DEBUG_EXPR_DECL, "debug_expr_decl", tcc_declaration, 0)
>
> +/* A stmt that marks the beginning of a source statement.  */
> +DEFTREECODE (DEBUG_BEGIN_STMT, "debug_begin_stmt", tcc_statement, 0)
> +
>  /* A namespace declaration.  Namespaces appear in DECL_CONTEXT of other
>     _DECLs, providing a hierarchy of names.  */
>  DEFTREECODE (NAMESPACE_DECL, "namespace_decl", tcc_declaration, 0)
> diff --git a/gcc/tree.h b/gcc/tree.h
> index 46debc1..eaa4962 100644
> --- a/gcc/tree.h
> +++ b/gcc/tree.h
> @@ -1127,7 +1127,8 @@ extern void omp_clause_range_check_failed (const_tree, const char *, int,
>    ((int)TREE_INT_CST_LOW (VL_EXP_CHECK (NODE)->exp.operands[0]))
>
>  /* Nonzero if is_gimple_debug() may possibly hold.  */
> -#define MAY_HAVE_DEBUG_STMTS    (flag_var_tracking_assignments)
> +#define MAY_HAVE_DEBUG_STMTS                                   \
> +  (flag_var_tracking_assignments || debug_nonbind_markers_p)
>
>  /* In a LOOP_EXPR node.  */
>  #define LOOP_EXPR_BODY(NODE) TREE_OPERAND_CHECK_CODE (NODE, LOOP_EXPR, 0)
> @@ -1219,7 +1220,7 @@ extern void protected_set_expr_location (tree, location_t);
>
>  /* GOTO_EXPR accessor. This gives access to the label associated with
>     a goto statement.  */
> -#define GOTO_DESTINATION(NODE)  TREE_OPERAND ((NODE), 0)
> +#define GOTO_DESTINATION(NODE)  TREE_OPERAND (GOTO_EXPR_CHECK (NODE), 0)
>
>  /* ASM_EXPR accessors. ASM_STRING returns a STRING_CST for the
>     instruction (e.g., "mov x, y"). ASM_OUTPUTS, ASM_INPUTS, and
> diff --git a/gcc/valtrack.c b/gcc/valtrack.c
> index 9e28d4b..2135458 100644
> --- a/gcc/valtrack.c
> +++ b/gcc/valtrack.c
> @@ -211,7 +211,7 @@ propagate_for_debug (rtx_insn *insn, rtx_insn *last, rtx dest, rtx src,
>      {
>        insn = next;
>        next = NEXT_INSN (insn);
> -      if (DEBUG_INSN_P (insn))
> +      if (BIND_DEBUG_INSN_P (insn))
>         {
>           loc = simplify_replace_fn_rtx (INSN_VAR_LOCATION_LOC (insn),
>                                          dest, propagate_for_debug_subst, &p);
> diff --git a/gcc/var-tracking.c b/gcc/var-tracking.c
> index 5c38c1d..d359517 100644
> --- a/gcc/var-tracking.c
> +++ b/gcc/var-tracking.c
> @@ -9471,6 +9471,24 @@ emit_notes_in_bb (basic_block bb, dataflow_set *set)
>      }
>  }
>
> +/* Return BB's head, unless BB is the block that succeeds ENTRY_BLOCK,
> +   in which case it searches back from BB's head for the very first
> +   insn.  Use [get_first_insn (bb), BB_HEAD (bb->next_bb)[ as a range
> +   to iterate over all insns of a function while iterating over its
> +   BBs.  */
> +
> +static rtx_insn *
> +get_first_insn (basic_block bb)
> +{
> +  rtx_insn *insn = BB_HEAD (bb);
> +
> +  if (bb->prev_bb == ENTRY_BLOCK_PTR_FOR_FN (cfun))
> +    while (rtx_insn *prev = PREV_INSN (insn))
> +      insn = prev;
> +
> +  return insn;
> +}
> +
>  /* Emit notes for the whole function.  */
>
>  static void
> @@ -9501,7 +9519,8 @@ vt_emit_notes (void)
>      {
>        /* Emit the notes for changes of variable locations between two
>          subsequent basic blocks.  */
> -      emit_notes_for_differences (BB_HEAD (bb), &cur, &VTI (bb)->in);
> +      emit_notes_for_differences (get_first_insn (bb),
> +                                 &cur, &VTI (bb)->in);
>
>        if (MAY_HAVE_DEBUG_INSNS)
>         local_get_addr_cache = new hash_map<rtx, rtx>;
> @@ -9901,6 +9920,37 @@ vt_init_cfa_base (void)
>    cselib_preserve_cfa_base_value (val, REGNO (cfa_base_rtx));
>  }
>
> +/* Reemit INSN, a MARKER_DEBUG_INSN, as a note.  */
> +
> +static rtx_insn *
> +reemit_marker_as_note (rtx_insn *insn, basic_block *bb)
> +{
> +  gcc_checking_assert (MARKER_DEBUG_INSN_P (insn));
> +
> +  enum insn_note kind = INSN_DEBUG_MARKER_KIND (insn);
> +
> +  switch (kind)
> +    {
> +    case NOTE_INSN_BEGIN_STMT:
> +    case NOTE_INSN_INLINE_ENTRY:
> +      {
> +       rtx_insn *note = NULL;
> +       if (cfun->debug_nonbind_markers)
> +         {
> +           note = emit_note_before (kind, insn);
> +           NOTE_MARKER_LOCATION (note) = INSN_LOCATION (insn);
> +           if (bb)
> +             BLOCK_FOR_INSN (note) = *bb;
> +         }
> +       delete_insn (insn);
> +       return note;
> +      }
> +
> +    default:
> +      gcc_unreachable ();
> +    }
> +}
> +
>  /* Allocate and initialize the data structures for variable tracking
>     and parse the RTL to get the micro operations.  */
>
> @@ -10097,11 +10147,34 @@ vt_initialize (void)
>         {
>           HOST_WIDE_INT offset = VTI (bb)->out.stack_adjust;
>           VTI (bb)->out.stack_adjust = VTI (bb)->in.stack_adjust;
> -         for (insn = BB_HEAD (bb); insn != NEXT_INSN (BB_END (bb));
> -              insn = NEXT_INSN (insn))
> +
> +         /* If we are walking the first basic block, walk any HEADER
> +            insns that might be before it too.  Unfortunately,
> +            BB_HEADER and BB_FOOTER are not set while we run this
> +            pass.  */
> +         insn = get_first_insn (bb);
> +         for (rtx_insn *next;
> +              insn != BB_HEAD (bb->next_bb)
> +                ? next = NEXT_INSN (insn), true : false;
> +              insn = next)
>             {
>               if (INSN_P (insn))
>                 {
> +                 basic_block save_bb = BLOCK_FOR_INSN (insn);
> +                 if (!BLOCK_FOR_INSN (insn))
> +                   {
> +                     BLOCK_FOR_INSN (insn) = bb;
> +                     gcc_assert (DEBUG_INSN_P (insn));
> +                     /* Reset debug insns between basic blocks.
> +                        Their location is not reliable, because they
> +                        were probably not maintained up to date.  */
> +                     if (BIND_DEBUG_INSN_P (insn))
> +                       INSN_VAR_LOCATION_LOC (insn)
> +                         = gen_rtx_UNKNOWN_VAR_LOC ();
> +                   }
> +                 else
> +                   gcc_assert (BLOCK_FOR_INSN (insn) == bb);
> +
>                   if (!frame_pointer_needed)
>                     {
>                       insn_stack_adjust_offset_pre_post (insn, &pre, &post);
> @@ -10123,6 +10196,12 @@ vt_initialize (void)
>                   adjust_insn (bb, insn);
>                   if (MAY_HAVE_DEBUG_INSNS)
>                     {
> +                     if (MARKER_DEBUG_INSN_P (insn))
> +                       {
> +                         insn = reemit_marker_as_note (insn, &save_bb);
> +                         continue;
> +                       }
> +
>                       if (CALL_P (insn))
>                         prepare_call_arguments (bb, insn);
>                       cselib_process_insn (insn);
> @@ -10169,6 +10248,7 @@ vt_initialize (void)
>                             }
>                         }
>                     }
> +                 BLOCK_FOR_INSN (insn) = save_bb;
>                 }
>             }
>           gcc_assert (offset == VTI (bb)->out.stack_adjust);
> @@ -10196,10 +10276,11 @@ vt_initialize (void)
>
>  static int debug_label_num = 1;
>
> -/* Get rid of all debug insns from the insn stream.  */
> +/* Remove from the insn stream all debug insns used for variable
> +   tracking at assignments.  */
>
>  static void
> -delete_debug_insns (void)
> +delete_vta_debug_insns (void)
>  {
>    basic_block bb;
>    rtx_insn *insn, *next;
> @@ -10209,9 +10290,18 @@ delete_debug_insns (void)
>
>    FOR_EACH_BB_FN (bb, cfun)
>      {
> -      FOR_BB_INSNS_SAFE (bb, insn, next)
> +      for (insn = get_first_insn (bb);
> +          insn != BB_HEAD (bb->next_bb)
> +            ? next = NEXT_INSN (insn), true : false;
> +          insn = next)
>         if (DEBUG_INSN_P (insn))
>           {
> +           if (MARKER_DEBUG_INSN_P (insn))
> +             {
> +               insn = reemit_marker_as_note (insn, NULL);
> +               continue;
> +             }
> +
>             tree decl = INSN_VAR_LOCATION_DECL (insn);
>             if (TREE_CODE (decl) == LABEL_DECL
>                 && DECL_NAME (decl)
> @@ -10237,10 +10327,13 @@ delete_debug_insns (void)
>     handled as well..  */
>
>  static void
> -vt_debug_insns_local (bool skipped ATTRIBUTE_UNUSED)
> +vt_debug_insns_local (bool skipped)
>  {
> -  /* ??? Just skip it all for now.  */
> -  delete_debug_insns ();
> +  /* ??? Just skip it all for now.  If we skipped the global pass,
> +     arrange for stmt markers to be dropped as well.  */
> +  if (skipped)
> +    cfun->debug_nonbind_markers = 0;
> +  delete_vta_debug_insns ();
>  }
>
>  /* Free the data structures needed for variable tracking.  */
> @@ -10305,15 +10398,21 @@ variable_tracking_main_1 (void)
>  {
>    bool success;
>
> -  if (flag_var_tracking_assignments < 0
> +  /* We won't be called as a separate pass if flag_var_tracking is not
> +     set, but final may call us to turn debug markers into notes.  */
> +  if ((!flag_var_tracking && MAY_HAVE_DEBUG_INSNS)
> +      || flag_var_tracking_assignments < 0
>        /* Var-tracking right now assumes the IR doesn't contain
>          any pseudos at this point.  */
>        || targetm.no_register_allocation)
>      {
> -      delete_debug_insns ();
> +      delete_vta_debug_insns ();
>        return 0;
>      }
>
> +  if (!flag_var_tracking)
> +    return 0;
> +
>    if (n_basic_blocks_for_fn (cfun) > 500 &&
>        n_edges_for_fn (cfun) / n_basic_blocks_for_fn (cfun) >= 20)
>      {
> @@ -10335,7 +10434,9 @@ variable_tracking_main_1 (void)
>      {
>        vt_finalize ();
>
> -      delete_debug_insns ();
> +      cfun->debug_nonbind_markers = 0;
> +
> +      delete_vta_debug_insns ();
>
>        /* This is later restored by our caller.  */
>        flag_var_tracking_assignments = 0;
> diff --git a/gcc/vmsdbgout.c b/gcc/vmsdbgout.c
> index 42300e2..557b76e 100644
> --- a/gcc/vmsdbgout.c
> +++ b/gcc/vmsdbgout.c
> @@ -203,6 +203,7 @@ const struct gcc_debug_hooks vmsdbg_debug_hooks
>     debug_nothing_rtx_code_label,  /* label */
>     debug_nothing_int,            /* handle_pch */
>     debug_nothing_rtx_insn,       /* var_location */
> +   debug_nothing_tree,           /* inline_entry */
>     debug_nothing_tree,           /* size_function */
>     debug_nothing_void,            /* switch_text_section */
>     debug_nothing_tree_tree,      /* set_name */
> diff --git a/include/dwarf2.def b/include/dwarf2.def
> index a91e943..1d6d13b 100644
> --- a/include/dwarf2.def
> +++ b/include/dwarf2.def
> @@ -443,6 +443,8 @@ DW_AT (DW_AT_GNU_pubtypes, 0x2135)
>  /* Attribute for discriminator.
>     See http://gcc.gnu.org/wiki/Discriminator  */
>  DW_AT (DW_AT_GNU_discriminator, 0x2136)
> +DW_AT (DW_AT_GNU_locviews, 0x2137)
> +DW_AT (DW_AT_GNU_entry_view, 0x2138)
>  /* VMS extensions.  */
>  DW_AT (DW_AT_VMS_rtnbeg_pd_address, 0x2201)
>  /* GNAT extensions.  */
> diff --git a/include/dwarf2.h b/include/dwarf2.h
> index 14b6f22e..c6d410e3 100644
> --- a/include/dwarf2.h
> +++ b/include/dwarf2.h
> @@ -296,6 +296,14 @@ enum dwarf_location_list_entry_type
>      DW_LLE_start_end = 0x07,
>      DW_LLE_start_length = 0x08,
>
> +    /* <http://lists.dwarfstd.org/private.cgi/dwarf-discuss-dwarfstd.org/2017-April/004347.html>
> +       has the proposal for now; only available to list members.
> +
> +       A (possibly updated) copy of the proposal is available at
> +       <http://people.redhat.com/aoliva/papers/sfn/dwarf6-sfn-lvu.txt>.  */
> +    DW_LLE_GNU_view_pair = 0x09,
> +#define DW_LLE_view_pair DW_LLE_GNU_view_pair
> +
>      /* Former extension for Fission.
>         See http://gcc.gnu.org/wiki/DebugFission.  */
>      DW_LLE_GNU_end_of_list_entry = 0x00,
>
>
> --
> Alexandre Oliva, freedom fighter    http://FSFLA.org/~lxoliva/
> You must be the change you wish to see in the world. -- Gandhi
> Be Free! -- http://FSFLA.org/   FSF Latin America board member
> Free Software Evangelist|Red Hat Brasil GNU Toolchain Engineer


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]