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:
parent
b4ec1d31a5
commit
6358a676c3
@ -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
|
||||
|
140
gcc/fold-const.c
140
gcc/fold-const.c
@ -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
|
||||
|
45
gcc/match.pd
45
gcc/match.pd
@ -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. */
|
||||
|
@ -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
|
||||
|
@ -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 *-*-* } } */
|
||||
}
|
||||
|
@ -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()
|
||||
|
Loading…
x
Reference in New Issue
Block a user