diff mbox series

[9/9,IEPM] Introduce inline entry point markers

Message ID 20170930090827.6604-9-aoliva@redhat.com
State New
Headers show
Series [1/9,SFN] adjust RTL insn-walking API | expand

Commit Message

Alexandre Oliva Sept. 30, 2017, 9:08 a.m. UTC
Output DW_AT_entry_pc based on markers.

Introduce DW_AT_GNU_entry_view as a DWARF extension.

If views are enabled are we're not in strict compliance mode, output
DW_AT_GNU_entry_view if it might be nonzero.

This patch depends on SFN and LVU patchsets, and on the IEPM patch that
introduces the inline_entry debug hook.

for  include/ChangeLog

	* dwarf2.def (DW_AT_GNU_entry_view): New.

for  gcc/ChangeLog

	* cfgexpand.c (expand_gimple_basic_block): Handle inline entry
	markers.
	* dwarf2out.c (dwarf2_debug_hooks): Enable inline_entry hook.
	(BLOCK_INLINE_ENTRY_LABEL): New.
	(dwarf2out_var_location): Disregard inline entry markers.
	(inline_entry_data): New struct.
	(inline_entry_data_hasher): New hashtable type.
	(inline_entry_data_hasher::hash): New.
	(inline_entry_data_hasher::equal): New.
	(inline_entry_data_table): New variable.
	(add_high_low_attributes): Add DW_AT_entry_pc and
	DW_AT_GNU_entry_view attributes if a pending entry is found
	in inline_entry_data_table.  Add old entry_pc attribute only
	if debug nonbinding markers are disabled.
	(gen_inlined_subroutine_die): Set BLOCK_DIE if nonbinding
	markers are enabled.
	(block_within_block_p, dwarf2out_inline_entry): New.
	(dwarf2out_finish): Check that no entries remained in
	inline_entry_data_table.
	* final.c (reemit_insn_block_notes): Handle inline entry notes.
	(final_scan_insn, notice_source_line): Likewise.
	(rest_of_clean_state): Skip inline entry markers.
	* gimple-pretty-print.c (dump_gimple_debug): Handle inline entry
	markers.
	* gimple.c (gimple_build_debug_inline_entry): New.
	* gimple.h (enum gimple_debug_subcode): Add
	GIMPLE_DEBUG_INLINE_ENTRY.
	(gimple_build_debug_inline_entry): Declare.
	(gimple_debug_inline_entry_p): New.
	(gimple_debug_nonbind_marker_p): Adjust.
	* insn-notes.def (INLINE_ENTRY): New.
	* print-rtl.c (rtx_writer::print_rtx_operand_code_0): Handle
	inline entry marker notes.
	(print_insn): Likewise.
	* rtl.h	(NOTE_MARKER_P): Add INLINE_ENTRY support.
	(INSN_DEBUG_MARKER_KIND): Likewise.
	* tree-inline.c	(expand_call_inline): Build and insert
	debug_inline_entry stmt.
	* tree-ssa-live.c (remove_unused_scope_block_p): Preserve
	inline entry blocks early, if nonbind markers are enabled.
	(dump_scope_block): Dump fragment info.
	* var-tracking.c (reemit_marker_as_note): Handle inline entry note.
	* doc/gimple.texi (gimple_debug_inline_entry_p): New.
	(gimple_build_debug_inline_entry): New.
	* doc/invoke.texi (gstatement-frontiers, gno-statement-frontiers):
	Enable/disable inline entry points too.
	* doc/rtl.texi (NOTE_INSN_INLINE_ENTRY): New.
	(DEBUG_INSN): Describe inline entry markers.
---
 gcc/cfgexpand.c           |   9 +++
 gcc/doc/gimple.texi       |  18 +++++
 gcc/doc/rtl.texi          |  24 ++++--
 gcc/dwarf2out.c           | 186 +++++++++++++++++++++++++++++++++++++++++++++-
 gcc/final.c               |  26 +++++++
 gcc/gimple-pretty-print.c |  13 ++++
 gcc/gimple.c              |  21 ++++++
 gcc/gimple.h              |  18 ++++-
 gcc/insn-notes.def        |   4 +
 gcc/print-rtl.c           |   5 ++
 gcc/rtl.h                 |   5 +-
 gcc/tree-inline.c         |   7 ++
 gcc/tree-ssa-live.c       |  27 +++++--
 gcc/var-tracking.c        |   1 +
 include/dwarf2.def        |   1 +
 15 files changed, 349 insertions(+), 16 deletions(-)

Comments

Jeff Law Oct. 31, 2017, 5:58 a.m. UTC | #1
On 09/30/2017 03:08 AM, Alexandre Oliva wrote:
> Output DW_AT_entry_pc based on markers.
> 
> Introduce DW_AT_GNU_entry_view as a DWARF extension.
> 
> If views are enabled are we're not in strict compliance mode, output
> DW_AT_GNU_entry_view if it might be nonzero.
> 
> This patch depends on SFN and LVU patchsets, and on the IEPM patch that
> introduces the inline_entry debug hook.
> 
> for  include/ChangeLog
> 
> 	* dwarf2.def (DW_AT_GNU_entry_view): New.
> 
> for  gcc/ChangeLog
> 
> 	* cfgexpand.c (expand_gimple_basic_block): Handle inline entry
> 	markers.
> 	* dwarf2out.c (dwarf2_debug_hooks): Enable inline_entry hook.
> 	(BLOCK_INLINE_ENTRY_LABEL): New.
> 	(dwarf2out_var_location): Disregard inline entry markers.
> 	(inline_entry_data): New struct.
> 	(inline_entry_data_hasher): New hashtable type.
> 	(inline_entry_data_hasher::hash): New.
> 	(inline_entry_data_hasher::equal): New.
> 	(inline_entry_data_table): New variable.
> 	(add_high_low_attributes): Add DW_AT_entry_pc and
> 	DW_AT_GNU_entry_view attributes if a pending entry is found
> 	in inline_entry_data_table.  Add old entry_pc attribute only
> 	if debug nonbinding markers are disabled.
> 	(gen_inlined_subroutine_die): Set BLOCK_DIE if nonbinding
> 	markers are enabled.
> 	(block_within_block_p, dwarf2out_inline_entry): New.
> 	(dwarf2out_finish): Check that no entries remained in
> 	inline_entry_data_table.
> 	* final.c (reemit_insn_block_notes): Handle inline entry notes.
> 	(final_scan_insn, notice_source_line): Likewise.
> 	(rest_of_clean_state): Skip inline entry markers.
> 	* gimple-pretty-print.c (dump_gimple_debug): Handle inline entry
> 	markers.
> 	* gimple.c (gimple_build_debug_inline_entry): New.
> 	* gimple.h (enum gimple_debug_subcode): Add
> 	GIMPLE_DEBUG_INLINE_ENTRY.
> 	(gimple_build_debug_inline_entry): Declare.
> 	(gimple_debug_inline_entry_p): New.
> 	(gimple_debug_nonbind_marker_p): Adjust.
> 	* insn-notes.def (INLINE_ENTRY): New.
> 	* print-rtl.c (rtx_writer::print_rtx_operand_code_0): Handle
> 	inline entry marker notes.
> 	(print_insn): Likewise.
> 	* rtl.h	(NOTE_MARKER_P): Add INLINE_ENTRY support.
> 	(INSN_DEBUG_MARKER_KIND): Likewise.
> 	* tree-inline.c	(expand_call_inline): Build and insert
> 	debug_inline_entry stmt.
> 	* tree-ssa-live.c (remove_unused_scope_block_p): Preserve
> 	inline entry blocks early, if nonbind markers are enabled.
> 	(dump_scope_block): Dump fragment info.
> 	* var-tracking.c (reemit_marker_as_note): Handle inline entry note.
> 	* doc/gimple.texi (gimple_debug_inline_entry_p): New.
> 	(gimple_build_debug_inline_entry): New.
> 	* doc/invoke.texi (gstatement-frontiers, gno-statement-frontiers):
> 	Enable/disable inline entry points too.
> 	* doc/rtl.texi (NOTE_INSN_INLINE_ENTRY): New.
> 	(DEBUG_INSN): Describe inline entry markers.
> ---
> 
> diff --git a/gcc/cfgexpand.c b/gcc/cfgexpand.c
> index c854ffd..8ccdafd 100644
> --- a/gcc/cfgexpand.c
> +++ b/gcc/cfgexpand.c
> @@ -5691,6 +5691,15 @@ expand_gimple_basic_block (basic_block bb, bool disable_tail_calls)
>  		goto delink_debug_stmt;
>  	      else if (gimple_debug_begin_stmt_p (stmt))
>  		val = gen_rtx_DEBUG_MARKER (VOIDmode);
> +	      else if (gimple_debug_inline_entry_p (stmt))
> +		{
> +		  tree block = gimple_block (stmt);
> +
> +		  if (block)
> +		    val = gen_rtx_DEBUG_MARKER (BLKmode);
> +		  else
> +		    goto delink_debug_stmt;
> +		}
>  	      else
>  		gcc_unreachable ();
So again, I haven't looked at prior patches.  It seems to me like we're
abusing the mode of the debug marker rtx here.  Is that really the best
way to do things?  Would it be better to have different RTXs for the
marker or real arguments?  Or what about keying on the existence of
INSN_LOCATION?!?  Something just feels a bit icky here.



> +/* 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.  */
So this seemed reasonable up to here.  Based on the name and function
comment, I'd think at this point you'd be able to return true.  We found
OUTER in BLOCK's supercontext chain.

But you've got another blob of code.  So it seems like you're check more
than what the name/function comment imply.

Otherwise this patch seems pretty reasonable.

jeff
Alexandre Oliva Nov. 1, 2017, 6:35 p.m. UTC | #2
On Oct 31, 2017, Jeff Law <law@redhat.com> wrote:

>> @@ -5691,6 +5691,15 @@ expand_gimple_basic_block (basic_block bb, bool disable_tail_calls)
>> goto delink_debug_stmt;
>> else if (gimple_debug_begin_stmt_p (stmt))
>> val = gen_rtx_DEBUG_MARKER (VOIDmode);
>> +	      else if (gimple_debug_inline_entry_p (stmt))
>> +		{
>> +		  tree block = gimple_block (stmt);
>> +
>> +		  if (block)
>> +		    val = gen_rtx_DEBUG_MARKER (BLKmode);
>> +		  else
>> +		    goto delink_debug_stmt;
>> +		}
>> else
>> gcc_unreachable ();
> So again, I haven't looked at prior patches.  It seems to me like we're
> abusing the mode of the debug marker rtx here.

It is still abuse if it's documented in INSN_DEBUG_MARKER_KIND and
rtl.texi?  :-)

We need some way to tell the (currently) two kinds of markers apart.  I
didn't want yet another rtl code that would have to be added to cases
all over; the distinction between markers matters at only very few
points in the compiler.  I considered adding an operand to the debug
marker, to reference a const_int that could tell them apart with room
for growth to other kinds of markers, or using any of the flag bits, but
the mode was the most visibly unused mandatory rtl field in debug
markers, so I went for it.

Changing that would make for a very localized patch, touching only this
creation point, the macro that tells the kinds apart, and the
documentation, so if you'd rather have something else, I'll be glad to
comply.



>> +/* 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.  */
> So this seemed reasonable up to here.  Based on the name and function
> comment, I'd think at this point you'd be able to return true.  We found
> OUTER in BLOCK's supercontext chain.

The part you quoted looks at only at child-to-parent links; the other
part looks at parent-to-children links, to make sure they match.  The
function is a consistency check, used only in a checking assert.  It's
intended to check both links, that the parent is reachable by the child,
and that the child is reachable by the parent.  At some point, I had
blocks that had been disconnected and discarded from the lexical block
tree, but that remained pointed-to by markers; they still pointed to
their parents, but their parents no longer pointed to them.

> But you've got another blob of code.  So it seems like you're check more
> than what the name/function comment imply.

I guess I should expand the comments ;-)

Will do...
Jeff Law Nov. 9, 2017, 4:05 p.m. UTC | #3
On 11/01/2017 12:35 PM, Alexandre Oliva wrote:
> On Oct 31, 2017, Jeff Law <law@redhat.com> wrote:
> 
>>> @@ -5691,6 +5691,15 @@ expand_gimple_basic_block (basic_block bb, bool disable_tail_calls)
>>> goto delink_debug_stmt;
>>> else if (gimple_debug_begin_stmt_p (stmt))
>>> val = gen_rtx_DEBUG_MARKER (VOIDmode);
>>> +	      else if (gimple_debug_inline_entry_p (stmt))
>>> +		{
>>> +		  tree block = gimple_block (stmt);
>>> +
>>> +		  if (block)
>>> +		    val = gen_rtx_DEBUG_MARKER (BLKmode);
>>> +		  else
>>> +		    goto delink_debug_stmt;
>>> +		}
>>> else
>>> gcc_unreachable ();
>> So again, I haven't looked at prior patches.  It seems to me like we're
>> abusing the mode of the debug marker rtx here.
> 
> It is still abuse if it's documented in INSN_DEBUG_MARKER_KIND and
> rtl.texi?  :-)
It's just documented abuse, but it's still abuse.  Though there's
certainly other cases where we've used modes to carry odd information
(reload was notorious for that, which I think we fixed a little while
back with some of David M's work).





> 
> We need some way to tell the (currently) two kinds of markers apart. 
I figured out that much.

> I
> didn't want yet another rtl code that would have to be added to cases
> all over; the distinction between markers matters at only very few
> points in the compiler.  
Is it fair to say one is just a variant of the other?


I considered adding an operand to the debug
> marker, to reference a const_int that could tell them apart with room
> for growth to other kinds of markers, or using any of the flag bits, but
> the mode was the most visibly unused mandatory rtl field in debug
> markers, so I went for it.
Is there a bit we could use in the rtx flags?  Yes, it's harder to prove
correct, but I would be a bit surprised if there wasn't a free one for
the debug rtxs.

>
> 
> Changing that would make for a very localized patch, touching only this
> creation point, the macro that tells the kinds apart, and the
> documentation, so if you'd rather have something else, I'll be glad to
> comply.
Alternately, let's at least abstract things via a macro or getter/setter
type function so that we can change the implementation in the future
without having to do searches on mode twiddling.


> 
> 
> 
>>> +/* 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.  */
>> So this seemed reasonable up to here.  Based on the name and function
>> comment, I'd think at this point you'd be able to return true.  We found
>> OUTER in BLOCK's supercontext chain.
> 
> The part you quoted looks at only at child-to-parent links; the other
> part looks at parent-to-children links, to make sure they match.  The
> function is a consistency check, used only in a checking assert.  It's
> intended to check both links, that the parent is reachable by the child,
> and that the child is reachable by the parent.  At some point, I had
> blocks that had been disconnected and discarded from the lexical block
> tree, but that remained pointed-to by markers; they still pointed to
> their parents, but their parents no longer pointed to them.
Ah, if it's just a consistency check then it makes perfect sense.

Jeff
Alexandre Oliva Nov. 10, 2017, 1:11 a.m. UTC | #4
On Nov  9, 2017, Jeff Law <law@redhat.com> wrote:

>> I didn't want yet another rtl code that would have to be added to
>> cases all over; the distinction between markers matters at only very
>> few points in the compiler.

> Is it fair to say one is just a variant of the other?

I don't see them that way, but the fact that there's a name that applies
to a whole class of potential debug markers, two of which are
implemented in this patchset, could imply they are.  They're variants of
debug markers, and as such optimization passes should generally leave
them alone.  They are all supposed to carry information about relevant
points in the source program throughout compilation, but they differ in
what the points are.

They currently don't carry any information besides their lexical block
and source location information, which makes a single RTL code enough,
but this could change: stmt markers could link back to a representation
of the source statement, if we had one; inline entry point markers could
link back to the original call that was inlined; end-of-prologue markers
might require other kinds of data I can't think of; return value
assignment points and actual return points also come to mind.  These are
the markers I've thought of so far; many of them are no more than ideas
yet to be implemented.

> Is there a bit we could use in the rtx flags?

As long as we have only two kinds of markers, yes.  Even more than that,
probably.

Now, I've just looked at the actual data, and my concern that having
separate RTL codes would require them to appear in tons of locations is
unfounded.  The only occurrence of DEBUG_MARKER, aside from that in
macros defined in rtl.h, is in extract_insn.c.

OTOH, having multiple RTL codes to check for in e.g. DEBUG_MARKER_INSN_P
(or DEBUG_BIND_INSN_P) could have a larger impact on the compiler
performance than I would like; these macros are used very often, and
currently they have to test three RTL codes: DEBUG_INSN, and then either
VAR_LOCATION or DEBUG_MARKER.  As long as one of the classes has only
one RTL code, we can test by negating the other (like
DEBUG_MARKER_INSN_P currently tests that the pattern is *not*
VAR_LOCATION), but if both classes were to have more than one RTL code,
the tests would become more expensive.  So I strive to reduce the number
of codes tested for in such pervasive tests, and, should that become
unavoidable, to keep them in sequence, so that the compiler can optimize
a sequence of tests to a range test, or maybe use distinct RTX_CLASSes
for them.

>> Changing that would make for a very localized patch, touching only this
>> creation point, the macro that tells the kinds apart, and the
>> documentation, so if you'd rather have something else, I'll be glad to
>> comply.
> Alternately, let's at least abstract things via a macro or getter/setter
> type function so that we can change the implementation in the future
> without having to do searches on mode twiddling.

Done in a patch I'm about to push to the branch.  (I was just about to
post the updated patchset when I got your email; now it will be a bit
later ;-)
diff mbox series

Patch

diff --git a/gcc/cfgexpand.c b/gcc/cfgexpand.c
index c854ffd..8ccdafd 100644
--- a/gcc/cfgexpand.c
+++ b/gcc/cfgexpand.c
@@ -5691,6 +5691,15 @@  expand_gimple_basic_block (basic_block bb, bool disable_tail_calls)
 		goto delink_debug_stmt;
 	      else if (gimple_debug_begin_stmt_p (stmt))
 		val = gen_rtx_DEBUG_MARKER (VOIDmode);
+	      else if (gimple_debug_inline_entry_p (stmt))
+		{
+		  tree block = gimple_block (stmt);
+
+		  if (block)
+		    val = gen_rtx_DEBUG_MARKER (BLKmode);
+		  else
+		    goto delink_debug_stmt;
+		}
 	      else
 		gcc_unreachable ();
 
diff --git a/gcc/doc/gimple.texi b/gcc/doc/gimple.texi
index 6c9c4789..af39d75 100644
--- a/gcc/doc/gimple.texi
+++ b/gcc/doc/gimple.texi
@@ -836,6 +836,11 @@  Return true if g is a @code{GIMPLE_DEBUG} that marks the beginning of
 a source statement.
 @end deftypefn
 
+@deftypefn {GIMPLE function} gimple_debug_inline_entry_p (gimple g)
+Return true if g is a @code{GIMPLE_DEBUG} that marks the entry
+point of an inlined function.
+@end deftypefn
+
 @deftypefn {GIMPLE function} gimple_debug_nonbind_marker_p (gimple g)
 Return true if g is a @code{GIMPLE_DEBUG} that marks a program location,
 without any variable binding.
@@ -1539,6 +1544,7 @@  Set the conditional @code{COND_STMT} to be of the form 'if (1 == 1)'.
 @cindex @code{GIMPLE_DEBUG}
 @cindex @code{GIMPLE_DEBUG_BIND}
 @cindex @code{GIMPLE_DEBUG_BEGIN_STMT}
+@cindex @code{GIMPLE_DEBUG_INLINE_ENTRY}
 
 @deftypefn {GIMPLE function} gdebug *gimple_build_debug_bind (tree var, @
 tree value, gimple stmt)
@@ -1624,6 +1630,18 @@  observable, and that none of the side effects of subsequent user
 statements are.
 @end deftypefn
 
+@deftypefn {GIMPLE function} gimple gimple_build_debug_inline_entry (tree block, location_t location)
+Build a @code{GIMPLE_DEBUG} statement with
+@code{GIMPLE_DEBUG_INLINE_ENTRY} @code{subcode}.  The effect of this
+statement is to tell debug information generation machinery that a
+function call at @code{location} underwent inline substitution, that
+@code{block} is the enclosing lexical block created for the
+substitution, and that at the point of the program in which the stmt is
+inserted, all parameters for the inlined function are bound to the
+respective arguments, and none of the side effects of its stmts are
+observable.
+@end deftypefn
+
 @node @code{GIMPLE_EH_FILTER}
 @subsection @code{GIMPLE_EH_FILTER}
 @cindex @code{GIMPLE_EH_FILTER}
diff --git a/gcc/doc/rtl.texi b/gcc/doc/rtl.texi
index 888ab02..a2f6e7a 100644
--- a/gcc/doc/rtl.texi
+++ b/gcc/doc/rtl.texi
@@ -3430,7 +3430,10 @@  Refers to a parameter that was completely optimized out.
 @item (debug_marker:@var{mode})
 Marks a program location.  With @code{VOIDmode}, it stands for the
 beginning of a statement, a recommended inspection point logically after
-all prior side effects, and before any subsequent side effects.
+all prior side effects, and before any subsequent side effects.  With
+@code{BLKmode}, it indicates an inline entry point: the lexical block
+encoded in the @code{INSN_LOCATION} is the enclosing block that encloses
+the inlined function.
 
 @end table
 
@@ -3714,6 +3717,13 @@  This note is used to generate @code{is_stmt} markers in line number
 debuggign information.  It indicates the beginning of a user
 statement.
 
+@findex NOTE_INSN_INLINE_ENTRY
+@item NOTE_INSN_INLINE_ENTRY
+This note is used to generate @code{entry_pc} for inlined subroutines in
+debugging information.  It indicates an inspection point at which all
+arguments for the inlined function have been bound, and before its first
+statement.
+
 @end table
 
 These codes are printed symbolically when they appear in debugging dumps.
@@ -3731,8 +3741,12 @@  binds a user variable tree to an RTL representation of the
 it stands for the value bound to the corresponding
 @code{DEBUG_EXPR_DECL}.
 
-@code{GIMPLE_DEBUG_BEGIN_STMT} is expanded to RTL as a @code{DEBUG_INSN}
-with a @code{VOIDmode} @code{DEBUG_MARKER} @code{PATTERN}.  These
+@code{GIMPLE_DEBUG_BEGIN_STMT} and @code{GIMPLE_DEBUG_INLINE_ENTRY} are
+expanded to RTL as a @code{DEBUG_INSN} with a @code{DEBUG_MARKER}
+@code{PATTERN}; the difference is the RTL mode: the former's
+@code{DEBUG_MARKER} is @code{VOIDmode}, whereas the latter is
+@code{BLKmode}; information about the inlined function can be taken from
+the lexical block encoded in the @code{INSN_LOCATION}.  These
 @code{DEBUG_INSN}s, that do not carry @code{VAR_LOCATION} information,
 just @code{DEBUG_MARKER}s, can be detected by testing
 @code{DEBUG_MARKER_INSN_P}, whereas those that do can be recognized as
@@ -3743,8 +3757,8 @@  with respect to each other, particularly during scheduling.  Binding
 information is kept in pseudo-instruction form, so that, unlike notes,
 it gets the same treatment and adjustments that regular instructions
 would.  It is the variable tracking pass that turns these
-pseudo-instructions into @code{NOTE_INSN_VAR_LOCATION} and
-@code{NOTE_INSN_BEGIN_STMT} notes,
+pseudo-instructions into @code{NOTE_INSN_VAR_LOCATION},
+@code{NOTE_INSN_BEGIN_STMT} and @code{NOTE_INSN_INLINE_ENTRY} notes,
 analyzing control flow, value equivalences and changes to registers and
 memory referenced in value expressions, propagating the values of debug
 temporaries and determining expressions that can be used to compute the
diff --git a/gcc/dwarf2out.c b/gcc/dwarf2out.c
index f435b5a..ed7a85a 100644
--- a/gcc/dwarf2out.c
+++ b/gcc/dwarf2out.c
@@ -2720,6 +2720,7 @@  static void dwarf2out_imported_module_or_decl_1 (tree, tree, tree,
 						 dw_die_ref);
 static void dwarf2out_abstract_function (tree);
 static void dwarf2out_var_location (rtx_insn *);
+static void dwarf2out_inline_entry (tree);
 static void dwarf2out_size_function (tree);
 static void dwarf2out_begin_function (tree);
 static void dwarf2out_end_function (unsigned int);
@@ -2773,7 +2774,7 @@  const struct gcc_debug_hooks dwarf2_debug_hooks =
   debug_nothing_rtx_code_label,	/* label */
   debug_nothing_int,		/* handle_pch */
   dwarf2out_var_location,
-  debug_nothing_tree,		/* inline_entry */
+  dwarf2out_inline_entry,	/* inline_entry */
   dwarf2out_size_function,	/* size_function */
   dwarf2out_switch_text_section,
   dwarf2out_set_name,
@@ -4011,6 +4012,9 @@  static char ranges_base_label[2 * MAX_ARTIFICIAL_LABEL_BYTES];
 #ifndef BLOCK_BEGIN_LABEL
 #define BLOCK_BEGIN_LABEL	"LBB"
 #endif
+#ifndef BLOCK_INLINE_ENTRY_LABEL
+#define BLOCK_INLINE_ENTRY_LABEL "LBI"
+#endif
 #ifndef BLOCK_END_LABEL
 #define BLOCK_END_LABEL		"LBE"
 #endif
@@ -23004,6 +23008,48 @@  block_die_hasher::equal (die_struct *x, die_struct *y)
   return x->decl_id == y->decl_id && x->die_parent == y->die_parent;
 }
 
+/* Hold information about markers for inlined entry points.  */
+struct GTY ((for_user)) inline_entry_data
+{
+  /* The block that's the inlined_function_outer_scope for an inlined
+     function.  */
+  tree block;
+
+  /* The label at the inlined entry point.  */
+  const char *label_pfx;
+  unsigned int label_num;
+
+  /* The view number to be used as the inlined entry point.  */
+  var_loc_view view;
+};
+
+struct inline_entry_data_hasher : ggc_ptr_hash <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
@@ -23458,6 +23504,42 @@  add_high_low_attributes (tree stmt, dw_die_ref die)
 {
   char label[MAX_ARTIFICIAL_LABEL_BYTES];
 
+  if (inline_entry_data **iedp
+      = !inline_entry_data_table ? NULL
+      : inline_entry_data_table->find_slot_with_hash (stmt,
+						      htab_hash_pointer (stmt),
+						      NO_INSERT))
+    {
+      inline_entry_data *ied = *iedp;
+      gcc_assert (MAY_HAVE_DEBUG_MARKER_INSNS);
+      gcc_assert (inlined_function_outer_scope_p (stmt));
+      ASM_GENERATE_INTERNAL_LABEL (label, ied->label_pfx, ied->label_num);
+      add_AT_lbl_id (die, DW_AT_entry_pc, label);
+
+      if (debug_variable_location_views && !ZERO_VIEW_P (ied->view))
+	{
+	  if (!output_asm_line_debug_info ())
+	    add_AT_unsigned (die, DW_AT_GNU_entry_view, ied->view);
+	  else
+	    {
+	      ASM_GENERATE_INTERNAL_LABEL (label, "LVU", ied->view);
+	      /* FIXME: this will resolve to a small number.  Could we
+		 possibly emit smaller data?  Ideally we'd emit a
+		 uleb128, but that would make the size of DIEs
+		 impossible for the compiler to compute, since it's
+		 the assembler that computes the value of the view
+		 label in this case.  Ideally, we'd have a single form
+		 encompassing both the address and the view, and
+		 indirecting them through a table might make things
+		 easier, but even that would be more wasteful,
+		 space-wise, than what we have now.  */
+	      add_AT_lbl_id (die, DW_AT_GNU_entry_view, label);
+	    }
+	}
+
+      inline_entry_data_table->clear_slot (iedp);
+    }
+
   if (BLOCK_FRAGMENT_CHAIN (stmt)
       && (dwarf_version >= 3 || !dwarf_strict))
     {
@@ -23465,7 +23547,7 @@  add_high_low_attributes (tree stmt, dw_die_ref die)
       dw_die_ref pdie;
       dw_attr_node *attr = NULL;
 
-      if (inlined_function_outer_scope_p (stmt))
+      if (!MAY_HAVE_DEBUG_MARKER_INSNS && inlined_function_outer_scope_p (stmt))
 	{
 	  ASM_GENERATE_INTERNAL_LABEL (label, BLOCK_BEGIN_LABEL,
 				       BLOCK_NUMBER (stmt));
@@ -23630,7 +23712,7 @@  gen_inlined_subroutine_die (tree stmt, dw_die_ref context_die)
       dw_die_ref subr_die
 	= new_die (DW_TAG_inlined_subroutine, context_die, stmt);
 
-      if (call_arg_locations)
+      if (call_arg_locations || MAY_HAVE_DEBUG_MARKER_INSNS)
 	BLOCK_DIE (stmt) = subr_die;
       add_abstract_origin_attribute (subr_die, decl);
       if (TREE_ASM_WRITTEN (stmt))
@@ -26656,6 +26738,7 @@  dwarf2out_var_location (rtx_insn *loc_note)
       || ! NOTE_P (next_note)
       || (NOTE_KIND (next_note) != NOTE_INSN_VAR_LOCATION
 	  && NOTE_KIND (next_note) != NOTE_INSN_BEGIN_STMT
+	  && NOTE_KIND (next_note) != NOTE_INSN_INLINE_ENTRY
 	  && NOTE_KIND (next_note) != NOTE_INSN_CALL_ARG_LOCATION))
     next_note = NULL;
 
@@ -26844,6 +26927,100 @@  create_label:
   last_in_cold_section_p = in_cold_section_p;
 }
 
+/* Check whether BLOCK, a lexical block, is nested within OUTER, or is
+   OUTER itself.  */
+static bool
+block_within_block_p (tree block, tree outer)
+{
+  if (block == outer)
+    return true;
+
+  /* Quickly check that OUTER is up BLOCK's supercontext chain.  */
+  for (tree context = BLOCK_SUPERCONTEXT (block);
+       context != outer;
+       context = BLOCK_SUPERCONTEXT (context))
+    if (!context || TREE_CODE (context) != BLOCK)
+      return false;
+
+  /* Now check that each block is actually referenced by its
+     parent.  */
+  for (tree context = BLOCK_SUPERCONTEXT (block); ;
+       context = BLOCK_SUPERCONTEXT (context))
+    {
+      if (BLOCK_FRAGMENT_ORIGIN (context))
+	{
+	  gcc_assert (!BLOCK_SUBBLOCKS (context));
+	  context = BLOCK_FRAGMENT_ORIGIN (context);
+	}
+      for (tree sub = BLOCK_SUBBLOCKS (context);
+	   sub != block;
+	   sub = BLOCK_CHAIN (sub))
+	if (!sub)
+	  return false;
+      if (context == outer)
+	return true;
+      else
+	block = context;
+    }
+}
+
+/* Called during final while assembling the marker of the entry point
+   for an inlined function.  */
+
+static void
+dwarf2out_inline_entry (tree block)
+{
+  gcc_assert (DECL_P (block_ultimate_origin (block)));
+
+  gcc_checking_assert (block_within_block_p (block,
+					     DECL_INITIAL
+					     (current_function_decl)));
+
+  gcc_assert (inlined_function_outer_scope_p (block));
+  gcc_assert (!BLOCK_DIE (block));
+
+  /* If we can't represent it, don't bother.  */
+  if (!(dwarf_version >= 3 || !dwarf_strict))
+    return;
+
+  if (BLOCK_FRAGMENT_ORIGIN (block))
+    block = BLOCK_FRAGMENT_ORIGIN (block);
+  /* Can the entry point ever not be at the beginning of an
+     unfragmented lexical block?  */
+  else if (!(BLOCK_FRAGMENT_CHAIN (block)
+	     || (cur_line_info_table
+		 && !ZERO_VIEW_P (cur_line_info_table->view))))
+    return;
+
+  if (!inline_entry_data_table)
+    inline_entry_data_table
+      = hash_table<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.  */
@@ -30315,6 +30492,9 @@  dwarf2out_finish (const char *)
   /* Flush out any latecomers to the limbo party.  */
   flush_limbo_die_list ();
 
+  if (inline_entry_data_table)
+    gcc_assert (inline_entry_data_table->elements () == 0);
+
   if (flag_checking)
     {
       verify_die (comp_unit_die ());
diff --git a/gcc/final.c b/gcc/final.c
index c52c950..6c3a73b 100644
--- a/gcc/final.c
+++ b/gcc/final.c
@@ -1672,6 +1672,7 @@  reemit_insn_block_notes (void)
 	    break;
 
 	  case NOTE_INSN_BEGIN_STMT:
+	  case NOTE_INSN_INLINE_ENTRY:
 	    this_block = LOCATION_BLOCK (NOTE_MARKER_LOCATION (insn));
 	    goto set_cur_block_to_this_block;
 
@@ -2514,6 +2515,7 @@  final_scan_insn (rtx_insn *insn, FILE *file, int optimize_p ATTRIBUTE_UNUSED,
 	  if (!DECL_IGNORED_P (current_function_decl)
 	      && notice_source_line (insn, NULL))
 	    {
+	    output_source_line:
 	      (*debug_hooks->source_line) (last_linenum, last_columnnum,
 					   last_filename, last_discriminator,
 					   true);
@@ -2521,6 +2523,18 @@  final_scan_insn (rtx_insn *insn, FILE *file, int optimize_p ATTRIBUTE_UNUSED,
 	    }
 	  break;
 
+	case NOTE_INSN_INLINE_ENTRY:
+	  gcc_checking_assert (cfun->debug_nonbind_markers);
+	  if (!DECL_IGNORED_P (current_function_decl))
+	    {
+	      if (!notice_source_line (insn, NULL))
+		break;
+	      (*debug_hooks->inline_entry) (LOCATION_BLOCK
+					    (NOTE_MARKER_LOCATION (insn)));
+	      goto output_source_line;
+	    }
+	  break;
+
 	default:
 	  gcc_unreachable ();
 	  break;
@@ -3224,6 +3238,17 @@  notice_source_line (rtx_insn *insn, bool *is_stmt)
   if (NOTE_MARKER_P (insn))
     {
       location_t loc = NOTE_MARKER_LOCATION (insn);
+      /* The inline entry markers (gimple, insn, note) carry the
+	 location of the call, because that's what we want to carry
+	 during compilation, but the location we want to output in
+	 debug information for the inline entry point is the location
+	 of the function itself.  */
+      if (NOTE_KIND (insn) == NOTE_INSN_INLINE_ENTRY)
+	{
+	  tree block = LOCATION_BLOCK (loc);
+	  tree fn = block_ultimate_origin (block);
+	  loc = DECL_SOURCE_LOCATION (fn);
+	}
       expanded_location xloc = expand_location (loc);
       if (xloc.line == 0)
 	{
@@ -4829,6 +4854,7 @@  rest_of_clean_state (void)
 	  && (!NOTE_P (insn) ||
 	      (NOTE_KIND (insn) != NOTE_INSN_VAR_LOCATION
 	       && NOTE_KIND (insn) != NOTE_INSN_BEGIN_STMT
+	       && NOTE_KIND (insn) != NOTE_INSN_INLINE_ENTRY
 	       && NOTE_KIND (insn) != NOTE_INSN_CALL_ARG_LOCATION
 	       && NOTE_KIND (insn) != NOTE_INSN_BLOCK_BEG
 	       && NOTE_KIND (insn) != NOTE_INSN_BLOCK_END
diff --git a/gcc/gimple-pretty-print.c b/gcc/gimple-pretty-print.c
index 2702854..7c9c754 100644
--- a/gcc/gimple-pretty-print.c
+++ b/gcc/gimple-pretty-print.c
@@ -1377,6 +1377,19 @@  dump_gimple_debug (pretty_printer *buffer, gdebug *gs, int spc,
 	dump_gimple_fmt (buffer, spc, flags, "# DEBUG BEGIN_STMT");
       break;
 
+    case GIMPLE_DEBUG_INLINE_ENTRY:
+      if (flags & TDF_RAW)
+	dump_gimple_fmt (buffer, spc, flags, "%G INLINE_ENTRY %T", gs,
+			 gimple_block (gs)
+			 ? block_ultimate_origin (gimple_block (gs))
+			 : NULL_TREE);
+      else
+	dump_gimple_fmt (buffer, spc, flags, "# DEBUG INLINE_ENTRY %T",
+			 gimple_block (gs)
+			 ? block_ultimate_origin (gimple_block (gs))
+			 : NULL_TREE);
+      break;
+
     default:
       gcc_unreachable ();
     }
diff --git a/gcc/gimple.c b/gcc/gimple.c
index dc9aa79..01ddc65 100644
--- a/gcc/gimple.c
+++ b/gcc/gimple.c
@@ -857,6 +857,27 @@  gimple_build_debug_begin_stmt (tree block, location_t location
 }
 
 
+/* Build a new GIMPLE_DEBUG_INLINE_ENTRY statement in BLOCK at
+   LOCATION.  The BLOCK links to the inlined function.  */
+
+gdebug *
+gimple_build_debug_inline_entry (tree block, location_t location
+				      MEM_STAT_DECL)
+{
+  gdebug *p
+    = as_a <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.
diff --git a/gcc/gimple.h b/gcc/gimple.h
index 68cd34f..909807f 100644
--- a/gcc/gimple.h
+++ b/gcc/gimple.h
@@ -203,7 +203,8 @@  enum gf_mask {
 enum gimple_debug_subcode {
   GIMPLE_DEBUG_BIND = 0,
   GIMPLE_DEBUG_SOURCE_BIND = 1,
-  GIMPLE_DEBUG_BEGIN_STMT = 2
+  GIMPLE_DEBUG_BEGIN_STMT = 2,
+  GIMPLE_DEBUG_INLINE_ENTRY = 3
 };
 
 /* Masks for selecting a pass local flag (PLF) to work on.  These
@@ -1455,6 +1456,7 @@  geh_dispatch *gimple_build_eh_dispatch (int);
 gdebug *gimple_build_debug_bind (tree, tree, gimple * CXX_MEM_STAT_INFO);
 gdebug *gimple_build_debug_source_bind (tree, tree, gimple * CXX_MEM_STAT_INFO);
 gdebug *gimple_build_debug_begin_stmt (tree, location_t CXX_MEM_STAT_INFO);
+gdebug *gimple_build_debug_inline_entry (tree, location_t CXX_MEM_STAT_INFO);
 gomp_critical *gimple_build_omp_critical (gimple_seq, tree, tree);
 gomp_for *gimple_build_omp_for (gimple_seq, int, tree, size_t, gimple_seq);
 gomp_parallel *gimple_build_omp_parallel (gimple_seq, tree, tree, tree);
@@ -4766,13 +4768,25 @@  gimple_debug_begin_stmt_p (const gimple *s)
   return false;
 }
 
+/* Return true if S is a GIMPLE_DEBUG INLINE_ENTRY statement.  */
+
+static inline bool
+gimple_debug_inline_entry_p (const gimple *s)
+{
+  if (is_gimple_debug (s))
+    return s->subcode == GIMPLE_DEBUG_INLINE_ENTRY;
+
+  return false;
+}
+
 /* Return true if S is a GIMPLE_DEBUG non-binding marker statement.  */
 
 static inline bool
 gimple_debug_nonbind_marker_p (const gimple *s)
 {
   if (is_gimple_debug (s))
-    return s->subcode == GIMPLE_DEBUG_BEGIN_STMT;
+    return s->subcode == GIMPLE_DEBUG_BEGIN_STMT
+      || s->subcode == GIMPLE_DEBUG_INLINE_ENTRY;
 
   return false;
 }
diff --git a/gcc/insn-notes.def b/gcc/insn-notes.def
index 960487b..252e957 100644
--- a/gcc/insn-notes.def
+++ b/gcc/insn-notes.def
@@ -71,6 +71,10 @@  INSN_NOTE (CALL_ARG_LOCATION)
 /* The beginning of a statement.  */
 INSN_NOTE (BEGIN_STMT)
 
+/* The entry point for an inlined function.  Its NOTE_BLOCK references
+   the lexical block whose abstract origin is the inlined function.  */
+INSN_NOTE (INLINE_ENTRY)
+
 /* Record the struct for the following basic block.  Uses
    NOTE_BASIC_BLOCK.  FIXME: Redundant with the basic block pointer
    now included in every insn.  NOTE: If there's no CFG anymore, in other words,
diff --git a/gcc/print-rtl.c b/gcc/print-rtl.c
index 0d36a42..cca8798 100644
--- a/gcc/print-rtl.c
+++ b/gcc/print-rtl.c
@@ -259,6 +259,7 @@  rtx_writer::print_rtx_operand_code_0 (const_rtx in_rtx ATTRIBUTE_UNUSED,
 	  break;
 
 	case NOTE_INSN_BEGIN_STMT:
+	case NOTE_INSN_INLINE_ENTRY:
 #ifndef GENERATOR_FILE
 	  {
 	    expanded_location xloc
@@ -1809,6 +1810,10 @@  print_insn (pretty_printer *pp, const rtx_insn *x, int verbose)
 		pp_string (pp, "debug begin stmt marker");
 		break;
 
+	      case NOTE_INSN_INLINE_ENTRY:
+		pp_string (pp, "debug inline entry marker");
+		break;
+
 	      default:
 		gcc_unreachable ();
 	      }
diff --git a/gcc/rtl.h b/gcc/rtl.h
index a0c27fc..cd177c7 100644
--- a/gcc/rtl.h
+++ b/gcc/rtl.h
@@ -1625,7 +1625,8 @@  extern const char * const reg_note_name[];
    for which NOTE_MARKER_LOCATION can be used.  */
 #define NOTE_MARKER_P(INSN)				\
   (NOTE_P (INSN) &&					\
-   (NOTE_KIND (INSN) == NOTE_INSN_BEGIN_STMT))
+   (NOTE_KIND (INSN) == NOTE_INSN_BEGIN_STMT		\
+    || NOTE_KIND (INSN) == NOTE_INSN_INLINE_ENTRY))
 
 /* Variable declaration and the location of a variable.  */
 #define PAT_VAR_LOCATION_DECL(PAT) (XCTREE ((PAT), 0, VAR_LOCATION))
@@ -1663,6 +1664,8 @@  extern const char * const reg_note_name[];
   (GET_CODE (PATTERN (INSN)) == DEBUG_MARKER	  \
    ? (GET_MODE (PATTERN (INSN)) == VOIDmode	  \
       ? NOTE_INSN_BEGIN_STMT			  \
+      : GET_MODE (PATTERN (INSN)) == BLKmode	  \
+      ? NOTE_INSN_INLINE_ENTRY			  \
       : (enum insn_note)-1) 			  \
    : (enum insn_note)-1)
 
diff --git a/gcc/tree-inline.c b/gcc/tree-inline.c
index a99e975..41b4fd9 100644
--- a/gcc/tree-inline.c
+++ b/gcc/tree-inline.c
@@ -4704,6 +4704,13 @@  expand_call_inline (basic_block bb, gimple *stmt, copy_body_data *id)
 			GSI_NEW_STMT);
     }
   initialize_inlined_parameters (id, stmt, fn, bb);
+  if (debug_nonbind_markers_p && id->block
+      && inlined_function_outer_scope_p (id->block))
+    {
+      gimple_stmt_iterator si = gsi_last_bb (bb);
+      gsi_insert_after (&si, gimple_build_debug_inline_entry
+			(id->block, input_location), GSI_NEW_STMT);
+    }
 
   if (DECL_INITIAL (fn))
     {
diff --git a/gcc/tree-ssa-live.c b/gcc/tree-ssa-live.c
index 8738fe2..734d15d 100644
--- a/gcc/tree-ssa-live.c
+++ b/gcc/tree-ssa-live.c
@@ -520,6 +520,11 @@  remove_unused_scope_block_p (tree scope, bool in_ctor_dtor_block)
    else if (!BLOCK_SUPERCONTEXT (scope)
             || TREE_CODE (BLOCK_SUPERCONTEXT (scope)) == FUNCTION_DECL)
      unused = false;
+   /* Preserve the block, it is referenced by at least the inline
+      entry point marker.  */
+   else if (debug_nonbind_markers_p
+	    && inlined_function_outer_scope_p (scope))
+     unused = false;
    /* Innermost blocks with no live variables nor statements can be always
       eliminated.  */
    else if (!nsubblocks)
@@ -548,11 +553,13 @@  remove_unused_scope_block_p (tree scope, bool in_ctor_dtor_block)
      }
    else if (BLOCK_VARS (scope) || BLOCK_NUM_NONLOCALIZED_VARS (scope))
      unused = false;
-   /* See if this block is important for representation of inlined function.
-      Inlined functions are always represented by block with
-      block_ultimate_origin being set to FUNCTION_DECL and DECL_SOURCE_LOCATION
-      set...  */
-   else if (inlined_function_outer_scope_p (scope))
+   /* See if this block is important for representation of inlined
+      function.  Inlined functions are always represented by block
+      with block_ultimate_origin being set to FUNCTION_DECL and
+      DECL_SOURCE_LOCATION set, unless they expand to nothing...  But
+      see above for the case of statement frontiers.  */
+   else if (!debug_nonbind_markers_p
+	    && inlined_function_outer_scope_p (scope))
      unused = false;
    else
    /* Verfify that only blocks with source location set
@@ -640,6 +647,16 @@  dump_scope_block (FILE *file, int indent, tree scope, dump_flags_t flags)
 	    fprintf (file, "#%i", BLOCK_NUMBER (origin));
 	}
     }
+  if (BLOCK_FRAGMENT_ORIGIN (scope))
+    fprintf (file, " Fragment of : #%i",
+	     BLOCK_NUMBER (BLOCK_FRAGMENT_ORIGIN (scope)));
+  else if (BLOCK_FRAGMENT_CHAIN (scope))
+    {
+      fprintf (file, " Fragment chain :");
+      for (t = BLOCK_FRAGMENT_CHAIN (scope); t ;
+	   t = BLOCK_FRAGMENT_CHAIN (t))
+	fprintf (file, " #%i", BLOCK_NUMBER (t));
+    }
   fprintf (file, " \n");
   for (var = BLOCK_VARS (scope); var; var = DECL_CHAIN (var))
     {
diff --git a/gcc/var-tracking.c b/gcc/var-tracking.c
index d3850af..21ffe57 100644
--- a/gcc/var-tracking.c
+++ b/gcc/var-tracking.c
@@ -9931,6 +9931,7 @@  reemit_marker_as_note (rtx_insn *insn, basic_block *bb)
   switch (kind)
     {
     case NOTE_INSN_BEGIN_STMT:
+    case NOTE_INSN_INLINE_ENTRY:
       {
 	rtx_insn *note = NULL;
 	if (cfun->debug_nonbind_markers)
diff --git a/include/dwarf2.def b/include/dwarf2.def
index f3fa400..8e731a3 100644
--- a/include/dwarf2.def
+++ b/include/dwarf2.def
@@ -444,6 +444,7 @@  DW_AT (DW_AT_GNU_pubtypes, 0x2135)
    See http://gcc.gnu.org/wiki/Discriminator  */
 DW_AT (DW_AT_GNU_discriminator, 0x2136)
 DW_AT (DW_AT_GNU_locviews, 0x2137)
+DW_AT (DW_AT_GNU_entry_view, 0x2138)
 /* VMS extensions.  */
 DW_AT (DW_AT_VMS_rtnbeg_pd_address, 0x2201)
 /* GNAT extensions.  */