From: Samarth Tandale <[email protected]>

For MIN_EXPR, if x is TYPE_MAX_VALUE, then min (x, y) is y.
So:
        x == TYPE_MAX_VALUE ? y : min (x, y)
can be simplified to:
        min (x, y)

Similarly for MAX_EXPR, if x is TYPE_MIN_VALUE, then max (x, y)
is y.
So:
        x == TYPE_MIN_VALUE ? y : max (x, y)
can be simplified to:
        max (x, y)

This adds a combined match.pd pattern for MIN_EXPR and MAX_EXPR.

        PR tree-optimization/125700

gcc/ChangeLog:

        * match.pd: Fold type-bound guarded min/max expressions.

gcc/testsuite/ChangeLog:

        * gcc.dg/tree-ssa/pr125700.c: New test.
        * gcc.dg/tree-ssa/pr125700-int-width.c: New test.
        * gcc.dg/tree-ssa/pr125700-negative.c: New test.

Signed-off-by: Samarth Tandale <[email protected]>
---
For MIN_EXPR, if x is TYPE_MAX_VALUE, then min (x, y) is y.
So:
        x == TYPE_MAX_VALUE ? y : min (x, y)
can be simplified to:
        min (x, y)

Similarly for MAX_EXPR, if x is TYPE_MIN_VALUE, then max (x, y)
is y.
So:
        x == TYPE_MIN_VALUE ? y : max (x, y)
can be simplified to:
        max (x, y)

This adds a combined match.pd pattern for MIN_EXPR and MAX_EXPR.

        PR tree-optimization/125700

```
gcc/ChangeLog:

        * match.pd: Fold type-bound guarded min/max expressions.

gcc/testsuite/ChangeLog:

        * gcc.dg/tree-ssa/pr125700.c: New test.
        * gcc.dg/tree-ssa/pr125700-int-width.c: New test.
        * gcc.dg/tree-ssa/pr125700-negative.c: New test.
```

Signed-off-by: Samarth Tandale <[email protected]>



This is a forge pull request published on the gcc-patches mailing list mailing 
list
as requested by Samarth Tandale via Sourceware Forge 
<[email protected]>.
Forge discussion: https://forge.sourceware.org/gcc/gcc/pulls/214

Get it locally using:
```
git fetch forge-upstream "+refs/versioned_pull/214/*:refs/versioned_pull/214/*"
git switch -c "pr-214-v1" "refs/versioned_pull/214/1/head"
```
Or, download the patch at: https://forge.sourceware.org/gcc/gcc/pulls/214.diff
Created on: 2026-08-10 06:22:31+00:00
Latest update: 2026-08-10 06:35:25+00:00
Changes: 4 changed files, 223 additions, 0 deletions
Head revision: sam-100/gcc ref pr125700 commit 
4d042112a60614fdea9eface9d3b6c00fab7a260 
Base revision: gcc/gcc ref trunk commit 
19a304d3680a1aeeb8ca412a6fe108a3f3b9d305 r17-3012-g19a304d3680a1a
Merge base: 19a304d3680a1aeeb8ca412a6fe108a3f3b9d305
Requested Reviewers: pinskia

Changed files:
- A: gcc/testsuite/gcc.dg/tree-ssa/pr125700-int-width.c
- A: gcc/testsuite/gcc.dg/tree-ssa/pr125700-negative.c
- A: gcc/testsuite/gcc.dg/tree-ssa/pr125700.c
- M: gcc/match.pd

 gcc/match.pd                                  |  16 +++
 .../gcc.dg/tree-ssa/pr125700-int-width.c      |  52 ++++++++
 .../gcc.dg/tree-ssa/pr125700-negative.c       |  41 +++++++
 gcc/testsuite/gcc.dg/tree-ssa/pr125700.c      | 114 ++++++++++++++++++
 4 files changed, 223 insertions(+)
 create mode 100644 gcc/testsuite/gcc.dg/tree-ssa/pr125700-int-width.c
 create mode 100644 gcc/testsuite/gcc.dg/tree-ssa/pr125700-negative.c
 create mode 100644 gcc/testsuite/gcc.dg/tree-ssa/pr125700.c

diff --git a/gcc/match.pd b/gcc/match.pd
index e99a35046bc86..39c57a06cc733 100644
--- a/gcc/match.pd
+++ b/gcc/match.pd
@@ -12707,3 +12707,19 @@ and,
  (if (INTEGRAL_TYPE_P (type))
    (with { tree itype = TREE_TYPE (@2); }
     (convert (minus @2 (convert:itype @1))))))
+
+/* Replace (x == TYPE_MAX) ? y : MIN (x, y) -> MIN (x, y)
+   because MIN (TYPE_MAX, y) is always y.
+   Similarly, (x == TYPE_MIN) ? y : MAX (x, y) -> MAX (x, y)
+   because MAX (TYPE_MIN, y) is always y.  */
+(for minmax (min max)
+ (simplify
+  (cond (eq @0 INTEGER_CST@1) @2 (minmax:c@3 @0 @2))
+  (if (INTEGRAL_TYPE_P (type))
+   (with {
+     tree bound = (minmax == MIN_EXPR)
+                 ? TYPE_MAX_VALUE (type)
+                 : TYPE_MIN_VALUE (type);
+    }
+    (if (bound && tree_int_cst_equal (@1, bound))
+     @3)))))
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr125700-int-width.c 
b/gcc/testsuite/gcc.dg/tree-ssa/pr125700-int-width.c
new file mode 100644
index 0000000000000..0ce990b6b4cf4
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/pr125700-int-width.c
@@ -0,0 +1,52 @@
+/* PR tree-optimization/125700  */
+/* Integer width variants to cover non-int widths and
+   both signed/unsigned.  */
+
+/* { dg-do compile } */
+/* { dg-options "-O1 -fdump-tree-optimized" } */
+
+#include <limits.h>
+
+#define GEN_FUNCS(TAG, UTYPE, STYPE, UMAX, SMAX, SMIN) \
+UTYPE \
+fumin_##TAG (UTYPE x, UTYPE y) \
+{ \
+  if (x == (UMAX)) \
+    return y; \
+  return x < y ? x : y; \
+} \
+\
+STYPE \
+fsmin_##TAG (STYPE x, STYPE y) \
+{ \
+  if (x == (SMAX)) \
+    return y; \
+  return x < y ? x : y; \
+} \
+\
+UTYPE \
+fumax_##TAG (UTYPE x, UTYPE y) \
+{ \
+  if (x == 0) \
+    return y; \
+  return x > y ? x : y; \
+} \
+\
+STYPE \
+fsmax_##TAG (STYPE x, STYPE y) \
+{ \
+  if (x == (SMIN)) \
+    return y; \
+  return x > y ? x : y; \
+}
+
+GEN_FUNCS (char, unsigned char, signed char, UCHAR_MAX, SCHAR_MAX, SCHAR_MIN)
+GEN_FUNCS (short, unsigned short, short, USHRT_MAX, SHRT_MAX, SHRT_MIN)
+GEN_FUNCS (long, unsigned long, long, ULONG_MAX, LONG_MAX, LONG_MIN)
+GEN_FUNCS (long_long, unsigned long long, long long, ULLONG_MAX, LLONG_MAX,
+    LLONG_MIN)
+
+/* { dg-final { scan-tree-dump-not "if" "optimized" } } */
+/* { dg-final { scan-tree-dump-not " == " "optimized" } } */
+/* { dg-final { scan-tree-dump-times "MIN_EXPR" 8 "optimized" } } */
+/* { dg-final { scan-tree-dump-times "MAX_EXPR" 8 "optimized" } } */
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr125700-negative.c 
b/gcc/testsuite/gcc.dg/tree-ssa/pr125700-negative.c
new file mode 100644
index 0000000000000..4bfd7f6ca5f05
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/pr125700-negative.c
@@ -0,0 +1,41 @@
+/* PR tree-optimization/125700  */
+/* Negative test cases, should not transform.  */
+
+/* { dg-do compile } */
+/* { dg-options "-O1 -fdump-tree-optimized" } */
+
+unsigned
+fumin_negative (unsigned x, unsigned y)
+{
+  if (x == 0)
+    return y;
+  return x < y ? x : y;
+}
+
+unsigned
+fumax_negative (unsigned x, unsigned y)
+{
+  if (x == -1u)
+    return y;
+  return x > y ? x : y;
+}
+
+signed
+fsmin_negative (signed x, signed y)
+{
+  if (x == -__INT_MAX__ - 1)
+    return y;
+  return x < y ? x : y;
+}
+
+signed
+fsmax_negative (signed x, signed y)
+{
+  if (x == __INT_MAX__)
+    return y;
+  return x > y ? x : y;
+}
+
+/* None of the if and '==' comparisons should be eliminated.  */
+/* { dg-final { scan-tree-dump-times "if" 4 "optimized" } } */
+/* { dg-final { scan-tree-dump-times " == " 4 "optimized" } } */
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr125700.c 
b/gcc/testsuite/gcc.dg/tree-ssa/pr125700.c
new file mode 100644
index 0000000000000..569c61141ef75
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/pr125700.c
@@ -0,0 +1,114 @@
+/* PR tree-optimization/125700  */
+/* Test the original cases, alternative condition forms and reversed
+   minimum/maximum operand orders.  */
+
+/* { dg-do compile } */
+/* { dg-options "-O1 -fdump-tree-optimized" } */
+
+unsigned
+fumin (unsigned x, unsigned y)
+{
+  if (x == -1u)
+    return y;
+  return x < y ? x : y;
+}
+
+signed
+fsmin (signed x, signed y)
+{
+  if (x == __INT_MAX__)
+    return y;
+  return x < y ? x : y;
+}
+
+unsigned
+fumax (unsigned x, unsigned y)
+{
+  if (x == 0)
+    return y;
+  return x > y ? x : y;
+}
+
+signed
+fsmax (signed x, signed y)
+{
+  if (x == -__INT_MAX__ - 1)
+    return y;
+  return x > y ? x : y;
+}
+
+unsigned
+fumin_ne (unsigned x, unsigned y)
+{
+  if (x != -1u)
+    return x < y ? x : y;
+  return y;
+}
+
+unsigned
+fumax_ne (unsigned x, unsigned y)
+{
+  if (x != 0)
+    return x > y ? x : y;
+  return y;
+}
+
+unsigned
+fumin_ge (unsigned x, unsigned y)
+{
+  if (x >= -1u)
+    return y;
+  return x < y ? x : y;
+}
+
+unsigned
+fumax_le (unsigned x, unsigned y)
+{
+  if (x <= 0)
+    return y;
+  return x > y ? x : y;
+}
+
+unsigned
+fumin_lt (unsigned x, unsigned y)
+{
+  if (!(x < -1u))
+    return y;
+  return x < y ? x : y;
+}
+
+unsigned
+fumax_gt (unsigned x, unsigned y)
+{
+  if (!(x > 0))
+    return y;
+  return x > y ? x : y;
+}
+
+unsigned
+fumin_flip (unsigned x, unsigned y)
+{
+  if (x == -1u)
+    return y;
+  return y > x ? x : y;
+}
+
+unsigned
+fumax_flip (unsigned x, unsigned y)
+{
+  if (x == 0)
+    return y;
+  return y < x ? x : y;
+}
+
+/* The if and all conditional operators should be removed
+   from the optimized dump output.  */
+/* { dg-final { scan-tree-dump-not "if" "optimized" } } */
+/* { dg-final { scan-tree-dump-not " == " "optimized" } } */
+/* { dg-final { scan-tree-dump-not " != " "optimized" } } */
+/* { dg-final { scan-tree-dump-not " <= " "optimized" } } */
+/* { dg-final { scan-tree-dump-not " >= " "optimized" } } */
+/* { dg-final { scan-tree-dump-not " < " "optimized" } } */
+/* { dg-final { scan-tree-dump-not " > " "optimized" } } */
+/* { dg-final { scan-tree-dump-times "MIN_EXPR" 6 "optimized" } } */
+/* { dg-final { scan-tree-dump-times "MAX_EXPR" 6 "optimized" } } */
-- 
2.54.0

Reply via email to