From: Samarth Tandale <[email protected]>
The pattern:
x == C ? y : min (x, y)
can be simplified to min (x, y) whenever C >= upper_bound (y),
because min (C, y) == y for all values y can take. Similarly:
x == C ? y : max (x, y)
can be simplified to max (x, y) whenever C <= lower_bound (y).
Use ranger to query the value range of y and check the bound condition.
PR tree-optimization/125700
gcc/ChangeLog:
PR tree-optimization/125700
* match.pd ((x == C) ? y : MIN/MAX (x, y)): New simplification.
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.
* gcc.dg/tree-ssa/pr125700-range.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.
* gcc.dg/tree-ssa/pr125700-range.c: New test.
```
Signed-off-by: Samarth Tandale <[email protected]>
Changes since v1:
- Extended the optimization beyond fixed type limits. It now handles constants
when Ranger proves their relationship with y's value range and conservatively
falls back when no useful range is available.
- Added positive and negative test cases for Ranger-derived ranges.
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-v2" "refs/versioned_pull/214/2/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-09-19 10:29:08+00:00
Changes: 5 changed files, 407 additions, 0 deletions
Head revision: sam-100/gcc ref pr125700 commit
7e709962d4f3c68b0f6f2522c743109a0d11aeea
Base revision: gcc/gcc ref trunk commit
7f405dfaa29e4c9d8c7b4e6ada13fa44ff053a0c r17-4446-g7f405dfaa29e4c
Merge base: 7f405dfaa29e4c9d8c7b4e6ada13fa44ff053a0c
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-range.c
- A: gcc/testsuite/gcc.dg/tree-ssa/pr125700.c
- M: gcc/match.pd
gcc/match.pd | 25 +++
.../gcc.dg/tree-ssa/pr125700-int-width.c | 51 +++++++
.../gcc.dg/tree-ssa/pr125700-negative.c | 70 +++++++++
.../gcc.dg/tree-ssa/pr125700-range.c | 144 ++++++++++++++++++
gcc/testsuite/gcc.dg/tree-ssa/pr125700.c | 117 ++++++++++++++
5 files changed, 407 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-range.c
create mode 100644 gcc/testsuite/gcc.dg/tree-ssa/pr125700.c
diff --git a/gcc/match.pd b/gcc/match.pd
index e59c11d5d131d..857dc9a6baa29 100644
--- a/gcc/match.pd
+++ b/gcc/match.pd
@@ -13596,3 +13596,28 @@ and,
(if (INTEGRAL_TYPE_P (type))
(with { tree itype = TREE_TYPE (@2); }
(convert (minus @2 (convert:itype @1))))))
+
+#if GIMPLE
+/* Replace (x == C) ? y : MIN (x, y) -> MIN (x, y) when C >= upper_bound (y),
+ and (x == C) ? y : MAX (x, y) -> MAX (x, y) when C <= lower_bound (y),
+ because in both cases the guarded arm equals the min/max expression. */
+(for minmax (min max)
+ (simplify
+ (cond (eq @0 INTEGER_CST@1) @2 (minmax:c@3 @0 @2))
+ (if (INTEGRAL_TYPE_P (type))
+ (with {
+ int_range_max r;
+ if (!gimple_match_range_of_expr (r, @2, @2))
+ r.set_varying (TREE_TYPE (@2));
+ wide_int bound;
+ if (minmax == MIN_EXPR)
+ bound = r.upper_bound ();
+ else
+ bound = r.lower_bound ();
+ }
+ (if ((minmax == MIN_EXPR
+ && wi::ge_p (wi::to_wide (@1), bound, TYPE_SIGN (type)))
+ || (minmax == MAX_EXPR
+ && wi::le_p (wi::to_wide (@1), bound, TYPE_SIGN (type))))
+ @3)))))
+#endif
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..a203fdb01189c
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/pr125700-int-width.c
@@ -0,0 +1,51 @@
+/* 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..2cfa280a138b8
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/pr125700-negative.c
@@ -0,0 +1,70 @@
+/* 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;
+}
+
+/* Unsigned char widened to unsigned int. */
+unsigned
+fumin_range_negative (unsigned char a, unsigned int b)
+{
+ unsigned aa = a;
+ if (aa == 255)
+ return b;
+ return aa < b ? aa : b;
+}
+
+/* Signed char widened to int. */
+int
+fsmin_range_negative (signed char a, signed int b)
+{
+ int aa = a;
+ if (aa == 127)
+ return b;
+ return aa < b ? aa : b;
+}
+
+int
+fsmax_range_negative (signed char a, signed int b)
+{
+ int aa = a;
+ if (aa == -128)
+ return b;
+ return aa > b ? aa : b;
+}
+
+/* None of the if and '==' comparisons should be eliminated. */
+/* { dg-final { scan-tree-dump-times {if \(} 7 "optimized" } } */
+/* { dg-final { scan-tree-dump-times " == " 7 "optimized" } } */
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr125700-range.c
b/gcc/testsuite/gcc.dg/tree-ssa/pr125700-range.c
new file mode 100644
index 0000000000000..d474162d5ceb0
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/pr125700-range.c
@@ -0,0 +1,144 @@
+/* PR tree-optimization/125700 */
+/* Test that the optimization fires using Ranger-derived value ranges,
+ including ranges from widened types and range-limiting operations. */
+
+/* { dg-do compile } */
+/* { dg-options "-O1 -fdump-tree-optimized" } */
+
+/* Unsigned char widened to unsigned int. */
+unsigned
+fumin_char_range (unsigned char a, unsigned char b)
+{
+ unsigned aa = a;
+ unsigned bb = b;
+ if (aa == 255)
+ return bb;
+ return aa < bb ? aa : bb;
+}
+
+unsigned
+fumax_char_range (unsigned char a, unsigned char b)
+{
+ unsigned aa = a;
+ unsigned bb = b;
+ if (aa == 0)
+ return bb;
+ return aa > bb ? aa : bb;
+}
+
+/* Signed char widened to int. */
+int
+fsmin_char_range (signed char a, signed char b)
+{
+ int aa = a;
+ int bb = b;
+ if (aa == 127)
+ return bb;
+ return aa < bb ? aa : bb;
+}
+
+int
+fsmax_char_range (signed char a, signed char b)
+{
+ int aa = a;
+ int bb = b;
+ if (aa == -128)
+ return bb;
+ return aa > bb ? aa : bb;
+}
+
+/* C is strictly above the upper bound of y's value range for MIN,
+ and strictly below the lower bound for MAX. */
+unsigned
+fumin_range_above_bound (unsigned x, unsigned y)
+{
+ if (y > 100)
+ y = 100;
+ if (x == 120)
+ return y;
+ return x < y ? x : y;
+}
+
+unsigned
+fumax_range_below_bound (unsigned x, unsigned y)
+{
+ y &= 127;
+ if (y < 27)
+ y = 27;
+ if (x == 10)
+ return y;
+ return x > y ? x : y;
+}
+
+int
+fsmin_range_above_bound (int x, int y)
+{
+ y &= 127;
+ if (y > 100)
+ y = 100;
+ if (x == 120)
+ return y;
+ return x < y ? x : y;
+}
+
+int
+fsmax_range_below_bound (int x, int y)
+{
+ y &= 127;
+ if (y < 27)
+ y = 27;
+ if (x == 10)
+ return y;
+ return x > y ? x : y;
+}
+
+/* C is equal to the upper bound of y's value range for MIN,
+ and equal to the lower bound for MAX. */
+unsigned
+fumin_range_at_bound (unsigned x, unsigned y)
+{
+ y &= 127;
+ if (y > 100)
+ y = 100;
+ if (x == 100)
+ return y;
+ return x < y ? x : y;
+}
+
+unsigned
+fumax_range_at_bound (unsigned x, unsigned y)
+{
+ y &= 127;
+ if (y < 27)
+ y = 27;
+ if (x == 27)
+ return y;
+ return x > y ? x : y;
+}
+
+int
+fsmin_range_at_bound (int x, int y)
+{
+ y &= 127;
+ if (y > 100)
+ y = 100;
+ if (x == 100)
+ return y;
+ return x < y ? x : y;
+}
+
+int
+fsmax_range_at_bound (int x, int y)
+{
+ y &= 127;
+ if (y < 27)
+ y = 27;
+ if (x == 27)
+ return y;
+ return x > y ? x : y;
+}
+
+/* { dg-final { scan-tree-dump-not {if \(} "optimized" } } */
+/* { dg-final { scan-tree-dump-not " == " "optimized" } } */
+/* { dg-final { scan-tree-dump-times "MIN_EXPR" 10 "optimized" } } */
+/* { dg-final { scan-tree-dump-times "MAX_EXPR" 10 "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..397c72544355b
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/pr125700.c
@@ -0,0 +1,117 @@
+/* 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" } */
+
+/* Base test cases. */
+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;
+}
+
+/* Conditional operator variants. */
+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;
+}
+
+/* Commutativity tests for min/max operator. */
+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" } } */
Range-diff against v1:
1: 4d042112a6061 ! 1: 7e709962d4f3c match: Simplify type-bound guarded
min/max expressions [PR125700]
@@ Metadata
Author: Samarth Tandale <[email protected]>
## Commit message ##
- match: Simplify type-bound guarded min/max expressions [PR125700]
+ match: Simplify value-range guarded min/max expressions [PR125700]
- 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)
+ The pattern:
- 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)
+ x == C ? y : min (x, y)
- This adds a combined match.pd pattern for MIN_EXPR and MAX_EXPR.
+ can be simplified to min (x, y) whenever C >= upper_bound (y),
+ because min (C, y) == y for all values y can take. Similarly:
+
+ x == C ? y : max (x, y)
+
+ can be simplified to max (x, y) whenever C <= lower_bound (y).
+
+ Use ranger to query the value range of y and check the bound condition.
PR tree-optimization/125700
gcc/ChangeLog:
-
- * match.pd: Fold type-bound guarded min/max expressions.
+ PR tree-optimization/125700
+ * match.pd ((x == C) ? y : MIN/MAX (x, y)): New simplification.
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.
+ * gcc.dg/tree-ssa/pr125700-range.c: New test.
Signed-off-by: Samarth Tandale <[email protected]>
@@ gcc/match.pd: and,
(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. */
++#if GIMPLE
++/* Replace (x == C) ? y : MIN (x, y) -> MIN (x, y) when C >= upper_bound
(y),
++ and (x == C) ? y : MAX (x, y) -> MAX (x, y) when C <= lower_bound (y),
++ because in both cases the guarded arm equals the min/max expression.
*/
+(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);
++ int_range_max r;
++ if (!gimple_match_range_of_expr (r, @2, @2))
++ r.set_varying (TREE_TYPE (@2));
++ wide_int bound;
++ if (minmax == MIN_EXPR)
++ bound = r.upper_bound ();
++ else
++ bound = r.lower_bound ();
+ }
-+ (if (bound && tree_int_cst_equal (@1, bound))
-+ @3)))))
++ (if ((minmax == MIN_EXPR
++ && wi::ge_p (wi::to_wide (@1), bound, TYPE_SIGN (type)))
++ || (minmax == MAX_EXPR
++ && wi::le_p (wi::to_wide (@1), bound, TYPE_SIGN (type))))
++ @3)))))
++#endif
## gcc/testsuite/gcc.dg/tree-ssa/pr125700-int-width.c (new) ##
@@
+/* PR tree-optimization/125700 */
-+/* Integer width variants to cover non-int widths and
-+ both signed/unsigned. */
++/* Integer width variants to cover non-int widths and both
signed/unsigned. */
+
+/* { dg-do compile } */
+/* { dg-options "-O1 -fdump-tree-optimized" } */
@@ gcc/testsuite/gcc.dg/tree-ssa/pr125700-int-width.c (new)
+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 {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" } } */
@@ gcc/testsuite/gcc.dg/tree-ssa/pr125700-negative.c (new)
+ return x > y ? x : y;
+}
+
++/* Unsigned char widened to unsigned int. */
++unsigned
++fumin_range_negative (unsigned char a, unsigned int b)
++{
++ unsigned aa = a;
++ if (aa == 255)
++ return b;
++ return aa < b ? aa : b;
++}
++
++/* Signed char widened to int. */
++int
++fsmin_range_negative (signed char a, signed int b)
++{
++ int aa = a;
++ if (aa == 127)
++ return b;
++ return aa < b ? aa : b;
++}
++
++int
++fsmax_range_negative (signed char a, signed int b)
++{
++ int aa = a;
++ if (aa == -128)
++ return b;
++ return aa > b ? aa : b;
++}
++
+/* 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" } } */
++/* { dg-final { scan-tree-dump-times {if \(} 7 "optimized" } } */
++/* { dg-final { scan-tree-dump-times " == " 7 "optimized" } } */
+
+ ## gcc/testsuite/gcc.dg/tree-ssa/pr125700-range.c (new) ##
+@@
++/* PR tree-optimization/125700 */
++/* Test that the optimization fires using Ranger-derived value ranges,
++ including ranges from widened types and range-limiting operations. */
++
++/* { dg-do compile } */
++/* { dg-options "-O1 -fdump-tree-optimized" } */
++
++/* Unsigned char widened to unsigned int. */
++unsigned
++fumin_char_range (unsigned char a, unsigned char b)
++{
++ unsigned aa = a;
++ unsigned bb = b;
++ if (aa == 255)
++ return bb;
++ return aa < bb ? aa : bb;
++}
++
++unsigned
++fumax_char_range (unsigned char a, unsigned char b)
++{
++ unsigned aa = a;
++ unsigned bb = b;
++ if (aa == 0)
++ return bb;
++ return aa > bb ? aa : bb;
++}
++
++/* Signed char widened to int. */
++int
++fsmin_char_range (signed char a, signed char b)
++{
++ int aa = a;
++ int bb = b;
++ if (aa == 127)
++ return bb;
++ return aa < bb ? aa : bb;
++}
++
++int
++fsmax_char_range (signed char a, signed char b)
++{
++ int aa = a;
++ int bb = b;
++ if (aa == -128)
++ return bb;
++ return aa > bb ? aa : bb;
++}
++
++/* C is strictly above the upper bound of y's value range for MIN,
++ and strictly below the lower bound for MAX. */
++unsigned
++fumin_range_above_bound (unsigned x, unsigned y)
++{
++ if (y > 100)
++ y = 100;
++ if (x == 120)
++ return y;
++ return x < y ? x : y;
++}
++
++unsigned
++fumax_range_below_bound (unsigned x, unsigned y)
++{
++ y &= 127;
++ if (y < 27)
++ y = 27;
++ if (x == 10)
++ return y;
++ return x > y ? x : y;
++}
++
++int
++fsmin_range_above_bound (int x, int y)
++{
++ y &= 127;
++ if (y > 100)
++ y = 100;
++ if (x == 120)
++ return y;
++ return x < y ? x : y;
++}
++
++int
++fsmax_range_below_bound (int x, int y)
++{
++ y &= 127;
++ if (y < 27)
++ y = 27;
++ if (x == 10)
++ return y;
++ return x > y ? x : y;
++}
++
++/* C is equal to the upper bound of y's value range for MIN,
++ and equal to the lower bound for MAX. */
++unsigned
++fumin_range_at_bound (unsigned x, unsigned y)
++{
++ y &= 127;
++ if (y > 100)
++ y = 100;
++ if (x == 100)
++ return y;
++ return x < y ? x : y;
++}
++
++unsigned
++fumax_range_at_bound (unsigned x, unsigned y)
++{
++ y &= 127;
++ if (y < 27)
++ y = 27;
++ if (x == 27)
++ return y;
++ return x > y ? x : y;
++}
++
++int
++fsmin_range_at_bound (int x, int y)
++{
++ y &= 127;
++ if (y > 100)
++ y = 100;
++ if (x == 100)
++ return y;
++ return x < y ? x : y;
++}
++
++int
++fsmax_range_at_bound (int x, int y)
++{
++ y &= 127;
++ if (y < 27)
++ y = 27;
++ if (x == 27)
++ return y;
++ return x > y ? x : y;
++}
++
++/* { dg-final { scan-tree-dump-not {if \(} "optimized" } } */
++/* { dg-final { scan-tree-dump-not " == " "optimized" } } */
++/* { dg-final { scan-tree-dump-times "MIN_EXPR" 10 "optimized" } } */
++/* { dg-final { scan-tree-dump-times "MAX_EXPR" 10 "optimized" } } */
## gcc/testsuite/gcc.dg/tree-ssa/pr125700.c (new) ##
@@
@@ gcc/testsuite/gcc.dg/tree-ssa/pr125700.c (new)
+/* { dg-do compile } */
+/* { dg-options "-O1 -fdump-tree-optimized" } */
+
++/* Base test cases. */
+unsigned
+fumin (unsigned x, unsigned y)
+{
@@ gcc/testsuite/gcc.dg/tree-ssa/pr125700.c (new)
+ return x > y ? x : y;
+}
+
++/* Conditional operator variants. */
+unsigned
+fumin_ne (unsigned x, unsigned y)
+{
@@ gcc/testsuite/gcc.dg/tree-ssa/pr125700.c (new)
+ return x > y ? x : y;
+}
+
++/* Commutativity tests for min/max operator. */
+unsigned
+fumin_flip (unsigned x, unsigned y)
+{
@@ gcc/testsuite/gcc.dg/tree-ssa/pr125700.c (new)
+
+/* 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 {if \(} "optimized" } } */
+/* { dg-final { scan-tree-dump-not " == " "optimized" } } */
+/* { dg-final { scan-tree-dump-not " != " "optimized" } } */
+/* { dg-final { scan-tree-dump-not " <= " "optimized" } } */
--
2.54.0