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

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

           What    |Removed                     |Added
----------------------------------------------------------------------------
   Target Milestone|---                         |5.0

--- Comment #5 from Jakub Jelinek <jakub at gcc dot gnu.org> ---
Self-contained testcase (-m32 -O2 to reproduce):
#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;
}

BTW, this testcase also shows that the debug info state of ICF is not really
solved:

grep '\.set' h.s; grep -A2 'DIE.*\(DW_TAG_subprogram\|DW_TAG_GNU_call_site)\)'
h.s
    .set    f1,f2
    .uleb128 0x3    # (DIE (0x2f) DW_TAG_subprogram)
    .ascii "f2\0"    # DW_AT_name
    .byte    0x1    # DW_AT_decl_file (/tmp/h.c)
--
    .uleb128 0x5    # (DIE (0x6f) DW_TAG_subprogram)
            # DW_AT_external
    .ascii "f3\0"    # DW_AT_name
--
    .uleb128 0x7    # (DIE (0xab) DW_TAG_GNU_call_site)
    .long    .LVL559    # DW_AT_low_pc
    .byte    0    # end of children of DIE 0x6f
    .uleb128 0x5    # (DIE (0xb1) DW_TAG_subprogram)
            # DW_AT_external
    .ascii "f4\0"    # DW_AT_name
--
    .uleb128 0x8    # (DIE (0xed) DW_TAG_GNU_call_site)
    .long    .LVL561    # DW_AT_low_pc
    .long    0x2f    # DW_AT_abstract_origin
--
    .uleb128 0x5    # (DIE (0x10d) DW_TAG_subprogram)
            # DW_AT_external
    .ascii "f5\0"    # DW_AT_name
--
    .uleb128 0x7    # (DIE (0x149) DW_TAG_GNU_call_site)
    .long    .LVL563    # DW_AT_low_pc
    .byte    0    # end of children of DIE 0x10d
    .uleb128 0x5    # (DIE (0x14f) DW_TAG_subprogram)
            # DW_AT_external
    .ascii "f6\0"    # DW_AT_name
--
    .uleb128 0x8    # (DIE (0x18b) DW_TAG_GNU_call_site)
    .long    .LVL565    # DW_AT_low_pc
    .long    0x2f    # DW_AT_abstract_origin
--

shows that
1) there is no DW_TAG_subprogram for f1 emitted (what exactly should be the
content of it is up to the discussions with GDB folks I guess, either pretty
much a copy of DW_TAG_subprogram for f2 with adjusted real type if needed,
perhaps different names of arguments etc., or some way to refer to f2
subprogram DIE and telling it is ICF merged)
2) probably because of that DW_TAG_GNU_call_site in f3 and f5 don't have
DW_AT_abstract_origin, meaning that even if the debugger had right code to
handle ICF, it could not, because we are not telling it that we were calling f1
there

Reply via email to