diff mbox

C++ PATCH for c++/64359 (alias_template_specialization_p high in profile)

Message ID 549653BD.9020501@redhat.com
State New
Headers show

Commit Message

Jason Merrill Dec. 21, 2014, 4:59 a.m. UTC
Markus pointed out that my patch for DR 1558 slowed down the compiler 
significantly for building Chrome: comparing entries in the template 
specialization hash table had to spend a lot of time figuring out if 
types were specializations of alias templates with dependent template 
arguments in order to avoid comparing them by TYPE_CANONICAL.

This patch addresses this in multiple ways:

1) Instead of looking deep into the type to see if it's a dependent 
alias, we just check for it being any kind of alias; strip_typedefs 
strips any aliases in non-dependent template argument lists, so we're 
safe just treating any aliases that make it to template_args_equal as 
different.

2) I optimized alias_template_specialization_p a bit to check for the 
alias bit before looking up the template info.  This is less interesting 
given #1, but I did it first and figured we might as well keep it.

3) I adjusted iterative_hash_template_arg to hash aliases differently to 
reduce the number of collisions that result in calls to template_args_equal.

And while I was in the area, I also fixed dependent_alias_spec_p to only 
look at the innermost template arguments.

alias_template_specialization_p is now down to 0.34% of perf time on the 
testcase.  template_args_equal is still at the top, but with a much 
smaller lead than before.

Tested x86_64-pc-linux-gnu, applying to trunk.
diff mbox

Patch

commit 99d81c4c903fb91fd017edbedfc4b4998934fc54
Author: Jason Merrill <jason@redhat.com>
Date:   Fri Dec 19 12:11:01 2014 -0500

    	PR c++/64359
    	* pt.c (iterative_hash_template_arg): Hash alias specializations
    	differently from their TYPE_CANONICAL.
    	(alias_template_specialization_p): Optimize.
    	(template_args_equal): Optimize alias handling.
    	(dependent_alias_template_spec_p): Only check innermost args.

diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index 15d304a..f5bd842 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -1674,6 +1674,18 @@  iterative_hash_template_arg (tree arg, hashval_t val)
   switch (tclass)
     {
     case tcc_type:
+      if (alias_template_specialization_p (arg))
+	{
+	  // We want an alias specialization that survived strip_typedefs
+	  // to hash differently from its TYPE_CANONICAL, to avoid hash
+	  // collisions that compare as different in template_args_equal.
+	  // These could be dependent specializations that strip_typedefs
+	  // left alone, or untouched specializations because
+	  // coerce_template_parms returns the unconverted template
+	  // arguments if it sees incomplete argument packs.
+	  tree ti = TYPE_TEMPLATE_INFO (arg);
+	  return hash_tmpl_and_args (TI_TEMPLATE (ti), TI_ARGS (ti));
+	}
       if (TYPE_CANONICAL (arg))
 	return iterative_hash_object (TYPE_HASH (TYPE_CANONICAL (arg)),
 				      val);
@@ -5314,13 +5326,19 @@  alias_type_or_template_p (tree t)
 bool
 alias_template_specialization_p (const_tree t)
 {
-  if (t == NULL_TREE)
-    return false;
-  
-  return (TYPE_P (t)
-	  && TYPE_TEMPLATE_INFO (t)
-	  && PRIMARY_TEMPLATE_P (TYPE_TI_TEMPLATE (t))
-	  && DECL_ALIAS_TEMPLATE_P (TYPE_TI_TEMPLATE (t)));
+  /* It's an alias template specialization if it's an alias and its
+     TYPE_NAME is a specialization of a primary template.  */
+  if (TYPE_ALIAS_P (t))
+    {
+      tree name = TYPE_NAME (t);
+      if (DECL_LANG_SPECIFIC (name))
+	if (tree ti = DECL_TEMPLATE_INFO (name))
+	  {
+	    tree tmpl = TI_TEMPLATE (ti);
+	    return PRIMARY_TEMPLATE_P (tmpl);
+	  }
+    }
+  return false;
 }
 
 /* Return TRUE iff T is a specialization of an alias template with
@@ -5330,7 +5348,8 @@  bool
 dependent_alias_template_spec_p (const_tree t)
 {
   return (alias_template_specialization_p (t)
-	  && any_dependent_template_arguments_p (TYPE_TI_ARGS (t)));
+	  && (any_dependent_template_arguments_p
+	      (INNERMOST_TEMPLATE_ARGS (TYPE_TI_ARGS (t)))));
 }
 
 /* Return the number of innermost template parameters in TMPL.  */
@@ -7283,16 +7302,12 @@  template_args_equal (tree ot, tree nt)
 	return false;
       /* Don't treat an alias template specialization with dependent
 	 arguments as equivalent to its underlying type when used as a
-	 template argument; we need them to hash differently.  */
-      bool ndep = dependent_alias_template_spec_p (nt);
-      ++processing_template_decl;
-      bool odep = dependent_alias_template_spec_p (ot);
-      --processing_template_decl;
-      if (ndep != odep)
+	 template argument; we need them to be distinct so that we
+	 substitute into the specialization arguments at instantiation
+	 time.  And aliases can't be equivalent without being ==, so
+	 we don't need to look any deeper.  */
+      if (TYPE_ALIAS_P (nt) || TYPE_ALIAS_P (ot))
 	return false;
-      else if (ndep)
-	return (TYPE_TI_TEMPLATE (nt) == TYPE_TI_TEMPLATE (ot)
-		&& template_args_equal (TYPE_TI_ARGS (nt), TYPE_TI_ARGS (ot)));
       else
 	return same_type_p (ot, nt);
     }