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 <andrew.pinski@oss.qualcomm.com>
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)
&& (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;
--- /dev/null
+/* 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" } } */
--- /dev/null
+/* 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;
+}