]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
match: Fix `a CMP CST0 ? MIN/MAX<a, b> : MIN/MAX<a, CST1>` pattern [PR126456]
authorAndrea Pinski <andrew.pinski@oss.qualcomm.com>
Wed, 29 Jul 2026 22:48:01 +0000 (15:48 -0700)
committerAndrea Pinski <andrew.pinski@oss.qualcomm.com>
Thu, 30 Jul 2026 03:51:50 +0000 (20:51 -0700)
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 <andrew.pinski@oss.qualcomm.com>
gcc/match.pd
gcc/testsuite/gcc.dg/torture/minmax-1.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/tree-ssa/minmax-29.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/tree-ssa/minmax-30.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/tree-ssa/minmax-31.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/tree-ssa/minmax-32.c [new file with mode: 0644]

index ff5d012f7fd6dc5457acbf9062c2557886a6ec74..eb2730c24f73f322baaf51522c0900cbffa7dad6 100644 (file)
@@ -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 (file)
index 0000000..875f245
--- /dev/null
@@ -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 (file)
index 0000000..8779c08
--- /dev/null
@@ -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 (file)
index 0000000..eb0c449
--- /dev/null
@@ -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 (file)
index 0000000..95f815e
--- /dev/null
@@ -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 (file)
index 0000000..390cd87
--- /dev/null
@@ -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" } } */