Fix updating of call_stmt_site_hash
authorJan Hubicka <jh@suse.cz>
Tue, 21 Jan 2020 15:33:43 +0000 (16:33 +0100)
committerJan Hubicka <jh@suse.cz>
Tue, 21 Jan 2020 15:33:43 +0000 (16:33 +0100)
This patch fixes ICE causes by call stmt site hash going out of sync.  For
speculative edges it is assumed to contain a direct call so if we are
removing it hashtable needs to be updated.  I realize that the code is ugly
but I will leave cleanup for next stage1.

Bootstrapped/regtested x86_64-linux. This patch makes it possible to build
Firefox again.

PR lto/93318
* cgraph.c (cgraph_edge::resolve_speculation,
cgraph_edge::redirect_call_stmt_to_callee): Fix update of
call_stmt_site_hash.

gcc/ChangeLog
gcc/cgraph.c
gcc/ipa.c

index 48c423a3b099320197d385a98dd14c2e3a56827b..1e596773ba0736f43dbb149198e56c9328b4bdc3 100644 (file)
@@ -1,3 +1,10 @@
+2020-01-18  Jan Hubicka  <hubicka@ucw.cz>
+
+       PR lto/93318    
+       * cgraph.c (cgraph_edge::resolve_speculation,
+       cgraph_edge::redirect_call_stmt_to_callee): Fix update of
+       call_stmt_site_hash.
+
 2020-01-21  Martin Liska  <mliska@suse.cz>
 
        * config/rs6000/rs6000.c (common_mode_defined): Remove
index 187f6ed30ba357b7bfaddf6039e72e205f3ac366..f7ebcc917d17d297e3d479d6312496ebca4863aa 100644 (file)
@@ -1248,7 +1248,22 @@ cgraph_edge::resolve_speculation (cgraph_edge *edge, tree callee_decl)
   else
     e2->callee->remove_symbol_and_inline_clones ();
   if (edge->caller->call_site_hash)
-    cgraph_update_edge_in_call_site_hash (edge);
+    {
+      /* We always maintain direct edge in the call site hash, if one
+        exists.  */
+      if (!edge->num_speculative_call_targets_p ())
+       cgraph_update_edge_in_call_site_hash (edge);
+      else
+       {
+         cgraph_edge *e;
+         for (e = edge->caller->callees;
+              e->call_stmt != edge->call_stmt
+              || e->lto_stmt_uid != edge->lto_stmt_uid;
+              e = e->next_callee)
+           ;
+         cgraph_update_edge_in_call_site_hash (e);
+       }
+    }
   return edge;
 }
 
@@ -1414,7 +1429,20 @@ cgraph_edge::redirect_call_stmt_to_callee (cgraph_edge *e)
          /* Indirect edges are not both in the call site hash.
             get it updated.  */
          if (e->caller->call_site_hash)
-           cgraph_update_edge_in_call_site_hash (e2);
+           {
+             if (!e2->num_speculative_call_targets_p ())
+               cgraph_update_edge_in_call_site_hash (e2);
+             else
+               {
+                 cgraph_edge *e;
+                 for (e = e2->caller->callees;
+                      e->call_stmt != e2->call_stmt
+                      || e->lto_stmt_uid != e2->lto_stmt_uid;
+                      e = e->next_callee)
+                   ;
+                 cgraph_update_edge_in_call_site_hash (e);
+               }
+           }
          pop_cfun ();
          /* Continue redirecting E to proper target.  */
        }
index e2635a717898f2571c426aab7ba0e1add0e58ec6..554819316682a3f2cd5950baba84b858edc03b16 100644 (file)
--- a/gcc/ipa.c
+++ b/gcc/ipa.c
@@ -391,17 +391,20 @@ symbol_table::remove_unreachable_nodes (FILE *file)
                      n->used_as_abstract_origin = true;
                }
            }
-         /* If any symbol in a comdat group is reachable, force
-            all externally visible symbols in the same comdat
+         /* If any non-external and non-local symbol in a comdat group is
+            reachable, force all externally visible symbols in the same comdat
             group to be reachable as well.  Comdat-local symbols
             can be discarded if all uses were inlined.  */
-         if (node->same_comdat_group)
+         if (node->same_comdat_group
+             && node->externally_visible
+             && !DECL_EXTERNAL (node->decl))
            {
              symtab_node *next;
              for (next = node->same_comdat_group;
                   next != node;
                   next = next->same_comdat_group)
                if (!next->comdat_local_p ()
+                   && !DECL_EXTERNAL (next->decl)
                    && !reachable.add (next))
                  enqueue_node (next, &first, &reachable);
            }