+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
(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
+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
--- /dev/null
+/* { 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" } } */
--- /dev/null
+/* { 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" } } */