Commit 6358a676 by Marc Glisse Committed by Marc Glisse

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
parent b4ec1d31
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> 2017-10-11 Bin Cheng <bin.cheng@arm.com>
PR tree-optimization/82472 PR tree-optimization/82472
...@@ -10502,40 +10502,6 @@ fold_binary_loc (location_t loc, ...@@ -10502,40 +10502,6 @@ fold_binary_loc (location_t loc,
&& code == NE_EXPR) && code == NE_EXPR)
return non_lvalue_loc (loc, fold_convert_loc (loc, type, arg0)); 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 /* If this is an EQ or NE comparison with zero and ARG0 is
(1 << foo) & bar, convert it to (bar >> foo) & 1. Both require (1 << foo) & bar, convert it to (bar >> foo) & 1. Both require
two operations, but the latter can be done in one less insn two operations, but the latter can be done in one less insn
...@@ -10918,132 +10884,40 @@ fold_binary_loc (location_t loc, ...@@ -10918,132 +10884,40 @@ fold_binary_loc (location_t loc,
/* Transform comparisons of the form X +- C CMP X. */ /* Transform comparisons of the form X +- C CMP X. */
if ((TREE_CODE (arg0) == PLUS_EXPR || TREE_CODE (arg0) == MINUS_EXPR) if ((TREE_CODE (arg0) == PLUS_EXPR || TREE_CODE (arg0) == MINUS_EXPR)
&& operand_equal_p (TREE_OPERAND (arg0, 0), arg1, 0) && operand_equal_p (TREE_OPERAND (arg0, 0), arg1, 0)
&& ((TREE_CODE (TREE_OPERAND (arg0, 1)) == REAL_CST && TREE_CODE (TREE_OPERAND (arg0, 1)) == REAL_CST
&& !HONOR_SNANS (arg0)) && !HONOR_SNANS (arg0))
|| (TREE_CODE (TREE_OPERAND (arg0, 1)) == INTEGER_CST
&& TYPE_OVERFLOW_UNDEFINED (TREE_TYPE (arg1)))))
{ {
tree arg01 = TREE_OPERAND (arg0, 1); tree arg01 = TREE_OPERAND (arg0, 1);
enum tree_code code0 = TREE_CODE (arg0); enum tree_code code0 = TREE_CODE (arg0);
int is_positive; int is_positive = REAL_VALUE_NEGATIVE (TREE_REAL_CST (arg01)) ? -1 : 1;
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);
/* (X - c) > X becomes false. */ /* (X - c) > X becomes false. */
if (code == GT_EXPR if (code == GT_EXPR
&& ((code0 == MINUS_EXPR && is_positive >= 0) && ((code0 == MINUS_EXPR && is_positive >= 0)
|| (code0 == PLUS_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. */ /* Likewise (X + c) < X becomes false. */
if (code == LT_EXPR if (code == LT_EXPR
&& ((code0 == PLUS_EXPR && is_positive >= 0) && ((code0 == PLUS_EXPR && is_positive >= 0)
|| (code0 == MINUS_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. */ /* Convert (X - c) <= X to true. */
if (!HONOR_NANS (arg1) if (!HONOR_NANS (arg1)
&& code == LE_EXPR && code == LE_EXPR
&& ((code0 == MINUS_EXPR && is_positive >= 0) && ((code0 == MINUS_EXPR && is_positive >= 0)
|| (code0 == PLUS_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. */ /* Convert (X + c) >= X to true. */
if (!HONOR_NANS (arg1) if (!HONOR_NANS (arg1)
&& code == GE_EXPR && code == GE_EXPR
&& ((code0 == PLUS_EXPR && is_positive >= 0) && ((code0 == PLUS_EXPR && is_positive >= 0)
|| (code0 == MINUS_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); 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);
}
}
}
/* If we are comparing an ABS_EXPR with a constant, we can /* If we are comparing an ABS_EXPR with a constant, we can
convert all the cases into explicit comparisons, but they may convert all the cases into explicit comparisons, but they may
well not be faster than doing the ABS and one comparison. well not be faster than doing the ABS and one comparison.
......
...@@ -1280,6 +1280,44 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT) ...@@ -1280,6 +1280,44 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
|| TYPE_OVERFLOW_WRAPS (TREE_TYPE (@0)))) || TYPE_OVERFLOW_WRAPS (TREE_TYPE (@0))))
(op @1 @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: /* Transform:
* (X / Y) == 0 -> X < Y if X, Y are unsigned. * (X / Y) == 0 -> X < Y if X, Y are unsigned.
* (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) ...@@ -3125,7 +3163,8 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
(op (abs @0) zerop@1) (op (abs @0) zerop@1)
(op @0 @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) (for cmp (simple_comparison)
(simplify (simplify
(cmp (convert@0 @00) (convert?@1 @10)) (cmp (convert@0 @00) (convert?@1 @10))
...@@ -3138,11 +3177,11 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT) ...@@ -3138,11 +3177,11 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
&& single_use (@0)) && single_use (@0))
(if (TYPE_PRECISION (TREE_TYPE (@00)) == TYPE_PRECISION (TREE_TYPE (@0)) (if (TYPE_PRECISION (TREE_TYPE (@00)) == TYPE_PRECISION (TREE_TYPE (@0))
&& (TREE_CODE (@10) == INTEGER_CST && (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)) && (TYPE_UNSIGNED (TREE_TYPE (@00)) == TYPE_UNSIGNED (TREE_TYPE (@0))
|| cmp == NE_EXPR || cmp == NE_EXPR
|| cmp == EQ_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 /* ??? The special-casing of INTEGER_CST conversion was in the original
code and here to avoid a spurious overflow flag on the resulting code and here to avoid a spurious overflow flag on the resulting
constant which fold_convert produces. */ constant which fold_convert produces. */
......
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> 2017-10-11 Bin Cheng <bin.cheng@arm.com>
PR tree-optimization/82472 PR tree-optimization/82472
......
...@@ -6,5 +6,5 @@ ...@@ -6,5 +6,5 @@
int int
foo (int i) 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 *-*-* } } */
} }
...@@ -15,7 +15,7 @@ void testing2() { ...@@ -15,7 +15,7 @@ void testing2() {
void testing3() { void testing3() {
int k = 4; int k = 4;
k + 4 < k; /* { dg-error "overflow" } */ k + 4 < k; /* { dg-error "overflow" "" { xfail *-*-* } } */
} }
int bar() int bar()
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment