re PR lto/85574 (LTO bootstapped binaries differ)
[gcc.git] / gcc / ipa-icf.c
index bededc3bbd5cd9b8956911cd4c3a3e6104ca0d27..ebaf5825e1e99c6a525b08793c986ae8e17c021e 100644 (file)
@@ -1,5 +1,5 @@
 /* Interprocedural Identical Code Folding pass
-   Copyright (C) 2014-2018 Free Software Foundation, Inc.
+   Copyright (C) 2014-2019 Free Software Foundation, Inc.
 
    Contributed by Jan Hubicka <hubicka@ucw.cz> and Martin Liska <mliska@suse.cz>
 
@@ -227,6 +227,8 @@ void sem_item::set_hash (hashval_t hash)
   m_hash_set = true;
 }
 
+hash_map<const_tree, hashval_t> sem_item::m_type_hash_cache;
+
 /* Semantic function constructor that uses STACK as bitmap memory stack.  */
 
 sem_function::sem_function (bitmap_obstack *stack)
@@ -303,57 +305,6 @@ sem_function::get_hash (void)
   return m_hash;
 }
 
-/* Return ture if A1 and A2 represent equivalent function attribute lists.
-   Based on comp_type_attributes.  */
-
-bool
-sem_item::compare_attributes (const_tree a1, const_tree a2)
-{
-  const_tree a;
-  if (a1 == a2)
-    return true;
-  for (a = a1; a != NULL_TREE; a = TREE_CHAIN (a))
-    {
-      const struct attribute_spec *as;
-      const_tree attr;
-
-      as = lookup_attribute_spec (get_attribute_name (a));
-      /* TODO: We can introduce as->affects_decl_identity
-        and as->affects_decl_reference_identity if attribute mismatch
-        gets a common reason to give up on merging.  It may not be worth
-        the effort.
-        For example returns_nonnull affects only references, while
-        optimize attribute can be ignored because it is already lowered
-        into flags representation and compared separately.  */
-      if (!as)
-        continue;
-
-      attr = lookup_attribute (as->name, CONST_CAST_TREE (a2));
-      if (!attr || !attribute_value_equal (a, attr))
-        break;
-    }
-  if (!a)
-    {
-      for (a = a2; a != NULL_TREE; a = TREE_CHAIN (a))
-       {
-         const struct attribute_spec *as;
-
-         as = lookup_attribute_spec (get_attribute_name (a));
-         if (!as)
-           continue;
-
-         if (!lookup_attribute (as->name, CONST_CAST_TREE (a1)))
-           break;
-         /* We don't need to compare trees again, as we did this
-            already in first loop.  */
-       }
-      if (!a)
-        return true;
-    }
-  /* TODO: As in comp_type_attributes we may want to introduce target hook.  */
-  return false;
-}
-
 /* Compare properties of symbols N1 and N2 that does not affect semantics of
    symbol itself but affects semantics of its references from USED_BY (which
    may be NULL if it is unknown).  If comparsion is false, symbols
@@ -427,8 +378,8 @@ sem_item::compare_referenced_symbol_properties (symtab_node *used_by,
         variables just compare attributes for references - the codegen
         for constructors is affected only by those attributes that we lower
         to explicit representation (such as DECL_ALIGN or DECL_SECTION).  */
-      if (!compare_attributes (DECL_ATTRIBUTES (n1->decl),
-                              DECL_ATTRIBUTES (n2->decl)))
+      if (!attribute_list_equal (DECL_ATTRIBUTES (n1->decl),
+                                DECL_ATTRIBUTES (n2->decl)))
        return return_false_with_msg ("different var decl attributes");
       if (comp_type_attributes (TREE_TYPE (n1->decl),
                                TREE_TYPE (n2->decl)) != 1)
@@ -591,6 +542,8 @@ sem_function::equals_wpa (sem_item *item,
         return return_false_with_msg ("thunk fixed_offset mismatch");
       if (cnode->thunk.virtual_value != cnode2->thunk.virtual_value)
         return return_false_with_msg ("thunk virtual_value mismatch");
+      if (cnode->thunk.indirect_offset != cnode2->thunk.indirect_offset)
+        return return_false_with_msg ("thunk indirect_offset mismatch");
       if (cnode->thunk.this_adjusting != cnode2->thunk.this_adjusting)
         return return_false_with_msg ("thunk this_adjusting mismatch");
       if (cnode->thunk.virtual_offset_p != cnode2->thunk.virtual_offset_p)
@@ -658,7 +611,7 @@ sem_function::equals_wpa (sem_item *item,
   cl_optimization *opt1 = opts_for_fn (decl);
   cl_optimization *opt2 = opts_for_fn (item->decl);
 
-  if (opt1 != opt2 && memcmp (opt1, opt2, sizeof(cl_optimization)))
+  if (opt1 != opt2 && !cl_optimization_option_eq (opt1, opt2))
     {
       if (dump_file && (dump_flags & TDF_DETAILS))
        {
@@ -712,8 +665,8 @@ sem_function::equals_wpa (sem_item *item,
   if (comp_type_attributes (TREE_TYPE (decl),
                            TREE_TYPE (item->decl)) != 1)
     return return_false_with_msg ("different type attributes");
-  if (!compare_attributes (DECL_ATTRIBUTES (decl),
-                          DECL_ATTRIBUTES (item->decl)))
+  if (!attribute_list_equal (DECL_ATTRIBUTES (decl),
+                            DECL_ATTRIBUTES (item->decl)))
     return return_false_with_msg ("different decl attributes");
 
   /* The type of THIS pointer type memory location for
@@ -1199,7 +1152,8 @@ sem_function::merge (sem_item *alias_item)
                     "can not create wrapper of stdarg function.\n");
        }
       else if (ipa_fn_summaries
-              && ipa_fn_summaries->get_create (alias)->self_size <= 2)
+              && ipa_fn_summaries->get (alias) != NULL
+              && ipa_fn_summaries->get (alias)->self_size <= 2)
        {
          if (dump_file)
            fprintf (dump_file, "Wrapper creation is not "
@@ -1586,7 +1540,7 @@ sem_item::add_type (const_tree type, inchash::hash &hstate)
          return;
        }
 
-      hashval_t *val = optimizer->m_type_hash_cache.get (type);
+      hashval_t *val = m_type_hash_cache.get (type);
 
       if (!val)
        {
@@ -1606,7 +1560,7 @@ sem_item::add_type (const_tree type, inchash::hash &hstate)
          hstate2.add_int (nf);
          hash = hstate2.end ();
          hstate.add_hwi (hash);
-         optimizer->m_type_hash_cache.put (type, hash);
+         m_type_hash_cache.put (type, hash);
        }
       else
         hstate.add_hwi (*val);
@@ -3163,6 +3117,22 @@ sem_item_optimizer::traverse_congruence_split (congruence_class * const &cls,
   return true;
 }
 
+/* Compare function for sorting pairs in do_congruence_step_f.  */
+
+int
+sem_item_optimizer::sort_congruence_split (const void *a_, const void *b_)
+{
+  const std::pair<congruence_class *, bitmap> *a
+    = (const std::pair<congruence_class *, bitmap> *)a_;
+  const std::pair<congruence_class *, bitmap> *b
+    = (const std::pair<congruence_class *, bitmap> *)b_;
+  if (a->first->id < b->first->id)
+    return -1;
+  else if (a->first->id > b->first->id)
+    return 1;
+  return 0;
+}
+
 /* Tests if a class CLS used as INDEXth splits any congruence classes.
    Bitmap stack BMSTACK is used for bitmap allocation.  */
 
@@ -3203,13 +3173,20 @@ sem_item_optimizer::do_congruence_step_for_index (congruence_class *cls,
        }
     }
 
+  auto_vec<std::pair<congruence_class *, bitmap> > to_split;
+  to_split.reserve_exact (split_map.elements ());
+  for (hash_map <congruence_class *, bitmap>::iterator i = split_map.begin ();
+       i != split_map.end (); ++i)
+    to_split.safe_push (*i);
+  to_split.qsort (sort_congruence_split);
+
   traverse_split_pair pair;
   pair.optimizer = this;
   pair.cls = cls;
 
   splitter_class_removed = false;
-  split_map.traverse <traverse_split_pair *,
-                     sem_item_optimizer::traverse_congruence_split> (&pair);
+  for (unsigned i = 0; i < to_split.length (); ++i)
+    traverse_congruence_split (to_split[i].first, to_split[i].second, &pair);
 
   /* Bitmap clean-up.  */
   split_map.traverse <traverse_split_pair *,