https://gcc.gnu.org/bugzilla/show_bug.cgi?id=63572

            Bug ID: 63572
           Summary: [5 Regression] ICF breaks user debugging experience
           Product: gcc
           Version: 5.0
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: debug
          Assignee: unassigned at gcc dot gnu.org
          Reporter: jakub at gcc dot gnu.org
                CC: hubicka at gcc dot gnu.org, jakub at gcc dot gnu.org,
                    jakub at redhat dot com, mliska at suse dot cz, uros at gcc 
dot gnu.org
        Depends on: 63566
            Blocks: 63571

+++ This bug was initially created as a clone of Bug #63566 +++

On -O2 -g:
#define A \
  x += y * z; \
  y = (y << ((z & 2) + 1)) \
      ^ (y >> (__SIZEOF_INT__ * __CHAR_BIT__ - (z & 2) - 1)); \
  z *= 7;
#define B A A A A A A A A A A
#define C B B B B B B B B B B

static unsigned int
f1 (unsigned int x, unsigned int y, unsigned int z)
{
  C
  return x + y + z;
}

static unsigned int
f2 (unsigned int x, unsigned int y, unsigned int z)
{
  C
  return x + y + z;
}

__attribute__((noinline, noclone)) unsigned int
f3 (unsigned int x, unsigned int y, unsigned int z)
{
  return f1 (x, z, y) + 6;
}

__attribute__((noinline, noclone)) unsigned int
f4 (unsigned int x, unsigned int y, unsigned int z)
{
  return f2 (y, x, z) + 7;
}

__attribute__((noinline, noclone, used)) unsigned int
f5 (unsigned int x, unsigned int y, unsigned int z)
{
  return f1 (2 * x, z / 2, y + 3) - 6;
}

__attribute__((noinline, noclone, used)) unsigned int
f6 (unsigned int x, unsigned int y, unsigned int z)
{
  return f2 (y + 2, x | 1, z / 73) + 1;
}

int
main ()
{
  unsigned int x = f3 (0x173214, 0x182172, 0x9314);
  unsigned int y = f4 (0x173214, 0x182172, 0x9314);
#if __SIZEOF_INT__ * __CHAR_BIT__ == 32
  if (x != 0xd8e56f78U || y != 0x494c6699U)
    __builtin_abort ();
#endif
  return 0;
}

GCC emits incomplete DW_TAG_GNU_call_site DIEs for the f1 calls (that have been
optimized into ICF alias to f2) - no DW_AT_abstract_origin is provided,
and does not emit any DW_TAG_subprogram for f1 at all, just f2.
The question is how exactly do we want to emit the DW_TAG_subprogram for
icf_merged aliases.  Name/abstract origin/function type/names of arguments must
be it's own, I guess ICF will happily merge functions where the arguments have
e.g. different argument names, or different DECL_ABSTRACT_ORIGIN etc.
My question is mainly about DW_TAG_lexical_block/DW_TAG_inlined_subroutine, but
as even names of local variables can differ, or it can have different functions
inlined, I bet we need to fully populate DW_TAG_subprogram for the ICF aliases,
and have some mapping between BLOCKs in the ICF alias and BLOCKs in the kept
definition, so that we can reconstruct ranges.  Then, when we emit
DW_TAG_subprogram details for the kept original function definition when
finalizing its RTL, we also need to handle similarly all the ICF aliases.
Which is going to be non-fun.  Also, supposedly not just that, but we also need
a way to track multiple locations, not just blocks.
E.g. in one function, first 3 statements can have one location_t, say line 31,
and last 3 statements can have another location_t, say line 38.  Now, in
another
function ICF merged with that, the similar first 2 statements can have one
location_t, say line 47, the second 2 statements can have location_t line 49
and last 2 statements location_t line 53.  So, it might be impossible to create
e.g. a pointer_map from one set of locations to another set, we'd need to
analyze the correspondence between location_t's in between all the spots in the
function (gimple_location, EXPR_LOCATION) where they appear, and perhaps create
some artificial locations to make sure there is a 1-1 mapping between all ICF
merged functions.  Another problem is that we emit these days .debug_line using
.file/.loc directives and gas constructs that.  Not sure if we can have
multiple .debug_line proglets describing the same area of code (perhaps we need
some DWARF extension for that?) and if we had that possibility, the question is
how to emit it.
As for the DW_AT_abstract_origin of DW_TAG_GNU_call_site, that should probably
be just very easy, if there is a DIE for the ICF merged alias, supposedly it
will be found normally.

And, then we'll certainly need some GDB changes (and systemtap/elfutils etc.) - 
if some code range has multiple DW_TAG_subprogram DIEs covering that range,
e.g. if you want to put a breakpoint into a line in one of the functions

Reply via email to