aboutsummaryrefslogtreecommitdiff
path: root/gcc/fold-const.c
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/fold-const.c')
-rw-r--r--gcc/fold-const.c348
1 files changed, 194 insertions, 154 deletions
diff --git a/gcc/fold-const.c b/gcc/fold-const.c
index 7d66736..0aca93c 100644
--- a/gcc/fold-const.c
+++ b/gcc/fold-const.c
@@ -1195,7 +1195,7 @@ negate_expr_p (tree t)
case CALL_EXPR:
/* Negate -f(x) as f(-x). */
if (negate_mathfn_p (builtin_mathfn_code (t)))
- return negate_expr_p (TREE_VALUE (TREE_OPERAND (t, 1)));
+ return negate_expr_p (CALL_EXPR_ARG (t, 0));
break;
case RSHIFT_EXPR:
@@ -1382,14 +1382,13 @@ fold_negate_expr (tree t)
case CALL_EXPR:
/* Negate -f(x) as f(-x). */
if (negate_mathfn_p (builtin_mathfn_code (t))
- && negate_expr_p (TREE_VALUE (TREE_OPERAND (t, 1))))
+ && negate_expr_p (CALL_EXPR_ARG (t, 0)))
{
- tree fndecl, arg, arglist;
+ tree fndecl, arg;
fndecl = get_callee_fndecl (t);
- arg = negate_expr (TREE_VALUE (TREE_OPERAND (t, 1)));
- arglist = build_tree_list (NULL_TREE, arg);
- return build_function_call_expr (fndecl, arglist);
+ arg = negate_expr (CALL_EXPR_ARG (t, 0));
+ return build_call_expr (fndecl, 1, arg);
}
break;
@@ -2929,10 +2928,18 @@ operand_equal_p (tree arg0, tree arg1, unsigned int flags)
&& operand_equal_p (TREE_OPERAND (arg0, 1),
TREE_OPERAND (arg1, 0), flags));
+ default:
+ return 0;
+ }
+
+ case tcc_vl_exp:
+ switch (TREE_CODE (arg0))
+ {
case CALL_EXPR:
/* If the CALL_EXPRs call different functions, then they
clearly can not be equal. */
- if (!OP_SAME (0))
+ if (! operand_equal_p (CALL_EXPR_FN (arg0), CALL_EXPR_FN (arg1),
+ flags))
return 0;
{
@@ -2945,25 +2952,22 @@ operand_equal_p (tree arg0, tree arg1, unsigned int flags)
return 0;
}
- /* Now see if all the arguments are the same. operand_equal_p
- does not handle TREE_LIST, so we walk the operands here
- feeding them to operand_equal_p. */
- arg0 = TREE_OPERAND (arg0, 1);
- arg1 = TREE_OPERAND (arg1, 1);
- while (arg0 && arg1)
- {
- if (! operand_equal_p (TREE_VALUE (arg0), TREE_VALUE (arg1),
- flags))
+ /* Now see if all the arguments are the same. */
+ {
+ call_expr_arg_iterator iter0, iter1;
+ tree a0, a1;
+ for (a0 = first_call_expr_arg (arg0, &iter0),
+ a1 = first_call_expr_arg (arg1, &iter1);
+ a0 && a1;
+ a0 = next_call_expr_arg (&iter0),
+ a1 = next_call_expr_arg (&iter1))
+ if (! operand_equal_p (a0, a1, flags))
return 0;
- arg0 = TREE_CHAIN (arg0);
- arg1 = TREE_CHAIN (arg1);
- }
-
- /* If we get here and both argument lists are exhausted
- then the CALL_EXPRs are equal. */
- return ! (arg0 || arg1);
-
+ /* If we get here and both argument lists are exhausted
+ then the CALL_EXPRs are equal. */
+ return ! (a0 || a1);
+ }
default:
return 0;
}
@@ -4035,7 +4039,7 @@ make_range (tree exp, int *pin_p, tree *plow, tree *phigh,
if (IS_EXPR_CODE_CLASS (TREE_CODE_CLASS (code)))
{
- if (TREE_CODE_LENGTH (code) > 0)
+ if (TREE_OPERAND_LENGTH (exp) > 0)
arg0 = TREE_OPERAND (exp, 0);
if (TREE_CODE_CLASS (code) == tcc_comparison
|| TREE_CODE_CLASS (code) == tcc_unary
@@ -4044,7 +4048,7 @@ make_range (tree exp, int *pin_p, tree *plow, tree *phigh,
if (TREE_CODE_CLASS (code) == tcc_binary
|| TREE_CODE_CLASS (code) == tcc_comparison
|| (TREE_CODE_CLASS (code) == tcc_expression
- && TREE_CODE_LENGTH (code) > 1))
+ && TREE_OPERAND_LENGTH (exp) > 1))
arg1 = TREE_OPERAND (exp, 1);
}
@@ -5677,6 +5681,7 @@ extract_muldiv_1 (tree t, tree c, enum tree_code code, tree wide_type,
if ((COMPARISON_CLASS_P (op0)
|| UNARY_CLASS_P (op0)
|| BINARY_CLASS_P (op0)
+ || VL_EXP_CLASS_P (op0)
|| EXPRESSION_CLASS_P (op0))
/* ... and is unsigned, and its type is smaller than ctype,
then we cannot pass through as widening. */
@@ -6151,7 +6156,7 @@ fold_mathfn_compare (enum built_in_function fcode, enum tree_code code,
if (BUILTIN_SQRT_P (fcode))
{
- tree arg = TREE_VALUE (TREE_OPERAND (arg0, 1));
+ tree arg = CALL_EXPR_ARG (arg0, 0);
enum machine_mode mode = TYPE_MODE (TREE_TYPE (arg0));
c = TREE_REAL_CST (arg1);
@@ -7970,8 +7975,7 @@ fold_unary (enum tree_code code, tree type, tree op0)
CASE_FLT_FN (BUILT_IN_CEXPI):
fn = mathfn_built_in (type, BUILT_IN_COS);
if (fn)
- return build_function_call_expr (fn,
- TREE_OPERAND (arg0, 1));
+ return build_call_expr (fn, 1, CALL_EXPR_ARG (arg0, 0));
break;
default:
@@ -8013,8 +8017,7 @@ fold_unary (enum tree_code code, tree type, tree op0)
CASE_FLT_FN (BUILT_IN_CEXPI):
fn = mathfn_built_in (type, BUILT_IN_SIN);
if (fn)
- return build_function_call_expr (fn,
- TREE_OPERAND (arg0, 1));
+ return build_call_expr (fn, 1, CALL_EXPR_ARG (arg0, 0));
break;
default:
@@ -9807,9 +9810,9 @@ fold_binary (enum tree_code code, tree type, tree op0, tree op1)
/* Optimizations of root(...)*root(...). */
if (fcode0 == fcode1 && BUILTIN_ROOT_P (fcode0))
{
- tree rootfn, arg, arglist;
- tree arg00 = TREE_VALUE (TREE_OPERAND (arg0, 1));
- tree arg10 = TREE_VALUE (TREE_OPERAND (arg1, 1));
+ tree rootfn, arg;
+ tree arg00 = CALL_EXPR_ARG (arg0, 0);
+ tree arg10 = CALL_EXPR_ARG (arg1, 0);
/* Optimize sqrt(x)*sqrt(x) as x. */
if (BUILTIN_SQRT_P (fcode0)
@@ -9818,21 +9821,19 @@ fold_binary (enum tree_code code, tree type, tree op0, tree op1)
return arg00;
/* Optimize root(x)*root(y) as root(x*y). */
- rootfn = TREE_OPERAND (TREE_OPERAND (arg0, 0), 0);
+ rootfn = TREE_OPERAND (CALL_EXPR_FN (arg0), 0);
arg = fold_build2 (MULT_EXPR, type, arg00, arg10);
- arglist = build_tree_list (NULL_TREE, arg);
- return build_function_call_expr (rootfn, arglist);
+ return build_call_expr (rootfn, 1, arg);
}
/* Optimize expN(x)*expN(y) as expN(x+y). */
if (fcode0 == fcode1 && BUILTIN_EXPONENT_P (fcode0))
{
- tree expfn = TREE_OPERAND (TREE_OPERAND (arg0, 0), 0);
+ tree expfn = TREE_OPERAND (CALL_EXPR_FN (arg0), 0);
tree arg = fold_build2 (PLUS_EXPR, type,
- TREE_VALUE (TREE_OPERAND (arg0, 1)),
- TREE_VALUE (TREE_OPERAND (arg1, 1)));
- tree arglist = build_tree_list (NULL_TREE, arg);
- return build_function_call_expr (expfn, arglist);
+ CALL_EXPR_ARG (arg0, 0),
+ CALL_EXPR_ARG (arg1, 0));
+ return build_call_expr (expfn, 1, arg);
}
/* Optimizations of pow(...)*pow(...). */
@@ -9840,33 +9841,25 @@ fold_binary (enum tree_code code, tree type, tree op0, tree op1)
|| (fcode0 == BUILT_IN_POWF && fcode1 == BUILT_IN_POWF)
|| (fcode0 == BUILT_IN_POWL && fcode1 == BUILT_IN_POWL))
{
- tree arg00 = TREE_VALUE (TREE_OPERAND (arg0, 1));
- tree arg01 = TREE_VALUE (TREE_CHAIN (TREE_OPERAND (arg0,
- 1)));
- tree arg10 = TREE_VALUE (TREE_OPERAND (arg1, 1));
- tree arg11 = TREE_VALUE (TREE_CHAIN (TREE_OPERAND (arg1,
- 1)));
+ tree arg00 = CALL_EXPR_ARG (arg0, 0);
+ tree arg01 = CALL_EXPR_ARG (arg0, 1);
+ tree arg10 = CALL_EXPR_ARG (arg1, 0);
+ tree arg11 = CALL_EXPR_ARG (arg1, 1);
/* Optimize pow(x,y)*pow(z,y) as pow(x*z,y). */
if (operand_equal_p (arg01, arg11, 0))
{
- tree powfn = TREE_OPERAND (TREE_OPERAND (arg0, 0), 0);
+ tree powfn = TREE_OPERAND (CALL_EXPR_FN (arg0), 0);
tree arg = fold_build2 (MULT_EXPR, type, arg00, arg10);
- tree arglist = tree_cons (NULL_TREE, arg,
- build_tree_list (NULL_TREE,
- arg01));
- return build_function_call_expr (powfn, arglist);
+ return build_call_expr (powfn, 2, arg, arg01);
}
/* Optimize pow(x,y)*pow(x,z) as pow(x,y+z). */
if (operand_equal_p (arg00, arg10, 0))
{
- tree powfn = TREE_OPERAND (TREE_OPERAND (arg0, 0), 0);
+ tree powfn = TREE_OPERAND (CALL_EXPR_FN (arg0), 0);
tree arg = fold_build2 (PLUS_EXPR, type, arg01, arg11);
- tree arglist = tree_cons (NULL_TREE, arg00,
- build_tree_list (NULL_TREE,
- arg));
- return build_function_call_expr (powfn, arglist);
+ return build_call_expr (powfn, 2, arg00, arg);
}
}
@@ -9877,14 +9870,13 @@ fold_binary (enum tree_code code, tree type, tree op0, tree op1)
|| (fcode0 == BUILT_IN_COS && fcode1 == BUILT_IN_TAN)
|| (fcode0 == BUILT_IN_COSF && fcode1 == BUILT_IN_TANF)
|| (fcode0 == BUILT_IN_COSL && fcode1 == BUILT_IN_TANL))
- && operand_equal_p (TREE_VALUE (TREE_OPERAND (arg0, 1)),
- TREE_VALUE (TREE_OPERAND (arg1, 1)), 0))
+ && operand_equal_p (CALL_EXPR_ARG (arg0, 0),
+ CALL_EXPR_ARG (arg1, 0), 0))
{
tree sinfn = mathfn_built_in (type, BUILT_IN_SIN);
if (sinfn != NULL_TREE)
- return build_function_call_expr (sinfn,
- TREE_OPERAND (arg0, 1));
+ return build_call_expr (sinfn, 1, CALL_EXPR_ARG (arg0, 0));
}
/* Optimize x*pow(x,c) as pow(x,c+1). */
@@ -9892,23 +9884,20 @@ fold_binary (enum tree_code code, tree type, tree op0, tree op1)
|| fcode1 == BUILT_IN_POWF
|| fcode1 == BUILT_IN_POWL)
{
- tree arg10 = TREE_VALUE (TREE_OPERAND (arg1, 1));
- tree arg11 = TREE_VALUE (TREE_CHAIN (TREE_OPERAND (arg1,
- 1)));
+ tree arg10 = CALL_EXPR_ARG (arg1, 0);
+ tree arg11 = CALL_EXPR_ARG (arg1, 1);
if (TREE_CODE (arg11) == REAL_CST
&& !TREE_OVERFLOW (arg11)
&& operand_equal_p (arg0, arg10, 0))
{
- tree powfn = TREE_OPERAND (TREE_OPERAND (arg1, 0), 0);
+ tree powfn = TREE_OPERAND (CALL_EXPR_FN (arg1), 0);
REAL_VALUE_TYPE c;
- tree arg, arglist;
+ tree arg;
c = TREE_REAL_CST (arg11);
real_arithmetic (&c, PLUS_EXPR, &c, &dconst1);
arg = build_real (type, c);
- arglist = build_tree_list (NULL_TREE, arg);
- arglist = tree_cons (NULL_TREE, arg0, arglist);
- return build_function_call_expr (powfn, arglist);
+ return build_call_expr (powfn, 2, arg0, arg);
}
}
@@ -9917,23 +9906,20 @@ fold_binary (enum tree_code code, tree type, tree op0, tree op1)
|| fcode0 == BUILT_IN_POWF
|| fcode0 == BUILT_IN_POWL)
{
- tree arg00 = TREE_VALUE (TREE_OPERAND (arg0, 1));
- tree arg01 = TREE_VALUE (TREE_CHAIN (TREE_OPERAND (arg0,
- 1)));
+ tree arg00 = CALL_EXPR_ARG (arg0, 0);
+ tree arg01 = CALL_EXPR_ARG (arg0, 1);
if (TREE_CODE (arg01) == REAL_CST
&& !TREE_OVERFLOW (arg01)
&& operand_equal_p (arg1, arg00, 0))
{
- tree powfn = TREE_OPERAND (TREE_OPERAND (arg0, 0), 0);
+ tree powfn = TREE_OPERAND (CALL_EXPR_FN (arg0), 0);
REAL_VALUE_TYPE c;
- tree arg, arglist;
+ tree arg;
c = TREE_REAL_CST (arg01);
real_arithmetic (&c, PLUS_EXPR, &c, &dconst1);
arg = build_real (type, c);
- arglist = build_tree_list (NULL_TREE, arg);
- arglist = tree_cons (NULL_TREE, arg1, arglist);
- return build_function_call_expr (powfn, arglist);
+ return build_call_expr (powfn, 2, arg1, arg);
}
}
@@ -9946,9 +9932,7 @@ fold_binary (enum tree_code code, tree type, tree op0, tree op1)
if (powfn)
{
tree arg = build_real (type, dconst2);
- tree arglist = build_tree_list (NULL_TREE, arg);
- arglist = tree_cons (NULL_TREE, arg0, arglist);
- return build_function_call_expr (powfn, arglist);
+ return build_call_expr (powfn, 2, arg0, arg);
}
}
}
@@ -10480,29 +10464,27 @@ fold_binary (enum tree_code code, tree type, tree op0, tree op1)
if (((fcode0 == BUILT_IN_SIN && fcode1 == BUILT_IN_COS)
|| (fcode0 == BUILT_IN_SINF && fcode1 == BUILT_IN_COSF)
|| (fcode0 == BUILT_IN_SINL && fcode1 == BUILT_IN_COSL))
- && operand_equal_p (TREE_VALUE (TREE_OPERAND (arg0, 1)),
- TREE_VALUE (TREE_OPERAND (arg1, 1)), 0))
+ && operand_equal_p (CALL_EXPR_ARG (arg0, 0),
+ CALL_EXPR_ARG (arg1, 0), 0))
{
tree tanfn = mathfn_built_in (type, BUILT_IN_TAN);
if (tanfn != NULL_TREE)
- return build_function_call_expr (tanfn,
- TREE_OPERAND (arg0, 1));
+ return build_call_expr (tanfn, 1, CALL_EXPR_ARG (arg0, 0));
}
/* Optimize cos(x)/sin(x) as 1.0/tan(x). */
if (((fcode0 == BUILT_IN_COS && fcode1 == BUILT_IN_SIN)
|| (fcode0 == BUILT_IN_COSF && fcode1 == BUILT_IN_SINF)
|| (fcode0 == BUILT_IN_COSL && fcode1 == BUILT_IN_SINL))
- && operand_equal_p (TREE_VALUE (TREE_OPERAND (arg0, 1)),
- TREE_VALUE (TREE_OPERAND (arg1, 1)), 0))
+ && operand_equal_p (CALL_EXPR_ARG (arg0, 0),
+ CALL_EXPR_ARG (arg1, 0), 0))
{
tree tanfn = mathfn_built_in (type, BUILT_IN_TAN);
if (tanfn != NULL_TREE)
{
- tree tmp = TREE_OPERAND (arg0, 1);
- tmp = build_function_call_expr (tanfn, tmp);
+ tree tmp = build_call_expr (tanfn, 1, CALL_EXPR_ARG (arg0, 0));
return fold_build2 (RDIV_EXPR, type,
build_real (type, dconst1), tmp);
}
@@ -10514,8 +10496,8 @@ fold_binary (enum tree_code code, tree type, tree op0, tree op1)
|| (fcode0 == BUILT_IN_SINF && fcode1 == BUILT_IN_TANF)
|| (fcode0 == BUILT_IN_SINL && fcode1 == BUILT_IN_TANL)))
{
- tree arg00 = TREE_VALUE (TREE_OPERAND (arg0, 1));
- tree arg01 = TREE_VALUE (TREE_OPERAND (arg1, 1));
+ tree arg00 = CALL_EXPR_ARG (arg0, 0);
+ tree arg01 = CALL_EXPR_ARG (arg1, 0);
if (! HONOR_NANS (TYPE_MODE (TREE_TYPE (arg00)))
&& ! HONOR_INFINITIES (TYPE_MODE (TREE_TYPE (arg00)))
@@ -10524,8 +10506,7 @@ fold_binary (enum tree_code code, tree type, tree op0, tree op1)
tree cosfn = mathfn_built_in (type, BUILT_IN_COS);
if (cosfn != NULL_TREE)
- return build_function_call_expr (cosfn,
- TREE_OPERAND (arg0, 1));
+ return build_call_expr (cosfn, 1, arg00);
}
}
@@ -10535,8 +10516,8 @@ fold_binary (enum tree_code code, tree type, tree op0, tree op1)
|| (fcode0 == BUILT_IN_TANF && fcode1 == BUILT_IN_SINF)
|| (fcode0 == BUILT_IN_TANL && fcode1 == BUILT_IN_SINL)))
{
- tree arg00 = TREE_VALUE (TREE_OPERAND (arg0, 1));
- tree arg01 = TREE_VALUE (TREE_OPERAND (arg1, 1));
+ tree arg00 = CALL_EXPR_ARG (arg0, 0);
+ tree arg01 = CALL_EXPR_ARG (arg1, 0);
if (! HONOR_NANS (TYPE_MODE (TREE_TYPE (arg00)))
&& ! HONOR_INFINITIES (TYPE_MODE (TREE_TYPE (arg00)))
@@ -10546,8 +10527,7 @@ fold_binary (enum tree_code code, tree type, tree op0, tree op1)
if (cosfn != NULL_TREE)
{
- tree tmp = TREE_OPERAND (arg0, 1);
- tmp = build_function_call_expr (cosfn, tmp);
+ tree tmp = build_call_expr (cosfn, 1, arg00);
return fold_build2 (RDIV_EXPR, type,
build_real (type, dconst1),
tmp);
@@ -10560,33 +10540,29 @@ fold_binary (enum tree_code code, tree type, tree op0, tree op1)
|| fcode0 == BUILT_IN_POWF
|| fcode0 == BUILT_IN_POWL)
{
- tree arg00 = TREE_VALUE (TREE_OPERAND (arg0, 1));
- tree arg01 = TREE_VALUE (TREE_CHAIN (TREE_OPERAND (arg0, 1)));
+ tree arg00 = CALL_EXPR_ARG (arg0, 0);
+ tree arg01 = CALL_EXPR_ARG (arg0, 1);
if (TREE_CODE (arg01) == REAL_CST
&& !TREE_OVERFLOW (arg01)
&& operand_equal_p (arg1, arg00, 0))
{
- tree powfn = TREE_OPERAND (TREE_OPERAND (arg0, 0), 0);
+ tree powfn = TREE_OPERAND (CALL_EXPR_FN (arg0), 0);
REAL_VALUE_TYPE c;
- tree arg, arglist;
+ tree arg;
c = TREE_REAL_CST (arg01);
real_arithmetic (&c, MINUS_EXPR, &c, &dconst1);
arg = build_real (type, c);
- arglist = build_tree_list (NULL_TREE, arg);
- arglist = tree_cons (NULL_TREE, arg1, arglist);
- return build_function_call_expr (powfn, arglist);
+ return build_call_expr (powfn, 2, arg1, arg);
}
}
/* Optimize x/expN(y) into x*expN(-y). */
if (BUILTIN_EXPONENT_P (fcode1))
{
- tree expfn = TREE_OPERAND (TREE_OPERAND (arg1, 0), 0);
- tree arg = negate_expr (TREE_VALUE (TREE_OPERAND (arg1, 1)));
- tree arglist = build_tree_list (NULL_TREE,
- fold_convert (type, arg));
- arg1 = build_function_call_expr (expfn, arglist);
+ tree expfn = TREE_OPERAND (CALL_EXPR_FN (arg1), 0);
+ tree arg = negate_expr (CALL_EXPR_ARG (arg1, 0));
+ arg1 = build_call_expr (expfn, 1, fold_convert (type, arg));
return fold_build2 (MULT_EXPR, type, arg0, arg1);
}
@@ -10595,13 +10571,11 @@ fold_binary (enum tree_code code, tree type, tree op0, tree op1)
|| fcode1 == BUILT_IN_POWF
|| fcode1 == BUILT_IN_POWL)
{
- tree powfn = TREE_OPERAND (TREE_OPERAND (arg1, 0), 0);
- tree arg10 = TREE_VALUE (TREE_OPERAND (arg1, 1));
- tree arg11 = TREE_VALUE (TREE_CHAIN (TREE_OPERAND (arg1, 1)));
+ tree powfn = TREE_OPERAND (CALL_EXPR_FN (arg1), 0);
+ tree arg10 = CALL_EXPR_ARG (arg1, 0);
+ tree arg11 = CALL_EXPR_ARG (arg1, 1);
tree neg11 = fold_convert (type, negate_expr (arg11));
- tree arglist = tree_cons (NULL_TREE, arg10,
- build_tree_list (NULL_TREE, neg11));
- arg1 = build_function_call_expr (powfn, arglist);
+ arg1 = build_call_expr (powfn, 2, arg10, neg11);
return fold_build2 (MULT_EXPR, type, arg0, arg1);
}
}
@@ -11386,16 +11360,14 @@ fold_binary (enum tree_code code, tree type, tree op0, tree op1)
&& integer_zerop (arg1))
{
tree fndecl = get_callee_fndecl (arg0);
- tree arglist;
if (fndecl
&& DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_NORMAL
&& DECL_FUNCTION_CODE (fndecl) == BUILT_IN_STRLEN
- && (arglist = TREE_OPERAND (arg0, 1))
- && TREE_CODE (TREE_TYPE (TREE_VALUE (arglist))) == POINTER_TYPE
- && ! TREE_CHAIN (arglist))
+ && call_expr_nargs (arg0) == 1
+ && TREE_CODE (TREE_TYPE (CALL_EXPR_ARG (arg0, 0))) == POINTER_TYPE)
{
- tree iref = build_fold_indirect_ref (TREE_VALUE (arglist));
+ tree iref = build_fold_indirect_ref (CALL_EXPR_ARG (arg0, 0));
return fold_build2 (code, type, iref,
build_int_cst (TREE_TYPE (iref), 0));
}
@@ -12376,12 +12348,9 @@ fold_ternary (enum tree_code code, tree type, tree op0, tree op1, tree op2)
return NULL_TREE;
case CALL_EXPR:
- /* Check for a built-in function. */
- if (TREE_CODE (op0) == ADDR_EXPR
- && TREE_CODE (TREE_OPERAND (op0, 0)) == FUNCTION_DECL
- && DECL_BUILT_IN (TREE_OPERAND (op0, 0)))
- return fold_builtin (TREE_OPERAND (op0, 0), op1, false);
- return NULL_TREE;
+ /* CALL_EXPRs used to be ternary exprs. Catch any mistaken uses
+ of fold_ternary on them. */
+ gcc_unreachable ();
case BIT_FIELD_REF:
if (TREE_CODE (arg0) == VECTOR_CST
@@ -12439,6 +12408,18 @@ fold (tree expr)
if (kind == tcc_constant)
return t;
+ /* CALL_EXPR-like objects with variable numbers of operands are
+ treated specially. */
+ if (kind == tcc_vl_exp)
+ {
+ if (code == CALL_EXPR)
+ {
+ tem = fold_call_expr (expr, false);
+ return tem ? tem : expr;
+ }
+ return expr;
+ }
+
if (IS_EXPR_CODE_CLASS (kind)
|| IS_GIMPLE_STMT_CODE_CLASS (kind))
{
@@ -12632,7 +12613,8 @@ recursive_label:
case tcc_unary:
case tcc_binary:
case tcc_statement:
- len = TREE_CODE_LENGTH (code);
+ case tcc_vl_exp:
+ len = TREE_OPERAND_LENGTH (expr);
for (i = 0; i < len; ++i)
fold_checksum_tree (TREE_OPERAND (expr, i), ctx, ht);
break;
@@ -12811,7 +12793,8 @@ fold_build3_stat (enum tree_code code, tree type, tree op0, tree op1, tree op2
md5_finish_ctx (&ctx, checksum_before_op2);
htab_empty (ht);
#endif
-
+
+ gcc_assert (TREE_CODE_CLASS (code) != tcc_vl_exp);
tem = fold_ternary (code, type, op0, op1, op2);
if (!tem)
tem = build3_stat (code, type, op0, op1, op2 PASS_MEM_STAT);
@@ -12844,6 +12827,57 @@ fold_build3_stat (enum tree_code code, tree type, tree op0, tree op1, tree op2
return tem;
}
+/* Fold a CALL_EXPR expression of type TYPE with operands FN and ARGLIST
+ and a null static chain.
+ Return a folded expression if successful. Otherwise, return a CALL_EXPR
+ of type TYPE from the given operands as constructed by build_call_list. */
+
+tree
+fold_build_call_list (tree type, tree fn, tree arglist)
+{
+ tree tem;
+#ifdef ENABLE_FOLD_CHECKING
+ unsigned char checksum_before_fn[16],
+ checksum_before_arglist[16],
+ checksum_after_fn[16],
+ checksum_after_arglist[16];
+ struct md5_ctx ctx;
+ htab_t ht;
+
+ ht = htab_create (32, htab_hash_pointer, htab_eq_pointer, NULL);
+ md5_init_ctx (&ctx);
+ fold_checksum_tree (fn, &ctx, ht);
+ md5_finish_ctx (&ctx, checksum_before_fn);
+ htab_empty (ht);
+
+ md5_init_ctx (&ctx);
+ fold_checksum_tree (arglist, &ctx, ht);
+ md5_finish_ctx (&ctx, checksum_before_arglist);
+ htab_empty (ht);
+#endif
+
+ tem = fold_builtin_call_list (type, fn, arglist);
+
+#ifdef ENABLE_FOLD_CHECKING
+ md5_init_ctx (&ctx);
+ fold_checksum_tree (fn, &ctx, ht);
+ md5_finish_ctx (&ctx, checksum_after_fn);
+ htab_empty (ht);
+
+ if (memcmp (checksum_before_fn, checksum_after_fn, 16))
+ fold_check_failed (fn, tem);
+
+ md5_init_ctx (&ctx);
+ fold_checksum_tree (arglist, &ctx, ht);
+ md5_finish_ctx (&ctx, checksum_after_arglist);
+ htab_delete (ht);
+
+ if (memcmp (checksum_before_arglist, checksum_after_arglist, 16))
+ fold_check_failed (arglist, tem);
+#endif
+ return tem;
+}
+
/* Perform constant folding and related simplification of initializer
expression EXPR. These behave identically to "fold_buildN" but ignore
potential run-time traps and exceptions that fold must preserve. */
@@ -12904,6 +12938,18 @@ fold_build3_initializer (enum tree_code code, tree type, tree op0, tree op1,
return result;
}
+tree
+fold_build_call_list_initializer (tree type, tree fn, tree arglist)
+{
+ tree result;
+ START_FOLD_INIT;
+
+ result = fold_build_call_list (type, fn, arglist);
+
+ END_FOLD_INIT;
+ return result;
+}
+
#undef START_FOLD_INIT
#undef END_FOLD_INIT
@@ -13223,7 +13269,6 @@ tree_expr_nonnegative_warnv_p (tree t, bool *strict_overflow_p)
case CALL_EXPR:
{
tree fndecl = get_callee_fndecl (t);
- tree arglist = TREE_OPERAND (t, 1);
if (fndecl && DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_NORMAL)
switch (DECL_FUNCTION_CODE (fndecl))
{
@@ -13251,7 +13296,7 @@ tree_expr_nonnegative_warnv_p (tree t, bool *strict_overflow_p)
/* sqrt(-0.0) is -0.0. */
if (!HONOR_SIGNED_ZEROS (TYPE_MODE (TREE_TYPE (t))))
return true;
- return tree_expr_nonnegative_warnv_p (TREE_VALUE (arglist),
+ return tree_expr_nonnegative_warnv_p (CALL_EXPR_ARG (t, 0),
strict_overflow_p);
CASE_FLT_FN (BUILT_IN_ASINH):
@@ -13282,52 +13327,49 @@ tree_expr_nonnegative_warnv_p (tree t, bool *strict_overflow_p)
CASE_FLT_FN (BUILT_IN_TANH):
CASE_FLT_FN (BUILT_IN_TRUNC):
/* True if the 1st argument is nonnegative. */
- return tree_expr_nonnegative_warnv_p (TREE_VALUE (arglist),
+ return tree_expr_nonnegative_warnv_p (CALL_EXPR_ARG (t, 0),
strict_overflow_p);
CASE_FLT_FN (BUILT_IN_FMAX):
/* True if the 1st OR 2nd arguments are nonnegative. */
- return (tree_expr_nonnegative_warnv_p (TREE_VALUE (arglist),
+ return (tree_expr_nonnegative_warnv_p (CALL_EXPR_ARG (t, 0),
strict_overflow_p)
- || (tree_expr_nonnegative_warnv_p
- (TREE_VALUE (TREE_CHAIN (arglist)),
- strict_overflow_p)));
+ || (tree_expr_nonnegative_warnv_p (CALL_EXPR_ARG (t, 1),
+ strict_overflow_p)));
CASE_FLT_FN (BUILT_IN_FMIN):
/* True if the 1st AND 2nd arguments are nonnegative. */
- return (tree_expr_nonnegative_warnv_p (TREE_VALUE (arglist),
+ return (tree_expr_nonnegative_warnv_p (CALL_EXPR_ARG (t, 0),
strict_overflow_p)
- && (tree_expr_nonnegative_warnv_p
- (TREE_VALUE (TREE_CHAIN (arglist)),
- strict_overflow_p)));
+ && (tree_expr_nonnegative_warnv_p (CALL_EXPR_ARG (t, 1),
+ strict_overflow_p)));
CASE_FLT_FN (BUILT_IN_COPYSIGN):
/* True if the 2nd argument is nonnegative. */
- return (tree_expr_nonnegative_warnv_p
- (TREE_VALUE (TREE_CHAIN (arglist)),
- strict_overflow_p));
+ return tree_expr_nonnegative_warnv_p (CALL_EXPR_ARG (t, 1),
+ strict_overflow_p);
CASE_FLT_FN (BUILT_IN_POWI):
/* True if the 1st argument is nonnegative or the second
argument is an even integer. */
- if (TREE_CODE (TREE_VALUE (TREE_CHAIN (arglist))) == INTEGER_CST)
+ if (TREE_CODE (CALL_EXPR_ARG (t, 1)) == INTEGER_CST)
{
- tree arg1 = TREE_VALUE (TREE_CHAIN (arglist));
+ tree arg1 = CALL_EXPR_ARG (t, 1);
if ((TREE_INT_CST_LOW (arg1) & 1) == 0)
return true;
}
- return tree_expr_nonnegative_warnv_p (TREE_VALUE (arglist),
+ return tree_expr_nonnegative_warnv_p (CALL_EXPR_ARG (t, 0),
strict_overflow_p);
CASE_FLT_FN (BUILT_IN_POW):
/* True if the 1st argument is nonnegative or the second
argument is an even integer valued real. */
- if (TREE_CODE (TREE_VALUE (TREE_CHAIN (arglist))) == REAL_CST)
+ if (TREE_CODE (CALL_EXPR_ARG (t, 1)) == REAL_CST)
{
REAL_VALUE_TYPE c;
HOST_WIDE_INT n;
- c = TREE_REAL_CST (TREE_VALUE (TREE_CHAIN (arglist)));
+ c = TREE_REAL_CST (CALL_EXPR_ARG (t, 1));
n = real_to_integer (&c);
if ((n & 1) == 0)
{
@@ -13338,7 +13380,7 @@ tree_expr_nonnegative_warnv_p (tree t, bool *strict_overflow_p)
return true;
}
}
- return tree_expr_nonnegative_warnv_p (TREE_VALUE (arglist),
+ return tree_expr_nonnegative_warnv_p (CALL_EXPR_ARG (t, 0),
strict_overflow_p);
default:
@@ -14336,19 +14378,17 @@ fold_strip_sign_ops (tree exp)
{
CASE_FLT_FN (BUILT_IN_COPYSIGN):
/* Strip copysign function call, return the 1st argument. */
- arg0 = TREE_VALUE (TREE_OPERAND (exp, 1));
- arg1 = TREE_VALUE (TREE_CHAIN (TREE_OPERAND (exp, 1)));
+ arg0 = CALL_EXPR_ARG (exp, 0);
+ arg1 = CALL_EXPR_ARG (exp, 1);
return omit_one_operand (TREE_TYPE (exp), arg0, arg1);
default:
/* Strip sign ops from the argument of "odd" math functions. */
if (negate_mathfn_p (fcode))
{
- arg0 = fold_strip_sign_ops (TREE_VALUE (TREE_OPERAND (exp, 1)));
+ arg0 = fold_strip_sign_ops (CALL_EXPR_ARG (exp, 0));
if (arg0)
- return build_function_call_expr (get_callee_fndecl (exp),
- build_tree_list (NULL_TREE,
- arg0));
+ return build_call_expr (get_callee_fndecl (exp), 1, arg0);
}
break;
}