builtins.c (fold_builtin_fpclassify): Change to take array of arguments instead of CALL_EXPR tree.

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): Use
	fold_build_call_array_loc.

From-SVN: r218311
This commit is contained in:
Richard Biener 2014-12-03 13:10:39 +00:00 committed by Richard Biener
parent a844a69583
commit a6a0570f15
7 changed files with 84 additions and 84 deletions

View File

@ -1,3 +1,22 @@
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.
2014-12-03 Alan Lawrence <alan.lawrence@arm.com>
* config/aarch64/aarch64-simd.md (aarch64_simd_dup<mode>, orn<mode>3,

View File

@ -196,7 +196,7 @@ static tree fold_builtin_1 (location_t, tree, tree, bool);
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);
@ -9692,7 +9692,7 @@ fold_builtin_classify (location_t loc, tree fndecl, tree arg, int builtin_index)
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;
@ -9701,17 +9701,21 @@ fold_builtin_fpclassify (location_t loc, tree exp)
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));
@ -10621,14 +10625,9 @@ fold_builtin_4 (location_t loc, tree fndecl,
}
/* 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)
@ -10654,6 +10653,7 @@ fold_builtin_n (location_t loc, tree fndecl, tree *args, int nargs, bool ignore)
ignore);
break;
default:
ret = fold_builtin_varargs (loc, fndecl, args, nargs, ignore);
break;
}
if (ret)
@ -10750,13 +10750,8 @@ fold_call_expr (location_t loc, tree exp, bool ignore)
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;
}
@ -10764,62 +10759,43 @@ fold_call_expr (location_t loc, tree exp, bool ignore)
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;
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);
}
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;
}
}
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
@ -11827,7 +11803,7 @@ fold_builtin_object_size (tree ptr, tree ost)
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);
@ -11836,7 +11812,7 @@ fold_builtin_varargs (location_t loc, tree fndecl, tree exp,
switch (fcode)
{
case BUILT_IN_FPCLASSIFY:
ret = fold_builtin_fpclassify (loc, exp);
ret = fold_builtin_fpclassify (loc, args, nargs);
break;
default:
@ -12747,8 +12723,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

View File

@ -1,3 +1,8 @@
2014-12-03 Richard Biener <rguenther@suse.de>
* constexpr.c (cxx_eval_builtin_function_call): Use
fold_build_call_array_loc.
2014-12-02 Marek Polacek <polacek@redhat.com>
* constexpr.c (cxx_eval_check_shift_p): New function.

View File

@ -1008,8 +1008,8 @@ cxx_eval_builtin_function_call (const constexpr_ctx *ctx, tree t,
}
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;
}

View File

@ -14405,6 +14405,8 @@ fold_build_call_array_loc (location_t loc, tree type, tree fn,
#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);

View File

@ -4744,14 +4744,13 @@ gimple_fold_stmt_to_constant_1 (gimple stmt, tree (*valueize) (tree),
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. */

View File

@ -10591,7 +10591,7 @@ build_call_expr_loc_array (location_t loc, tree fndecl, int n, tree *argarray)
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