]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
match: improve handling of `((signed)x) < 0` to `x >= (unsigned)SIGNED_TYPE_MIN`...
authorAndrew Pinski <andrew.pinski@oss.qualcomm.com>
Wed, 22 Oct 2025 22:46:03 +0000 (15:46 -0700)
committerAndrew Pinski <andrew.pinski@oss.qualcomm.com>
Thu, 23 Oct 2025 16:10:04 +0000 (09:10 -0700)
This is a follow on r16-4534-g07800a565abd20 based on the review of
the other pattern (https://gcc.gnu.org/pipermail/gcc-patches/2025-October/698336.html)
as the same issue mentioned in that review apply here.

This changes to use the new version of minmax_from_comparison so we don't need to create
a tree for the constant. and use wi::mask instead of TYPE_MIN_VALUE.

gcc/ChangeLog:

* match.pd (`(type1)x CMP CST1 ? (type2)x : CST2`): Better handling
of `((signed)x) < 0`.

Signed-off-by: Andrew Pinski <andrew.pinski@oss.qualcomm.com>
gcc/match.pd

index d00b925416ae38184f7ca315cbe02328e3e377e0..4c05fe2c1a6dd4d4056534ffaadac51bb0faaf21 100644 (file)
@@ -6592,25 +6592,30 @@ 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)
+     if (integer_zerop (@3)
+         && INTEGRAL_TYPE_P (from_type)
          && (cmp == GE_EXPR || cmp == LT_EXPR)
         && TYPE_UNSIGNED (from_type)
         && !TYPE_UNSIGNED (c1_type)
-        && TYPE_PRECISION (from_type) == TYPE_PRECISION (c1_type))
+        && TYPE_PRECISION (from_type) == TYPE_PRECISION (c1_type)
+        && int_fits_type_p (@2, from_type)
+        && (types_match (c2_type, from_type)
+            || (TYPE_PRECISION (c2_type) > TYPE_PRECISION (from_type)
+                && (TYPE_UNSIGNED (from_type)
+                    || TYPE_SIGN (c2_type) == TYPE_SIGN (from_type)))))
        {
-         ncmp = cmp == GE_EXPR ? LT_EXPR : GE_EXPR;
-         c1 = fold_convert (from_type, TYPE_MIN_VALUE (c1_type));
-         c1_type = from_type;
+         tree_code ncmp = cmp == GE_EXPR ? LE_EXPR : GT_EXPR;
+         widest_int c1 = wi::mask<widest_int>(TYPE_PRECISION (type) - 1, 0);
+         code = minmax_from_comparison (ncmp, @1, c1, wi::to_widest (@2));
        }
 
-     if (INTEGRAL_TYPE_P (from_type)
+     if (code == ERROR_MARK
+         && INTEGRAL_TYPE_P (from_type)
         && int_fits_type_p (@2, from_type)
         && (types_match (c1_type, from_type)
             || (TYPE_PRECISION (c1_type) > TYPE_PRECISION (from_type)
@@ -6621,8 +6626,8 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
                 && (TYPE_UNSIGNED (from_type)
                     || TYPE_SIGN (c2_type) == TYPE_SIGN (from_type)))))
        {
-        if (ncmp != EQ_EXPR)
-          code = minmax_from_comparison (ncmp, @1, c1, @1, @2);
+        if (cmp != EQ_EXPR)
+          code = minmax_from_comparison (cmp, @1, @3, @1, @2);
         /* Can do A == C1 ? A : C2  ->  A == C1 ? C1 : C2?  */
         else if (int_fits_type_p (@3, from_type))
           code = EQ_EXPR;