diff options
Diffstat (limited to 'gcc/fold-const.cc')
-rw-r--r-- | gcc/fold-const.cc | 35 |
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; |