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