Alexandre Oliva - emit DW_AT_entry_pc for non-contiguous inlined functions (original) (raw)
This is the mail archive of the gcc-patches@gcc.gnu.orgmailing 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] |
- From: Alexandre Oliva
- To: gcc-patches at gcc dot gnu dot org
- Date: Wed, 28 Feb 2007 02:15:33 -0300
- Subject: emit DW_AT_entry_pc for non-contiguous inlined functions
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.
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);
-- 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}
- Follow-Ups:
- Re: emit DW_AT_entry_pc for non-contiguous inlined functions
* From: Daniel Jacobowitz
- Re: emit DW_AT_entry_pc for non-contiguous inlined functions
Index Nav: | [Date Index] [Subject Index] [Author Index] [Thread Index] | |
---|---|---|
Message Nav: | [Date Prev] [Date Next] | [Thread Prev] [Thread Next] |