summaryrefslogtreecommitdiff
path: root/gcc/fold-const.cc
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/fold-const.cc')
-rw-r--r--gcc/fold-const.cc35
1 files changed, 30 insertions, 5 deletions
diff --git a/gcc/fold-const.cc b/gcc/fold-const.cc
index fb08fa1dbc6..a57ad0739fb 100644
--- a/gcc/fold-const.cc
+++ b/gcc/fold-const.cc
@@ -2379,13 +2379,12 @@ build_zero_vector (tree type)
return build_vector_from_val (type, t);
}
-/* Returns true, if ARG, an operand or a type, is convertible to TYPE
- using a NOP_EXPR. */
+/* Returns true, if ARG is convertible to TYPE using a NOP_EXPR. */
bool
fold_convertible_p (const_tree type, const_tree arg)
{
- const_tree orig = TYPE_P (arg) ? arg : TREE_TYPE (arg);
+ const_tree orig = TREE_TYPE (arg);
if (type == orig)
return true;
@@ -2417,7 +2416,7 @@ fold_convertible_p (const_tree type, const_tree arg)
return (VECTOR_TYPE_P (orig)
&& known_eq (TYPE_VECTOR_SUBPARTS (type),
TYPE_VECTOR_SUBPARTS (orig))
- && fold_convertible_p (TREE_TYPE (type), TREE_TYPE (orig)));
+ && tree_int_cst_equal (TYPE_SIZE (type), TYPE_SIZE (orig)));
default:
return false;
@@ -5212,7 +5211,7 @@ make_range_step (location_t loc, enum tree_code code, tree arg0, tree arg1,
n_high = fold_convert_loc (loc, arg0_type, n_high);
/* If we're converting arg0 from an unsigned type, to exp,
- a signed type, we will be doing the comparison as unsigned.
+ a signed type, we will be doing the comparison as unsigned.
The tests above have already verified that LOW and HIGH
are both positive.
@@ -5274,6 +5273,32 @@ make_range_step (location_t loc, enum tree_code code, tree arg0, tree arg1,
}
}
+ /* Otherwise, if we are converting arg0 from signed type, to exp,
+ an unsigned type, we will do the comparison as signed. If
+ high is non-NULL, we punt above if it doesn't fit in the signed
+ type, so if we get through here, +[-, high] or +[low, high] are
+ equivalent to +[-, n_high] or +[n_low, n_high]. Similarly,
+ +[-, -] or -[-, -] are equivalent too. But if low is specified and
+ high is not, the +[low, -] range is equivalent to union of
+ +[n_low, -] and +[-, -1] ranges, so +[low, -] is equivalent to
+ -[0, n_low-1] and similarly -[low, -] to +[0, n_low-1], except for
+ low being 0, which should be treated as [-, -]. */
+ else if (TYPE_UNSIGNED (exp_type)
+ && !TYPE_UNSIGNED (arg0_type)
+ && low
+ && !high)
+ {
+ if (integer_zerop (low))
+ n_low = NULL_TREE;
+ else
+ {
+ n_high = fold_build2_loc (loc, PLUS_EXPR, arg0_type,
+ n_low, build_int_cst (arg0_type, -1));
+ n_low = build_zero_cst (arg0_type);
+ in_p = !in_p;
+ }
+ }
+
*p_low = n_low;
*p_high = n_high;
*p_in_p = in_p;