static tree negate_expr (tree);
static tree split_tree (tree, enum tree_code, tree *, tree *, tree *, int);
static tree associate_trees (tree, tree, enum tree_code, tree);
-static tree int_const_binop (enum tree_code, tree, tree, int);
static tree const_binop (enum tree_code, tree, tree, int);
static hashval_t size_htab_hash (const void *);
static int size_htab_eq (const void *, const void *);
static tree fold_convert_const (enum tree_code, tree, tree);
-static tree fold_convert (tree, tree);
static enum tree_code invert_tree_comparison (enum tree_code);
static enum tree_code swap_tree_comparison (enum tree_code);
static int comparison_to_compcode (enum tree_code);
static tree optimize_minmax_comparison (tree);
static tree extract_muldiv (tree, tree, enum tree_code, tree);
static tree extract_muldiv_1 (tree, tree, enum tree_code, tree);
-static tree strip_compound_expr (tree, tree);
static int multiple_of_p (tree, tree, tree);
static tree constant_boolean_node (int, tree);
-static int count_cond (tree, int);
static tree fold_binary_op_with_conditional_arg (enum tree_code, tree, tree,
tree, int);
static bool fold_real_zero_addition_p (tree, tree, int);
static tree fold_mathfn_compare (enum built_in_function, enum tree_code,
tree, tree, tree);
static tree fold_inf_compare (enum tree_code, tree, tree, tree);
+static tree fold_div_compare (enum tree_code, tree, tree, tree);
static bool reorder_operands_p (tree, tree);
static bool tree_swap_operands_p (tree, tree, bool);
+static tree fold_negate_const (tree, tree);
+static tree fold_abs_const (tree, tree);
+static tree fold_relational_const (enum tree_code, tree, tree, tree);
+static tree fold_relational_hi_lo (enum tree_code *, const tree, tree *, tree *);
+
/* The following constants represent a bit based encoding of GCC's
comparison operators. This encoding simplifies transformations
on relational comparison operators, such as AND and OR. */
/* Unsigned types do not suffer sign extension or overflow unless they
are a sizetype. */
- if (TREE_UNSIGNED (TREE_TYPE (t))
+ if (TYPE_UNSIGNED (TREE_TYPE (t))
&& ! (TREE_CODE (TREE_TYPE (t)) == INTEGER_TYPE
&& TYPE_IS_SIZETYPE (TREE_TYPE (t))))
return overflow;
return;
}
-#ifdef SHIFT_COUNT_TRUNCATED
if (SHIFT_COUNT_TRUNCATED)
count %= prec;
-#endif
if (count >= 2 * HOST_BITS_PER_WIDE_INT)
{
? -((unsigned HOST_WIDE_INT) h1 >> (HOST_BITS_PER_WIDE_INT - 1))
: 0);
-#ifdef SHIFT_COUNT_TRUNCATED
if (SHIFT_COUNT_TRUNCATED)
count %= prec;
-#endif
if (count >= 2 * HOST_BITS_PER_WIDE_INT)
{
if (quo_neg)
neg_double (*lquo, *hquo, lquo, hquo);
- /* compute trial remainder: rem = num - (quo * den) */
+ /* Compute trial remainder: rem = num - (quo * den) */
mul_double (*lquo, *hquo, lden_orig, hden_orig, lrem, hrem);
neg_double (*lrem, *hrem, lrem, hrem);
add_double (lnum_orig, hnum_orig, *lrem, *hrem, lrem, hrem);
switch (TREE_CODE (t))
{
case INTEGER_CST:
- if (TREE_UNSIGNED (type) || ! flag_trapv)
+ if (TYPE_UNSIGNED (type) || ! flag_trapv)
return true;
/* Check that -CST will not overflow type. */
TREE_OPERAND (t, 1));
case MULT_EXPR:
- if (TREE_UNSIGNED (TREE_TYPE (t)))
+ if (TYPE_UNSIGNED (TREE_TYPE (t)))
break;
/* Fall through. */
return negate_expr_p (TREE_VALUE (TREE_OPERAND (t, 1)));
break;
+ case RSHIFT_EXPR:
+ /* Optimize -((int)x >> 31) into (unsigned)x >> 31. */
+ if (TREE_CODE (TREE_OPERAND (t, 1)) == INTEGER_CST)
+ {
+ tree op1 = TREE_OPERAND (t, 1);
+ if (TREE_INT_CST_HIGH (op1) == 0
+ && (unsigned HOST_WIDE_INT) (TYPE_PRECISION (type) - 1)
+ == TREE_INT_CST_LOW (op1))
+ return true;
+ }
+ break;
+
default:
break;
}
switch (TREE_CODE (t))
{
case INTEGER_CST:
- {
- unsigned HOST_WIDE_INT low;
- HOST_WIDE_INT high;
- int overflow = neg_double (TREE_INT_CST_LOW (t),
- TREE_INT_CST_HIGH (t),
- &low, &high);
- tem = build_int_2 (low, high);
- TREE_TYPE (tem) = type;
- TREE_OVERFLOW (tem)
- = (TREE_OVERFLOW (t)
- | force_fit_type (tem, overflow && !TREE_UNSIGNED (type)));
- TREE_CONSTANT_OVERFLOW (tem)
- = TREE_OVERFLOW (tem) | TREE_CONSTANT_OVERFLOW (t);
- }
+ tem = fold_negate_const (t, type);
if (! TREE_OVERFLOW (tem)
- || TREE_UNSIGNED (type)
+ || TYPE_UNSIGNED (type)
|| ! flag_trapv)
return tem;
break;
case REAL_CST:
- tem = build_real (type, REAL_VALUE_NEGATE (TREE_REAL_CST (t)));
+ tem = fold_negate_const (t, type);
/* Two's complement FP formats, such as c4x, may overflow. */
if (! TREE_OVERFLOW (tem) || ! flag_trapping_math)
return fold_convert (type, tem);
if (negate_expr_p (TREE_OPERAND (t, 1))
&& reorder_operands_p (TREE_OPERAND (t, 0),
TREE_OPERAND (t, 1)))
- return fold_convert (type,
- fold (build (MINUS_EXPR, TREE_TYPE (t),
- negate_expr (TREE_OPERAND (t, 1)),
- TREE_OPERAND (t, 0))));
+ {
+ tem = negate_expr (TREE_OPERAND (t, 1));
+ tem = fold (build2 (MINUS_EXPR, TREE_TYPE (t),
+ tem, TREE_OPERAND (t, 0)));
+ return fold_convert (type, tem);
+ }
+
/* -(A + B) -> (-A) - B. */
if (negate_expr_p (TREE_OPERAND (t, 0)))
- return fold_convert (type,
- fold (build (MINUS_EXPR, TREE_TYPE (t),
- negate_expr (TREE_OPERAND (t, 0)),
- TREE_OPERAND (t, 1))));
+ {
+ tem = negate_expr (TREE_OPERAND (t, 0));
+ tem = fold (build2 (MINUS_EXPR, TREE_TYPE (t),
+ tem, TREE_OPERAND (t, 1)));
+ return fold_convert (type, tem);
+ }
}
break;
if ((! FLOAT_TYPE_P (type) || flag_unsafe_math_optimizations)
&& reorder_operands_p (TREE_OPERAND (t, 0), TREE_OPERAND (t, 1)))
return fold_convert (type,
- fold (build (MINUS_EXPR, TREE_TYPE (t),
- TREE_OPERAND (t, 1),
- TREE_OPERAND (t, 0))));
+ fold (build2 (MINUS_EXPR, TREE_TYPE (t),
+ TREE_OPERAND (t, 1),
+ TREE_OPERAND (t, 0))));
break;
case MULT_EXPR:
- if (TREE_UNSIGNED (TREE_TYPE (t)))
+ if (TYPE_UNSIGNED (TREE_TYPE (t)))
break;
/* Fall through. */
tem = TREE_OPERAND (t, 1);
if (negate_expr_p (tem))
return fold_convert (type,
- fold (build (TREE_CODE (t), TREE_TYPE (t),
- TREE_OPERAND (t, 0),
- negate_expr (tem))));
+ fold (build2 (TREE_CODE (t), TREE_TYPE (t),
+ TREE_OPERAND (t, 0),
+ negate_expr (tem))));
tem = TREE_OPERAND (t, 0);
if (negate_expr_p (tem))
return fold_convert (type,
- fold (build (TREE_CODE (t), TREE_TYPE (t),
- negate_expr (tem),
- TREE_OPERAND (t, 1))));
+ fold (build2 (TREE_CODE (t), TREE_TYPE (t),
+ negate_expr (tem),
+ TREE_OPERAND (t, 1))));
}
break;
}
break;
+ case RSHIFT_EXPR:
+ /* Optimize -((int)x >> 31) into (unsigned)x >> 31. */
+ if (TREE_CODE (TREE_OPERAND (t, 1)) == INTEGER_CST)
+ {
+ tree op1 = TREE_OPERAND (t, 1);
+ if (TREE_INT_CST_HIGH (op1) == 0
+ && (unsigned HOST_WIDE_INT) (TYPE_PRECISION (type) - 1)
+ == TREE_INT_CST_LOW (op1))
+ {
+ tree ntype = TYPE_UNSIGNED (type)
+ ? lang_hooks.types.signed_type (type)
+ : lang_hooks.types.unsigned_type (type);
+ tree temp = fold_convert (ntype, TREE_OPERAND (t, 0));
+ temp = fold (build2 (RSHIFT_EXPR, ntype, temp, op1));
+ return fold_convert (type, temp);
+ }
+ }
+ break;
+
default:
break;
}
if (code == PLUS_EXPR)
{
if (TREE_CODE (t1) == NEGATE_EXPR)
- return build (MINUS_EXPR, type, fold_convert (type, t2),
- fold_convert (type, TREE_OPERAND (t1, 0)));
+ return build2 (MINUS_EXPR, type, fold_convert (type, t2),
+ fold_convert (type, TREE_OPERAND (t1, 0)));
else if (TREE_CODE (t2) == NEGATE_EXPR)
- return build (MINUS_EXPR, type, fold_convert (type, t1),
- fold_convert (type, TREE_OPERAND (t2, 0)));
+ return build2 (MINUS_EXPR, type, fold_convert (type, t1),
+ fold_convert (type, TREE_OPERAND (t2, 0)));
}
- return build (code, type, fold_convert (type, t1),
- fold_convert (type, t2));
+ return build2 (code, type, fold_convert (type, t1),
+ fold_convert (type, t2));
}
- return fold (build (code, type, fold_convert (type, t1),
- fold_convert (type, t2)));
+ return fold (build2 (code, type, fold_convert (type, t1),
+ fold_convert (type, t2)));
}
\f
/* Combine two integer constants ARG1 and ARG2 under operation CODE
If NOTRUNC is nonzero, do not truncate the result to fit the data type. */
-static tree
+tree
int_const_binop (enum tree_code code, tree arg1, tree arg2, int notrunc)
{
unsigned HOST_WIDE_INT int1l, int2l;
HOST_WIDE_INT garbageh;
tree t;
tree type = TREE_TYPE (arg1);
- int uns = TREE_UNSIGNED (type);
+ int uns = TYPE_UNSIGNED (type);
int is_sizetype
= (TREE_CODE (type) == INTEGER_TYPE && TYPE_IS_SIZETYPE (type));
int overflow = 0;
if (arg0 == error_mark_node || arg1 == error_mark_node)
return error_mark_node;
- return fold (build (code, type, arg0, arg1));
+ return fold (build2 (code, type, arg0, arg1));
}
/* Given two values, either both of sizetype or both of bitsizetype,
abort ();
/* If the type is already signed, just do the simple thing. */
- if (! TREE_UNSIGNED (type))
+ if (!TYPE_UNSIGNED (type))
return size_binop (MINUS_EXPR, arg0, arg1);
ctype = (type == bitsizetype || type == ubitsizetype
TREE_OVERFLOW (t)
= ((force_fit_type (t,
(TREE_INT_CST_HIGH (arg1) < 0
- && (TREE_UNSIGNED (type)
- < TREE_UNSIGNED (TREE_TYPE (arg1)))))
+ && (TYPE_UNSIGNED (type)
+ < TYPE_UNSIGNED (TREE_TYPE (arg1)))))
&& ! POINTER_TYPE_P (TREE_TYPE (arg1)))
|| TREE_OVERFLOW (arg1));
TREE_CONSTANT_OVERFLOW (t)
real_floor (&r, VOIDmode, &x);
break;
+ case FIX_ROUND_EXPR:
+ real_round (&r, VOIDmode, &x);
+ break;
+
default:
abort ();
}
/* Convert expression ARG to type TYPE. Used by the middle-end for
simple conversions in preference to calling the front-end's convert. */
-static tree
+tree
fold_convert (tree type, tree arg)
{
tree orig = TREE_TYPE (arg);
if (INTEGRAL_TYPE_P (orig)
|| POINTER_TYPE_P (orig)
|| TREE_CODE (orig) == REAL_TYPE)
- return build (COMPLEX_EXPR, type,
- fold_convert (TREE_TYPE (type), arg),
- fold_convert (TREE_TYPE (type), integer_zero_node));
+ return build2 (COMPLEX_EXPR, type,
+ fold_convert (TREE_TYPE (type), arg),
+ fold_convert (TREE_TYPE (type), integer_zero_node));
if (TREE_CODE (orig) == COMPLEX_TYPE)
{
tree rpart, ipart;
{
rpart = fold_convert (TREE_TYPE (type), TREE_OPERAND (arg, 0));
ipart = fold_convert (TREE_TYPE (type), TREE_OPERAND (arg, 1));
- return fold (build (COMPLEX_EXPR, type, rpart, ipart));
+ return fold (build2 (COMPLEX_EXPR, type, rpart, ipart));
}
arg = save_expr (arg);
ipart = fold (build1 (IMAGPART_EXPR, TREE_TYPE (orig), arg));
rpart = fold_convert (TREE_TYPE (type), rpart);
ipart = fold_convert (TREE_TYPE (type), ipart);
- return fold (build (COMPLEX_EXPR, type, rpart, ipart));
+ return fold (build2 (COMPLEX_EXPR, type, rpart, ipart));
}
}
else if (TREE_CODE (type) == VECTOR_TYPE)
tree
non_lvalue (tree x)
{
- tree result;
-
/* These things are certainly not lvalues. */
if (TREE_CODE (x) == NON_LVALUE_EXPR
|| TREE_CODE (x) == INTEGER_CST
|| TREE_CODE (x) == ADDR_EXPR)
return x;
- result = build1 (NON_LVALUE_EXPR, TREE_TYPE (x), x);
- TREE_CONSTANT (result) = TREE_CONSTANT (x);
- return result;
+ return build1 (NON_LVALUE_EXPR, TREE_TYPE (x), x);
}
/* Nonzero means lvalues are limited to those valid in pedantic ANSI C.
\f
/* Return nonzero if two operands (typically of the same tree node)
are necessarily equal. If either argument has side-effects this
- function returns zero.
+ function returns zero. FLAGS modifies behaviour as follows:
- If ONLY_CONST is nonzero, only return nonzero for constants.
+ If OEP_ONLY_CONST is set, only return nonzero for constants.
This function tests whether the operands are indistinguishable;
it does not test whether they are equal using C's == operation.
The distinction is important for IEEE floating point, because
(1) -0.0 and 0.0 are distinguishable, but -0.0==0.0, and
(2) two NaNs may be indistinguishable, but NaN!=NaN.
- If ONLY_CONST is zero, a VAR_DECL is considered equal to itself
+ If OEP_ONLY_CONST is unset, a VAR_DECL is considered equal to itself
even though it may hold multiple values during a function.
This is because a GCC tree node guarantees that nothing else is
executed between the evaluation of its "operands" (which may often
same value in each operand/subexpression. Hence a zero value for
ONLY_CONST assumes isochronic (or instantaneous) tree equivalence.
If comparing arbitrary expression trees, such as from different
- statements, ONLY_CONST must usually be nonzero. */
+ statements, ONLY_CONST must usually be nonzero.
+
+ If OEP_PURE_SAME is set, then pure functions with identical arguments
+ are considered the same. It is used when the caller has other ways
+ to ensure that global memory is unchanged in between. */
int
-operand_equal_p (tree arg0, tree arg1, int only_const)
+operand_equal_p (tree arg0, tree arg1, unsigned int flags)
{
- tree fndecl;
+ /* If either is ERROR_MARK, they aren't equal. */
+ if (TREE_CODE (arg0) == ERROR_MARK || TREE_CODE (arg1) == ERROR_MARK)
+ return 0;
/* If both types don't have the same signedness, then we can't consider
them equal. We must check this before the STRIP_NOPS calls
because they may change the signedness of the arguments. */
- if (TREE_UNSIGNED (TREE_TYPE (arg0)) != TREE_UNSIGNED (TREE_TYPE (arg1)))
+ if (TYPE_UNSIGNED (TREE_TYPE (arg0)) != TYPE_UNSIGNED (TREE_TYPE (arg1)))
return 0;
STRIP_NOPS (arg0);
expressions with side effects that should be treated the same due
to the only side effects being identical SAVE_EXPR's, that will
be detected in the recursive calls below. */
- if (arg0 == arg1 && ! only_const
+ if (arg0 == arg1 && ! (flags & OEP_ONLY_CONST)
&& (TREE_CODE (arg0) == SAVE_EXPR
|| (! TREE_SIDE_EFFECTS (arg0) && ! TREE_SIDE_EFFECTS (arg1))))
return 1;
v2 = TREE_VECTOR_CST_ELTS (arg1);
while (v1 && v2)
{
- if (!operand_equal_p (v1, v2, only_const))
+ if (!operand_equal_p (TREE_VALUE (v1), TREE_VALUE (v2),
+ flags))
return 0;
v1 = TREE_CHAIN (v1);
v2 = TREE_CHAIN (v2);
case COMPLEX_CST:
return (operand_equal_p (TREE_REALPART (arg0), TREE_REALPART (arg1),
- only_const)
+ flags)
&& operand_equal_p (TREE_IMAGPART (arg0), TREE_IMAGPART (arg1),
- only_const));
+ flags));
case STRING_CST:
return (TREE_STRING_LENGTH (arg0) == TREE_STRING_LENGTH (arg1)
break;
}
- if (only_const)
+ if (flags & OEP_ONLY_CONST)
return 0;
switch (TREE_CODE_CLASS (TREE_CODE (arg0)))
case '1':
/* Two conversions are equal only if signedness and modes match. */
if ((TREE_CODE (arg0) == NOP_EXPR || TREE_CODE (arg0) == CONVERT_EXPR)
- && (TREE_UNSIGNED (TREE_TYPE (arg0))
- != TREE_UNSIGNED (TREE_TYPE (arg1))))
+ && (TYPE_UNSIGNED (TREE_TYPE (arg0))
+ != TYPE_UNSIGNED (TREE_TYPE (arg1))))
return 0;
return operand_equal_p (TREE_OPERAND (arg0, 0),
- TREE_OPERAND (arg1, 0), 0);
+ TREE_OPERAND (arg1, 0), flags);
case '<':
case '2':
/* For commutative ops, allow the other order. */
return (commutative_tree_code (TREE_CODE (arg0))
&& operand_equal_p (TREE_OPERAND (arg0, 0),
- TREE_OPERAND (arg1, 1), 0)
+ TREE_OPERAND (arg1, 1), flags)
&& operand_equal_p (TREE_OPERAND (arg0, 1),
- TREE_OPERAND (arg1, 0), 0));
+ TREE_OPERAND (arg1, 0), flags));
case 'r':
/* If either of the pointer (or reference) expressions we are
{
case INDIRECT_REF:
return operand_equal_p (TREE_OPERAND (arg0, 0),
- TREE_OPERAND (arg1, 0), 0);
+ TREE_OPERAND (arg1, 0), flags);
case COMPONENT_REF:
case ARRAY_REF:
case ARRAY_RANGE_REF:
return (operand_equal_p (TREE_OPERAND (arg0, 0),
- TREE_OPERAND (arg1, 0), 0)
+ TREE_OPERAND (arg1, 0), flags)
&& operand_equal_p (TREE_OPERAND (arg0, 1),
- TREE_OPERAND (arg1, 1), 0));
+ TREE_OPERAND (arg1, 1), flags));
case BIT_FIELD_REF:
return (operand_equal_p (TREE_OPERAND (arg0, 0),
- TREE_OPERAND (arg1, 0), 0)
+ TREE_OPERAND (arg1, 0), flags)
&& operand_equal_p (TREE_OPERAND (arg0, 1),
- TREE_OPERAND (arg1, 1), 0)
+ TREE_OPERAND (arg1, 1), flags)
&& operand_equal_p (TREE_OPERAND (arg0, 2),
- TREE_OPERAND (arg1, 2), 0));
+ TREE_OPERAND (arg1, 2), flags));
default:
return 0;
}
case ADDR_EXPR:
case TRUTH_NOT_EXPR:
return operand_equal_p (TREE_OPERAND (arg0, 0),
- TREE_OPERAND (arg1, 0), 0);
+ TREE_OPERAND (arg1, 0), flags);
case RTL_EXPR:
return rtx_equal_p (RTL_EXPR_RTL (arg0), RTL_EXPR_RTL (arg1));
/* If the CALL_EXPRs call different functions, then they
clearly can not be equal. */
if (! operand_equal_p (TREE_OPERAND (arg0, 0),
- TREE_OPERAND (arg1, 0), 0))
+ TREE_OPERAND (arg1, 0), flags))
return 0;
- /* Only consider const functions equivalent. */
- fndecl = get_callee_fndecl (arg0);
- if (fndecl == NULL_TREE
- || ! (flags_from_decl_or_type (fndecl) & ECF_CONST))
- return 0;
+ {
+ unsigned int cef = call_expr_flags (arg0);
+ if (flags & OEP_PURE_SAME)
+ cef &= ECF_CONST | ECF_PURE;
+ else
+ cef &= ECF_CONST;
+ if (!cef)
+ 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
arg1 = TREE_OPERAND (arg1, 1);
while (arg0 && arg1)
{
- if (! operand_equal_p (TREE_VALUE (arg0), TREE_VALUE (arg1), 0))
+ if (! operand_equal_p (TREE_VALUE (arg0), TREE_VALUE (arg1),
+ flags))
return 0;
arg0 = TREE_CHAIN (arg0);
}
case 'd':
- /* Consider __builtin_sqrt equal to sqrt. */
- return TREE_CODE (arg0) == FUNCTION_DECL
- && DECL_BUILT_IN (arg0) && DECL_BUILT_IN (arg1)
- && DECL_BUILT_IN_CLASS (arg0) == DECL_BUILT_IN_CLASS (arg1)
- && DECL_FUNCTION_CODE (arg0) == DECL_FUNCTION_CODE (arg1);
+ /* Consider __builtin_sqrt equal to sqrt. */
+ return (TREE_CODE (arg0) == FUNCTION_DECL
+ && DECL_BUILT_IN (arg0) && DECL_BUILT_IN (arg1)
+ && DECL_BUILT_IN_CLASS (arg0) == DECL_BUILT_IN_CLASS (arg1)
+ && DECL_FUNCTION_CODE (arg0) == DECL_FUNCTION_CODE (arg1));
default:
return 0;
/* Make sure shorter operand is extended the right way
to match the longer operand. */
- primarg1 = fold_convert ((*lang_hooks.types.signed_or_unsigned_type)
+ primarg1 = fold_convert (lang_hooks.types.signed_or_unsigned_type
(unsignedp1, TREE_TYPE (primarg1)), primarg1);
if (operand_equal_p (arg0, fold_convert (type, primarg1), 0))
old0, new0, old1, new1)));
case '2':
- return fold (build (code, type,
- eval_subst (TREE_OPERAND (arg, 0),
- old0, new0, old1, new1),
- eval_subst (TREE_OPERAND (arg, 1),
- old0, new0, old1, new1)));
+ return fold (build2 (code, type,
+ eval_subst (TREE_OPERAND (arg, 0),
+ old0, new0, old1, new1),
+ eval_subst (TREE_OPERAND (arg, 1),
+ old0, new0, old1, new1)));
case 'e':
switch (code)
return eval_subst (TREE_OPERAND (arg, 1), old0, new0, old1, new1);
case COND_EXPR:
- return fold (build (code, type,
- eval_subst (TREE_OPERAND (arg, 0),
- old0, new0, old1, new1),
- eval_subst (TREE_OPERAND (arg, 1),
- old0, new0, old1, new1),
- eval_subst (TREE_OPERAND (arg, 2),
- old0, new0, old1, new1)));
+ return fold (build3 (code, type,
+ eval_subst (TREE_OPERAND (arg, 0),
+ old0, new0, old1, new1),
+ eval_subst (TREE_OPERAND (arg, 1),
+ old0, new0, old1, new1),
+ eval_subst (TREE_OPERAND (arg, 2),
+ old0, new0, old1, new1)));
default:
break;
}
else if (arg1 == old1 || operand_equal_p (arg1, old1, 0))
arg1 = new1;
- return fold (build (code, type, arg0, arg1));
+ return fold (build2 (code, type, arg0, arg1));
}
default:
tree t = fold_convert (type, result);
if (TREE_SIDE_EFFECTS (omitted))
- return build (COMPOUND_EXPR, type, omitted, t);
+ return build2 (COMPOUND_EXPR, type, omitted, t);
return non_lvalue (t);
}
tree t = fold_convert (type, result);
if (TREE_SIDE_EFFECTS (omitted))
- return build (COMPOUND_EXPR, type, omitted, t);
+ return build2 (COMPOUND_EXPR, type, omitted, t);
return pedantic_non_lvalue (t);
}
&& code != NE_EXPR
&& code != EQ_EXPR)
return build1 (TRUTH_NOT_EXPR, type, arg);
+ else if (code == UNORDERED_EXPR
+ || code == ORDERED_EXPR
+ || code == UNEQ_EXPR
+ || code == UNLT_EXPR
+ || code == UNLE_EXPR
+ || code == UNGT_EXPR
+ || code == UNGE_EXPR)
+ return build1 (TRUTH_NOT_EXPR, type, arg);
else
- return build (invert_tree_comparison (code), type,
- TREE_OPERAND (arg, 0), TREE_OPERAND (arg, 1));
+ return build2 (invert_tree_comparison (code), type,
+ TREE_OPERAND (arg, 0), TREE_OPERAND (arg, 1));
}
switch (code)
return fold_convert (type, build_int_2 (integer_zerop (arg), 0));
case TRUTH_AND_EXPR:
- return build (TRUTH_OR_EXPR, type,
- invert_truthvalue (TREE_OPERAND (arg, 0)),
- invert_truthvalue (TREE_OPERAND (arg, 1)));
+ return build2 (TRUTH_OR_EXPR, type,
+ invert_truthvalue (TREE_OPERAND (arg, 0)),
+ invert_truthvalue (TREE_OPERAND (arg, 1)));
case TRUTH_OR_EXPR:
- return build (TRUTH_AND_EXPR, type,
- invert_truthvalue (TREE_OPERAND (arg, 0)),
- invert_truthvalue (TREE_OPERAND (arg, 1)));
+ return build2 (TRUTH_AND_EXPR, type,
+ invert_truthvalue (TREE_OPERAND (arg, 0)),
+ invert_truthvalue (TREE_OPERAND (arg, 1)));
case TRUTH_XOR_EXPR:
/* Here we can invert either operand. We invert the first operand
negation of the second operand. */
if (TREE_CODE (TREE_OPERAND (arg, 1)) == TRUTH_NOT_EXPR)
- return build (TRUTH_XOR_EXPR, type, TREE_OPERAND (arg, 0),
- TREE_OPERAND (TREE_OPERAND (arg, 1), 0));
+ return build2 (TRUTH_XOR_EXPR, type, TREE_OPERAND (arg, 0),
+ TREE_OPERAND (TREE_OPERAND (arg, 1), 0));
else
- return build (TRUTH_XOR_EXPR, type,
- invert_truthvalue (TREE_OPERAND (arg, 0)),
- TREE_OPERAND (arg, 1));
+ return build2 (TRUTH_XOR_EXPR, type,
+ invert_truthvalue (TREE_OPERAND (arg, 0)),
+ TREE_OPERAND (arg, 1));
case TRUTH_ANDIF_EXPR:
- return build (TRUTH_ORIF_EXPR, type,
- invert_truthvalue (TREE_OPERAND (arg, 0)),
- invert_truthvalue (TREE_OPERAND (arg, 1)));
+ return build2 (TRUTH_ORIF_EXPR, type,
+ invert_truthvalue (TREE_OPERAND (arg, 0)),
+ invert_truthvalue (TREE_OPERAND (arg, 1)));
case TRUTH_ORIF_EXPR:
- return build (TRUTH_ANDIF_EXPR, type,
- invert_truthvalue (TREE_OPERAND (arg, 0)),
- invert_truthvalue (TREE_OPERAND (arg, 1)));
+ return build2 (TRUTH_ANDIF_EXPR, type,
+ invert_truthvalue (TREE_OPERAND (arg, 0)),
+ invert_truthvalue (TREE_OPERAND (arg, 1)));
case TRUTH_NOT_EXPR:
return TREE_OPERAND (arg, 0);
case COND_EXPR:
- return build (COND_EXPR, type, TREE_OPERAND (arg, 0),
- invert_truthvalue (TREE_OPERAND (arg, 1)),
- invert_truthvalue (TREE_OPERAND (arg, 2)));
+ return build3 (COND_EXPR, type, TREE_OPERAND (arg, 0),
+ invert_truthvalue (TREE_OPERAND (arg, 1)),
+ invert_truthvalue (TREE_OPERAND (arg, 2)));
case COMPOUND_EXPR:
- return build (COMPOUND_EXPR, type, TREE_OPERAND (arg, 0),
- invert_truthvalue (TREE_OPERAND (arg, 1)));
-
- case WITH_RECORD_EXPR:
- return build (WITH_RECORD_EXPR, type,
- invert_truthvalue (TREE_OPERAND (arg, 0)),
- TREE_OPERAND (arg, 1));
+ return build2 (COMPOUND_EXPR, type, TREE_OPERAND (arg, 0),
+ invert_truthvalue (TREE_OPERAND (arg, 1)));
case NON_LVALUE_EXPR:
return invert_truthvalue (TREE_OPERAND (arg, 0));
case NOP_EXPR:
+ if (TREE_CODE (TREE_TYPE (arg)) == BOOLEAN_TYPE)
+ break;
+
case CONVERT_EXPR:
case FLOAT_EXPR:
return build1 (TREE_CODE (arg), type,
case BIT_AND_EXPR:
if (!integer_onep (TREE_OPERAND (arg, 1)))
break;
- return build (EQ_EXPR, type, arg,
- fold_convert (type, integer_zero_node));
+ return build2 (EQ_EXPR, type, arg,
+ fold_convert (type, integer_zero_node));
case SAVE_EXPR:
return build1 (TRUTH_NOT_EXPR, type, arg);
else
return 0;
- return fold (build (TREE_CODE (arg0), type, common,
- fold (build (code, type, left, right))));
+ return fold (build2 (TREE_CODE (arg0), type, common,
+ fold (build2 (code, type, left, right))));
}
\f
/* Return a BIT_FIELD_REF of type TYPE to refer to BITSIZE bits of INNER
make_bit_field_ref (tree inner, tree type, int bitsize, int bitpos,
int unsignedp)
{
- tree result = build (BIT_FIELD_REF, type, inner,
- size_int (bitsize), bitsize_int (bitpos));
+ tree result = build3 (BIT_FIELD_REF, type, inner,
+ size_int (bitsize), bitsize_int (bitpos));
- TREE_UNSIGNED (result) = unsignedp;
+ BIT_FIELD_REF_UNSIGNED (result) = unsignedp;
return result;
}
/* Set signed and unsigned types of the precision of this mode for the
shifts below. */
- signed_type = (*lang_hooks.types.type_for_mode) (nmode, 0);
- unsigned_type = (*lang_hooks.types.type_for_mode) (nmode, 1);
+ signed_type = lang_hooks.types.type_for_mode (nmode, 0);
+ unsigned_type = lang_hooks.types.type_for_mode (nmode, 1);
/* Compute the bit position and size for the new reference and our offset
within it. If the new reference is the same size as the original, we
if (! const_p)
/* If not comparing with constant, just rework the comparison
and return. */
- return build (code, compare_type,
- build (BIT_AND_EXPR, unsigned_type,
- make_bit_field_ref (linner, unsigned_type,
- nbitsize, nbitpos, 1),
- mask),
- build (BIT_AND_EXPR, unsigned_type,
- make_bit_field_ref (rinner, unsigned_type,
- nbitsize, nbitpos, 1),
- mask));
+ return build2 (code, compare_type,
+ build2 (BIT_AND_EXPR, unsigned_type,
+ make_bit_field_ref (linner, unsigned_type,
+ nbitsize, nbitpos, 1),
+ mask),
+ build2 (BIT_AND_EXPR, unsigned_type,
+ make_bit_field_ref (rinner, unsigned_type,
+ nbitsize, nbitpos, 1),
+ mask));
/* Otherwise, we are handling the constant case. See if the constant is too
big for the field. Warn and return a tree of for 0 (false) if so. We do
size_int (lbitpos), 0),
mask, 0));
- return build (code, compare_type,
- build (BIT_AND_EXPR, unsigned_type, lhs, mask),
- rhs);
+ return build2 (code, compare_type,
+ build2 (BIT_AND_EXPR, unsigned_type, lhs, mask),
+ rhs);
}
\f
/* Subroutine for fold_truthop: decode a field reference.
the outer type, then the outer type gives the signedness. Otherwise
(in case of a small bitfield) the signedness is unchanged. */
if (outer_type && *pbitsize == tree_low_cst (TYPE_SIZE (outer_type), 1))
- *punsignedp = TREE_UNSIGNED (outer_type);
+ *punsignedp = TYPE_UNSIGNED (outer_type);
/* Compute the mask to access the bitfield. */
- unsigned_type = (*lang_hooks.types.type_for_size) (*pbitsize, 1);
+ unsigned_type = lang_hooks.types.type_for_size (*pbitsize, 1);
precision = TYPE_PRECISION (unsigned_type);
mask = build_int_2 (~0, ~0);
/* Merge it with the mask we found in the BIT_AND_EXPR, if any. */
if (and_mask != 0)
- mask = fold (build (BIT_AND_EXPR, unsigned_type,
- fold_convert (unsigned_type, and_mask), mask));
+ mask = fold (build2 (BIT_AND_EXPR, unsigned_type,
+ fold_convert (unsigned_type, and_mask), mask));
*pmask = mask;
*pand_mask = and_mask;
tree tmask;
tmask = build_int_2 (~0, ~0);
- TREE_TYPE (tmask) = (*lang_hooks.types.signed_type) (type);
+ TREE_TYPE (tmask) = lang_hooks.types.signed_type (type);
force_fit_type (tmask, 0);
return
tree_int_cst_equal (mask,
if (arg0 != 0 && arg1 != 0)
{
- tem = fold (build (code, type != 0 ? type : TREE_TYPE (arg0),
- arg0, fold_convert (TREE_TYPE (arg0), arg1)));
+ tem = fold (build2 (code, type != 0 ? type : TREE_TYPE (arg0),
+ arg0, fold_convert (TREE_TYPE (arg0), arg1)));
STRIP_NOPS (tem);
return TREE_CODE (tem) == INTEGER_CST ? tem : 0;
}
greater than or equal to zero. We base the range tests we make
on that fact, so we record it here so we can parse existing
range tests. */
- if (TREE_UNSIGNED (type) && (low == 0 || high == 0))
+ if (TYPE_UNSIGNED (type) && (low == 0 || high == 0))
{
if (! merge_ranges (&n_in_p, &n_low, &n_high, in_p, low, high,
1, fold_convert (type, integer_zero_node),
case BIT_NOT_EXPR:
/* ~ X -> -X - 1 */
- exp = build (MINUS_EXPR, type, negate_expr (arg0),
- fold_convert (type, integer_one_node));
+ exp = build2 (MINUS_EXPR, type, negate_expr (arg0),
+ fold_convert (type, integer_one_node));
continue;
case PLUS_EXPR: case MINUS_EXPR:
So we have to make sure that the original unsigned value will
be interpreted as positive. */
- if (TREE_UNSIGNED (type) && ! TREE_UNSIGNED (TREE_TYPE (exp)))
+ if (TYPE_UNSIGNED (type) && ! TYPE_UNSIGNED (TREE_TYPE (exp)))
{
- tree equiv_type = (*lang_hooks.types.type_for_mode)
+ tree equiv_type = lang_hooks.types.type_for_mode
(TYPE_MODE (type), 1);
tree high_positive;
: TYPE_MAX_VALUE (type);
if (TYPE_PRECISION (type) == TYPE_PRECISION (TREE_TYPE (exp)))
- high_positive = fold (build (RSHIFT_EXPR, type,
- fold_convert (type,
- high_positive),
- fold_convert (type,
- integer_one_node)));
+ high_positive = fold (build2 (RSHIFT_EXPR, type,
+ fold_convert (type,
+ high_positive),
+ fold_convert (type,
+ integer_one_node)));
/* If the low bound is specified, "and" the range with the
range for which the original unsigned value will be
return fold_convert (type, integer_one_node);
if (low == 0)
- return fold (build (LE_EXPR, type, exp, high));
+ return fold (build2 (LE_EXPR, type, exp, high));
if (high == 0)
- return fold (build (GE_EXPR, type, exp, low));
+ return fold (build2 (GE_EXPR, type, exp, low));
if (operand_equal_p (low, high, 0))
- return fold (build (EQ_EXPR, type, exp, low));
+ return fold (build2 (EQ_EXPR, type, exp, low));
if (integer_zerop (low))
{
- if (! TREE_UNSIGNED (etype))
+ if (! TYPE_UNSIGNED (etype))
{
- etype = (*lang_hooks.types.unsigned_type) (etype);
+ etype = lang_hooks.types.unsigned_type (etype);
high = fold_convert (etype, high);
exp = fold_convert (etype, exp);
}
if (TREE_INT_CST_HIGH (high) == hi && TREE_INT_CST_LOW (high) == lo)
{
- if (TREE_UNSIGNED (etype))
+ if (TYPE_UNSIGNED (etype))
{
- etype = (*lang_hooks.types.signed_type) (etype);
+ etype = lang_hooks.types.signed_type (etype);
exp = fold_convert (etype, exp);
}
- return fold (build (GT_EXPR, type, exp,
- fold_convert (etype, integer_zero_node)));
+ return fold (build2 (GT_EXPR, type, exp,
+ fold_convert (etype, integer_zero_node)));
}
}
if (0 != (value = const_binop (MINUS_EXPR, high, low, 0))
&& ! TREE_OVERFLOW (value))
return build_range_check (type,
- fold (build (MINUS_EXPR, etype, exp, low)),
+ fold (build2 (MINUS_EXPR, etype, exp, low)),
1, fold_convert (etype, integer_zero_node),
value);
unless we are at top level or LHS contains a PLACEHOLDER_EXPR, in
which cases we can't do this. */
if (simple_operand_p (lhs))
- return build (TREE_CODE (exp) == TRUTH_ANDIF_EXPR
- ? TRUTH_AND_EXPR : TRUTH_OR_EXPR,
- TREE_TYPE (exp), TREE_OPERAND (exp, 0),
- TREE_OPERAND (exp, 1));
+ return build2 (TREE_CODE (exp) == TRUTH_ANDIF_EXPR
+ ? TRUTH_AND_EXPR : TRUTH_OR_EXPR,
+ TREE_TYPE (exp), TREE_OPERAND (exp, 0),
+ TREE_OPERAND (exp, 1));
- else if ((*lang_hooks.decls.global_bindings_p) () == 0
+ else if (lang_hooks.decls.global_bindings_p () == 0
&& ! CONTAINS_PLACEHOLDER_P (lhs))
{
tree common = save_expr (lhs);
&& (0 != (rhs = build_range_check (TREE_TYPE (exp), common,
or_op ? ! in1_p : in1_p,
low1, high1))))
- return build (TREE_CODE (exp) == TRUTH_ANDIF_EXPR
- ? TRUTH_AND_EXPR : TRUTH_OR_EXPR,
- TREE_TYPE (exp), lhs, rhs);
+ return build2 (TREE_CODE (exp) == TRUTH_ANDIF_EXPR
+ ? TRUTH_AND_EXPR : TRUTH_OR_EXPR,
+ TREE_TYPE (exp), lhs, rhs);
}
}
do the type conversion here. At this point, the constant is either
zero or one, and the conversion to a signed type can never overflow.
We could get an overflow if this conversion is done anywhere else. */
- if (TREE_UNSIGNED (type))
- temp = fold_convert ((*lang_hooks.types.signed_type) (type), temp);
+ if (TYPE_UNSIGNED (type))
+ temp = fold_convert (lang_hooks.types.signed_type (type), temp);
temp = const_binop (LSHIFT_EXPR, temp, size_int (modesize - 1), 0);
temp = const_binop (RSHIFT_EXPR, temp, size_int (modesize - p - 1), 0);
temp = const_binop (BIT_AND_EXPR, temp,
fold_convert (TREE_TYPE (c), mask), 0);
/* If necessary, convert the type back to match the type of C. */
- if (TREE_UNSIGNED (type))
+ if (TYPE_UNSIGNED (type))
temp = fold_convert (type, temp);
return fold_convert (type, const_binop (BIT_XOR_EXPR, c, temp, 0));
rcode = TREE_CODE (rhs);
if (lcode == BIT_AND_EXPR && integer_onep (TREE_OPERAND (lhs, 1)))
- lcode = NE_EXPR, lhs = build (NE_EXPR, truth_type, lhs, integer_zero_node);
+ {
+ lhs = build2 (NE_EXPR, truth_type, lhs, integer_zero_node);
+ lcode = NE_EXPR;
+ }
if (rcode == BIT_AND_EXPR && integer_onep (TREE_OPERAND (rhs, 1)))
- rcode = NE_EXPR, rhs = build (NE_EXPR, truth_type, rhs, integer_zero_node);
+ {
+ rhs = build2 (NE_EXPR, truth_type, rhs, integer_zero_node);
+ rcode = NE_EXPR;
+ }
if (TREE_CODE_CLASS (lcode) != '<' || TREE_CODE_CLASS (rcode) != '<')
return 0;
else if (compcode == COMPCODE_FALSE)
return fold_convert (truth_type, integer_zero_node);
else if (compcode != -1)
- return build (compcode_to_comparison (compcode),
- truth_type, ll_arg, lr_arg);
+ return build2 (compcode_to_comparison (compcode),
+ truth_type, ll_arg, lr_arg);
}
/* If the RHS can be evaluated unconditionally and its operands are
&& lcode == NE_EXPR && integer_zerop (lr_arg)
&& rcode == NE_EXPR && integer_zerop (rr_arg)
&& TREE_TYPE (ll_arg) == TREE_TYPE (rl_arg))
- return build (NE_EXPR, truth_type,
- build (BIT_IOR_EXPR, TREE_TYPE (ll_arg),
- ll_arg, rl_arg),
- integer_zero_node);
+ return build2 (NE_EXPR, truth_type,
+ build2 (BIT_IOR_EXPR, TREE_TYPE (ll_arg),
+ ll_arg, rl_arg),
+ integer_zero_node);
/* Convert (a == 0) && (b == 0) into (a | b) == 0. */
if (code == TRUTH_AND_EXPR
&& lcode == EQ_EXPR && integer_zerop (lr_arg)
&& rcode == EQ_EXPR && integer_zerop (rr_arg)
&& TREE_TYPE (ll_arg) == TREE_TYPE (rl_arg))
- return build (EQ_EXPR, truth_type,
- build (BIT_IOR_EXPR, TREE_TYPE (ll_arg),
- ll_arg, rl_arg),
- integer_zero_node);
+ return build2 (EQ_EXPR, truth_type,
+ build2 (BIT_IOR_EXPR, TREE_TYPE (ll_arg),
+ ll_arg, rl_arg),
+ integer_zero_node);
- return build (code, truth_type, lhs, rhs);
+ return build2 (code, truth_type, lhs, rhs);
}
/* See if the comparisons can be merged. Then get all the parameters for
/* After this point all optimizations will generate bit-field
references, which we might not want. */
- if (! (*lang_hooks.can_use_bit_fields_p) ())
+ if (! lang_hooks.can_use_bit_fields_p ())
return 0;
/* See if we can find a mode that contains both fields being compared on
lnbitsize = GET_MODE_BITSIZE (lnmode);
lnbitpos = first_bit & ~ (lnbitsize - 1);
- lntype = (*lang_hooks.types.type_for_size) (lnbitsize, 1);
+ lntype = lang_hooks.types.type_for_size (lnbitsize, 1);
xll_bitpos = ll_bitpos - lnbitpos, xrl_bitpos = rl_bitpos - lnbitpos;
if (BYTES_BIG_ENDIAN)
rnbitsize = GET_MODE_BITSIZE (rnmode);
rnbitpos = first_bit & ~ (rnbitsize - 1);
- rntype = (*lang_hooks.types.type_for_size) (rnbitsize, 1);
+ rntype = lang_hooks.types.type_for_size (rnbitsize, 1);
xlr_bitpos = lr_bitpos - rnbitpos, xrr_bitpos = rr_bitpos - rnbitpos;
if (BYTES_BIG_ENDIAN)
lhs = make_bit_field_ref (ll_inner, lntype, lnbitsize, lnbitpos,
ll_unsignedp || rl_unsignedp);
if (! all_ones_mask_p (ll_mask, lnbitsize))
- lhs = build (BIT_AND_EXPR, lntype, lhs, ll_mask);
+ lhs = build2 (BIT_AND_EXPR, lntype, lhs, ll_mask);
rhs = make_bit_field_ref (lr_inner, rntype, rnbitsize, rnbitpos,
lr_unsignedp || rr_unsignedp);
if (! all_ones_mask_p (lr_mask, rnbitsize))
- rhs = build (BIT_AND_EXPR, rntype, rhs, lr_mask);
+ rhs = build2 (BIT_AND_EXPR, rntype, rhs, lr_mask);
- return build (wanted_code, truth_type, lhs, rhs);
+ return build2 (wanted_code, truth_type, lhs, rhs);
}
/* There is still another way we can do something: If both pairs of
}
if (! all_ones_mask_p (ll_mask, ll_bitsize + rl_bitsize))
- lhs = build (BIT_AND_EXPR, type, lhs, ll_mask);
+ lhs = build2 (BIT_AND_EXPR, type, lhs, ll_mask);
if (! all_ones_mask_p (lr_mask, lr_bitsize + rr_bitsize))
- rhs = build (BIT_AND_EXPR, type, rhs, lr_mask);
+ rhs = build2 (BIT_AND_EXPR, type, rhs, lr_mask);
- return build (wanted_code, truth_type, lhs, rhs);
+ return build2 (wanted_code, truth_type, lhs, rhs);
}
return 0;
ll_mask = const_binop (BIT_IOR_EXPR, ll_mask, rl_mask, 0);
if (! all_ones_mask_p (ll_mask, lnbitsize))
- result = build (BIT_AND_EXPR, lntype, result, ll_mask);
+ result = build2 (BIT_AND_EXPR, lntype, result, ll_mask);
- return build (wanted_code, truth_type, result,
- const_binop (BIT_IOR_EXPR, l_const, r_const, 0));
+ return build2 (wanted_code, truth_type, result,
+ const_binop (BIT_IOR_EXPR, l_const, r_const, 0));
}
\f
/* Optimize T, which is a comparison of a MIN_EXPR or MAX_EXPR with a
case GE_EXPR:
return
- fold (build (TRUTH_ORIF_EXPR, type,
- optimize_minmax_comparison
- (build (EQ_EXPR, type, arg0, comp_const)),
- optimize_minmax_comparison
- (build (GT_EXPR, type, arg0, comp_const))));
+ fold (build2 (TRUTH_ORIF_EXPR, type,
+ optimize_minmax_comparison
+ (build2 (EQ_EXPR, type, arg0, comp_const)),
+ optimize_minmax_comparison
+ (build2 (GT_EXPR, type, arg0, comp_const))));
case EQ_EXPR:
if (op_code == MAX_EXPR && consts_equal)
/* MAX (X, 0) == 0 -> X <= 0 */
- return fold (build (LE_EXPR, type, inner, comp_const));
+ return fold (build2 (LE_EXPR, type, inner, comp_const));
else if (op_code == MAX_EXPR && consts_lt)
/* MAX (X, 0) == 5 -> X == 5 */
- return fold (build (EQ_EXPR, type, inner, comp_const));
+ return fold (build2 (EQ_EXPR, type, inner, comp_const));
else if (op_code == MAX_EXPR)
/* MAX (X, 0) == -1 -> false */
else if (consts_equal)
/* MIN (X, 0) == 0 -> X >= 0 */
- return fold (build (GE_EXPR, type, inner, comp_const));
+ return fold (build2 (GE_EXPR, type, inner, comp_const));
else if (consts_lt)
/* MIN (X, 0) == 5 -> false */
else
/* MIN (X, 0) == -1 -> X == -1 */
- return fold (build (EQ_EXPR, type, inner, comp_const));
+ return fold (build2 (EQ_EXPR, type, inner, comp_const));
case GT_EXPR:
if (op_code == MAX_EXPR && (consts_equal || consts_lt))
/* MAX (X, 0) > 0 -> X > 0
MAX (X, 0) > 5 -> X > 5 */
- return fold (build (GT_EXPR, type, inner, comp_const));
+ return fold (build2 (GT_EXPR, type, inner, comp_const));
else if (op_code == MAX_EXPR)
/* MAX (X, 0) > -1 -> true */
else
/* MIN (X, 0) > -1 -> X > -1 */
- return fold (build (GT_EXPR, type, inner, comp_const));
+ return fold (build2 (GT_EXPR, type, inner, comp_const));
default:
return t;
|| TREE_CODE_CLASS (TREE_CODE (op0)) == 'e')
/* ... and is unsigned, and its type is smaller than ctype,
then we cannot pass through as widening. */
- && ((TREE_UNSIGNED (TREE_TYPE (op0))
+ && ((TYPE_UNSIGNED (TREE_TYPE (op0))
&& ! (TREE_CODE (TREE_TYPE (op0)) == INTEGER_TYPE
&& TYPE_IS_SIZETYPE (TREE_TYPE (op0)))
&& (GET_MODE_SIZE (TYPE_MODE (ctype))
/* ... or signedness changes for division or modulus,
then we cannot pass through this conversion. */
|| (code != MULT_EXPR
- && (TREE_UNSIGNED (ctype)
- != TREE_UNSIGNED (TREE_TYPE (op0))))))
+ && (TYPE_UNSIGNED (ctype)
+ != TYPE_UNSIGNED (TREE_TYPE (op0))))))
break;
/* Pass the constant down and see if we can make a simplification. If
case MIN_EXPR: case MAX_EXPR:
/* If widening the type changes the signedness, then we can't perform
this optimization as that changes the result. */
- if (TREE_UNSIGNED (ctype) != TREE_UNSIGNED (type))
+ if (TYPE_UNSIGNED (ctype) != TYPE_UNSIGNED (type))
break;
/* MIN (a, b) / 5 -> MIN (a / 5, b / 5) */
if (tree_int_cst_sgn (c) < 0)
tcode = (tcode == MIN_EXPR ? MAX_EXPR : MIN_EXPR);
- return fold (build (tcode, ctype, fold_convert (ctype, t1),
- fold_convert (ctype, t2)));
+ return fold (build2 (tcode, ctype, fold_convert (ctype, t1),
+ fold_convert (ctype, t2)));
}
break;
- case WITH_RECORD_EXPR:
- if ((t1 = extract_muldiv (TREE_OPERAND (t, 0), c, code, wide_type)) != 0)
- return build (WITH_RECORD_EXPR, TREE_TYPE (t1), t1,
- TREE_OPERAND (t, 1));
- break;
-
case LSHIFT_EXPR: case RSHIFT_EXPR:
/* If the second operand is constant, this is a multiplication
or floor division, by a power of two, so we can treat it that
size_one_node,
op1, 0)))
&& ! TREE_OVERFLOW (t1))
- return extract_muldiv (build (tcode == LSHIFT_EXPR
- ? MULT_EXPR : FLOOR_DIV_EXPR,
- ctype, fold_convert (ctype, op0), t1),
+ return extract_muldiv (build2 (tcode == LSHIFT_EXPR
+ ? MULT_EXPR : FLOOR_DIV_EXPR,
+ ctype, fold_convert (ctype, op0), t1),
c, code, wide_type);
break;
are divisible by c. */
|| (multiple_of_p (ctype, op0, c)
&& multiple_of_p (ctype, op1, c))))
- return fold (build (tcode, ctype, fold_convert (ctype, t1),
- fold_convert (ctype, t2)));
+ return fold (build2 (tcode, ctype, fold_convert (ctype, t1),
+ fold_convert (ctype, t2)));
/* If this was a subtraction, negate OP1 and set it to be an addition.
This simplifies the logic below. */
/* If we have an unsigned type is not a sizetype, we cannot widen
the operation since it will change the result if the original
computation overflowed. */
- if (TREE_UNSIGNED (ctype)
+ if (TYPE_UNSIGNED (ctype)
&& ! (TREE_CODE (ctype) == INTEGER_TYPE && TYPE_IS_SIZETYPE (ctype))
&& ctype != type)
break;
/* If we were able to eliminate our operation from the first side,
apply our operation to the second side and reform the PLUS. */
if (t1 != 0 && (TREE_CODE (t1) != code || code == MULT_EXPR))
- return fold (build (tcode, ctype, fold_convert (ctype, t1), op1));
+ return fold (build2 (tcode, ctype, fold_convert (ctype, t1), op1));
/* The last case is if we are a multiply. In that case, we can
apply the distributive law to commute the multiply and addition
if the multiplication of the constants doesn't overflow. */
if (code == MULT_EXPR)
- return fold (build (tcode, ctype,
- fold (build (code, ctype,
- fold_convert (ctype, op0),
- fold_convert (ctype, c))),
- op1));
+ return fold (build2 (tcode, ctype,
+ fold (build2 (code, ctype,
+ fold_convert (ctype, op0),
+ fold_convert (ctype, c))),
+ op1));
break;
do something only if the second operand is a constant. */
if (same_p
&& (t1 = extract_muldiv (op0, c, code, wide_type)) != 0)
- return fold (build (tcode, ctype, fold_convert (ctype, t1),
- fold_convert (ctype, op1)));
+ return fold (build2 (tcode, ctype, fold_convert (ctype, t1),
+ fold_convert (ctype, op1)));
else if (tcode == MULT_EXPR && code == MULT_EXPR
&& (t1 = extract_muldiv (op1, c, code, wide_type)) != 0)
- return fold (build (tcode, ctype, fold_convert (ctype, op0),
- fold_convert (ctype, t1)));
+ return fold (build2 (tcode, ctype, fold_convert (ctype, op0),
+ fold_convert (ctype, t1)));
else if (TREE_CODE (op1) != INTEGER_CST)
return 0;
&& 0 != (t1 = const_binop (MULT_EXPR, fold_convert (ctype, op1),
fold_convert (ctype, c), 0))
&& ! TREE_OVERFLOW (t1))
- return fold (build (tcode, ctype, fold_convert (ctype, op0), t1));
+ return fold (build2 (tcode, ctype, fold_convert (ctype, op0), t1));
/* If these operations "cancel" each other, we have the main
optimizations of this pass, which occur when either constant is a
If we have an unsigned type that is not a sizetype, we cannot do
this since it will change the result if the original computation
overflowed. */
- if ((! TREE_UNSIGNED (ctype)
+ if ((! TYPE_UNSIGNED (ctype)
|| (TREE_CODE (ctype) == INTEGER_TYPE && TYPE_IS_SIZETYPE (ctype)))
&& ! flag_wrapv
&& ((code == MULT_EXPR && tcode == EXACT_DIV_EXPR)
&& code != FLOOR_MOD_EXPR && code != ROUND_MOD_EXPR)))
{
if (integer_zerop (const_binop (TRUNC_MOD_EXPR, op1, c, 0)))
- return fold (build (tcode, ctype, fold_convert (ctype, op0),
- fold_convert (ctype,
- const_binop (TRUNC_DIV_EXPR,
- op1, c, 0))));
+ return fold (build2 (tcode, ctype, fold_convert (ctype, op0),
+ fold_convert (ctype,
+ const_binop (TRUNC_DIV_EXPR,
+ op1, c, 0))));
else if (integer_zerop (const_binop (TRUNC_MOD_EXPR, c, op1, 0)))
- return fold (build (code, ctype, fold_convert (ctype, op0),
- fold_convert (ctype,
- const_binop (TRUNC_DIV_EXPR,
- c, op1, 0))));
+ return fold (build2 (code, ctype, fold_convert (ctype, op0),
+ fold_convert (ctype,
+ const_binop (TRUNC_DIV_EXPR,
+ c, op1, 0))));
}
break;
return 0;
}
\f
-/* If T contains a COMPOUND_EXPR which was inserted merely to evaluate
- S, a SAVE_EXPR, return the expression actually being evaluated. Note
- that we may sometimes modify the tree. */
-
-static tree
-strip_compound_expr (tree t, tree s)
-{
- enum tree_code code = TREE_CODE (t);
-
- /* See if this is the COMPOUND_EXPR we want to eliminate. */
- if (code == COMPOUND_EXPR && TREE_CODE (TREE_OPERAND (t, 0)) == CONVERT_EXPR
- && TREE_OPERAND (TREE_OPERAND (t, 0), 0) == s)
- return TREE_OPERAND (t, 1);
-
- /* See if this is a COND_EXPR or a simple arithmetic operator. We
- don't bother handling any other types. */
- else if (code == COND_EXPR)
- {
- TREE_OPERAND (t, 0) = strip_compound_expr (TREE_OPERAND (t, 0), s);
- TREE_OPERAND (t, 1) = strip_compound_expr (TREE_OPERAND (t, 1), s);
- TREE_OPERAND (t, 2) = strip_compound_expr (TREE_OPERAND (t, 2), s);
- }
- else if (TREE_CODE_CLASS (code) == '1')
- TREE_OPERAND (t, 0) = strip_compound_expr (TREE_OPERAND (t, 0), s);
- else if (TREE_CODE_CLASS (code) == '<'
- || TREE_CODE_CLASS (code) == '2')
- {
- TREE_OPERAND (t, 0) = strip_compound_expr (TREE_OPERAND (t, 0), s);
- TREE_OPERAND (t, 1) = strip_compound_expr (TREE_OPERAND (t, 1), s);
- }
-
- return t;
-}
-\f
/* Return a node which has the indicated constant VALUE (either 0 or
1), and is of the indicated TYPE. */
if (type == integer_type_node)
return value ? integer_one_node : integer_zero_node;
else if (TREE_CODE (type) == BOOLEAN_TYPE)
- return (*lang_hooks.truthvalue_conversion) (value ? integer_one_node :
- integer_zero_node);
+ return lang_hooks.truthvalue_conversion (value ? integer_one_node
+ : integer_zero_node);
else
{
tree t = build_int_2 (value, 0);
}
}
-/* Utility function for the following routine, to see how complex a nesting of
- COND_EXPRs can be. EXPR is the expression and LIMIT is a count beyond which
- we don't care (to avoid spending too much time on complex expressions.). */
-
-static int
-count_cond (tree expr, int lim)
-{
- int ctrue, cfalse;
-
- if (TREE_CODE (expr) != COND_EXPR)
- return 0;
- else if (lim <= 0)
- return 0;
-
- ctrue = count_cond (TREE_OPERAND (expr, 1), lim - 1);
- cfalse = count_cond (TREE_OPERAND (expr, 2), lim - 1 - ctrue);
- return MIN (lim, 1 + ctrue + cfalse);
-}
-
/* Transform `a + (b ? x : y)' into `b ? (a + x) : (a + y)'.
Transform, `a + (x < y)' into `(x < y) ? (a + 1) : (a + 0)'. Here
CODE corresponds to the `+', COND to the `(b ? x : y)' or `(x < y)'
expression, and ARG to `a'. If COND_FIRST_P is nonzero, then the
COND is the first argument to CODE; otherwise (as in the example
given here), it is the second argument. TYPE is the type of the
- original expression. */
+ original expression. Return NULL_TREE if no simplification is
+ possible. */
static tree
fold_binary_op_with_conditional_arg (enum tree_code code, tree type,
tree test, true_value, false_value;
tree lhs = NULL_TREE;
tree rhs = NULL_TREE;
- /* In the end, we'll produce a COND_EXPR. Both arms of the
- conditional expression will be binary operations. The left-hand
- side of the expression to be executed if the condition is true
- will be pointed to by TRUE_LHS. Similarly, the right-hand side
- of the expression to be executed if the condition is true will be
- pointed to by TRUE_RHS. FALSE_LHS and FALSE_RHS are analogous --
- but apply to the expression to be executed if the conditional is
- false. */
- tree *true_lhs;
- tree *true_rhs;
- tree *false_lhs;
- tree *false_rhs;
- /* These are the codes to use for the left-hand side and right-hand
- side of the COND_EXPR. Normally, they are the same as CODE. */
- enum tree_code lhs_code = code;
- enum tree_code rhs_code = code;
- /* And these are the types of the expressions. */
- tree lhs_type = type;
- tree rhs_type = type;
- int save = 0;
-
- if (cond_first_p)
- {
- true_rhs = false_rhs = &arg;
- true_lhs = &true_value;
- false_lhs = &false_value;
- }
- else
- {
- true_lhs = false_lhs = &arg;
- true_rhs = &true_value;
- false_rhs = &false_value;
- }
+
+ /* This transformation is only worthwhile if we don't have to wrap
+ arg in a SAVE_EXPR, and the operation can be simplified on atleast
+ one of the branches once its pushed inside the COND_EXPR. */
+ if (!TREE_CONSTANT (arg))
+ return NULL_TREE;
if (TREE_CODE (cond) == COND_EXPR)
{
false_value = TREE_OPERAND (cond, 2);
/* If this operand throws an expression, then it does not make
sense to try to perform a logical or arithmetic operation
- involving it. Instead of building `a + throw 3' for example,
- we simply build `a, throw 3'. */
+ involving it. */
if (VOID_TYPE_P (TREE_TYPE (true_value)))
- {
- if (! cond_first_p)
- {
- lhs_code = COMPOUND_EXPR;
- lhs_type = void_type_node;
- }
- else
- lhs = true_value;
- }
+ lhs = true_value;
if (VOID_TYPE_P (TREE_TYPE (false_value)))
- {
- if (! cond_first_p)
- {
- rhs_code = COMPOUND_EXPR;
- rhs_type = void_type_node;
- }
- else
- rhs = false_value;
- }
+ rhs = false_value;
}
else
{
false_value = fold_convert (testtype, integer_zero_node);
}
- /* If ARG is complex we want to make sure we only evaluate it once. Though
- this is only required if it is volatile, it might be more efficient even
- if it is not. However, if we succeed in folding one part to a constant,
- we do not need to make this SAVE_EXPR. Since we do this optimization
- primarily to see if we do end up with constant and this SAVE_EXPR
- interferes with later optimizations, suppressing it when we can is
- important.
-
- If we are not in a function, we can't make a SAVE_EXPR, so don't try to
- do so. Don't try to see if the result is a constant if an arm is a
- COND_EXPR since we get exponential behavior in that case. */
-
- if (saved_expr_p (arg))
- save = 1;
- else if (lhs == 0 && rhs == 0
- && !TREE_CONSTANT (arg)
- && (*lang_hooks.decls.global_bindings_p) () == 0
- && ((TREE_CODE (arg) != VAR_DECL && TREE_CODE (arg) != PARM_DECL)
- || TREE_SIDE_EFFECTS (arg)))
- {
- if (TREE_CODE (true_value) != COND_EXPR)
- lhs = fold (build (lhs_code, lhs_type, *true_lhs, *true_rhs));
-
- if (TREE_CODE (false_value) != COND_EXPR)
- rhs = fold (build (rhs_code, rhs_type, *false_lhs, *false_rhs));
-
- if ((lhs == 0 || ! TREE_CONSTANT (lhs))
- && (rhs == 0 || !TREE_CONSTANT (rhs)))
- {
- arg = save_expr (arg);
- lhs = rhs = 0;
- save = saved_expr_p (arg);
- }
- }
-
if (lhs == 0)
- lhs = fold (build (lhs_code, lhs_type, *true_lhs, *true_rhs));
+ lhs = fold (cond_first_p ? build2 (code, type, true_value, arg)
+ : build2 (code, type, arg, true_value));
if (rhs == 0)
- rhs = fold (build (rhs_code, rhs_type, *false_lhs, *false_rhs));
-
- test = fold (build (COND_EXPR, type, test, lhs, rhs));
-
- /* If ARG involves a SAVE_EXPR, we need to ensure it is evaluated
- ahead of the COND_EXPR we made. Otherwise we would have it only
- evaluated in one branch, with the other branch using the result
- but missing the evaluation code. Beware that the save_expr call
- above might not return a SAVE_EXPR, so testing the TREE_CODE
- of ARG is not enough to decide here. Â */
- if (save)
- return build (COMPOUND_EXPR, type,
- fold_convert (void_type_node, arg),
- strip_compound_expr (test, arg));
- else
- return fold_convert (type, test);
+ rhs = fold (cond_first_p ? build2 (code, type, false_value, arg)
+ : build2 (code, type, arg, false_value));
+
+ test = fold (build3 (COND_EXPR, type, test, lhs, rhs));
+ return fold_convert (type, test);
}
\f
{
REAL_VALUE_TYPE c;
- if (fcode == BUILT_IN_SQRT
- || fcode == BUILT_IN_SQRTF
- || fcode == BUILT_IN_SQRTL)
+ if (BUILTIN_SQRT_P (fcode))
{
tree arg = TREE_VALUE (TREE_OPERAND (arg0, 1));
enum machine_mode mode = TYPE_MODE (TREE_TYPE (arg0));
arg);
/* sqrt(x) > y is the same as x >= 0, if y is negative. */
- return fold (build (GE_EXPR, type, arg,
- build_real (TREE_TYPE (arg), dconst0)));
+ return fold (build2 (GE_EXPR, type, arg,
+ build_real (TREE_TYPE (arg), dconst0)));
}
else if (code == GT_EXPR || code == GE_EXPR)
{
{
/* sqrt(x) > y is x == +Inf, when y is very large. */
if (HONOR_INFINITIES (mode))
- return fold (build (EQ_EXPR, type, arg,
- build_real (TREE_TYPE (arg), c2)));
+ return fold (build2 (EQ_EXPR, type, arg,
+ build_real (TREE_TYPE (arg), c2)));
/* sqrt(x) > y is always false, when y is very large
and we don't care about infinities. */
}
/* sqrt(x) > c is the same as x > c*c. */
- return fold (build (code, type, arg,
- build_real (TREE_TYPE (arg), c2)));
+ return fold (build2 (code, type, arg,
+ build_real (TREE_TYPE (arg), c2)));
}
else if (code == LT_EXPR || code == LE_EXPR)
{
/* sqrt(x) < y is x != +Inf when y is very large and we
don't care about NaNs. */
if (! HONOR_NANS (mode))
- return fold (build (NE_EXPR, type, arg,
- build_real (TREE_TYPE (arg), c2)));
+ return fold (build2 (NE_EXPR, type, arg,
+ build_real (TREE_TYPE (arg), c2)));
/* sqrt(x) < y is x >= 0 when y is very large and we
don't care about Infinities. */
if (! HONOR_INFINITIES (mode))
- return fold (build (GE_EXPR, type, arg,
- build_real (TREE_TYPE (arg), dconst0)));
+ return fold (build2 (GE_EXPR, type, arg,
+ build_real (TREE_TYPE (arg), dconst0)));
/* sqrt(x) < y is x >= 0 && x != +Inf, when y is large. */
- if ((*lang_hooks.decls.global_bindings_p) () != 0
+ if (lang_hooks.decls.global_bindings_p () != 0
|| CONTAINS_PLACEHOLDER_P (arg))
return NULL_TREE;
arg = save_expr (arg);
- return fold (build (TRUTH_ANDIF_EXPR, type,
- fold (build (GE_EXPR, type, arg,
- build_real (TREE_TYPE (arg),
- dconst0))),
- fold (build (NE_EXPR, type, arg,
- build_real (TREE_TYPE (arg),
- c2)))));
+ return fold (build2 (TRUTH_ANDIF_EXPR, type,
+ fold (build2 (GE_EXPR, type, arg,
+ build_real (TREE_TYPE (arg),
+ dconst0))),
+ fold (build2 (NE_EXPR, type, arg,
+ build_real (TREE_TYPE (arg),
+ c2)))));
}
/* sqrt(x) < c is the same as x < c*c, if we ignore NaNs. */
if (! HONOR_NANS (mode))
- return fold (build (code, type, arg,
- build_real (TREE_TYPE (arg), c2)));
+ return fold (build2 (code, type, arg,
+ build_real (TREE_TYPE (arg), c2)));
/* sqrt(x) < c is the same as x >= 0 && x < c*c. */
- if ((*lang_hooks.decls.global_bindings_p) () == 0
+ if (lang_hooks.decls.global_bindings_p () == 0
&& ! CONTAINS_PLACEHOLDER_P (arg))
{
arg = save_expr (arg);
- return fold (build (TRUTH_ANDIF_EXPR, type,
- fold (build (GE_EXPR, type, arg,
- build_real (TREE_TYPE (arg),
- dconst0))),
- fold (build (code, type, arg,
- build_real (TREE_TYPE (arg),
- c2)))));
+ return fold (build2 (TRUTH_ANDIF_EXPR, type,
+ fold (build2 (GE_EXPR, type, arg,
+ build_real (TREE_TYPE (arg),
+ dconst0))),
+ fold (build2 (code, type, arg,
+ build_real (TREE_TYPE (arg),
+ c2)))));
}
}
}
arg0);
/* x <= +Inf is the same as x == x, i.e. isfinite(x). */
- if ((*lang_hooks.decls.global_bindings_p) () == 0
+ if (lang_hooks.decls.global_bindings_p () == 0
&& ! CONTAINS_PLACEHOLDER_P (arg0))
{
arg0 = save_expr (arg0);
- return fold (build (EQ_EXPR, type, arg0, arg0));
+ return fold (build2 (EQ_EXPR, type, arg0, arg0));
}
break;
case GE_EXPR:
/* x == +Inf and x >= +Inf are always equal to x > DBL_MAX. */
real_maxval (&max, neg, mode);
- return fold (build (neg ? LT_EXPR : GT_EXPR, type,
- arg0, build_real (TREE_TYPE (arg0), max)));
+ return fold (build2 (neg ? LT_EXPR : GT_EXPR, type,
+ arg0, build_real (TREE_TYPE (arg0), max)));
case LT_EXPR:
/* x < +Inf is always equal to x <= DBL_MAX. */
real_maxval (&max, neg, mode);
- return fold (build (neg ? GE_EXPR : LE_EXPR, type,
- arg0, build_real (TREE_TYPE (arg0), max)));
+ return fold (build2 (neg ? GE_EXPR : LE_EXPR, type,
+ arg0, build_real (TREE_TYPE (arg0), max)));
case NE_EXPR:
/* x != +Inf is always equal to !(x > DBL_MAX). */
real_maxval (&max, neg, mode);
if (! HONOR_NANS (mode))
- return fold (build (neg ? GE_EXPR : LE_EXPR, type,
- arg0, build_real (TREE_TYPE (arg0), max)));
- temp = fold (build (neg ? LT_EXPR : GT_EXPR, type,
- arg0, build_real (TREE_TYPE (arg0), max)));
+ return fold (build2 (neg ? GE_EXPR : LE_EXPR, type,
+ arg0, build_real (TREE_TYPE (arg0), max)));
+ temp = fold (build2 (neg ? LT_EXPR : GT_EXPR, type,
+ arg0, build_real (TREE_TYPE (arg0), max)));
return fold (build1 (TRUTH_NOT_EXPR, type, temp));
default:
return NULL_TREE;
}
+/* Subroutine of fold() that optimizes comparisons of a division by
+ a non-zero integer constant against an integer constant, i.e.
+ X/C1 op C2.
+
+ CODE is the comparison operator: EQ_EXPR, NE_EXPR, GT_EXPR, LT_EXPR,
+ GE_EXPR or LE_EXPR. TYPE is the type of the result and ARG0 and ARG1
+ are the operands of the comparison. ARG1 must be a TREE_REAL_CST.
+
+ The function returns the constant folded tree if a simplification
+ can be made, and NULL_TREE otherwise. */
+
+static tree
+fold_div_compare (enum tree_code code, tree type, tree arg0, tree arg1)
+{
+ tree prod, tmp, hi, lo;
+ tree arg00 = TREE_OPERAND (arg0, 0);
+ tree arg01 = TREE_OPERAND (arg0, 1);
+ unsigned HOST_WIDE_INT lpart;
+ HOST_WIDE_INT hpart;
+ int overflow;
+
+ /* We have to do this the hard way to detect unsigned overflow.
+ prod = int_const_binop (MULT_EXPR, arg01, arg1, 0); */
+ overflow = mul_double (TREE_INT_CST_LOW (arg01),
+ TREE_INT_CST_HIGH (arg01),
+ TREE_INT_CST_LOW (arg1),
+ TREE_INT_CST_HIGH (arg1), &lpart, &hpart);
+ prod = build_int_2 (lpart, hpart);
+ TREE_TYPE (prod) = TREE_TYPE (arg00);
+ TREE_OVERFLOW (prod) = force_fit_type (prod, overflow)
+ || TREE_INT_CST_HIGH (prod) != hpart
+ || TREE_INT_CST_LOW (prod) != lpart;
+ TREE_CONSTANT_OVERFLOW (prod) = TREE_OVERFLOW (prod);
+
+ if (TYPE_UNSIGNED (TREE_TYPE (arg0)))
+ {
+ tmp = int_const_binop (MINUS_EXPR, arg01, integer_one_node, 0);
+ lo = prod;
+
+ /* Likewise hi = int_const_binop (PLUS_EXPR, prod, tmp, 0). */
+ overflow = add_double (TREE_INT_CST_LOW (prod),
+ TREE_INT_CST_HIGH (prod),
+ TREE_INT_CST_LOW (tmp),
+ TREE_INT_CST_HIGH (tmp),
+ &lpart, &hpart);
+ hi = build_int_2 (lpart, hpart);
+ TREE_TYPE (hi) = TREE_TYPE (arg00);
+ TREE_OVERFLOW (hi) = force_fit_type (hi, overflow)
+ || TREE_INT_CST_HIGH (hi) != hpart
+ || TREE_INT_CST_LOW (hi) != lpart
+ || TREE_OVERFLOW (prod);
+ TREE_CONSTANT_OVERFLOW (hi) = TREE_OVERFLOW (hi);
+ }
+ else if (tree_int_cst_sgn (arg01) >= 0)
+ {
+ tmp = int_const_binop (MINUS_EXPR, arg01, integer_one_node, 0);
+ switch (tree_int_cst_sgn (arg1))
+ {
+ case -1:
+ lo = int_const_binop (MINUS_EXPR, prod, tmp, 0);
+ hi = prod;
+ break;
+
+ case 0:
+ lo = fold_negate_const (tmp, TREE_TYPE (arg0));
+ hi = tmp;
+ break;
+
+ case 1:
+ hi = int_const_binop (PLUS_EXPR, prod, tmp, 0);
+ lo = prod;
+ break;
+
+ default:
+ abort ();
+ }
+ }
+ else
+ {
+ tmp = int_const_binop (PLUS_EXPR, arg01, integer_one_node, 0);
+ switch (tree_int_cst_sgn (arg1))
+ {
+ case -1:
+ hi = int_const_binop (MINUS_EXPR, prod, tmp, 0);
+ lo = prod;
+ break;
+
+ case 0:
+ hi = fold_negate_const (tmp, TREE_TYPE (arg0));
+ lo = tmp;
+ break;
+
+ case 1:
+ lo = int_const_binop (PLUS_EXPR, prod, tmp, 0);
+ hi = prod;
+ break;
+
+ default:
+ abort ();
+ }
+ }
+
+ switch (code)
+ {
+ case EQ_EXPR:
+ if (TREE_OVERFLOW (lo) && TREE_OVERFLOW (hi))
+ return omit_one_operand (type, integer_zero_node, arg00);
+ if (TREE_OVERFLOW (hi))
+ return fold (build2 (GE_EXPR, type, arg00, lo));
+ if (TREE_OVERFLOW (lo))
+ return fold (build2 (LE_EXPR, type, arg00, hi));
+ return build_range_check (type, arg00, 1, lo, hi);
+
+ case NE_EXPR:
+ if (TREE_OVERFLOW (lo) && TREE_OVERFLOW (hi))
+ return omit_one_operand (type, integer_one_node, arg00);
+ if (TREE_OVERFLOW (hi))
+ return fold (build2 (LT_EXPR, type, arg00, lo));
+ if (TREE_OVERFLOW (lo))
+ return fold (build2 (GT_EXPR, type, arg00, hi));
+ return build_range_check (type, arg00, 0, lo, hi);
+
+ case LT_EXPR:
+ if (TREE_OVERFLOW (lo))
+ return omit_one_operand (type, integer_zero_node, arg00);
+ return fold (build2 (LT_EXPR, type, arg00, lo));
+
+ case LE_EXPR:
+ if (TREE_OVERFLOW (hi))
+ return omit_one_operand (type, integer_one_node, arg00);
+ return fold (build2 (LE_EXPR, type, arg00, hi));
+
+ case GT_EXPR:
+ if (TREE_OVERFLOW (hi))
+ return omit_one_operand (type, integer_zero_node, arg00);
+ return fold (build2 (GT_EXPR, type, arg00, hi));
+
+ case GE_EXPR:
+ if (TREE_OVERFLOW (lo))
+ return omit_one_operand (type, integer_one_node, arg00);
+ return fold (build2 (GE_EXPR, type, arg00, lo));
+
+ default:
+ break;
+ }
+
+ return NULL_TREE;
+}
+
+
/* If CODE with arguments ARG0 and ARG1 represents a single bit
equality/inequality test, then return a simplified form of
the test using shifts and logical operations. Otherwise return
arg00 = sign_bit_p (TREE_OPERAND (arg0, 0), TREE_OPERAND (arg0, 1));
if (arg00 != NULL_TREE)
{
- tree stype = (*lang_hooks.types.signed_type) (TREE_TYPE (arg00));
- return fold (build (code == EQ_EXPR ? GE_EXPR : LT_EXPR, result_type,
- fold_convert (stype, arg00),
- fold_convert (stype, integer_zero_node)));
+ tree stype = lang_hooks.types.signed_type (TREE_TYPE (arg00));
+ return fold (build2 (code == EQ_EXPR ? GE_EXPR : LT_EXPR,
+ result_type, fold_convert (stype, arg00),
+ fold_convert (stype, integer_zero_node)));
}
/* At this point, we know that arg0 is not testing the sign bit. */
ops_unsigned = 1;
#endif
- signed_type = (*lang_hooks.types.type_for_mode) (operand_mode, 0);
- unsigned_type = (*lang_hooks.types.type_for_mode) (operand_mode, 1);
+ signed_type = lang_hooks.types.type_for_mode (operand_mode, 0);
+ unsigned_type = lang_hooks.types.type_for_mode (operand_mode, 1);
intermediate_type = ops_unsigned ? unsigned_type : signed_type;
inner = fold_convert (intermediate_type, inner);
if (bitnum != 0)
- inner = build (RSHIFT_EXPR, intermediate_type,
- inner, size_int (bitnum));
+ inner = build2 (RSHIFT_EXPR, intermediate_type,
+ inner, size_int (bitnum));
if (code == EQ_EXPR)
- inner = build (BIT_XOR_EXPR, intermediate_type,
- inner, integer_one_node);
+ inner = build2 (BIT_XOR_EXPR, intermediate_type,
+ inner, integer_one_node);
/* Put the AND last so it can combine with more things. */
- inner = build (BIT_AND_EXPR, intermediate_type,
- inner, integer_one_node);
+ inner = build2 (BIT_AND_EXPR, intermediate_type,
+ inner, integer_one_node);
/* Make sure to return the proper type. */
inner = fold_convert (result_type, inner);
if (DECL_P (arg0))
return 1;
+ if (reorder && flag_evaluation_order
+ && (TREE_SIDE_EFFECTS (arg0) || TREE_SIDE_EFFECTS (arg1)))
+ return 0;
+
+ if (DECL_P (arg1))
+ return 0;
+ if (DECL_P (arg0))
+ return 1;
+
return 0;
}
The related simplifications include x*1 => x, x*0 => 0, etc.,
and application of the associative law.
NOP_EXPR conversions may be removed freely (as long as we
- are careful not to change the C type of the overall expression)
+ are careful not to change the type of the overall expression).
We cannot simplify through a CONVERT_EXPR, FIX_EXPR or FLOAT_EXPR,
but we can constant-fold them if they have constant operands. */
tree
fold (tree expr)
{
- tree t = expr, orig_t;
+ const tree t = expr;
+ const tree type = TREE_TYPE (expr);
tree t1 = NULL_TREE;
tree tem;
- tree type = TREE_TYPE (expr);
tree arg0 = NULL_TREE, arg1 = NULL_TREE;
enum tree_code code = TREE_CODE (t);
int kind = TREE_CODE_CLASS (code);
- int invert;
+
/* WINS will be nonzero when the switch is done
if all operands are constant. */
int wins = 1;
if (kind == 'c')
return t;
- orig_t = t;
-
if (code == NOP_EXPR || code == FLOAT_EXPR || code == CONVERT_EXPR)
{
tree subop;
if (op == 0)
continue; /* Valid for CALL_EXPR, at least. */
- if (kind == '<' || code == RSHIFT_EXPR)
- {
- /* Signedness matters here. Perhaps we can refine this
- later. */
- STRIP_SIGN_NOPS (op);
- }
+ /* Strip any conversions that don't change the mode. This is
+ safe for every expression, except for a comparison expression
+ because its signedness is derived from its operands. So, in
+ the latter case, only strip conversions that don't change the
+ signedness.
+
+ Note that this is done as an internal manipulation within the
+ constant folder, in order to find the simplest representation
+ of the arguments so that their form can be studied. In any
+ cases, the appropriate type conversions should be put back in
+ the tree that will get out of the constant folder. */
+ if (kind == '<')
+ STRIP_SIGN_NOPS (op);
else
- /* Strip any conversions that don't change the mode. */
STRIP_NOPS (op);
if (TREE_CODE (op) == COMPLEX_CST)
to ARG1 to reduce the number of tests below. */
if (commutative_tree_code (code)
&& tree_swap_operands_p (arg0, arg1, true))
- return fold (build (code, type, arg1, arg0));
+ return fold (build2 (code, type, TREE_OPERAND (t, 1),
+ TREE_OPERAND (t, 0)));
/* Now WINS is set as described above,
ARG0 is the first operand of EXPR,
|| (TREE_CODE (arg0) == BIT_AND_EXPR
&& integer_onep (TREE_OPERAND (arg0, 1)))))))
{
- t = fold (build (code == BIT_AND_EXPR ? TRUTH_AND_EXPR
- : code == BIT_IOR_EXPR ? TRUTH_OR_EXPR
- : TRUTH_XOR_EXPR,
- type, arg0, arg1));
+ tem = fold (build2 (code == BIT_AND_EXPR ? TRUTH_AND_EXPR
+ : code == BIT_IOR_EXPR ? TRUTH_OR_EXPR
+ : TRUTH_XOR_EXPR,
+ type, fold_convert (boolean_type_node, arg0),
+ fold_convert (boolean_type_node, arg1)));
if (code == EQ_EXPR)
- t = invert_truthvalue (t);
+ tem = invert_truthvalue (tem);
- return t;
+ return tem;
}
if (TREE_CODE_CLASS (code) == '1')
{
if (TREE_CODE (arg0) == COMPOUND_EXPR)
- return build (COMPOUND_EXPR, type, TREE_OPERAND (arg0, 0),
- fold (build1 (code, type, TREE_OPERAND (arg0, 1))));
+ return build2 (COMPOUND_EXPR, type, TREE_OPERAND (arg0, 0),
+ fold (build1 (code, type, TREE_OPERAND (arg0, 1))));
else if (TREE_CODE (arg0) == COND_EXPR)
{
tree arg01 = TREE_OPERAND (arg0, 1);
arg01 = fold (build1 (code, type, arg01));
if (! VOID_TYPE_P (TREE_TYPE (arg02)))
arg02 = fold (build1 (code, type, arg02));
- t = fold (build (COND_EXPR, type, TREE_OPERAND (arg0, 0),
- arg01, arg02));
+ tem = fold (build3 (COND_EXPR, type, TREE_OPERAND (arg0, 0),
+ arg01, arg02));
/* If this was a conversion, and all we did was to move into
inside the COND_EXPR, bring it back out. But leave it if
if ((code == NOP_EXPR || code == CONVERT_EXPR
|| code == NON_LVALUE_EXPR)
- && TREE_CODE (t) == COND_EXPR
- && TREE_CODE (TREE_OPERAND (t, 1)) == code
- && TREE_CODE (TREE_OPERAND (t, 2)) == code
- && ! VOID_TYPE_P (TREE_OPERAND (t, 1))
- && ! VOID_TYPE_P (TREE_OPERAND (t, 2))
- && (TREE_TYPE (TREE_OPERAND (TREE_OPERAND (t, 1), 0))
- == TREE_TYPE (TREE_OPERAND (TREE_OPERAND (t, 2), 0)))
- && ! (INTEGRAL_TYPE_P (TREE_TYPE (t))
+ && TREE_CODE (tem) == COND_EXPR
+ && TREE_CODE (TREE_OPERAND (tem, 1)) == code
+ && TREE_CODE (TREE_OPERAND (tem, 2)) == code
+ && ! VOID_TYPE_P (TREE_OPERAND (tem, 1))
+ && ! VOID_TYPE_P (TREE_OPERAND (tem, 2))
+ && (TREE_TYPE (TREE_OPERAND (TREE_OPERAND (tem, 1), 0))
+ == TREE_TYPE (TREE_OPERAND (TREE_OPERAND (tem, 2), 0)))
+ && ! (INTEGRAL_TYPE_P (TREE_TYPE (tem))
&& (INTEGRAL_TYPE_P
- (TREE_TYPE (TREE_OPERAND (TREE_OPERAND (t, 1), 0))))
- && TYPE_PRECISION (TREE_TYPE (t)) <= BITS_PER_WORD))
- t = build1 (code, type,
- build (COND_EXPR,
- TREE_TYPE (TREE_OPERAND
- (TREE_OPERAND (t, 1), 0)),
- TREE_OPERAND (t, 0),
- TREE_OPERAND (TREE_OPERAND (t, 1), 0),
- TREE_OPERAND (TREE_OPERAND (t, 2), 0)));
- return t;
+ (TREE_TYPE (TREE_OPERAND (TREE_OPERAND (tem, 1), 0))))
+ && TYPE_PRECISION (TREE_TYPE (tem)) <= BITS_PER_WORD))
+ tem = build1 (code, type,
+ build3 (COND_EXPR,
+ TREE_TYPE (TREE_OPERAND
+ (TREE_OPERAND (tem, 1), 0)),
+ TREE_OPERAND (tem, 0),
+ TREE_OPERAND (TREE_OPERAND (tem, 1), 0),
+ TREE_OPERAND (TREE_OPERAND (tem, 2), 0)));
+ return tem;
}
else if (TREE_CODE_CLASS (TREE_CODE (arg0)) == '<')
- return fold (build (COND_EXPR, type, arg0,
- fold (build1 (code, type, integer_one_node)),
- fold (build1 (code, type, integer_zero_node))));
+ {
+ if (TREE_CODE (type) == BOOLEAN_TYPE)
+ {
+ arg0 = copy_node (arg0);
+ TREE_TYPE (arg0) = type;
+ return arg0;
+ }
+ else if (TREE_CODE (type) != INTEGER_TYPE)
+ return fold (build3 (COND_EXPR, type, arg0,
+ fold (build1 (code, type,
+ integer_one_node)),
+ fold (build1 (code, type,
+ integer_zero_node))));
+ }
}
else if (TREE_CODE_CLASS (code) == '<'
&& TREE_CODE (arg0) == COMPOUND_EXPR)
- return build (COMPOUND_EXPR, type, TREE_OPERAND (arg0, 0),
- fold (build (code, type, TREE_OPERAND (arg0, 1), arg1)));
+ return build2 (COMPOUND_EXPR, type, TREE_OPERAND (arg0, 0),
+ fold (build2 (code, type, TREE_OPERAND (arg0, 1), arg1)));
else if (TREE_CODE_CLASS (code) == '<'
&& TREE_CODE (arg1) == COMPOUND_EXPR)
- return build (COMPOUND_EXPR, type, TREE_OPERAND (arg1, 0),
- fold (build (code, type, arg0, TREE_OPERAND (arg1, 1))));
+ return build2 (COMPOUND_EXPR, type, TREE_OPERAND (arg1, 0),
+ fold (build2 (code, type, arg0, TREE_OPERAND (arg1, 1))));
else if (TREE_CODE_CLASS (code) == '2'
|| TREE_CODE_CLASS (code) == '<')
{
+ if (TREE_CODE (arg0) == COMPOUND_EXPR)
+ return build2 (COMPOUND_EXPR, type, TREE_OPERAND (arg0, 0),
+ fold (build2 (code, type, TREE_OPERAND (arg0, 1),
+ arg1)));
if (TREE_CODE (arg1) == COMPOUND_EXPR
- && ! TREE_SIDE_EFFECTS (TREE_OPERAND (arg1, 0))
- && ! TREE_SIDE_EFFECTS (arg0))
- return build (COMPOUND_EXPR, type, TREE_OPERAND (arg1, 0),
- fold (build (code, type,
- arg0, TREE_OPERAND (arg1, 1))));
- else if ((TREE_CODE (arg1) == COND_EXPR
- || (TREE_CODE_CLASS (TREE_CODE (arg1)) == '<'
- && TREE_CODE_CLASS (code) != '<'))
- && (TREE_CODE (arg0) != COND_EXPR
- || count_cond (arg0, 25) + count_cond (arg1, 25) <= 25)
- && (! TREE_SIDE_EFFECTS (arg0)
- || ((*lang_hooks.decls.global_bindings_p) () == 0
- && ! CONTAINS_PLACEHOLDER_P (arg0))))
- return
- fold_binary_op_with_conditional_arg (code, type, arg1, arg0,
- /*cond_first_p=*/0);
- else if (TREE_CODE (arg0) == COMPOUND_EXPR)
- return build (COMPOUND_EXPR, type, TREE_OPERAND (arg0, 0),
- fold (build (code, type, TREE_OPERAND (arg0, 1), arg1)));
- else if ((TREE_CODE (arg0) == COND_EXPR
- || (TREE_CODE_CLASS (TREE_CODE (arg0)) == '<'
- && TREE_CODE_CLASS (code) != '<'))
- && (TREE_CODE (arg1) != COND_EXPR
- || count_cond (arg0, 25) + count_cond (arg1, 25) <= 25)
- && (! TREE_SIDE_EFFECTS (arg1)
- || ((*lang_hooks.decls.global_bindings_p) () == 0
- && ! CONTAINS_PLACEHOLDER_P (arg1))))
- return
- fold_binary_op_with_conditional_arg (code, type, arg0, arg1,
- /*cond_first_p=*/1);
+ && reorder_operands_p (arg0, TREE_OPERAND (arg1, 0)))
+ return build2 (COMPOUND_EXPR, type, TREE_OPERAND (arg1, 0),
+ fold (build2 (code, type,
+ arg0, TREE_OPERAND (arg1, 1))));
+
+ if (TREE_CODE (arg0) == COND_EXPR
+ || TREE_CODE_CLASS (TREE_CODE (arg0)) == '<')
+ {
+ tem = fold_binary_op_with_conditional_arg (code, type, arg0, arg1,
+ /*cond_first_p=*/1);
+ if (tem != NULL_TREE)
+ return tem;
+ }
+
+ if (TREE_CODE (arg1) == COND_EXPR
+ || TREE_CODE_CLASS (TREE_CODE (arg1)) == '<')
+ {
+ tem = fold_binary_op_with_conditional_arg (code, type, arg1, arg0,
+ /*cond_first_p=*/0);
+ if (tem != NULL_TREE)
+ return tem;
+ }
}
switch (code)
{
- case INTEGER_CST:
- case REAL_CST:
- case VECTOR_CST:
- case STRING_CST:
- case COMPLEX_CST:
- case CONSTRUCTOR:
- return t;
-
case CONST_DECL:
return fold (DECL_INITIAL (t));
case FIX_TRUNC_EXPR:
case FIX_CEIL_EXPR:
case FIX_FLOOR_EXPR:
- if (TREE_TYPE (TREE_OPERAND (t, 0)) == TREE_TYPE (t))
+ case FIX_ROUND_EXPR:
+ if (TREE_TYPE (TREE_OPERAND (t, 0)) == type)
return TREE_OPERAND (t, 0);
/* Handle cases of two conversions in a row. */
{
tree inside_type = TREE_TYPE (TREE_OPERAND (TREE_OPERAND (t, 0), 0));
tree inter_type = TREE_TYPE (TREE_OPERAND (t, 0));
- tree final_type = TREE_TYPE (t);
int inside_int = INTEGRAL_TYPE_P (inside_type);
int inside_ptr = POINTER_TYPE_P (inside_type);
int inside_float = FLOAT_TYPE_P (inside_type);
unsigned int inside_prec = TYPE_PRECISION (inside_type);
- int inside_unsignedp = TREE_UNSIGNED (inside_type);
+ int inside_unsignedp = TYPE_UNSIGNED (inside_type);
int inter_int = INTEGRAL_TYPE_P (inter_type);
int inter_ptr = POINTER_TYPE_P (inter_type);
int inter_float = FLOAT_TYPE_P (inter_type);
unsigned int inter_prec = TYPE_PRECISION (inter_type);
- int inter_unsignedp = TREE_UNSIGNED (inter_type);
- int final_int = INTEGRAL_TYPE_P (final_type);
- int final_ptr = POINTER_TYPE_P (final_type);
- int final_float = FLOAT_TYPE_P (final_type);
- unsigned int final_prec = TYPE_PRECISION (final_type);
- int final_unsignedp = TREE_UNSIGNED (final_type);
+ int inter_unsignedp = TYPE_UNSIGNED (inter_type);
+ int final_int = INTEGRAL_TYPE_P (type);
+ int final_ptr = POINTER_TYPE_P (type);
+ int final_float = FLOAT_TYPE_P (type);
+ unsigned int final_prec = TYPE_PRECISION (type);
+ int final_unsignedp = TYPE_UNSIGNED (type);
/* In addition to the cases of two conversions in a row
handled below, if we are converting something to its own
type via an object of identical or wider precision, neither
conversion is needed. */
- if (TYPE_MAIN_VARIANT (inside_type) == TYPE_MAIN_VARIANT (final_type)
+ if (TYPE_MAIN_VARIANT (inside_type) == TYPE_MAIN_VARIANT (type)
&& ((inter_int && final_int) || (inter_float && final_float))
&& inter_prec >= final_prec)
- return fold (build1 (code, final_type,
+ return fold (build1 (code, type,
TREE_OPERAND (TREE_OPERAND (t, 0), 0)));
/* Likewise, if the intermediate and final types are either both
|| (inter_float && inside_float))
&& inter_prec >= inside_prec
&& (inter_float || inter_unsignedp == inside_unsignedp)
- && ! (final_prec != GET_MODE_BITSIZE (TYPE_MODE (final_type))
- && TYPE_MODE (final_type) == TYPE_MODE (inter_type))
+ && ! (final_prec != GET_MODE_BITSIZE (TYPE_MODE (type))
+ && TYPE_MODE (type) == TYPE_MODE (inter_type))
&& ! final_ptr)
- return fold (build1 (code, final_type,
+ return fold (build1 (code, type,
TREE_OPERAND (TREE_OPERAND (t, 0), 0)));
/* If we have a sign-extension of a zero-extended value, we can
if (inside_int && inter_int && final_int
&& inside_prec < inter_prec && inter_prec < final_prec
&& inside_unsignedp && !inter_unsignedp)
- return fold (build1 (code, final_type,
+ return fold (build1 (code, type,
TREE_OPERAND (TREE_OPERAND (t, 0), 0)));
/* Two conversions in a row are not needed unless:
== (final_unsignedp && final_prec > inter_prec))
&& ! (inside_ptr && inter_prec != final_prec)
&& ! (final_ptr && inside_prec != inter_prec)
- && ! (final_prec != GET_MODE_BITSIZE (TYPE_MODE (final_type))
- && TYPE_MODE (final_type) == TYPE_MODE (inter_type))
+ && ! (final_prec != GET_MODE_BITSIZE (TYPE_MODE (type))
+ && TYPE_MODE (type) == TYPE_MODE (inter_type))
&& ! final_ptr)
- return fold (build1 (code, final_type,
+ return fold (build1 (code, type,
TREE_OPERAND (TREE_OPERAND (t, 0), 0)));
}
/* Don't leave an assignment inside a conversion
unless assigning a bitfield. */
tree prev = TREE_OPERAND (t, 0);
- if (t == orig_t)
- t = copy_node (t);
- TREE_OPERAND (t, 0) = TREE_OPERAND (prev, 1);
+ tem = copy_node (t);
+ TREE_OPERAND (tem, 0) = TREE_OPERAND (prev, 1);
/* First do the assignment, then return converted constant. */
- t = build (COMPOUND_EXPR, TREE_TYPE (t), prev, fold (t));
- TREE_USED (t) = 1;
- return t;
+ tem = build2 (COMPOUND_EXPR, TREE_TYPE (tem), prev, fold (tem));
+ TREE_NO_WARNING (tem) = 1;
+ TREE_USED (tem) = 1;
+ return tem;
}
/* Convert (T)(x & c) into (T)x & (T)c, if c is an integer
constants (if x has signed type, the sign bit cannot be set
in c). This folds extension into the BIT_AND_EXPR. */
- if (INTEGRAL_TYPE_P (TREE_TYPE (t))
- && TREE_CODE (TREE_TYPE (t)) != BOOLEAN_TYPE
+ if (INTEGRAL_TYPE_P (type)
+ && TREE_CODE (type) != BOOLEAN_TYPE
&& TREE_CODE (TREE_OPERAND (t, 0)) == BIT_AND_EXPR
&& TREE_CODE (TREE_OPERAND (TREE_OPERAND (t, 0), 1)) == INTEGER_CST)
{
tree and0 = TREE_OPERAND (and, 0), and1 = TREE_OPERAND (and, 1);
int change = 0;
- if (TREE_UNSIGNED (TREE_TYPE (and))
- || (TYPE_PRECISION (TREE_TYPE (t))
+ if (TYPE_UNSIGNED (TREE_TYPE (and))
+ || (TYPE_PRECISION (type)
<= TYPE_PRECISION (TREE_TYPE (and))))
change = 1;
else if (TYPE_PRECISION (TREE_TYPE (and1))
&& (LOAD_EXTEND_OP (TYPE_MODE (TREE_TYPE (and0)))
== ZERO_EXTEND))
{
- tree uns = (*lang_hooks.types.unsigned_type) (TREE_TYPE (and0));
+ tree uns = lang_hooks.types.unsigned_type (TREE_TYPE (and0));
and0 = fold_convert (uns, and0);
and1 = fold_convert (uns, and1);
}
#endif
}
if (change)
- return fold (build (BIT_AND_EXPR, TREE_TYPE (t),
- fold_convert (TREE_TYPE (t), and0),
- fold_convert (TREE_TYPE (t), and1)));
+ return fold (build2 (BIT_AND_EXPR, type,
+ fold_convert (type, and0),
+ fold_convert (type, and1)));
+ }
+
+ /* Convert (T1)((T2)X op Y) into (T1)X op Y, for pointer types T1 and
+ T2 being pointers to types of the same size. */
+ if (POINTER_TYPE_P (TREE_TYPE (t))
+ && TREE_CODE_CLASS (TREE_CODE (arg0)) == '2'
+ && TREE_CODE (TREE_OPERAND (arg0, 0)) == NOP_EXPR
+ && POINTER_TYPE_P (TREE_TYPE (TREE_OPERAND (arg0, 0))))
+ {
+ tree arg00 = TREE_OPERAND (arg0, 0);
+ tree t0 = TREE_TYPE (t);
+ tree t1 = TREE_TYPE (arg00);
+ tree tt0 = TREE_TYPE (t0);
+ tree tt1 = TREE_TYPE (t1);
+ tree s0 = TYPE_SIZE (tt0);
+ tree s1 = TYPE_SIZE (tt1);
+
+ if (s0 && s1 && operand_equal_p (s0, s1, OEP_ONLY_CONST))
+ return build2 (TREE_CODE (arg0), t0, fold_convert (t0, arg00),
+ TREE_OPERAND (arg0, 1));
}
- tem = fold_convert_const (code, TREE_TYPE (t), arg0);
+ tem = fold_convert_const (code, type, arg0);
return tem ? tem : t;
case VIEW_CONVERT_EXPR:
{
tree m = purpose_member (arg1, CONSTRUCTOR_ELTS (arg0));
if (m)
- t = TREE_VALUE (m);
+ return TREE_VALUE (m);
}
return t;
case RANGE_EXPR:
if (TREE_CONSTANT (t) != wins)
{
- if (t == orig_t)
- t = copy_node (t);
- TREE_CONSTANT (t) = wins;
+ tem = copy_node (t);
+ TREE_CONSTANT (tem) = wins;
+ TREE_INVARIANT (tem) = wins;
+ return tem;
}
return t;
return t;
case ABS_EXPR:
- if (wins)
- {
- if (TREE_CODE (arg0) == INTEGER_CST)
- {
- /* If the value is unsigned, then the absolute value is
- the same as the ordinary value. */
- if (TREE_UNSIGNED (type))
- return arg0;
- /* Similarly, if the value is non-negative. */
- else if (INT_CST_LT (integer_minus_one_node, arg0))
- return arg0;
- /* If the value is negative, then the absolute value is
- its negation. */
- else
- {
- unsigned HOST_WIDE_INT low;
- HOST_WIDE_INT high;
- int overflow = neg_double (TREE_INT_CST_LOW (arg0),
- TREE_INT_CST_HIGH (arg0),
- &low, &high);
- t = build_int_2 (low, high);
- TREE_TYPE (t) = type;
- TREE_OVERFLOW (t)
- = (TREE_OVERFLOW (arg0)
- | force_fit_type (t, overflow));
- TREE_CONSTANT_OVERFLOW (t)
- = TREE_OVERFLOW (t) | TREE_CONSTANT_OVERFLOW (arg0);
- }
- }
- else if (TREE_CODE (arg0) == REAL_CST)
- {
- if (REAL_VALUE_NEGATIVE (TREE_REAL_CST (arg0)))
- t = build_real (type,
- REAL_VALUE_NEGATE (TREE_REAL_CST (arg0)));
- }
- }
+ if (wins
+ && (TREE_CODE (arg0) == INTEGER_CST || TREE_CODE (arg0) == REAL_CST))
+ return fold_abs_const (arg0, type);
else if (TREE_CODE (arg0) == NEGATE_EXPR)
return fold (build1 (ABS_EXPR, type, TREE_OPERAND (arg0, 0)));
/* Convert fabs((double)float) into (double)fabsf(float). */
if (TREE_CODE (TREE_TYPE (arg0)) != COMPLEX_TYPE)
return fold_convert (type, arg0);
else if (TREE_CODE (arg0) == COMPLEX_EXPR)
- return build (COMPLEX_EXPR, type,
- TREE_OPERAND (arg0, 0),
- negate_expr (TREE_OPERAND (arg0, 1)));
+ return build2 (COMPLEX_EXPR, type,
+ TREE_OPERAND (arg0, 0),
+ negate_expr (TREE_OPERAND (arg0, 1)));
else if (TREE_CODE (arg0) == COMPLEX_CST)
return build_complex (type, TREE_REALPART (arg0),
negate_expr (TREE_IMAGPART (arg0)));
else if (TREE_CODE (arg0) == PLUS_EXPR || TREE_CODE (arg0) == MINUS_EXPR)
- return fold (build (TREE_CODE (arg0), type,
- fold (build1 (CONJ_EXPR, type,
- TREE_OPERAND (arg0, 0))),
- fold (build1 (CONJ_EXPR,
- type, TREE_OPERAND (arg0, 1)))));
+ return fold (build2 (TREE_CODE (arg0), type,
+ fold (build1 (CONJ_EXPR, type,
+ TREE_OPERAND (arg0, 0))),
+ fold (build1 (CONJ_EXPR, type,
+ TREE_OPERAND (arg0, 1)))));
else if (TREE_CODE (arg0) == CONJ_EXPR)
return TREE_OPERAND (arg0, 0);
return t;
case BIT_NOT_EXPR:
if (wins)
{
- t = build_int_2 (~ TREE_INT_CST_LOW (arg0),
- ~ TREE_INT_CST_HIGH (arg0));
- TREE_TYPE (t) = type;
- force_fit_type (t, 0);
- TREE_OVERFLOW (t) = TREE_OVERFLOW (arg0);
- TREE_CONSTANT_OVERFLOW (t) = TREE_CONSTANT_OVERFLOW (arg0);
+ tem = build_int_2 (~ TREE_INT_CST_LOW (arg0),
+ ~ TREE_INT_CST_HIGH (arg0));
+ TREE_TYPE (tem) = type;
+ force_fit_type (tem, 0);
+ TREE_OVERFLOW (tem) = TREE_OVERFLOW (arg0);
+ TREE_CONSTANT_OVERFLOW (tem) = TREE_CONSTANT_OVERFLOW (arg0);
+ return tem;
}
else if (TREE_CODE (arg0) == BIT_NOT_EXPR)
return TREE_OPERAND (arg0, 0);
case PLUS_EXPR:
/* A + (-B) -> A - B */
if (TREE_CODE (arg1) == NEGATE_EXPR)
- return fold (build (MINUS_EXPR, type, arg0, TREE_OPERAND (arg1, 0)));
+ return fold (build2 (MINUS_EXPR, type, arg0, TREE_OPERAND (arg1, 0)));
/* (-A) + B -> B - A */
- if (TREE_CODE (arg0) == NEGATE_EXPR)
- return fold (build (MINUS_EXPR, type, arg1, TREE_OPERAND (arg0, 0)));
- else if (! FLOAT_TYPE_P (type))
+ if (TREE_CODE (arg0) == NEGATE_EXPR
+ && reorder_operands_p (TREE_OPERAND (arg0, 0), arg1))
+ return fold (build2 (MINUS_EXPR, type, arg1, TREE_OPERAND (arg0, 0)));
+ if (! FLOAT_TYPE_P (type))
{
if (integer_zerop (arg1))
return non_lvalue (fold_convert (type, arg0));
if (TREE_CODE (parg0) == MULT_EXPR
&& TREE_CODE (parg1) != MULT_EXPR)
- return fold (build (PLUS_EXPR, type,
- fold (build (PLUS_EXPR, type,
- fold_convert (type, parg0),
- fold_convert (type, marg))),
- fold_convert (type, parg1)));
+ return fold (build2 (PLUS_EXPR, type,
+ fold (build2 (PLUS_EXPR, type,
+ fold_convert (type, parg0),
+ fold_convert (type, marg))),
+ fold_convert (type, parg1)));
if (TREE_CODE (parg0) != MULT_EXPR
&& TREE_CODE (parg1) == MULT_EXPR)
- return fold (build (PLUS_EXPR, type,
- fold (build (PLUS_EXPR, type,
- fold_convert (type, parg1),
- fold_convert (type, marg))),
- fold_convert (type, parg0)));
+ return fold (build2 (PLUS_EXPR, type,
+ fold (build2 (PLUS_EXPR, type,
+ fold_convert (type, parg1),
+ fold_convert (type, marg))),
+ fold_convert (type, parg0)));
}
if (TREE_CODE (arg0) == MULT_EXPR && TREE_CODE (arg1) == MULT_EXPR)
if (exact_log2 (int11) > 0 && int01 % int11 == 0)
{
- alt0 = fold (build (MULT_EXPR, type, arg00,
- build_int_2 (int01 / int11, 0)));
+ alt0 = fold (build2 (MULT_EXPR, type, arg00,
+ build_int_2 (int01 / int11, 0)));
alt1 = arg10;
same = arg11;
}
}
if (same)
- return fold (build (MULT_EXPR, type,
- fold (build (PLUS_EXPR, type, alt0, alt1)),
- same));
+ return fold (build2 (MULT_EXPR, type,
+ fold (build2 (PLUS_EXPR, type,
+ alt0, alt1)),
+ same));
}
}
else
/* Convert x+x into x*2.0. */
if (operand_equal_p (arg0, arg1, 0)
&& SCALAR_FLOAT_TYPE_P (type))
- return fold (build (MULT_EXPR, type, arg0,
- build_real (type, dconst2)));
+ return fold (build2 (MULT_EXPR, type, arg0,
+ build_real (type, dconst2)));
/* Convert x*c+x into x*(c+1). */
if (flag_unsafe_math_optimizations
c = TREE_REAL_CST (TREE_OPERAND (arg0, 1));
real_arithmetic (&c, PLUS_EXPR, &c, &dconst1);
- return fold (build (MULT_EXPR, type, arg1,
- build_real (type, c)));
+ return fold (build2 (MULT_EXPR, type, arg1,
+ build_real (type, c)));
}
/* Convert x+x*c into x*(c+1). */
c = TREE_REAL_CST (TREE_OPERAND (arg1, 1));
real_arithmetic (&c, PLUS_EXPR, &c, &dconst1);
- return fold (build (MULT_EXPR, type, arg0,
- build_real (type, c)));
+ return fold (build2 (MULT_EXPR, type, arg0,
+ build_real (type, c)));
}
/* Convert x*c1+x*c2 into x*(c1+c2). */
c1 = TREE_REAL_CST (TREE_OPERAND (arg0, 1));
c2 = TREE_REAL_CST (TREE_OPERAND (arg1, 1));
real_arithmetic (&c1, PLUS_EXPR, &c1, &c2);
- return fold (build (MULT_EXPR, type,
- TREE_OPERAND (arg0, 0),
- build_real (type, c1)));
+ return fold (build2 (MULT_EXPR, type,
+ TREE_OPERAND (arg0, 0),
+ build_real (type, c1)));
}
+ /* Convert a + (b*c + d*e) into (a + b*c) + d*e */
+ if (flag_unsafe_math_optimizations
+ && TREE_CODE (arg1) == PLUS_EXPR
+ && TREE_CODE (arg0) != MULT_EXPR)
+ {
+ tree tree10 = TREE_OPERAND (arg1, 0);
+ tree tree11 = TREE_OPERAND (arg1, 1);
+ if (TREE_CODE (tree11) == MULT_EXPR
+ && TREE_CODE (tree10) == MULT_EXPR)
+ {
+ tree tree0;
+ tree0 = fold (build2 (PLUS_EXPR, type, arg0, tree10));
+ return fold (build2 (PLUS_EXPR, type, tree0, tree11));
+ }
+ }
+ /* Convert (b*c + d*e) + a into b*c + (d*e +a) */
+ if (flag_unsafe_math_optimizations
+ && TREE_CODE (arg0) == PLUS_EXPR
+ && TREE_CODE (arg1) != MULT_EXPR)
+ {
+ tree tree00 = TREE_OPERAND (arg0, 0);
+ tree tree01 = TREE_OPERAND (arg0, 1);
+ if (TREE_CODE (tree01) == MULT_EXPR
+ && TREE_CODE (tree00) == MULT_EXPR)
+ {
+ tree tree0;
+ tree0 = fold (build2 (PLUS_EXPR, type, tree01, arg1));
+ return fold (build2 (PLUS_EXPR, type, tree00, tree0));
+ }
+ }
}
bit_rotate:
|| (code1 == RSHIFT_EXPR && code0 == LSHIFT_EXPR))
&& operand_equal_p (TREE_OPERAND (arg0, 0),
TREE_OPERAND (arg1, 0), 0)
- && TREE_UNSIGNED (TREE_TYPE (TREE_OPERAND (arg0, 0))))
+ && TYPE_UNSIGNED (TREE_TYPE (TREE_OPERAND (arg0, 0))))
{
tree tree01, tree11;
enum tree_code code01, code11;
&& TREE_INT_CST_HIGH (tree11) == 0
&& ((TREE_INT_CST_LOW (tree01) + TREE_INT_CST_LOW (tree11))
== TYPE_PRECISION (TREE_TYPE (TREE_OPERAND (arg0, 0)))))
- return build (LROTATE_EXPR, type, TREE_OPERAND (arg0, 0),
- code0 == LSHIFT_EXPR ? tree01 : tree11);
+ return build2 (LROTATE_EXPR, type, TREE_OPERAND (arg0, 0),
+ code0 == LSHIFT_EXPR ? tree01 : tree11);
else if (code11 == MINUS_EXPR)
{
tree tree110, tree111;
(TREE_TYPE (TREE_OPERAND
(arg0, 0))))
&& operand_equal_p (tree01, tree111, 0))
- return build ((code0 == LSHIFT_EXPR
- ? LROTATE_EXPR
- : RROTATE_EXPR),
- type, TREE_OPERAND (arg0, 0), tree01);
+ return build2 ((code0 == LSHIFT_EXPR
+ ? LROTATE_EXPR
+ : RROTATE_EXPR),
+ type, TREE_OPERAND (arg0, 0), tree01);
}
else if (code01 == MINUS_EXPR)
{
(TREE_TYPE (TREE_OPERAND
(arg0, 0))))
&& operand_equal_p (tree11, tree011, 0))
- return build ((code0 != LSHIFT_EXPR
- ? LROTATE_EXPR
- : RROTATE_EXPR),
- type, TREE_OPERAND (arg0, 0), tree11);
+ return build2 ((code0 != LSHIFT_EXPR
+ ? LROTATE_EXPR
+ : RROTATE_EXPR),
+ type, TREE_OPERAND (arg0, 0), tree11);
}
}
}
{
/* The return value should always have
the same type as the original expression. */
- if (TREE_TYPE (t1) != TREE_TYPE (t))
- t1 = fold_convert (TREE_TYPE (t), t1);
+ if (TREE_TYPE (t1) != type)
+ t1 = fold_convert (type, t1);
return t1;
}
case MINUS_EXPR:
/* A - (-B) -> A + B */
if (TREE_CODE (arg1) == NEGATE_EXPR)
- return fold (build (PLUS_EXPR, type, arg0, TREE_OPERAND (arg1, 0)));
+ return fold (build2 (PLUS_EXPR, type, arg0, TREE_OPERAND (arg1, 0)));
/* (-A) - B -> (-B) - A where B is easily negated and we can swap. */
if (TREE_CODE (arg0) == NEGATE_EXPR
&& (FLOAT_TYPE_P (type)
|| (INTEGRAL_TYPE_P (type) && flag_wrapv && !flag_trapv))
&& negate_expr_p (arg1)
&& reorder_operands_p (arg0, arg1))
- return fold (build (MINUS_EXPR, type, negate_expr (arg1),
- TREE_OPERAND (arg0, 0)));
+ return fold (build2 (MINUS_EXPR, type, negate_expr (arg1),
+ TREE_OPERAND (arg0, 0)));
if (! FLOAT_TYPE_P (type))
{
&& TREE_CODE (arg1) == BIT_AND_EXPR)
{
if (operand_equal_p (arg0, TREE_OPERAND (arg1, 1), 0))
- return fold (build (BIT_AND_EXPR, type,
- fold (build1 (BIT_NOT_EXPR, type,
- TREE_OPERAND (arg1, 0))),
- arg0));
+ return fold (build2 (BIT_AND_EXPR, type,
+ fold (build1 (BIT_NOT_EXPR, type,
+ TREE_OPERAND (arg1, 0))),
+ arg0));
if (operand_equal_p (arg0, TREE_OPERAND (arg1, 0), 0))
- return fold (build (BIT_AND_EXPR, type,
- fold (build1 (BIT_NOT_EXPR, type,
- TREE_OPERAND (arg1, 1))),
- arg0));
+ return fold (build2 (BIT_AND_EXPR, type,
+ fold (build1 (BIT_NOT_EXPR, type,
+ TREE_OPERAND (arg1, 1))),
+ arg0));
}
/* Fold (A & ~B) - (A & B) into (A ^ B) - B, where B is
if (operand_equal_p (tem, mask1, 0))
{
- tem = fold (build (BIT_XOR_EXPR, type,
- TREE_OPERAND (arg0, 0), mask1));
- return fold (build (MINUS_EXPR, type, tem, mask1));
+ tem = fold (build2 (BIT_XOR_EXPR, type,
+ TREE_OPERAND (arg0, 0), mask1));
+ return fold (build2 (MINUS_EXPR, type, tem, mask1));
}
}
}
if (!wins && negate_expr_p (arg1)
&& (FLOAT_TYPE_P (type)
|| (INTEGRAL_TYPE_P (type) && flag_wrapv && !flag_trapv)))
- return fold (build (PLUS_EXPR, type, arg0, negate_expr (arg1)));
+ return fold (build2 (PLUS_EXPR, type, arg0, negate_expr (arg1)));
if (TREE_CODE (arg0) == MULT_EXPR
&& TREE_CODE (arg1) == MULT_EXPR
/* (A * C) - (B * C) -> (A-B) * C. */
if (operand_equal_p (TREE_OPERAND (arg0, 1),
TREE_OPERAND (arg1, 1), 0))
- return fold (build (MULT_EXPR, type,
- fold (build (MINUS_EXPR, type,
- TREE_OPERAND (arg0, 0),
- TREE_OPERAND (arg1, 0))),
- TREE_OPERAND (arg0, 1)));
+ return fold (build2 (MULT_EXPR, type,
+ fold (build2 (MINUS_EXPR, type,
+ TREE_OPERAND (arg0, 0),
+ TREE_OPERAND (arg1, 0))),
+ TREE_OPERAND (arg0, 1)));
/* (A * C1) - (A * C2) -> A * (C1-C2). */
if (operand_equal_p (TREE_OPERAND (arg0, 0),
TREE_OPERAND (arg1, 0), 0))
- return fold (build (MULT_EXPR, type,
- TREE_OPERAND (arg0, 0),
- fold (build (MINUS_EXPR, type,
- TREE_OPERAND (arg0, 1),
- TREE_OPERAND (arg1, 1)))));
+ return fold (build2 (MULT_EXPR, type,
+ TREE_OPERAND (arg0, 0),
+ fold (build2 (MINUS_EXPR, type,
+ TREE_OPERAND (arg0, 1),
+ TREE_OPERAND (arg1, 1)))));
}
goto associate;
case MULT_EXPR:
/* (-A) * (-B) -> A * B */
if (TREE_CODE (arg0) == NEGATE_EXPR && negate_expr_p (arg1))
- return fold (build (MULT_EXPR, type,
- TREE_OPERAND (arg0, 0),
- negate_expr (arg1)));
+ return fold (build2 (MULT_EXPR, type,
+ TREE_OPERAND (arg0, 0),
+ negate_expr (arg1)));
if (TREE_CODE (arg1) == NEGATE_EXPR && negate_expr_p (arg0))
- return fold (build (MULT_EXPR, type,
- negate_expr (arg0),
- TREE_OPERAND (arg1, 0)));
+ return fold (build2 (MULT_EXPR, type,
+ negate_expr (arg0),
+ TREE_OPERAND (arg1, 0)));
if (! FLOAT_TYPE_P (type))
{
/* (a * (1 << b)) is (a << b) */
if (TREE_CODE (arg1) == LSHIFT_EXPR
&& integer_onep (TREE_OPERAND (arg1, 0)))
- return fold (build (LSHIFT_EXPR, type, arg0,
- TREE_OPERAND (arg1, 1)));
+ return fold (build2 (LSHIFT_EXPR, type, arg0,
+ TREE_OPERAND (arg1, 1)));
if (TREE_CODE (arg0) == LSHIFT_EXPR
&& integer_onep (TREE_OPERAND (arg0, 0)))
- return fold (build (LSHIFT_EXPR, type, arg1,
- TREE_OPERAND (arg0, 1)));
+ return fold (build2 (LSHIFT_EXPR, type, arg1,
+ TREE_OPERAND (arg0, 1)));
if (TREE_CODE (arg1) == INTEGER_CST
&& 0 != (tem = extract_muldiv (TREE_OPERAND (t, 0),
/* Transform x * -1.0 into -x. */
if (!HONOR_SNANS (TYPE_MODE (TREE_TYPE (arg0)))
&& real_minus_onep (arg1))
- return fold (build1 (NEGATE_EXPR, type, arg0));
+ return fold_convert (type, negate_expr (arg0));
/* Convert (C1/X)*C2 into (C1*C2)/X. */
if (flag_unsafe_math_optimizations
tree tem = const_binop (MULT_EXPR, TREE_OPERAND (arg0, 0),
arg1, 0);
if (tem)
- return fold (build (RDIV_EXPR, type, tem,
- TREE_OPERAND (arg0, 1)));
+ return fold (build2 (RDIV_EXPR, type, tem,
+ TREE_OPERAND (arg0, 1)));
}
if (flag_unsafe_math_optimizations)
enum built_in_function fcode0 = builtin_mathfn_code (arg0);
enum built_in_function fcode1 = builtin_mathfn_code (arg1);
- /* Optimizations of sqrt(...)*sqrt(...). */
- if ((fcode0 == BUILT_IN_SQRT && fcode1 == BUILT_IN_SQRT)
- || (fcode0 == BUILT_IN_SQRTF && fcode1 == BUILT_IN_SQRTF)
- || (fcode0 == BUILT_IN_SQRTL && fcode1 == BUILT_IN_SQRTL))
+ /* Optimizations of root(...)*root(...). */
+ if (fcode0 == fcode1 && BUILTIN_ROOT_P (fcode0))
{
- tree sqrtfn, arg, arglist;
+ tree rootfn, arg, arglist;
tree arg00 = TREE_VALUE (TREE_OPERAND (arg0, 1));
tree arg10 = TREE_VALUE (TREE_OPERAND (arg1, 1));
/* Optimize sqrt(x)*sqrt(x) as x. */
- if (operand_equal_p (arg00, arg10, 0)
+ if (BUILTIN_SQRT_P (fcode0)
+ && operand_equal_p (arg00, arg10, 0)
&& ! HONOR_SNANS (TYPE_MODE (type)))
return arg00;
- /* Optimize sqrt(x)*sqrt(y) as sqrt(x*y). */
- sqrtfn = TREE_OPERAND (TREE_OPERAND (arg0, 0), 0);
- arg = fold (build (MULT_EXPR, type, arg00, arg10));
+ /* Optimize root(x)*root(y) as root(x*y). */
+ rootfn = TREE_OPERAND (TREE_OPERAND (arg0, 0), 0);
+ arg = fold (build2 (MULT_EXPR, type, arg00, arg10));
arglist = build_tree_list (NULL_TREE, arg);
- return build_function_call_expr (sqrtfn, arglist);
+ return build_function_call_expr (rootfn, arglist);
}
/* Optimize expN(x)*expN(y) as expN(x+y). */
- if (fcode0 == fcode1
- && (fcode0 == BUILT_IN_EXP
- || fcode0 == BUILT_IN_EXPF
- || fcode0 == BUILT_IN_EXPL
- || fcode0 == BUILT_IN_EXP2
- || fcode0 == BUILT_IN_EXP2F
- || fcode0 == BUILT_IN_EXP2L
- || fcode0 == BUILT_IN_EXP10
- || fcode0 == BUILT_IN_EXP10F
- || fcode0 == BUILT_IN_EXP10L
- || fcode0 == BUILT_IN_POW10
- || fcode0 == BUILT_IN_POW10F
- || fcode0 == BUILT_IN_POW10L))
+ if (fcode0 == fcode1 && BUILTIN_EXPONENT_P (fcode0))
{
tree expfn = TREE_OPERAND (TREE_OPERAND (arg0, 0), 0);
- tree arg = build (PLUS_EXPR, type,
- TREE_VALUE (TREE_OPERAND (arg0, 1)),
- TREE_VALUE (TREE_OPERAND (arg1, 1)));
+ tree arg = build2 (PLUS_EXPR, type,
+ TREE_VALUE (TREE_OPERAND (arg0, 1)),
+ TREE_VALUE (TREE_OPERAND (arg1, 1)));
tree arglist = build_tree_list (NULL_TREE, fold (arg));
return build_function_call_expr (expfn, arglist);
}
if (operand_equal_p (arg01, arg11, 0))
{
tree powfn = TREE_OPERAND (TREE_OPERAND (arg0, 0), 0);
- tree arg = build (MULT_EXPR, type, arg00, arg10);
+ tree arg = build2 (MULT_EXPR, type, arg00, arg10);
tree arglist = tree_cons (NULL_TREE, fold (arg),
build_tree_list (NULL_TREE,
arg01));
if (operand_equal_p (arg00, arg10, 0))
{
tree powfn = TREE_OPERAND (TREE_OPERAND (arg0, 0), 0);
- tree arg = fold (build (PLUS_EXPR, type, arg01, arg11));
+ tree arg = fold (build2 (PLUS_EXPR, type, arg01, arg11));
tree arglist = tree_cons (NULL_TREE, arg00,
build_tree_list (NULL_TREE,
arg));
&& operand_equal_p (TREE_VALUE (TREE_OPERAND (arg0, 1)),
TREE_VALUE (TREE_OPERAND (arg1, 1)), 0))
{
- tree sinfn;
-
- switch (fcode0)
- {
- case BUILT_IN_TAN:
- case BUILT_IN_COS:
- sinfn = implicit_built_in_decls[BUILT_IN_SIN];
- break;
- case BUILT_IN_TANF:
- case BUILT_IN_COSF:
- sinfn = implicit_built_in_decls[BUILT_IN_SINF];
- break;
- case BUILT_IN_TANL:
- case BUILT_IN_COSL:
- sinfn = implicit_built_in_decls[BUILT_IN_SINL];
- break;
- default:
- sinfn = NULL_TREE;
- }
+ tree sinfn = mathfn_built_in (type, BUILT_IN_SIN);
if (sinfn != NULL_TREE)
return build_function_call_expr (sinfn,
if (! optimize_size
&& operand_equal_p (arg0, arg1, 0))
{
- tree powfn;
-
- if (type == double_type_node)
- powfn = implicit_built_in_decls[BUILT_IN_POW];
- else if (type == float_type_node)
- powfn = implicit_built_in_decls[BUILT_IN_POWF];
- else if (type == long_double_type_node)
- powfn = implicit_built_in_decls[BUILT_IN_POWL];
- else
- powfn = NULL_TREE;
+ tree powfn = mathfn_built_in (type, BUILT_IN_POW);
if (powfn)
{
return omit_one_operand (type, arg1, arg0);
if (integer_zerop (arg1))
return non_lvalue (fold_convert (type, arg0));
+ if (operand_equal_p (arg0, arg1, 0))
+ return non_lvalue (fold_convert (type, arg0));
t1 = distribute_bit_expr (code, type, arg0, arg1);
if (t1 != NULL_TREE)
return t1;
&& TREE_CODE (arg1) == BIT_NOT_EXPR)
{
return fold (build1 (BIT_NOT_EXPR, type,
- build (BIT_AND_EXPR, type,
- TREE_OPERAND (arg0, 0),
- TREE_OPERAND (arg1, 0))));
+ build2 (BIT_AND_EXPR, type,
+ TREE_OPERAND (arg0, 0),
+ TREE_OPERAND (arg1, 0))));
}
/* See if this can be simplified into a rotate first. If that
return non_lvalue (fold_convert (type, arg0));
if (integer_all_onesp (arg1))
return fold (build1 (BIT_NOT_EXPR, type, arg0));
+ if (operand_equal_p (arg0, arg1, 0))
+ return omit_one_operand (type, integer_zero_node, arg0);
/* If we are XORing two BIT_AND_EXPR's, both of which are and'ing
with a constant, and the two constants have no bits in common,
return non_lvalue (fold_convert (type, arg0));
if (integer_zerop (arg1))
return omit_one_operand (type, arg1, arg0);
+ if (operand_equal_p (arg0, arg1, 0))
+ return non_lvalue (fold_convert (type, arg0));
t1 = distribute_bit_expr (code, type, arg0, arg1);
if (t1 != NULL_TREE)
return t1;
/* Simplify ((int)c & 0377) into (int)c, if c is unsigned char. */
if (TREE_CODE (arg1) == INTEGER_CST && TREE_CODE (arg0) == NOP_EXPR
- && TREE_UNSIGNED (TREE_TYPE (TREE_OPERAND (arg0, 0))))
+ && TYPE_UNSIGNED (TREE_TYPE (TREE_OPERAND (arg0, 0))))
{
unsigned int prec
= TYPE_PRECISION (TREE_TYPE (TREE_OPERAND (arg0, 0)));
&& TREE_CODE (arg1) == BIT_NOT_EXPR)
{
return fold (build1 (BIT_NOT_EXPR, type,
- build (BIT_IOR_EXPR, type,
- TREE_OPERAND (arg0, 0),
- TREE_OPERAND (arg1, 0))));
+ build2 (BIT_IOR_EXPR, type,
+ TREE_OPERAND (arg0, 0),
+ TREE_OPERAND (arg1, 0))));
}
goto associate;
/* (-A) / (-B) -> A / B */
if (TREE_CODE (arg0) == NEGATE_EXPR && negate_expr_p (arg1))
- return fold (build (RDIV_EXPR, type,
- TREE_OPERAND (arg0, 0),
- negate_expr (arg1)));
+ return fold (build2 (RDIV_EXPR, type,
+ TREE_OPERAND (arg0, 0),
+ negate_expr (arg1)));
if (TREE_CODE (arg1) == NEGATE_EXPR && negate_expr_p (arg0))
- return fold (build (RDIV_EXPR, type,
- negate_expr (arg0),
- TREE_OPERAND (arg1, 0)));
+ return fold (build2 (RDIV_EXPR, type,
+ negate_expr (arg0),
+ TREE_OPERAND (arg1, 0)));
/* In IEEE floating point, x/1 is not equivalent to x for snans. */
if (!HONOR_SNANS (TYPE_MODE (TREE_TYPE (arg0)))
if (flag_unsafe_math_optimizations
&& 0 != (tem = const_binop (code, build_real (type, dconst1),
arg1, 0)))
- return fold (build (MULT_EXPR, type, arg0, tem));
+ return fold (build2 (MULT_EXPR, type, arg0, tem));
/* Find the reciprocal if optimizing and the result is exact. */
if (optimize)
{
if (exact_real_inverse (TYPE_MODE(TREE_TYPE(arg0)), &r))
{
tem = build_real (type, r);
- return fold (build (MULT_EXPR, type, arg0, tem));
+ return fold (build2 (MULT_EXPR, type, arg0, tem));
}
}
}
/* Convert A/B/C to A/(B*C). */
if (flag_unsafe_math_optimizations
&& TREE_CODE (arg0) == RDIV_EXPR)
- return fold (build (RDIV_EXPR, type, TREE_OPERAND (arg0, 0),
- fold (build (MULT_EXPR, type,
- TREE_OPERAND (arg0, 1), arg1))));
+ return fold (build2 (RDIV_EXPR, type, TREE_OPERAND (arg0, 0),
+ fold (build2 (MULT_EXPR, type,
+ TREE_OPERAND (arg0, 1), arg1))));
/* Convert A/(B/C) to (A/B)*C. */
if (flag_unsafe_math_optimizations
&& TREE_CODE (arg1) == RDIV_EXPR)
- return fold (build (MULT_EXPR, type,
- fold (build (RDIV_EXPR, type, arg0,
- TREE_OPERAND (arg1, 0))),
- TREE_OPERAND (arg1, 1)));
+ return fold (build2 (MULT_EXPR, type,
+ fold (build2 (RDIV_EXPR, type, arg0,
+ TREE_OPERAND (arg1, 0))),
+ TREE_OPERAND (arg1, 1)));
/* Convert C1/(X*C2) into (C1/C2)/X. */
if (flag_unsafe_math_optimizations
tree tem = const_binop (RDIV_EXPR, arg0,
TREE_OPERAND (arg1, 1), 0);
if (tem)
- return fold (build (RDIV_EXPR, type, tem,
- TREE_OPERAND (arg1, 0)));
+ return fold (build2 (RDIV_EXPR, type, tem,
+ TREE_OPERAND (arg1, 0)));
}
if (flag_unsafe_math_optimizations)
{
enum built_in_function fcode = builtin_mathfn_code (arg1);
/* Optimize x/expN(y) into x*expN(-y). */
- if (fcode == BUILT_IN_EXP
- || fcode == BUILT_IN_EXPF
- || fcode == BUILT_IN_EXPL
- || fcode == BUILT_IN_EXP2
- || fcode == BUILT_IN_EXP2F
- || fcode == BUILT_IN_EXP2L
- || fcode == BUILT_IN_EXP10
- || fcode == BUILT_IN_EXP10F
- || fcode == BUILT_IN_EXP10L
- || fcode == BUILT_IN_POW10
- || fcode == BUILT_IN_POW10F
- || fcode == BUILT_IN_POW10L)
+ if (BUILTIN_EXPONENT_P (fcode))
{
tree expfn = TREE_OPERAND (TREE_OPERAND (arg1, 0), 0);
- tree arg = build1 (NEGATE_EXPR, type,
- TREE_VALUE (TREE_OPERAND (arg1, 1)));
- tree arglist = build_tree_list (NULL_TREE, fold (arg));
+ 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);
- return fold (build (MULT_EXPR, type, arg0, arg1));
+ return fold (build2 (MULT_EXPR, type, arg0, arg1));
}
/* Optimize x/pow(y,z) into x*pow(y,-z). */
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 neg11 = fold (build1 (NEGATE_EXPR, type, arg11));
+ 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);
- return fold (build (MULT_EXPR, type, arg0, arg1));
+ return fold (build2 (MULT_EXPR, type, arg0, arg1));
}
}
&& operand_equal_p (TREE_VALUE (TREE_OPERAND (arg0, 1)),
TREE_VALUE (TREE_OPERAND (arg1, 1)), 0))
{
- tree tanfn;
-
- if (fcode0 == BUILT_IN_SIN)
- tanfn = implicit_built_in_decls[BUILT_IN_TAN];
- else if (fcode0 == BUILT_IN_SINF)
- tanfn = implicit_built_in_decls[BUILT_IN_TANF];
- else if (fcode0 == BUILT_IN_SINL)
- tanfn = implicit_built_in_decls[BUILT_IN_TANL];
- else
- tanfn = NULL_TREE;
+ tree tanfn = mathfn_built_in (type, BUILT_IN_TAN);
if (tanfn != NULL_TREE)
return build_function_call_expr (tanfn,
&& operand_equal_p (TREE_VALUE (TREE_OPERAND (arg0, 1)),
TREE_VALUE (TREE_OPERAND (arg1, 1)), 0))
{
- tree tanfn;
-
- if (fcode0 == BUILT_IN_COS)
- tanfn = implicit_built_in_decls[BUILT_IN_TAN];
- else if (fcode0 == BUILT_IN_COSF)
- tanfn = implicit_built_in_decls[BUILT_IN_TANF];
- else if (fcode0 == BUILT_IN_COSL)
- tanfn = implicit_built_in_decls[BUILT_IN_TANL];
- else
- tanfn = NULL_TREE;
+ 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);
- return fold (build (RDIV_EXPR, type,
- build_real (type, dconst1),
- tmp));
+ return fold (build2 (RDIV_EXPR, type,
+ build_real (type, dconst1), tmp));
}
}
return non_lvalue (fold_convert (type, arg0));
if (integer_zerop (arg1))
return t;
+ /* X / -1 is -X. */
+ if (!TYPE_UNSIGNED (type)
+ && TREE_CODE (arg1) == INTEGER_CST
+ && TREE_INT_CST_LOW (arg1) == (unsigned HOST_WIDE_INT) -1
+ && TREE_INT_CST_HIGH (arg1) == -1)
+ return fold_convert (type, negate_expr (arg0));
/* If arg0 is a multiple of arg1, then rewrite to the fastest div
operation, EXACT_DIV_EXPR.
after the last round to changes to the DIV code in expmed.c. */
if ((code == CEIL_DIV_EXPR || code == FLOOR_DIV_EXPR)
&& multiple_of_p (type, arg0, arg1))
- return fold (build (EXACT_DIV_EXPR, type, arg0, arg1));
+ return fold (build2 (EXACT_DIV_EXPR, type, arg0, arg1));
if (TREE_CODE (arg1) == INTEGER_CST
&& 0 != (tem = extract_muldiv (TREE_OPERAND (t, 0), arg1,
return omit_one_operand (type, integer_zero_node, arg0);
if (integer_zerop (arg1))
return t;
+ /* X % -1 is zero. */
+ if (!TYPE_UNSIGNED (type)
+ && TREE_CODE (arg1) == INTEGER_CST
+ && TREE_INT_CST_LOW (arg1) == (unsigned HOST_WIDE_INT) -1
+ && TREE_INT_CST_HIGH (arg1) == -1)
+ return omit_one_operand (type, integer_zero_node, arg0);
if (TREE_CODE (arg1) == INTEGER_CST
&& 0 != (tem = extract_muldiv (TREE_OPERAND (t, 0), arg1,
case RSHIFT_EXPR:
/* Optimize -1 >> x for arithmetic right shifts. */
- if (integer_all_onesp (arg0) && ! TREE_UNSIGNED (type))
+ if (integer_all_onesp (arg0) && !TYPE_UNSIGNED (type))
return omit_one_operand (type, arg0, arg1);
/* ... fall through ... */
tree tem = build_int_2 (GET_MODE_BITSIZE (TYPE_MODE (type)), 0);
tem = fold_convert (TREE_TYPE (arg1), tem);
tem = const_binop (MINUS_EXPR, tem, arg1, 0);
- return fold (build (RROTATE_EXPR, type, arg0, tem));
+ return fold (build2 (RROTATE_EXPR, type, arg0, tem));
}
/* If we have a rotate of a bit operation with the rotate count and
|| TREE_CODE (arg0) == BIT_IOR_EXPR
|| TREE_CODE (arg0) == BIT_XOR_EXPR)
&& TREE_CODE (TREE_OPERAND (arg0, 1)) == INTEGER_CST)
- return fold (build (TREE_CODE (arg0), type,
- fold (build (code, type,
- TREE_OPERAND (arg0, 0), arg1)),
- fold (build (code, type,
- TREE_OPERAND (arg0, 1), arg1))));
+ return fold (build2 (TREE_CODE (arg0), type,
+ fold (build2 (code, type,
+ TREE_OPERAND (arg0, 0), arg1)),
+ fold (build2 (code, type,
+ TREE_OPERAND (arg0, 1), arg1))));
/* Two consecutive rotates adding up to the width of the mode can
be ignored. */
if (operand_equal_p (arg0, arg1, 0))
return omit_one_operand (type, arg0, arg1);
if (INTEGRAL_TYPE_P (type)
- && operand_equal_p (arg1, TYPE_MIN_VALUE (type), 1))
+ && operand_equal_p (arg1, TYPE_MIN_VALUE (type), OEP_ONLY_CONST))
return omit_one_operand (type, arg1, arg0);
goto associate;
return omit_one_operand (type, arg0, arg1);
if (INTEGRAL_TYPE_P (type)
&& TYPE_MAX_VALUE (type)
- && operand_equal_p (arg1, TYPE_MAX_VALUE (type), 1))
+ && operand_equal_p (arg1, TYPE_MAX_VALUE (type), OEP_ONLY_CONST))
return omit_one_operand (type, arg1, arg0);
goto associate;
|| code == TRUTH_OR_EXPR));
if (operand_equal_p (a00, a10, 0))
- return fold (build (TREE_CODE (arg0), type, a00,
- fold (build (code, type, a01, a11))));
+ return fold (build2 (TREE_CODE (arg0), type, a00,
+ fold (build2 (code, type, a01, a11))));
else if (commutative && operand_equal_p (a00, a11, 0))
- return fold (build (TREE_CODE (arg0), type, a00,
- fold (build (code, type, a01, a10))));
+ return fold (build2 (TREE_CODE (arg0), type, a00,
+ fold (build2 (code, type, a01, a10))));
else if (commutative && operand_equal_p (a01, a10, 0))
- return fold (build (TREE_CODE (arg0), type, a01,
- fold (build (code, type, a00, a11))));
+ return fold (build2 (TREE_CODE (arg0), type, a01,
+ fold (build2 (code, type, a00, a11))));
/* This case if tricky because we must either have commutative
operators or else A10 must not have side-effects. */
else if ((commutative || ! TREE_SIDE_EFFECTS (a10))
&& operand_equal_p (a01, a11, 0))
- return fold (build (TREE_CODE (arg0), type,
- fold (build (code, type, a00, a10)),
- a01));
+ return fold (build2 (TREE_CODE (arg0), type,
+ fold (build2 (code, type, a00, a10)),
+ a01));
}
/* See if we can build a range comparison. */
if (TREE_CODE (arg0) == code
&& 0 != (tem = fold_truthop (code, type,
TREE_OPERAND (arg0, 1), arg1)))
- return fold (build (code, type, TREE_OPERAND (arg0, 0), tem));
+ return fold (build2 (code, type, TREE_OPERAND (arg0, 0), tem));
if ((tem = fold_truthop (code, type, arg0, arg1)) != 0)
return tem;
return non_lvalue (fold_convert (type, invert_truthvalue (arg1)));
if (integer_onep (arg1))
return non_lvalue (fold_convert (type, invert_truthvalue (arg0)));
+ /* Identical arguments cancel to zero. */
+ if (operand_equal_p (arg0, arg1, 0))
+ return omit_one_operand (type, integer_zero_node, arg0);
return t;
case EQ_EXPR:
case GE_EXPR:
/* If one arg is a real or integer constant, put it last. */
if (tree_swap_operands_p (arg0, arg1, true))
- return fold (build (swap_tree_comparison (code), type, arg1, arg0));
+ return fold (build2 (swap_tree_comparison (code), type, arg1, arg0));
- if (FLOAT_TYPE_P (TREE_TYPE (arg0)))
+ /* If this is an equality comparison of the address of a non-weak
+ object against zero, then we know the result. */
+ if ((code == EQ_EXPR || code == NE_EXPR)
+ && TREE_CODE (arg0) == ADDR_EXPR
+ && DECL_P (TREE_OPERAND (arg0, 0))
+ && ! DECL_WEAK (TREE_OPERAND (arg0, 0))
+ && integer_zerop (arg1))
{
- tree targ0 = strip_float_extensions (arg0);
- tree targ1 = strip_float_extensions (arg1);
- tree newtype = TREE_TYPE (targ0);
+ if (code == EQ_EXPR)
+ return fold_convert (type, integer_zero_node);
+ else
+ return fold_convert (type, integer_one_node);
+ }
- if (TYPE_PRECISION (TREE_TYPE (targ1)) > TYPE_PRECISION (newtype))
- newtype = TREE_TYPE (targ1);
+ /* If this is an equality comparison of the address of two non-weak,
+ unaliased symbols neither of which are extern (since we do not
+ have access to attributes for externs), then we know the result. */
+ if ((code == EQ_EXPR || code == NE_EXPR)
+ && TREE_CODE (arg0) == ADDR_EXPR
+ && DECL_P (TREE_OPERAND (arg0, 0))
+ && ! DECL_WEAK (TREE_OPERAND (arg0, 0))
+ && ! lookup_attribute ("alias",
+ DECL_ATTRIBUTES (TREE_OPERAND (arg0, 0)))
+ && ! DECL_EXTERNAL (TREE_OPERAND (arg0, 0))
+ && TREE_CODE (arg1) == ADDR_EXPR
+ && DECL_P (TREE_OPERAND (arg1, 0))
+ && ! DECL_WEAK (TREE_OPERAND (arg1, 0))
+ && ! lookup_attribute ("alias",
+ DECL_ATTRIBUTES (TREE_OPERAND (arg1, 0)))
+ && ! DECL_EXTERNAL (TREE_OPERAND (arg1, 0)))
+ {
+ if (code == EQ_EXPR)
+ return fold_convert (type, (operand_equal_p (arg0, arg1, 0)
+ ? integer_one_node : integer_zero_node));
+ else
+ return fold_convert (type, (operand_equal_p (arg0, arg1, 0)
+ ? integer_zero_node : integer_one_node));
+ }
+
+ if (FLOAT_TYPE_P (TREE_TYPE (arg0)))
+ {
+ tree targ0 = strip_float_extensions (arg0);
+ tree targ1 = strip_float_extensions (arg1);
+ tree newtype = TREE_TYPE (targ0);
+
+ if (TYPE_PRECISION (TREE_TYPE (targ1)) > TYPE_PRECISION (newtype))
+ newtype = TREE_TYPE (targ1);
/* Fold (double)float1 CMP (double)float2 into float1 CMP float2. */
if (TYPE_PRECISION (newtype) < TYPE_PRECISION (TREE_TYPE (arg0)))
- return fold (build (code, type, fold_convert (newtype, targ0),
- fold_convert (newtype, targ1)));
+ return fold (build2 (code, type, fold_convert (newtype, targ0),
+ fold_convert (newtype, targ1)));
/* (-a) CMP (-b) -> b CMP a */
if (TREE_CODE (arg0) == NEGATE_EXPR
&& TREE_CODE (arg1) == NEGATE_EXPR)
- return fold (build (code, type, TREE_OPERAND (arg1, 0),
- TREE_OPERAND (arg0, 0)));
+ return fold (build2 (code, type, TREE_OPERAND (arg1, 0),
+ TREE_OPERAND (arg0, 0)));
if (TREE_CODE (arg1) == REAL_CST)
{
/* (-a) CMP CST -> a swap(CMP) (-CST) */
if (TREE_CODE (arg0) == NEGATE_EXPR)
return
- fold (build (swap_tree_comparison (code), type,
- TREE_OPERAND (arg0, 0),
- build_real (TREE_TYPE (arg1),
- REAL_VALUE_NEGATE (cst))));
+ fold (build2 (swap_tree_comparison (code), type,
+ TREE_OPERAND (arg0, 0),
+ build_real (TREE_TYPE (arg1),
+ REAL_VALUE_NEGATE (cst))));
/* IEEE doesn't distinguish +0 and -0 in comparisons. */
/* a CMP (-0) -> a CMP 0 */
if (REAL_VALUE_MINUS_ZERO (cst))
- return fold (build (code, type, arg0,
- build_real (TREE_TYPE (arg1), dconst0)));
+ return fold (build2 (code, type, arg0,
+ build_real (TREE_TYPE (arg1), dconst0)));
/* x != NaN is always true, other ops are always false. */
if (REAL_VALUE_ISNAN (cst)
&& ! HONOR_SNANS (TYPE_MODE (TREE_TYPE (arg1))))
{
- t = (code == NE_EXPR) ? integer_one_node : integer_zero_node;
- return omit_one_operand (type, fold_convert (type, t), arg0);
+ tem = (code == NE_EXPR) ? integer_one_node : integer_zero_node;
+ return omit_one_operand (type, fold_convert (type, tem), arg0);
}
/* Fold comparisons against infinity. */
? MINUS_EXPR : PLUS_EXPR,
arg1, TREE_OPERAND (arg0, 1), 0))
&& ! TREE_CONSTANT_OVERFLOW (tem))
- return fold (build (code, type, TREE_OPERAND (arg0, 0), tem));
+ return fold (build2 (code, type, TREE_OPERAND (arg0, 0), tem));
/* Likewise, we can simplify a comparison of a real constant with
a MINUS_EXPR whose first operand is also a real constant, i.e.
&& 0 != (tem = const_binop (MINUS_EXPR, TREE_OPERAND (arg0, 0),
arg1, 0))
&& ! TREE_CONSTANT_OVERFLOW (tem))
- return fold (build (swap_tree_comparison (code), type,
- TREE_OPERAND (arg0, 1), tem));
+ return fold (build2 (swap_tree_comparison (code), type,
+ TREE_OPERAND (arg0, 1), tem));
/* Fold comparisons against built-in math functions. */
if (TREE_CODE (arg1) == REAL_CST
}
}
- /* Convert foo++ == CONST into ++foo == CONST + INCR.
- First, see if one arg is constant; find the constant arg
- and the other one. */
- {
- tree constop = 0, varop = NULL_TREE;
- int constopnum = -1;
+ /* Convert foo++ == CONST into ++foo == CONST + INCR. */
+ if (TREE_CONSTANT (arg1)
+ && (TREE_CODE (arg0) == POSTINCREMENT_EXPR
+ || TREE_CODE (arg0) == POSTDECREMENT_EXPR)
+ /* This optimization is invalid for ordered comparisons
+ if CONST+INCR overflows or if foo+incr might overflow.
+ This optimization is invalid for floating point due to rounding.
+ For pointer types we assume overflow doesn't happen. */
+ && (POINTER_TYPE_P (TREE_TYPE (arg0))
+ || (INTEGRAL_TYPE_P (TREE_TYPE (arg0))
+ && (code == EQ_EXPR || code == NE_EXPR))))
+ {
+ tree varop, newconst;
- if (TREE_CONSTANT (arg1))
- constopnum = 1, constop = arg1, varop = arg0;
- if (TREE_CONSTANT (arg0))
- constopnum = 0, constop = arg0, varop = arg1;
+ if (TREE_CODE (arg0) == POSTINCREMENT_EXPR)
+ {
+ newconst = fold (build2 (PLUS_EXPR, TREE_TYPE (arg0),
+ arg1, TREE_OPERAND (arg0, 1)));
+ varop = build2 (PREINCREMENT_EXPR, TREE_TYPE (arg0),
+ TREE_OPERAND (arg0, 0),
+ TREE_OPERAND (arg0, 1));
+ }
+ else
+ {
+ newconst = fold (build2 (MINUS_EXPR, TREE_TYPE (arg0),
+ arg1, TREE_OPERAND (arg0, 1)));
+ varop = build2 (PREDECREMENT_EXPR, TREE_TYPE (arg0),
+ TREE_OPERAND (arg0, 0),
+ TREE_OPERAND (arg0, 1));
+ }
- if (constop && TREE_CODE (varop) == POSTINCREMENT_EXPR)
- {
- /* This optimization is invalid for ordered comparisons
- if CONST+INCR overflows or if foo+incr might overflow.
- This optimization is invalid for floating point due to rounding.
- For pointer types we assume overflow doesn't happen. */
- if (POINTER_TYPE_P (TREE_TYPE (varop))
- || (! FLOAT_TYPE_P (TREE_TYPE (varop))
- && (code == EQ_EXPR || code == NE_EXPR)))
- {
- tree newconst
- = fold (build (PLUS_EXPR, TREE_TYPE (varop),
- constop, TREE_OPERAND (varop, 1)));
-
- /* Do not overwrite the current varop to be a preincrement,
- create a new node so that we won't confuse our caller who
- might create trees and throw them away, reusing the
- arguments that they passed to build. This shows up in
- the THEN or ELSE parts of ?: being postincrements. */
- varop = build (PREINCREMENT_EXPR, TREE_TYPE (varop),
- TREE_OPERAND (varop, 0),
- TREE_OPERAND (varop, 1));
-
- /* If VAROP is a reference to a bitfield, we must mask
- the constant by the width of the field. */
- if (TREE_CODE (TREE_OPERAND (varop, 0)) == COMPONENT_REF
- && DECL_BIT_FIELD(TREE_OPERAND
- (TREE_OPERAND (varop, 0), 1)))
- {
- int size
- = TREE_INT_CST_LOW (DECL_SIZE
- (TREE_OPERAND
- (TREE_OPERAND (varop, 0), 1)));
- tree mask, unsigned_type;
- unsigned int precision;
- tree folded_compare;
-
- /* First check whether the comparison would come out
- always the same. If we don't do that we would
- change the meaning with the masking. */
- if (constopnum == 0)
- folded_compare = fold (build (code, type, constop,
- TREE_OPERAND (varop, 0)));
- else
- folded_compare = fold (build (code, type,
- TREE_OPERAND (varop, 0),
- constop));
- if (integer_zerop (folded_compare)
- || integer_onep (folded_compare))
- return omit_one_operand (type, folded_compare, varop);
-
- unsigned_type = (*lang_hooks.types.type_for_size)(size, 1);
- precision = TYPE_PRECISION (unsigned_type);
- mask = build_int_2 (~0, ~0);
- TREE_TYPE (mask) = unsigned_type;
- force_fit_type (mask, 0);
- mask = const_binop (RSHIFT_EXPR, mask,
- size_int (precision - size), 0);
- newconst = fold (build (BIT_AND_EXPR,
- TREE_TYPE (varop), newconst,
- fold_convert (TREE_TYPE (varop),
- mask)));
- }
- t = build (code, type,
- (constopnum == 0) ? newconst : varop,
- (constopnum == 1) ? newconst : varop);
- return t;
- }
- }
- else if (constop && TREE_CODE (varop) == POSTDECREMENT_EXPR)
- {
- if (POINTER_TYPE_P (TREE_TYPE (varop))
- || (! FLOAT_TYPE_P (TREE_TYPE (varop))
- && (code == EQ_EXPR || code == NE_EXPR)))
- {
- tree newconst
- = fold (build (MINUS_EXPR, TREE_TYPE (varop),
- constop, TREE_OPERAND (varop, 1)));
-
- /* Do not overwrite the current varop to be a predecrement,
- create a new node so that we won't confuse our caller who
- might create trees and throw them away, reusing the
- arguments that they passed to build. This shows up in
- the THEN or ELSE parts of ?: being postdecrements. */
- varop = build (PREDECREMENT_EXPR, TREE_TYPE (varop),
- TREE_OPERAND (varop, 0),
- TREE_OPERAND (varop, 1));
-
- if (TREE_CODE (TREE_OPERAND (varop, 0)) == COMPONENT_REF
- && DECL_BIT_FIELD(TREE_OPERAND
- (TREE_OPERAND (varop, 0), 1)))
- {
- int size
- = TREE_INT_CST_LOW (DECL_SIZE
- (TREE_OPERAND
- (TREE_OPERAND (varop, 0), 1)));
- tree mask, unsigned_type;
- unsigned int precision;
- tree folded_compare;
-
- if (constopnum == 0)
- folded_compare = fold (build (code, type, constop,
- TREE_OPERAND (varop, 0)));
- else
- folded_compare = fold (build (code, type,
- TREE_OPERAND (varop, 0),
- constop));
- if (integer_zerop (folded_compare)
- || integer_onep (folded_compare))
- return omit_one_operand (type, folded_compare, varop);
-
- unsigned_type = (*lang_hooks.types.type_for_size)(size, 1);
- precision = TYPE_PRECISION (unsigned_type);
- mask = build_int_2 (~0, ~0);
- TREE_TYPE (mask) = TREE_TYPE (varop);
- force_fit_type (mask, 0);
- mask = const_binop (RSHIFT_EXPR, mask,
- size_int (precision - size), 0);
- newconst = fold (build (BIT_AND_EXPR,
- TREE_TYPE (varop), newconst,
- fold_convert (TREE_TYPE (varop),
- mask)));
- }
+ /* If VAROP is a reference to a bitfield, we must mask
+ the constant by the width of the field. */
+ if (TREE_CODE (TREE_OPERAND (varop, 0)) == COMPONENT_REF
+ && DECL_BIT_FIELD (TREE_OPERAND (TREE_OPERAND (varop, 0), 1)))
+ {
+ tree fielddecl = TREE_OPERAND (TREE_OPERAND (varop, 0), 1);
+ int size = TREE_INT_CST_LOW (DECL_SIZE (fielddecl));
+ tree folded_compare, shift;
+
+ /* First check whether the comparison would come out
+ always the same. If we don't do that we would
+ change the meaning with the masking. */
+ folded_compare = fold (build2 (code, type,
+ TREE_OPERAND (varop, 0),
+ arg1));
+ if (integer_zerop (folded_compare)
+ || integer_onep (folded_compare))
+ return omit_one_operand (type, folded_compare, varop);
+
+ shift = build_int_2 (TYPE_PRECISION (TREE_TYPE (varop)) - size,
+ 0);
+ newconst = fold (build2 (LSHIFT_EXPR, TREE_TYPE (varop),
+ newconst, shift));
+ newconst = fold (build2 (RSHIFT_EXPR, TREE_TYPE (varop),
+ newconst, shift));
+ }
- t = build (code, type,
- (constopnum == 0) ? newconst : varop,
- (constopnum == 1) ? newconst : varop);
- return t;
- }
- }
- }
+ return fold (build2 (code, type, varop, newconst));
+ }
/* Change X >= C to X > (C - 1) and X < C to X <= (C - 1) if C > 0.
This transformation affects the cases which are handled in later
{
case GE_EXPR:
arg1 = const_binop (MINUS_EXPR, arg1, integer_one_node, 0);
- return fold (build (GT_EXPR, type, arg0, arg1));
+ return fold (build2 (GT_EXPR, type, arg0, arg1));
case LT_EXPR:
arg1 = const_binop (MINUS_EXPR, arg1, integer_one_node, 0);
- return fold (build (LE_EXPR, type, arg0, arg1));
+ return fold (build2 (LE_EXPR, type, arg0, arg1));
default:
break;
}
/* Comparisons with the highest or lowest possible integer of
- the specified size will have known values. */
+ the specified size will have known values.
+
+ This is quite similar to fold_relational_hi_lo; however, my
+ attempts to share the code have been nothing but trouble.
+ I give up for now. */
{
int width = GET_MODE_BITSIZE (TYPE_MODE (TREE_TYPE (arg1)));
signed_max = ((unsigned HOST_WIDE_INT) 1 << (width - 1)) - 1;
- if (TREE_UNSIGNED (TREE_TYPE (arg1)))
+ if (TYPE_UNSIGNED (TREE_TYPE (arg1)))
{
max = ((unsigned HOST_WIDE_INT) 2 << (width - 1)) - 1;
min = 0;
integer_zero_node),
arg0);
case GE_EXPR:
- return fold (build (EQ_EXPR, type, arg0, arg1));
+ return fold (build2 (EQ_EXPR, type, arg0, arg1));
case LE_EXPR:
return omit_one_operand (type,
integer_one_node),
arg0);
case LT_EXPR:
- return fold (build (NE_EXPR, type, arg0, arg1));
+ return fold (build2 (NE_EXPR, type, arg0, arg1));
/* The GE_EXPR and LT_EXPR cases above are not normally
reached because of previous transformations. */
{
case GT_EXPR:
arg1 = const_binop (PLUS_EXPR, arg1, integer_one_node, 0);
- return fold (build (EQ_EXPR, type, arg0, arg1));
+ return fold (build2 (EQ_EXPR, type, arg0, arg1));
case LE_EXPR:
arg1 = const_binop (PLUS_EXPR, arg1, integer_one_node, 0);
- return fold (build (NE_EXPR, type, arg0, arg1));
+ return fold (build2 (NE_EXPR, type, arg0, arg1));
default:
break;
}
integer_zero_node),
arg0);
case LE_EXPR:
- return fold (build (EQ_EXPR, type, arg0, arg1));
+ return fold (build2 (EQ_EXPR, type, arg0, arg1));
case GE_EXPR:
return omit_one_operand (type,
integer_one_node),
arg0);
case GT_EXPR:
- return fold (build (NE_EXPR, type, arg0, arg1));
+ return fold (build2 (NE_EXPR, type, arg0, arg1));
default:
break;
{
case GE_EXPR:
arg1 = const_binop (MINUS_EXPR, arg1, integer_one_node, 0);
- return fold (build (NE_EXPR, type, arg0, arg1));
+ return fold (build2 (NE_EXPR, type, arg0, arg1));
case LT_EXPR:
arg1 = const_binop (MINUS_EXPR, arg1, integer_one_node, 0);
- return fold (build (EQ_EXPR, type, arg0, arg1));
+ return fold (build2 (EQ_EXPR, type, arg0, arg1));
default:
break;
}
- else if (TREE_INT_CST_HIGH (arg1) == 0
+ else if (!in_gimple_form
+ && TREE_INT_CST_HIGH (arg1) == 0
&& TREE_INT_CST_LOW (arg1) == signed_max
- && TREE_UNSIGNED (TREE_TYPE (arg1))
+ && TYPE_UNSIGNED (TREE_TYPE (arg1))
/* signed_type does not work on pointer types. */
&& INTEGRAL_TYPE_P (TREE_TYPE (arg1)))
{
if (code == LE_EXPR || code == GT_EXPR)
{
tree st0, st1;
- st0 = (*lang_hooks.types.signed_type) (TREE_TYPE (arg0));
- st1 = (*lang_hooks.types.signed_type) (TREE_TYPE (arg1));
+ st0 = lang_hooks.types.signed_type (TREE_TYPE (arg0));
+ st1 = lang_hooks.types.signed_type (TREE_TYPE (arg1));
return fold
- (build (code == LE_EXPR ? GE_EXPR: LT_EXPR,
- type, fold_convert (st0, arg0),
- fold_convert (st1, integer_zero_node)));
+ (build2 (code == LE_EXPR ? GE_EXPR: LT_EXPR,
+ type, fold_convert (st0, arg0),
+ fold_convert (st1, integer_zero_node)));
}
}
}
? MINUS_EXPR : PLUS_EXPR,
arg1, TREE_OPERAND (arg0, 1), 0))
&& ! TREE_CONSTANT_OVERFLOW (tem))
- return fold (build (code, type, TREE_OPERAND (arg0, 0), tem));
+ return fold (build2 (code, type, TREE_OPERAND (arg0, 0), tem));
/* Similarly for a NEGATE_EXPR. */
else if ((code == EQ_EXPR || code == NE_EXPR)
&& 0 != (tem = negate_expr (arg1))
&& TREE_CODE (tem) == INTEGER_CST
&& ! TREE_CONSTANT_OVERFLOW (tem))
- return fold (build (code, type, TREE_OPERAND (arg0, 0), tem));
+ return fold (build2 (code, type, TREE_OPERAND (arg0, 0), tem));
/* If we have X - Y == 0, we can convert that to X == Y and similarly
for !=. Don't do this for ordered comparisons due to overflow. */
else if ((code == NE_EXPR || code == EQ_EXPR)
&& integer_zerop (arg1) && TREE_CODE (arg0) == MINUS_EXPR)
- return fold (build (code, type,
- TREE_OPERAND (arg0, 0), TREE_OPERAND (arg0, 1)));
+ return fold (build2 (code, type,
+ TREE_OPERAND (arg0, 0), TREE_OPERAND (arg0, 1)));
/* If we are widening one operand of an integer comparison,
see if the other operand is similarly being widened. Perhaps we
else if (TREE_CODE (TREE_TYPE (arg0)) == INTEGER_TYPE
&& TREE_CODE (arg0) == NOP_EXPR
&& (tem = get_unwidened (arg0, NULL_TREE)) != arg0
+ && (code == EQ_EXPR || code == NE_EXPR
+ || TYPE_UNSIGNED (TREE_TYPE (arg0))
+ == TYPE_UNSIGNED (TREE_TYPE (tem)))
&& (t1 = get_unwidened (arg1, TREE_TYPE (tem))) != 0
&& (TREE_TYPE (t1) == TREE_TYPE (tem)
|| (TREE_CODE (t1) == INTEGER_CST
&& int_fits_type_p (t1, TREE_TYPE (tem)))))
- return fold (build (code, type, tem,
- fold_convert (TREE_TYPE (tem), t1)));
+ return fold (build2 (code, type, tem,
+ fold_convert (TREE_TYPE (tem), t1)));
/* If this is comparing a constant with a MIN_EXPR or a MAX_EXPR of a
constant, we can simplify it. */
&& (0 != (tem = negate_expr (arg1)))
&& TREE_CODE (tem) == INTEGER_CST
&& ! TREE_CONSTANT_OVERFLOW (tem))
- return fold (build (TRUTH_ANDIF_EXPR, type,
- build (GE_EXPR, type, TREE_OPERAND (arg0, 0), tem),
- build (LE_EXPR, type,
- TREE_OPERAND (arg0, 0), arg1)));
+ return fold (build2 (TRUTH_ANDIF_EXPR, type,
+ build2 (GE_EXPR, type,
+ TREE_OPERAND (arg0, 0), tem),
+ build2 (LE_EXPR, type,
+ TREE_OPERAND (arg0, 0), arg1)));
/* If this is an EQ or NE comparison with zero and ARG0 is
(1 << foo) & bar, convert it to (bar >> foo) & 1. Both require
if (integer_zerop (arg1) && (code == EQ_EXPR || code == NE_EXPR)
&& TREE_CODE (arg0) == BIT_AND_EXPR)
{
- if (TREE_CODE (TREE_OPERAND (arg0, 0)) == LSHIFT_EXPR
- && integer_onep (TREE_OPERAND (TREE_OPERAND (arg0, 0), 0)))
+ tree arg00 = TREE_OPERAND (arg0, 0);
+ tree arg01 = TREE_OPERAND (arg0, 1);
+ if (TREE_CODE (arg00) == LSHIFT_EXPR
+ && integer_onep (TREE_OPERAND (arg00, 0)))
return
- fold (build (code, type,
- build (BIT_AND_EXPR, TREE_TYPE (arg0),
- build (RSHIFT_EXPR,
- TREE_TYPE (TREE_OPERAND (arg0, 0)),
- TREE_OPERAND (arg0, 1),
- TREE_OPERAND (TREE_OPERAND (arg0, 0), 1)),
- fold_convert (TREE_TYPE (arg0),
- integer_one_node)),
- arg1));
+ fold (build2 (code, type,
+ build2 (BIT_AND_EXPR, TREE_TYPE (arg0),
+ build2 (RSHIFT_EXPR, TREE_TYPE (arg00),
+ arg01, TREE_OPERAND (arg00, 1)),
+ fold_convert (TREE_TYPE (arg0),
+ integer_one_node)),
+ arg1));
else if (TREE_CODE (TREE_OPERAND (arg0, 1)) == LSHIFT_EXPR
&& integer_onep (TREE_OPERAND (TREE_OPERAND (arg0, 1), 0)))
return
- fold (build (code, type,
- build (BIT_AND_EXPR, TREE_TYPE (arg0),
- build (RSHIFT_EXPR,
- TREE_TYPE (TREE_OPERAND (arg0, 1)),
- TREE_OPERAND (arg0, 0),
- TREE_OPERAND (TREE_OPERAND (arg0, 1), 1)),
- fold_convert (TREE_TYPE (arg0),
- integer_one_node)),
- arg1));
+ fold (build2 (code, type,
+ build2 (BIT_AND_EXPR, TREE_TYPE (arg0),
+ build2 (RSHIFT_EXPR, TREE_TYPE (arg01),
+ arg00, TREE_OPERAND (arg01, 1)),
+ fold_convert (TREE_TYPE (arg0),
+ integer_one_node)),
+ arg1));
}
/* If this is an NE or EQ comparison of zero against the result of a
the MOD operation unsigned since it is simpler and equivalent. */
if ((code == NE_EXPR || code == EQ_EXPR)
&& integer_zerop (arg1)
- && ! TREE_UNSIGNED (TREE_TYPE (arg0))
+ && !TYPE_UNSIGNED (TREE_TYPE (arg0))
&& (TREE_CODE (arg0) == TRUNC_MOD_EXPR
|| TREE_CODE (arg0) == CEIL_MOD_EXPR
|| TREE_CODE (arg0) == FLOOR_MOD_EXPR
|| TREE_CODE (arg0) == ROUND_MOD_EXPR)
&& integer_pow2p (TREE_OPERAND (arg0, 1)))
{
- tree newtype = (*lang_hooks.types.unsigned_type) (TREE_TYPE (arg0));
- tree newmod = build (TREE_CODE (arg0), newtype,
- fold_convert (newtype,
- TREE_OPERAND (arg0, 0)),
- fold_convert (newtype,
- TREE_OPERAND (arg0, 1)));
-
- return build (code, type, newmod, fold_convert (newtype, arg1));
+ tree newtype = lang_hooks.types.unsigned_type (TREE_TYPE (arg0));
+ tree newmod = build2 (TREE_CODE (arg0), newtype,
+ fold_convert (newtype,
+ TREE_OPERAND (arg0, 0)),
+ fold_convert (newtype,
+ TREE_OPERAND (arg0, 1)));
+
+ return build2 (code, type, newmod, fold_convert (newtype, arg1));
}
/* If this is an NE comparison of zero with an AND of one, remove the
&& TREE_CODE (arg0) == BIT_AND_EXPR
&& integer_pow2p (TREE_OPERAND (arg0, 1))
&& operand_equal_p (TREE_OPERAND (arg0, 1), arg1, 0))
- return fold (build (code == EQ_EXPR ? NE_EXPR : EQ_EXPR, type,
- arg0, integer_zero_node));
+ return fold (build2 (code == EQ_EXPR ? NE_EXPR : EQ_EXPR, type,
+ arg0, integer_zero_node));
/* If we have (A & C) != 0 or (A & C) == 0 and C is a power of
2, then fold the expression into shifts and logical operations. */
&& TREE_CODE (TREE_OPERAND (arg0, 1)) == INTEGER_CST)
{
tree dandnotc
- = fold (build (BIT_AND_EXPR, TREE_TYPE (arg0),
- arg1, build1 (BIT_NOT_EXPR,
- TREE_TYPE (TREE_OPERAND (arg0, 1)),
- TREE_OPERAND (arg0, 1))));
+ = fold (build2 (BIT_AND_EXPR, TREE_TYPE (arg0),
+ arg1, build1 (BIT_NOT_EXPR,
+ TREE_TYPE (TREE_OPERAND (arg0, 1)),
+ TREE_OPERAND (arg0, 1))));
tree rslt = code == EQ_EXPR ? integer_zero_node : integer_one_node;
if (integer_nonzerop (dandnotc))
return omit_one_operand (type, rslt, arg0);
&& TREE_CODE (TREE_OPERAND (arg0, 1)) == INTEGER_CST)
{
tree candnotd
- = fold (build (BIT_AND_EXPR, TREE_TYPE (arg0),
- TREE_OPERAND (arg0, 1),
- build1 (BIT_NOT_EXPR, TREE_TYPE (arg1), arg1)));
+ = fold (build2 (BIT_AND_EXPR, TREE_TYPE (arg0),
+ TREE_OPERAND (arg0, 1),
+ build1 (BIT_NOT_EXPR, TREE_TYPE (arg1), arg1)));
tree rslt = code == EQ_EXPR ? integer_zero_node : integer_one_node;
if (integer_nonzerop (candnotd))
return omit_one_operand (type, rslt, arg0);
/* If X is unsigned, convert X < (1 << Y) into X >> Y == 0
and similarly for >= into !=. */
if ((code == LT_EXPR || code == GE_EXPR)
- && TREE_UNSIGNED (TREE_TYPE (arg0))
+ && TYPE_UNSIGNED (TREE_TYPE (arg0))
&& TREE_CODE (arg1) == LSHIFT_EXPR
&& integer_onep (TREE_OPERAND (arg1, 0)))
- return build (code == LT_EXPR ? EQ_EXPR : NE_EXPR, type,
- build (RSHIFT_EXPR, TREE_TYPE (arg0), arg0,
- TREE_OPERAND (arg1, 1)),
- fold_convert (TREE_TYPE (arg0), integer_zero_node));
+ return build2 (code == LT_EXPR ? EQ_EXPR : NE_EXPR, type,
+ build2 (RSHIFT_EXPR, TREE_TYPE (arg0), arg0,
+ TREE_OPERAND (arg1, 1)),
+ fold_convert (TREE_TYPE (arg0), integer_zero_node));
else if ((code == LT_EXPR || code == GE_EXPR)
- && TREE_UNSIGNED (TREE_TYPE (arg0))
+ && TYPE_UNSIGNED (TREE_TYPE (arg0))
&& (TREE_CODE (arg1) == NOP_EXPR
|| TREE_CODE (arg1) == CONVERT_EXPR)
&& TREE_CODE (TREE_OPERAND (arg1, 0)) == LSHIFT_EXPR
&& integer_onep (TREE_OPERAND (TREE_OPERAND (arg1, 0), 0)))
return
- build (code == LT_EXPR ? EQ_EXPR : NE_EXPR, type,
- fold_convert (TREE_TYPE (arg0),
- build (RSHIFT_EXPR, TREE_TYPE (arg0), arg0,
- TREE_OPERAND (TREE_OPERAND (arg1, 0),
- 1))),
- fold_convert (TREE_TYPE (arg0), integer_zero_node));
+ build2 (code == LT_EXPR ? EQ_EXPR : NE_EXPR, type,
+ fold_convert (TREE_TYPE (arg0),
+ build2 (RSHIFT_EXPR, TREE_TYPE (arg0), arg0,
+ TREE_OPERAND (TREE_OPERAND (arg1, 0),
+ 1))),
+ fold_convert (TREE_TYPE (arg0), integer_zero_node));
/* Simplify comparison of something with itself. (For IEEE
floating-point, we can only do some of these simplifications.) */
if (! FLOAT_TYPE_P (TREE_TYPE (arg0))
|| ! HONOR_NANS (TYPE_MODE (TREE_TYPE (arg0))))
return constant_boolean_node (1, type);
- return fold (build (EQ_EXPR, type, arg0, arg1));
+ return fold (build2 (EQ_EXPR, type, arg0, arg1));
case NE_EXPR:
/* For NE, we can only do this simplification if integer
was the same as ARG1. */
tree high_result
- = fold (build (code, type,
- eval_subst (arg0, cval1, maxval, cval2, minval),
- arg1));
+ = fold (build2 (code, type,
+ eval_subst (arg0, cval1, maxval,
+ cval2, minval),
+ arg1));
tree equal_result
- = fold (build (code, type,
- eval_subst (arg0, cval1, maxval, cval2, maxval),
- arg1));
+ = fold (build2 (code, type,
+ eval_subst (arg0, cval1, maxval,
+ cval2, maxval),
+ arg1));
tree low_result
- = fold (build (code, type,
- eval_subst (arg0, cval1, minval, cval2, maxval),
- arg1));
+ = fold (build2 (code, type,
+ eval_subst (arg0, cval1, minval,
+ cval2, maxval),
+ arg1));
/* All three of these results should be 0 or 1. Confirm they
are. Then use those values to select the proper code
return omit_one_operand (type, integer_one_node, arg0);
}
- t = build (code, type, cval1, cval2);
+ tem = build2 (code, type, cval1, cval2);
if (save_p)
- return save_expr (t);
+ return save_expr (tem);
else
- return fold (t);
+ return fold (tem);
}
}
}
/* If this is a comparison of a field, we may be able to simplify it. */
if (((TREE_CODE (arg0) == COMPONENT_REF
- && (*lang_hooks.can_use_bit_fields_p) ())
+ && lang_hooks.can_use_bit_fields_p ())
|| TREE_CODE (arg0) == BIT_FIELD_REF)
&& (code == EQ_EXPR || code == NE_EXPR)
/* Handle the constant case even without -O
real1 = fold (build1 (REALPART_EXPR, subtype, arg1));
imag1 = fold (build1 (IMAGPART_EXPR, subtype, arg1));
- return fold (build ((code == EQ_EXPR ? TRUTH_ANDIF_EXPR
- : TRUTH_ORIF_EXPR),
- type,
- fold (build (code, type, real0, real1)),
- fold (build (code, type, imag0, imag1))));
+ return fold (build2 ((code == EQ_EXPR ? TRUTH_ANDIF_EXPR
+ : TRUTH_ORIF_EXPR),
+ type,
+ fold (build2 (code, type, real0, real1)),
+ fold (build2 (code, type, imag0, imag1))));
}
/* Optimize comparisons of strlen vs zero to a compare of the
&& (arglist = TREE_OPERAND (arg0, 1))
&& TREE_CODE (TREE_TYPE (TREE_VALUE (arglist))) == POINTER_TYPE
&& ! TREE_CHAIN (arglist))
- return fold (build (code, type,
- build1 (INDIRECT_REF, char_type_node,
- TREE_VALUE(arglist)),
- integer_zero_node));
+ return fold (build2 (code, type,
+ build1 (INDIRECT_REF, char_type_node,
+ TREE_VALUE(arglist)),
+ integer_zero_node));
}
- /* From here on, the only cases we handle are when the result is
- known to be a constant.
-
- To compute GT, swap the arguments and do LT.
- To compute GE, do LT and invert the result.
- To compute LE, swap the arguments, do LT and invert the result.
- To compute NE, do EQ and invert the result.
-
- Therefore, the code below must handle only EQ and LT. */
-
- if (code == LE_EXPR || code == GT_EXPR)
- {
- tem = arg0, arg0 = arg1, arg1 = tem;
- code = swap_tree_comparison (code);
- }
-
- /* Note that it is safe to invert for real values here because we
- will check below in the one case that it matters. */
-
- t1 = NULL_TREE;
- invert = 0;
- if (code == NE_EXPR || code == GE_EXPR)
- {
- invert = 1;
- code = invert_tree_comparison (code);
- }
-
- /* Compute a result for LT or EQ if args permit;
- otherwise return T. */
- if (TREE_CODE (arg0) == INTEGER_CST && TREE_CODE (arg1) == INTEGER_CST)
+ /* We can fold X/C1 op C2 where C1 and C2 are integer constants
+ into a single range test. */
+ if (TREE_CODE (arg0) == TRUNC_DIV_EXPR
+ && TREE_CODE (arg1) == INTEGER_CST
+ && TREE_CODE (TREE_OPERAND (arg0, 1)) == INTEGER_CST
+ && !integer_zerop (TREE_OPERAND (arg0, 1))
+ && !TREE_OVERFLOW (TREE_OPERAND (arg0, 1))
+ && !TREE_OVERFLOW (arg1))
{
- if (code == EQ_EXPR)
- t1 = build_int_2 (tree_int_cst_equal (arg0, arg1), 0);
- else
- t1 = build_int_2 ((TREE_UNSIGNED (TREE_TYPE (arg0))
- ? INT_CST_LT_UNSIGNED (arg0, arg1)
- : INT_CST_LT (arg0, arg1)),
- 0);
- }
-
-#if 0 /* This is no longer useful, but breaks some real code. */
- /* Assume a nonexplicit constant cannot equal an explicit one,
- since such code would be undefined anyway.
- Exception: on sysvr4, using #pragma weak,
- a label can come out as 0. */
- else if (TREE_CODE (arg1) == INTEGER_CST
- && !integer_zerop (arg1)
- && TREE_CONSTANT (arg0)
- && TREE_CODE (arg0) == ADDR_EXPR
- && code == EQ_EXPR)
- t1 = build_int_2 (0, 0);
-#endif
- /* Two real constants can be compared explicitly. */
- else if (TREE_CODE (arg0) == REAL_CST && TREE_CODE (arg1) == REAL_CST)
- {
- /* If either operand is a NaN, the result is false with two
- exceptions: First, an NE_EXPR is true on NaNs, but that case
- is already handled correctly since we will be inverting the
- result for NE_EXPR. Second, if we had inverted a LE_EXPR
- or a GE_EXPR into a LT_EXPR, we must return true so that it
- will be inverted into false. */
-
- if (REAL_VALUE_ISNAN (TREE_REAL_CST (arg0))
- || REAL_VALUE_ISNAN (TREE_REAL_CST (arg1)))
- t1 = build_int_2 (invert && code == LT_EXPR, 0);
-
- else if (code == EQ_EXPR)
- t1 = build_int_2 (REAL_VALUES_EQUAL (TREE_REAL_CST (arg0),
- TREE_REAL_CST (arg1)),
- 0);
- else
- t1 = build_int_2 (REAL_VALUES_LESS (TREE_REAL_CST (arg0),
- TREE_REAL_CST (arg1)),
- 0);
+ t1 = fold_div_compare (code, type, arg0, arg1);
+ if (t1 != NULL_TREE)
+ return t1;
}
- if (t1 == NULL_TREE)
- return t;
-
- if (invert)
- TREE_INT_CST_LOW (t1) ^= 1;
-
- TREE_TYPE (t1) = type;
- if (TREE_CODE (type) == BOOLEAN_TYPE)
- return (*lang_hooks.truthvalue_conversion) (t1);
- return t1;
+ /* Both ARG0 and ARG1 are known to be constants at this point. */
+ t1 = fold_relational_const (code, type, arg0, arg1);
+ return (t1 == NULL_TREE ? t : t1);
case COND_EXPR:
/* Pedantic ANSI C says that a conditional expression is never an lvalue,
has the same type as the COND_EXPR. This avoids optimizing
away "c ? x : throw", where the throw has a void type. */
if (! VOID_TYPE_P (TREE_TYPE (tem))
- || VOID_TYPE_P (TREE_TYPE (t)))
+ || VOID_TYPE_P (type))
return pedantic_non_lvalue (tem);
return t;
}
- if (operand_equal_p (arg1, TREE_OPERAND (expr, 2), 0))
+ if (operand_equal_p (arg1, TREE_OPERAND (t, 2), 0))
return pedantic_omit_one_operand (type, arg1, arg0);
/* If we have A op B ? A : C, we may be able to convert this to a
return pedantic_non_lvalue (fold_convert (type, arg1));
case GE_EXPR:
case GT_EXPR:
- if (TREE_UNSIGNED (TREE_TYPE (arg1)))
- arg1 = fold_convert ((*lang_hooks.types.signed_type)
+ if (TYPE_UNSIGNED (TREE_TYPE (arg1)))
+ arg1 = fold_convert (lang_hooks.types.signed_type
(TREE_TYPE (arg1)), arg1);
arg1 = fold (build1 (ABS_EXPR, TREE_TYPE (arg1), arg1));
return pedantic_non_lvalue (fold_convert (type, arg1));
case LE_EXPR:
case LT_EXPR:
- if (TREE_UNSIGNED (TREE_TYPE (arg1)))
- arg1 = fold_convert ((lang_hooks.types.signed_type)
+ if (TYPE_UNSIGNED (TREE_TYPE (arg1)))
+ arg1 = fold_convert (lang_hooks.types.signed_type
(TREE_TYPE (arg1)), arg1);
arg1 = fold (build1 (ABS_EXPR, TREE_TYPE (arg1), arg1));
arg1 = negate_expr (fold_convert (type, arg1));
corresponding COND_EXPR. */
if (!HONOR_NANS (TYPE_MODE (TREE_TYPE (arg1))))
return pedantic_non_lvalue (fold_convert
- (type, fold (build (MIN_EXPR, comp_type,
- (comp_code == LE_EXPR
- ? comp_op0 : comp_op1),
- (comp_code == LE_EXPR
- ? comp_op1 : comp_op0)))));
+ (type, fold (build2 (MIN_EXPR, comp_type,
+ (comp_code == LE_EXPR
+ ? comp_op0 : comp_op1),
+ (comp_code == LE_EXPR
+ ? comp_op1 : comp_op0)))));
break;
case GE_EXPR:
case GT_EXPR:
if (!HONOR_NANS (TYPE_MODE (TREE_TYPE (arg1))))
return pedantic_non_lvalue (fold_convert
- (type, fold (build (MAX_EXPR, comp_type,
- (comp_code == GE_EXPR
- ? comp_op0 : comp_op1),
- (comp_code == GE_EXPR
- ? comp_op1 : comp_op0)))));
+ (type, fold (build2 (MAX_EXPR, comp_type,
+ (comp_code == GE_EXPR
+ ? comp_op0 : comp_op1),
+ (comp_code == GE_EXPR
+ ? comp_op1 : comp_op0)))));
break;
default:
abort ();
case EQ_EXPR:
/* We can replace A with C1 in this case. */
arg1 = fold_convert (type, TREE_OPERAND (arg0, 1));
- return fold (build (code, type, TREE_OPERAND (t, 0), arg1,
- TREE_OPERAND (t, 2)));
+ return fold (build3 (code, type, TREE_OPERAND (t, 0), arg1,
+ TREE_OPERAND (t, 2)));
case LT_EXPR:
/* If C1 is C2 + 1, this is min(A, C2). */
- if (! operand_equal_p (arg2, TYPE_MAX_VALUE (type), 1)
+ if (! operand_equal_p (arg2, TYPE_MAX_VALUE (type),
+ OEP_ONLY_CONST)
&& operand_equal_p (TREE_OPERAND (arg0, 1),
const_binop (PLUS_EXPR, arg2,
- integer_one_node, 0), 1))
+ integer_one_node, 0),
+ OEP_ONLY_CONST))
return pedantic_non_lvalue
- (fold (build (MIN_EXPR, type, arg1, arg2)));
+ (fold (build2 (MIN_EXPR, type, arg1, arg2)));
break;
case LE_EXPR:
/* If C1 is C2 - 1, this is min(A, C2). */
- if (! operand_equal_p (arg2, TYPE_MIN_VALUE (type), 1)
+ if (! operand_equal_p (arg2, TYPE_MIN_VALUE (type),
+ OEP_ONLY_CONST)
&& operand_equal_p (TREE_OPERAND (arg0, 1),
const_binop (MINUS_EXPR, arg2,
- integer_one_node, 0), 1))
+ integer_one_node, 0),
+ OEP_ONLY_CONST))
return pedantic_non_lvalue
- (fold (build (MIN_EXPR, type, arg1, arg2)));
+ (fold (build2 (MIN_EXPR, type, arg1, arg2)));
break;
case GT_EXPR:
/* If C1 is C2 - 1, this is max(A, C2). */
- if (! operand_equal_p (arg2, TYPE_MIN_VALUE (type), 1)
+ if (! operand_equal_p (arg2, TYPE_MIN_VALUE (type),
+ OEP_ONLY_CONST)
&& operand_equal_p (TREE_OPERAND (arg0, 1),
const_binop (MINUS_EXPR, arg2,
- integer_one_node, 0), 1))
+ integer_one_node, 0),
+ OEP_ONLY_CONST))
return pedantic_non_lvalue
- (fold (build (MAX_EXPR, type, arg1, arg2)));
+ (fold (build2 (MAX_EXPR, type, arg1, arg2)));
break;
case GE_EXPR:
/* If C1 is C2 + 1, this is max(A, C2). */
- if (! operand_equal_p (arg2, TYPE_MAX_VALUE (type), 1)
+ if (! operand_equal_p (arg2, TYPE_MAX_VALUE (type),
+ OEP_ONLY_CONST)
&& operand_equal_p (TREE_OPERAND (arg0, 1),
const_binop (PLUS_EXPR, arg2,
- integer_one_node, 0), 1))
+ integer_one_node, 0),
+ OEP_ONLY_CONST))
return pedantic_non_lvalue
- (fold (build (MAX_EXPR, type, arg1, arg2)));
+ (fold (build2 (MAX_EXPR, type, arg1, arg2)));
break;
case NE_EXPR:
break;
tem = invert_truthvalue (arg0);
if (TREE_CODE (tem) != TRUTH_NOT_EXPR)
- return fold (build (code, type, tem,
- TREE_OPERAND (t, 2), TREE_OPERAND (t, 1)));
+ return fold (build3 (code, type, tem,
+ TREE_OPERAND (t, 2), TREE_OPERAND (t, 1)));
}
/* Convert A ? 1 : 0 to simply A. */
&& integer_pow2p (arg1)
&& TREE_CODE (TREE_OPERAND (arg0, 0)) == BIT_AND_EXPR
&& operand_equal_p (TREE_OPERAND (TREE_OPERAND (arg0, 0), 1),
- arg1, 1))
+ arg1, OEP_ONLY_CONST))
return pedantic_non_lvalue (fold_convert (type,
TREE_OPERAND (arg0, 0)));
if (integer_zerop (TREE_OPERAND (t, 2))
&& truth_value_p (TREE_CODE (arg0))
&& truth_value_p (TREE_CODE (arg1)))
- return pedantic_non_lvalue (fold (build (TRUTH_ANDIF_EXPR, type,
- arg0, arg1)));
+ return pedantic_non_lvalue (fold (build2 (TRUTH_ANDIF_EXPR, type,
+ arg0, arg1)));
/* Convert A ? B : 1 into !A || B if A and B are truth values. */
if (integer_onep (TREE_OPERAND (t, 2))
/* Only perform transformation if ARG0 is easily inverted. */
tem = invert_truthvalue (arg0);
if (TREE_CODE (tem) != TRUTH_NOT_EXPR)
- return pedantic_non_lvalue (fold (build (TRUTH_ORIF_EXPR, type,
- tem, arg1)));
+ return pedantic_non_lvalue (fold (build2 (TRUTH_ORIF_EXPR, type,
+ tem, arg1)));
}
return t;
else if (TREE_CODE (arg0) == COMPLEX_CST)
return TREE_REALPART (arg0);
else if (TREE_CODE (arg0) == PLUS_EXPR || TREE_CODE (arg0) == MINUS_EXPR)
- return fold (build (TREE_CODE (arg0), type,
- fold (build1 (REALPART_EXPR, type,
- TREE_OPERAND (arg0, 0))),
- fold (build1 (REALPART_EXPR,
- type, TREE_OPERAND (arg0, 1)))));
+ return fold (build2 (TREE_CODE (arg0), type,
+ fold (build1 (REALPART_EXPR, type,
+ TREE_OPERAND (arg0, 0))),
+ fold (build1 (REALPART_EXPR, type,
+ TREE_OPERAND (arg0, 1)))));
return t;
case IMAGPART_EXPR:
else if (TREE_CODE (arg0) == COMPLEX_CST)
return TREE_IMAGPART (arg0);
else if (TREE_CODE (arg0) == PLUS_EXPR || TREE_CODE (arg0) == MINUS_EXPR)
- return fold (build (TREE_CODE (arg0), type,
- fold (build1 (IMAGPART_EXPR, type,
- TREE_OPERAND (arg0, 0))),
- fold (build1 (IMAGPART_EXPR, type,
- TREE_OPERAND (arg0, 1)))));
+ return fold (build2 (TREE_CODE (arg0), type,
+ fold (build1 (IMAGPART_EXPR, type,
+ TREE_OPERAND (arg0, 0))),
+ fold (build1 (IMAGPART_EXPR, type,
+ TREE_OPERAND (arg0, 1)))));
return t;
/* Pull arithmetic ops out of the CLEANUP_POINT_EXPR where
if (TREE_CONSTANT (arg00)
|| ((code0 == TRUTH_ANDIF_EXPR || code0 == TRUTH_ORIF_EXPR)
&& ! has_cleanups (arg00)))
- return fold (build (code0, type, arg00,
- fold (build1 (CLEANUP_POINT_EXPR,
- TREE_TYPE (arg01), arg01))));
+ return fold (build2 (code0, type, arg00,
+ fold (build1 (CLEANUP_POINT_EXPR,
+ TREE_TYPE (arg01), arg01))));
if (TREE_CONSTANT (arg01))
- return fold (build (code0, type,
- fold (build1 (CLEANUP_POINT_EXPR,
- TREE_TYPE (arg00), arg00)),
- arg01));
+ return fold (build2 (code0, type,
+ fold (build1 (CLEANUP_POINT_EXPR,
+ TREE_TYPE (arg00), arg00)),
+ arg01));
}
return t;
case CALL_EXPR:
/* Check for a built-in function. */
- if (TREE_CODE (TREE_OPERAND (expr, 0)) == ADDR_EXPR
- && (TREE_CODE (TREE_OPERAND (TREE_OPERAND (expr, 0), 0))
+ if (TREE_CODE (TREE_OPERAND (t, 0)) == ADDR_EXPR
+ && (TREE_CODE (TREE_OPERAND (TREE_OPERAND (t, 0), 0))
== FUNCTION_DECL)
- && DECL_BUILT_IN (TREE_OPERAND (TREE_OPERAND (expr, 0), 0)))
+ && DECL_BUILT_IN (TREE_OPERAND (TREE_OPERAND (t, 0), 0)))
{
- tree tmp = fold_builtin (expr);
+ tree tmp = fold_builtin (t);
if (tmp)
return tmp;
}
case INTEGER_CST:
if (TREE_CODE (bottom) != INTEGER_CST
- || (TREE_UNSIGNED (type)
+ || (TYPE_UNSIGNED (type)
&& (tree_int_cst_sgn (top) < 0
|| tree_int_cst_sgn (bottom) < 0)))
return 0;
{
tree inner1 = TREE_TYPE (TREE_OPERAND (TREE_OPERAND (t, 0), 0));
tree inner2 = TREE_TYPE (TREE_OPERAND (TREE_OPERAND (t, 1), 0));
- if (TREE_CODE (inner1) == INTEGER_TYPE && TREE_UNSIGNED (inner1)
- && TREE_CODE (inner2) == INTEGER_TYPE && TREE_UNSIGNED (inner2))
+ if (TREE_CODE (inner1) == INTEGER_TYPE && TYPE_UNSIGNED (inner1)
+ && TREE_CODE (inner2) == INTEGER_TYPE && TYPE_UNSIGNED (inner2))
{
unsigned int prec = MAX (TYPE_PRECISION (inner1),
TYPE_PRECISION (inner2)) + 1;
{
tree inner1 = TREE_TYPE (TREE_OPERAND (TREE_OPERAND (t, 0), 0));
tree inner2 = TREE_TYPE (TREE_OPERAND (TREE_OPERAND (t, 1), 0));
- if (TREE_CODE (inner1) == INTEGER_TYPE && TREE_UNSIGNED (inner1)
- && TREE_CODE (inner2) == INTEGER_TYPE && TREE_UNSIGNED (inner2))
+ if (TREE_CODE (inner1) == INTEGER_TYPE && TYPE_UNSIGNED (inner1)
+ && TREE_CODE (inner2) == INTEGER_TYPE && TYPE_UNSIGNED (inner2))
return TYPE_PRECISION (inner1) + TYPE_PRECISION (inner2)
< TYPE_PRECISION (TREE_TYPE (t));
}
return tree_expr_nonnegative_p (TREE_OPERAND (t, 0))
&& tree_expr_nonnegative_p (TREE_OPERAND (t, 1));
+ case BIT_AND_EXPR:
+ return tree_expr_nonnegative_p (TREE_OPERAND (t, 1))
+ || tree_expr_nonnegative_p (TREE_OPERAND (t, 0));
+ case BIT_IOR_EXPR:
+ case BIT_XOR_EXPR:
+ return tree_expr_nonnegative_p (TREE_OPERAND (t, 0))
+ && tree_expr_nonnegative_p (TREE_OPERAND (t, 1));
+
case NOP_EXPR:
{
tree inner_type = TREE_TYPE (TREE_OPERAND (t, 0));
return tree_expr_nonnegative_p (TREE_OPERAND (t, 0));
if (TREE_CODE (inner_type) == INTEGER_TYPE)
{
- if (TREE_UNSIGNED (inner_type))
+ if (TYPE_UNSIGNED (inner_type))
return 1;
return tree_expr_nonnegative_p (TREE_OPERAND (t, 0));
}
return tree_expr_nonnegative_p (TREE_OPERAND (t,0));
if (TREE_CODE (inner_type) == INTEGER_TYPE)
return TYPE_PRECISION (inner_type) < TYPE_PRECISION (outer_type)
- && TREE_UNSIGNED (inner_type);
+ && TYPE_UNSIGNED (inner_type);
}
}
break;
&& DECL_BUILT_IN_CLASS (fndecl) != BUILT_IN_MD)
switch (DECL_FUNCTION_CODE (fndecl))
{
- case BUILT_IN_CABS:
- case BUILT_IN_CABSL:
- case BUILT_IN_CABSF:
- case BUILT_IN_EXP:
- case BUILT_IN_EXPF:
- case BUILT_IN_EXPL:
- case BUILT_IN_EXP2:
- case BUILT_IN_EXP2F:
- case BUILT_IN_EXP2L:
- case BUILT_IN_EXP10:
- case BUILT_IN_EXP10F:
- case BUILT_IN_EXP10L:
- case BUILT_IN_FABS:
- case BUILT_IN_FABSF:
- case BUILT_IN_FABSL:
- case BUILT_IN_FFS:
- case BUILT_IN_FFSL:
- case BUILT_IN_FFSLL:
- case BUILT_IN_PARITY:
- case BUILT_IN_PARITYL:
- case BUILT_IN_PARITYLL:
- case BUILT_IN_POPCOUNT:
- case BUILT_IN_POPCOUNTL:
- case BUILT_IN_POPCOUNTLL:
- case BUILT_IN_POW10:
- case BUILT_IN_POW10F:
- case BUILT_IN_POW10L:
- case BUILT_IN_SQRT:
- case BUILT_IN_SQRTF:
- case BUILT_IN_SQRTL:
+#define CASE_BUILTIN_F(BUILT_IN_FN) \
+ case BUILT_IN_FN: case BUILT_IN_FN##F: case BUILT_IN_FN##L:
+#define CASE_BUILTIN_I(BUILT_IN_FN) \
+ case BUILT_IN_FN: case BUILT_IN_FN##L: case BUILT_IN_FN##LL:
+
+ CASE_BUILTIN_F (BUILT_IN_ACOS)
+ CASE_BUILTIN_F (BUILT_IN_ACOSH)
+ CASE_BUILTIN_F (BUILT_IN_CABS)
+ CASE_BUILTIN_F (BUILT_IN_COSH)
+ CASE_BUILTIN_F (BUILT_IN_ERFC)
+ CASE_BUILTIN_F (BUILT_IN_EXP)
+ CASE_BUILTIN_F (BUILT_IN_EXP10)
+ CASE_BUILTIN_F (BUILT_IN_EXP2)
+ CASE_BUILTIN_F (BUILT_IN_FABS)
+ CASE_BUILTIN_F (BUILT_IN_FDIM)
+ CASE_BUILTIN_F (BUILT_IN_FREXP)
+ CASE_BUILTIN_F (BUILT_IN_HYPOT)
+ CASE_BUILTIN_F (BUILT_IN_POW10)
+ CASE_BUILTIN_F (BUILT_IN_SQRT)
+ CASE_BUILTIN_I (BUILT_IN_FFS)
+ CASE_BUILTIN_I (BUILT_IN_PARITY)
+ CASE_BUILTIN_I (BUILT_IN_POPCOUNT)
+ /* Always true. */
return 1;
- case BUILT_IN_ATAN:
- case BUILT_IN_ATANF:
- case BUILT_IN_ATANL:
- case BUILT_IN_CEIL:
- case BUILT_IN_CEILF:
- case BUILT_IN_CEILL:
- case BUILT_IN_FLOOR:
- case BUILT_IN_FLOORF:
- case BUILT_IN_FLOORL:
- case BUILT_IN_NEARBYINT:
- case BUILT_IN_NEARBYINTF:
- case BUILT_IN_NEARBYINTL:
- case BUILT_IN_ROUND:
- case BUILT_IN_ROUNDF:
- case BUILT_IN_ROUNDL:
- case BUILT_IN_TRUNC:
- case BUILT_IN_TRUNCF:
- case BUILT_IN_TRUNCL:
+ CASE_BUILTIN_F (BUILT_IN_ASINH)
+ CASE_BUILTIN_F (BUILT_IN_ATAN)
+ CASE_BUILTIN_F (BUILT_IN_ATANH)
+ CASE_BUILTIN_F (BUILT_IN_CBRT)
+ CASE_BUILTIN_F (BUILT_IN_CEIL)
+ CASE_BUILTIN_F (BUILT_IN_ERF)
+ CASE_BUILTIN_F (BUILT_IN_EXPM1)
+ CASE_BUILTIN_F (BUILT_IN_FLOOR)
+ CASE_BUILTIN_F (BUILT_IN_FMOD)
+ CASE_BUILTIN_F (BUILT_IN_LDEXP)
+ CASE_BUILTIN_F (BUILT_IN_LLRINT)
+ CASE_BUILTIN_F (BUILT_IN_LLROUND)
+ CASE_BUILTIN_F (BUILT_IN_LRINT)
+ CASE_BUILTIN_F (BUILT_IN_LROUND)
+ CASE_BUILTIN_F (BUILT_IN_MODF)
+ CASE_BUILTIN_F (BUILT_IN_NEARBYINT)
+ CASE_BUILTIN_F (BUILT_IN_POW)
+ CASE_BUILTIN_F (BUILT_IN_RINT)
+ CASE_BUILTIN_F (BUILT_IN_ROUND)
+ CASE_BUILTIN_F (BUILT_IN_SIGNBIT)
+ CASE_BUILTIN_F (BUILT_IN_SINH)
+ CASE_BUILTIN_F (BUILT_IN_TANH)
+ CASE_BUILTIN_F (BUILT_IN_TRUNC)
+ /* True if the 1st argument is nonnegative. */
return tree_expr_nonnegative_p (TREE_VALUE (arglist));
- case BUILT_IN_POW:
- case BUILT_IN_POWF:
- case BUILT_IN_POWL:
- return tree_expr_nonnegative_p (TREE_VALUE (arglist));
+ CASE_BUILTIN_F(BUILT_IN_FMAX)
+ /* True if the 1st OR 2nd arguments are nonnegative. */
+ return tree_expr_nonnegative_p (TREE_VALUE (arglist))
+ || tree_expr_nonnegative_p (TREE_VALUE (TREE_CHAIN (arglist)));
+
+ CASE_BUILTIN_F(BUILT_IN_FMIN)
+ /* True if the 1st AND 2nd arguments are nonnegative. */
+ return tree_expr_nonnegative_p (TREE_VALUE (arglist))
+ && tree_expr_nonnegative_p (TREE_VALUE (TREE_CHAIN (arglist)));
+
+ CASE_BUILTIN_F(BUILT_IN_COPYSIGN)
+ /* True if the 2nd argument is nonnegative. */
+ return tree_expr_nonnegative_p (TREE_VALUE (TREE_CHAIN (arglist)));
default:
break;
+#undef CASE_BUILTIN_F
+#undef CASE_BUILTIN_I
}
}
return 0;
}
+/* Return true when T is an address and is known to be nonzero.
+ For floating point we further ensure that T is not denormal.
+ Similar logic is present in nonzero_address in rtlanal.h */
+
+static bool
+tree_expr_nonzero_p (tree t)
+{
+ tree type = TREE_TYPE (t);
+
+ /* Doing something useful for floating point would need more work. */
+ if (!INTEGRAL_TYPE_P (type) && !POINTER_TYPE_P (type))
+ return false;
+
+ switch (TREE_CODE (t))
+ {
+ case ABS_EXPR:
+ if (!TYPE_UNSIGNED (type) && !flag_wrapv)
+ return tree_expr_nonzero_p (TREE_OPERAND (t, 0));
+
+ case INTEGER_CST:
+ return !integer_zerop (t);
+
+ case PLUS_EXPR:
+ if (!TYPE_UNSIGNED (type) && !flag_wrapv)
+ {
+ /* With the presence of negative values it is hard
+ to say something. */
+ if (!tree_expr_nonnegative_p (TREE_OPERAND (t, 0))
+ || !tree_expr_nonnegative_p (TREE_OPERAND (t, 1)))
+ return false;
+ /* One of operands must be positive and the other non-negative. */
+ return (tree_expr_nonzero_p (TREE_OPERAND (t, 0))
+ || tree_expr_nonzero_p (TREE_OPERAND (t, 1)));
+ }
+ break;
+
+ case MULT_EXPR:
+ if (!TYPE_UNSIGNED (type) && !flag_wrapv)
+ {
+ return (tree_expr_nonzero_p (TREE_OPERAND (t, 0))
+ && tree_expr_nonzero_p (TREE_OPERAND (t, 1)));
+ }
+ break;
+
+ case NOP_EXPR:
+ {
+ tree inner_type = TREE_TYPE (TREE_OPERAND (t, 0));
+ tree outer_type = TREE_TYPE (t);
+
+ return (TYPE_PRECISION (inner_type) >= TYPE_PRECISION (outer_type)
+ && tree_expr_nonzero_p (TREE_OPERAND (t, 0)));
+ }
+ break;
+
+ case ADDR_EXPR:
+ /* Weak declarations may link to NULL. */
+ if (DECL_P (TREE_OPERAND (t, 0)))
+ return !DECL_WEAK (TREE_OPERAND (t, 0));
+ /* Constants and all other cases are never weak. */
+ return true;
+
+ case COND_EXPR:
+ return (tree_expr_nonzero_p (TREE_OPERAND (t, 1))
+ && tree_expr_nonzero_p (TREE_OPERAND (t, 2)));
+
+ case MIN_EXPR:
+ return (tree_expr_nonzero_p (TREE_OPERAND (t, 0))
+ && tree_expr_nonzero_p (TREE_OPERAND (t, 1)));
+
+ case MAX_EXPR:
+ if (tree_expr_nonzero_p (TREE_OPERAND (t, 0)))
+ {
+ /* When both operands are nonzero, then MAX must be too. */
+ if (tree_expr_nonzero_p (TREE_OPERAND (t, 1)))
+ return true;
+
+ /* MAX where operand 0 is positive is positive. */
+ return tree_expr_nonnegative_p (TREE_OPERAND (t, 0));
+ }
+ /* MAX where operand 1 is positive is positive. */
+ else if (tree_expr_nonzero_p (TREE_OPERAND (t, 1))
+ && tree_expr_nonnegative_p (TREE_OPERAND (t, 1)))
+ return true;
+ break;
+
+ case COMPOUND_EXPR:
+ case MODIFY_EXPR:
+ case BIND_EXPR:
+ return tree_expr_nonzero_p (TREE_OPERAND (t, 1));
+
+ case SAVE_EXPR:
+ case NON_LVALUE_EXPR:
+ return tree_expr_nonzero_p (TREE_OPERAND (t, 0));
+
+ case BIT_IOR_EXPR:
+ return tree_expr_nonzero_p (TREE_OPERAND (t, 1))
+ || tree_expr_nonzero_p (TREE_OPERAND (t, 0));
+
+ default:
+ break;
+ }
+ return false;
+}
+
/* Return true if `r' is known to be non-negative.
Only handles constants at the moment. */
}
}
+
+/* See if we are applying CODE, a relational to the highest or lowest
+ possible integer of TYPE. If so, then the result is a compile
+ time constant. */
+
+static tree
+fold_relational_hi_lo (enum tree_code *code_p, const tree type, tree *op0_p,
+ tree *op1_p)
+{
+ tree op0 = *op0_p;
+ tree op1 = *op1_p;
+ enum tree_code code = *code_p;
+ int width = GET_MODE_BITSIZE (TYPE_MODE (TREE_TYPE (op1)));
+
+ if (TREE_CODE (op1) == INTEGER_CST
+ && ! TREE_CONSTANT_OVERFLOW (op1)
+ && width <= HOST_BITS_PER_WIDE_INT
+ && (INTEGRAL_TYPE_P (TREE_TYPE (op1))
+ || POINTER_TYPE_P (TREE_TYPE (op1))))
+ {
+ unsigned HOST_WIDE_INT signed_max;
+ unsigned HOST_WIDE_INT max, min;
+
+ signed_max = ((unsigned HOST_WIDE_INT) 1 << (width - 1)) - 1;
+
+ if (TYPE_UNSIGNED (TREE_TYPE (op1)))
+ {
+ max = ((unsigned HOST_WIDE_INT) 2 << (width - 1)) - 1;
+ min = 0;
+ }
+ else
+ {
+ max = signed_max;
+ min = ((unsigned HOST_WIDE_INT) -1 << (width - 1));
+ }
+
+ if (TREE_INT_CST_HIGH (op1) == 0
+ && TREE_INT_CST_LOW (op1) == max)
+ switch (code)
+ {
+ case GT_EXPR:
+ return omit_one_operand (type,
+ fold_convert (type, integer_zero_node),
+ op0);
+ case GE_EXPR:
+ *code_p = EQ_EXPR;
+ break;
+ case LE_EXPR:
+ return omit_one_operand (type,
+ fold_convert (type, integer_one_node),
+ op0);
+ case LT_EXPR:
+ *code_p = NE_EXPR;
+ break;
+
+ /* The GE_EXPR and LT_EXPR cases above are not normally
+ reached because of previous transformations. */
+
+ default:
+ break;
+ }
+ else if (TREE_INT_CST_HIGH (op1) == 0
+ && TREE_INT_CST_LOW (op1) == max - 1)
+ switch (code)
+ {
+ case GT_EXPR:
+ *code_p = EQ_EXPR;
+ *op1_p = const_binop (PLUS_EXPR, op1, integer_one_node, 0);
+ break;
+ case LE_EXPR:
+ *code_p = NE_EXPR;
+ *op1_p = const_binop (PLUS_EXPR, op1, integer_one_node, 0);
+ break;
+ default:
+ break;
+ }
+ else if (TREE_INT_CST_HIGH (op1) == (min ? -1 : 0)
+ && TREE_INT_CST_LOW (op1) == min)
+ switch (code)
+ {
+ case LT_EXPR:
+ return omit_one_operand (type,
+ fold_convert (type, integer_zero_node),
+ op0);
+ case LE_EXPR:
+ *code_p = EQ_EXPR;
+ break;
+
+ case GE_EXPR:
+ return omit_one_operand (type,
+ fold_convert (type, integer_one_node),
+ op0);
+ case GT_EXPR:
+ *code_p = NE_EXPR;
+ break;
+
+ default:
+ break;
+ }
+ else if (TREE_INT_CST_HIGH (op1) == (min ? -1 : 0)
+ && TREE_INT_CST_LOW (op1) == min + 1)
+ switch (code)
+ {
+ case GE_EXPR:
+ *code_p = NE_EXPR;
+ *op1_p = const_binop (MINUS_EXPR, op1, integer_one_node, 0);
+ break;
+ case LT_EXPR:
+ *code_p = EQ_EXPR;
+ *op1_p = const_binop (MINUS_EXPR, op1, integer_one_node, 0);
+ break;
+ default:
+ break;
+ }
+
+ else if (TREE_INT_CST_HIGH (op1) == 0
+ && TREE_INT_CST_LOW (op1) == signed_max
+ && TYPE_UNSIGNED (TREE_TYPE (op1))
+ /* signed_type does not work on pointer types. */
+ && INTEGRAL_TYPE_P (TREE_TYPE (op1)))
+ {
+ /* The following case also applies to X < signed_max+1
+ and X >= signed_max+1 because previous transformations. */
+ if (code == LE_EXPR || code == GT_EXPR)
+ {
+ tree st0, st1, exp, retval;
+ st0 = lang_hooks.types.signed_type (TREE_TYPE (op0));
+ st1 = lang_hooks.types.signed_type (TREE_TYPE (op1));
+
+ exp = build2 (code == LE_EXPR ? GE_EXPR: LT_EXPR,
+ type,
+ fold_convert (st0, op0),
+ fold_convert (st1, integer_zero_node));
+
+ retval
+ = nondestructive_fold_binary_to_constant (TREE_CODE (exp),
+ TREE_TYPE (exp),
+ TREE_OPERAND (exp, 0),
+ TREE_OPERAND (exp, 1));
+
+ /* If we are in gimple form, then returning EXP would create
+ non-gimple expressions. Clearing it is safe and insures
+ we do not allow a non-gimple expression to escape. */
+ if (in_gimple_form)
+ exp = NULL;
+
+ return (retval ? retval : exp);
+ }
+ }
+ }
+
+ return NULL_TREE;
+}
+
+
+/* Given the components of a binary expression CODE, TYPE, OP0 and OP1,
+ attempt to fold the expression to a constant without modifying TYPE,
+ OP0 or OP1.
+
+ If the expression could be simplified to a constant, then return
+ the constant. If the expression would not be simplified to a
+ constant, then return NULL_TREE.
+
+ Note this is primarily designed to be called after gimplification
+ of the tree structures and when at least one operand is a constant.
+ As a result of those simplifying assumptions this routine is far
+ simpler than the generic fold routine. */
+
+tree
+nondestructive_fold_binary_to_constant (enum tree_code code, tree type,
+ tree op0, tree op1)
+{
+ int wins = 1;
+ tree subop0;
+ tree subop1;
+ tree tem;
+
+ /* If this is a commutative operation, and ARG0 is a constant, move it
+ to ARG1 to reduce the number of tests below. */
+ if (commutative_tree_code (code)
+ && (TREE_CODE (op0) == INTEGER_CST || TREE_CODE (op0) == REAL_CST))
+ {
+ tem = op0;
+ op0 = op1;
+ op1 = tem;
+ }
+
+ /* If either operand is a complex type, extract its real component. */
+ if (TREE_CODE (op0) == COMPLEX_CST)
+ subop0 = TREE_REALPART (op0);
+ else
+ subop0 = op0;
+
+ if (TREE_CODE (op1) == COMPLEX_CST)
+ subop1 = TREE_REALPART (op1);
+ else
+ subop1 = op1;
+
+ /* Note if either argument is not a real or integer constant.
+ With a few exceptions, simplification is limited to cases
+ where both arguments are constants. */
+ if ((TREE_CODE (subop0) != INTEGER_CST
+ && TREE_CODE (subop0) != REAL_CST)
+ || (TREE_CODE (subop1) != INTEGER_CST
+ && TREE_CODE (subop1) != REAL_CST))
+ wins = 0;
+
+ switch (code)
+ {
+ case PLUS_EXPR:
+ /* (plus (address) (const_int)) is a constant. */
+ if (TREE_CODE (op0) == PLUS_EXPR
+ && TREE_CODE (op1) == INTEGER_CST
+ && (TREE_CODE (TREE_OPERAND (op0, 0)) == ADDR_EXPR
+ || (TREE_CODE (TREE_OPERAND (op0, 0)) == NOP_EXPR
+ && (TREE_CODE (TREE_OPERAND (TREE_OPERAND (op0, 0), 0))
+ == ADDR_EXPR)))
+ && TREE_CODE (TREE_OPERAND (op0, 1)) == INTEGER_CST)
+ {
+ return build2 (PLUS_EXPR, type, TREE_OPERAND (op0, 0),
+ const_binop (PLUS_EXPR, op1,
+ TREE_OPERAND (op0, 1), 0));
+ }
+ case BIT_XOR_EXPR:
+
+ binary:
+ if (!wins)
+ return NULL_TREE;
+
+ /* Both arguments are constants. Simplify. */
+ tem = const_binop (code, op0, op1, 0);
+ if (tem != NULL_TREE)
+ {
+ /* The return value should always have the same type as
+ the original expression. */
+ if (TREE_TYPE (tem) != type)
+ tem = fold_convert (type, tem);
+
+ return tem;
+ }
+ return NULL_TREE;
+
+ case MINUS_EXPR:
+ /* Fold &x - &x. This can happen from &x.foo - &x.
+ This is unsafe for certain floats even in non-IEEE formats.
+ In IEEE, it is unsafe because it does wrong for NaNs.
+ Also note that operand_equal_p is always false if an
+ operand is volatile. */
+ if (! FLOAT_TYPE_P (type) && operand_equal_p (op0, op1, 0))
+ return fold_convert (type, integer_zero_node);
+
+ goto binary;
+
+ case MULT_EXPR:
+ case BIT_AND_EXPR:
+ /* Special case multiplication or bitwise AND where one argument
+ is zero. */
+ if (! FLOAT_TYPE_P (type) && integer_zerop (op1))
+ return omit_one_operand (type, op1, op0);
+ else
+ if (!HONOR_NANS (TYPE_MODE (TREE_TYPE (op0)))
+ && !HONOR_SIGNED_ZEROS (TYPE_MODE (TREE_TYPE (op0)))
+ && real_zerop (op1))
+ return omit_one_operand (type, op1, op0);
+
+ goto binary;
+
+ case BIT_IOR_EXPR:
+ /* Special case when we know the result will be all ones. */
+ if (integer_all_onesp (op1))
+ return omit_one_operand (type, op1, op0);
+
+ goto binary;
+
+ case TRUNC_DIV_EXPR:
+ case ROUND_DIV_EXPR:
+ case FLOOR_DIV_EXPR:
+ case CEIL_DIV_EXPR:
+ case EXACT_DIV_EXPR:
+ case TRUNC_MOD_EXPR:
+ case ROUND_MOD_EXPR:
+ case FLOOR_MOD_EXPR:
+ case CEIL_MOD_EXPR:
+ case RDIV_EXPR:
+ /* Division by zero is undefined. */
+ if (integer_zerop (op1))
+ return NULL_TREE;
+
+ if (TREE_CODE (op1) == REAL_CST
+ && !MODE_HAS_INFINITIES (TYPE_MODE (TREE_TYPE (op1)))
+ && real_zerop (op1))
+ return NULL_TREE;
+
+ goto binary;
+
+ case MIN_EXPR:
+ if (INTEGRAL_TYPE_P (type)
+ && operand_equal_p (op1, TYPE_MIN_VALUE (type), OEP_ONLY_CONST))
+ return omit_one_operand (type, op1, op0);
+
+ goto binary;
+
+ case MAX_EXPR:
+ if (INTEGRAL_TYPE_P (type)
+ && TYPE_MAX_VALUE (type)
+ && operand_equal_p (op1, TYPE_MAX_VALUE (type), OEP_ONLY_CONST))
+ return omit_one_operand (type, op1, op0);
+
+ goto binary;
+
+ case RSHIFT_EXPR:
+ /* Optimize -1 >> x for arithmetic right shifts. */
+ if (integer_all_onesp (op0) && ! TYPE_UNSIGNED (type))
+ return omit_one_operand (type, op0, op1);
+ /* ... fall through ... */
+
+ case LSHIFT_EXPR:
+ if (integer_zerop (op0))
+ return omit_one_operand (type, op0, op1);
+
+ /* Since negative shift count is not well-defined, don't
+ try to compute it in the compiler. */
+ if (TREE_CODE (op1) == INTEGER_CST && tree_int_cst_sgn (op1) < 0)
+ return NULL_TREE;
+
+ goto binary;
+
+ case LROTATE_EXPR:
+ case RROTATE_EXPR:
+ /* -1 rotated either direction by any amount is still -1. */
+ if (integer_all_onesp (op0))
+ return omit_one_operand (type, op0, op1);
+
+ /* 0 rotated either direction by any amount is still zero. */
+ if (integer_zerop (op0))
+ return omit_one_operand (type, op0, op1);
+
+ goto binary;
+
+ case COMPLEX_EXPR:
+ if (wins)
+ return build_complex (type, op0, op1);
+ return NULL_TREE;
+
+ case LT_EXPR:
+ case LE_EXPR:
+ case GT_EXPR:
+ case GE_EXPR:
+ case EQ_EXPR:
+ case NE_EXPR:
+ /* If one arg is a real or integer constant, put it last. */
+ if ((TREE_CODE (op0) == INTEGER_CST
+ && TREE_CODE (op1) != INTEGER_CST)
+ || (TREE_CODE (op0) == REAL_CST
+ && TREE_CODE (op0) != REAL_CST))
+ {
+ tree temp;
+
+ temp = op0;
+ op0 = op1;
+ op1 = temp;
+ code = swap_tree_comparison (code);
+ }
+
+ /* Change X >= C to X > (C - 1) and X < C to X <= (C - 1) if C > 0.
+ This transformation affects the cases which are handled in later
+ optimizations involving comparisons with non-negative constants. */
+ if (TREE_CODE (op1) == INTEGER_CST
+ && TREE_CODE (op0) != INTEGER_CST
+ && tree_int_cst_sgn (op1) > 0)
+ {
+ switch (code)
+ {
+ case GE_EXPR:
+ code = GT_EXPR;
+ op1 = const_binop (MINUS_EXPR, op1, integer_one_node, 0);
+ break;
+
+ case LT_EXPR:
+ code = LE_EXPR;
+ op1 = const_binop (MINUS_EXPR, op1, integer_one_node, 0);
+ break;
+
+ default:
+ break;
+ }
+ }
+
+ tem = fold_relational_hi_lo (&code, type, &op0, &op1);
+ if (tem)
+ return tem;
+
+ if (!wins)
+ return NULL_TREE;
+
+ return fold_relational_const (code, type, op0, op1);
+
+ case RANGE_EXPR:
+ /* This could probably be handled. */
+ return NULL_TREE;
+
+ case TRUTH_AND_EXPR:
+ /* If second arg is constant zero, result is zero, but first arg
+ must be evaluated. */
+ if (integer_zerop (op1))
+ return omit_one_operand (type, op1, op0);
+ /* Likewise for first arg, but note that only the TRUTH_AND_EXPR
+ case will be handled here. */
+ if (integer_zerop (op0))
+ return omit_one_operand (type, op0, op1);
+ if (TREE_CODE (op0) == INTEGER_CST && TREE_CODE (op1) == INTEGER_CST)
+ {
+ int x1 = ! integer_zerop (op0);
+ int x2 = ! integer_zerop (op1);
+
+ return ((x1 & x2) ? integer_one_node : integer_zero_node);
+ }
+ return NULL_TREE;
+
+ case TRUTH_OR_EXPR:
+ /* If second arg is constant true, result is true, but we must
+ evaluate first arg. */
+ if (TREE_CODE (op1) == INTEGER_CST && ! integer_zerop (op1))
+ return omit_one_operand (type, op1, op0);
+ /* Likewise for first arg, but note this only occurs here for
+ TRUTH_OR_EXPR. */
+ if (TREE_CODE (op0) == INTEGER_CST && ! integer_zerop (op0))
+ return omit_one_operand (type, op0, op1);
+ if (TREE_CODE (op0) == INTEGER_CST && TREE_CODE (op1) == INTEGER_CST)
+ {
+ int x1 = ! integer_zerop (op0);
+ int x2 = ! integer_zerop (op1);
+
+ return ((x1 | x2) ? integer_one_node : integer_zero_node);
+ }
+ return NULL_TREE;
+
+ case TRUTH_XOR_EXPR:
+ if (TREE_CODE (op0) == INTEGER_CST && TREE_CODE (op1) == INTEGER_CST)
+ {
+ int x1 = ! integer_zerop (op0);
+ int x2 = ! integer_zerop (op1);
+
+ return ((x1 ^ x2) ? integer_one_node : integer_zero_node);
+ }
+ return NULL_TREE;
+
+ default:
+ return NULL_TREE;
+ }
+}
+
+/* Given the components of a unary expression CODE, TYPE and OP0,
+ attempt to fold the expression to a constant without modifying
+ TYPE or OP0.
+
+ If the expression could be simplified to a constant, then return
+ the constant. If the expression would not be simplified to a
+ constant, then return NULL_TREE.
+
+ Note this is primarily designed to be called after gimplification
+ of the tree structures and when op0 is a constant. As a result
+ of those simplifying assumptions this routine is far simpler than
+ the generic fold routine. */
+
+tree
+nondestructive_fold_unary_to_constant (enum tree_code code, tree type,
+ tree op0)
+{
+ tree t;
+
+ /* Make sure we have a suitable constant argument. */
+ if (code == NOP_EXPR || code == FLOAT_EXPR || code == CONVERT_EXPR)
+ {
+ tree subop;
+
+ if (TREE_CODE (op0) == COMPLEX_CST)
+ subop = TREE_REALPART (op0);
+ else
+ subop = op0;
+
+ if (TREE_CODE (subop) != INTEGER_CST && TREE_CODE (subop) != REAL_CST)
+ return NULL_TREE;
+ }
+
+ switch (code)
+ {
+ case NOP_EXPR:
+ case FLOAT_EXPR:
+ case CONVERT_EXPR:
+ case FIX_TRUNC_EXPR:
+ case FIX_FLOOR_EXPR:
+ case FIX_CEIL_EXPR:
+ return fold_convert_const (code, type, op0);
+
+ case NEGATE_EXPR:
+ if (TREE_CODE (op0) == INTEGER_CST || TREE_CODE (op0) == REAL_CST)
+ return fold_negate_const (op0, type);
+ else
+ return NULL_TREE;
+
+ case ABS_EXPR:
+ if (TREE_CODE (op0) == INTEGER_CST || TREE_CODE (op0) == REAL_CST)
+ return fold_abs_const (op0, type);
+ else
+ return NULL_TREE;
+
+ case BIT_NOT_EXPR:
+ if (TREE_CODE (op0) == INTEGER_CST || TREE_CODE (op0) == REAL_CST)
+ {
+ t = build_int_2 (~ TREE_INT_CST_LOW (op0), ~ TREE_INT_CST_HIGH (op0));
+ TREE_TYPE (t) = type;
+ force_fit_type (t, 0);
+ TREE_OVERFLOW (t) = TREE_OVERFLOW (op0);
+ TREE_CONSTANT_OVERFLOW (t) = TREE_CONSTANT_OVERFLOW (op0);
+ return t;
+ }
+ else
+ return NULL_TREE;
+
+ case REALPART_EXPR:
+ if (TREE_CODE (op0) == COMPLEX_CST)
+ return TREE_REALPART (op0);
+ else
+ return NULL_TREE;
+
+ case IMAGPART_EXPR:
+ if (TREE_CODE (op0) == COMPLEX_CST)
+ return TREE_IMAGPART (op0);
+ else
+ return NULL_TREE;
+
+ case CONJ_EXPR:
+ if (TREE_CODE (op0) == COMPLEX_CST
+ && TREE_CODE (TREE_TYPE (op0)) == COMPLEX_TYPE)
+ return build_complex (type, TREE_REALPART (op0),
+ negate_expr (TREE_IMAGPART (op0)));
+ return NULL_TREE;
+
+ default:
+ return NULL_TREE;
+ }
+}
+
+/* If EXP represents referencing an element in a constant string
+ (either via pointer arithmetic or array indexing), return the
+ tree representing the value accessed, otherwise return NULL. */
+
+tree
+fold_read_from_constant_string (tree exp)
+{
+ if (TREE_CODE (exp) == INDIRECT_REF || TREE_CODE (exp) == ARRAY_REF)
+ {
+ tree exp1 = TREE_OPERAND (exp, 0);
+ tree index;
+ tree string;
+
+ if (TREE_CODE (exp) == INDIRECT_REF)
+ {
+ string = string_constant (exp1, &index);
+ }
+ else
+ {
+ tree domain = TYPE_DOMAIN (TREE_TYPE (exp1));
+ tree low_bound = domain ? TYPE_MIN_VALUE (domain) : integer_zero_node;
+ index = fold_convert (sizetype, TREE_OPERAND (exp, 1));
+
+ /* Optimize the special-case of a zero lower bound.
+
+ We convert the low_bound to sizetype to avoid some problems
+ with constant folding. (E.g. suppose the lower bound is 1,
+ and its mode is QI. Without the conversion,l (ARRAY
+ +(INDEX-(unsigned char)1)) becomes ((ARRAY+(-(unsigned char)1))
+ +INDEX), which becomes (ARRAY+255+INDEX). Opps!) */
+ if (! integer_zerop (low_bound))
+ index = size_diffop (index, fold_convert (sizetype, low_bound));
+
+ string = exp1;
+ }
+
+ if (string
+ && TREE_CODE (string) == STRING_CST
+ && TREE_CODE (index) == INTEGER_CST
+ && compare_tree_int (index, TREE_STRING_LENGTH (string)) < 0
+ && (GET_MODE_CLASS (TYPE_MODE (TREE_TYPE (TREE_TYPE (string))))
+ == MODE_INT)
+ && (GET_MODE_SIZE (TYPE_MODE (TREE_TYPE (TREE_TYPE (string)))) == 1))
+ return build_int_2 ((TREE_STRING_POINTER (string)
+ [TREE_INT_CST_LOW (index)]), 0);
+ }
+ return NULL;
+}
+
+/* Return the tree for neg (ARG0) when ARG0 is known to be either
+ an integer constant or real constant.
+
+ TYPE is the type of the result. */
+
+static tree
+fold_negate_const (tree arg0, tree type)
+{
+ tree t = NULL_TREE;
+
+ if (TREE_CODE (arg0) == INTEGER_CST)
+ {
+ unsigned HOST_WIDE_INT low;
+ HOST_WIDE_INT high;
+ int overflow = neg_double (TREE_INT_CST_LOW (arg0),
+ TREE_INT_CST_HIGH (arg0),
+ &low, &high);
+ t = build_int_2 (low, high);
+ TREE_TYPE (t) = type;
+ TREE_OVERFLOW (t)
+ = (TREE_OVERFLOW (arg0)
+ | force_fit_type (t, overflow && !TYPE_UNSIGNED (type)));
+ TREE_CONSTANT_OVERFLOW (t)
+ = TREE_OVERFLOW (t) | TREE_CONSTANT_OVERFLOW (arg0);
+ }
+ else if (TREE_CODE (arg0) == REAL_CST)
+ t = build_real (type, REAL_VALUE_NEGATE (TREE_REAL_CST (arg0)));
+#ifdef ENABLE_CHECKING
+ else
+ abort ();
+#endif
+
+ return t;
+}
+
+/* Return the tree for abs (ARG0) when ARG0 is known to be either
+ an integer constant or real constant.
+
+ TYPE is the type of the result. */
+
+static tree
+fold_abs_const (tree arg0, tree type)
+{
+ tree t = NULL_TREE;
+
+ if (TREE_CODE (arg0) == INTEGER_CST)
+ {
+ /* If the value is unsigned, then the absolute value is
+ the same as the ordinary value. */
+ if (TYPE_UNSIGNED (type))
+ return arg0;
+ /* Similarly, if the value is non-negative. */
+ else if (INT_CST_LT (integer_minus_one_node, arg0))
+ return arg0;
+ /* If the value is negative, then the absolute value is
+ its negation. */
+ else
+ {
+ unsigned HOST_WIDE_INT low;
+ HOST_WIDE_INT high;
+ int overflow = neg_double (TREE_INT_CST_LOW (arg0),
+ TREE_INT_CST_HIGH (arg0),
+ &low, &high);
+ t = build_int_2 (low, high);
+ TREE_TYPE (t) = type;
+ TREE_OVERFLOW (t)
+ = (TREE_OVERFLOW (arg0)
+ | force_fit_type (t, overflow));
+ TREE_CONSTANT_OVERFLOW (t)
+ = TREE_OVERFLOW (t) | TREE_CONSTANT_OVERFLOW (arg0);
+ return t;
+ }
+ }
+ else if (TREE_CODE (arg0) == REAL_CST)
+ {
+ if (REAL_VALUE_NEGATIVE (TREE_REAL_CST (arg0)))
+ return build_real (type, REAL_VALUE_NEGATE (TREE_REAL_CST (arg0)));
+ else
+ return arg0;
+ }
+#ifdef ENABLE_CHECKING
+ else
+ abort ();
+#endif
+
+ return t;
+}
+
+/* Given CODE, a relational operator, the target type, TYPE and two
+ constant operands OP0 and OP1, return the result of the
+ relational operation. If the result is not a compile time
+ constant, then return NULL_TREE. */
+
+static tree
+fold_relational_const (enum tree_code code, tree type, tree op0, tree op1)
+{
+ tree tem;
+ int invert;
+
+ /* From here on, the only cases we handle are when the result is
+ known to be a constant.
+
+ To compute GT, swap the arguments and do LT.
+ To compute GE, do LT and invert the result.
+ To compute LE, swap the arguments, do LT and invert the result.
+ To compute NE, do EQ and invert the result.
+
+ Therefore, the code below must handle only EQ and LT. */
+
+ if (code == LE_EXPR || code == GT_EXPR)
+ {
+ tem = op0, op0 = op1, op1 = tem;
+ code = swap_tree_comparison (code);
+ }
+
+ /* Note that it is safe to invert for real values here because we
+ will check below in the one case that it matters. */
+
+ tem = NULL_TREE;
+ invert = 0;
+ if (code == NE_EXPR || code == GE_EXPR)
+ {
+ invert = 1;
+ code = invert_tree_comparison (code);
+ }
+
+ /* Compute a result for LT or EQ if args permit;
+ Otherwise return T. */
+ if (TREE_CODE (op0) == INTEGER_CST && TREE_CODE (op1) == INTEGER_CST)
+ {
+ if (code == EQ_EXPR)
+ tem = build_int_2 (tree_int_cst_equal (op0, op1), 0);
+ else
+ tem = build_int_2 ((TYPE_UNSIGNED (TREE_TYPE (op0))
+ ? INT_CST_LT_UNSIGNED (op0, op1)
+ : INT_CST_LT (op0, op1)),
+ 0);
+ }
+
+ else if (code == EQ_EXPR && !TREE_SIDE_EFFECTS (op0)
+ && integer_zerop (op1) && tree_expr_nonzero_p (op0))
+ tem = build_int_2 (0, 0);
+
+ /* Two real constants can be compared explicitly. */
+ else if (TREE_CODE (op0) == REAL_CST && TREE_CODE (op1) == REAL_CST)
+ {
+ /* If either operand is a NaN, the result is false with two
+ exceptions: First, an NE_EXPR is true on NaNs, but that case
+ is already handled correctly since we will be inverting the
+ result for NE_EXPR. Second, if we had inverted a LE_EXPR
+ or a GE_EXPR into a LT_EXPR, we must return true so that it
+ will be inverted into false. */
+
+ if (REAL_VALUE_ISNAN (TREE_REAL_CST (op0))
+ || REAL_VALUE_ISNAN (TREE_REAL_CST (op1)))
+ tem = build_int_2 (invert && code == LT_EXPR, 0);
+
+ else if (code == EQ_EXPR)
+ tem = build_int_2 (REAL_VALUES_EQUAL (TREE_REAL_CST (op0),
+ TREE_REAL_CST (op1)),
+ 0);
+ else
+ tem = build_int_2 (REAL_VALUES_LESS (TREE_REAL_CST (op0),
+ TREE_REAL_CST (op1)),
+ 0);
+ }
+
+ if (tem == NULL_TREE)
+ return NULL_TREE;
+
+ if (invert)
+ TREE_INT_CST_LOW (tem) ^= 1;
+
+ TREE_TYPE (tem) = type;
+ if (TREE_CODE (type) == BOOLEAN_TYPE)
+ return lang_hooks.truthvalue_conversion (tem);
+ return tem;
+}
+
#include "gt-fold-const.h"