[gcc r17-2802] match: Fix `a CMP CST0 ? MIN/MAX<a, b> : MIN/MAX<a, CST1>` pattern [PR126456]

Andrea Pinski via Gcc-cvs <[email protected]> Thu, 30 Jul 2026 03:53:21 +0000 (GMT)
Newsgroups gmane.comp.gcc.cvs
Message-ID <[email protected]>
https://gcc.gnu.org/g:8f6eb7077059952273cc39de66e1dca01b84cb4d

commit r17-2802-g8f6eb7077059952273cc39de66e1dca01b84cb4d
Author: Andrea Pinski <[email protected]>
Date:   Wed Jul 29 15:48:01 2026 -0700

    match: Fix `a CMP CST0 ? MIN/MAX<a, b> : MIN/MAX<a, CST1>` pattern [PR126456]
    
    The order of the arguments for minmax_from_comparison is wrong for this
    pattern. I swapped the 2 CST which in some cases could cause
    incorrect code.
    
    Pushed as obvious after a bootstrap/testing on x86_64-linux-gnu.
    Note for backporting, minmax-29.c and minmax-30.c will need to be
    changed slightly because we don't factor out the min/max before GCC 17.
    
            PR tree-optimization/126456
    
    gcc/ChangeLog:
    
            * match.pd (`a CMP b ? MIN/MAX<a, c> : MIN/MAX<a, d>`): Fix
            order of minmax_from_comparison arguments.
    
    gcc/testsuite/ChangeLog:
    
            * gcc.dg/torture/minmax-1.c: New test.
            * gcc.dg/tree-ssa/minmax-29.c: New test.
            * gcc.dg/tree-ssa/minmax-30.c: New test.
            * gcc.dg/tree-ssa/minmax-31.c: New test.
            * gcc.dg/tree-ssa/minmax-32.c: New test.
    
    Signed-off-by: Andrea Pinski <[email protected]>

Diff:
---
 gcc/match.pd                              |  2 +-
 gcc/testsuite/gcc.dg/torture/minmax-1.c   | 28 ++++++++++++++++++++++++++++
 gcc/testsuite/gcc.dg/tree-ssa/minmax-29.c | 31 +++++++++++++++++++++++++++++++
 gcc/testsuite/gcc.dg/tree-ssa/minmax-30.c | 30 ++++++++++++++++++++++++++++++
 gcc/testsuite/gcc.dg/tree-ssa/minmax-31.c | 30 ++++++++++++++++++++++++++++++
 gcc/testsuite/gcc.dg/tree-ssa/minmax-32.c | 29 +++++++++++++++++++++++++++++
 6 files changed, 149 insertions(+), 1 deletion(-)

diff --git a/gcc/match.pd b/gcc/match.pd
index ff5d012f7fd6..eb2730c24f73 100644
--- a/gcc/match.pd
+++ b/gcc/match.pd
@@ -6888,7 +6888,7 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
    (cond (cmp:c @1 @3) (minmax:c @1 @4) (minmax:c @2 @4))
    (with
     {
-      tree_code code = minmax_from_comparison (cmp, @1, @2, @1, @3);
+      tree_code code = minmax_from_comparison (cmp, @1, @3, @1, @2);
     }
     (if (code == MIN_EXPR)
      (minmax (min @1 @2) @4)
diff --git a/gcc/testsuite/gcc.dg/torture/minmax-1.c b/gcc/testsuite/gcc.dg/torture/minmax-1.c
new file mode 100644
index 000000000000..875f24553655
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/torture/minmax-1.c
@@ -0,0 +1,28 @@
+/* { dg-do run } */
+/* PR tree-optimization/126456 */
+
+/* These should not produce min/max for
+   the outer conditional.  */
+
+__attribute__((noipa)) int
+min_le (int a, int c)
+{
+  return (a <= 6) ? (a < c ? a : c) : (5 < c ? 5 : c);
+}
+
+__attribute__((noipa)) int
+max_ge (int a, int c)
+{
+  return (a >= 4) ? (a > c ? a : c) : (5 > c ? 5 : c);
+}
+
+int
+main (void)
+{
+  if (min_le (6, 10) != 6)
+    __builtin_abort ();
+  if (max_ge (4, 0) != 4)
+    __builtin_abort ();
+  return 0;
+}
+
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/minmax-29.c b/gcc/testsuite/gcc.dg/tree-ssa/minmax-29.c
new file mode 100644
index 000000000000..8779c08a30df
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/minmax-29.c
@@ -0,0 +1,31 @@
+/* { dg-do compile } */
+/* { dg-options "-O1 -fdump-tree-optimized" } */
+
+/* These should not produce max, only 3 min and there should be an if left. */
+
+__attribute__((noipa)) int
+min_le (int a, int c)
+{
+  return (a <= 6) ? (a < c ? a : c) : (5 < c ? 5 : c);
+}
+
+int
+min_le_1 (int a, int c)
+{
+  if (a <= 6)
+    return (a < c ? a : c);
+  return (5 < c ? 5 : c);
+}
+
+int
+min_le_2 (int a, int c)
+{
+  int t = (a < c ? a : c);
+  int t1 = (5 < c ? 5 : c);
+  if (a <= 6)
+    return t;
+  return t1;
+}
+/* { dg-final { scan-tree-dump-not "MAX_EXPR " "optimized" } } */
+/* { dg-final { scan-tree-dump-times "MIN_EXPR " 3 "optimized" } } */
+/* { dg-final { scan-tree-dump-times "if " 3 "optimized" } } */
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/minmax-30.c b/gcc/testsuite/gcc.dg/tree-ssa/minmax-30.c
new file mode 100644
index 000000000000..eb0c4499001a
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/minmax-30.c
@@ -0,0 +1,30 @@
+/* { dg-do compile } */
+/* { dg-options "-O1 -fdump-tree-optimized" } */
+
+/* These should not produce min, only 3 max and there should be an if left. */
+int
+max_ge (int a, int c)
+{
+  return (a >= 4) ? (a > c ? a : c) : (5 > c ? 5 : c);
+}
+
+int
+max_ge_1 (int a, int c)
+{
+  int t = (a > c ? a : c);
+  int t1 = (5 > c ? 5 : c);
+  return (a >= 4) ? t : t1;
+}
+
+int
+max_ge_2 (int a, int c)
+{
+  if (a >= 4)
+    return (a > c ? a : c);
+  return (5 > c ? 5 : c);
+}
+
+
+/* { dg-final { scan-tree-dump-times "MAX_EXPR " 3 "optimized" } } */
+/* { dg-final { scan-tree-dump-times "if " 3 "optimized" } } */
+/* { dg-final { scan-tree-dump-not "MIN_EXPR " "optimized" } } */
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/minmax-31.c b/gcc/testsuite/gcc.dg/tree-ssa/minmax-31.c
new file mode 100644
index 000000000000..95f815e16bcf
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/minmax-31.c
@@ -0,0 +1,30 @@
+/* { dg-do compile } */
+/* { dg-options "-O1 -fdump-tree-optimized" } */
+
+/* These should produce 2x min for each function. */
+
+__attribute__((noipa)) int
+min_le (int a, int c)
+{
+  return (a < 5) ? (a < c ? a : c) : (5 < c ? 5 : c);
+}
+
+int
+min_le_1 (int a, int c)
+{
+  if (a < 5)
+    return (a < c ? a : c);
+  return (5 < c ? 5 : c);
+}
+
+int
+min_le_2 (int a, int c)
+{
+  int t = (a < c ? a : c);
+  int t1 = (5 < c ? 5 : c);
+  if (a < 5)
+    return t;
+  return t1;
+}
+/* { dg-final { scan-tree-dump-not "MAX_EXPR " "optimized" } } */
+/* { dg-final { scan-tree-dump-times "MIN_EXPR " 6 "optimized" } } */
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/minmax-32.c b/gcc/testsuite/gcc.dg/tree-ssa/minmax-32.c
new file mode 100644
index 000000000000..390cd874ce87
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/minmax-32.c
@@ -0,0 +1,29 @@
+/* { dg-do compile } */
+/* { dg-options "-O1 -fdump-tree-optimized" } */
+
+/* These should produce 2x max for each function. */
+int
+max_ge (int a, int c)
+{
+  return (a > 4) ? (a > c ? a : c) : (5 > c ? 5 : c);
+}
+
+int
+max_ge_1 (int a, int c)
+{
+  int t = (a > c ? a : c);
+  int t1 = (5 > c ? 5 : c);
+  return (a > 4) ? t : t1;
+}
+
+int
+max_ge_2 (int a, int c)
+{
+  if (a > 4)
+    return (a > c ? a : c);
+  return (5 > c ? 5 : c);
+}
+
+
+/* { dg-final { scan-tree-dump-times "MAX_EXPR " 6 "optimized" } } */
+/* { dg-final { scan-tree-dump-not "MIN_EXPR " "optimized" } } */