]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
match.pd: unsigned A - B > A --> A < B
authorMarc Glisse <marc.glisse@inria.fr>
Wed, 27 Apr 2016 21:30:27 +0000 (23:30 +0200)
committerMarc Glisse <glisse@gcc.gnu.org>
Wed, 27 Apr 2016 21:30:27 +0000 (21:30 +0000)
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

gcc/ChangeLog
gcc/match.pd
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.dg/tree-ssa/minus-ovf.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/tree-ssa/overflow-2.c [new file with mode: 0644]

index 225ade991ce454355908cf01e40e0300f9257781..5fd8bec815f1ba667f8ff9b1b3b588a31bd157d3 100644 (file)
@@ -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
index 476818709cf0f2ba2a1da68589ee56e14c1a28ac..f645157a4f4aed1af8e6f01a1591643ebbc1c133 100644 (file)
@@ -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
index 6189bee94ac4e841e7cadfcb9a6cc07693dacc22..ec1f3a2cc45df058ec4522fe675d6df70b3d328d 100644 (file)
@@ -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
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/minus-ovf.c b/gcc/testsuite/gcc.dg/tree-ssa/minus-ovf.c
new file mode 100644 (file)
index 0000000..aad66bb
--- /dev/null
@@ -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" } } */
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/overflow-2.c b/gcc/testsuite/gcc.dg/tree-ssa/overflow-2.c
new file mode 100644 (file)
index 0000000..83183e8
--- /dev/null
@@ -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" } } */