Hi,
this patch fixes ICE bilding lto1 with autoprofiledbootstrap and in pr114790.
What happens is that auto-fdo speculatively devirtualizes to a wrong target.
This is due to a bug where it mixes up dwarf names and linkage names of inline
functions I need to fix as well.

Later we clone at WPA time. At ltrans time clone is materialized and call is
turned into a direct call (this optimization is missed by ipa-cp propagation).
At this time we should resolve speculation but we don't.  As a result we get
error from verifier after inlining complaining that there is speculative call
with corresponding direct call lacking speculative flag.

This seems long-lasting problem in cgraph_update_edges_for_call_stmt_node but
I suppose it does not trigger since we usually speculate correctly or notice
the direct call at WPA time already.

profiledbootstrapped and autoprofiledbootstraped/regtested x86_64-linux

gcc/ChangeLog:

        PR ipa/114790
        * cgraph.cc (cgraph_update_edges_for_call_stmt_node): Resolve 
devirtualization
        if call statement was optimized out or turned to direct call.

gcc/testsuite/ChangeLog:

        * g++.dg/lto/pr114790_0.C: New test.
        * g++.dg/lto/pr114790_1.C: New test.


diff --git a/gcc/cgraph.cc b/gcc/cgraph.cc
index 94a2e6e6105..32071a84bac 100644
--- a/gcc/cgraph.cc
+++ b/gcc/cgraph.cc
@@ -1790,6 +1790,19 @@ cgraph_update_edges_for_call_stmt_node (cgraph_node 
*node,
 
       if (e)
        {
+         /* If call was devirtualized during cloning, mark edge
+            as resolved.  */
+         if (e->speculative)
+           {
+             if (new_stmt && is_gimple_call (new_stmt))
+               {
+                 tree decl = gimple_call_fndecl (new_stmt);
+                 if (decl)
+                   e = cgraph_edge::resolve_speculation (e, decl);
+               }
+             else
+               e = cgraph_edge::resolve_speculation (e, NULL);
+           }
          /* Keep calls marked as dead dead.  */
          if (new_stmt && is_gimple_call (new_stmt) && e->callee
              && fndecl_built_in_p (e->callee->decl, BUILT_IN_UNREACHABLE,

diff --git a/gcc/testsuite/g++.dg/lto/pr114790_0.C 
b/gcc/testsuite/g++.dg/lto/pr114790_0.C
new file mode 100644
index 00000000000..eed112df389
--- /dev/null
+++ b/gcc/testsuite/g++.dg/lto/pr114790_0.C
@@ -0,0 +1,16 @@
+// { dg-lto-do link }
+// { dg-lto-options { { -w -flto -g -flto-partition=1to1 -O2 -shared -fPIC 
-fvisibility=hidden} } }
+// { dg-require-effective-target fpic }
+// { dg-require-effective-target shared }
+struct APITracerContext {
+  virtual ~APITracerContext() = default;
+  virtual void releaseActivetracersList() = 0;
+};
+struct APITracerContextImp : APITracerContext {
+  ~APITracerContextImp() override;
+  void releaseActivetracersList() override;
+};
+struct APITracerContextImp globalAPITracerContextImp;
+struct APITracerContextImp *pGlobalAPITracerContextImp = 
&globalAPITracerContextImp;
+APITracerContextImp::~APITracerContextImp() {}
+
diff --git a/gcc/testsuite/g++.dg/lto/pr114790_1.C 
b/gcc/testsuite/g++.dg/lto/pr114790_1.C
new file mode 100644
index 00000000000..511fae45be8
--- /dev/null
+++ b/gcc/testsuite/g++.dg/lto/pr114790_1.C
@@ -0,0 +1,15 @@
+struct APITracerContext {
+  virtual void releaseActivetracersList() = 0;
+};
+extern struct APITracerContextImp *pGlobalAPITracerContextImp;
+struct APITracerContextImp : APITracerContext { void 
releaseActivetracersList();};
+int g();
+inline int
+apiTracerWrapperImp(  ) {
+  for (int i = 0; i < g(); i++) 
+  pGlobalAPITracerContextImp->releaseActivetracersList();
+}
+__attribute__((visibility("default"))) int
+zeCommandListAppendMemoryCopyTracing() {
+  return apiTracerWrapperImp(      );
+}

Reply via email to