[gcc r17-3279] match: Try to remove casts for `(int)-(unsigned)a`[PR107765]

Andrea Pinski via Gcc-cvs <[email protected]>
Newsgroups gmane.comp.gcc.cvs
Message-ID <[email protected]>
https://gcc.gnu.org/g:8d004ef91c4f7c315519975ffaec78d28d4a21ff

commit r17-3279-g8d004ef91c4f7c315519975ffaec78d28d4a21ff
Author: Andrea Pinski <[email protected]>
Date:   Mon Jul 27 23:02:07 2026 -0700

    match: Try to remove casts for `(int)-(unsigned)a`[PR107765]
    
    This adds some extra checks to see if we can remove the casts
    for signed integer overflow reasons while doing a negative.
    This is needed more due to the recent patch which adds them
    in some cases.
    
    This also changes TYPE_UNSIGNED to be TYPE_OVERFLOW_WRAPS to
    allow this to happen with -fwrapv too.
    
    Changes since v1:
    * Use expr_not_equal_to and simplify the if stmt.
    Also use TYPE_OVERFLOW_WRAPS instead of TYPE_UNSIGNED.
    
    Bootstrapped and tested on x86_64-linux-gnu.
    
            PR tree-optimization/107765
    
    gcc/ChangeLog:
    
            * match.pd (`(cast)-(cast)a`): Expand to
            use expr_not_equal_to of INT_MIN.
    
    gcc/testsuite/ChangeLog:
    
            * gcc.dg/tree-ssa/neg-cast-1.c: New test.
            * gcc.dg/tree-ssa/neg-cast-4.c: New test.
    
    Signed-off-by: Andrea Pinski <[email protected]>

Diff:
---
 gcc/match.pd                               | 10 +++++++---
 gcc/testsuite/gcc.dg/tree-ssa/neg-cast-1.c | 23 +++++++++++++++++++++++
 gcc/testsuite/gcc.dg/tree-ssa/neg-cast-4.c | 16 ++++++++++++++++
 3 files changed, 46 insertions(+), 3 deletions(-)

diff --git a/gcc/match.pd b/gcc/match.pd
index f43d2e79363b..4ddddc43bd72 100644
--- a/gcc/match.pd
+++ b/gcc/match.pd
@@ -1231,13 +1231,17 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
    show up.  Else it is safe if the negation is done in an unsigned type.
    Note the outer cast cannot be a boolean type as the only valid values
    are 0,-1/1 (depending on the signedness of the boolean) and the negative
-   is there to get the correct value.  */
+   is there to get the correct value.
+   Also handle the case where we know that we won't cause a signed
+   integer overflow at the point of the negation.  */
 (simplify
- (convert (negate:s@1 (convert:s @0)))
+ (convert (negate:s@1 (convert:s@ic @0)))
  (if (INTEGRAL_TYPE_P (type)
       && tree_nop_conversion_p (type, TREE_TYPE (@1))
       && (TYPE_PRECISION (type) > TYPE_PRECISION (TREE_TYPE (@0))
-	  || TYPE_UNSIGNED (type))
+	  || TYPE_OVERFLOW_WRAPS (type)
+	  || expr_not_equal_to (@ic, wi::min_value (signed_type_for (type)),
+				gimple_match_ctx (@1)))
       && TREE_CODE (type) != BOOLEAN_TYPE)
     (negate (convert @0))))
 
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/neg-cast-1.c b/gcc/testsuite/gcc.dg/tree-ssa/neg-cast-1.c
new file mode 100644
index 000000000000..ec5d0e15251b
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/neg-cast-1.c
@@ -0,0 +1,23 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-tree-optimized -fdump-tree-cddce1" } */
+/* PR tree-optimization/107765 */
+
+int a(int input)
+{
+    if (input == -__INT_MAX__-1) return 1;
+    unsigned t = input;
+    int tt =  -t;
+    return tt == -input;
+}
+
+int b(int input)
+{
+    if (input == -__INT_MAX__-1) __builtin_trap();
+    unsigned t = input;
+    int tt =  -t;
+    return tt;
+}
+
+/* { dg-final { scan-tree-dump "return 1" "optimized" } } */
+/* { dg-final { scan-tree-dump-not "\\(unsigned int\\)" "cddce1" } } */
+/* { dg-final { scan-tree-dump-not "\\(int\\)" "cddce1" } } */
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/neg-cast-4.c b/gcc/testsuite/gcc.dg/tree-ssa/neg-cast-4.c
new file mode 100644
index 000000000000..fe3fe6a2eccf
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/neg-cast-4.c
@@ -0,0 +1,16 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-tree-phiopt2-details -fdump-tree-optimized" } */
+/* PR tree-optimization/107765 */
+
+int b(int input)
+{
+    if (input == -__INT_MAX__-1) return input;
+    unsigned t = input;
+    int tt =  -t;
+    return tt;
+}
+
+/* { dg-final { scan-tree-dump-not "if " "optimized" } } */
+/* { dg-final { scan-tree-dump-times "\\(unsigned int\\)" 1 "optimized" } } */
+/* { dg-final { scan-tree-dump-times "\\(int\\)" 1 "optimized" } } */
+/* { dg-final { scan-tree-dump-times "converted to straightline code" 1 "phiopt2" } } */
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.