https://gcc.gnu.org/bugzilla/show_bug.cgi?id=113988

--- Comment #14 from Jakub Jelinek <jakub at gcc dot gnu.org> ---
--- gcc/gimple-fold.cc.jj       2024-02-06 12:59:58.343050621 +0100
+++ gcc/gimple-fold.cc  2024-02-19 19:48:11.162126759 +0100
@@ -995,9 +995,27 @@ gimple_fold_builtin_memory_op (gimple_st
                if (warning != OPT_Wrestrict)
                  return false;

-             scalar_int_mode mode;
-             if (int_mode_for_size (ilen * 8, 0).exists (&mode)
-                 && GET_MODE_SIZE (mode) * BITS_PER_UNIT == ilen * 8
+             machine_mode mode = BLKmode;
+             scalar_int_mode imode;
+             if (ilen * BITS_PER_UNIT <= MAX_FIXED_MODE_SIZE)
+               {
+                 if (int_mode_for_size (ilen * BITS_PER_UNIT,
+                                        0).exists (&imode)
+                     && GET_MODE_SIZE (imode) == ilen)
+                   mode = imode;
+               }
+             else if (int_mode_for_size (ilen * BITS_PER_UNIT,
+                                         0).exists (&imode))
+               {
+                 /* For > MAX_FIXED_MODE_SIZE, use a vector mode if
+                    it exists rather than a barely supported huge
+                    INTEGER_TYPE.  */
+                 if (!mode_for_vector (QImode, ilen).exists (&mode)
+                     || !VECTOR_MODE_P (mode)
+                     || !targetm.vector_mode_supported_p (mode))
+                   mode = BLKmode;
+               }
+             if (mode != BLKmode
                  /* If the destination pointer is not aligned we must be able
                     to emit an unaligned store.  */
                  && (dest_align >= GET_MODE_ALIGNMENT (mode)
@@ -1005,7 +1023,12 @@ gimple_fold_builtin_memory_op (gimple_st
                      || (optab_handler (movmisalign_optab, mode)
                          != CODE_FOR_nothing)))
                {
-                 tree type = build_nonstandard_integer_type (ilen * 8, 1);
+                 tree type;
+                 if (VECTOR_MODE_P (mode))
+                   type = build_vector_type_for_mode (char_type_node, mode);
+                 else
+                   type = build_nonstandard_integer_type (ilen
+                                                          * BITS_PER_UNIT, 1);
                  tree srctype = type;
                  tree desttype = type;
                  if (src_align < GET_MODE_ALIGNMENT (mode))
does something like that (kept the int_mode_for_size (ilen * BITS_PER_UNIT,
0).exists (&imode) in there even for the large modes for now so that it doesn't
try to use it for sizes for which it previously did nothing).
That said, with that now both PR113783 and following ICE.  Guess I should add
VCE support to arbitrary types from and to large/huge BITINT_TYPE + more
testsuite coverage, and guess even handling the conversions to the barely
supported huge INTEGER_TYPEs won't hurt, so perhaps the above patch just for
stage1?

/* PR tree-optimization/113988 */
/* { dg-do compile { target bitint } } */
/* { dg-options "-O2" } */
/* { dg-additional-options "-mavx512f" { target i?86-*-* x86_64-*-* } } */

int i;

#if __BITINT_MAXWIDTH__ >= 256
void
foo (void *p, _BitInt(256) x)
{
  __builtin_memcpy (p, &x, sizeof x);
}

_BitInt(256)
bar (void *p, _BitInt(256) x)
{
  _BitInt(246) y = x + 1;
  __builtin_memcpy (p, &y, sizeof y);
  return x;
}
#endif

#if __BITINT_MAXWIDTH__ >= 512
void
baz (void *p, _BitInt(512) x)
{
  __builtin_memcpy (p, &x, sizeof x);
}

_BitInt(512)
qux (void *p, _BitInt(512) x)
{
  _BitInt(512) y = x + 1;
  __builtin_memcpy (p, &y, sizeof y);
  return x;
}
#endif

Reply via email to