Hi!

The following patch implements support for VIEW_CONVERT_EXPRs from/to
large/huge _BitInt to/from vector or complex types or anything else but
integral/pointer types which doesn't need to live in memory.

Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk?

2024-02-24  Jakub Jelinek  <ja...@redhat.com>

        PR middle-end/114073
        * gimple-lower-bitint.cc (bitint_large_huge::lower_stmt): Handle
        VIEW_CONVERT_EXPRs between large/huge _BitInt and non-integer/pointer
        types like vector or complex types.
        (gimple_lower_bitint): Don't merge VIEW_CONVERT_EXPRs to non-integral
        types.  Fix up VIEW_CONVERT_EXPR handling.  Allow merging
        VIEW_CONVERT_EXPR from non-integral/pointer types with a store.

        * gcc.dg/bitint-93.c: New test.

--- gcc/gimple-lower-bitint.cc.jj       2024-02-23 11:36:06.977015730 +0100
+++ gcc/gimple-lower-bitint.cc  2024-02-23 18:21:09.282751377 +0100
@@ -5305,27 +5305,21 @@ bitint_large_huge::lower_stmt (gimple *s
       else if (TREE_CODE (TREE_TYPE (rhs1)) == BITINT_TYPE
               && bitint_precision_kind (TREE_TYPE (rhs1)) >= bitint_prec_large
               && (INTEGRAL_TYPE_P (TREE_TYPE (lhs))
-                  || POINTER_TYPE_P (TREE_TYPE (lhs))))
+                  || POINTER_TYPE_P (TREE_TYPE (lhs))
+                  || gimple_assign_rhs_code (stmt) == VIEW_CONVERT_EXPR))
        {
          final_cast_p = true;
-         if (TREE_CODE (TREE_TYPE (lhs)) == INTEGER_TYPE
-             && TYPE_PRECISION (TREE_TYPE (lhs)) > MAX_FIXED_MODE_SIZE
+         if (((TREE_CODE (TREE_TYPE (lhs)) == INTEGER_TYPE
+               && TYPE_PRECISION (TREE_TYPE (lhs)) > MAX_FIXED_MODE_SIZE)
+              || (!INTEGRAL_TYPE_P (TREE_TYPE (lhs))
+                  && !POINTER_TYPE_P (TREE_TYPE (lhs))))
              && gimple_assign_rhs_code (stmt) == VIEW_CONVERT_EXPR)
            {
              /* Handle VIEW_CONVERT_EXPRs to not generally supported
                 huge INTEGER_TYPEs like uint256_t or uint512_t.  These
                 are usually emitted from memcpy folding and backends
-                support moves with them but that is usually it.  */
-             if (TREE_CODE (rhs1) == INTEGER_CST)
-               {
-                 rhs1 = fold_unary (VIEW_CONVERT_EXPR, TREE_TYPE (lhs),
-                                    rhs1);
-                 gcc_assert (rhs1 && TREE_CODE (rhs1) == INTEGER_CST);
-                 gimple_assign_set_rhs1 (stmt, rhs1);
-                 gimple_assign_set_rhs_code (stmt, INTEGER_CST);
-                 update_stmt (stmt);
-                 return;
-               }
+                support moves with them but that is usually it.
+                Similarly handle VCEs to vector/complex types etc.  */
              gcc_assert (TREE_CODE (rhs1) == SSA_NAME);
              if (SSA_NAME_IS_DEFAULT_DEF (rhs1)
                  && (!SSA_NAME_VAR (rhs1) || VAR_P (SSA_NAME_VAR (rhs1))))
@@ -5376,6 +5370,18 @@ bitint_large_huge::lower_stmt (gimple *s
                }
            }
        }
+      else if (TREE_CODE (TREE_TYPE (lhs)) == BITINT_TYPE
+              && bitint_precision_kind (TREE_TYPE (lhs)) >= bitint_prec_large
+              && !INTEGRAL_TYPE_P (TREE_TYPE (rhs1))
+              && !POINTER_TYPE_P (TREE_TYPE (rhs1))
+              && gimple_assign_rhs_code (stmt) == VIEW_CONVERT_EXPR)
+       {
+         int part = var_to_partition (m_map, lhs);
+         gcc_assert (m_vars[part] != NULL_TREE);
+         lhs = build1 (VIEW_CONVERT_EXPR, TREE_TYPE (rhs1), m_vars[part]);
+         insert_before (gimple_build_assign (lhs, rhs1));
+         return;
+       }
     }
   if (gimple_store_p (stmt))
     {
@@ -5411,6 +5417,28 @@ bitint_large_huge::lower_stmt (gimple *s
              case IMAGPART_EXPR:
                lower_cplxpart_stmt (lhs, g);
                goto handled;
+             case VIEW_CONVERT_EXPR:
+               {
+                 tree rhs1 = gimple_assign_rhs1 (g);
+                 rhs1 = TREE_OPERAND (rhs1, 0);
+                 if (!INTEGRAL_TYPE_P (TREE_TYPE (rhs1))
+                     && !POINTER_TYPE_P (TREE_TYPE (rhs1)))
+                   {
+                     tree ltype = TREE_TYPE (rhs1);
+                     addr_space_t as = TYPE_ADDR_SPACE (TREE_TYPE (lhs));
+                     ltype
+                       = build_qualified_type (ltype,
+                                               TYPE_QUALS (TREE_TYPE (lhs))
+                                               | ENCODE_QUAL_ADDR_SPACE (as));
+                     lhs = build1 (VIEW_CONVERT_EXPR, ltype, lhs);
+                     gimple_assign_set_lhs (stmt, lhs);
+                     gimple_assign_set_rhs1 (stmt, rhs1);
+                     gimple_assign_set_rhs_code (stmt, TREE_CODE (rhs1));
+                     update_stmt (stmt);
+                     return;
+                   }
+               }
+               break;
              default:
                break;
              }
@@ -6235,6 +6263,14 @@ gimple_lower_bitint (void)
              if (gimple_assign_cast_p (SSA_NAME_DEF_STMT (s)))
                {
                  tree rhs1 = gimple_assign_rhs1 (SSA_NAME_DEF_STMT (s));
+                 if (TREE_CODE (rhs1) == VIEW_CONVERT_EXPR)
+                   {
+                     rhs1 = TREE_OPERAND (rhs1, 0);
+                     if (!INTEGRAL_TYPE_P (TREE_TYPE (rhs1))
+                         && !POINTER_TYPE_P (TREE_TYPE (rhs1))
+                         && gimple_store_p (use_stmt))
+                       continue;
+                   }
                  if (INTEGRAL_TYPE_P (TREE_TYPE (rhs1))
                      && ((is_gimple_assign (use_stmt)
                           && (gimple_assign_rhs_code (use_stmt)
@@ -6279,11 +6315,15 @@ gimple_lower_bitint (void)
                              goto force_name;
                            break;
                          case VIEW_CONVERT_EXPR:
-                           /* Don't merge with VIEW_CONVERT_EXPRs to
-                              huge INTEGER_TYPEs used sometimes in memcpy
-                              expansion.  */
                            {
                              tree lhs = gimple_assign_lhs (use_stmt);
+                             /* Don't merge with VIEW_CONVERT_EXPRs to
+                                non-integral types.  */
+                             if (!INTEGRAL_TYPE_P (TREE_TYPE (lhs)))
+                               goto force_name;
+                             /* Don't merge with VIEW_CONVERT_EXPRs to
+                                huge INTEGER_TYPEs used sometimes in memcpy
+                                expansion.  */
                              if (TREE_CODE (TREE_TYPE (lhs)) == INTEGER_TYPE
                                  && (TYPE_PRECISION (TREE_TYPE (lhs))
                                      > MAX_FIXED_MODE_SIZE))
--- gcc/testsuite/gcc.dg/bitint-93.c.jj 2024-02-23 17:28:44.761989660 +0100
+++ gcc/testsuite/gcc.dg/bitint-93.c    2024-02-23 17:28:33.092149911 +0100
@@ -0,0 +1,253 @@
+/* PR middle-end/114073 */
+/* { dg-do compile { target bitint } } */
+/* { dg-options "-O2 -Wno-psabi" } */
+/* { dg-additional-options "-mavx512f" { target i?86-*-* x86_64-*-* } } */
+
+typedef int V __attribute__((vector_size (sizeof (_BitInt(256)))));
+typedef int W __attribute__((vector_size (sizeof (_BitInt(512)))));
+
+#if __BITINT_MAXWIDTH__ >= 256 && defined (__SIZEOF_INT128__)
+_Complex __int128
+f1 (_BitInt(256) x)
+{
+  union U { _BitInt(256) x; _Complex __int128 y; } u;
+  u.x = x;
+  return u.y;
+}
+
+_Complex __int128
+f2 (_BitInt(254) x)
+{
+  union U { _BitInt(254) x; _Complex __int128 y; } u;
+  u.x = x;
+  return u.y;
+}
+
+_BitInt(256)
+f3 (_Complex __int128 x)
+{
+  union U { _BitInt(256) x; _Complex __int128 y; } u;
+  u.y = x;
+  return u.x;
+}
+
+_BitInt(252)
+f4 (_Complex __int128 x)
+{
+  union U { _BitInt(252) x; _Complex __int128 y; } u;
+  u.y = x;
+  return u.x;
+}
+
+_Complex __int128
+f5 (_BitInt(256) x)
+{
+  union U { _BitInt(256) x; _Complex __int128 y; } u;
+  u.x = x + 1;
+  return u.y;
+}
+
+_Complex __int128
+f6 (_BitInt(254) x)
+{
+  union U { _BitInt(254) x; _Complex __int128 y; } u;
+  u.x = x + 1;
+  return u.y;
+}
+
+_Complex __int128
+f7 (_BitInt(256) *x)
+{
+  union U { _BitInt(256) x; _Complex __int128 y; } u;
+  u.x = *x + 1;
+  return u.y;
+}
+
+_Complex __int128
+f8 (_BitInt(254) *x)
+{
+  union U { _BitInt(254) x; _Complex __int128 y; } u;
+  u.x = *x + 1;
+  return u.y;
+}
+
+_BitInt(256)
+f9 (_Complex __int128 x)
+{
+  union U { _BitInt(256) x; _Complex __int128 y; } u;
+  u.y = x;
+  return u.x + 1;
+}
+
+_BitInt(252)
+f10 (_Complex __int128 x)
+{
+  union U { _BitInt(252) x; _Complex __int128 y; } u;
+  u.y = x;
+  return u.x + 1;
+}
+#endif
+
+#if __BITINT_MAXWIDTH__ >= 256
+V
+f11 (_BitInt(256) x)
+{
+  union U { _BitInt(256) x; V y; } u;
+  u.x = x;
+  return u.y;
+}
+
+V
+f12 (_BitInt(254) x)
+{
+  union U { _BitInt(254) x; V y; } u;
+  u.x = x;
+  return u.y;
+}
+
+_BitInt(256)
+f13 (V x)
+{
+  union U { _BitInt(256) x; V y; } u;
+  u.y = x;
+  return u.x;
+}
+
+_BitInt(252)
+f14 (V x)
+{
+  union U { _BitInt(252) x; V y; } u;
+  u.y = x;
+  return u.x;
+}
+
+V
+f15 (_BitInt(256) x)
+{
+  union U { _BitInt(256) x; V y; } u;
+  u.x = x + 1;
+  return u.y;
+}
+
+V
+f16 (_BitInt(254) x)
+{
+  union U { _BitInt(254) x; V y; } u;
+  u.x = x + 1;
+  return u.y;
+}
+
+V
+f17 (_BitInt(256) *x)
+{
+  union U { _BitInt(256) x; V y; } u;
+  u.x = *x + 1;
+  return u.y;
+}
+
+V
+f18 (_BitInt(254) *x)
+{
+  union U { _BitInt(254) x; V y; } u;
+  u.x = *x + 1;
+  return u.y;
+}
+
+_BitInt(256)
+f19 (V x)
+{
+  union U { _BitInt(256) x; V y; } u;
+  u.y = x;
+  return u.x + 1;
+}
+
+_BitInt(252)
+f20 (V x)
+{
+  union U { _BitInt(252) x; V y; } u;
+  u.y = x;
+  return u.x + 1;
+}
+#endif
+
+#if __BITINT_MAXWIDTH__ >= 512
+W
+f21 (_BitInt(512) x)
+{
+  union U { _BitInt(512) x; W y; } u;
+  u.x = x;
+  return u.y;
+}
+
+W
+f22 (_BitInt(509) x)
+{
+  union U { _BitInt(509) x; W y; } u;
+  u.x = x;
+  return u.y;
+}
+
+_BitInt(512)
+f23 (W x)
+{
+  union U { _BitInt(512) x; W y; } u;
+  u.y = x;
+  return u.x;
+}
+
+_BitInt(506)
+f24 (W x)
+{
+  union U { _BitInt(506) x; W y; } u;
+  u.y = x;
+  return u.x;
+}
+
+W
+f25 (_BitInt(512) x)
+{
+  union U { _BitInt(512) x; W y; } u;
+  u.x = x + 1;
+  return u.y;
+}
+
+W
+f26 (_BitInt(509) x)
+{
+  union U { _BitInt(509) x; W y; } u;
+  u.x = x + 1;
+  return u.y;
+}
+
+W
+f27 (_BitInt(512) *x)
+{
+  union U { _BitInt(512) x; W y; } u;
+  u.x = *x + 1;
+  return u.y;
+}
+
+W
+f28 (_BitInt(509) *x)
+{
+  union U { _BitInt(509) x; W y; } u;
+  u.x = *x + 1;
+  return u.y;
+}
+
+_BitInt(512)
+f29 (W x)
+{
+  union U { _BitInt(512) x; W y; } u;
+  u.y = x;
+  return u.x + 1;
+}
+
+_BitInt(506)
+f30 (W x)
+{
+  union U { _BitInt(506) x; W y; } u;
+  u.y = x;
+  return u.x + 1;
+}
+#endif

        Jakub

Reply via email to