c++: improve template parameter level lowering

Message ID 20230420153437.2910374-1-ppalka@redhat.com
State New
Headers
Series c++: improve template parameter level lowering |

Commit Message

Patrick Palka April 20, 2023, 3:34 p.m. UTC
  1. Now that we no longer substitute the constraints of an auto, we can
   get rid of the infinite recursion loop breaker during level lowering
   of a constrained auto and we can also use the TEMPLATE_PARM_DESCENDANTS
   cache in this case.
2. Don't bother recursing when level lowering a cv-qualified type template
   parameter.
3. Use TEMPLATE_PARM_DESCENDANTS when level lowering a non-type template
   parameter too.

Bootstrapped and regtested on x86_64-pc-linux-gnu, does this look OK for
trunk?

gcc/cp/ChangeLog:

	* pt.cc (tsubst) <case TEMPLATE_TYPE_PARM>: Remove infinite
	recursion loop breaker in the level lowering case for
	constrained autos.  Use the TEMPLATE_PARM_DESCENDANTS cache in
	this case as well.
	<case TEMPLATE_PARM_INDEX>: Use the TEMPLATE_PARM_INDEX cache
	when level lowering a non-type template parameter.
---
 gcc/cp/pt.cc | 42 ++++++++++++++++++++----------------------
 1 file changed, 20 insertions(+), 22 deletions(-)
  

Comments

Patrick Palka April 20, 2023, 3:44 p.m. UTC | #1
On Thu, 20 Apr 2023, Patrick Palka wrote:

> 1. Now that we no longer substitute the constraints of an auto, we can
>    get rid of the infinite recursion loop breaker during level lowering
>    of a constrained auto and we can also use the TEMPLATE_PARM_DESCENDANTS
>    cache in this case.
> 2. Don't bother recursing when level lowering a cv-qualified type template
>    parameter.
> 3. Use TEMPLATE_PARM_DESCENDANTS when level lowering a non-type template
>    parameter too.
> 
> Bootstrapped and regtested on x86_64-pc-linux-gnu, does this look OK for
> trunk?
> 
> gcc/cp/ChangeLog:
> 
> 	* pt.cc (tsubst) <case TEMPLATE_TYPE_PARM>: Remove infinite
> 	recursion loop breaker in the level lowering case for
> 	constrained autos.  Use the TEMPLATE_PARM_DESCENDANTS cache in
> 	this case as well.
> 	<case TEMPLATE_PARM_INDEX>: Use the TEMPLATE_PARM_INDEX cache
> 	when level lowering a non-type template parameter.
> ---
>  gcc/cp/pt.cc | 42 ++++++++++++++++++++----------------------
>  1 file changed, 20 insertions(+), 22 deletions(-)
> 
> diff --git a/gcc/cp/pt.cc b/gcc/cp/pt.cc
> index f65f2d58b28..07e9736cdce 100644
> --- a/gcc/cp/pt.cc
> +++ b/gcc/cp/pt.cc
> @@ -16228,33 +16228,23 @@ tsubst (tree t, tree args, tsubst_flags_t complain, tree in_decl)
>  	/* If we get here, we must have been looking at a parm for a
>  	   more deeply nested template.  Make a new version of this
>  	   template parameter, but with a lower level.  */
> +	int quals;
>  	switch (code)
>  	  {
>  	  case TEMPLATE_TYPE_PARM:
>  	  case TEMPLATE_TEMPLATE_PARM:
> -	    if (cp_type_quals (t))
> +	    quals = cp_type_quals (t);
> +	    if (quals)
>  	      {
> -		r = tsubst (TYPE_MAIN_VARIANT (t), args, complain, in_decl);
> -		r = cp_build_qualified_type
> -		  (r, cp_type_quals (t),
> -		   complain | (code == TEMPLATE_TYPE_PARM
> -			       ? tf_ignore_bad_quals : 0));
> +		gcc_checking_assert (code == TEMPLATE_TYPE_PARM);
> +		t = TYPE_MAIN_VARIANT (t);
>  	      }
> -	    else if (TREE_CODE (t) == TEMPLATE_TYPE_PARM
> -		     && PLACEHOLDER_TYPE_CONSTRAINTS_INFO (t)
> -		     && (r = (TEMPLATE_PARM_DESCENDANTS
> -			      (TEMPLATE_TYPE_PARM_INDEX (t))))
> -		     && (r = TREE_TYPE (r))
> -		     && !PLACEHOLDER_TYPE_CONSTRAINTS_INFO (r))
> -	      /* Break infinite recursion when substituting the constraints
> -		 of a constrained placeholder.  */;
> -	    else if (TREE_CODE (t) == TEMPLATE_TYPE_PARM
> -		     && !PLACEHOLDER_TYPE_CONSTRAINTS_INFO (t)
> -		     && (arg = TEMPLATE_TYPE_PARM_INDEX (t),
> -			 r = TEMPLATE_PARM_DESCENDANTS (arg))
> -		     && (TEMPLATE_PARM_LEVEL (r)
> -			 == TEMPLATE_PARM_LEVEL (arg) - levels))
> -		/* Cache the simple case of lowering a type parameter.  */
> +	    if (TREE_CODE (t) == TEMPLATE_TYPE_PARM
> +		&& (arg = TEMPLATE_TYPE_PARM_INDEX (t),
> +		    r = TEMPLATE_PARM_DESCENDANTS (arg))
> +		&& (TEMPLATE_PARM_LEVEL (r)
> +		    == TEMPLATE_PARM_LEVEL (arg) - levels))
> +	      /* Cache the simple case of lowering a type parameter.  */
>  	      r = TREE_TYPE (r);
>  	    else
>  	      {
> @@ -16278,6 +16268,9 @@ tsubst (tree t, tree args, tsubst_flags_t complain, tree in_decl)
>  		else
>  		  TYPE_CANONICAL (r) = canonical_type_parameter (r);
>  	      }
> +	    if (quals)
> +	      r = cp_build_qualified_type (r, quals,
> +					   complain | tf_ignore_bad_quals);
>  	    break;
>  
>  	  case BOUND_TEMPLATE_TEMPLATE_PARM:
> @@ -16307,7 +16300,12 @@ tsubst (tree t, tree args, tsubst_flags_t complain, tree in_decl)
>  	    type = tsubst (type, args, complain, in_decl);
>  	    if (type == error_mark_node)
>  	      return error_mark_node;
> -	    r = reduce_template_parm_level (t, type, levels, args, complain);
> +	    if ((r = TEMPLATE_PARM_DESCENDANTS (t))
> +		&& (TEMPLATE_PARM_LEVEL (r) == TEMPLATE_PARM_LEVEL (t) - levels)
> +		&& TREE_TYPE (r) == type)
> +	      /* Cache the simple case of lowering a non-type parameter.  */;
> +	    else
> +	      r = reduce_template_parm_level (t, type, levels, args, complain);

D'oh, this hunk is totally redundant since reduce_template_parm_level
already checks TEMPLATE_PARM_DESCENDANTS, and so we've been caching
level-lowering of non-type template parameters this whole time.

Please consider this patch instead, which removes this hunk and
therefore only changes TEMPLATE_TYPE_PARM level lowering:

-- >8 --

Subject: [PATCH] c++: improve TEMPLATE_TYPE_PARM level lowering

1. Don't bother recursing when level lowering a cv-qualified type template
   parameter.
2. Get rid of the infinite recursion loop breaker during level lowering of
   a constrained auto and use the TEMPLATE_PARM_DESCENDANTS cache in this
   case too, now that we no longer substitute its constraints.

gcc/cp/ChangeLog:

	* pt.cc (tsubst) <case TEMPLATE_TYPE_PARM>: Don't recurse when
	level lowering a cv-qualified type template parameter.  Remove
	infinite recursion loop breaker in the level lowering case for
	constrained autos.  Use the TEMPLATE_PARM_DESCENDANTS cache in
	this case as well.
---
 gcc/cp/pt.cc | 35 ++++++++++++++---------------------
 1 file changed, 14 insertions(+), 21 deletions(-)

diff --git a/gcc/cp/pt.cc b/gcc/cp/pt.cc
index f65f2d58b28..ed038b9ca24 100644
--- a/gcc/cp/pt.cc
+++ b/gcc/cp/pt.cc
@@ -16228,33 +16228,23 @@ tsubst (tree t, tree args, tsubst_flags_t complain, tree in_decl)
 	/* If we get here, we must have been looking at a parm for a
 	   more deeply nested template.  Make a new version of this
 	   template parameter, but with a lower level.  */
+	int quals;
 	switch (code)
 	  {
 	  case TEMPLATE_TYPE_PARM:
 	  case TEMPLATE_TEMPLATE_PARM:
-	    if (cp_type_quals (t))
+	    quals = cp_type_quals (t);
+	    if (quals)
 	      {
-		r = tsubst (TYPE_MAIN_VARIANT (t), args, complain, in_decl);
-		r = cp_build_qualified_type
-		  (r, cp_type_quals (t),
-		   complain | (code == TEMPLATE_TYPE_PARM
-			       ? tf_ignore_bad_quals : 0));
+		gcc_checking_assert (code == TEMPLATE_TYPE_PARM);
+		t = TYPE_MAIN_VARIANT (t);
 	      }
-	    else if (TREE_CODE (t) == TEMPLATE_TYPE_PARM
-		     && PLACEHOLDER_TYPE_CONSTRAINTS_INFO (t)
-		     && (r = (TEMPLATE_PARM_DESCENDANTS
-			      (TEMPLATE_TYPE_PARM_INDEX (t))))
-		     && (r = TREE_TYPE (r))
-		     && !PLACEHOLDER_TYPE_CONSTRAINTS_INFO (r))
-	      /* Break infinite recursion when substituting the constraints
-		 of a constrained placeholder.  */;
-	    else if (TREE_CODE (t) == TEMPLATE_TYPE_PARM
-		     && !PLACEHOLDER_TYPE_CONSTRAINTS_INFO (t)
-		     && (arg = TEMPLATE_TYPE_PARM_INDEX (t),
-			 r = TEMPLATE_PARM_DESCENDANTS (arg))
-		     && (TEMPLATE_PARM_LEVEL (r)
-			 == TEMPLATE_PARM_LEVEL (arg) - levels))
-		/* Cache the simple case of lowering a type parameter.  */
+	    if (TREE_CODE (t) == TEMPLATE_TYPE_PARM
+		&& (arg = TEMPLATE_TYPE_PARM_INDEX (t),
+		    r = TEMPLATE_PARM_DESCENDANTS (arg))
+		&& (TEMPLATE_PARM_LEVEL (r)
+		    == TEMPLATE_PARM_LEVEL (arg) - levels))
+	      /* Cache the simple case of lowering a type parameter.  */
 	      r = TREE_TYPE (r);
 	    else
 	      {
@@ -16278,6 +16268,9 @@ tsubst (tree t, tree args, tsubst_flags_t complain, tree in_decl)
 		else
 		  TYPE_CANONICAL (r) = canonical_type_parameter (r);
 	      }
+	    if (quals)
+	      r = cp_build_qualified_type (r, quals,
+					   complain | tf_ignore_bad_quals);
 	    break;
 
 	  case BOUND_TEMPLATE_TEMPLATE_PARM:
  
Jason Merrill April 20, 2023, 5:07 p.m. UTC | #2
On 4/20/23 11:44, Patrick Palka wrote:
> On Thu, 20 Apr 2023, Patrick Palka wrote:
> 
>> 1. Now that we no longer substitute the constraints of an auto, we can
>>     get rid of the infinite recursion loop breaker during level lowering
>>     of a constrained auto and we can also use the TEMPLATE_PARM_DESCENDANTS
>>     cache in this case.
>> 2. Don't bother recursing when level lowering a cv-qualified type template
>>     parameter.
>> 3. Use TEMPLATE_PARM_DESCENDANTS when level lowering a non-type template
>>     parameter too.
>>
>> Bootstrapped and regtested on x86_64-pc-linux-gnu, does this look OK for
>> trunk?
>>
>> gcc/cp/ChangeLog:
>>
>> 	* pt.cc (tsubst) <case TEMPLATE_TYPE_PARM>: Remove infinite
>> 	recursion loop breaker in the level lowering case for
>> 	constrained autos.  Use the TEMPLATE_PARM_DESCENDANTS cache in
>> 	this case as well.
>> 	<case TEMPLATE_PARM_INDEX>: Use the TEMPLATE_PARM_INDEX cache
>> 	when level lowering a non-type template parameter.
>> ---
>>   gcc/cp/pt.cc | 42 ++++++++++++++++++++----------------------
>>   1 file changed, 20 insertions(+), 22 deletions(-)
>>
>> diff --git a/gcc/cp/pt.cc b/gcc/cp/pt.cc
>> index f65f2d58b28..07e9736cdce 100644
>> --- a/gcc/cp/pt.cc
>> +++ b/gcc/cp/pt.cc
>> @@ -16228,33 +16228,23 @@ tsubst (tree t, tree args, tsubst_flags_t complain, tree in_decl)
>>   	/* If we get here, we must have been looking at a parm for a
>>   	   more deeply nested template.  Make a new version of this
>>   	   template parameter, but with a lower level.  */
>> +	int quals;
>>   	switch (code)
>>   	  {
>>   	  case TEMPLATE_TYPE_PARM:
>>   	  case TEMPLATE_TEMPLATE_PARM:
>> -	    if (cp_type_quals (t))
>> +	    quals = cp_type_quals (t);
>> +	    if (quals)
>>   	      {
>> -		r = tsubst (TYPE_MAIN_VARIANT (t), args, complain, in_decl);
>> -		r = cp_build_qualified_type
>> -		  (r, cp_type_quals (t),
>> -		   complain | (code == TEMPLATE_TYPE_PARM
>> -			       ? tf_ignore_bad_quals : 0));
>> +		gcc_checking_assert (code == TEMPLATE_TYPE_PARM);
>> +		t = TYPE_MAIN_VARIANT (t);
>>   	      }
>> -	    else if (TREE_CODE (t) == TEMPLATE_TYPE_PARM
>> -		     && PLACEHOLDER_TYPE_CONSTRAINTS_INFO (t)
>> -		     && (r = (TEMPLATE_PARM_DESCENDANTS
>> -			      (TEMPLATE_TYPE_PARM_INDEX (t))))
>> -		     && (r = TREE_TYPE (r))
>> -		     && !PLACEHOLDER_TYPE_CONSTRAINTS_INFO (r))
>> -	      /* Break infinite recursion when substituting the constraints
>> -		 of a constrained placeholder.  */;
>> -	    else if (TREE_CODE (t) == TEMPLATE_TYPE_PARM
>> -		     && !PLACEHOLDER_TYPE_CONSTRAINTS_INFO (t)
>> -		     && (arg = TEMPLATE_TYPE_PARM_INDEX (t),
>> -			 r = TEMPLATE_PARM_DESCENDANTS (arg))
>> -		     && (TEMPLATE_PARM_LEVEL (r)
>> -			 == TEMPLATE_PARM_LEVEL (arg) - levels))
>> -		/* Cache the simple case of lowering a type parameter.  */
>> +	    if (TREE_CODE (t) == TEMPLATE_TYPE_PARM
>> +		&& (arg = TEMPLATE_TYPE_PARM_INDEX (t),
>> +		    r = TEMPLATE_PARM_DESCENDANTS (arg))
>> +		&& (TEMPLATE_PARM_LEVEL (r)
>> +		    == TEMPLATE_PARM_LEVEL (arg) - levels))
>> +	      /* Cache the simple case of lowering a type parameter.  */
>>   	      r = TREE_TYPE (r);
>>   	    else
>>   	      {
>> @@ -16278,6 +16268,9 @@ tsubst (tree t, tree args, tsubst_flags_t complain, tree in_decl)
>>   		else
>>   		  TYPE_CANONICAL (r) = canonical_type_parameter (r);
>>   	      }
>> +	    if (quals)
>> +	      r = cp_build_qualified_type (r, quals,
>> +					   complain | tf_ignore_bad_quals);
>>   	    break;
>>   
>>   	  case BOUND_TEMPLATE_TEMPLATE_PARM:
>> @@ -16307,7 +16300,12 @@ tsubst (tree t, tree args, tsubst_flags_t complain, tree in_decl)
>>   	    type = tsubst (type, args, complain, in_decl);
>>   	    if (type == error_mark_node)
>>   	      return error_mark_node;
>> -	    r = reduce_template_parm_level (t, type, levels, args, complain);
>> +	    if ((r = TEMPLATE_PARM_DESCENDANTS (t))
>> +		&& (TEMPLATE_PARM_LEVEL (r) == TEMPLATE_PARM_LEVEL (t) - levels)
>> +		&& TREE_TYPE (r) == type)
>> +	      /* Cache the simple case of lowering a non-type parameter.  */;
>> +	    else
>> +	      r = reduce_template_parm_level (t, type, levels, args, complain);
> 
> D'oh, this hunk is totally redundant since reduce_template_parm_level
> already checks TEMPLATE_PARM_DESCENDANTS, and so we've been caching
> level-lowering of non-type template parameters this whole time.
> 
> Please consider this patch instead, which removes this hunk and
> therefore only changes TEMPLATE_TYPE_PARM level lowering:

OK.

> -- >8 --
> 
> Subject: [PATCH] c++: improve TEMPLATE_TYPE_PARM level lowering
> 
> 1. Don't bother recursing when level lowering a cv-qualified type template
>     parameter.
> 2. Get rid of the infinite recursion loop breaker during level lowering of
>     a constrained auto and use the TEMPLATE_PARM_DESCENDANTS cache in this
>     case too, now that we no longer substitute its constraints.
> 
> gcc/cp/ChangeLog:
> 
> 	* pt.cc (tsubst) <case TEMPLATE_TYPE_PARM>: Don't recurse when
> 	level lowering a cv-qualified type template parameter.  Remove
> 	infinite recursion loop breaker in the level lowering case for
> 	constrained autos.  Use the TEMPLATE_PARM_DESCENDANTS cache in
> 	this case as well.
> ---
>   gcc/cp/pt.cc | 35 ++++++++++++++---------------------
>   1 file changed, 14 insertions(+), 21 deletions(-)
> 
> diff --git a/gcc/cp/pt.cc b/gcc/cp/pt.cc
> index f65f2d58b28..ed038b9ca24 100644
> --- a/gcc/cp/pt.cc
> +++ b/gcc/cp/pt.cc
> @@ -16228,33 +16228,23 @@ tsubst (tree t, tree args, tsubst_flags_t complain, tree in_decl)
>   	/* If we get here, we must have been looking at a parm for a
>   	   more deeply nested template.  Make a new version of this
>   	   template parameter, but with a lower level.  */
> +	int quals;
>   	switch (code)
>   	  {
>   	  case TEMPLATE_TYPE_PARM:
>   	  case TEMPLATE_TEMPLATE_PARM:
> -	    if (cp_type_quals (t))
> +	    quals = cp_type_quals (t);
> +	    if (quals)
>   	      {
> -		r = tsubst (TYPE_MAIN_VARIANT (t), args, complain, in_decl);
> -		r = cp_build_qualified_type
> -		  (r, cp_type_quals (t),
> -		   complain | (code == TEMPLATE_TYPE_PARM
> -			       ? tf_ignore_bad_quals : 0));
> +		gcc_checking_assert (code == TEMPLATE_TYPE_PARM);
> +		t = TYPE_MAIN_VARIANT (t);
>   	      }
> -	    else if (TREE_CODE (t) == TEMPLATE_TYPE_PARM
> -		     && PLACEHOLDER_TYPE_CONSTRAINTS_INFO (t)
> -		     && (r = (TEMPLATE_PARM_DESCENDANTS
> -			      (TEMPLATE_TYPE_PARM_INDEX (t))))
> -		     && (r = TREE_TYPE (r))
> -		     && !PLACEHOLDER_TYPE_CONSTRAINTS_INFO (r))
> -	      /* Break infinite recursion when substituting the constraints
> -		 of a constrained placeholder.  */;
> -	    else if (TREE_CODE (t) == TEMPLATE_TYPE_PARM
> -		     && !PLACEHOLDER_TYPE_CONSTRAINTS_INFO (t)
> -		     && (arg = TEMPLATE_TYPE_PARM_INDEX (t),
> -			 r = TEMPLATE_PARM_DESCENDANTS (arg))
> -		     && (TEMPLATE_PARM_LEVEL (r)
> -			 == TEMPLATE_PARM_LEVEL (arg) - levels))
> -		/* Cache the simple case of lowering a type parameter.  */
> +	    if (TREE_CODE (t) == TEMPLATE_TYPE_PARM
> +		&& (arg = TEMPLATE_TYPE_PARM_INDEX (t),
> +		    r = TEMPLATE_PARM_DESCENDANTS (arg))
> +		&& (TEMPLATE_PARM_LEVEL (r)
> +		    == TEMPLATE_PARM_LEVEL (arg) - levels))
> +	      /* Cache the simple case of lowering a type parameter.  */
>   	      r = TREE_TYPE (r);
>   	    else
>   	      {
> @@ -16278,6 +16268,9 @@ tsubst (tree t, tree args, tsubst_flags_t complain, tree in_decl)
>   		else
>   		  TYPE_CANONICAL (r) = canonical_type_parameter (r);
>   	      }
> +	    if (quals)
> +	      r = cp_build_qualified_type (r, quals,
> +					   complain | tf_ignore_bad_quals);
>   	    break;
>   
>   	  case BOUND_TEMPLATE_TEMPLATE_PARM:
  

Patch

diff --git a/gcc/cp/pt.cc b/gcc/cp/pt.cc
index f65f2d58b28..07e9736cdce 100644
--- a/gcc/cp/pt.cc
+++ b/gcc/cp/pt.cc
@@ -16228,33 +16228,23 @@  tsubst (tree t, tree args, tsubst_flags_t complain, tree in_decl)
 	/* If we get here, we must have been looking at a parm for a
 	   more deeply nested template.  Make a new version of this
 	   template parameter, but with a lower level.  */
+	int quals;
 	switch (code)
 	  {
 	  case TEMPLATE_TYPE_PARM:
 	  case TEMPLATE_TEMPLATE_PARM:
-	    if (cp_type_quals (t))
+	    quals = cp_type_quals (t);
+	    if (quals)
 	      {
-		r = tsubst (TYPE_MAIN_VARIANT (t), args, complain, in_decl);
-		r = cp_build_qualified_type
-		  (r, cp_type_quals (t),
-		   complain | (code == TEMPLATE_TYPE_PARM
-			       ? tf_ignore_bad_quals : 0));
+		gcc_checking_assert (code == TEMPLATE_TYPE_PARM);
+		t = TYPE_MAIN_VARIANT (t);
 	      }
-	    else if (TREE_CODE (t) == TEMPLATE_TYPE_PARM
-		     && PLACEHOLDER_TYPE_CONSTRAINTS_INFO (t)
-		     && (r = (TEMPLATE_PARM_DESCENDANTS
-			      (TEMPLATE_TYPE_PARM_INDEX (t))))
-		     && (r = TREE_TYPE (r))
-		     && !PLACEHOLDER_TYPE_CONSTRAINTS_INFO (r))
-	      /* Break infinite recursion when substituting the constraints
-		 of a constrained placeholder.  */;
-	    else if (TREE_CODE (t) == TEMPLATE_TYPE_PARM
-		     && !PLACEHOLDER_TYPE_CONSTRAINTS_INFO (t)
-		     && (arg = TEMPLATE_TYPE_PARM_INDEX (t),
-			 r = TEMPLATE_PARM_DESCENDANTS (arg))
-		     && (TEMPLATE_PARM_LEVEL (r)
-			 == TEMPLATE_PARM_LEVEL (arg) - levels))
-		/* Cache the simple case of lowering a type parameter.  */
+	    if (TREE_CODE (t) == TEMPLATE_TYPE_PARM
+		&& (arg = TEMPLATE_TYPE_PARM_INDEX (t),
+		    r = TEMPLATE_PARM_DESCENDANTS (arg))
+		&& (TEMPLATE_PARM_LEVEL (r)
+		    == TEMPLATE_PARM_LEVEL (arg) - levels))
+	      /* Cache the simple case of lowering a type parameter.  */
 	      r = TREE_TYPE (r);
 	    else
 	      {
@@ -16278,6 +16268,9 @@  tsubst (tree t, tree args, tsubst_flags_t complain, tree in_decl)
 		else
 		  TYPE_CANONICAL (r) = canonical_type_parameter (r);
 	      }
+	    if (quals)
+	      r = cp_build_qualified_type (r, quals,
+					   complain | tf_ignore_bad_quals);
 	    break;
 
 	  case BOUND_TEMPLATE_TEMPLATE_PARM:
@@ -16307,7 +16300,12 @@  tsubst (tree t, tree args, tsubst_flags_t complain, tree in_decl)
 	    type = tsubst (type, args, complain, in_decl);
 	    if (type == error_mark_node)
 	      return error_mark_node;
-	    r = reduce_template_parm_level (t, type, levels, args, complain);
+	    if ((r = TEMPLATE_PARM_DESCENDANTS (t))
+		&& (TEMPLATE_PARM_LEVEL (r) == TEMPLATE_PARM_LEVEL (t) - levels)
+		&& TREE_TYPE (r) == type)
+	      /* Cache the simple case of lowering a non-type parameter.  */;
+	    else
+	      r = reduce_template_parm_level (t, type, levels, args, complain);
 	    break;
 
 	  default: