fold_convert (type, t2));
}
\f
+/* Check whether TYPE1 and TYPE2 are equivalent integer types, suitable
+ for use in int_const_binop, size_binop and size_diffop. */
+
+static bool
+int_binop_types_match_p (enum tree_code code, tree type1, tree type2)
+{
+ if (TREE_CODE (type1) != INTEGER_TYPE && !POINTER_TYPE_P (type1))
+ return false;
+ if (TREE_CODE (type2) != INTEGER_TYPE && !POINTER_TYPE_P (type2))
+ return false;
+
+ switch (code)
+ {
+ case LSHIFT_EXPR:
+ case RSHIFT_EXPR:
+ case LROTATE_EXPR:
+ case RROTATE_EXPR:
+ return true;
+
+ default:
+ break;
+ }
+
+ return TYPE_UNSIGNED (type1) == TYPE_UNSIGNED (type2)
+ && TYPE_PRECISION (type1) == TYPE_PRECISION (type2)
+ && TYPE_MODE (type1) == TYPE_MODE (type2);
+}
+
+
/* Combine two integer constants ARG1 and ARG2 under operation CODE
to produce a new constant. Return NULL_TREE if we don't know how
to evaluate CODE at compile-time.
\f
/* Combine operands OP1 and OP2 with arithmetic operation CODE. CODE
is a tree code. The type of the result is taken from the operands.
- Both must be the same type integer type and it must be a size type.
+ Both must be equivalent integer types, ala int_binop_types_match_p.
If the operands are constant, so is the result. */
tree
if (arg0 == error_mark_node || arg1 == error_mark_node)
return error_mark_node;
- gcc_assert (TREE_CODE (type) == INTEGER_TYPE && TYPE_IS_SIZETYPE (type)
- && type == TREE_TYPE (arg1));
+ gcc_assert (int_binop_types_match_p (code, TREE_TYPE (arg0),
+ TREE_TYPE (arg1)));
/* Handle the special case of two integer constants faster. */
if (TREE_CODE (arg0) == INTEGER_CST && TREE_CODE (arg1) == INTEGER_CST)
tree type = TREE_TYPE (arg0);
tree ctype;
- gcc_assert (TREE_CODE (type) == INTEGER_TYPE && TYPE_IS_SIZETYPE (type)
- && type == TREE_TYPE (arg1));
+ gcc_assert (int_binop_types_match_p (MINUS_EXPR, TREE_TYPE (arg0),
+ TREE_TYPE (arg1)));
/* If the type is already signed, just do the simple thing. */
if (!TYPE_UNSIGNED (type))
return size_binop (MINUS_EXPR, arg0, arg1);
- ctype = type == bitsizetype ? sbitsizetype : ssizetype;
+ if (type == sizetype)
+ ctype = ssizetype;
+ else if (type == bitsizetype)
+ ctype = sbitsizetype;
+ else
+ ctype = lang_hooks.types.signed_type (type);
/* If either operand is not a constant, do the conversions to the signed
type and subtract. The hardware will do the right thing with any
high_positive = fold_build2 (RSHIFT_EXPR, arg0_type,
fold_convert (arg0_type,
high_positive),
- fold_convert (arg0_type,
- integer_one_node));
+ build_int_cst (arg0_type, 1));
/* If the low bound is specified, "and" the range with the
range for which the original unsigned value will be
OEP_ONLY_CONST)
&& operand_equal_p (arg01,
const_binop (PLUS_EXPR, arg2,
- integer_one_node, 0),
+ build_int_cst (type, 1), 0),
OEP_ONLY_CONST))
return pedantic_non_lvalue (fold_build2 (MIN_EXPR,
type, arg1, arg2));
OEP_ONLY_CONST)
&& operand_equal_p (arg01,
const_binop (MINUS_EXPR, arg2,
- integer_one_node, 0),
+ build_int_cst (type, 1), 0),
OEP_ONLY_CONST))
return pedantic_non_lvalue (fold_build2 (MIN_EXPR,
type, arg1, arg2));
OEP_ONLY_CONST)
&& operand_equal_p (arg01,
const_binop (MINUS_EXPR, arg2,
- integer_one_node, 0),
+ build_int_cst (type, 1), 0),
OEP_ONLY_CONST))
return pedantic_non_lvalue (fold_build2 (MAX_EXPR,
type, arg1, arg2));
OEP_ONLY_CONST)
&& operand_equal_p (arg01,
const_binop (PLUS_EXPR, arg2,
- integer_one_node, 0),
+ build_int_cst (type, 1), 0),
OEP_ONLY_CONST))
return pedantic_non_lvalue (fold_build2 (MAX_EXPR,
type, arg1, arg2));
if (unsigned_p)
{
- tmp = int_const_binop (MINUS_EXPR, arg01, integer_one_node, 0);
+ tmp = int_const_binop (MINUS_EXPR, arg01,
+ build_int_cst (TREE_TYPE (arg01), 1), 0);
lo = prod;
/* Likewise hi = int_const_binop (PLUS_EXPR, prod, tmp, 0). */
}
else if (tree_int_cst_sgn (arg01) >= 0)
{
- tmp = int_const_binop (MINUS_EXPR, arg01, integer_one_node, 0);
+ tmp = int_const_binop (MINUS_EXPR, arg01,
+ build_int_cst (TREE_TYPE (arg01), 1), 0);
switch (tree_int_cst_sgn (arg1))
{
case -1:
/* A negative divisor reverses the relational operators. */
code = swap_tree_comparison (code);
- tmp = int_const_binop (PLUS_EXPR, arg01, integer_one_node, 0);
+ tmp = int_const_binop (PLUS_EXPR, arg01,
+ build_int_cst (TREE_TYPE (arg01), 1), 0);
switch (tree_int_cst_sgn (arg1))
{
case -1:
enum machine_mode operand_mode = TYPE_MODE (type);
int ops_unsigned;
tree signed_type, unsigned_type, intermediate_type;
- tree tem;
+ tree tem, one;
/* First, see if we can fold the single bit test into a sign-bit
test. */
inner = build2 (RSHIFT_EXPR, intermediate_type,
inner, size_int (bitnum));
+ one = build_int_cst (intermediate_type, 1);
+
if (code == EQ_EXPR)
- inner = fold_build2 (BIT_XOR_EXPR, intermediate_type,
- inner, integer_one_node);
+ inner = fold_build2 (BIT_XOR_EXPR, intermediate_type, inner, one);
/* Put the AND last so it can combine with more things. */
- inner = build2 (BIT_AND_EXPR, intermediate_type,
- inner, integer_one_node);
+ inner = build2 (BIT_AND_EXPR, intermediate_type, inner, one);
/* Make sure to return the proper type. */
inner = fold_convert (result_type, inner);
if (integer_pow2p (c) && tree_int_cst_sgn (c) > 0)
{
- tree mask = fold_build2 (MINUS_EXPR, TREE_TYPE (arg1),
- arg1, integer_one_node);
+ tree mask = fold_build2 (MINUS_EXPR, TREE_TYPE (arg1), arg1,
+ build_int_cst (TREE_TYPE (arg1), 1));
return fold_build2 (BIT_AND_EXPR, type,
fold_convert (type, arg0),
fold_convert (type, mask));
RROTATE_EXPR by a new constant. */
if (code == LROTATE_EXPR && TREE_CODE (arg1) == INTEGER_CST)
{
- tree tem = build_int_cst (NULL_TREE,
+ tree tem = build_int_cst (TREE_TYPE (arg1),
GET_MODE_BITSIZE (TYPE_MODE (type)));
- tem = fold_convert (TREE_TYPE (arg1), tem);
tem = const_binop (MINUS_EXPR, tem, arg1, 0);
return fold_build2 (RROTATE_EXPR, type, arg0, tem);
}
switch (code)
{
case GT_EXPR:
- arg1 = const_binop (PLUS_EXPR, arg1, integer_one_node, 0);
+ arg1 = const_binop (PLUS_EXPR, arg1,
+ build_int_cst (TREE_TYPE (arg1), 1), 0);
return fold_build2 (EQ_EXPR, type, arg0, arg1);
case LE_EXPR:
- arg1 = const_binop (PLUS_EXPR, arg1, integer_one_node, 0);
+ arg1 = const_binop (PLUS_EXPR, arg1,
+ build_int_cst (TREE_TYPE (arg1), 1), 0);
return fold_build2 (NE_EXPR, type, arg0, arg1);
default:
break;