https://gcc.gnu.org/g:b085fc9965b7d1e99725892587682822068f2baa

commit r15-5356-gb085fc9965b7d1e99725892587682822068f2baa
Author: Andrew Pinski <quic_apin...@quicinc.com>
Date:   Fri Nov 15 23:20:42 2024 -0800

    match: Optimize `max(a,b) == 0` to `(a|b) == 0` for unsigned [PR115275]
    
    For unsigned types, you can optimize `max<a,b> == 0` into
    `(a|b) == 0` (that is both have to be zero). A similar thing happens for 
`!= 0`.
    This optimization fixes the missed optimization (g++.dg/tree-ssa/pr115275.C)
    that was reported exposed by adding phiprop early.
    
    Bootstrapped and tested on x86_64-linux-gnu.
    
            PR tree-optimization/115275
    
    gcc/ChangeLog:
    
            * match.pd (umax(a,b) ==/!= 0): New pattern.
    
    gcc/testsuite/ChangeLog:
    
            * g++.dg/tree-ssa/pr115275.C: New test.
            * gcc.dg/tree-ssa/max_eqne-1.c: New test.
            * gcc.dg/tree-ssa/max_eqne-2.c: New test.
    
    Signed-off-by: Andrew Pinski <quic_apin...@quicinc.com>

Diff:
---
 gcc/match.pd                               |  8 +++++++
 gcc/testsuite/g++.dg/tree-ssa/pr115275.C   | 36 ++++++++++++++++++++++++++++++
 gcc/testsuite/gcc.dg/tree-ssa/max_eqne-1.c | 20 +++++++++++++++++
 gcc/testsuite/gcc.dg/tree-ssa/max_eqne-2.c | 19 ++++++++++++++++
 4 files changed, 83 insertions(+)

diff --git a/gcc/match.pd b/gcc/match.pd
index 937076422323..4bec24a21b29 100644
--- a/gcc/match.pd
+++ b/gcc/match.pd
@@ -4795,6 +4795,14 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
   (cmp (minmax @0 INTEGER_CST@1) INTEGER_CST@2)
   (comb (cmp @0 @2) (cmp @1 @2))))
 
+/* MAX (A, B) == 0 -> (A|B) == 0 iff unsigned.
+   MAX (A, B) != 0 -> (A|B) != 0 iff unsigned.  */
+(for cmp (eq ne)
+ (simplify
+  (cmp (max @0 @1) integer_zerop@2)
+  (if (TYPE_UNSIGNED (TREE_TYPE (@0)))
+   (cmp (bit_ior @0 @1) @2))))
+
 /* Undo fancy ways of writing max/min or other ?: expressions, like
    a - ((a - b) & -(a < b))  and  a - (a - b) * (a < b) into (a < b) ? b : a.
    People normally use ?: and that is what we actually try to optimize.  */
diff --git a/gcc/testsuite/g++.dg/tree-ssa/pr115275.C 
b/gcc/testsuite/g++.dg/tree-ssa/pr115275.C
new file mode 100644
index 000000000000..1b84766186af
--- /dev/null
+++ b/gcc/testsuite/g++.dg/tree-ssa/pr115275.C
@@ -0,0 +1,36 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-tree-optimized" } */
+
+/* PR tree-optimization/115275 */
+
+template<class T>
+inline const T &
+min(const T &a, const T &b)
+{
+  return a < b ? a : b;
+}
+
+template<class T>
+inline const T &
+max(const T &a, const T &b)
+{
+  return a < b ? b : a;
+}
+
+
+unsigned short m, a, b;
+void removeme ();
+void fn(unsigned short f) {
+    if(
+    (min(max(f, a) ? f : 0U, 84991U))
+    -
+    (min(max(f, b) ? f : 0U, 84991U))
+    )
+    {
+      removeme();
+    }
+}
+
+/* removeme call should be optimized out.  */
+
+/* { dg-final { scan-tree-dump-not "removeme " "optimized" } } */
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/max_eqne-1.c 
b/gcc/testsuite/gcc.dg/tree-ssa/max_eqne-1.c
new file mode 100644
index 000000000000..a7f5e0ec7dc9
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/max_eqne-1.c
@@ -0,0 +1,20 @@
+/* { dg-do compile } */
+/* { dg-options "-O1 -fdump-tree-optimized-raw" } */
+
+/* PR tree-optimization/115275 */
+
+unsigned maxne(unsigned a, unsigned b)
+{
+  unsigned t = a > b ? a : b;
+  return t != 0;
+}
+unsigned maxeq(unsigned a, unsigned b)
+{
+  unsigned t = a > b ? a : b;
+  return t == 0;
+}
+/* `max(a,b) == 0` should be optimized to `(a|b) == 0` for unsigned types. */
+/* { dg-final { scan-tree-dump-not "max_expr, " "optimized" } } */
+/* { dg-final { scan-tree-dump-times "bit_ior_expr, " 2 "optimized" } } */
+/* { dg-final { scan-tree-dump-times "eq_expr, " 1 "optimized" } } */
+/* { dg-final { scan-tree-dump-times "ne_expr, " 1 "optimized" } } */
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/max_eqne-2.c 
b/gcc/testsuite/gcc.dg/tree-ssa/max_eqne-2.c
new file mode 100644
index 000000000000..50808cc7e02a
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/max_eqne-2.c
@@ -0,0 +1,19 @@
+/* { dg-do compile } */
+/* { dg-options "-O1 -fdump-tree-optimized-raw" } */
+
+/* PR tree-optimization/115275 */
+signed maxne(signed a, signed b)
+{
+  unsigned t = a > b ? a : b;
+  return t != 0;
+}
+signed maxeq(signed a, signed b)
+{
+  unsigned t = a > b ? a : b;
+  return t == 0;
+}
+/* For signed types, `max(a,b) == 0` should not optimized to `(a|b) == 0`. */
+/* { dg-final { scan-tree-dump-times "max_expr, " 2 "optimized" } } */
+/* { dg-final { scan-tree-dump-not "bit_ior_expr, " "optimized" } } */
+/* { dg-final { scan-tree-dump-times "eq_expr, " 1 "optimized" } } */
+/* { dg-final { scan-tree-dump-times "ne_expr, " 1 "optimized" } } */

Reply via email to