public inbox for gcc-bugs@sourceware.org
help / color / mirror / Atom feed
* [Bug debug/51902] New: lexical_blocks inside inlined_subroutines generate duplicate debug_ranges
@ 2012-01-19 15:01 mark at gcc dot gnu.org
  2012-01-19 18:55 ` [Bug debug/51902] " jakub at gcc dot gnu.org
                   ` (9 more replies)
  0 siblings, 10 replies; 11+ messages in thread
From: mark at gcc dot gnu.org @ 2012-01-19 15:01 UTC (permalink / raw)
  To: gcc-bugs

http://gcc.gnu.org/bugzilla/show_bug.cgi?id=51902

             Bug #: 51902
           Summary: lexical_blocks inside inlined_subroutines generate
                    duplicate debug_ranges
    Classification: Unclassified
           Product: gcc
           Version: 4.7.0
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: debug
        AssignedTo: unassigned@gcc.gnu.org
        ReportedBy: mark@gcc.gnu.org
                CC: jakub@gcc.gnu.org, jason@gcc.gnu.org


Created attachment 26380
  --> http://gcc.gnu.org/bugzilla/attachment.cgi?id=26380
debug_ranges.c - Get some statistics on .debug_ranges section.

I noticed that when you generate dwarf for an inlined function it often
comes with duplicate range lists for both the DW_TAG_inlined_subroutine
and the child DW_TAG_lexical_block DIE. For example:

static int k;

static int foo (int i)
{
  int j = i + 42;
  return k + (j > 14 ? j : i);
}

int main (int argc, char **argv)
{
  int c = argc;
  k = 2 * c;
  c = foo (c);
  return c;
}

Generates with -O2 -gdwarf-4:

DWARF section [27] '.debug_info' at offset 0x895:
 [Offset]
 Compilation unit at offset 0:
 Version: 4, Abbreviation section offset: 0, Address size: 8, Offset size: 4
[...]
 [    a8]      inlined_subroutine
               abstract_origin      (ref4) [    31]
               entry_pc             (addr) 0x0000000000400360 <main>
               ranges               (data4) range list [     0]
               call_file            (data1) 1
               call_line            (data1) 13
 [    bb]        formal_parameter
                 abstract_origin      (ref4) [    42]
                 location             (block1) 
                  [   0] reg5
 [    c2]        lexical_block
                 ranges               (data4) range list [    40]
 [    c7]          variable
                   abstract_origin      (ref4) [    4b]
                   location             (data4) location list [    23]
[...]
DWARF section [32] '.debug_ranges' at offset 0xb4e:
 [     0]  0x0000000000400360 <main>..0x0000000000400363 <main+0x3>
           0x0000000000400366 <main+0x6>..0x0000000000400369 <main+0x9>
           0x000000000040036f <main+0xf>..0x0000000000400374 <main+0x14>
 [    40]  0x0000000000400360 <main>..0x0000000000400363 <main+0x3>
           0x0000000000400366 <main+0x6>..0x0000000000400369 <main+0x9>
           0x000000000040036f <main+0xf>..0x0000000000400374 <main+0x14>
 [    80]  0x0000000000400360 <main>..0x0000000000400375

So range list 0 for the inlined_subroutine DIE a8 is the same as range
list 40 for the lexical_block DIE c2.

I wrote a quick and dirty elfutils libdw/libdwfl based program to look for this
pattern and it seems to occur reasonably often:

$ ./debug_ranges /usr/lib/debug/bin/bash.debug 
cus: 160
  subprograms: 6397
    inlined_subroutines: 838
      lexical_blocks: 359
dup_ranges: 220
dup_addrs: 1454

$ ./debug_ranges ~/build/gcc-obj/gcc/cc1
cus: 390
  subprograms: 84288
    inlined_subroutines: 7860
      lexical_blocks: 6256
dup_ranges: 5274
dup_addrs: 29190

$ ./debug_ranges /usr/lib/debug/lib/modules/3.1.9-1.fc16.x86_64/vmlinux 
cus: 1616
  subprograms: 108066
    inlined_subroutines: 42784
      lexical_blocks: 15276
dup_ranges: 7763
dup_addrs: 38586

Given that there will be relocations for .debug_ranges addresses pointing into
.text it could even save twice that number of addresses for ET_REL files.

See also this thread for a first try of a fix (needs some help):
http://gcc.gnu.org/ml/gcc/2012-01/msg00158.html


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

* [Bug debug/51902] lexical_blocks inside inlined_subroutines generate duplicate debug_ranges
  2012-01-19 15:01 [Bug debug/51902] New: lexical_blocks inside inlined_subroutines generate duplicate debug_ranges mark at gcc dot gnu.org
@ 2012-01-19 18:55 ` jakub at gcc dot gnu.org
  2012-01-20 11:30 ` jakub at gcc dot gnu.org
                   ` (8 subsequent siblings)
  9 siblings, 0 replies; 11+ messages in thread
From: jakub at gcc dot gnu.org @ 2012-01-19 18:55 UTC (permalink / raw)
  To: gcc-bugs

http://gcc.gnu.org/bugzilla/show_bug.cgi?id=51902

--- Comment #1 from Jakub Jelinek <jakub at gcc dot gnu.org> 2012-01-19 18:04:54 UTC ---
Created attachment 26385
  --> http://gcc.gnu.org/bugzilla/attachment.cgi?id=26385
gcc47-pr51902.patch

Partial patch.

The following example shows it even better, there are 5 identical 3 item
ranges:

static int k;

static int
foo (int i)
{
  int q1 = i, q2 = i;
  {
    int q3 = i;
    {
      int q4 = i, q5 = i;
      {
int j = i + 42;
return k + (j > 14 ? j : i);
      }
    }
  }
}

int
main (int argc, char **argv)
{
  int c = argc;
  k = 2 * c;
  c = foo (c);
  return c;
}

IMHO it is impossible to handle this solely in dwarf2out.c, you don't know if
the begin/end notes for a block are adjacent to its BLOCK_SUPERCONTEXT or not.
The attached patch is an untested attempt to provide that info (on a
per-fragment basis).  If the stmt BLOCK given to add_high_low_attributes has
BLOCK_SAME_RANGE bit set and all blocks in its BLOCK_FRAGMENT_CHAIN have it set
as well, then you should be able to use the range of its BLOCK_SUPERCONTEXT (if
both stmt and BLOCK_SUPERCONTEXT (stmt) have the same length of fragment chain,
then the whole supercontext's range, otherwise some tail part of it).  And
recursively so.

I guess in order to avoid searching through the fragment chains all the time
we should clear BLOCK_SAME_RANGE if BLOCK_SAME_RANGE (BLOCK_FRAGMENT_CHAIN) is
clear (somewhere still during reorder_blocks or number_blocks).

And then the question is how to find the range in the .debug_ranges table
effectively.  Walking the whole table would be O(n^2), so have some hash table
that maps the BLOCK_NUM ints that have BLOCK_SAME_RANGE children (at least one)
to .debug_range offsets?


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

* [Bug debug/51902] lexical_blocks inside inlined_subroutines generate duplicate debug_ranges
  2012-01-19 15:01 [Bug debug/51902] New: lexical_blocks inside inlined_subroutines generate duplicate debug_ranges mark at gcc dot gnu.org
  2012-01-19 18:55 ` [Bug debug/51902] " jakub at gcc dot gnu.org
@ 2012-01-20 11:30 ` jakub at gcc dot gnu.org
  2012-01-20 14:19 ` mark at gcc dot gnu.org
                   ` (7 subsequent siblings)
  9 siblings, 0 replies; 11+ messages in thread
From: jakub at gcc dot gnu.org @ 2012-01-20 11:30 UTC (permalink / raw)
  To: gcc-bugs

http://gcc.gnu.org/bugzilla/show_bug.cgi?id=51902

Jakub Jelinek <jakub at gcc dot gnu.org> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
  Attachment #26385|0                           |1
        is obsolete|                            |

--- Comment #2 from Jakub Jelinek <jakub at gcc dot gnu.org> 2012-01-20 10:46:29 UTC ---
Created attachment 26391
  --> http://gcc.gnu.org/bugzilla/attachment.cgi?id=26391
gcc47-pr51902.patch

This updated patch does that (I actually managed to implement it without
any sort of extra hash table or array).  Fixes up the testcase, I wonder if I
can find a testcase where the supercontext doesn't have completely identical
range, but only tail of it (i.e. that nested block/inlined subroutine could
refer to a couple of tail elements in supercontext's range).
Mark, can you please look at this if it does the right thing you want from it?


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

* [Bug debug/51902] lexical_blocks inside inlined_subroutines generate duplicate debug_ranges
  2012-01-19 15:01 [Bug debug/51902] New: lexical_blocks inside inlined_subroutines generate duplicate debug_ranges mark at gcc dot gnu.org
  2012-01-19 18:55 ` [Bug debug/51902] " jakub at gcc dot gnu.org
  2012-01-20 11:30 ` jakub at gcc dot gnu.org
@ 2012-01-20 14:19 ` mark at gcc dot gnu.org
  2012-01-20 14:20 ` jakub at gcc dot gnu.org
                   ` (6 subsequent siblings)
  9 siblings, 0 replies; 11+ messages in thread
From: mark at gcc dot gnu.org @ 2012-01-20 14:19 UTC (permalink / raw)
  To: gcc-bugs

http://gcc.gnu.org/bugzilla/show_bug.cgi?id=51902

--- Comment #3 from Mark Wielaard <mark at gcc dot gnu.org> 2012-01-20 13:31:04 UTC ---
(In reply to comment #2)
> Mark, can you please look at this if it does the right thing you want from it?

Yes, this seems to do what I was thinking of. And it works on my testcases.

It does a bit more by searching up the block supercontext and by trying to find
a partial range. I think it would be fine to look for and pick the first block
supercontext and only check the chains are equal (but haven't tried that yet).


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

* [Bug debug/51902] lexical_blocks inside inlined_subroutines generate duplicate debug_ranges
  2012-01-19 15:01 [Bug debug/51902] New: lexical_blocks inside inlined_subroutines generate duplicate debug_ranges mark at gcc dot gnu.org
                   ` (2 preceding siblings ...)
  2012-01-20 14:19 ` mark at gcc dot gnu.org
@ 2012-01-20 14:20 ` jakub at gcc dot gnu.org
  2012-01-20 18:01 ` jakub at gcc dot gnu.org
                   ` (5 subsequent siblings)
  9 siblings, 0 replies; 11+ messages in thread
From: jakub at gcc dot gnu.org @ 2012-01-20 14:20 UTC (permalink / raw)
  To: gcc-bugs

http://gcc.gnu.org/bugzilla/show_bug.cgi?id=51902

--- Comment #4 from Jakub Jelinek <jakub at gcc dot gnu.org> 2012-01-20 13:37:50 UTC ---
We could go just to the immediate supercontext if BLOCK_SAME_RANGE (both when
the fragment count is the same and when it is smaller in the child), but we'd
lose all the verification (we couldn't test ranges_table[something].num against
BLOCK_NUM).
So perhaps we could do that, and only if ENABLE_CHECKING do the additional
verification afterwards, in the normal code just verify that the start of the
range has > 0 num (so it isn't one ranged by labels).


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

* [Bug debug/51902] lexical_blocks inside inlined_subroutines generate duplicate debug_ranges
  2012-01-19 15:01 [Bug debug/51902] New: lexical_blocks inside inlined_subroutines generate duplicate debug_ranges mark at gcc dot gnu.org
                   ` (3 preceding siblings ...)
  2012-01-20 14:20 ` jakub at gcc dot gnu.org
@ 2012-01-20 18:01 ` jakub at gcc dot gnu.org
  2012-01-21  5:23 ` mark at gcc dot gnu.org
                   ` (4 subsequent siblings)
  9 siblings, 0 replies; 11+ messages in thread
From: jakub at gcc dot gnu.org @ 2012-01-20 18:01 UTC (permalink / raw)
  To: gcc-bugs

http://gcc.gnu.org/bugzilla/show_bug.cgi?id=51902

--- Comment #5 from Jakub Jelinek <jakub at gcc dot gnu.org> 2012-01-20 17:44:50 UTC ---
The patch breaks g++.dg/guality/redeclaration1.C on i?86 -m32 -Os -g.
The supercontext range has 3 elements, the same range child range has 2
elements, same as the first and last of the supercontext.
So, either we'd need to stop optimizing if thiscount != supercount, or tweak
somehow reorder_blocks_1 so that it clears BLOCK_SAME_RANGE even when it didn't
show up adjacent to supercontext's NOTE_INSN_BLOCK_BEGIN resp. END.


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

* [Bug debug/51902] lexical_blocks inside inlined_subroutines generate duplicate debug_ranges
  2012-01-19 15:01 [Bug debug/51902] New: lexical_blocks inside inlined_subroutines generate duplicate debug_ranges mark at gcc dot gnu.org
                   ` (4 preceding siblings ...)
  2012-01-20 18:01 ` jakub at gcc dot gnu.org
@ 2012-01-21  5:23 ` mark at gcc dot gnu.org
  2012-01-23 15:33 ` jakub at gcc dot gnu.org
                   ` (3 subsequent siblings)
  9 siblings, 0 replies; 11+ messages in thread
From: mark at gcc dot gnu.org @ 2012-01-21  5:23 UTC (permalink / raw)
  To: gcc-bugs

http://gcc.gnu.org/bugzilla/show_bug.cgi?id=51902

Mark Wielaard <mark at gcc dot gnu.org> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
  Attachment #26380|0                           |1
        is obsolete|                            |

--- Comment #6 from Mark Wielaard <mark at gcc dot gnu.org> 2012-01-21 00:33:03 UTC ---
Created attachment 26399
  --> http://gcc.gnu.org/bugzilla/attachment.cgi?id=26399
debug_ranges.c - Get some statistics on .debug_ranges section.

Here is a slightly tweaked version of debug_ranges.c that also recognizes
nested lexical_blocks and will print which dies/ranges it finds that are equal,
but are at different range offsets.

die [ed] and [d3] use range [40] and [0], 6 equal addresses.
die [100] and [ed] use range [80] and [40], 6 equal addresses.
die [10c] and [100] use range [c0] and [80], 6 equal addresses.
die [11f] and [10c] use range [100] and [c0], 6 equal addresses.
cus: 1
  subprograms: 2
    inlined_subroutines: 1
      lexical_blocks: 4
equal_ranges: 0
shared_addrs: 0
dup_ranges: 4
dup_addrs: 24


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

* [Bug debug/51902] lexical_blocks inside inlined_subroutines generate duplicate debug_ranges
  2012-01-19 15:01 [Bug debug/51902] New: lexical_blocks inside inlined_subroutines generate duplicate debug_ranges mark at gcc dot gnu.org
                   ` (5 preceding siblings ...)
  2012-01-21  5:23 ` mark at gcc dot gnu.org
@ 2012-01-23 15:33 ` jakub at gcc dot gnu.org
  2012-01-24 10:37 ` jakub at gcc dot gnu.org
                   ` (2 subsequent siblings)
  9 siblings, 0 replies; 11+ messages in thread
From: jakub at gcc dot gnu.org @ 2012-01-23 15:33 UTC (permalink / raw)
  To: gcc-bugs

http://gcc.gnu.org/bugzilla/show_bug.cgi?id=51902

Jakub Jelinek <jakub at gcc dot gnu.org> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
  Attachment #26391|0                           |1
        is obsolete|                            |

--- Comment #7 from Jakub Jelinek <jakub at gcc dot gnu.org> 2012-01-23 15:25:09 UTC ---
Created attachment 26432
  --> http://gcc.gnu.org/bugzilla/attachment.cgi?id=26432
gcc47-pr51902.patch

Updated patch that ought to fix up redeclaration1.C.

It is like the previous patch, but additionally for the duration in between
reorder_blocks_1 and blocks_nreverse_all temporarily sets BLOCK_SUPERCONTEXT
not to the supercontext origin block, but to the supercontext fragment in which
it has been seen.  This is then used in extra BLOCK_SAME_RANGE clearing.  If we
didn't adjust BLOCK_SUPERCONTEXT to the old meaning right away, if
BLOCK_FRAGMENT_CHAIN (BLOCK_SUPERCONTEXT (block)) is different from
BLOCK_SUPERCONTEXT (BLOCK_FRAGMENT_CHAIN (block)), we clear BLOCK_SAME_RANGE
(block) as well.  This should IMHO ensure that if BLOCK_SAME_RANGE is set,
the .debug_range can be merged or tail merged with the parent.  As the patch
does adjust BLOCK_SUPERCONTEXT of the block in the same loop to avoid multiple
chain walks, we remember it in prev_super variable instead.


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

* [Bug debug/51902] lexical_blocks inside inlined_subroutines generate duplicate debug_ranges
  2012-01-19 15:01 [Bug debug/51902] New: lexical_blocks inside inlined_subroutines generate duplicate debug_ranges mark at gcc dot gnu.org
                   ` (6 preceding siblings ...)
  2012-01-23 15:33 ` jakub at gcc dot gnu.org
@ 2012-01-24 10:37 ` jakub at gcc dot gnu.org
  2012-03-05 20:18 ` jakub at gcc dot gnu.org
  2012-03-06 17:43 ` jakub at gcc dot gnu.org
  9 siblings, 0 replies; 11+ messages in thread
From: jakub at gcc dot gnu.org @ 2012-01-24 10:37 UTC (permalink / raw)
  To: gcc-bugs

http://gcc.gnu.org/bugzilla/show_bug.cgi?id=51902

Jakub Jelinek <jakub at gcc dot gnu.org> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
   Target Milestone|---                         |4.8.0

--- Comment #8 from Jakub Jelinek <jakub at gcc dot gnu.org> 2012-01-24 10:19:02 UTC ---
http://gcc.gnu.org/ml/gcc-patches/2012-01/msg01171.html


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

* [Bug debug/51902] lexical_blocks inside inlined_subroutines generate duplicate debug_ranges
  2012-01-19 15:01 [Bug debug/51902] New: lexical_blocks inside inlined_subroutines generate duplicate debug_ranges mark at gcc dot gnu.org
                   ` (7 preceding siblings ...)
  2012-01-24 10:37 ` jakub at gcc dot gnu.org
@ 2012-03-05 20:18 ` jakub at gcc dot gnu.org
  2012-03-06 17:43 ` jakub at gcc dot gnu.org
  9 siblings, 0 replies; 11+ messages in thread
From: jakub at gcc dot gnu.org @ 2012-03-05 20:18 UTC (permalink / raw)
  To: gcc-bugs

http://gcc.gnu.org/bugzilla/show_bug.cgi?id=51902

--- Comment #9 from Jakub Jelinek <jakub at gcc dot gnu.org> 2012-03-05 20:17:54 UTC ---
Author: jakub
Date: Mon Mar  5 20:17:44 2012
New Revision: 184958

URL: http://gcc.gnu.org/viewcvs?root=gcc&view=rev&rev=184958
Log:
    PR debug/51902
    * tree.h (BLOCK_SAME_RANGE): Define.
    * function.c (block_fragments_nreverse): Clear BLOCK_SAME_RANGE
    if BLOCK_FRAGMENT_CHAIN is non-NULL, but has it cleared.
    Also clear BLOCK_SAME_RANGE if fragment chain's supercontext fragment
    isn't equal to supercontext fragment's fragment chain.
    Adjust BLOCK_SUPERCONTEXT to point to supercontext fragment's
    fragment origin.
    (blocks_nreverse_all): Likewise.
    (reorder_blocks_1): Compute BLOCK_SAME_RANGE bits.  Set
    BLOCK_SUPERCONTEXT to supercontext fragment instead of
    supercontext fragment's fragment origin.
    * dwarf2out.c (add_high_low_attributes): If stmt has the same
    range as its parent (or parents thereof etc.), use the parent's
    DW_AT_ranges value instead of creating a new .debug_ranges range.

Modified:
    trunk/gcc/ChangeLog
    trunk/gcc/dwarf2out.c
    trunk/gcc/function.c
    trunk/gcc/tree.h


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

* [Bug debug/51902] lexical_blocks inside inlined_subroutines generate duplicate debug_ranges
  2012-01-19 15:01 [Bug debug/51902] New: lexical_blocks inside inlined_subroutines generate duplicate debug_ranges mark at gcc dot gnu.org
                   ` (8 preceding siblings ...)
  2012-03-05 20:18 ` jakub at gcc dot gnu.org
@ 2012-03-06 17:43 ` jakub at gcc dot gnu.org
  9 siblings, 0 replies; 11+ messages in thread
From: jakub at gcc dot gnu.org @ 2012-03-06 17:43 UTC (permalink / raw)
  To: gcc-bugs

http://gcc.gnu.org/bugzilla/show_bug.cgi?id=51902

Jakub Jelinek <jakub at gcc dot gnu.org> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
             Status|UNCONFIRMED                 |RESOLVED
         Resolution|                            |FIXED

--- Comment #10 from Jakub Jelinek <jakub at gcc dot gnu.org> 2012-03-06 17:42:29 UTC ---
Fixed for 4.8+.


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

end of thread, other threads:[~2012-03-06 17:43 UTC | newest]

Thread overview: 11+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2012-01-19 15:01 [Bug debug/51902] New: lexical_blocks inside inlined_subroutines generate duplicate debug_ranges mark at gcc dot gnu.org
2012-01-19 18:55 ` [Bug debug/51902] " jakub at gcc dot gnu.org
2012-01-20 11:30 ` jakub at gcc dot gnu.org
2012-01-20 14:19 ` mark at gcc dot gnu.org
2012-01-20 14:20 ` jakub at gcc dot gnu.org
2012-01-20 18:01 ` jakub at gcc dot gnu.org
2012-01-21  5:23 ` mark at gcc dot gnu.org
2012-01-23 15:33 ` jakub at gcc dot gnu.org
2012-01-24 10:37 ` jakub at gcc dot gnu.org
2012-03-05 20:18 ` jakub at gcc dot gnu.org
2012-03-06 17:43 ` jakub at gcc dot gnu.org

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).