diff mbox series

Remove -fodr-type-merging

Message ID 20190606211304.vxwnqlw7w6p5pj5d@kam.mff.cuni.cz
State New
Headers show
Series Remove -fodr-type-merging | expand

Commit Message

Jan Hubicka June 6, 2019, 9:13 p.m. UTC
Hi,
at the type introducing ODR type merging via mangled type names I was
concerned about streaming overhead of this infrastructure and
implemented flag to disable it.  Maintaining this flag is harder over a
time since we really want to establing ODR based type euivalences and
also the type streaming is now relatively cheap after the type
simplification and merging improvemets.

This patch thus drops the flag. I plan to commit it tomorrow if there
are no complains.

Honza

	* common.opt (flto-odr-type-merging): Ignore.
	* invoke.texi (-flto-odr-type-merging): Remove.
	* ipa-devirt.c (odr_vtable_hasher:odr_name_hasher): Remove.
	(can_be_vtable_hashed_p): Remove.
	(hash_odr_vtable): Remove.
	(odr_vtable_hasher::hash): Remove.
	(types_same_for_odr): Remove.
	(types_odr_comparable): Remove.
	(odr_vtable_hasher::equal): Remove.
	(odr_vtable_hash_type, odr_vtable_hash): Remove.	
	(add_type_duplicate): Do not synchronize vtable and name hashtables.
	(get_odr_type): Do not use vtable hash.
	(dump_odr_type): Remove commented out code.
	(build_type_inheritance_graph): Do not allocate vtable hash.
	(rebuild_type_inheritance_graph): Do not delete vtable hash.
	* ipa-utils.h (type_with_linkage_p): Drop vtable hash path.
	(odr_type_p): Likewise.
	* tree.c (need_assembler_name_p): Remove flag_lto_odr_type_mering
	test.
diff mbox series

Patch

Index: common.opt
===================================================================
--- common.opt	(revision 272018)
+++ common.opt	(working copy)
@@ -1888,8 +1888,8 @@  Common Joined RejectNegative UInteger Va
 -flto-compression-level=<number>	Use zlib compression level <number> for IL.
 
 flto-odr-type-merging
-Common Report Var(flag_lto_odr_type_mering) Init(1)
-Merge C++ types using One Definition Rule.
+Common Ignore
+Does nothing.  Preserved for backward compatibility.
 
 flto-report
 Common Report Var(flag_lto_report) Init(0)
Index: doc/invoke.texi
===================================================================
--- doc/invoke.texi	(revision 272018)
+++ doc/invoke.texi	(working copy)
@@ -7357,7 +7357,7 @@  Do not warn about compile-time overflow
 @opindex Wno-odr
 @opindex Wodr
 Warn about One Definition Rule violations during link-time optimization.
-Requires @option{-flto-odr-type-merging} to be enabled.  Enabled by default.
+Enabled by default.
 
 @item -Wopenmp-simd
 @opindex Wopenmp-simd
@@ -10353,12 +10353,6 @@  The value @samp{one} specifies that exac
 used while the value @samp{none} bypasses partitioning and executes
 the link-time optimization step directly from the WPA phase.
 
-@item -flto-odr-type-merging
-@opindex flto-odr-type-merging
-Enable streaming of mangled types names of C++ types and their unification
-at link time.  This increases size of LTO object files, but enables
-diagnostics about One Definition Rule violations.
-
 @item -flto-compression-level=@var{n}
 @opindex flto-compression-level
 This option specifies the level of compression used for intermediate
Index: ipa-devirt.c
===================================================================
--- ipa-devirt.c	(revision 272018)
+++ ipa-devirt.c	(working copy)
@@ -284,16 +284,6 @@  struct odr_name_hasher : pointer_hash <o
   static inline void remove (odr_type_d *);
 };
 
-/* Has used to unify ODR types based on their associated virtual table.
-   This hash is needed to keep -fno-lto-odr-type-merging to work and contains
-   only polymorphic types.  Types with mangled names are inserted to both.  */
-
-struct odr_vtable_hasher:odr_name_hasher
-{
-  static inline hashval_t hash (const odr_type_d *);
-  static inline bool equal (const odr_type_d *, const tree_node *);
-};
-
 static bool
 can_be_name_hashed_p (tree t)
 {
@@ -329,51 +319,6 @@  odr_name_hasher::hash (const odr_type_d
   return hash_odr_name (odr_type->type);
 }
 
-static bool
-can_be_vtable_hashed_p (tree t)
-{
-  /* vtable hashing can distinguish only main variants.  */
-  if (TYPE_MAIN_VARIANT (t) != t)
-    return false;
-  /* Anonymous namespace types are always handled by name hash.  */
-  if (type_with_linkage_p (t) && type_in_anonymous_namespace_p (t))
-    return false;
-  return (TREE_CODE (t) == RECORD_TYPE
-	  && TYPE_BINFO (t) && BINFO_VTABLE (TYPE_BINFO (t)));
-}
-
-/* Hash type by assembler name of its vtable.  */
-
-static hashval_t
-hash_odr_vtable (const_tree t)
-{
-  tree v = BINFO_VTABLE (TYPE_BINFO (TYPE_MAIN_VARIANT (t)));
-  inchash::hash hstate;
-
-  gcc_checking_assert (in_lto_p);
-  gcc_checking_assert (!type_in_anonymous_namespace_p (t));
-  gcc_checking_assert (TREE_CODE (t) == RECORD_TYPE
-		       && TYPE_BINFO (t) && BINFO_VTABLE (TYPE_BINFO (t)));
-  gcc_checking_assert (TYPE_MAIN_VARIANT (t) == t);
-
-  if (TREE_CODE (v) == POINTER_PLUS_EXPR)
-    {
-      add_expr (TREE_OPERAND (v, 1), hstate);
-      v = TREE_OPERAND (TREE_OPERAND (v, 0), 0);
-    }
-
-  hstate.add_hwi (IDENTIFIER_HASH_VALUE (DECL_ASSEMBLER_NAME (v)));
-  return hstate.end ();
-}
-
-/* Return the computed hashcode for ODR_TYPE.  */
-
-inline hashval_t
-odr_vtable_hasher::hash (const odr_type_d *odr_type)
-{
-  return hash_odr_vtable (odr_type->type);
-}
-
 /* For languages with One Definition Rule, work out if
    types are the same based on their name.
 
@@ -404,60 +349,6 @@  types_same_for_odr (const_tree type1, co
       || (type_with_linkage_p (type2) && type_in_anonymous_namespace_p (type2)))
     return false;
 
-
-  /* ODR name of the type is set in DECL_ASSEMBLER_NAME of its TYPE_NAME.
-
-     Ideally we should never need types without ODR names here.  It can however
-     happen in two cases:
-
-       1) for builtin types that are not streamed but rebuilt in lto/lto-lang.c
-          Here testing for equivalence is safe, since their MAIN_VARIANTs are
-          unique.
-       2) for units streamed with -fno-lto-odr-type-merging.  Here we can't
-	  establish precise ODR equivalency, but for correctness we care only
-	  about equivalency on complete polymorphic types.  For these we can
-	  compare assembler names of their virtual tables.  */
-  if ((!TYPE_NAME (type1) || !DECL_ASSEMBLER_NAME_SET_P (TYPE_NAME (type1)))
-      || (!TYPE_NAME (type2) || !DECL_ASSEMBLER_NAME_SET_P (TYPE_NAME (type2))))
-    {
-      /* See if types are obviously different (i.e. different codes
-	 or polymorphic wrt non-polymorphic).  This is not strictly correct
-	 for ODR violating programs, but we can't do better without streaming
-	 ODR names.  */
-      if (TREE_CODE (type1) != TREE_CODE (type2))
-	return false;
-      if (TREE_CODE (type1) == RECORD_TYPE
-	  && (TYPE_BINFO (type1) == NULL_TREE)
-	      != (TYPE_BINFO (type2) == NULL_TREE))
-	return false;
-      if (TREE_CODE (type1) == RECORD_TYPE && TYPE_BINFO (type1)
-	  && (BINFO_VTABLE (TYPE_BINFO (type1)) == NULL_TREE)
-	     != (BINFO_VTABLE (TYPE_BINFO (type2)) == NULL_TREE))
-	return false;
-
-      /* At the moment we have no way to establish ODR equivalence at LTO
-	 other than comparing virtual table pointers of polymorphic types.
-	 Eventually we should start saving mangled names in TYPE_NAME.
-	 Then this condition will become non-trivial.  */
-
-      if (TREE_CODE (type1) == RECORD_TYPE
-	  && TYPE_BINFO (type1) && TYPE_BINFO (type2)
-	  && BINFO_VTABLE (TYPE_BINFO (type1))
-	  && BINFO_VTABLE (TYPE_BINFO (type2)))
-	{
-	  tree v1 = BINFO_VTABLE (TYPE_BINFO (type1));
-	  tree v2 = BINFO_VTABLE (TYPE_BINFO (type2));
-	  gcc_assert (TREE_CODE (v1) == POINTER_PLUS_EXPR
-		      && TREE_CODE (v2) == POINTER_PLUS_EXPR);
-	  return (operand_equal_p (TREE_OPERAND (v1, 1),
-				   TREE_OPERAND (v2, 1), 0)
-		  && DECL_ASSEMBLER_NAME
-			 (TREE_OPERAND (TREE_OPERAND (v1, 0), 0))
-		     == DECL_ASSEMBLER_NAME
-			 (TREE_OPERAND (TREE_OPERAND (v2, 0), 0)));
-	}
-      gcc_unreachable ();
-    }
   return (DECL_ASSEMBLER_NAME (TYPE_NAME (type1))
 	  == DECL_ASSEMBLER_NAME (TYPE_NAME (type2)));
 }
@@ -473,11 +364,7 @@  types_odr_comparable (tree t1, tree t2)
   return (!in_lto_p
 	  || TYPE_MAIN_VARIANT (t1) == TYPE_MAIN_VARIANT (t2)
 	  || (odr_type_p (TYPE_MAIN_VARIANT (t1))
-	      && odr_type_p (TYPE_MAIN_VARIANT (t2)))
-	  || (TREE_CODE (t1) == RECORD_TYPE && TREE_CODE (t2) == RECORD_TYPE
-	      && TYPE_BINFO (t1) && TYPE_BINFO (t2)
-	      && polymorphic_type_binfo_p (TYPE_BINFO (t1))
-	      && polymorphic_type_binfo_p (TYPE_BINFO (t2))));
+	      && odr_type_p (TYPE_MAIN_VARIANT (t2))));
 }
 
 /* Return true if T1 and T2 are ODR equivalent.  If ODR equivalency is not
@@ -569,31 +456,6 @@  odr_name_hasher::equal (const odr_type_d
 	  == DECL_ASSEMBLER_NAME (TYPE_NAME (t2)));
 }
 
-/* Compare types T1 and T2 and return true if they are
-   equivalent.  */
-
-inline bool
-odr_vtable_hasher::equal (const odr_type_d *o1, const tree_node *t2)
-{
-  tree t1 = o1->type;
-
-  gcc_checking_assert (TYPE_MAIN_VARIANT (t2) == t2);
-  gcc_checking_assert (TYPE_MAIN_VARIANT (t1) == t1);
-  gcc_checking_assert (in_lto_p);
-  t1 = TYPE_MAIN_VARIANT (t1);
-  t2 = TYPE_MAIN_VARIANT (t2);
-  if (t1 == t2)
-    return true;
-  tree v1 = BINFO_VTABLE (TYPE_BINFO (t1));
-  tree v2 = BINFO_VTABLE (TYPE_BINFO (t2));
-  return (operand_equal_p (TREE_OPERAND (v1, 1),
-			   TREE_OPERAND (v2, 1), 0)
-	  && DECL_ASSEMBLER_NAME
-		 (TREE_OPERAND (TREE_OPERAND (v1, 0), 0))
-	     == DECL_ASSEMBLER_NAME
-		 (TREE_OPERAND (TREE_OPERAND (v2, 0), 0)));
-}
-
 /* Free ODR type V.  */
 
 inline void
@@ -610,8 +472,6 @@  odr_name_hasher::remove (odr_type_d *v)
 
 typedef hash_table<odr_name_hasher> odr_hash_type;
 static odr_hash_type *odr_hash;
-typedef hash_table<odr_vtable_hasher> odr_vtable_hash_type;
-static odr_vtable_hash_type *odr_vtable_hash;
 
 /* ODR types are also stored into ODR_TYPE vector to allow consistent
    walking.  Bases appear before derived types.  Vector is garbage collected
@@ -1750,12 +1610,8 @@  add_type_duplicate (odr_type val, tree t
 
   val->types_set->add (type);
 
-  /* If we now have a mangled name, be sure to record it to val->type
-     so ODR hash can work.  */
-
-  if (can_be_name_hashed_p (type) && !can_be_name_hashed_p (val->type))
-    SET_DECL_ASSEMBLER_NAME (TYPE_NAME (val->type),
-			     DECL_ASSEMBLER_NAME (TYPE_NAME (type)));
+  gcc_checking_assert (can_be_name_hashed_p (type)
+		       && can_be_name_hashed_p (val->type));
 
   bool merge = true;
   bool base_mismatch = false;
@@ -2034,7 +1890,6 @@  odr_type
 get_odr_type (tree type, bool insert)
 {
   odr_type_d **slot = NULL;
-  odr_type_d **vtable_slot = NULL;
   odr_type val = NULL;
   hashval_t hash;
   bool build_bases = false;
@@ -2045,68 +1900,23 @@  get_odr_type (tree type, bool insert)
   if (!in_lto_p && !TYPE_STRUCTURAL_EQUALITY_P (type))
     type = TYPE_CANONICAL (type);
 
-  gcc_checking_assert (can_be_name_hashed_p (type)
-		       || can_be_vtable_hashed_p (type));
+  gcc_checking_assert (can_be_name_hashed_p (type));
 
-  /* Lookup entry, first try name hash, fallback to vtable hash.  */
-  if (can_be_name_hashed_p (type))
-    {
-      hash = hash_odr_name (type);
-      slot = odr_hash->find_slot_with_hash (type, hash,
-					    insert ? INSERT : NO_INSERT);
-    }
-  if ((!slot || !*slot) && in_lto_p && can_be_vtable_hashed_p (type))
-    {
-      hash = hash_odr_vtable (type);
-      if (!odr_vtable_hash)
-        odr_vtable_hash = new odr_vtable_hash_type (23);
-      vtable_slot = odr_vtable_hash->find_slot_with_hash (type, hash,
-					           insert ? INSERT : NO_INSERT);
-    }
+  hash = hash_odr_name (type);
+  slot = odr_hash->find_slot_with_hash (type, hash,
+					insert ? INSERT : NO_INSERT);
 
-  if (!slot && !vtable_slot)
+  if (!slot)
     return NULL;
 
   /* See if we already have entry for type.  */
-  if ((slot && *slot) || (vtable_slot && *vtable_slot))
+  if (*slot)
     {
-      if (slot && *slot)
-	{
-	  val = *slot;
-	  if (flag_checking
-	      && in_lto_p && can_be_vtable_hashed_p (type))
-	    {
-	      hash = hash_odr_vtable (type);
-	      vtable_slot = odr_vtable_hash->find_slot_with_hash (type, hash,
-						                  NO_INSERT);
-	      gcc_assert (!vtable_slot || *vtable_slot == *slot);
-	      vtable_slot = NULL;
-	    }
-	}
-      else if (*vtable_slot)
-	val = *vtable_slot;
+      val = *slot;
 
       if (val->type != type && insert
 	  && (!val->types_set || !val->types_set->add (type)))
-	{
-	  /* We have type duplicate, but it may introduce vtable name or
- 	     mangled name; be sure to keep hashes in sync.  */
-	  if (in_lto_p && can_be_vtable_hashed_p (type)
-	      && (!vtable_slot || !*vtable_slot))
-	    {
-	      if (!vtable_slot)
-		{
-		  hash = hash_odr_vtable (type);
-		  vtable_slot = odr_vtable_hash->find_slot_with_hash
-			     (type, hash, INSERT);
-		  gcc_checking_assert (!*vtable_slot || *vtable_slot == val);
-		}
-	      *vtable_slot = val;
-	    }
-	  if (slot && !*slot)
-	    *slot = val;
-	  build_bases = add_type_duplicate (val, type);
-	}
+	build_bases = add_type_duplicate (val, type);
     }
   else
     {
@@ -2120,10 +1930,7 @@  get_odr_type (tree type, bool insert)
 	val->anonymous_namespace = 0;
       build_bases = COMPLETE_TYPE_P (val->type);
       insert_to_odr_array = true;
-      if (slot)
-        *slot = val;
-      if (vtable_slot)
-	*vtable_slot = val;
+      *slot = val;
     }
 
   if (build_bases && TREE_CODE (type) == RECORD_TYPE && TYPE_BINFO (type)
@@ -2196,11 +2003,7 @@  void
 register_odr_type (tree type)
 {
   if (!odr_hash)
-    {
-      odr_hash = new odr_hash_type (23);
-      if (in_lto_p)
-        odr_vtable_hash = new odr_vtable_hash_type (23);
-    }
+    odr_hash = new odr_hash_type (23);
   if (type == TYPE_MAIN_VARIANT (type))
     {
       /* To get ODR warings right, first register all sub-types.  */
@@ -2258,9 +2061,6 @@  dump_odr_type (FILE *f, odr_type t, int
   fprintf (f, "%s\n", t->all_derivations_known ? " (derivations known)":"");
   if (TYPE_NAME (t->type))
     {
-      /*fprintf (f, "%*s defined at: %s:%i\n", indent * 2, "",
-	       DECL_SOURCE_FILE (TYPE_NAME (t->type)),
-	       DECL_SOURCE_LINE (TYPE_NAME (t->type)));*/
       if (DECL_ASSEMBLER_NAME_SET_P (TYPE_NAME (t->type)))
         fprintf (f, "%*s mangled name: %s\n", indent * 2, "",
 		 IDENTIFIER_POINTER
@@ -2400,8 +2200,6 @@  build_type_inheritance_graph (void)
   timevar_push (TV_IPA_INHERITANCE);
   inheritance_dump_file = dump_begin (TDI_inheritance, &flags);
   odr_hash = new odr_hash_type (23);
-  if (in_lto_p)
-    odr_vtable_hash = new odr_vtable_hash_type (23);
 
   /* We reconstruct the graph starting of types of all methods seen in the
      unit.  */
@@ -2892,10 +2690,7 @@  rebuild_type_inheritance_graph ()
   if (!odr_hash)
     return;
   delete odr_hash;
-  if (in_lto_p)
-    delete odr_vtable_hash;
   odr_hash = NULL;
-  odr_vtable_hash = NULL;
   odr_types_ptr = NULL;
   free_polymorphic_call_targets_hash ();
 }
Index: ipa-utils.h
===================================================================
--- ipa-utils.h	(revision 272018)
+++ ipa-utils.h	(working copy)
@@ -187,19 +187,14 @@  type_with_linkage_p (const_tree t)
   if (!TYPE_NAME (t) || TREE_CODE (TYPE_NAME (t)) != TYPE_DECL)
     return false;
 
-  /* To support -fno-lto-odr-type-merigng recognize types with vtables
-     to have linkage.  */
-  if (RECORD_OR_UNION_TYPE_P (t)
-      && TYPE_BINFO (t) && BINFO_VTABLE (TYPE_BINFO (t)))
-    return true;
-
-  /* After free_lang_data was run and -flto-odr-type-merging we can recongize
+  /* After free_lang_data was run we can recongize
      types with linkage by presence of mangled name.  */
   if (DECL_ASSEMBLER_NAME_SET_P (TYPE_NAME (t)))
     return true;
 
   if (in_lto_p)
     return false;
+
   /* We used to check for TYPE_STUB_DECL but that is set to NULL for forward
      declarations.  */
 
@@ -243,23 +238,8 @@  odr_type_p (const_tree t)
   /* We do not have this information when not in LTO, but we do not need
      to care, since it is used only for type merging.  */
   gcc_checking_assert (in_lto_p || flag_lto);
-
-  if (!type_with_linkage_p (t))
-    return false;
-
-  /* To support -fno-lto-odr-type-merging consider types with vtables ODR.  */
-  if (type_in_anonymous_namespace_p (t))
-    return true;
-
-  if (TYPE_NAME (t) && DECL_ASSEMBLER_NAME_SET_P (TYPE_NAME (t)))
-    {
-      /* C++ FE uses magic <anon> as assembler names of anonymous types.
- 	 verify that this match with type_in_anonymous_namespace_p.  */
-      gcc_checking_assert (strcmp ("<anon>",
-				   IDENTIFIER_POINTER
-				   (DECL_ASSEMBLER_NAME (TYPE_NAME (t)))));
-      return true;
-    }
+  return TYPE_NAME (t) && TREE_CODE (TYPE_NAME (t)) == TYPE_DECL
+         && DECL_ASSEMBLER_NAME_SET_P (TYPE_NAME (t));
   return false;
 }
 
Index: tree.c
===================================================================
--- tree.c	(revision 272018)
+++ tree.c	(working copy)
@@ -5590,8 +5590,7 @@  need_assembler_name_p (tree decl)
 
   if (TREE_CODE (decl) == TYPE_DECL)
     {
-      if (flag_lto_odr_type_mering
-	  && DECL_NAME (decl)
+      if (DECL_NAME (decl)
 	  && decl == TYPE_NAME (TREE_TYPE (decl))
 	  && TYPE_MAIN_VARIANT (TREE_TYPE (decl)) == TREE_TYPE (decl)
 	  && !TYPE_ARTIFICIAL (TREE_TYPE (decl))