From: Andrea Pinski Date: Wed, 29 Jul 2026 22:48:01 +0000 (-0700) Subject: match: Fix `a CMP CST0 ? MIN/MAX : MIN/MAX` pattern [PR126456] X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=8f6eb7077059952273cc39de66e1dca01b84cb4d;p=thirdparty%2Fgcc.git match: Fix `a CMP CST0 ? MIN/MAX : MIN/MAX` 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 : MIN/MAX`): 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 --- diff --git a/gcc/match.pd b/gcc/match.pd index ff5d012f7fd..eb2730c24f7 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 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" } } */