https://gcc.gnu.org/bugzilla/show_bug.cgi?id=92983
Richard Biener <rguenth at gcc dot gnu.org> changed: What |Removed |Added ---------------------------------------------------------------------------- Status|WAITING |NEW --- Comment #8 from Richard Biener <rguenth at gcc dot gnu.org> --- So I did some more experiments. With int foo (int x) { if (x != 0) return 1; __builtin_printf ("%d\n", x); __builtin_printf ("%d\n", x); __builtin_printf ("%d\n", x); __builtin_printf ("%d\n", x); __builtin_printf ("%d\n", x); __builtin_printf ("%d\n", x); __builtin_printf ("%d\n", x); return 0; } int main() { int i = foo (0); return i; } IPA split splits foo. Arranging things (unpatched) to not inline anything after splitting does Temporary breakpoint 1, main () at x.c:16 16 { (gdb) s 17 int i = foo (0); (gdb) s foo (x=0) at x.c:3 3 if (x != 0) (gdb) s foo (x=<optimized out>) at x.c:5 5 __builtin_printf ("%d\n", x); (gdb) fin Run till exit from #0 foo (x=<optimized out>) at x.c:5 0 0 0 0 0 0 0 0x0000000000400522 in main () at x.c:17 17 int i = foo (0); Value returned is $1 = 0 arranging the head to be inlined into main Temporary breakpoint 1, main () at x.c:17 17 int i = foo (0); (gdb) s foo (x=0) at x.c:17 17 int i = foo (0); (gdb) s foo (x=<optimized out>) at x.c:5 5 __builtin_printf ("%d\n", x); (gdb) fin Run till exit from #0 foo (x=<optimized out>) at x.c:5 0 0 0 0 0 0 0 __libc_start_main (main=0x400430 <main>, argc=1, argv=0x7fffffffde98, init=<optimized out>, fini=<optimized out>, rtld_fini=<optimized out>, stack_end=0x7fffffffde88) at libc-start.c:323 323 libc-start.c: No such file or directory. Value returned is $1 = 0 arranging the tail to be re-inlined into the head: Temporary breakpoint 1, main () at x.c:16 16 { (gdb) s 17 int i = foo (0); (gdb) foo (x=0) at x.c:3 3 if (x != 0) (gdb) 5 __builtin_printf ("%d\n", x); (gdb) fin Run till exit from #0 foo (x=0) at x.c:5 0 0 0 0 0 0 0 0x0000000000400522 in main () at x.c:17 17 int i = foo (0); now with the proposed patch: Temporary breakpoint 1, main () at x.c:16 16 { (gdb) s 17 int i = foo (0); (gdb) foo (x=0) at x.c:3 3 if (x != 0) (gdb) __printf (format=0x400644 "%d\n") at printf.c:28 28 printf.c: No such file or directory. (gdb) fin Run till exit from #0 __printf (format=0x400644 "%d\n") at printf.c:28 0 0x0000000000400542 in foo.part () at x.c:18 18 return i; Value returned is $1 = 2 (gdb) fin Run till exit from #0 0x0000000000400542 in foo.part () at x.c:18 0 0 0 0 0 0 0x0000000000400522 in main () at x.c:17 17 int i = foo (0); and Temporary breakpoint 1, main () at x.c:17 17 int i = foo (0); (gdb) s foo (x=0) at x.c:17 17 int i = foo (0); (gdb) 0x0000000000400520 in foo.part () (gdb) Single stepping until exit from function foo.part.0, which has no line number information. __printf (format=0x400634 "%d\n") at printf.c:28 28 printf.c: No such file or directory. (gdb) fin Run till exit from #0 __printf (format=0x400634 "%d\n") at printf.c:28 0 0x0000000000400532 in foo.part () Value returned is $1 = 2 (gdb) fin Run till exit from #0 0x0000000000400532 in foo.part () 0 0 0 0 0 0 __libc_start_main (main=0x400430 <main>, argc=1, argv=0x7fffffffde98, init=<optimized out>, fini=<optimized out>, rtld_fini=<optimized out>, stack_end=0x7fffffffde88) at libc-start.c:323 323 libc-start.c: No such file or directory. and finally Temporary breakpoint 1, main () at x.c:16 16 { (gdb) s 17 int i = foo (0); (gdb) foo (x=0) at x.c:3 3 if (x != 0) (gdb) 1 int foo (int x) (gdb) __printf (format=format@entry=0x400634 "%d\n") at printf.c:28 28 printf.c: No such file or directory. (gdb) fin Run till exit from #0 __printf (format=format@entry=0x400634 "%d\n") at printf.c:28 0 0x0000000000400552 in foo (x=<optimized out>) at x.c:1 1 int foo (int x) Value returned is $1 = 2 (gdb) fin Run till exit from #0 0x0000000000400552 in foo (x=<optimized out>) at x.c:1 0 0 0 0 0 0 0x0000000000400522 in main () at x.c:17 17 int i = foo (0); Value returned is $2 = 0 to me that clearly isn't an improvement :/ I guess gdb doesn't like the DW_TAG_inlined_subroutine for DECL_INGORED_P entities - in this case we end up with <2><18e>: Abbrev Number: 11 (DW_TAG_inlined_subroutine) <18f> DW_AT_entry_pc : 0x400540 <197> DW_AT_GNU_entry_view: 1 <198> DW_AT_ranges : 0x40 <19c> DW_AT_call_file : 1 <19d> DW_AT_call_line : 1 <19e> DW_AT_call_column : 5 <19f> DW_AT_sibling : <0x1b1> but there's no abstract origin here. Of course the whole point of the patch was to avoid the "inline" as that would appear as a breakpoint location. I suppose in dwarf2out we should elide the use of DW_TAG_inlined_subroutine for DECL_IGNORED (or even DECL_ARTIFICIAL?) functions and instead just emit a lexical block (w/o abstract origin)? That said, as usual it's difficult to say what is an appropriate DWARF representation for the issue at hand and what's the optimal representation for the gdb side. I suppose for the split function case re-inlining the tail should be transparent but that's not how the block tree side looks like. For the case where the head is inlined there's no way but to have the entry to the head visible as inlined subroutine - and since the actual call to the tail creates a new frame I don't see how a consumer can not make it visible (in the patched case above you see gdb simply presents the symbol here and we've elided _all_ debuginfo which clearly isn't what we want). So for the outline case we maybe need a DWARF extension telling the consumer (would maybe also help OMP outlined functions). So no, at this point I'm not going to push the simple proposed patch, it seems to need care on the dwarf2out side at least (and eventually some guality testcase with all inlining variants of a call to a split function).