match.pd: unsigned A - B > A --> A < B
2016-04-27 Marc Glisse <marc.glisse@inria.fr> gcc/ * match.pd (A - B > A, A + B < A): New transformations. gcc/testsuite/ * gcc.dg/tree-ssa/overflow-2.c: New testcase. * gcc.dg/tree-ssa/minus-ovf.c: Likewise. From-SVN: r235537
This commit is contained in:
parent
044a73da40
commit
3563f78f97
|
@ -1,3 +1,7 @@
|
|||
2016-04-27 Marc Glisse <marc.glisse@inria.fr>
|
||||
|
||||
* match.pd (A - B > A, A + B < A): New transformations.
|
||||
|
||||
2016-04-27 Patrick Palka <ppalka@gcc.gnu.org>
|
||||
|
||||
* genattrtab.c (write_test_expr): New parameter EMIT_PARENS
|
||||
|
|
54
gcc/match.pd
54
gcc/match.pd
|
@ -2508,6 +2508,60 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
|
|||
(out @0 { wide_int_to_tree (TREE_TYPE (@0), wi::max_value
|
||||
(TYPE_PRECISION (TREE_TYPE (@0)), UNSIGNED) - @1); }))))
|
||||
|
||||
/* To detect overflow in unsigned A - B, A < B is simpler than A - B > A.
|
||||
However, the detection logic for SUB_OVERFLOW in tree-ssa-math-opts.c
|
||||
expects the long form, so we restrict the transformation for now. */
|
||||
(for cmp (gt le)
|
||||
(simplify
|
||||
(cmp (minus@2 @0 @1) @0)
|
||||
(if (single_use (@2)
|
||||
&& ANY_INTEGRAL_TYPE_P (TREE_TYPE (@0))
|
||||
&& TYPE_UNSIGNED (TREE_TYPE (@0))
|
||||
&& TYPE_OVERFLOW_WRAPS (TREE_TYPE (@0)))
|
||||
(cmp @1 @0))))
|
||||
(for cmp (lt ge)
|
||||
(simplify
|
||||
(cmp @0 (minus@2 @0 @1))
|
||||
(if (single_use (@2)
|
||||
&& ANY_INTEGRAL_TYPE_P (TREE_TYPE (@0))
|
||||
&& TYPE_UNSIGNED (TREE_TYPE (@0))
|
||||
&& TYPE_OVERFLOW_WRAPS (TREE_TYPE (@0)))
|
||||
(cmp @0 @1))))
|
||||
|
||||
/* Testing for overflow is unnecessary if we already know the result. */
|
||||
/* A < A - B */
|
||||
(for cmp (lt ge)
|
||||
out (ne eq)
|
||||
(simplify
|
||||
(cmp @0 (realpart (IFN_SUB_OVERFLOW@2 @0 @1)))
|
||||
(if (TYPE_UNSIGNED (TREE_TYPE (@0))
|
||||
&& types_match (TREE_TYPE (@0), TREE_TYPE (@1)))
|
||||
(out (imagpart @2) { build_zero_cst (TREE_TYPE (@0)); }))))
|
||||
/* A - B > A */
|
||||
(for cmp (gt le)
|
||||
out (ne eq)
|
||||
(simplify
|
||||
(cmp (realpart (IFN_SUB_OVERFLOW@2 @0 @1)) @0)
|
||||
(if (TYPE_UNSIGNED (TREE_TYPE (@0))
|
||||
&& types_match (TREE_TYPE (@0), TREE_TYPE (@1)))
|
||||
(out (imagpart @2) { build_zero_cst (TREE_TYPE (@0)); }))))
|
||||
/* A + B < A */
|
||||
(for cmp (lt ge)
|
||||
out (ne eq)
|
||||
(simplify
|
||||
(cmp (realpart (IFN_ADD_OVERFLOW:c@2 @0 @1)) @0)
|
||||
(if (TYPE_UNSIGNED (TREE_TYPE (@0))
|
||||
&& types_match (TREE_TYPE (@0), TREE_TYPE (@1)))
|
||||
(out (imagpart @2) { build_zero_cst (TREE_TYPE (@0)); }))))
|
||||
/* A > A + B */
|
||||
(for cmp (gt le)
|
||||
out (ne eq)
|
||||
(simplify
|
||||
(cmp @0 (realpart (IFN_ADD_OVERFLOW:c@2 @0 @1)))
|
||||
(if (TYPE_UNSIGNED (TREE_TYPE (@0))
|
||||
&& types_match (TREE_TYPE (@0), TREE_TYPE (@1)))
|
||||
(out (imagpart @2) { build_zero_cst (TREE_TYPE (@0)); }))))
|
||||
|
||||
|
||||
/* Simplification of math builtins. These rules must all be optimizations
|
||||
as well as IL simplifications. If there is a possibility that the new
|
||||
|
|
|
@ -1,3 +1,8 @@
|
|||
2016-04-27 Marc Glisse <marc.glisse@inria.fr>
|
||||
|
||||
* gcc.dg/tree-ssa/overflow-2.c: New testcase.
|
||||
* gcc.dg/tree-ssa/minus-ovf.c: Likewise.
|
||||
|
||||
2015-04-27 Ryan Burn <contact@rnburn.com>
|
||||
|
||||
PR c++/69024
|
||||
|
|
|
@ -0,0 +1,24 @@
|
|||
/* { dg-do compile } */
|
||||
/* { dg-options "-O -fdump-tree-optimized" } */
|
||||
|
||||
int f(unsigned a, unsigned b) {
|
||||
unsigned remove = a - b;
|
||||
return remove > a;
|
||||
}
|
||||
|
||||
int g(unsigned a, unsigned b) {
|
||||
unsigned remove = a - b;
|
||||
return remove <= a;
|
||||
}
|
||||
|
||||
int h(unsigned a, unsigned b) {
|
||||
unsigned remove = a - b;
|
||||
return a < remove;
|
||||
}
|
||||
|
||||
int i(unsigned a, unsigned b) {
|
||||
unsigned remove = a - b;
|
||||
return a >= remove;
|
||||
}
|
||||
|
||||
/* { dg-final { scan-tree-dump-not "remove" "optimized" } } */
|
|
@ -0,0 +1,68 @@
|
|||
/* { dg-do compile } */
|
||||
/* { dg-options "-O2 -fdump-tree-optimized-raw" } */
|
||||
|
||||
int carry;
|
||||
int f(unsigned a, unsigned b) {
|
||||
unsigned r;
|
||||
carry = __builtin_sub_overflow(a, b, &r);
|
||||
return r > a;
|
||||
}
|
||||
int g(unsigned a, unsigned b) {
|
||||
unsigned r;
|
||||
carry = __builtin_sub_overflow(a, b, &r);
|
||||
return a < r;
|
||||
}
|
||||
int h(unsigned a, unsigned b) {
|
||||
unsigned r;
|
||||
carry = __builtin_sub_overflow(a, b, &r);
|
||||
return r <= a;
|
||||
}
|
||||
int i(unsigned a, unsigned b) {
|
||||
unsigned r;
|
||||
carry = __builtin_sub_overflow(a, b, &r);
|
||||
return a >= r;
|
||||
}
|
||||
int j(unsigned a, unsigned b) {
|
||||
unsigned r;
|
||||
carry = __builtin_add_overflow(a, b, &r);
|
||||
return r < a;
|
||||
}
|
||||
int j2(unsigned a, unsigned b) {
|
||||
unsigned r;
|
||||
carry = __builtin_add_overflow(a, b, &r);
|
||||
return r < b;
|
||||
}
|
||||
int k(unsigned a, unsigned b) {
|
||||
unsigned r;
|
||||
carry = __builtin_add_overflow(a, b, &r);
|
||||
return a > r;
|
||||
}
|
||||
int k2(unsigned a, unsigned b) {
|
||||
unsigned r;
|
||||
carry = __builtin_add_overflow(a, b, &r);
|
||||
return b > r;
|
||||
}
|
||||
int l(unsigned a, unsigned b) {
|
||||
unsigned r;
|
||||
carry = __builtin_add_overflow(a, b, &r);
|
||||
return r >= a;
|
||||
}
|
||||
int l2(unsigned a, unsigned b) {
|
||||
unsigned r;
|
||||
carry = __builtin_add_overflow(a, b, &r);
|
||||
return r >= b;
|
||||
}
|
||||
int m(unsigned a, unsigned b) {
|
||||
unsigned r;
|
||||
carry = __builtin_add_overflow(a, b, &r);
|
||||
return a <= r;
|
||||
}
|
||||
int m2(unsigned a, unsigned b) {
|
||||
unsigned r;
|
||||
carry = __builtin_add_overflow(a, b, &r);
|
||||
return b <= r;
|
||||
}
|
||||
|
||||
/* { dg-final { scan-tree-dump-not "(le|lt|ge|gt)_expr" "optimized" } } */
|
||||
/* { dg-final { scan-tree-dump-times "ADD_OVERFLOW" 8 "optimized" } } */
|
||||
/* { dg-final { scan-tree-dump-times "SUB_OVERFLOW" 4 "optimized" } } */
|
Loading…
Reference in New Issue