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]>
---
 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(-)
 create mode 100644 gcc/testsuite/gcc.dg/torture/minmax-1.c
 create mode 100644 gcc/testsuite/gcc.dg/tree-ssa/minmax-29.c
 create mode 100644 gcc/testsuite/gcc.dg/tree-ssa/minmax-30.c
 create mode 100644 gcc/testsuite/gcc.dg/tree-ssa/minmax-31.c
 create mode 100644 gcc/testsuite/gcc.dg/tree-ssa/minmax-32.c

diff --git a/gcc/match.pd b/gcc/match.pd
index 83418241bd9..9b14a042d05 100644
--- a/gcc/match.pd
+++ b/gcc/match.pd
@@ -6917,7 +6917,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 00000000000..875f2455365
--- /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 00000000000..8779c08a30d
--- /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 00000000000..eb0c4499001
--- /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 00000000000..95f815e16bc
--- /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 00000000000..390cd874ce8
--- /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" } } */
-- 
2.43.0

Reply via email to