}
}
\f
-/* Return an expr equal to X but certainly not valid as an lvalue. */
+/* Return false if expr can be assumed not to be an value, true
+ otherwise. */
-tree
-non_lvalue (tree x)
+static bool
+maybe_lvalue_p (tree x)
{
- /* While we are in GIMPLE, NON_LVALUE_EXPR doesn't mean anything to
- us. */
- if (in_gimple_form)
- return x;
-
/* We only need to wrap lvalue tree codes. */
switch (TREE_CODE (x))
{
/* Assume the worst for front-end tree codes. */
if ((int)TREE_CODE (x) >= NUM_TREE_CODES)
break;
- return x;
+ return false;
}
+
+ return true;
+}
+
+/* Return an expr equal to X but certainly not valid as an lvalue. */
+
+tree
+non_lvalue (tree x)
+{
+ /* While we are in GIMPLE, NON_LVALUE_EXPR doesn't mean anything to
+ us. */
+ if (in_gimple_form)
+ return x;
+
+ if (! maybe_lvalue_p (x))
+ return x;
return build1 (NON_LVALUE_EXPR, TREE_TYPE (x), x);
}
if ((FLOAT_TYPE_P (TREE_TYPE (arg01))
? real_zerop (arg01)
: integer_zerop (arg01))
- && TREE_CODE (arg2) == NEGATE_EXPR
- && operand_equal_p (TREE_OPERAND (arg2, 0), arg1, 0))
+ && ((TREE_CODE (arg2) == NEGATE_EXPR
+ && operand_equal_p (TREE_OPERAND (arg2, 0), arg1, 0))
+ /* In the case that A is of the form X-Y, '-A' (arg2) may
+ have already been folded to Y-X, check for that. */
+ || (TREE_CODE (arg1) == MINUS_EXPR
+ && TREE_CODE (arg2) == MINUS_EXPR
+ && operand_equal_p (TREE_OPERAND (arg1, 0),
+ TREE_OPERAND (arg2, 1), 0)
+ && operand_equal_p (TREE_OPERAND (arg1, 1),
+ TREE_OPERAND (arg2, 0), 0))))
switch (comp_code)
{
case EQ_EXPR:
a number and A is not. The conditions in the original
expressions will be false, so all four give B. The min()
and max() versions would give a NaN instead. */
- if (operand_equal_for_comparison_p (arg01, arg2, arg00))
+ if (operand_equal_for_comparison_p (arg01, arg2, arg00)
+ /* Avoid these transformations if the COND_EXPR may be used
+ as an lvalue in the C++ front-end. PR c++/19199. */
+ && (in_gimple_form
+ || strcmp (lang_hooks.name, "GNU C++") != 0
+ || ! maybe_lvalue_p (arg1)
+ || ! maybe_lvalue_p (arg2)))
{
tree comp_op0 = arg00;
tree comp_op1 = arg01;
if (lhs == 0)
{
true_value = fold_convert (cond_type, true_value);
- lhs = fold (cond_first_p ? build2 (code, type, true_value, arg)
- : build2 (code, type, arg, true_value));
+ if (cond_first_p)
+ lhs = fold_build2 (code, type, true_value, arg);
+ else
+ lhs = fold_build2 (code, type, arg, true_value);
}
if (rhs == 0)
{
false_value = fold_convert (cond_type, false_value);
- rhs = fold (cond_first_p ? build2 (code, type, false_value, arg)
- : build2 (code, type, arg, false_value));
+ if (cond_first_p)
+ rhs = fold_build2 (code, type, false_value, arg);
+ else
+ rhs = fold_build2 (code, type, arg, false_value);
}
test = fold_build3 (COND_EXPR, type, test, lhs, rhs);
int inside_int = INTEGRAL_TYPE_P (inside_type);
int inside_ptr = POINTER_TYPE_P (inside_type);
int inside_float = FLOAT_TYPE_P (inside_type);
+ int inside_vec = TREE_CODE (inside_type) == VECTOR_TYPE;
unsigned int inside_prec = TYPE_PRECISION (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);
+ int inter_vec = TREE_CODE (inter_type) == VECTOR_TYPE;
unsigned int inter_prec = TYPE_PRECISION (inter_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);
+ int final_vec = TREE_CODE (type) == VECTOR_TYPE;
unsigned int final_prec = TYPE_PRECISION (type);
int final_unsignedp = TYPE_UNSIGNED (type);
since then we sometimes need the inner conversion. Likewise if
the outer has a precision not equal to the size of its mode. */
if ((((inter_int || inter_ptr) && (inside_int || inside_ptr))
- || (inter_float && inside_float))
+ || (inter_float && inside_float)
+ || (inter_vec && inside_vec))
&& inter_prec >= inside_prec
- && (inter_float || inter_unsignedp == inside_unsignedp)
+ && (inter_float || inter_vec
+ || inter_unsignedp == inside_unsignedp)
&& ! (final_prec != GET_MODE_BITSIZE (TYPE_MODE (type))
&& TYPE_MODE (type) == TYPE_MODE (inter_type))
- && ! final_ptr)
+ && ! final_ptr
+ && (! final_vec || inter_prec == inside_prec))
return fold_build1 (code, type, TREE_OPERAND (op0, 0));
/* If we have a sign-extension of a zero-extended value, we can
/* Two conversions in a row are not needed unless:
- some conversion is floating-point (overstrict for now), or
+ - some conversion is a vector (overstrict for now), or
- the intermediate type is narrower than both initial and
final, or
- the intermediate type and innermost type differ in signedness,
- the final type is a pointer type and the precisions of the
initial and intermediate types differ. */
if (! inside_float && ! inter_float && ! final_float
+ && ! inside_vec && ! inter_vec && ! final_vec
&& (inter_prec > inside_prec || inter_prec > final_prec)
&& ! (inside_int && inter_int
&& inter_unsignedp != inside_unsignedp
{
/* Don't leave an assignment inside a conversion
unless assigning a bitfield. */
- tem = build1 (code, type, TREE_OPERAND (op0, 1));
+ tem = fold_build1 (code, type, TREE_OPERAND (op0, 1));
/* First do the assignment, then return converted constant. */
- tem = build2 (COMPOUND_EXPR, TREE_TYPE (tem), op0, fold (tem));
+ tem = build2 (COMPOUND_EXPR, TREE_TYPE (tem), op0, tem);
TREE_NO_WARNING (tem) = 1;
TREE_USED (tem) = 1;
return tem;
if (fcode0 == fcode1 && BUILTIN_EXPONENT_P (fcode0))
{
tree expfn = TREE_OPERAND (TREE_OPERAND (arg0, 0), 0);
- 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));
+ tree arg = fold_build2 (PLUS_EXPR, type,
+ TREE_VALUE (TREE_OPERAND (arg0, 1)),
+ TREE_VALUE (TREE_OPERAND (arg1, 1)));
+ tree arglist = build_tree_list (NULL_TREE, arg);
return build_function_call_expr (expfn, arglist);
}
if (operand_equal_p (arg01, arg11, 0))
{
tree powfn = TREE_OPERAND (TREE_OPERAND (arg0, 0), 0);
- tree arg = build2 (MULT_EXPR, type, arg00, arg10);
- tree arglist = tree_cons (NULL_TREE, fold (arg),
+ tree arg = fold_build2 (MULT_EXPR, type, arg00, arg10);
+ tree arglist = tree_cons (NULL_TREE, arg,
build_tree_list (NULL_TREE,
arg01));
return build_function_call_expr (powfn, arglist);
return omit_one_operand (type, integer_one_node, arg0);
}
- tem = build2 (code, type, cval1, cval2);
if (save_p)
- return save_expr (tem);
+ return save_expr (build2 (code, type, cval1, cval2));
else
- return fold (tem);
+ return fold_build2 (code, type, cval1, cval2);
}
}
}
case CONST_DECL:
return fold (DECL_INITIAL (t));
+ case ASSERT_EXPR:
+ {
+ /* Given ASSERT_EXPR <Y, COND>, return Y if COND can be folded
+ to boolean_true_node. If COND folds to boolean_false_node,
+ return ASSERT_EXPR <Y, 0>. Otherwise, return the original
+ expression. */
+ tree c = fold (ASSERT_EXPR_COND (t));
+ if (c == boolean_true_node)
+ return ASSERT_EXPR_VAR (t);
+ else if (c == boolean_false_node)
+ return build (ASSERT_EXPR, TREE_TYPE (t), ASSERT_EXPR_VAR (t), c);
+ else
+ return t;
+ }
+
default:
return t;
} /* switch (code) */
#endif
/* Fold a unary tree expression with code CODE of type TYPE with an
- operand OP0. Return a folded expresion if successful. Otherwise,
+ operand OP0. Return a folded expression if successful. Otherwise,
return a tree expression with code CODE of type TYPE with an
operand OP0. */
}
/* Fold a binary tree expression with code CODE of type TYPE with
- operands OP0 and OP1. Return a folded expresion if successful.
+ operands OP0 and OP1. Return a folded expression if successful.
Otherwise, return a tree expression with code CODE of type TYPE
with operands OP0 and OP1. */
}
/* Fold a ternary tree expression with code CODE of type TYPE with
- operands OP0, OP1, and OP2. Return a folded expresion if
+ operands OP0, OP1, and OP2. Return a folded expression if
successful. Otherwise, return a tree expression with code CODE of
type TYPE with operands OP0, OP1, and OP2. */
CASE_BUILTIN_F (BUILT_IN_EXPM1)
CASE_BUILTIN_F (BUILT_IN_FLOOR)
CASE_BUILTIN_F (BUILT_IN_FMOD)
+ CASE_BUILTIN_F (BUILT_IN_LCEIL)
CASE_BUILTIN_F (BUILT_IN_LDEXP)
+ CASE_BUILTIN_F (BUILT_IN_LFLOOR)
+ CASE_BUILTIN_F (BUILT_IN_LLCEIL)
+ CASE_BUILTIN_F (BUILT_IN_LLFLOOR)
CASE_BUILTIN_F (BUILT_IN_LLRINT)
CASE_BUILTIN_F (BUILT_IN_LLROUND)
CASE_BUILTIN_F (BUILT_IN_LRINT)