X+Y < X iff Y<0 moved to match.pd

2017-10-11  Marc Glisse  <marc.glisse@inria.fr>

gcc/
	* fold-const.c (fold_binary_loc) [X +- Y CMP X]: Move ...
	* match.pd: ... here.
	((T) X == (T) Y): Relax condition.

gcc/testsuite/
	* gcc.dg/Wstrict-overflow-7.c: Xfail.
	* gcc.dg/pragma-diag-3.c: Likewise.

From-SVN: r253642
This commit is contained in:
Marc Glisse 2017-10-11 15:18:06 +02:00 committed by Marc Glisse
parent b4ec1d31a5
commit 6358a676c3
6 changed files with 62 additions and 138 deletions

View File

@ -1,3 +1,9 @@
2017-10-11 Marc Glisse <marc.glisse@inria.fr>
* fold-const.c (fold_binary_loc) [X +- Y CMP X]: Move ...
* match.pd: ... here.
((T) X == (T) Y): Relax condition.
2017-10-11 Bin Cheng <bin.cheng@arm.com>
PR tree-optimization/82472

View File

@ -10502,40 +10502,6 @@ fold_binary_loc (location_t loc,
&& code == NE_EXPR)
return non_lvalue_loc (loc, fold_convert_loc (loc, type, arg0));
/* Transform comparisons of the form X +- Y CMP X to Y CMP 0. */
if ((TREE_CODE (arg0) == PLUS_EXPR
|| TREE_CODE (arg0) == POINTER_PLUS_EXPR
|| TREE_CODE (arg0) == MINUS_EXPR)
&& operand_equal_p (tree_strip_nop_conversions (TREE_OPERAND (arg0,
0)),
arg1, 0)
&& (INTEGRAL_TYPE_P (TREE_TYPE (arg0))
|| POINTER_TYPE_P (TREE_TYPE (arg0))))
{
tree val = TREE_OPERAND (arg0, 1);
val = fold_build2_loc (loc, code, type, val,
build_int_cst (TREE_TYPE (val), 0));
return omit_two_operands_loc (loc, type, val,
TREE_OPERAND (arg0, 0), arg1);
}
/* Transform comparisons of the form X CMP X +- Y to Y CMP 0. */
if ((TREE_CODE (arg1) == PLUS_EXPR
|| TREE_CODE (arg1) == POINTER_PLUS_EXPR
|| TREE_CODE (arg1) == MINUS_EXPR)
&& operand_equal_p (tree_strip_nop_conversions (TREE_OPERAND (arg1,
0)),
arg0, 0)
&& (INTEGRAL_TYPE_P (TREE_TYPE (arg1))
|| POINTER_TYPE_P (TREE_TYPE (arg1))))
{
tree val = TREE_OPERAND (arg1, 1);
val = fold_build2_loc (loc, code, type, val,
build_int_cst (TREE_TYPE (val), 0));
return omit_two_operands_loc (loc, type, val,
TREE_OPERAND (arg1, 0), arg0);
}
/* If this is an EQ or NE comparison with zero and ARG0 is
(1 << foo) & bar, convert it to (bar >> foo) & 1. Both require
two operations, but the latter can be done in one less insn
@ -10918,130 +10884,38 @@ fold_binary_loc (location_t loc,
/* Transform comparisons of the form X +- C CMP X. */
if ((TREE_CODE (arg0) == PLUS_EXPR || TREE_CODE (arg0) == MINUS_EXPR)
&& operand_equal_p (TREE_OPERAND (arg0, 0), arg1, 0)
&& ((TREE_CODE (TREE_OPERAND (arg0, 1)) == REAL_CST
&& !HONOR_SNANS (arg0))
|| (TREE_CODE (TREE_OPERAND (arg0, 1)) == INTEGER_CST
&& TYPE_OVERFLOW_UNDEFINED (TREE_TYPE (arg1)))))
&& TREE_CODE (TREE_OPERAND (arg0, 1)) == REAL_CST
&& !HONOR_SNANS (arg0))
{
tree arg01 = TREE_OPERAND (arg0, 1);
enum tree_code code0 = TREE_CODE (arg0);
int is_positive;
if (TREE_CODE (arg01) == REAL_CST)
is_positive = REAL_VALUE_NEGATIVE (TREE_REAL_CST (arg01)) ? -1 : 1;
else
is_positive = tree_int_cst_sgn (arg01);
int is_positive = REAL_VALUE_NEGATIVE (TREE_REAL_CST (arg01)) ? -1 : 1;
/* (X - c) > X becomes false. */
if (code == GT_EXPR
&& ((code0 == MINUS_EXPR && is_positive >= 0)
|| (code0 == PLUS_EXPR && is_positive <= 0)))
{
if (TREE_CODE (arg01) == INTEGER_CST
&& TYPE_OVERFLOW_UNDEFINED (TREE_TYPE (arg1)))
fold_overflow_warning (("assuming signed overflow does not "
"occur when assuming that (X - c) > X "
"is always false"),
WARN_STRICT_OVERFLOW_ALL);
return constant_boolean_node (0, type);
}
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)))
{
if (TREE_CODE (arg01) == INTEGER_CST
&& TYPE_OVERFLOW_UNDEFINED (TREE_TYPE (arg1)))
fold_overflow_warning (("assuming signed overflow does not "
"occur when assuming that "
"(X + c) < X is always false"),
WARN_STRICT_OVERFLOW_ALL);
return constant_boolean_node (0, type);
}
return constant_boolean_node (0, type);
/* Convert (X - c) <= X to true. */
if (!HONOR_NANS (arg1)
&& code == LE_EXPR
&& ((code0 == MINUS_EXPR && is_positive >= 0)
|| (code0 == PLUS_EXPR && is_positive <= 0)))
{
if (TREE_CODE (arg01) == INTEGER_CST
&& TYPE_OVERFLOW_UNDEFINED (TREE_TYPE (arg1)))
fold_overflow_warning (("assuming signed overflow does not "
"occur when assuming that "
"(X - c) <= X is always true"),
WARN_STRICT_OVERFLOW_ALL);
return constant_boolean_node (1, type);
}
return constant_boolean_node (1, type);
/* Convert (X + c) >= X to true. */
if (!HONOR_NANS (arg1)
&& code == GE_EXPR
&& ((code0 == PLUS_EXPR && is_positive >= 0)
|| (code0 == MINUS_EXPR && is_positive <= 0)))
{
if (TREE_CODE (arg01) == INTEGER_CST
&& TYPE_OVERFLOW_UNDEFINED (TREE_TYPE (arg1)))
fold_overflow_warning (("assuming signed overflow does not "
"occur when assuming that "
"(X + c) >= X is always true"),
WARN_STRICT_OVERFLOW_ALL);
return constant_boolean_node (1, type);
}
if (TREE_CODE (arg01) == INTEGER_CST)
{
/* Convert X + c > X and X - c < X to true for integers. */
if (code == GT_EXPR
&& ((code0 == PLUS_EXPR && is_positive > 0)
|| (code0 == MINUS_EXPR && is_positive < 0)))
{
if (TYPE_OVERFLOW_UNDEFINED (TREE_TYPE (arg1)))
fold_overflow_warning (("assuming signed overflow does "
"not occur when assuming that "
"(X + c) > X is always true"),
WARN_STRICT_OVERFLOW_ALL);
return constant_boolean_node (1, type);
}
if (code == LT_EXPR
&& ((code0 == MINUS_EXPR && is_positive > 0)
|| (code0 == PLUS_EXPR && is_positive < 0)))
{
if (TYPE_OVERFLOW_UNDEFINED (TREE_TYPE (arg1)))
fold_overflow_warning (("assuming signed overflow does "
"not occur when assuming that "
"(X - c) < X is always true"),
WARN_STRICT_OVERFLOW_ALL);
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)))
{
if (TYPE_OVERFLOW_UNDEFINED (TREE_TYPE (arg1)))
fold_overflow_warning (("assuming signed overflow does "
"not occur when assuming that "
"(X + c) <= X is always false"),
WARN_STRICT_OVERFLOW_ALL);
return constant_boolean_node (0, type);
}
if (code == GE_EXPR
&& ((code0 == MINUS_EXPR && is_positive > 0)
|| (code0 == PLUS_EXPR && is_positive < 0)))
{
if (TYPE_OVERFLOW_UNDEFINED (TREE_TYPE (arg1)))
fold_overflow_warning (("assuming signed overflow does "
"not occur when assuming that "
"(X - c) >= X is always false"),
WARN_STRICT_OVERFLOW_ALL);
return constant_boolean_node (0, type);
}
}
return constant_boolean_node (1, type);
}
/* If we are comparing an ABS_EXPR with a constant, we can

View File

@ -1280,6 +1280,44 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
|| TYPE_OVERFLOW_WRAPS (TREE_TYPE (@0))))
(op @1 @0))))
/* X + Y < Y is the same as X < 0 when there is no overflow. */
(for op (lt le gt ge)
(simplify
(op:c (plus:c@2 @0 @1) @1)
(if (ANY_INTEGRAL_TYPE_P (TREE_TYPE (@0))
&& TYPE_OVERFLOW_UNDEFINED (TREE_TYPE (@0))
&& (CONSTANT_CLASS_P (@0) || single_use (@2)))
(op @0 { build_zero_cst (TREE_TYPE (@0)); }))))
/* For equality, this is also true with wrapping overflow. */
(for op (eq ne)
(simplify
(op:c (nop_convert@3 (plus:c@2 @0 (convert1? @1))) (convert2? @1))
(if (ANY_INTEGRAL_TYPE_P (TREE_TYPE (@0))
&& (TYPE_OVERFLOW_UNDEFINED (TREE_TYPE (@0))
|| TYPE_OVERFLOW_WRAPS (TREE_TYPE (@0)))
&& (CONSTANT_CLASS_P (@0) || (single_use (@2) && single_use (@3)))
&& tree_nop_conversion_p (TREE_TYPE (@3), TREE_TYPE (@2))
&& tree_nop_conversion_p (TREE_TYPE (@3), TREE_TYPE (@1)))
(op @0 { build_zero_cst (TREE_TYPE (@0)); })))
(simplify
(op:c (nop_convert@3 (pointer_plus@2 (convert1? @0) @1)) (convert2? @0))
(if (tree_nop_conversion_p (TREE_TYPE (@2), TREE_TYPE (@0))
&& tree_nop_conversion_p (TREE_TYPE (@3), TREE_TYPE (@0))
&& (CONSTANT_CLASS_P (@1) || (single_use (@2) && single_use (@3))))
(op @1 { build_zero_cst (TREE_TYPE (@1)); }))))
/* X - Y < X is the same as Y > 0 when there is no overflow.
For equality, this is also true with wrapping overflow. */
(for op (simple_comparison)
(simplify
(op:c @0 (minus@2 @0 @1))
(if (ANY_INTEGRAL_TYPE_P (TREE_TYPE (@0))
&& (TYPE_OVERFLOW_UNDEFINED (TREE_TYPE (@0))
|| ((op == EQ_EXPR || op == NE_EXPR)
&& TYPE_OVERFLOW_WRAPS (TREE_TYPE (@0))))
&& (CONSTANT_CLASS_P (@1) || single_use (@2)))
(op @1 { build_zero_cst (TREE_TYPE (@1)); }))))
/* Transform:
* (X / Y) == 0 -> X < Y if X, Y are unsigned.
* (X / Y) != 0 -> X >= Y, if X, Y are unsigned.
@ -3125,7 +3163,8 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
(op (abs @0) zerop@1)
(op @0 @1)))
/* From fold_sign_changed_comparison and fold_widened_comparison. */
/* From fold_sign_changed_comparison and fold_widened_comparison.
FIXME: the lack of symmetry is disturbing. */
(for cmp (simple_comparison)
(simplify
(cmp (convert@0 @00) (convert?@1 @10))
@ -3138,11 +3177,11 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
&& single_use (@0))
(if (TYPE_PRECISION (TREE_TYPE (@00)) == TYPE_PRECISION (TREE_TYPE (@0))
&& (TREE_CODE (@10) == INTEGER_CST
|| (@1 != @10 && types_match (TREE_TYPE (@10), TREE_TYPE (@00))))
|| @1 != @10)
&& (TYPE_UNSIGNED (TREE_TYPE (@00)) == TYPE_UNSIGNED (TREE_TYPE (@0))
|| cmp == NE_EXPR
|| cmp == EQ_EXPR)
&& (POINTER_TYPE_P (TREE_TYPE (@00)) == POINTER_TYPE_P (TREE_TYPE (@0))))
&& !POINTER_TYPE_P (TREE_TYPE (@00)))
/* ??? The special-casing of INTEGER_CST conversion was in the original
code and here to avoid a spurious overflow flag on the resulting
constant which fold_convert produces. */

View File

@ -1,3 +1,8 @@
2017-10-11 Marc Glisse <marc.glisse@inria.fr>
* gcc.dg/Wstrict-overflow-7.c: Xfail.
* gcc.dg/pragma-diag-3.c: Likewise.
2017-10-11 Bin Cheng <bin.cheng@arm.com>
PR tree-optimization/82472

View File

@ -6,5 +6,5 @@
int
foo (int i)
{
return i + 10 > i; /* { dg-warning "assuming signed overflow does not occur" "correct warning" } */
return i + 10 > i; /* { dg-warning "assuming signed overflow does not occur" "correct warning" { xfail *-*-* } } */
}

View File

@ -15,7 +15,7 @@ void testing2() {
void testing3() {
int k = 4;
k + 4 < k; /* { dg-error "overflow" } */
k + 4 < k; /* { dg-error "overflow" "" { xfail *-*-* } } */
}
int bar()