public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
* emit DW_AT_entry_pc for non-contiguous inlined functions
@ 2007-02-28 15:19 Alexandre Oliva
  2007-02-28 19:15 ` Daniel Jacobowitz
  2007-03-05 19:45 ` Richard Henderson
  0 siblings, 2 replies; 5+ messages in thread
From: Alexandre Oliva @ 2007-02-28 15:19 UTC (permalink / raw)
  To: gcc-patches

[-- Attachment #1: Type: text/plain, Size: 2026 bytes --]

Without this patch, whenever an inlined function is in non-contiguous
blocks, we end up without any hint at its entry point whatsoever.

This patch attempts to address that, but only emitting a
DW_AT_entry_pc when the inlined function hasn't been combined and
rearranged such that different portions thereof can be reached by
independent code paths.

The only hopefully-reliable way I could come up with to identify it
was to check that the first sub-block of the stmt that corresponds to
the inlined function's decl corresponds itself to the abstract
function's entry point.

FWIW, I've bootstrapped the compiler on x86_64-linux-gnu with an
assertion to check that no other block in a chain of fragments could
ever satisfy this condition.  Having got no matches, I dropped the
assertion.

As a result, when we compile this:

typedef int (*fp)(int, int); extern fp f1, f2, f3, f4;
static inline int f0(int i, int j)
{ if (i<j) return f1(i,j); else return f2(i,j); }
int g1(int a, int b)
{ int x; if (a<b) x = f3(a,b); else x = f4(a,b); return x + f0(a,b); }
int g2(int a, int b)
{ int x=0, y; if (a<b) x = f3(a,b); y = f4(a,b); return x+y+f0(a,b); }
int g3(int a, int b)
{ int x = f0(a,b); if (a<b) return x+f3(a,b); else return x+f4(a,b); }
int g4(int a, int b)
{ if (a<b) return f0(a,b)+f3(a,b); else return f0(a,b)+f4(a,b); }

we optimize it to:

g1: if (a<b) return f3(a,b)+f1(a,b); else return f4(a,b)+f2(a,b);
g2: if (a<b) return f3(a,b)+f4(a,b)+f1(a,b); else return f4(a,b)+f2(a,b);
g3: if (a<b) return f1(a,b)+f3(a,b); else return f2(a,b)+f4(a,b);
g4: if (a<b) return f1(a,b)+f3(a,b); else return f2(a,b)+f4(a,b);

So f0's inlined fragments in g1 and g2 do not represent entry points.
In g3, the compare is taken from f0, so it's regarded as an entry
point.  In g4, we get two inlined copies, each one contiguous, thus
represented with low/high rather than ranges, so no explicit
DW_AT_entry_pc is needed/useful.

Ok to install?  Bootstrapped and regression-tested (with an additional
assertion) on x86_64-linux-gnu.


[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: gcc-debug-inlined-ranges-entry.patch --]
[-- Type: text/x-patch, Size: 1784 bytes --]

for  gcc/ChangeLog
from  Alexandre Oliva  <aoliva@redhat.com>

	* dwarf2out.c (is_inlined_entry_point): New
	(add_high_low_attributes): Emit DW_AT_entry_pc along with
	DW_AT_ranges if the first subblock is the entry point.

Index: trunk/gcc/dwarf2out.c
===================================================================
--- trunk.orig/gcc/dwarf2out.c	2007-02-27 01:59:21.000000000 -0300
+++ trunk/gcc/dwarf2out.c	2007-02-28 01:46:56.000000000 -0300
@@ -12231,6 +12231,36 @@ add_call_src_coords_attributes (tree stm
   add_AT_unsigned (die, DW_AT_call_line, s.line);
 }
 
+
+/* If STMT's abstract origin is a function declaration and STMT's
+   first subblock's abstract origin is the function's outermost block,
+   then we're looking at the main entry point.  */
+static bool
+is_inlined_entry_point (tree stmt)
+{
+  tree decl, block;
+
+  if (!stmt || TREE_CODE (stmt) != BLOCK)
+    return false;
+
+  decl = block_ultimate_origin (stmt);
+
+  if (!decl || TREE_CODE (decl) != FUNCTION_DECL)
+    return false;
+
+  block = BLOCK_SUBBLOCKS (stmt);
+
+  if (block)
+    {
+      if (TREE_CODE (block) != BLOCK)
+	return false;
+
+      block = block_ultimate_origin (block);
+    }
+
+  return block == DECL_INITIAL (decl);
+}
+
 /* A helper function for gen_lexical_block_die and gen_inlined_subroutine_die.
    Add low_pc and high_pc attributes to the DIE for a block STMT.  */
 
@@ -12243,6 +12273,13 @@ add_high_low_attributes (tree stmt, dw_d
     {
       tree chain;
 
+      if (is_inlined_entry_point (stmt))
+	{
+	  ASM_GENERATE_INTERNAL_LABEL (label, BLOCK_BEGIN_LABEL,
+				       BLOCK_NUMBER (stmt));
+	  add_AT_lbl_id (die, DW_AT_entry_pc, label);
+	}
+
       add_AT_range_list (die, DW_AT_ranges, add_ranges (stmt));
 
       chain = BLOCK_FRAGMENT_CHAIN (stmt);

[-- Attachment #3: Type: text/plain, Size: 249 bytes --]


-- 
Alexandre Oliva         http://www.lsd.ic.unicamp.br/~oliva/
FSF Latin America Board Member         http://www.fsfla.org/
Red Hat Compiler Engineer   aoliva@{redhat.com, gcc.gnu.org}
Free Software Evangelist  oliva@{lsd.ic.unicamp.br, gnu.org}

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

* Re: emit DW_AT_entry_pc for non-contiguous inlined functions
  2007-02-28 15:19 emit DW_AT_entry_pc for non-contiguous inlined functions Alexandre Oliva
@ 2007-02-28 19:15 ` Daniel Jacobowitz
  2007-03-03  5:53   ` Alexandre Oliva
  2007-03-05 19:45 ` Richard Henderson
  1 sibling, 1 reply; 5+ messages in thread
From: Daniel Jacobowitz @ 2007-02-28 19:15 UTC (permalink / raw)
  To: Alexandre Oliva; +Cc: gcc-patches

On Wed, Feb 28, 2007 at 02:15:33AM -0300, Alexandre Oliva wrote:
> Without this patch, whenever an inlined function is in non-contiguous
> blocks, we end up without any hint at its entry point whatsoever.
> 
> This patch attempts to address that, but only emitting a
> DW_AT_entry_pc when the inlined function hasn't been combined and
> rearranged such that different portions thereof can be reached by
> independent code paths.

As it happens I've been working on inline functions for a few weeks.
I'd been going under the assumption that "entry PC" is a useless
concept for inline functions.  What do you want to use it for, and
do you think it's available often enough to bother?

I see DWARF does mention it as a valid meaning of DW_AT_entry_pc,
so obviously someone agrees with you :-)

-- 
Daniel Jacobowitz
CodeSourcery

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

* Re: emit DW_AT_entry_pc for non-contiguous inlined functions
  2007-02-28 19:15 ` Daniel Jacobowitz
@ 2007-03-03  5:53   ` Alexandre Oliva
  2007-03-05  3:56     ` Daniel Jacobowitz
  0 siblings, 1 reply; 5+ messages in thread
From: Alexandre Oliva @ 2007-03-03  5:53 UTC (permalink / raw)
  To: gcc-patches

On Feb 28, 2007, Daniel Jacobowitz <drow@false.org> wrote:

> I'd been going under the assumption that "entry PC" is a useless
> concept for inline functions.

If you want to set breakpoints at inlined occurrences of a function,
or want to monitor executions of a function (including inlined
copies), this information helps.  It is certainly not *required* to be
there (I'm not sure any dwarf attribute is ;-), but every piece of
information is supposed to aid debuggers and other tools
(e.g. systemtap).  If the information is missing, the tool has to work
harder, so it probably must be able to deal with the absence of entry
PC.  But if we can easily emit it when it makes sense, we should.

-- 
Alexandre Oliva         http://www.lsd.ic.unicamp.br/~oliva/
FSF Latin America Board Member         http://www.fsfla.org/
Red Hat Compiler Engineer   aoliva@{redhat.com, gcc.gnu.org}
Free Software Evangelist  oliva@{lsd.ic.unicamp.br, gnu.org}

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

* Re: emit DW_AT_entry_pc for non-contiguous inlined functions
  2007-03-03  5:53   ` Alexandre Oliva
@ 2007-03-05  3:56     ` Daniel Jacobowitz
  0 siblings, 0 replies; 5+ messages in thread
From: Daniel Jacobowitz @ 2007-03-05  3:56 UTC (permalink / raw)
  To: gcc-patches

On Sat, Mar 03, 2007 at 02:53:44AM -0300, Alexandre Oliva wrote:
> On Feb 28, 2007, Daniel Jacobowitz <drow@false.org> wrote:
> 
> > I'd been going under the assumption that "entry PC" is a useless
> > concept for inline functions.
> 
> If you want to set breakpoints at inlined occurrences of a function,
> or want to monitor executions of a function (including inlined
> copies), this information helps.

Yes, I now understand this a bit better :-)  Thanks.

-- 
Daniel Jacobowitz
CodeSourcery

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

* Re: emit DW_AT_entry_pc for non-contiguous inlined functions
  2007-02-28 15:19 emit DW_AT_entry_pc for non-contiguous inlined functions Alexandre Oliva
  2007-02-28 19:15 ` Daniel Jacobowitz
@ 2007-03-05 19:45 ` Richard Henderson
  1 sibling, 0 replies; 5+ messages in thread
From: Richard Henderson @ 2007-03-05 19:45 UTC (permalink / raw)
  To: Alexandre Oliva; +Cc: gcc-patches

On Wed, Feb 28, 2007 at 02:15:33AM -0300, Alexandre Oliva wrote:
> 	* dwarf2out.c (is_inlined_entry_point): New
> 	(add_high_low_attributes): Emit DW_AT_entry_pc along with
> 	DW_AT_ranges if the first subblock is the entry point.

Ok.


r~

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

end of thread, other threads:[~2007-03-05 19:45 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2007-02-28 15:19 emit DW_AT_entry_pc for non-contiguous inlined functions Alexandre Oliva
2007-02-28 19:15 ` Daniel Jacobowitz
2007-03-03  5:53   ` Alexandre Oliva
2007-03-05  3:56     ` Daniel Jacobowitz
2007-03-05 19:45 ` Richard Henderson

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