> Am 24.02.2024 um 08:40 schrieb Jakub Jelinek <ja...@redhat.com>:
>
> 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?
Ok
Richard
> 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
>