https://gcc.gnu.org/g:02142e21d98b0f9a70a5fe3fb636d38c01c466d3

commit r16-4066-g02142e21d98b0f9a70a5fe3fb636d38c01c466d3
Author: Pan Li <[email protected]>
Date:   Fri Sep 19 14:54:47 2025 +0800

    Match: Add form 5 of unsigned SAT_MUL for mul
    
    This patch would like to try to match the the unsigned
    SAT_MUL form 5, aka below:
    
      #define DEF_SAT_U_MUL_FMT_5(NT, WT)             \
      NT __attribute__((noinline))                    \
      sat_u_mul_##NT##_from_##WT##_fmt_5 (NT a, NT b) \
      {                                               \
        WT x = (WT)a * (WT)b;                         \
        NT hi = x >> (sizeof(NT) * 8);                \
        NT lo = (NT)x;                                \
        return lo | -!!hi;                            \
      }
    
      while WT is uint16_t, uint32_t and uint64_t.
      and T is uint8_t, uint16_t, uint32_t.
    
    gcc/ChangeLog:
    
            * match.pd: Add pattern of mult and reuse the widen-mul
            by for keyword.
    
    Signed-off-by: Pan Li <[email protected]>

Diff:
---
 gcc/match.pd | 55 ++++++++++++++++++++++++++++++-------------------------
 1 file changed, 30 insertions(+), 25 deletions(-)

diff --git a/gcc/match.pd b/gcc/match.pd
index 2e629fd31cea..b3fd26e18ddd 100644
--- a/gcc/match.pd
+++ b/gcc/match.pd
@@ -3695,31 +3695,36 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
       bool c2_is_type_precision_p = c2 == prec;
      }
      (if (widen_prec > prec && c2_is_type_precision_p && c4_is_max_p)))))
-  (match (unsigned_integer_sat_mul @0 @1)
-   /* SAT_U_MUL (X, Y) = {
-       WT x = (WT)a * (WT)b;
-       NT hi = x >> (sizeof(NT) * 8);
-       NT lo = (NT)x;
-       return lo | -!!hi;
-      } while WT is uint128_t, T is uint8_t, uint16_t, uint32_t or uint64_t.  
*/
-   (convert1?
-    (bit_ior (convert? (negate (convert (ne (convert (rshift @3 INTEGER_CST@2))
-                                           integer_zerop))))
-            (convert (widen_mult:c@3 (convert@4 @0)
-                                     (convert@5 @1)))))
-   (if (types_match (type, @0, @1))
-    (with
-     {
-      unsigned widen_prec = TYPE_PRECISION (TREE_TYPE (@3));
-      unsigned cvt4_prec = TYPE_PRECISION (TREE_TYPE (@4));
-      unsigned cvt5_prec = TYPE_PRECISION (TREE_TYPE (@5));
-      bool widen_mult_p = cvt4_prec == cvt5_prec && widen_prec == cvt5_prec * 
2;
-
-      unsigned c2 = tree_to_uhwi (@2);
-      unsigned prec = TYPE_PRECISION (type);
-      bool c2_is_type_precision_p = c2 == prec;
-     }
-     (if (widen_mult_p && c2_is_type_precision_p)))))
+  (for mult_op (mult widen_mult)
+   (match (unsigned_integer_sat_mul @0 @1)
+    /* SAT_U_MUL (X, Y) = {
+        WT x = (WT)a * (WT)b;
+        NT hi = x >> (sizeof(NT) * 8);
+         NT lo = (NT)x;
+         return lo | -!!hi;
+       } while WT is uint128_t, uint64_t, uint32_t, uint16_t,
+         and T is uint64_t, uint32_t, uint16_t, uint8_t.  */
+    (convert1?
+     (bit_ior
+      (convert?
+       (negate
+       (convert (ne (convert2? (rshift @3 INTEGER_CST@2)) integer_zerop))))
+      (convert (mult_op:c@3 (convert@4 @0) (convert@5 @1)))))
+    (if (types_match (type, @0, @1))
+     (with
+      {
+       unsigned prec = TYPE_PRECISION (type);
+       unsigned widen_prec = TYPE_PRECISION (TREE_TYPE (@3));
+       unsigned cvt4_prec = TYPE_PRECISION (TREE_TYPE (@4));
+       unsigned cvt5_prec = TYPE_PRECISION (TREE_TYPE (@5));
+
+       bool widen_mult_p = mult_op == WIDEN_MULT_EXPR && cvt4_prec == cvt5_prec
+        && widen_prec == cvt5_prec * 2;
+       bool mult_p = mult_op == MULT_EXPR && cvt4_prec == cvt5_prec
+        && cvt4_prec == widen_prec && widen_prec > prec;
+       bool c2_is_type_precision_p = tree_to_uhwi (@2) == prec;
+      }
+      (if (c2_is_type_precision_p && (mult_p || widen_mult_p)))))))
 )
 
 /* The boundary condition for case 10: IMM = 1:

Reply via email to