diff options
author | Eric Botcazou <ebotcazou@adacore.com> | 2016-05-20 21:46:58 +0000 |
---|---|---|
committer | Eric Botcazou <ebotcazou@gcc.gnu.org> | 2016-05-20 21:46:58 +0000 |
commit | 55c8849f5d8ca231dba2e4ed2c40c4d435c84ae3 (patch) | |
tree | 0b4f1df898e1cc3a5d61e29748c1888ebaa51560 /gcc/tree-vrp.c | |
parent | aa6d7407f90130dfea5df768787ce5c46c87f07b (diff) | |
download | gcc-55c8849f5d8ca231dba2e4ed2c40c4d435c84ae3.zip gcc-55c8849f5d8ca231dba2e4ed2c40c4d435c84ae3.tar.gz gcc-55c8849f5d8ca231dba2e4ed2c40c4d435c84ae3.tar.bz2 |
tree-vrp.c (compare_values_warnv): Simplify handling of symbolic ranges by calling get_single_symbol and tidy up.
* tree-vrp.c (compare_values_warnv): Simplify handling of symbolic
ranges by calling get_single_symbol and tidy up. Look more closely
into NAME + CST1 vs CST2 comparisons if type overflow is undefined.
ada/
* gcc-interface/decl.c (gnat_to_gnu_entity) <E_Signed_Integer_Subtype>:
Make same-sized subtypes of signed base types signed.
* gcc-interface/utils.c (make_type_from_size): Adjust to above change.
(unchecked_convert): Likewise.
From-SVN: r236548
Diffstat (limited to 'gcc/tree-vrp.c')
-rw-r--r-- | gcc/tree-vrp.c | 164 |
1 files changed, 56 insertions, 108 deletions
diff --git a/gcc/tree-vrp.c b/gcc/tree-vrp.c index 92d889c..68f2e90 100644 --- a/gcc/tree-vrp.c +++ b/gcc/tree-vrp.c @@ -1187,129 +1187,77 @@ compare_values_warnv (tree val1, tree val2, bool *strict_overflow_p) val2 = fold_convert (TREE_TYPE (val1), val2); STRIP_USELESS_TYPE_CONVERSION (val2); - if ((TREE_CODE (val1) == SSA_NAME - || (TREE_CODE (val1) == NEGATE_EXPR - && TREE_CODE (TREE_OPERAND (val1, 0)) == SSA_NAME) - || TREE_CODE (val1) == PLUS_EXPR - || TREE_CODE (val1) == MINUS_EXPR) - && (TREE_CODE (val2) == SSA_NAME - || (TREE_CODE (val2) == NEGATE_EXPR - && TREE_CODE (TREE_OPERAND (val2, 0)) == SSA_NAME) - || TREE_CODE (val2) == PLUS_EXPR - || TREE_CODE (val2) == MINUS_EXPR)) - { - tree n1, c1, n2, c2; - enum tree_code code1, code2; - - /* If VAL1 and VAL2 are of the form '[-]NAME [+-] CST' or 'NAME', - return -1 or +1 accordingly. If VAL1 and VAL2 don't use the - same name, return -2. */ - if (TREE_CODE (val1) == SSA_NAME || TREE_CODE (val1) == NEGATE_EXPR) - { - code1 = SSA_NAME; - n1 = val1; - c1 = NULL_TREE; - } - else - { - code1 = TREE_CODE (val1); - n1 = TREE_OPERAND (val1, 0); - c1 = TREE_OPERAND (val1, 1); - if (tree_int_cst_sgn (c1) == -1) - { - if (is_negative_overflow_infinity (c1)) - return -2; - c1 = fold_unary_to_constant (NEGATE_EXPR, TREE_TYPE (c1), c1); - if (!c1) - return -2; - code1 = code1 == MINUS_EXPR ? PLUS_EXPR : MINUS_EXPR; - } - } - - if (TREE_CODE (val2) == SSA_NAME || TREE_CODE (val2) == NEGATE_EXPR) - { - code2 = SSA_NAME; - n2 = val2; - c2 = NULL_TREE; - } - else - { - code2 = TREE_CODE (val2); - n2 = TREE_OPERAND (val2, 0); - c2 = TREE_OPERAND (val2, 1); - if (tree_int_cst_sgn (c2) == -1) - { - if (is_negative_overflow_infinity (c2)) - return -2; - c2 = fold_unary_to_constant (NEGATE_EXPR, TREE_TYPE (c2), c2); - if (!c2) - return -2; - code2 = code2 == MINUS_EXPR ? PLUS_EXPR : MINUS_EXPR; - } - } - - /* Both values must use the same name. */ - if (TREE_CODE (n1) == NEGATE_EXPR && TREE_CODE (n2) == NEGATE_EXPR) - { - n1 = TREE_OPERAND (n1, 0); - n2 = TREE_OPERAND (n2, 0); - } - if (n1 != n2) + const bool overflow_undefined + = INTEGRAL_TYPE_P (TREE_TYPE (val1)) + && TYPE_OVERFLOW_UNDEFINED (TREE_TYPE (val1)); + tree inv1, inv2; + bool neg1, neg2; + tree sym1 = get_single_symbol (val1, &neg1, &inv1); + tree sym2 = get_single_symbol (val2, &neg2, &inv2); + + /* If VAL1 and VAL2 are of the form '[-]NAME [+ CST]', return -1 or +1 + accordingly. If VAL1 and VAL2 don't use the same name, return -2. */ + if (sym1 && sym2) + { + /* Both values must use the same name with the same sign. */ + if (sym1 != sym2 || neg1 != neg2) return -2; - if (code1 == SSA_NAME && code2 == SSA_NAME) - /* NAME == NAME */ + /* [-]NAME + CST == [-]NAME + CST. */ + if (inv1 == inv2) return 0; /* If overflow is defined we cannot simplify more. */ - if (!TYPE_OVERFLOW_UNDEFINED (TREE_TYPE (val1))) + if (!overflow_undefined) return -2; if (strict_overflow_p != NULL - && (code1 == SSA_NAME || !TREE_NO_WARNING (val1)) - && (code2 == SSA_NAME || !TREE_NO_WARNING (val2))) + && (!inv1 || !TREE_NO_WARNING (val1)) + && (!inv2 || !TREE_NO_WARNING (val2))) *strict_overflow_p = true; - if (code1 == SSA_NAME) - { - if (code2 == PLUS_EXPR) - /* NAME < NAME + CST */ - return -1; - else if (code2 == MINUS_EXPR) - /* NAME > NAME - CST */ - return 1; - } - else if (code1 == PLUS_EXPR) - { - if (code2 == SSA_NAME) - /* NAME + CST > NAME */ - return 1; - else if (code2 == PLUS_EXPR) - /* NAME + CST1 > NAME + CST2, if CST1 > CST2 */ - return compare_values_warnv (c1, c2, strict_overflow_p); - else if (code2 == MINUS_EXPR) - /* NAME + CST1 > NAME - CST2 */ - return 1; - } - else if (code1 == MINUS_EXPR) + if (!inv1) + inv1 = build_int_cst (TREE_TYPE (val1), 0); + if (!inv2) + inv2 = build_int_cst (TREE_TYPE (val2), 0); + + return compare_values_warnv (inv1, inv2, strict_overflow_p); + } + + const bool cst1 = is_gimple_min_invariant (val1); + const bool cst2 = is_gimple_min_invariant (val2); + + /* If one is of the form '[-]NAME + CST' and the other is constant, then + it might be possible to say something depending on the constants. */ + if ((sym1 && inv1 && cst2) || (sym2 && inv2 && cst1)) + { + if (!overflow_undefined) + return -2; + + if (strict_overflow_p != NULL + && (!sym1 || !TREE_NO_WARNING (val1)) + && (!sym2 || !TREE_NO_WARNING (val2))) + *strict_overflow_p = true; + + const signop sgn = TYPE_SIGN (TREE_TYPE (val1)); + tree cst = cst1 ? val1 : val2; + tree inv = cst1 ? inv2 : inv1; + + /* Compute the difference between the constants. If it overflows or + underflows, this means that we can trivially compare the NAME with + it and, consequently, the two values with each other. */ + wide_int diff = wi::sub (cst, inv); + if (wi::cmp (0, inv, sgn) != wi::cmp (diff, cst, sgn)) { - if (code2 == SSA_NAME) - /* NAME - CST < NAME */ - return -1; - else if (code2 == PLUS_EXPR) - /* NAME - CST1 < NAME + CST2 */ - return -1; - else if (code2 == MINUS_EXPR) - /* NAME - CST1 > NAME - CST2, if CST1 < CST2. Notice that - C1 and C2 are swapped in the call to compare_values. */ - return compare_values_warnv (c2, c1, strict_overflow_p); + const int res = wi::cmp (cst, inv, sgn); + return cst1 ? res : -res; } - gcc_unreachable (); + return -2; } - /* We cannot compare non-constants. */ - if (!is_gimple_min_invariant (val1) || !is_gimple_min_invariant (val2)) + /* We cannot say anything more for non-constants. */ + if (!cst1 || !cst2) return -2; if (!POINTER_TYPE_P (TREE_TYPE (val1))) |