This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: [PATCH] Avoid building CALL_EXPRs in gimple_fold_stmt_to_constant_1


On Wed, 3 Dec 2014, Richard Biener wrote:

> 
> This refactors fold_builtin_call_array to not build a CALL_EXPR if
> no simplification was possible (we have fold_build_call_array_loc
> for that).  This requires to fix the single case where that was
> deemed necessary (fold_builtin_varargs calling fold_builtin_fpclassify)
> which is easily fixed to simply work with the call argument array.
> 
> This also fixes missing fpclassify folding from fold_stmt which
> dispatches to fold_call_stmt which only calls fold_builtin_n.
> 
> Bootstrapped on x86_64-unknown-linux-gnu, testing in progress.
> 
> I'll consider the cp/ part as obvious and will commit this after
> testing succeeded.

Which that part didn't (the rest did).  I'll replace it with the
even more obvious

Index: gcc/cp/constexpr.c
===================================================================
--- gcc/cp/constexpr.c  (revision 218308)
+++ gcc/cp/constexpr.c  (working copy)
@@ -1008,8 +1008,8 @@ cxx_eval_builtin_function_call (const co
     }
   if (*non_constant_p)
     return t;
-  new_call = fold_builtin_call_array (EXPR_LOCATION (t), TREE_TYPE (t),
-                                     CALL_EXPR_FN (t), nargs, args);
+  new_call = fold_build_call_array_loc (EXPR_LOCATION (t), TREE_TYPE (t),
+                                       CALL_EXPR_FN (t), nargs, args);
   VERIFY_CONSTANT (new_call);
   return new_call;
 }

re-testing that.

Thanks,
Richard.

> Thanks,
> Richard.
> 
> 2014-12-03  Richard Biener  <rguenther@suse.de>
> 
> 	* builtins.c (fold_builtin_fpclassify): Change to take
> 	array of arguments instead of CALL_EXPR tree.
> 	(MAX_ARGS_TO_FOLD_BUILTIN): Remove.
> 	(fold_builtin_n): Dispatch to fold_builtin_varargs.
> 	(fold_call_expr): Always use fold_builtin_n.
> 	(fold_builtin_call_array): Change to not build the unfolded call,
> 	always use fold_builtin_n.
> 	(fold_builtin_varargs): Change to take array of arguments instead
> 	of CALL_EXPR tree.
> 	(fold_call_stmt): Always use fold_builtin_n.
> 	* tree.c (build_call_expr_loc_array): Use fold_build_call_array_loc.
> 	* fold-const.c (fold_build_call_array_loc): Build the call
> 	if fold_builtin_call_array returned NULL_TREE.
> 	* gimple-fold.c (gimple_fold_stmt_to_constant_1): Do not build
> 	a CALL_EXPR and use fold_builtin_call_array instead of
> 	fold_call_expr.
> 
> 	cp/
> 	* constexpr.c (cxx_eval_builtin_function_call): Deal with
> 	fold_builtin_call_array only returning non-NULL if it simplified
> 	something.
> 
> Index: gcc/builtins.c
> ===================================================================
> --- gcc/builtins.c	(revision 218271)
> +++ gcc/builtins.c	(working copy)
> @@ -196,7 +196,7 @@ static tree fold_builtin_1 (location_t,
>  static tree fold_builtin_2 (location_t, tree, tree, tree, bool);
>  static tree fold_builtin_3 (location_t, tree, tree, tree, tree, bool);
>  static tree fold_builtin_4 (location_t, tree, tree, tree, tree, tree, bool);
> -static tree fold_builtin_varargs (location_t, tree, tree, bool);
> +static tree fold_builtin_varargs (location_t, tree, tree*, int, bool);
>  
>  static tree fold_builtin_strpbrk (location_t, tree, tree, tree);
>  static tree fold_builtin_strstr (location_t, tree, tree, tree);
> @@ -9785,7 +9785,7 @@ fold_builtin_classify (location_t loc, t
>     one floating point argument which is "type generic".  */
>  
>  static tree
> -fold_builtin_fpclassify (location_t loc, tree exp)
> +fold_builtin_fpclassify (location_t loc, tree *args, int nargs)
>  {
>    tree fp_nan, fp_infinite, fp_normal, fp_subnormal, fp_zero,
>      arg, type, res, tmp;
> @@ -9794,17 +9794,21 @@ fold_builtin_fpclassify (location_t loc,
>    char buf[128];
>  
>    /* Verify the required arguments in the original call.  */
> -  if (!validate_arglist (exp, INTEGER_TYPE, INTEGER_TYPE,
> -			 INTEGER_TYPE, INTEGER_TYPE,
> -			 INTEGER_TYPE, REAL_TYPE, VOID_TYPE))
> +  if (nargs != 6
> +      || !validate_arg (args[0], INTEGER_TYPE)
> +      || !validate_arg (args[1], INTEGER_TYPE)
> +      || !validate_arg (args[2], INTEGER_TYPE)
> +      || !validate_arg (args[3], INTEGER_TYPE)
> +      || !validate_arg (args[4], INTEGER_TYPE)
> +      || !validate_arg (args[5], REAL_TYPE))
>      return NULL_TREE;
>  
> -  fp_nan = CALL_EXPR_ARG (exp, 0);
> -  fp_infinite = CALL_EXPR_ARG (exp, 1);
> -  fp_normal = CALL_EXPR_ARG (exp, 2);
> -  fp_subnormal = CALL_EXPR_ARG (exp, 3);
> -  fp_zero = CALL_EXPR_ARG (exp, 4);
> -  arg = CALL_EXPR_ARG (exp, 5);
> +  fp_nan = args[0];
> +  fp_infinite = args[1];
> +  fp_normal = args[2];
> +  fp_subnormal = args[3];
> +  fp_zero = args[4];
> +  arg = args[5];
>    type = TREE_TYPE (arg);
>    mode = TYPE_MODE (type);
>    arg = builtin_save_expr (fold_build1_loc (loc, ABS_EXPR, type, arg));
> @@ -10708,14 +10712,9 @@ fold_builtin_4 (location_t loc, tree fnd
>  }
>  
>  /* Fold a call to built-in function FNDECL.  ARGS is an array of NARGS
> -    arguments, where NARGS <= 4.  IGNORE is true if the result of the
> -    function call is ignored.  This function returns NULL_TREE if no
> -    simplification was possible.  Note that this only folds builtins with
> -    fixed argument patterns.  Foldings that do varargs-to-varargs
> -    transformations, or that match calls with more than 4 arguments,
> -    need to be handled with fold_builtin_varargs instead.  */
> -
> -#define MAX_ARGS_TO_FOLD_BUILTIN 4
> +   arguments.  IGNORE is true if the result of the
> +   function call is ignored.  This function returns NULL_TREE if no
> +   simplification was possible.  */
>  
>  tree
>  fold_builtin_n (location_t loc, tree fndecl, tree *args, int nargs, bool ignore)
> @@ -10741,6 +10740,7 @@ fold_builtin_n (location_t loc, tree fnd
>   			    ignore);
>        break;
>      default:
> +      ret = fold_builtin_varargs (loc, fndecl, args, nargs, ignore);
>        break;
>      }
>    if (ret)
> @@ -10837,13 +10837,8 @@ fold_call_expr (location_t loc, tree exp
>  				     CALL_EXPR_ARGP (exp), ignore);
>        else
>  	{
> -	  if (nargs <= MAX_ARGS_TO_FOLD_BUILTIN)
> -	    {
> -	      tree *args = CALL_EXPR_ARGP (exp);
> -	      ret = fold_builtin_n (loc, fndecl, args, nargs, ignore);
> -	    }
> -	  if (!ret)
> -	    ret = fold_builtin_varargs (loc, fndecl, exp, ignore);
> +	  tree *args = CALL_EXPR_ARGP (exp);
> +	  ret = fold_builtin_n (loc, fndecl, args, nargs, ignore);
>  	  if (ret)
>  	    return ret;
>  	}
> @@ -10851,62 +10846,43 @@ fold_call_expr (location_t loc, tree exp
>    return NULL_TREE;
>  }
>  
> -/* Construct a CALL_EXPR with type TYPE with FN as the function expression.
> -   N arguments are passed in the array ARGARRAY.  */
> +/* Fold a CALL_EXPR with type TYPE with FN as the function expression.
> +   N arguments are passed in the array ARGARRAY.  Return a folded
> +   expression or NULL_TREE if no simplification was possible.  */
>  
>  tree
> -fold_builtin_call_array (location_t loc, tree type,
> +fold_builtin_call_array (location_t loc, tree,
>  			 tree fn,
>  			 int n,
>  			 tree *argarray)
>  {
> -  tree ret = NULL_TREE;
> -   tree exp;
> +  if (TREE_CODE (fn) != ADDR_EXPR)
> +    return NULL_TREE;
>  
> -  if (TREE_CODE (fn) == ADDR_EXPR)
> -  {
> -    tree fndecl = TREE_OPERAND (fn, 0);
> -    if (TREE_CODE (fndecl) == FUNCTION_DECL
> -        && DECL_BUILT_IN (fndecl))
> -      {
> -	/* If last argument is __builtin_va_arg_pack (), arguments to this
> -	   function are not finalized yet.  Defer folding until they are.  */
> -	if (n && TREE_CODE (argarray[n - 1]) == CALL_EXPR)
> -	  {
> -	    tree fndecl2 = get_callee_fndecl (argarray[n - 1]);
> -	    if (fndecl2
> -		&& TREE_CODE (fndecl2) == FUNCTION_DECL
> -		&& DECL_BUILT_IN_CLASS (fndecl2) == BUILT_IN_NORMAL
> -		&& DECL_FUNCTION_CODE (fndecl2) == BUILT_IN_VA_ARG_PACK)
> -	      return build_call_array_loc (loc, type, fn, n, argarray);
> -	  }
> -	if (avoid_folding_inline_builtin (fndecl))
> -	  return build_call_array_loc (loc, type, fn, n, argarray);
> -        if (DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_MD)
> -          {
> -	    ret = targetm.fold_builtin (fndecl, n, argarray, false);
> -	    if (ret)
> -	      return ret;
> -
> -	    return build_call_array_loc (loc, type, fn, n, argarray);
> -          }
> -        else if (n <= MAX_ARGS_TO_FOLD_BUILTIN)
> -          {
> -            /* First try the transformations that don't require consing up
> -               an exp.  */
> -            ret = fold_builtin_n (loc, fndecl, argarray, n, false);
> -            if (ret)
> -              return ret;
> -          }
> -
> -        /* If we got this far, we need to build an exp.  */
> -        exp = build_call_array_loc (loc, type, fn, n, argarray);
> -        ret = fold_builtin_varargs (loc, fndecl, exp, false);
> -        return ret ? ret : exp;
> -      }
> -  }
> +  tree fndecl = TREE_OPERAND (fn, 0);
> +  if (TREE_CODE (fndecl) == FUNCTION_DECL
> +      && DECL_BUILT_IN (fndecl))
> +    {
> +      /* If last argument is __builtin_va_arg_pack (), arguments to this
> +	 function are not finalized yet.  Defer folding until they are.  */
> +      if (n && TREE_CODE (argarray[n - 1]) == CALL_EXPR)
> +	{
> +	  tree fndecl2 = get_callee_fndecl (argarray[n - 1]);
> +	  if (fndecl2
> +	      && TREE_CODE (fndecl2) == FUNCTION_DECL
> +	      && DECL_BUILT_IN_CLASS (fndecl2) == BUILT_IN_NORMAL
> +	      && DECL_FUNCTION_CODE (fndecl2) == BUILT_IN_VA_ARG_PACK)
> +	    return NULL_TREE;
> +	}
> +      if (avoid_folding_inline_builtin (fndecl))
> +	return NULL_TREE;
> +      if (DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_MD)
> +	return targetm.fold_builtin (fndecl, n, argarray, false);
> +      else
> +	return fold_builtin_n (loc, fndecl, argarray, n, false);
> +    }
>  
> -  return build_call_array_loc (loc, type, fn, n, argarray);
> +  return NULL_TREE;
>  }
>  
>  /* Construct a new CALL_EXPR using the tail of the argument list of EXP
> @@ -11914,7 +11890,7 @@ fold_builtin_object_size (tree ptr, tree
>     result of the function call is ignored.  */
>  
>  static tree
> -fold_builtin_varargs (location_t loc, tree fndecl, tree exp,
> +fold_builtin_varargs (location_t loc, tree fndecl, tree *args, int nargs,
>  		      bool ignore ATTRIBUTE_UNUSED)
>  {
>    enum built_in_function fcode = DECL_FUNCTION_CODE (fndecl);
> @@ -11923,7 +11899,7 @@ fold_builtin_varargs (location_t loc, tr
>    switch (fcode)
>      {
>      case BUILT_IN_FPCLASSIFY:
> -      ret = fold_builtin_fpclassify (loc, exp);
> +      ret = fold_builtin_fpclassify (loc, args, nargs);
>        break;
>  
>      default:
> @@ -12834,8 +12810,7 @@ fold_call_stmt (gcall *stmt, bool ignore
>          }
>        else
>  	{
> -	  if (nargs <= MAX_ARGS_TO_FOLD_BUILTIN)
> -	    ret = fold_builtin_n (loc, fndecl, args, nargs, ignore);
> +	  ret = fold_builtin_n (loc, fndecl, args, nargs, ignore);
>  	  if (ret)
>  	    {
>  	      /* Propagate location information from original call to
> Index: gcc/tree.c
> ===================================================================
> --- gcc/tree.c	(revision 218271)
> +++ gcc/tree.c	(working copy)
> @@ -10591,7 +10591,7 @@ build_call_expr_loc_array (location_t lo
>    tree fntype = TREE_TYPE (fndecl);
>    tree fn = build1 (ADDR_EXPR, build_pointer_type (fntype), fndecl);
>   
> -  return fold_builtin_call_array (loc, TREE_TYPE (fntype), fn, n, argarray);
> +  return fold_build_call_array_loc (loc, TREE_TYPE (fntype), fn, n, argarray);
>  }
>  
>  /* Conveniently construct a function call expression.  FNDECL names the
> Index: gcc/fold-const.c
> ===================================================================
> --- gcc/fold-const.c	(revision 218271)
> +++ gcc/fold-const.c	(working copy)
> @@ -14405,6 +14422,8 @@ fold_build_call_array_loc (location_t lo
>  #endif
>  
>    tem = fold_builtin_call_array (loc, type, fn, nargs, argarray);
> +  if (!tem)
> +    tem = build_call_array_loc (loc, type, fn, nargs, argarray);
>  
>  #ifdef ENABLE_FOLD_CHECKING
>    md5_init_ctx (&ctx);
> Index: gcc/gimple-fold.c
> ===================================================================
> --- gcc/gimple-fold.c	(revision 218271)
> +++ gcc/gimple-fold.c	(working copy)
> @@ -4744,14 +4744,13 @@ gimple_fold_stmt_to_constant_1 (gimple s
>  						       TREE_OPERAND (fn, 0)))
>  	  {
>  	    tree *args = XALLOCAVEC (tree, gimple_call_num_args (stmt));
> -	    tree call, retval;
> +	    tree retval;
>  	    unsigned i;
>  	    for (i = 0; i < gimple_call_num_args (stmt); ++i)
>  	      args[i] = (*valueize) (gimple_call_arg (stmt, i));
> -	    call = build_call_array_loc (loc,
> +	    retval = fold_builtin_call_array (loc,
>  					 gimple_call_return_type (call_stmt),
>  					 fn, gimple_call_num_args (stmt), args);
> -	    retval = fold_call_expr (EXPR_LOCATION (call), call, false);
>  	    if (retval)
>  	      {
>  		/* fold_call_expr wraps the result inside a NOP_EXPR.  */
> Index: gcc/cp/constexpr.c
> ===================================================================
> --- gcc/cp/constexpr.c	(revision 218271)
> +++ gcc/cp/constexpr.c	(working copy)
> @@ -1010,8 +1010,9 @@ cxx_eval_builtin_function_call (const co
>      return t;
>    new_call = fold_builtin_call_array (EXPR_LOCATION (t), TREE_TYPE (t),
>  				      CALL_EXPR_FN (t), nargs, args);
> -  VERIFY_CONSTANT (new_call);
> -  return new_call;
> +  if (new_call)
> +    VERIFY_CONSTANT (new_call);
> +  return t;
>  }
>  
>  /* TEMP is the constant value of a temporary object of type TYPE.  Adjust
> 

-- 
Richard Biener <rguenther@suse.de>
SUSE LINUX GmbH, GF: Jeff Hawn, Jennifer Guild, Felix Imendoerffer, HRB 21284
(AG Nuernberg)
Maxfeldstrasse 5, 90409 Nuernberg, Germany


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]