]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
gimple-fold: Use bitwise vector types rather than barely supported huge integral...
authorJakub Jelinek <jakub@redhat.com>
Wed, 28 Feb 2024 08:40:15 +0000 (09:40 +0100)
committerJakub Jelinek <jakub@redhat.com>
Wed, 28 Feb 2024 08:40:15 +0000 (09:40 +0100)
The following patch changes the memcpy etc. folding to use bitwise vector
types rather  than huge INTEGER_TYPEs for copying of > MAX_FIXED_MODE_SIZE
lengths.  The problem with the huge INTEGER_TYPEs is that they aren't
supported very much, usually there are just optabs to handle moves of them,
perhaps misaligned moves and that is it, so they pose problems e.g. to
BITINT_TYPE lowering.

2024-02-28  Jakub Jelinek  <jakub@redhat.com>

PR tree-optimization/113988
* stor-layout.h (bitwise_mode_for_size): Declare.
* stor-layout.cc (bitwise_mode_for_size): New function.
* gimple-fold.cc (gimple_fold_builtin_memory_op): Use it.
Use bitwise_type_for_mode instead of build_nonstandard_integer_type.
Use BITS_PER_UNIT instead of 8.

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

gcc/gimple-fold.cc
gcc/stor-layout.cc
gcc/stor-layout.h
gcc/testsuite/gcc.dg/bitint-91.c [new file with mode: 0644]

index 5191102df6882ba552db856ec62457ce9ae0f563..d2a0f6ddf19606b6ace6fb70432a57e8e4d1d304 100644 (file)
@@ -995,9 +995,12 @@ gimple_fold_builtin_memory_op (gimple_stmt_iterator *gsi,
                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
+             scalar_int_mode imode;
+             machine_mode mode;
+             if (int_mode_for_size (ilen * BITS_PER_UNIT, 0).exists (&imode)
+                 && bitwise_mode_for_size (ilen
+                                           * BITS_PER_UNIT).exists (&mode)
+                 && known_eq (GET_MODE_BITSIZE (mode), ilen * BITS_PER_UNIT)
                  /* If the destination pointer is not aligned we must be able
                     to emit an unaligned store.  */
                  && (dest_align >= GET_MODE_ALIGNMENT (mode)
@@ -1005,7 +1008,7 @@ gimple_fold_builtin_memory_op (gimple_stmt_iterator *gsi,
                      || (optab_handler (movmisalign_optab, mode)
                          != CODE_FOR_nothing)))
                {
-                 tree type = build_nonstandard_integer_type (ilen * 8, 1);
+                 tree type = bitwise_type_for_mode (mode);
                  tree srctype = type;
                  tree desttype = type;
                  if (src_align < GET_MODE_ALIGNMENT (mode))
index 4cf249133e9d34c074d9568f72733f8d3b89ebff..e34be19689c097ff564caa4905793c48fcfcc889 100644 (file)
@@ -476,6 +476,32 @@ bitwise_type_for_mode (machine_mode mode)
   return inner_type;
 }
 
+/* Find a mode that can be used for efficient bitwise operations on SIZE
+   bits, if one exists.  */
+
+opt_machine_mode
+bitwise_mode_for_size (poly_uint64 size)
+{
+  if (known_le (size, (unsigned int) MAX_FIXED_MODE_SIZE))
+    return mode_for_size (size, MODE_INT, true);
+
+  machine_mode mode, ret = VOIDmode;
+  FOR_EACH_MODE_FROM (mode, MIN_MODE_VECTOR_INT)
+    if (known_eq (GET_MODE_BITSIZE (mode), size)
+       && (ret == VOIDmode || GET_MODE_INNER (mode) == QImode)
+       && have_regs_of_mode[mode]
+       && targetm.vector_mode_supported_p (mode))
+      {
+       if (GET_MODE_INNER (mode) == QImode)
+         return mode;
+       else if (ret == VOIDmode)
+         ret = mode;
+      }
+  if (ret != VOIDmode)
+    return ret;
+  return opt_machine_mode ();
+}
+
 /* Find a mode that is suitable for representing a vector with NUNITS
    elements of mode INNERMODE, if one exists.  The returned mode can be
    either an integer mode or a vector mode.  */
index 7fbc312bdf8b36bd6b1d06572547ade8d00f6b97..096ca8117627d3c04edd4ee8ca2cb6be8ccdf22c 100644 (file)
@@ -102,6 +102,8 @@ extern opt_machine_mode mode_for_size_tree (const_tree, enum mode_class, int);
 
 extern tree bitwise_type_for_mode (machine_mode);
 
+extern opt_machine_mode bitwise_mode_for_size (poly_uint64);
+
 /* Given a VAR_DECL, PARM_DECL or RESULT_DECL, clears the results of
    a previous call to layout_decl and calls it again.  */
 extern void relayout_decl (tree);
diff --git a/gcc/testsuite/gcc.dg/bitint-91.c b/gcc/testsuite/gcc.dg/bitint-91.c
new file mode 100644 (file)
index 0000000..ede6f68
--- /dev/null
@@ -0,0 +1,38 @@
+/* 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