aboutsummaryrefslogtreecommitdiff
path: root/gcc/tree-vrp.c
diff options
context:
space:
mode:
authorEric Botcazou <ebotcazou@adacore.com>2016-05-20 21:46:58 +0000
committerEric Botcazou <ebotcazou@gcc.gnu.org>2016-05-20 21:46:58 +0000
commit55c8849f5d8ca231dba2e4ed2c40c4d435c84ae3 (patch)
tree0b4f1df898e1cc3a5d61e29748c1888ebaa51560 /gcc/tree-vrp.c
parentaa6d7407f90130dfea5df768787ce5c46c87f07b (diff)
downloadgcc-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.c164
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)))