From 32ee472864ada44ef05b2a3b087b8ce413bee282 Mon Sep 17 00:00:00 2001
From: Jeff Law <law@redhat.com>
Date: Thu, 5 Nov 2020 20:42:17 -0700
Subject: [PATCH] Improve overflow check
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Convert
x < (short) ((unsigned short)x + const)
to
x <= SHORT_MAX – const
(and similarly for other integral types) if const is not 0.

gcc/
	PR tree-optimization/97223
	* match.pd (overflow detection and optimization): Handle conversions.

gcc/testsuite/

	* gcc.dg/no-strict-overflow-4.c: Adjust expected output.
---
 gcc/match.pd                                | 16 ++++++++++------
 gcc/testsuite/gcc.dg/no-strict-overflow-4.c |  5 +++--
 2 files changed, 13 insertions(+), 8 deletions(-)

diff --git a/gcc/match.pd b/gcc/match.pd
index d82a62052fc7..349eab61d6b3 100644
--- a/gcc/match.pd
+++ b/gcc/match.pd
@@ -4945,18 +4945,22 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
 /* When one argument is a constant, overflow detection can be simplified.
    Currently restricted to single use so as not to interfere too much with
    ADD_OVERFLOW detection in tree-ssa-math-opts.c.
-   A + CST CMP A  ->  A CMP' CST' */
+   CONVERT?(CONVERT?(A) + CST) CMP A  ->  A CMP' CST' */
 (for cmp (lt le ge gt)
      out (gt gt le le)
  (simplify
-  (cmp:c (plus@2 @0 INTEGER_CST@1) @0)
-  (if (TYPE_UNSIGNED (TREE_TYPE (@0))
-       && TYPE_OVERFLOW_WRAPS (TREE_TYPE (@0))
+  (cmp:c (convert?@3 (plus@2 (convert?@4 @0) INTEGER_CST@1)) @0)
+  (if (TYPE_OVERFLOW_WRAPS (TREE_TYPE (@2))
+       && types_match (TREE_TYPE (@0), TREE_TYPE (@3))
+       && tree_nop_conversion_p (TREE_TYPE (@4), TREE_TYPE (@0))
        && wi::to_wide (@1) != 0
        && single_use (@2))
-   (with { unsigned int prec = TYPE_PRECISION (TREE_TYPE (@0)); }
+   (with {
+     unsigned int prec = TYPE_PRECISION (TREE_TYPE (@0));
+     signop sign = TYPE_SIGN (TREE_TYPE (@0));
+    }
     (out @0 { wide_int_to_tree (TREE_TYPE (@0),
-			        wi::max_value (prec, UNSIGNED)
+			        wi::max_value (prec, sign)
 				- wi::to_wide (@1)); })))))
 
 /* To detect overflow in unsigned A - B, A < B is simpler than A - B > A.
diff --git a/gcc/testsuite/gcc.dg/no-strict-overflow-4.c b/gcc/testsuite/gcc.dg/no-strict-overflow-4.c
index b6d3da3f8318..90145ff9422a 100644
--- a/gcc/testsuite/gcc.dg/no-strict-overflow-4.c
+++ b/gcc/testsuite/gcc.dg/no-strict-overflow-4.c
@@ -4,7 +4,8 @@
 /* Source: Ian Lance Taylor.  Dual of strict-overflow-4.c.  */
 
 /* We can only simplify the conditional when using strict overflow
-   semantics.  */
+   semantics or when using wrap overflow semantics. -fno-strict-overflow is
+   equivalent to -fwrapv.  */
 
 int
 foo (int i)
@@ -12,4 +13,4 @@ foo (int i)
   return i + 1 > i;
 }
 
-/* { dg-final { scan-tree-dump "\[^ \]*_.(\\\(D\\\))? (>|<) \[^ \]*_." "optimized" } } */
+/* { dg-final { scan-tree-dump "\[^ \]*_.(\\\(D\\\))? != \[0-9]+" "optimized" } } */
-- 
GitLab