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
This commit is contained in:
Eric Botcazou 2016-05-20 21:46:58 +00:00 committed by Eric Botcazou
parent aa6d7407f9
commit 55c8849f5d
8 changed files with 122 additions and 114 deletions

View File

@ -1,3 +1,9 @@
2016-05-20 Eric Botcazou <ebotcazou@adacore.com>
* 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.
2016-05-20 Jeff Law <law@redhat.com> 2016-05-20 Jeff Law <law@redhat.com>
* bitmap.c (bitmap_find_bit): Remove useless test. * bitmap.c (bitmap_find_bit): Remove useless test.

View File

@ -1,3 +1,10 @@
2016-05-20 Eric Botcazou <ebotcazou@adacore.com>
* 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.
2016-05-16 Eric Botcazou <ebotcazou@adacore.com> 2016-05-16 Eric Botcazou <ebotcazou@adacore.com>
* gcc-interface/decl.c (gnat_to_gnu_entity) <E_Variable>: Do not build * gcc-interface/decl.c (gnat_to_gnu_entity) <E_Variable>: Do not build

View File

@ -1814,7 +1814,12 @@ gnat_to_gnu_entity (Entity_Id gnat_entity, tree gnu_expr, bool definition)
/* First subtypes of Character are treated as Character; otherwise /* First subtypes of Character are treated as Character; otherwise
this should be an unsigned type if the base type is unsigned or this should be an unsigned type if the base type is unsigned or
if the lower bound is constant and non-negative or if the type if the lower bound is constant and non-negative or if the type
is biased. */ is biased. However, even if the lower bound is constant and
non-negative, we use a signed type for a subtype with the same
size as its signed base type, because this eliminates useless
conversions to it and gives more leeway to the optimizer; but
this means that we will need to explicitly test for this case
when we change the representation based on the RM size. */
if (kind == E_Enumeration_Subtype if (kind == E_Enumeration_Subtype
&& No (First_Literal (Etype (gnat_entity))) && No (First_Literal (Etype (gnat_entity)))
&& Esize (gnat_entity) == RM_Size (gnat_entity) && Esize (gnat_entity) == RM_Size (gnat_entity)
@ -1822,7 +1827,8 @@ gnat_to_gnu_entity (Entity_Id gnat_entity, tree gnu_expr, bool definition)
&& flag_signed_char) && flag_signed_char)
gnu_type = make_signed_type (CHAR_TYPE_SIZE); gnu_type = make_signed_type (CHAR_TYPE_SIZE);
else if (Is_Unsigned_Type (Etype (gnat_entity)) else if (Is_Unsigned_Type (Etype (gnat_entity))
|| Is_Unsigned_Type (gnat_entity) || (Esize (Etype (gnat_entity)) != Esize (gnat_entity)
&& Is_Unsigned_Type (gnat_entity))
|| Has_Biased_Representation (gnat_entity)) || Has_Biased_Representation (gnat_entity))
gnu_type = make_unsigned_type (esize); gnu_type = make_unsigned_type (esize);
else else

View File

@ -1116,7 +1116,14 @@ make_type_from_size (tree type, tree size_tree, bool for_biased)
break; break;
biased_p |= for_biased; biased_p |= for_biased;
if (TYPE_UNSIGNED (type) || biased_p)
/* The type should be an unsigned type if the original type is unsigned
or if the lower bound is constant and non-negative or if the type is
biased, see E_Signed_Integer_Subtype case of gnat_to_gnu_entity. */
if (TYPE_UNSIGNED (type)
|| (TREE_CODE (TYPE_MIN_VALUE (type)) == INTEGER_CST
&& tree_int_cst_sgn (TYPE_MIN_VALUE (type)) >= 0)
|| biased_p)
new_type = make_unsigned_type (size); new_type = make_unsigned_type (size);
else else
new_type = make_signed_type (size); new_type = make_signed_type (size);
@ -5111,7 +5118,9 @@ unchecked_convert (tree type, tree expr, bool notrunc_p)
/* If the result is an integral type whose precision is not equal to its /* If the result is an integral type whose precision is not equal to its
size, sign- or zero-extend the result. We need not do this if the input size, sign- or zero-extend the result. We need not do this if the input
is an integral type of the same precision and signedness or if the output is an integral type of the same precision and signedness or if the output
is a biased type or if both the input and output are unsigned. */ is a biased type or if both the input and output are unsigned, or if the
lower bound is constant and non-negative, see E_Signed_Integer_Subtype
case of gnat_to_gnu_entity. */
if (!notrunc_p if (!notrunc_p
&& INTEGRAL_TYPE_P (type) && INTEGRAL_TYPE_P (type)
&& TYPE_RM_SIZE (type) && TYPE_RM_SIZE (type)
@ -5123,7 +5132,10 @@ unchecked_convert (tree type, tree expr, bool notrunc_p)
? TYPE_RM_SIZE (etype) ? TYPE_RM_SIZE (etype)
: TYPE_SIZE (etype)) == 0) : TYPE_SIZE (etype)) == 0)
&& !(code == INTEGER_TYPE && TYPE_BIASED_REPRESENTATION_P (type)) && !(code == INTEGER_TYPE && TYPE_BIASED_REPRESENTATION_P (type))
&& !(TYPE_UNSIGNED (type) && TYPE_UNSIGNED (etype))) && !((TYPE_UNSIGNED (type)
|| (TREE_CODE (TYPE_MIN_VALUE (type)) == INTEGER_CST
&& tree_int_cst_sgn (TYPE_MIN_VALUE (type)) >= 0))
&& TYPE_UNSIGNED (etype)))
{ {
tree base_type tree base_type
= gnat_type_for_size (TREE_INT_CST_LOW (TYPE_SIZE (type)), = gnat_type_for_size (TREE_INT_CST_LOW (TYPE_SIZE (type)),

View File

@ -1,3 +1,8 @@
2016-05-20 Eric Botcazou <ebotcazou@adacore.com>
* gnat.dg/opt53.adb: New test.
* gnat.dg/opt54.adb: Likewise.
2016-05-20 Martin Jambor <mjambor@suse.cz> 2016-05-20 Martin Jambor <mjambor@suse.cz>
PR tree-optimization/70884 PR tree-optimization/70884

View File

@ -0,0 +1,12 @@
-- { dg-do compile }
-- { dg-options "-O2 -fdump-tree-optimized" }
function Opt53 (Val, Max : Positive) return Positive is
begin
if Val >= Max then
return Max;
end if;
return Val + 1;
end;
-- { dg-final { scan-tree-dump-not "gnat_rcheck" "optimized" } }

View File

@ -0,0 +1,12 @@
-- { dg-do compile }
-- { dg-options "-O2 -fdump-tree-optimized" }
function Opt54 (Val, Max : Integer) return Integer is
begin
if Val >= Max then
return Max;
end if;
return Val + 1;
end;
-- { dg-final { scan-tree-dump-not "gnat_rcheck" "optimized" } }

View File

@ -1187,129 +1187,77 @@ compare_values_warnv (tree val1, tree val2, bool *strict_overflow_p)
val2 = fold_convert (TREE_TYPE (val1), val2); val2 = fold_convert (TREE_TYPE (val1), val2);
STRIP_USELESS_TYPE_CONVERSION (val2); STRIP_USELESS_TYPE_CONVERSION (val2);
if ((TREE_CODE (val1) == SSA_NAME const bool overflow_undefined
|| (TREE_CODE (val1) == NEGATE_EXPR = INTEGRAL_TYPE_P (TREE_TYPE (val1))
&& TREE_CODE (TREE_OPERAND (val1, 0)) == SSA_NAME) && TYPE_OVERFLOW_UNDEFINED (TREE_TYPE (val1));
|| TREE_CODE (val1) == PLUS_EXPR tree inv1, inv2;
|| TREE_CODE (val1) == MINUS_EXPR) bool neg1, neg2;
&& (TREE_CODE (val2) == SSA_NAME tree sym1 = get_single_symbol (val1, &neg1, &inv1);
|| (TREE_CODE (val2) == NEGATE_EXPR tree sym2 = get_single_symbol (val2, &neg2, &inv2);
&& TREE_CODE (TREE_OPERAND (val2, 0)) == SSA_NAME)
|| TREE_CODE (val2) == PLUS_EXPR /* If VAL1 and VAL2 are of the form '[-]NAME [+ CST]', return -1 or +1
|| TREE_CODE (val2) == MINUS_EXPR)) accordingly. If VAL1 and VAL2 don't use the same name, return -2. */
if (sym1 && sym2)
{ {
tree n1, c1, n2, c2; /* Both values must use the same name with the same sign. */
enum tree_code code1, code2; if (sym1 != sym2 || neg1 != neg2)
/* 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)
return -2; return -2;
if (code1 == SSA_NAME && code2 == SSA_NAME) /* [-]NAME + CST == [-]NAME + CST. */
/* NAME == NAME */ if (inv1 == inv2)
return 0; return 0;
/* If overflow is defined we cannot simplify more. */ /* If overflow is defined we cannot simplify more. */
if (!TYPE_OVERFLOW_UNDEFINED (TREE_TYPE (val1))) if (!overflow_undefined)
return -2; return -2;
if (strict_overflow_p != NULL if (strict_overflow_p != NULL
&& (code1 == SSA_NAME || !TREE_NO_WARNING (val1)) && (!inv1 || !TREE_NO_WARNING (val1))
&& (code2 == SSA_NAME || !TREE_NO_WARNING (val2))) && (!inv2 || !TREE_NO_WARNING (val2)))
*strict_overflow_p = true; *strict_overflow_p = true;
if (code1 == SSA_NAME) if (!inv1)
{ inv1 = build_int_cst (TREE_TYPE (val1), 0);
if (code2 == PLUS_EXPR) if (!inv2)
/* NAME < NAME + CST */ inv2 = build_int_cst (TREE_TYPE (val2), 0);
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 (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);
}
gcc_unreachable (); return compare_values_warnv (inv1, inv2, strict_overflow_p);
} }
/* We cannot compare non-constants. */ const bool cst1 = is_gimple_min_invariant (val1);
if (!is_gimple_min_invariant (val1) || !is_gimple_min_invariant (val2)) 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))
{
const int res = wi::cmp (cst, inv, sgn);
return cst1 ? res : -res;
}
return -2;
}
/* We cannot say anything more for non-constants. */
if (!cst1 || !cst2)
return -2; return -2;
if (!POINTER_TYPE_P (TREE_TYPE (val1))) if (!POINTER_TYPE_P (TREE_TYPE (val1)))