This is the last patch that is needed to support to remove minmax_replacement.
This fixes pr101024-1.c which is failing when minmax_replacement is removed.

This next patch will remove it.

Changes since v1:
* v2: Add new version of minmax_from_comparison that takes widest_int.
      Constraint the pattern to constant integers in some cases.
      Use mask to create the SIGNED_MAX and use GT/LE instead.
      Use wi::le_p/wi::ge_p instead of fold_build to do the comparison.

gcc/ChangeLog:

        PR tree-optimization/101024
        * fold-const.cc (minmax_from_comparison): New version that takes 
widest_int
        instead of tree.
        (minmax_from_comparison):  Call minmax_from_comparison for integer cst 
case.
        * fold-const.h (minmax_from_comparison):
        * match.pd (`((signed)a </>= 0) ? min/max (a, c) : b`): New pattern.

Signed-off-by: Andrew Pinski <[email protected]>
---
 gcc/fold-const.cc | 123 ++++++++++++++++++++++++++--------------------
 gcc/fold-const.h  |   3 ++
 gcc/match.pd      |  29 +++++++++++
 3 files changed, 101 insertions(+), 54 deletions(-)

diff --git a/gcc/fold-const.cc b/gcc/fold-const.cc
index e8cfee81553..1311c6ed7de 100644
--- a/gcc/fold-const.cc
+++ b/gcc/fold-const.cc
@@ -150,75 +150,90 @@ static tree fold_convert_const (enum tree_code, tree, 
tree);
 static tree fold_view_convert_expr (tree, tree);
 static tree fold_negate_expr (location_t, tree);
 
+/* This is a helper function to detect min/max for some operands of COND_EXPR.
+   The form is "(exp0 CMP cst1) ? exp0 : cst2". */
+tree_code
+minmax_from_comparison (tree_code cmp, tree exp0,
+                       const widest_int cst1,
+                       const widest_int cst2)
+{
+  if (cst1 == cst2)
+    {
+      if (cmp == LE_EXPR || cmp == LT_EXPR)
+       return MIN_EXPR;
+      if (cmp == GT_EXPR || cmp == GE_EXPR)
+       return MAX_EXPR;
+    }
+  if (cst1 == cst2 - 1)
+    {
+      /* X <= Y - 1 equals to X < Y.  */
+      if (cmp == LE_EXPR)
+       return MIN_EXPR;
+      /* X > Y - 1 equals to X >= Y.  */
+      if (cmp == GT_EXPR)
+       return MAX_EXPR;
+      /* a != MIN_RANGE<a> ? a : MIN_RANGE<a>+1 -> MAX_EXPR<MIN_RANGE<a>+1, a> 
*/
+      if (cmp == NE_EXPR && TREE_CODE (exp0) == SSA_NAME)
+       {
+         int_range_max r;
+         get_range_query (cfun)->range_of_expr (r, exp0);
+         if (r.undefined_p ())
+           r.set_varying (TREE_TYPE (exp0));
+
+         widest_int min = widest_int::from (r.lower_bound (),
+                                            TYPE_SIGN (TREE_TYPE (exp0)));
+         if (min == cst1)
+           return MAX_EXPR;
+       }
+  }
+  if (cst1 == cst2 + 1)
+    {
+      /* X < Y + 1 equals to X <= Y.  */
+      if (cmp == LT_EXPR)
+        return MIN_EXPR;
+      /* X >= Y + 1 equals to X > Y.  */
+      if (cmp == GE_EXPR)
+       return MAX_EXPR;
+      /* a != MAX_RANGE<a> ? a : MAX_RANGE<a>-1 -> MIN_EXPR<MIN_RANGE<a>-1, a> 
*/
+      if (cmp == NE_EXPR && TREE_CODE (exp0) == SSA_NAME)
+       {
+         int_range_max r;
+         get_range_query (cfun)->range_of_expr (r, exp0);
+         if (r.undefined_p ())
+           r.set_varying (TREE_TYPE (exp0));
+
+         widest_int max = widest_int::from (r.upper_bound (),
+                                            TYPE_SIGN (TREE_TYPE (exp0)));
+         if (max == cst1)
+           return MIN_EXPR;
+       }
+    }
+  return ERROR_MARK;
+}
+       
+       
 /* This is a helper function to detect min/max for some operands of COND_EXPR.
    The form is "(EXP0 CMP EXP1) ? EXP2 : EXP3". */
 tree_code
 minmax_from_comparison (tree_code cmp, tree exp0, tree exp1, tree exp2, tree 
exp3)
 {
-  enum tree_code code = ERROR_MARK;
-
   if (HONOR_NANS (exp0) || HONOR_SIGNED_ZEROS (exp0))
     return ERROR_MARK;
 
   if (!operand_equal_p (exp0, exp2))
     return ERROR_MARK;
 
-  if (TREE_CODE (exp3) == INTEGER_CST && TREE_CODE (exp1) == INTEGER_CST)
-    {
-      if (wi::to_widest (exp1) == (wi::to_widest (exp3) - 1))
-       {
-         /* X <= Y - 1 equals to X < Y.  */
-         if (cmp == LE_EXPR)
-           code = LT_EXPR;
-         /* X > Y - 1 equals to X >= Y.  */
-         if (cmp == GT_EXPR)
-           code = GE_EXPR;
-         /* a != MIN_RANGE<a> ? a : MIN_RANGE<a>+1 -> MAX_EXPR<MIN_RANGE<a>+1, 
a> */
-         if (cmp == NE_EXPR && TREE_CODE (exp0) == SSA_NAME)
-           {
-             int_range_max r;
-             get_range_query (cfun)->range_of_expr (r, exp0);
-             if (r.undefined_p ())
-               r.set_varying (TREE_TYPE (exp0));
-
-             widest_int min = widest_int::from (r.lower_bound (),
-                                                TYPE_SIGN (TREE_TYPE (exp0)));
-             if (min == wi::to_widest (exp1))
-               code = MAX_EXPR;
-           }
-       }
-      if (wi::to_widest (exp1) == (wi::to_widest (exp3) + 1))
-       {
-         /* X < Y + 1 equals to X <= Y.  */
-         if (cmp == LT_EXPR)
-           code = LE_EXPR;
-         /* X >= Y + 1 equals to X > Y.  */
-         if (cmp == GE_EXPR)
-         code = GT_EXPR;
-         /* a != MAX_RANGE<a> ? a : MAX_RANGE<a>-1 -> MIN_EXPR<MIN_RANGE<a>-1, 
a> */
-         if (cmp == NE_EXPR && TREE_CODE (exp0) == SSA_NAME)
-           {
-             int_range_max r;
-             get_range_query (cfun)->range_of_expr (r, exp0);
-             if (r.undefined_p ())
-               r.set_varying (TREE_TYPE (exp0));
-
-             widest_int max = widest_int::from (r.upper_bound (),
-                                                TYPE_SIGN (TREE_TYPE (exp0)));
-             if (max == wi::to_widest (exp1))
-               code = MIN_EXPR;
-           }
-       }
-    }
-  if (code != ERROR_MARK
-      || operand_equal_p (exp1, exp3))
+  if (operand_equal_p (exp1, exp3))
     {
       if (cmp == LT_EXPR || cmp == LE_EXPR)
-       code = MIN_EXPR;
+       return MIN_EXPR;
       if (cmp == GT_EXPR || cmp == GE_EXPR)
-       code = MAX_EXPR;
+       return MAX_EXPR;
     }
-  return code;
+  if (TREE_CODE (exp3) == INTEGER_CST
+      && TREE_CODE (exp1) == INTEGER_CST)
+    return minmax_from_comparison (cmp, exp0, wi::to_widest (exp1), 
wi::to_widest (exp3));
+  return ERROR_MARK;
 }
 
 /* Return EXPR_LOCATION of T if it is not UNKNOWN_LOCATION.
diff --git a/gcc/fold-const.h b/gcc/fold-const.h
index e95cf48c176..00975dcddd6 100644
--- a/gcc/fold-const.h
+++ b/gcc/fold-const.h
@@ -254,6 +254,9 @@ extern tree fold_build_pointer_plus_hwi_loc (location_t 
loc, tree ptr, HOST_WIDE
 #define fold_build_pointer_plus_hwi(p,o) \
        fold_build_pointer_plus_hwi_loc (UNKNOWN_LOCATION, p, o)
 
+extern tree_code minmax_from_comparison (tree_code, tree,
+                                        const widest_int,
+                                        const widest_int);
 extern tree_code minmax_from_comparison (tree_code, tree, tree,
                                         tree, tree);
 
diff --git a/gcc/match.pd b/gcc/match.pd
index a4248a521cf..cbf03512b71 100644
--- a/gcc/match.pd
+++ b/gcc/match.pd
@@ -6911,6 +6911,35 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
           && integer_nonzerop (fold_build2 (GE_EXPR, boolean_type_node, @3, 
@4)))
       (max @2 @4))))))
 
+/* Optimize (((signed)a CMP 0) ? max<a,CST2> : CST3 */
+(for cmp    (lt  ge)
+     minmax (min max)
+ (simplify
+  (cond (cmp:c (nop_convert @0) integer_zerop@1) (minmax@2 @0 INTEGER_CST@3) 
INTEGER_CST@4)
+   (if (!TYPE_UNSIGNED (TREE_TYPE (@1))
+        && TYPE_UNSIGNED (TREE_TYPE (@0)))
+    (with
+     {
+       tree_code code;
+       /* ((signed)a) < 0 -> a > SIGNED_MAX */
+       /* ((signed)a) >= 0 -> a <= SIGNED_MAX */
+       widest_int c1 = wi::mask<widest_int>(TYPE_PRECISION (type) - 1, 0);
+       tree_code ncmp = cmp == GE_EXPR ? LE_EXPR : GT_EXPR;
+       code = minmax_from_comparison (ncmp, @0, c1, wi::to_widest (@4));
+     }
+     (if (ncmp == LE_EXPR
+         && code == MIN_EXPR
+         && wi::le_p (wi::to_wide (@3),
+                      wi::to_wide (@4),
+                      TYPE_SIGN (type)))
+      (min @2 @4)
+      (if (ncmp == GT_EXPR
+          && code == MAX_EXPR
+          && wi::ge_p (wi::to_wide (@3),
+                       wi::to_wide (@4),
+                       TYPE_SIGN (type)))
+       (max @2 @4)))))))
+
 #if GIMPLE
 /* These patterns should be after min/max detection as simplifications
    of `(type)(zero_one ==/!= 0)` to `(type)(zero_one)`
-- 
2.43.0

Reply via email to