From 3563f78f97c4c1e1738cbd159b12d65f57c13bfb Mon Sep 17 00:00:00 2001 From: Marc Glisse Date: Wed, 27 Apr 2016 23:30:27 +0200 Subject: [PATCH] match.pd: unsigned A - B > A --> A < B 2016-04-27 Marc Glisse 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 | 4 ++ gcc/match.pd | 54 +++++++++++++++++ gcc/testsuite/ChangeLog | 5 ++ gcc/testsuite/gcc.dg/tree-ssa/minus-ovf.c | 24 ++++++++ gcc/testsuite/gcc.dg/tree-ssa/overflow-2.c | 68 ++++++++++++++++++++++ 5 files changed, 155 insertions(+) create mode 100644 gcc/testsuite/gcc.dg/tree-ssa/minus-ovf.c create mode 100644 gcc/testsuite/gcc.dg/tree-ssa/overflow-2.c diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 225ade991ce..5fd8bec815f 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,7 @@ +2016-04-27 Marc Glisse + + * match.pd (A - B > A, A + B < A): New transformations. + 2016-04-27 Patrick Palka * genattrtab.c (write_test_expr): New parameter EMIT_PARENS diff --git a/gcc/match.pd b/gcc/match.pd index 476818709cf..f645157a4f4 100644 --- a/gcc/match.pd +++ b/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 diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 6189bee94ac..ec1f3a2cc45 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2016-04-27 Marc Glisse + + * gcc.dg/tree-ssa/overflow-2.c: New testcase. + * gcc.dg/tree-ssa/minus-ovf.c: Likewise. + 2015-04-27 Ryan Burn 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 index 00000000000..aad66bbcb06 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/minus-ovf.c @@ -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 index 00000000000..83183e8a9cc --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/overflow-2.c @@ -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" } } */