> Another problem here is that get_inline_stack returns an empty stack if
> no inlining occurred in the corresponding GIMPLE statement. So if an
> inline callsite does exist in the profile at the current GIMPLE
> statement but no inlining actually occurs during auto-profile, the
> information is just dropped.
Hi,
I created a testcase for what seems to work on trunk

gcc/testsuite/ChangeLog:

        * gcc.dg/tree-prof/afdo-vpt-earlyinline.c: New test.

diff --git a/gcc/testsuite/gcc.dg/tree-prof/afdo-vpt-earlyinline.c 
b/gcc/testsuite/gcc.dg/tree-prof/afdo-vpt-earlyinline.c
new file mode 100644
index 00000000000..3b51ea9f8a9
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-prof/afdo-vpt-earlyinline.c
@@ -0,0 +1,32 @@
+/* { dg-options "-O2 -fdump-ipa-afdo-details -fdump-tree-einline-details" } */
+/* { dg-require-profiling "-fauto-profile" } */ 
+
+volatile int array[1000];
+int reta (int i)
+{
+       return array[i];
+}
+struct wrapptr 
+{
+       int (*ret)(int);
+};
+int test (struct wrapptr *p)
+{
+       int s = 0;
+       for (int pos = 0; pos < 1000; pos++)
+         s+p->ret(pos);
+       if (s)
+               __builtin_printf ("sum error\n");
+}
+int main()
+{
+       struct wrapptr p={reta};
+       for (int i = 0; i < 10000; i++)
+               test(&p);
+       return 0;
+}
+/* { dg-final-use-autofdo { scan-tree-dump "Inlining test" "einline"} } */
+/* { dg-final-use-autofdo { scan-ipa-dump "Checking indirect call -> direct 
call reta" "afdo"} } */
+/* { dg-final-use-autofdo { scan-ipa-dump "looks good" "afdo"} } */
+/* If we inlined reta->test->main, it will contian array[pos].  */
+/* { dg-final-use-autofdo { scan-ipa-dump "array.pos_" "afdo"} } */


Here without AFDO we do not early inlined test->main since test is quite
large (has loop and two calls).  In IPA inlining we inline the whole
chain main->test->reta while resolving the indirect call rest->reta.

As tested by the testcase, autofdo is able to convince early inliner to
inline main->test since from feedback it knows that during the train run
test was inlined and it was hot.

In the VPT pass within afdo pass it resolves indirect call to p->ret to
reta and inlines it by the integrated einline pass.

So the logic works.  I think there is importnat wrong code hazard by
trusting the info from feedback to inline indirect call unspeculatively.
I think we want to inline speculatively and expect optimizers to cleanup
the indirect call.

Also I think we can remove the integrated VPT and einline passes and
move all this into actual early inliner.

Early inliner is non-recursive because it is intended to handle
primarily direct calls and it inlines already optimized function bodies
into unoptimized function body, so recursion is unecessary.

We could make it recursive for afdo and use afdo data.  We can also
integreate the VPT logic and produce speculative edges.

I think this is some work that is better to do independently of your
patch, so I still think we want to now change the code to first do the
integerated vpt+einline, then move data from inlined functions we did
not inline so far into their offline variants and finally do the
annotation.

I will check in the testcase.  It took me a while to work it out,
but I think it is quite common C++ programming pattern where the
function pointer may be virutal call or std::function callback or member
pointer.
Honza

Reply via email to