}
else if (flag_trapping_math)
{
- /* Check that the original operation and the optimized ones will trap
+ /* Check that the original operation and the optimized ones will trap
under the same condition. */
bool ltrap = (lcompcode & COMPCODE_UNORD) == 0
&& (lcompcode != COMPCODE_EQ)
make_range (tree exp, int *pin_p, tree *plow, tree *phigh)
{
enum tree_code code;
- tree arg0 = NULL_TREE, arg1 = NULL_TREE, type = NULL_TREE;
- tree orig_type = NULL_TREE;
+ tree arg0 = NULL_TREE, arg1 = NULL_TREE;
+ tree exp_type = NULL_TREE, arg0_type = NULL_TREE;
int in_p, n_in_p;
tree low, high, n_low, n_high;
while (1)
{
code = TREE_CODE (exp);
+ exp_type = TREE_TYPE (exp);
if (IS_EXPR_CODE_CLASS (TREE_CODE_CLASS (code)))
{
if (TREE_CODE_CLASS (code) == '<'
|| TREE_CODE_CLASS (code) == '1'
|| TREE_CODE_CLASS (code) == '2')
- type = TREE_TYPE (arg0);
+ arg0_type = TREE_TYPE (arg0);
if (TREE_CODE_CLASS (code) == '2'
|| TREE_CODE_CLASS (code) == '<'
|| (TREE_CODE_CLASS (code) == 'e'
arg1 = TREE_OPERAND (exp, 1);
}
- /* Set ORIG_TYPE as soon as TYPE is non-null so that we do not
- lose a cast by accident. */
- if (type != NULL_TREE && orig_type == NULL_TREE)
- orig_type = type;
-
switch (code)
{
case TRUTH_NOT_EXPR:
abort ();
}
- exp = arg0;
-
/* If this is an unsigned comparison, we also know that EXP is
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 (TYPE_UNSIGNED (type) && (low == 0 || high == 0))
+ range tests. We test arg0_type since often the return type
+ of, e.g. EQ_EXPR, is boolean. */
+ if (TYPE_UNSIGNED (arg0_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),
+ 1, fold_convert (arg0_type, integer_zero_node),
NULL_TREE))
break;
in_p = ! in_p;
high = range_binop (MINUS_EXPR, NULL_TREE, low, 0,
integer_one_node, 0);
- low = fold_convert (type, integer_zero_node);
+ low = fold_convert (arg0_type, integer_zero_node);
}
}
+
+ exp = arg0;
continue;
case NEGATE_EXPR:
/* (-x) IN [a,b] -> x in [-b, -a] */
- n_low = range_binop (MINUS_EXPR, type,
- fold_convert (type, integer_zero_node),
+ n_low = range_binop (MINUS_EXPR, exp_type,
+ fold_convert (exp_type, integer_zero_node),
0, high, 1);
- n_high = range_binop (MINUS_EXPR, type,
- fold_convert (type, integer_zero_node),
+ n_high = range_binop (MINUS_EXPR, exp_type,
+ fold_convert (exp_type, integer_zero_node),
0, low, 0);
low = n_low, high = n_high;
exp = arg0;
case BIT_NOT_EXPR:
/* ~ X -> -X - 1 */
- exp = build2 (MINUS_EXPR, type, negate_expr (arg0),
- fold_convert (type, integer_one_node));
+ exp = build2 (MINUS_EXPR, exp_type, negate_expr (arg0),
+ fold_convert (exp_type, integer_one_node));
continue;
case PLUS_EXPR: case MINUS_EXPR:
the bounds don't overflow. For unsigned, overflow is defined
and this is exactly the right thing. */
n_low = range_binop (code == MINUS_EXPR ? PLUS_EXPR : MINUS_EXPR,
- type, low, 0, arg1, 0);
+ arg0_type, low, 0, arg1, 0);
n_high = range_binop (code == MINUS_EXPR ? PLUS_EXPR : MINUS_EXPR,
- type, high, 1, arg1, 0);
+ arg0_type, high, 1, arg1, 0);
if ((n_low != 0 && TREE_OVERFLOW (n_low))
|| (n_high != 0 && TREE_OVERFLOW (n_high)))
break;
value thus making n_high < n_low, and normalize it. */
if (n_low && n_high && tree_int_cst_lt (n_high, n_low))
{
- low = range_binop (PLUS_EXPR, type, n_high, 0,
+ low = range_binop (PLUS_EXPR, arg0_type, n_high, 0,
integer_one_node, 0);
- high = range_binop (MINUS_EXPR, type, n_low, 0,
+ high = range_binop (MINUS_EXPR, arg0_type, n_low, 0,
integer_one_node, 0);
/* If the range is of the form +/- [ x+1, x ], we won't
continue;
case NOP_EXPR: case NON_LVALUE_EXPR: case CONVERT_EXPR:
- if (TYPE_PRECISION (type) > TYPE_PRECISION (orig_type))
+ if (TYPE_PRECISION (arg0_type) > TYPE_PRECISION (exp_type))
break;
- if (! INTEGRAL_TYPE_P (type)
- || (low != 0 && ! int_fits_type_p (low, type))
- || (high != 0 && ! int_fits_type_p (high, type)))
+ if (! INTEGRAL_TYPE_P (arg0_type)
+ || (low != 0 && ! int_fits_type_p (low, arg0_type))
+ || (high != 0 && ! int_fits_type_p (high, arg0_type)))
break;
n_low = low, n_high = high;
if (n_low != 0)
- n_low = fold_convert (type, n_low);
+ n_low = fold_convert (arg0_type, n_low);
if (n_high != 0)
- n_high = fold_convert (type, n_high);
+ n_high = fold_convert (arg0_type, n_high);
- /* If we're converting from an unsigned to a signed type,
- we will be doing the comparison as unsigned. The tests above
- have already verified that LOW and HIGH are both positive.
- So we have to make sure that the original unsigned value will
- be interpreted as positive. */
- if (TYPE_UNSIGNED (type) && ! TYPE_UNSIGNED (TREE_TYPE (exp)))
+ /* If we're converting arg0 from an unsigned type, to exp,
+ a signed type, we will be doing the compairson as unsigned.
+ The tests above have already verified that LOW and HIGH
+ are both positive.
+
+ So we have to ensure that we will handle large unsigned
+ values the same way that the current signed bounds treat
+ negative values. */
+
+ if (!TYPE_UNSIGNED (exp_type) && TYPE_UNSIGNED (arg0_type))
{
- tree equiv_type = lang_hooks.types.type_for_mode
- (TYPE_MODE (type), 1);
tree high_positive;
+ tree equiv_type = lang_hooks.types.type_for_mode
+ (TYPE_MODE (arg0_type), 1);
/* A range without an upper bound is, naturally, unbounded.
Since convert would have cropped a very large value, use
the max value for the destination type. */
high_positive
= TYPE_MAX_VALUE (equiv_type) ? TYPE_MAX_VALUE (equiv_type)
- : TYPE_MAX_VALUE (type);
+ : TYPE_MAX_VALUE (arg0_type);
- if (TYPE_PRECISION (type) == TYPE_PRECISION (TREE_TYPE (exp)))
- high_positive = fold (build2 (RSHIFT_EXPR, type,
- fold_convert (type,
+ if (TYPE_PRECISION (exp_type) == TYPE_PRECISION (arg0_type))
+ high_positive = fold (build2 (RSHIFT_EXPR, arg0_type,
+ fold_convert (arg0_type,
high_positive),
- fold_convert (type,
+ fold_convert (arg0_type,
integer_one_node)));
/* If the low bound is specified, "and" the range with the
{
if (! merge_ranges (&n_in_p, &n_low, &n_high,
1, n_low, n_high, 1,
- fold_convert (type, integer_zero_node),
+ fold_convert (arg0_type, integer_zero_node),
high_positive))
break;
that will be interpreted as negative. */
if (! merge_ranges (&n_in_p, &n_low, &n_high,
0, n_low, n_high, 1,
- fold_convert (type, integer_zero_node),
+ fold_convert (arg0_type, integer_zero_node),
high_positive))
break;
not appropriate if we are in gimple form. */
if (in_gimple_form)
return NULL_TREE;
-
+
temp = fold (build2 (neg ? LT_EXPR : GT_EXPR, type,
arg0, build_real (TREE_TYPE (arg0), max)));
return fold (build1 (TRUTH_NOT_EXPR, type, temp));
equality/inequality test, then return a simplified form of
the test using shifts and logical operations. Otherwise return
NULL. TYPE is the desired result type. */
-
+
tree
fold_single_bit_test (enum tree_code code, tree arg0, tree arg1,
tree result_type)
arg1 = TREE_OPERAND (arg0, 1);
arg0 = TREE_OPERAND (arg0, 0);
- /* This requires us to invert the code. */
+ /* This requires us to invert the code. */
code = (code == EQ_EXPR ? NE_EXPR : EQ_EXPR);
}
int ops_unsigned;
tree signed_type, unsigned_type, intermediate_type;
tree arg00;
-
+
/* If we have (A & C) != 0 where C is the sign bit of A, convert
this into A < 0. Similarly for (A & C) == 0 into A >= 0. */
arg00 = sign_bit_p (TREE_OPERAND (arg0, 0), TREE_OPERAND (arg0, 1));
fold_convert (stype, integer_zero_node)));
}
- /* Otherwise we have (A & C) != 0 where C is a single bit,
+ /* Otherwise we have (A & C) != 0 where C is a single bit,
convert that into ((A >> C2) & 1). Where C2 = log2(C).
Similarly for (A & C) == 0. */
return 0;
if (TREE_CONSTANT (arg0))
return 1;
-
+
if (optimize_size)
return 0;
tree mask0 = TREE_OPERAND (arg0, 1);
tree mask1 = TREE_OPERAND (arg1, 1);
tree tem = fold (build1 (BIT_NOT_EXPR, type, mask0));
-
+
if (operand_equal_p (tem, mask1, 0))
{
tem = fold (build2 (BIT_XOR_EXPR, type,
/* The argument to invert_truthvalue must have Boolean type. */
if (TREE_CODE (TREE_TYPE (arg0)) != BOOLEAN_TYPE)
arg0 = fold_convert (boolean_type_node, arg0);
-
+
/* Note that the operand of this must be an int
and its values must be 0 or 1.
("true" is a fixed value perhaps depending on the language,
}
/* 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.
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.
return omit_one_operand (type, op1, op0);
goto binary;
-
+
case TRUNC_DIV_EXPR:
case ROUND_DIV_EXPR:
case FLOOR_DIV_EXPR:
/* Given the components of a unary expression CODE, TYPE and OP0,
attempt to fold the expression to a constant without modifying
- TYPE or OP0.
+ 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
{
tree low_bound = array_ref_low_bound (exp);
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
else
abort ();
#endif
-
+
return t;
}
else
abort ();
#endif
-
+
return t;
}
else
abort ();
#endif
-
+
return t;
}