From 07800a565abd20814468a4f84a988e0d95bf30b5 Mon Sep 17 00:00:00 2001 From: Andrew Pinski Date: Mon, 20 Oct 2025 15:48:43 -0700 Subject: [PATCH] match: Add support for convert `((signed)x) < 0` to `x >= (unsigned)SIGNED_TYPE_MIN` while detecting min/max [PR110068] This copies the optimization which was done to fix PR 95699 to match detection of MIN/MAX from minmax_replacement to match. This is another step in getting rid of minmax_replacement in phiopt. There are still a few more min/max detections that needs to be handled before the removal. pr101024-1.c adds one example of that but since the testcase currently passes I didn't xfail it. pr110068-1.c adds a testcase which was not detected beforehand either. Changes since v1: * v2: Fix comment about how it is transformed. Use SIGNED_TYPE_MIN everywhere instead of mxing in SIGNED_TYPE_MAX too. Bootstrapped and tested on x86_64-linux-gnu. PR tree-optimization/95699 PR tree-optimization/101024 PR tree-optimization/110068 gcc/ChangeLog: * match.pd (`(type1)x CMP CST1 ? (type2)x : CST2`): Treat `(signed)x = 0` as `x >=/< SIGNED_TYPE_MIN` gcc/testsuite/ChangeLog: * gcc.dg/tree-ssa/pr101024-1.c: New test. * gcc.dg/tree-ssa/pr110068-1.c: New test. Signed-off-by: Andrew Pinski --- gcc/match.pd | 21 ++++++++++-- gcc/testsuite/gcc.dg/tree-ssa/pr101024-1.c | 39 ++++++++++++++++++++++ gcc/testsuite/gcc.dg/tree-ssa/pr110068-1.c | 22 ++++++++++++ 3 files changed, 80 insertions(+), 2 deletions(-) create mode 100644 gcc/testsuite/gcc.dg/tree-ssa/pr101024-1.c create mode 100644 gcc/testsuite/gcc.dg/tree-ssa/pr110068-1.c diff --git a/gcc/match.pd b/gcc/match.pd index bfc51e6579a..a4248a521cf 100644 --- a/gcc/match.pd +++ b/gcc/match.pd @@ -6571,6 +6571,23 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT) tree from_type = TREE_TYPE (@1); tree c1_type = TREE_TYPE (@3), c2_type = TREE_TYPE (@2); enum tree_code code = ERROR_MARK; + enum tree_code ncmp = cmp; + tree c1 = @3; + + /* `((signed)a) < 0` should be converted back into + `a >= (unsigned)SIGNED_TYPE_MIN`. + `((signed)a) >= 0` should be converted back into + `a < (unsigned)SIGNED_TYPE_MIN`. */ + if (integer_zerop (c1) + && (cmp == GE_EXPR || cmp == LT_EXPR) + && TYPE_UNSIGNED (from_type) + && !TYPE_UNSIGNED (c1_type) + && TYPE_PRECISION (from_type) == TYPE_PRECISION (c1_type)) + { + ncmp = cmp == GE_EXPR ? LT_EXPR : GE_EXPR; + c1 = fold_convert (from_type, TYPE_MIN_VALUE (c1_type)); + c1_type = from_type; + } if (INTEGRAL_TYPE_P (from_type) && int_fits_type_p (@2, from_type) @@ -6583,8 +6600,8 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT) && (TYPE_UNSIGNED (from_type) || TYPE_SIGN (c2_type) == TYPE_SIGN (from_type))))) { - if (cmp != EQ_EXPR) - code = minmax_from_comparison (cmp, @1, @3, @1, @2); + if (ncmp != EQ_EXPR) + code = minmax_from_comparison (ncmp, @1, c1, @1, @2); /* Can do A == C1 ? A : C2 -> A == C1 ? C1 : C2? */ else if (int_fits_type_p (@3, from_type)) code = EQ_EXPR; diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr101024-1.c b/gcc/testsuite/gcc.dg/tree-ssa/pr101024-1.c new file mode 100644 index 00000000000..14379bf3b6a --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/pr101024-1.c @@ -0,0 +1,39 @@ +/* PR tree-optimization/95699 */ +/* PR tree-optimization/101024 */ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-optimized -fdump-tree-phiopt1" } */ +unsigned long long +f2 (unsigned long long x) +{ + if (x < 0x8000000000000000ULL) + x = 0x8000000000000000ULL; + else + { + if (x >= 0x8000000000000023ULL) + x = 0x8000000000000023ULL; + } + return x; +} +unsigned long long +f1 (unsigned long long x) +{ + if (x >= 100) + { + if (x >= 0x8000000000000000ULL) + x = 0x8000000000000000ULL; + } + else + x = 100; + return x; +} +/* f2: */ +/* { dg-final { scan-tree-dump "MIN_EXPR <\[^>\n\r]*9223372036854775843>" "optimized" } } */ +/* { dg-final { scan-tree-dump "MAX_EXPR <\[^>\n\r]*9223372036854775808>" "optimized" } } */ +/* { dg-final { scan-tree-dump "MIN_EXPR <\[^>\n\r]*9223372036854775843>" "phiopt1" } } */ +/* { dg-final { scan-tree-dump "MAX_EXPR <\[^>\n\r]*9223372036854775808>" "phiopt1" } } */ + +/* f1: */ +/* { dg-final { scan-tree-dump "MIN_EXPR <\[^>\n\r]*9223372036854775808>" "optimized" } } */ +/* { dg-final { scan-tree-dump "MAX_EXPR <\[^>\n\r]*100>" "optimized" } } */ +/* { dg-final { scan-tree-dump "MIN_EXPR <\[^>\n\r]*9223372036854775808>" "phiopt1" } } */ +/* { dg-final { scan-tree-dump "MAX_EXPR <\[^>\n\r]*100>" "phiopt1" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr110068-1.c b/gcc/testsuite/gcc.dg/tree-ssa/pr110068-1.c new file mode 100644 index 00000000000..df88553474c --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/pr110068-1.c @@ -0,0 +1,22 @@ +/* PR tree-optimization/95699 */ +/* PR tree-optimization/110068 */ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-optimized -fdump-tree-phiopt1" } */ +/* { dg-final { scan-tree-dump-times "MIN_EXPR " 2 "phiopt1" } } */ + +#define min1(x,y) ((x) < (y) ? (x) : (y)) +unsigned +f1 (unsigned x) +{ + return min1(x, 1U<<(sizeof(x)*8-1)); +} +unsigned +f5 (unsigned x) +{ + bool t = x >= 1U<<(sizeof(x)*8-1); + if (!t) + ; + else + x = 1U<<(sizeof(x)*8-1); + return x; +} -- 2.47.3