Index: gcc/tree-vrp.c =================================================================== --- gcc/tree-vrp.c (revision 120274) +++ gcc/tree-vrp.c (working copy) @@ -23,6 +23,7 @@ Boston, MA 02110-1301, USA. */ #include "system.h" #include "coretypes.h" #include "tm.h" +#include "toplev.h" #include "ggc.h" #include "flags.h" #include "tree.h" @@ -90,6 +91,90 @@ static sbitmap blocks_visited; of values that SSA name N_I may take. */ static value_range_t **vr_value; +/* Hash table of minimum and maximum infinity values for types. */ +static GTY ((if_marked ("tree_map_marked_p"), param_is (struct tree_map))) + htab_t vrp_type_infinity_hash; + + +/* Return whether TYPE has an infinity distinct from + TYPE_{MIN,MAX}_VALUE. */ + +static bool +has_special_infinity (tree type) +{ + return INTEGRAL_TYPE_P (type) && !TYPE_UNSIGNED (type) && !flag_wrapv; +} + +/* Return the entry for the minimum and maximum infinities for TYPE. */ + +static tree +infinity_hash_entry (tree type) +{ + unsigned int hash; + struct tree_map in; + void **loc; + struct tree_map *h; + tree min, max; + + hash = htab_hash_pointer (type); + in.from = type; + loc = htab_find_slot_with_hash (vrp_type_infinity_hash, &in, hash, INSERT); + if (*loc != NULL) + { + h = *(struct tree_map **) loc; + return h->to; + } + + min = copy_node (TYPE_MIN_VALUE (type)); + max = copy_node (TYPE_MAX_VALUE (type)); + + h = ggc_alloc (sizeof (struct tree_map)); + h->hash = hash; + h->from = type; + h->to = tree_cons (min, max, NULL_TREE); + *(struct tree_map **) loc = h; + + return h->to; +} + +/* Return the negative infinity to use for TYPE. */ + +static tree +negative_infinity (tree type) +{ + if (!has_special_infinity (type)) + { + if (INTEGRAL_TYPE_P (type) || SCALAR_FLOAT_TYPE_P (type)) + return TYPE_MIN_VALUE (type); + return NULL_TREE; + } + return TREE_PURPOSE (infinity_hash_entry (type)); +} + +/* Return the positive infinity to use for TYPE. */ + +static tree +positive_infinity (tree type) +{ + if (!has_special_infinity (type)) + { + if (INTEGRAL_TYPE_P (type) || SCALAR_FLOAT_TYPE_P (type)) + return TYPE_MAX_VALUE (type); + return NULL_TREE; + } + return TREE_VALUE (infinity_hash_entry (type)); +} + +/* Return whether VAL is a positive or negative special infinity. */ + +static bool +is_infinity (tree val) +{ + return (has_special_infinity (TREE_TYPE (val)) + && (val == positive_infinity (TREE_TYPE (val)) + || val == negative_infinity (TREE_TYPE (val)))); +} + /* Return true if ARG is marked with the nonnull attribute in the current function signature. */ @@ -154,8 +239,8 @@ set_value_range (value_range_t *vr, enum gcc_assert (min && max); if (INTEGRAL_TYPE_P (TREE_TYPE (min)) && t == VR_ANTI_RANGE) - gcc_assert (min != TYPE_MIN_VALUE (TREE_TYPE (min)) - || max != TYPE_MAX_VALUE (TREE_TYPE (max))); + gcc_assert (min != negative_infinity (TREE_TYPE (min)) + || max != positive_infinity (TREE_TYPE (max))); cmp = compare_values (min, max); gcc_assert (cmp == 0 || cmp == -1 || cmp == -2); @@ -201,7 +286,7 @@ static inline void set_value_range_to_nonnegative (value_range_t *vr, tree type) { tree zero = build_int_cst (type, 0); - set_value_range (vr, VR_RANGE, zero, TYPE_MAX_VALUE (type), vr->equiv); + set_value_range (vr, VR_RANGE, zero, positive_infinity (type), vr->equiv); } /* Set value range VR to a non-NULL range of type TYPE. */ @@ -298,9 +383,17 @@ get_value_range (tree var) static inline bool vrp_operand_equal_p (tree val1, tree val2) { - return (val1 == val2 - || (val1 && val2 - && operand_equal_p (val1, val2, 0))); + if (val1 == val2) + return true; + if (!val1 || !val2 || !operand_equal_p (val1, val2, 0)) + return false; + if (!has_special_infinity (TREE_TYPE (val1))) + return true; + if (val1 == positive_infinity (TREE_TYPE (val1))) + return val2 == positive_infinity (TREE_TYPE (val2)); + if (val1 == negative_infinity (TREE_TYPE (val1))) + return val2 == negative_infinity (TREE_TYPE (val2)); + return true; } /* Return true, if the bitmaps B1 and B2 are equal. */ @@ -392,12 +485,25 @@ symbolic_range_p (value_range_t *vr) || !is_gimple_min_invariant (vr->max)); } +/* Return true if value range VR uses an infinity. */ + +static inline bool +infinity_range_p (value_range_t *vr) +{ + return (vr->type == VR_RANGE + && (is_infinity (vr->min) + || is_infinity (vr->max))); +} + /* Like tree_expr_nonnegative_p, but this function uses value ranges obtained so far. */ static bool vrp_expr_computes_nonnegative (tree expr) { + if (is_infinity (expr)) + return expr == positive_infinity (TREE_TYPE (expr)); + return tree_expr_nonnegative_p (expr); } @@ -407,6 +513,9 @@ vrp_expr_computes_nonnegative (tree expr static bool vrp_expr_computes_nonzero (tree expr) { + if (is_infinity (expr)) + return true; + if (tree_expr_nonzero_p (expr)) return true; @@ -454,6 +563,19 @@ static inline int operand_less_p (tree val, tree val2) { tree tcmp; + + if (is_infinity (val) || is_infinity (val2)) + { + if (val2 == negative_infinity (TREE_TYPE (val2))) + return 0; + else if (val == negative_infinity (TREE_TYPE (val))) + return 1; + else if (val == positive_infinity (TREE_TYPE (val))) + return 0; + else if (val2 == positive_infinity (TREE_TYPE (val2))) + return 1; + } + /* LT is folded faster than GE and others. Inline the common case. */ if (TREE_CODE (val) == INTEGER_CST && TREE_CODE (val2) == INTEGER_CST) { @@ -517,9 +639,16 @@ compare_values (tree val1, tree val2) c1 = TREE_OPERAND (val1, 1); if (tree_int_cst_sgn (c1) == -1) { - c1 = fold_unary_to_constant (NEGATE_EXPR, TREE_TYPE (c1), c1); - if (!c1) - return -2; + if (has_special_infinity (TREE_TYPE (c1)) + && c1 == negative_infinity (TREE_TYPE (c1))) + c2 = positive_infinity (TREE_TYPE (c1)); + else + { + c1 = fold_unary_to_constant (NEGATE_EXPR, TREE_TYPE (c1), + c1); + if (!c1) + return -2; + } code1 = code1 == MINUS_EXPR ? PLUS_EXPR : MINUS_EXPR; } } @@ -537,9 +666,16 @@ compare_values (tree val1, tree val2) c2 = TREE_OPERAND (val2, 1); if (tree_int_cst_sgn (c2) == -1) { - c2 = fold_unary_to_constant (NEGATE_EXPR, TREE_TYPE (c2), c2); - if (!c2) - return -2; + if (has_special_infinity (TREE_TYPE (c2)) + && c2 == negative_infinity (TREE_TYPE (c2))) + c2 = positive_infinity (TREE_TYPE (c2)); + else + { + c2 = fold_unary_to_constant (NEGATE_EXPR, TREE_TYPE (c2), + c2); + if (!c2) + return -2; + } code2 = code2 == MINUS_EXPR ? PLUS_EXPR : MINUS_EXPR; } } @@ -558,6 +694,13 @@ compare_values (tree val1, tree val2) || flag_wrapv) return -2; + if (warn_warnv + && ((c1 != NULL_TREE && is_infinity (c1)) + || (c2 != NULL_TREE && is_infinity (c2)))) + warning (OPT_Warnv, + "assuming signed overflow is undefined when " + "comparing values for VRP"); + if (code1 == SSA_NAME) { if (code2 == PLUS_EXPR) @@ -600,6 +743,44 @@ compare_values (tree val1, tree val2) if (!is_gimple_min_invariant (val1) || !is_gimple_min_invariant (val2)) return -2; + if (is_infinity (val1) || is_infinity (val2)) + { + if (val1 == negative_infinity (TREE_TYPE (val1))) + { + if (val2 == negative_infinity (TREE_TYPE (val2))) + return 0; + else if (TREE_CODE (val2) == INTEGER_CST) + return -1; + else + return -2; + } + else if (val2 == negative_infinity (TREE_TYPE (val2))) + { + if (TREE_CODE (val1) == INTEGER_CST) + return 1; + else + return -2; + } + else if (val1 == positive_infinity (TREE_TYPE (val1))) + { + if (val2 == positive_infinity (TREE_TYPE (val2))) + return 0; + else if (TREE_CODE (val2) == INTEGER_CST) + return 1; + else + return -2; + } + else if (val2 == positive_infinity (TREE_TYPE (val2))) + { + if (TREE_CODE (val1) == INTEGER_CST) + return -1; + else + return -2; + } + else + gcc_unreachable (); + } + if (!POINTER_TYPE_P (TREE_TYPE (val1))) { /* We cannot compare overflowed values. */ @@ -905,14 +1086,16 @@ extract_range_from_assert (value_range_t /* If MIN and MAX cover the whole range for their type, then just use the original LIMIT. */ if (INTEGRAL_TYPE_P (type) - && min == TYPE_MIN_VALUE (type) - && max == TYPE_MAX_VALUE (type)) + && min == negative_infinity (type) + && max == positive_infinity (type)) min = max = limit; set_value_range (vr_p, VR_ANTI_RANGE, min, max, vr_p->equiv); } else if (cond_code == LE_EXPR || cond_code == LT_EXPR) { + /* This should not be negative infinity; there is no overflow + here. */ min = TYPE_MIN_VALUE (type); if (limit_vr == NULL || limit_vr->type == VR_ANTI_RANGE) @@ -933,7 +1116,9 @@ extract_range_from_assert (value_range_t else { /* For LT_EXPR, we create the range [MIN, MAX - 1]. */ - if (cond_code == LT_EXPR) + if (cond_code == LT_EXPR + && (!has_special_infinity (type) + || max != positive_infinity (type))) { tree one = build_int_cst (type, 1); max = fold_build2 (MINUS_EXPR, type, max, one); @@ -944,6 +1129,8 @@ extract_range_from_assert (value_range_t } else if (cond_code == GE_EXPR || cond_code == GT_EXPR) { + /* This should not be positive infinity; there is no overflow + here. */ max = TYPE_MAX_VALUE (type); if (limit_vr == NULL || limit_vr->type == VR_ANTI_RANGE) @@ -964,7 +1151,9 @@ extract_range_from_assert (value_range_t else { /* For GT_EXPR, we create the range [MIN + 1, MAX]. */ - if (cond_code == GT_EXPR) + if (cond_code == GT_EXPR + && (!has_special_infinity (type) + || min != negative_infinity (type))) { tree one = build_int_cst (type, 1); min = fold_build2 (PLUS_EXPR, type, min, one); @@ -1134,9 +1323,13 @@ extract_range_from_assert (value_range_t || compare_values (anti_max, real_min) == 0) && compare_values (anti_max, real_max) == -1) { - min = fold_build2 (PLUS_EXPR, TREE_TYPE (var_vr->min), - anti_max, - build_int_cst (TREE_TYPE (var_vr->min), 1)); + if (has_special_infinity (TREE_TYPE (anti_max)) + && anti_max == TYPE_MAX_VALUE (TREE_TYPE (anti_max))) + min = positive_infinity (TREE_TYPE (var_vr->min)); + else + min = fold_build2 (PLUS_EXPR, TREE_TYPE (var_vr->min), + anti_max, + build_int_cst (TREE_TYPE (var_vr->min), 1)); max = real_max; set_value_range (vr_p, VR_RANGE, min, max, vr_p->equiv); } @@ -1147,9 +1340,13 @@ extract_range_from_assert (value_range_t && (compare_values (anti_min, real_max) == -1 || compare_values (anti_min, real_max) == 0)) { - max = fold_build2 (MINUS_EXPR, TREE_TYPE (var_vr->min), - anti_min, - build_int_cst (TREE_TYPE (var_vr->min), 1)); + if (has_special_infinity (TREE_TYPE (anti_min)) + && anti_min == TYPE_MIN_VALUE (TREE_TYPE (anti_min))) + max = negative_infinity (TREE_TYPE (var_vr->min)); + else + max = fold_build2 (MINUS_EXPR, TREE_TYPE (var_vr->min), + anti_min, + build_int_cst (TREE_TYPE (var_vr->min), 1)); min = real_min; set_value_range (vr_p, VR_RANGE, min, max, vr_p->equiv); } @@ -1236,9 +1433,11 @@ vrp_int_const_binop (enum tree_code code } } - else if (TREE_OVERFLOW (res) - && !TREE_OVERFLOW (val1) - && !TREE_OVERFLOW (val2)) + else if ((TREE_OVERFLOW (res) + && !TREE_OVERFLOW (val1) + && !TREE_OVERFLOW (val2)) + || is_infinity (val1) + || is_infinity (val2)) { /* If the operation overflowed but neither VAL1 nor VAL2 are overflown, return -INF or +INF depending on the operation @@ -1274,9 +1473,9 @@ vrp_int_const_binop (enum tree_code code || code == CEIL_DIV_EXPR || code == EXACT_DIV_EXPR || code == ROUND_DIV_EXPR) - return TYPE_MAX_VALUE (TREE_TYPE (res)); + return positive_infinity (TREE_TYPE (res)); else - return TYPE_MIN_VALUE (TREE_TYPE (res)); + return negative_infinity (TREE_TYPE (res)); } return res; @@ -1430,7 +1629,9 @@ extract_range_from_binary_expr (value_ra && vr1.type != VR_VARYING && vr0.type == vr1.type && !symbolic_range_p (&vr0) - && !symbolic_range_p (&vr1)) + && !infinity_range_p (&vr0) + && !symbolic_range_p (&vr1) + && !infinity_range_p (&vr1)) { /* Boolean expressions cannot be folded with int_const_binop. */ min = fold_binary (code, TREE_TYPE (expr), vr0.min, vr1.min); @@ -1581,15 +1782,17 @@ extract_range_from_binary_expr (value_ra if (vr0.type == VR_RANGE && vr0.min == vr0.max && tree_expr_nonnegative_p (vr0.max) - && TREE_CODE (vr0.max) == INTEGER_CST) + && TREE_CODE (vr0.max) == INTEGER_CST + && !infinity_range_p (&vr0)) { min = build_int_cst (TREE_TYPE (expr), 0); max = vr0.max; } else if (vr1.type == VR_RANGE - && vr1.min == vr1.max - && tree_expr_nonnegative_p (vr1.max) - && TREE_CODE (vr1.max) == INTEGER_CST) + && vr1.min == vr1.max + && tree_expr_nonnegative_p (vr1.max) + && TREE_CODE (vr1.max) == INTEGER_CST + && !infinity_range_p (&vr1)) { type = VR_RANGE; min = build_int_cst (TREE_TYPE (expr), 0); @@ -1606,8 +1809,12 @@ extract_range_from_binary_expr (value_ra /* If either MIN or MAX overflowed, then set the resulting range to VARYING. */ - if (!is_gimple_min_invariant (min) || TREE_OVERFLOW (min) - || !is_gimple_min_invariant (max) || TREE_OVERFLOW (max)) + if (!is_gimple_min_invariant (min) + || TREE_OVERFLOW (min) + || is_infinity (min) + || !is_gimple_min_invariant (max) + || TREE_OVERFLOW (max) + || is_infinity (max)) { set_value_range_to_varying (vr); return; @@ -1720,13 +1927,26 @@ extract_range_from_unary_expr (value_ran } else { - orig_min = TYPE_MIN_VALUE (inner_type); - orig_max = TYPE_MAX_VALUE (inner_type); + orig_min = negative_infinity (inner_type); + orig_max = positive_infinity (inner_type); } new_min = fold_convert (outer_type, orig_min); new_max = fold_convert (outer_type, orig_max); + if (has_special_infinity (inner_type)) + { + if (orig_min == negative_infinity (inner_type)) + new_min = negative_infinity (outer_type); + else if (orig_min == positive_infinity (inner_type)) + new_min = positive_infinity (outer_type); + + if (orig_max == negative_infinity (inner_type)) + new_max = negative_infinity (outer_type); + else if (orig_max == positive_infinity (inner_type)) + new_max = positive_infinity (outer_type); + } + /* Verify the new min/max values are gimple values and that they compare equal to the original input's min/max values. */ @@ -1777,16 +1997,28 @@ extract_range_from_unary_expr (value_ran -~[MIN, MIN] == ~[MIN, MIN] -[MIN, 0] == [0, MAX] for -fno-wrapv -[MIN, 0] == [0, MIN] for -fwrapv (will be set to varying later) */ - min = vr0.max == TYPE_MIN_VALUE (TREE_TYPE (expr)) - ? TYPE_MIN_VALUE (TREE_TYPE (expr)) - : fold_unary_to_constant (code, TREE_TYPE (expr), vr0.max); - - max = vr0.min == TYPE_MIN_VALUE (TREE_TYPE (expr)) - ? (vr0.type == VR_ANTI_RANGE || flag_wrapv - ? TYPE_MIN_VALUE (TREE_TYPE (expr)) - : TYPE_MAX_VALUE (TREE_TYPE (expr))) - : fold_unary_to_constant (code, TREE_TYPE (expr), vr0.min); - + if (!has_special_infinity (TREE_TYPE (expr))) + { + min = (vr0.max == TYPE_MIN_VALUE (TREE_TYPE (expr)) + ? TYPE_MIN_VALUE (TREE_TYPE (expr)) + : fold_unary_to_constant (code, TREE_TYPE (expr), vr0.max)); + + max = (vr0.min == TYPE_MIN_VALUE (TREE_TYPE (expr)) + ? TYPE_MIN_VALUE (TREE_TYPE (expr)) + : fold_unary_to_constant (code, TREE_TYPE (expr), vr0.min)); + } + else + { + min = ((vr0.max == positive_infinity (TREE_TYPE (expr)) + || vr0.max == TYPE_MIN_VALUE (TREE_TYPE (expr))) + ? negative_infinity (TREE_TYPE (expr)) + : fold_unary_to_constant (code, TREE_TYPE (expr), vr0.max)); + + max = ((vr0.min == negative_infinity (TREE_TYPE (expr)) + || vr0.min == TYPE_MIN_VALUE (TREE_TYPE (expr))) + ? positive_infinity (TREE_TYPE (expr)) + : fold_unary_to_constant (code, TREE_TYPE (expr), vr0.min)); + } } else if (code == NEGATE_EXPR && TYPE_UNSIGNED (TREE_TYPE (expr))) @@ -1823,11 +2055,17 @@ extract_range_from_unary_expr (value_ran /* ABS_EXPR may flip the range around, if the original range included negative values. */ - min = (vr0.min == TYPE_MIN_VALUE (TREE_TYPE (expr))) - ? TYPE_MAX_VALUE (TREE_TYPE (expr)) - : fold_unary_to_constant (code, TREE_TYPE (expr), vr0.min); - - max = fold_unary_to_constant (code, TREE_TYPE (expr), vr0.max); + min = ((vr0.min == negative_infinity (TREE_TYPE (expr)) + || vr0.min == positive_infinity (TREE_TYPE (expr)) + || vr0.min == TYPE_MIN_VALUE (TREE_TYPE (expr))) + ? positive_infinity (TREE_TYPE (expr)) + : fold_unary_to_constant (code, TREE_TYPE (expr), vr0.min)); + + max = ((vr0.max == positive_infinity (TREE_TYPE (expr)) + || (has_special_infinity (TREE_TYPE (expr)) + && vr0.max == negative_infinity (TREE_TYPE (expr)))) + ? positive_infinity (TREE_TYPE (expr)) + : fold_unary_to_constant (code, TREE_TYPE (expr), vr0.max)); cmp = compare_values (min, max); @@ -1837,7 +2075,7 @@ extract_range_from_unary_expr (value_ran { if (range_includes_zero_p (&vr0)) { - tree type_min_value = TYPE_MIN_VALUE (TREE_TYPE (expr)); + tree type_min_value = negative_infinity (TREE_TYPE (expr)); /* Take the lower of the two values. */ if (cmp != 1) @@ -1860,7 +2098,7 @@ extract_range_from_unary_expr (value_ran anti-range. */ vr0.type = VR_RANGE; min = build_int_cst (TREE_TYPE (expr), 0); - max = TYPE_MAX_VALUE (TREE_TYPE (expr)); + max = positive_infinity (TREE_TYPE (expr)); } } @@ -1888,6 +2126,39 @@ extract_range_from_unary_expr (value_ran /* Otherwise, operate on each end of the range. */ min = fold_unary_to_constant (code, TREE_TYPE (expr), vr0.min); max = fold_unary_to_constant (code, TREE_TYPE (expr), vr0.max); + + if (has_special_infinity (TREE_TYPE (expr))) + { + if (vr0.min == negative_infinity (TREE_TYPE (expr))) + { + if (code == NEGATE_EXPR || code == ABS_EXPR) + min = positive_infinity (TREE_TYPE (expr)); + else + min = vr0.min; + } + else if (vr0.min == positive_infinity (TREE_TYPE (expr))) + { + if (code == NEGATE_EXPR) + min = negative_infinity (TREE_TYPE (expr)); + else + min = vr0.min; + } + + if (vr0.max == positive_infinity (TREE_TYPE (expr))) + { + if (code == NEGATE_EXPR) + max = negative_infinity (TREE_TYPE (expr)); + else + max = vr0.max; + } + else if (vr0.max == negative_infinity (TREE_TYPE (expr))) + { + if (code == NEGATE_EXPR || code == ABS_EXPR) + max = positive_infinity (TREE_TYPE (expr)); + else + max = vr0.max; + } + } } cmp = compare_values (min, max); @@ -1910,7 +2181,7 @@ static void extract_range_from_comparison (value_range_t *vr, tree expr) { tree val = vrp_evaluate_conditional (expr, false); - if (val) + if (val && !is_infinity (val)) { /* Since this expression was found on the RHS of an assignment, its type may be different from _Bool. Convert VAL to EXPR's @@ -2010,11 +2281,11 @@ adjust_range_with_scev (value_range_t *v if (POINTER_TYPE_P (type) || !TYPE_MIN_VALUE (type)) tmin = lower_bound_in_type (type, type); else - tmin = TYPE_MIN_VALUE (type); + tmin = negative_infinity (type); if (POINTER_TYPE_P (type) || !TYPE_MAX_VALUE (type)) tmax = upper_bound_in_type (type, type); else - tmax = TYPE_MAX_VALUE (type); + tmax = positive_infinity (type); if (vr->type == VR_VARYING || vr->type == VR_UNDEFINED) { @@ -2198,13 +2469,25 @@ compare_ranges (enum tree_code comp, val tst = compare_values (vr0->max, vr1->min); if ((comp == LT_EXPR && tst == -1) || (comp == LE_EXPR && (tst == -1 || tst == 0))) - return boolean_true_node; + { + if (infinity_range_p (vr0) || infinity_range_p (vr1)) + warning (OPT_Warnv, + "assuming signed overflow is undefined when " + "comparing ranges in VRP"); + return boolean_true_node; + } /* If VR0 is to the right of VR1, return false. */ tst = compare_values (vr0->min, vr1->max); if ((comp == LT_EXPR && (tst == 0 || tst == 1)) || (comp == LE_EXPR && tst == 1)) - return boolean_false_node; + { + if (infinity_range_p (vr0) || infinity_range_p (vr1)) + warning (OPT_Warnv, + "assuming signed overflow is undefined when " + "comparing ranges in VRP"); + return boolean_false_node; + } /* Otherwise, we don't know. */ return NULL_TREE; @@ -2214,14 +2497,16 @@ compare_ranges (enum tree_code comp, val } -/* Given a value range VR, a value VAL and a comparison code COMP, return - BOOLEAN_TRUE_NODE if VR COMP VAL always returns true for all the - values in VR. Return BOOLEAN_FALSE_NODE if the comparison - always returns false. Return NULL_TREE if it is not always - possible to determine the value of the comparison. */ +/* Given a value range VR, a value VAL and a comparison code COMP, + return BOOLEAN_TRUE_NODE if VR COMP VAL always returns true for all + the values in VR. If INFINITY_CHECK is true, issue warnings when + using an infinite range if appropriate. Return BOOLEAN_FALSE_NODE + if the comparison always returns false. Return NULL_TREE if it is + not always possible to determine the value of the comparison. */ static tree -compare_range_with_value (enum tree_code comp, value_range_t *vr, tree val) +compare_range_with_value (enum tree_code comp, value_range_t *vr, tree val, + bool infinity_check) { if (vr->type == VR_VARYING || vr->type == VR_UNDEFINED) return NULL_TREE; @@ -2278,7 +2563,8 @@ compare_range_with_value (enum tree_code /* Otherwise, they may or may not be different. */ return NULL_TREE; } - else if (comp == LT_EXPR || comp == LE_EXPR) + + if (comp == LT_EXPR || comp == LE_EXPR) { int tst; @@ -2286,13 +2572,27 @@ compare_range_with_value (enum tree_code tst = compare_values (vr->max, val); if ((comp == LT_EXPR && tst == -1) || (comp == LE_EXPR && (tst == -1 || tst == 0))) - return boolean_true_node; + { + if (infinity_check + && (infinity_range_p (vr) || is_infinity (val))) + warning (OPT_Warnv, + "assuming signed overflow is undefined when " + "comparing range with value in VRP"); + return boolean_true_node; + } /* If VR is to the right of VAL, return false. */ tst = compare_values (vr->min, val); if ((comp == LT_EXPR && (tst == 0 || tst == 1)) || (comp == LE_EXPR && tst == 1)) - return boolean_false_node; + { + if (infinity_check + && (infinity_range_p (vr) || is_infinity (val))) + warning (OPT_Warnv, + "assuming signed overflow is undefined when " + "comparing range with value in VRP"); + return boolean_false_node; + } /* Otherwise, we don't know. */ return NULL_TREE; @@ -2305,13 +2605,27 @@ compare_range_with_value (enum tree_code tst = compare_values (vr->min, val); if ((comp == GT_EXPR && tst == 1) || (comp == GE_EXPR && (tst == 0 || tst == 1))) - return boolean_true_node; + { + if (infinity_check + && (infinity_range_p (vr) || is_infinity (val))) + warning (OPT_Warnv, + "assuming signed overflow is undefined when " + "comparing range with value in VRP"); + return boolean_true_node; + } /* If VR is to the left of VAL, return false. */ tst = compare_values (vr->max, val); if ((comp == GT_EXPR && (tst == -1 || tst == 0)) || (comp == GE_EXPR && tst == -1)) - return boolean_false_node; + { + if (infinity_check + && (infinity_range_p (vr) || is_infinity (val))) + warning (OPT_Warnv, + "assuming signed overflow is undefined when " + "comparing range with value in VRP"); + return boolean_false_node; + } /* Otherwise, we don't know. */ return NULL_TREE; @@ -2348,7 +2662,7 @@ dump_value_range (FILE *file, value_rang if (INTEGRAL_TYPE_P (type) && !TYPE_UNSIGNED (type) - && vr->min == TYPE_MIN_VALUE (type)) + && vr->min == negative_infinity (type)) fprintf (file, "-INF"); else print_generic_expr (file, vr->min, 0); @@ -2356,7 +2670,7 @@ dump_value_range (FILE *file, value_rang fprintf (file, ", "); if (INTEGRAL_TYPE_P (type) - && vr->max == TYPE_MAX_VALUE (type)) + && vr->max == positive_infinity (type)) fprintf (file, "+INF"); else print_generic_expr (file, vr->max, 0); @@ -3675,7 +3989,7 @@ compare_name_with_value (enum tree_code equiv_vr.max = ssa_name (i); } - t = compare_range_with_value (comp, &equiv_vr, val); + t = compare_range_with_value (comp, &equiv_vr, val, true); if (t) { /* If we get different answers from different members @@ -3827,7 +4141,8 @@ vrp_evaluate_conditional (tree cond, boo else { value_range_t *vr = get_value_range (cond); - retval = compare_range_with_value (NE_EXPR, vr, boolean_false_node); + retval = compare_range_with_value (NE_EXPR, vr, boolean_false_node, + true); } /* If COND has a known boolean range, return it. */ @@ -3870,10 +4185,12 @@ vrp_evaluate_conditional (tree cond, boo if (vr0 && vr1) return compare_ranges (TREE_CODE (cond), vr0, vr1); else if (vr0 && vr1 == NULL) - return compare_range_with_value (TREE_CODE (cond), vr0, op1); + return compare_range_with_value (TREE_CODE (cond), vr0, op1, + true); else if (vr0 == NULL && vr1) return compare_range_with_value ( - swap_tree_comparison (TREE_CODE (cond)), vr1, op0); + swap_tree_comparison (TREE_CODE (cond)), vr1, op0, + true); } } @@ -4252,17 +4569,18 @@ vrp_visit_phi_node (tree phi) other case to avoid infinite bouncing between different minimums. */ if (cmp_min > 0 || cmp_min < 0) - vr_result.min = TYPE_MIN_VALUE (TREE_TYPE (vr_result.min)); + vr_result.min = negative_infinity (TREE_TYPE (vr_result.min)); /* Similarly, if the new maximum is smaller or larger than the previous one, go all the way to +INF. */ if (cmp_max < 0 || cmp_max > 0) - vr_result.max = TYPE_MAX_VALUE (TREE_TYPE (vr_result.max)); + vr_result.max = positive_infinity (TREE_TYPE (vr_result.max)); /* If we ended up with a (-INF, +INF) range, set it to VARYING. */ - if (vr_result.min == TYPE_MIN_VALUE (TREE_TYPE (vr_result.min)) - && vr_result.max == TYPE_MAX_VALUE (TREE_TYPE (vr_result.max))) + if (vr_result.min == negative_infinity (TREE_TYPE (vr_result.min)) + && (vr_result.max + == positive_infinity (TREE_TYPE (vr_result.max)))) goto varying; } } @@ -4298,7 +4616,10 @@ simplify_div_or_mod_using_ranges (tree s } else { - val = compare_range_with_value (GT_EXPR, vr, integer_zero_node); + /* This simplification is reasonable to make even if the value + has overflowed and become negative, so we don't warn about + possible overflows. */ + val = compare_range_with_value (GT_EXPR, vr, integer_zero_node, false); } if (val && integer_onep (val)) @@ -4343,10 +4664,11 @@ simplify_abs_using_ranges (tree stmt, tr } else if (vr) { - val = compare_range_with_value (LE_EXPR, vr, integer_zero_node); + val = compare_range_with_value (LE_EXPR, vr, integer_zero_node, true); if (!val) { - val = compare_range_with_value (GE_EXPR, vr, integer_zero_node); + val = compare_range_with_value (GE_EXPR, vr, integer_zero_node, + true); if (val) { @@ -4390,10 +4712,10 @@ test_for_singularity (enum tree_code con the conditional as it was written. */ if (cond_code == LE_EXPR || cond_code == LT_EXPR) { - min = TYPE_MIN_VALUE (TREE_TYPE (op0)); + min = negative_infinity (TREE_TYPE (op0)); max = op1; - if (cond_code == LT_EXPR) + if (cond_code == LT_EXPR && !is_infinity (max)) { tree one = build_int_cst (TREE_TYPE (op0), 1); max = fold_build2 (MINUS_EXPR, TREE_TYPE (op0), max, one); @@ -4401,10 +4723,10 @@ test_for_singularity (enum tree_code con } else if (cond_code == GE_EXPR || cond_code == GT_EXPR) { - max = TYPE_MAX_VALUE (TREE_TYPE (op0)); + max = positive_infinity (TREE_TYPE (op0)); min = op1; - if (cond_code == GT_EXPR) + if (cond_code == GT_EXPR && !is_infinity (min)) { tree one = build_int_cst (TREE_TYPE (op0), 1); min = fold_build2 (PLUS_EXPR, TREE_TYPE (op0), min, one); @@ -4805,6 +5127,10 @@ vrp_finalize (void) static unsigned int execute_vrp (void) { + if (vrp_type_infinity_hash == NULL && !flag_wrapv) + vrp_type_infinity_hash = htab_create_ggc (10, tree_map_hash, tree_map_eq, + NULL); + insert_range_assertions (); loop_optimizer_init (LOOPS_NORMAL); @@ -4864,3 +5190,5 @@ struct tree_opt_pass pass_vrp = | TODO_update_smt_usage, /* todo_flags_finish */ 0 /* letter */ }; + +#include "gt-tree-vrp.h" Index: gcc/fold-const.c =================================================================== --- gcc/fold-const.c (revision 120274) +++ gcc/fold-const.c (working copy) @@ -3962,8 +3962,14 @@ make_range (tree exp, int *pin_p, tree * /* If flag_wrapv and ARG0_TYPE is signed, then we cannot move a constant to the other side. */ - if (flag_wrapv && !TYPE_UNSIGNED (arg0_type)) - break; + if (!TYPE_UNSIGNED (arg0_type)) + { + if (flag_wrapv) + break; + + /* We don't to check warn_warnv here: this won't + introduce signed overflow. */ + } /* If EXP is signed, any overflow in the computation is undefined, so we don't worry about it so long as our computations on @@ -4216,6 +4222,10 @@ build_range_check (tree type, tree exp, { tree utype, minv, maxv; + /* We don't need a warn_warnv warning here. This converts to an + unsigned type, which is implementation defined to be + safe. */ + /* Check if (unsigned) INT_MAX + 1 == (unsigned) INT_MIN for the type in question, as we rely on this here. */ utype = lang_hooks.types.unsigned_type (etype); @@ -5699,15 +5709,29 @@ extract_muldiv_1 (tree t, tree c, enum t && code != FLOOR_MOD_EXPR && code != ROUND_MOD_EXPR))) { if (integer_zerop (const_binop (TRUNC_MOD_EXPR, op1, c, 0))) - return fold_build2 (tcode, ctype, fold_convert (ctype, op0), - fold_convert (ctype, - const_binop (TRUNC_DIV_EXPR, - op1, c, 0))); + { + if (warn_warnv && !TYPE_UNSIGNED (ctype)) + warning (OPT_Warnv, + "assuming signed overflow is undefined when " + "cancelling constant through multiply or divide"); + + return fold_build2 (tcode, ctype, fold_convert (ctype, op0), + fold_convert (ctype, + const_binop (TRUNC_DIV_EXPR, + op1, c, 0))); + } else if (integer_zerop (const_binop (TRUNC_MOD_EXPR, c, op1, 0))) - return fold_build2 (code, ctype, fold_convert (ctype, op0), - fold_convert (ctype, - const_binop (TRUNC_DIV_EXPR, - c, op1, 0))); + { + if (warn_warnv && !TYPE_UNSIGNED (ctype)) + warning (OPT_Warnv, + "assuming signed overflow is undefined when " + "cancelling constant through multiply or divide"); + + return fold_build2 (code, ctype, fold_convert (ctype, op0), + fold_convert (ctype, + const_binop (TRUNC_DIV_EXPR, + c, op1, 0))); + } } break; @@ -7926,6 +7950,10 @@ maybe_canonicalize_comparison (enum tree || POINTER_TYPE_P (TREE_TYPE (arg0)))) return NULL_TREE; + /* We don't need to check warn_warnv here: this canonicalization can + not introduce any signed overflow which was not already + present. */ + /* Try canonicalization by simplifying arg0. */ t = maybe_canonicalize_comparison_1 (code, type, arg0, arg1); if (t) @@ -7934,7 +7962,11 @@ maybe_canonicalize_comparison (enum tree /* Try canonicalization by simplifying arg1 using the swapped comparison. */ code = swap_tree_comparison (code); - return maybe_canonicalize_comparison_1 (code, type, arg1, arg0); + t = maybe_canonicalize_comparison_1 (code, type, arg1, arg0); + if (t) + return t; + + return NULL_TREE; } /* Subroutine of fold_binary. This routine performs all of the @@ -7985,7 +8017,11 @@ fold_comparison (enum tree_code code, tr if (TREE_CODE (lhs) == TREE_CODE (arg1) && (TREE_CODE (lhs) != INTEGER_CST || !TREE_OVERFLOW (lhs))) - return fold_build2 (code, type, variable, lhs); + { + /* We don't need a warn_warnv warning here: this won't + introduce signed overflow which was not there before. */ + return fold_build2 (code, type, variable, lhs); + } } /* If this is a comparison of two exprs that look like an ARRAY_REF of the @@ -8049,20 +8085,30 @@ fold_comparison (enum tree_code code, tr const2, const1, 0); if (!TREE_OVERFLOW (cst) && tree_int_cst_compare (const2, cst) == tree_int_cst_sgn (const2)) - return fold_build2 (code, type, - variable1, - fold_build2 (TREE_CODE (arg1), TREE_TYPE (arg1), - variable2, cst)); + { + /* We don't need a warn_warnv warning here: this won't + introduce signed overflow which was not there before. */ + return fold_build2 (code, type, + variable1, + fold_build2 (TREE_CODE (arg1), TREE_TYPE (arg1), + variable2, cst)); + } cst = int_const_binop (TREE_CODE (arg0) == TREE_CODE (arg1) ? MINUS_EXPR : PLUS_EXPR, const1, const2, 0); if (!TREE_OVERFLOW (cst) && tree_int_cst_compare (const1, cst) == tree_int_cst_sgn (const1)) - return fold_build2 (code, type, - fold_build2 (TREE_CODE (arg0), TREE_TYPE (arg0), - variable1, cst), - variable2); + { + if (warn_warnv) + warning (OPT_Warnv, + "assuming signed overflow is undefined when " + "grouping constants in comparison"); + return fold_build2 (code, type, + fold_build2 (TREE_CODE (arg0), TREE_TYPE (arg0), + variable1, cst), + variable2); + } } tem = maybe_canonicalize_comparison (code, type, arg0, arg1); @@ -10128,13 +10174,25 @@ fold_binary (enum tree_code code, tree t if (!TYPE_UNSIGNED (type) && !flag_wrapv && TREE_CODE (arg0) == NEGATE_EXPR && negate_expr_p (arg1)) - return fold_build2 (code, type, TREE_OPERAND (arg0, 0), - negate_expr (arg1)); + { + if (warn_warnv) + warning (OPT_Warnv, + "assuming signed overflow is undefined when " + "distributing negation across division"); + return fold_build2 (code, type, TREE_OPERAND (arg0, 0), + negate_expr (arg1)); + } if (!TYPE_UNSIGNED (type) && !flag_wrapv && TREE_CODE (arg1) == NEGATE_EXPR && negate_expr_p (arg0)) - return fold_build2 (code, type, negate_expr (arg0), - TREE_OPERAND (arg1, 0)); + { + if (warn_warnv) + warning (OPT_Warnv, + "assuming signed overflow is undefined when " + "distributing negation across division"); + return fold_build2 (code, type, negate_expr (arg0), + TREE_OPERAND (arg1, 0)); + } /* If arg0 is a multiple of arg1, then rewrite to the fastest div operation, EXACT_DIV_EXPR. @@ -11013,27 +11071,59 @@ fold_binary (enum tree_code code, tree t if (code == GT_EXPR && ((code0 == MINUS_EXPR && is_positive >= 0) || (code0 == PLUS_EXPR && is_positive <= 0))) - return constant_boolean_node (0, type); + { + if (warn_warnv + && TREE_CODE (arg01) == INTEGER_CST + && !TYPE_UNSIGNED (TREE_TYPE (arg1))) + warning (OPT_Warnv, + "assuming signed overflow is undefined when " + "assuming that (X - c) > X is always false"); + return constant_boolean_node (0, type); + } /* Likewise (X + c) < X becomes false. */ if (code == LT_EXPR && ((code0 == PLUS_EXPR && is_positive >= 0) || (code0 == MINUS_EXPR && is_positive <= 0))) - return constant_boolean_node (0, type); + { + if (warn_warnv + && TREE_CODE (arg01) == INTEGER_CST + && !TYPE_UNSIGNED (TREE_TYPE (arg1))) + warning (OPT_Warnv, + "assuming signed overflow is undefined when " + "assuming that (X + c) < X is always false"); + return constant_boolean_node (0, type); + } /* Convert (X - c) <= X to true. */ if (!HONOR_NANS (TYPE_MODE (TREE_TYPE (arg1))) && code == LE_EXPR && ((code0 == MINUS_EXPR && is_positive >= 0) || (code0 == PLUS_EXPR && is_positive <= 0))) - return constant_boolean_node (1, type); + { + if (warn_warnv + && TREE_CODE (arg01) == INTEGER_CST + && !TYPE_UNSIGNED (TREE_TYPE (arg1))) + warning (OPT_Warnv, + "assuming signed overflow is undefined when " + "assuming that (X - c) <= X is always true"); + return constant_boolean_node (1, type); + } /* Convert (X + c) >= X to true. */ if (!HONOR_NANS (TYPE_MODE (TREE_TYPE (arg1))) && code == GE_EXPR && ((code0 == PLUS_EXPR && is_positive >= 0) || (code0 == MINUS_EXPR && is_positive <= 0))) - return constant_boolean_node (1, type); + { + if (warn_warnv + && TREE_CODE (arg01) == INTEGER_CST + && !TYPE_UNSIGNED (TREE_TYPE (arg1))) + warning (OPT_Warnv, + "assuming signed overflow is undefined when " + "assuming that (X + c) >= X is always true"); + return constant_boolean_node (1, type); + } if (TREE_CODE (arg01) == INTEGER_CST) { @@ -11041,23 +11131,47 @@ fold_binary (enum tree_code code, tree t if (code == GT_EXPR && ((code0 == PLUS_EXPR && is_positive > 0) || (code0 == MINUS_EXPR && is_positive < 0))) - return constant_boolean_node (1, type); + { + if (warn_warnv && !TYPE_UNSIGNED (TREE_TYPE (arg1))) + warning (OPT_Warnv, + "assuming signed overflow is undefined when " + "assuming that (X + c) > X is always true"); + return constant_boolean_node (1, type); + } if (code == LT_EXPR && ((code0 == MINUS_EXPR && is_positive > 0) || (code0 == PLUS_EXPR && is_positive < 0))) - return constant_boolean_node (1, type); + { + if (warn_warnv && !TYPE_UNSIGNED (TREE_TYPE (arg1))) + warning (OPT_Warnv, + "assuming signed overflow is undefined when " + "assuming that (X - c) < X is always true"); + return constant_boolean_node (1, type); + } /* Convert X + c <= X and X - c >= X to false for integers. */ if (code == LE_EXPR && ((code0 == PLUS_EXPR && is_positive > 0) || (code0 == MINUS_EXPR && is_positive < 0))) - return constant_boolean_node (0, type); + { + if (warn_warnv && !TYPE_UNSIGNED (TREE_TYPE (arg1))) + warning (OPT_Warnv, + "assuming signed overflow is undefined when " + "assuming that (X + c) <= X is always false"); + return constant_boolean_node (0, type); + } if (code == GE_EXPR && ((code0 == MINUS_EXPR && is_positive > 0) || (code0 == PLUS_EXPR && is_positive < 0))) - return constant_boolean_node (0, type); + { + if (warn_warnv && !TYPE_UNSIGNED (TREE_TYPE (arg1))) + warning (OPT_Warnv, + "assuming signed overflow is undefined when " + "assuming that (X - c) >= X is always false"); + return constant_boolean_node (0, type); + } } } @@ -12367,7 +12481,13 @@ tree_expr_nonnegative_p (tree t) /* We can't return 1 if flag_wrapv is set because ABS_EXPR = INT_MIN. */ if (!(flag_wrapv && INTEGRAL_TYPE_P (TREE_TYPE (t)))) - return true; + { + if (warn_warnv) + warning (OPT_Warnv, + "assuming signed overflow is undefined when " + "assuming that absolute value is always non-negative"); + return true; + } break; case INTEGER_CST: @@ -12684,17 +12804,24 @@ tree_expr_nonzero_p (tree t) || !tree_expr_nonnegative_p (TREE_OPERAND (t, 1))) return false; /* One of operands must be positive and the other non-negative. */ - return (tree_expr_nonzero_p (TREE_OPERAND (t, 0)) - || tree_expr_nonzero_p (TREE_OPERAND (t, 1))); + if (tree_expr_nonzero_p (TREE_OPERAND (t, 0)) + || tree_expr_nonzero_p (TREE_OPERAND (t, 1))) + { + /* We don't issue an OPT_Warnv warning here: even if + this value overflows, on a twos-complement machine + the sum of two positive numbers can never be + zero. */ + return true; + } } break; case MULT_EXPR: - if (!TYPE_UNSIGNED (type) && !flag_wrapv) - { - return (tree_expr_nonzero_p (TREE_OPERAND (t, 0)) - && tree_expr_nonzero_p (TREE_OPERAND (t, 1))); - } + /* For a signed type if !flag_wrapv, we used to assume that + multiplying two non-zero values gave a non-zero values. But + this is unlikely to be useful in practice, and it can break + incorrect code which tries to count the numbers of bits in an + int by using signed multiplication. */ break; case NOP_EXPR: Index: gcc/c-opts.c =================================================================== --- gcc/c-opts.c (revision 120274) +++ gcc/c-opts.c (working copy) @@ -396,6 +396,7 @@ c_common_handle_option (size_t scode, co warn_strict_aliasing = value; warn_string_literal_comparison = value; warn_always_true = value; + warn_warnv = value; /* Only warn about unknown pragmas that are not in system headers. */ Index: gcc/simplify-rtx.c =================================================================== --- gcc/simplify-rtx.c (revision 120274) +++ gcc/simplify-rtx.c (working copy) @@ -3944,7 +3944,13 @@ simplify_const_relational_operation (enu tem = GET_CODE (trueop0) == FLOAT_EXTEND ? XEXP (trueop0, 0) : trueop0; if (GET_CODE (tem) == ABS) - return const0_rtx; + { + if (warn_warnv && INTEGRAL_MODE_P (mode)) + warning (OPT_Warnv, + "assuming signed overflow is undefined when " + "assuming that abs (x) < 0 is false"); + return const0_rtx; + } } break; @@ -3957,7 +3963,13 @@ simplify_const_relational_operation (enu tem = GET_CODE (trueop0) == FLOAT_EXTEND ? XEXP (trueop0, 0) : trueop0; if (GET_CODE (tem) == ABS) - return const_true_rtx; + { + if (warn_warnv && INTEGRAL_MODE_P (mode)) + warning (OPT_Warnv, + "assuming signed overflow is undefined when " + "assuming that abs (x) >= 0 is true"); + return const_true_rtx; + } } break; Index: gcc/common.opt =================================================================== --- gcc/common.opt (revision 120274) +++ gcc/common.opt (working copy) @@ -61,6 +61,10 @@ Walways-true Common Var(warn_always_true) Warn about comparisons that always evaluate to true +Warnv +Common Var(warn_warnv) +Warn about optimizations that assume that signed overflow is undefined + Wattributes Common Var(warn_attributes) Init(1) Warn about inappropriate attribute usage Index: gcc/Makefile.in =================================================================== --- gcc/Makefile.in (revision 120274) +++ gcc/Makefile.in (working copy) @@ -1929,7 +1929,7 @@ tree-vn.o : tree-vn.c $(CONFIG_H) $(SYST tree-vrp.o : tree-vrp.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(TREE_H) \ $(TREE_FLOW_H) tree-pass.h $(TREE_DUMP_H) $(DIAGNOSTIC_H) $(GGC_H) \ $(BASIC_BLOCK_H) tree-ssa-propagate.h $(FLAGS_H) $(TREE_DUMP_H) \ - $(CFGLOOP_H) $(SCEV_H) tree-chrec.h $(TIMEVAR_H) + $(CFGLOOP_H) $(SCEV_H) tree-chrec.h $(TIMEVAR_H) gt-tree-vrp.h tree-cfg.o : tree-cfg.c $(TREE_FLOW_H) $(CONFIG_H) $(SYSTEM_H) \ $(RTL_H) $(TREE_H) $(TM_P_H) $(EXPR_H) $(GGC_H) $(FLAGS_H) output.h \ $(DIAGNOSTIC_H) $(FUNCTION_H) $(TIMEVAR_H) $(TM_H) coretypes.h \ @@ -2881,7 +2881,7 @@ GTFILES = $(srcdir)/input.h $(srcdir)/co $(srcdir)/tree-ssa-operands.h \ $(srcdir)/tree-profile.c $(srcdir)/tree-nested.c \ $(srcdir)/ipa-reference.c $(srcdir)/tree-ssa-structalias.h \ - $(srcdir)/tree-ssa-structalias.c \ + $(srcdir)/tree-ssa-structalias.c $(srcdir)/tree-vrp.c \ $(srcdir)/c-pragma.h $(srcdir)/omp-low.c $(srcdir)/varpool.c \ $(srcdir)/targhooks.c $(out_file) \ @all_gtfiles@ @@ -2914,7 +2914,7 @@ gt-tree-profile.h gt-tree-ssa-address.h gt-tree-iterator.h gt-gimplify.h \ gt-tree-phinodes.h gt-tree-nested.h \ gt-tree-ssa-propagate.h gt-varpool.h \ -gt-tree-ssa-structalias.h gt-ipa-inline.h \ +gt-tree-ssa-structalias.h gt-ipa-inline.h gt-tree-vrp.h \ gt-stringpool.h gt-targhooks.h gt-omp-low.h : s-gtype ; @true define echo_quoted_to_gtyp