]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
machmode.h (bitwise_mode_for_mode): Declare.
authorRichard Sandiford <rdsandiford@googlemail.com>
Tue, 22 Apr 2014 12:46:07 +0000 (12:46 +0000)
committerRichard Sandiford <rsandifo@gcc.gnu.org>
Tue, 22 Apr 2014 12:46:07 +0000 (12:46 +0000)
gcc/
* machmode.h (bitwise_mode_for_mode): Declare.
* stor-layout.h (bitwise_type_for_mode): Likewise.
* stor-layout.c (bitwise_mode_for_mode): New function.
(bitwise_type_for_mode): Likewise.
* builtins.c (fold_builtin_memory_op): Use it instead of
int_mode_for_mode and build_nonstandard_integer_type.

gcc/testsuite/
* gcc.dg/memcpy-5.c: New test.

From-SVN: r209622

gcc/ChangeLog
gcc/builtins.c
gcc/machmode.h
gcc/stor-layout.c
gcc/stor-layout.h
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.dg/memcpy-5.c [new file with mode: 0644]

index a0220156d8ed662172ddca7ad51b4f672ceafde1..3a46e6f66b8e853275dcba32f8cb953e343a50f6 100644 (file)
@@ -1,3 +1,12 @@
+2014-04-22  Richard Sandiford  <rdsandiford@googlemail.com>
+
+       * machmode.h (bitwise_mode_for_mode): Declare.
+       * stor-layout.h (bitwise_type_for_mode): Likewise.
+       * stor-layout.c (bitwise_mode_for_mode): New function.
+       (bitwise_type_for_mode): Likewise.
+       * builtins.c (fold_builtin_memory_op): Use it instead of
+       int_mode_for_mode and build_nonstandard_integer_type.
+
 2014-04-22  Rainer Orth  <ro@CeBiTec.Uni-Bielefeld.DE>
 
        * config.gcc (enable_obsolete): Remove *-*-solaris2.9*.
index dd57b1ae42a1aeee2749c4619fcd945dec87c9a7..42e4af263ab1a111127e8e40ae7b2b075bb3373b 100644 (file)
@@ -8921,29 +8921,11 @@ fold_builtin_memory_op (location_t loc, tree dest, tree src,
       if (FLOAT_MODE_P (TYPE_MODE (desttype))
          || TREE_CODE (desttype) == BOOLEAN_TYPE
          || TREE_CODE (desttype) == ENUMERAL_TYPE)
-       {
-         /* A more suitable int_mode_for_mode would return a vector
-            integer mode for a vector float mode or a integer complex
-            mode for a float complex mode if there isn't a regular
-            integer mode covering the mode of desttype.  */
-         enum machine_mode mode = int_mode_for_mode (TYPE_MODE (desttype));
-         if (mode == BLKmode)
-           desttype = NULL_TREE;
-         else
-           desttype = build_nonstandard_integer_type (GET_MODE_BITSIZE (mode),
-                                                      1);
-       }
+       desttype = bitwise_type_for_mode (TYPE_MODE (desttype));
       if (FLOAT_MODE_P (TYPE_MODE (srctype))
          || TREE_CODE (srctype) == BOOLEAN_TYPE
          || TREE_CODE (srctype) == ENUMERAL_TYPE)
-       {
-         enum machine_mode mode = int_mode_for_mode (TYPE_MODE (srctype));
-         if (mode == BLKmode)
-           srctype = NULL_TREE;
-         else
-           srctype = build_nonstandard_integer_type (GET_MODE_BITSIZE (mode),
-                                                     1);
-       }
+       srctype = bitwise_type_for_mode (TYPE_MODE (srctype));
       if (!srctype)
        srctype = desttype;
       if (!desttype)
index 222e6263e0b3ee048bb4a43f199651d2e3865c0e..8d6ea187b4dc535a355d23e2aaf87ec0e9f039a3 100644 (file)
@@ -271,6 +271,8 @@ extern enum machine_mode smallest_mode_for_size (unsigned int,
 
 extern enum machine_mode int_mode_for_mode (enum machine_mode);
 
+extern enum machine_mode bitwise_mode_for_mode (enum machine_mode);
+
 /* Return a mode that is suitable for representing a vector,
    or BLKmode on failure.  */
 
index e3f8406626bef14b7beac592cabfb9540425e5e0..4f99fa3469aafab0369f057f9b268c108c8bd18a 100644 (file)
@@ -403,6 +403,73 @@ int_mode_for_mode (enum machine_mode mode)
   return mode;
 }
 
+/* Find a mode that can be used for efficient bitwise operations on MODE.
+   Return BLKmode if no such mode exists.  */
+
+enum machine_mode
+bitwise_mode_for_mode (enum machine_mode mode)
+{
+  /* Quick exit if we already have a suitable mode.  */
+  unsigned int bitsize = GET_MODE_BITSIZE (mode);
+  if (SCALAR_INT_MODE_P (mode) && bitsize <= MAX_FIXED_MODE_SIZE)
+    return mode;
+
+  /* Reuse the sanity checks from int_mode_for_mode.  */
+  gcc_checking_assert ((int_mode_for_mode (mode), true));
+
+  /* Try to replace complex modes with complex modes.  In general we
+     expect both components to be processed independently, so we only
+     care whether there is a register for the inner mode.  */
+  if (COMPLEX_MODE_P (mode))
+    {
+      enum machine_mode trial = mode;
+      if (GET_MODE_CLASS (mode) != MODE_COMPLEX_INT)
+       trial = mode_for_size (bitsize, MODE_COMPLEX_INT, false);
+      if (trial != BLKmode
+         && have_regs_of_mode[GET_MODE_INNER (trial)])
+       return trial;
+    }
+
+  /* Try to replace vector modes with vector modes.  Also try using vector
+     modes if an integer mode would be too big.  */
+  if (VECTOR_MODE_P (mode) || bitsize > MAX_FIXED_MODE_SIZE)
+    {
+      enum machine_mode trial = mode;
+      if (GET_MODE_CLASS (mode) != MODE_VECTOR_INT)
+       trial = mode_for_size (bitsize, MODE_VECTOR_INT, 0);
+      if (trial != BLKmode
+         && have_regs_of_mode[trial]
+         && targetm.vector_mode_supported_p (trial))
+       return trial;
+    }
+
+  /* Otherwise fall back on integers while honoring MAX_FIXED_MODE_SIZE.  */
+  return mode_for_size (bitsize, MODE_INT, true);
+}
+
+/* Find a type that can be used for efficient bitwise operations on MODE.
+   Return null if no such mode exists.  */
+
+tree
+bitwise_type_for_mode (enum machine_mode mode)
+{
+  mode = bitwise_mode_for_mode (mode);
+  if (mode == BLKmode)
+    return NULL_TREE;
+
+  unsigned int inner_size = GET_MODE_UNIT_BITSIZE (mode);
+  tree inner_type = build_nonstandard_integer_type (inner_size, true);
+
+  if (VECTOR_MODE_P (mode))
+    return build_vector_type_for_mode (inner_type, mode);
+
+  if (COMPLEX_MODE_P (mode))
+    return build_complex_type (inner_type);
+
+  gcc_checking_assert (GET_MODE_INNER (mode) == VOIDmode);
+  return inner_type;
+}
+
 /* Find a mode that is suitable for representing a vector with
    NUNITS elements of mode INNERMODE.  Returns BLKmode if there
    is no suitable mode.  */
index 74a2c6c4412700b09cf9c3738950178adc426cb8..e2f800d3b7601f35ea725833f84abf532d6a4517 100644 (file)
@@ -98,6 +98,8 @@ extern tree make_unsigned_type (int);
    mode_for_size, but is passed a tree.  */
 extern enum machine_mode mode_for_size_tree (const_tree, enum mode_class, int);
 
+extern tree bitwise_type_for_mode (enum machine_mode);
+
 /* 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);
index a721c7b7b05e4e5f858070e80c14f30f31197750..53f5e27d946bdfbc0e14a8ff034f47e3d32fecd3 100644 (file)
@@ -1,3 +1,7 @@
+2014-04-22  Richard Sandiford  <rdsandiford@googlemail.com>
+
+       * gcc.dg/memcpy-5.c: New test.
+
 2014-04-22  Rainer Orth  <ro@CeBiTec.Uni-Bielefeld.DE>
 
        * gcc.c-torture/compile/pr28865.c: Remove dg-xfail-if.
diff --git a/gcc/testsuite/gcc.dg/memcpy-5.c b/gcc/testsuite/gcc.dg/memcpy-5.c
new file mode 100644 (file)
index 0000000..dc5afed
--- /dev/null
@@ -0,0 +1,27 @@
+/* { dg-options "-O -fdump-tree-optimized" } */
+
+extern void *memcpy (void *, const void *, __SIZE_TYPE__);
+
+#define TEST(NAME, TYPE) \
+  TYPE NAME##x; \
+  char NAME##y[sizeof (NAME##x)] __attribute__((aligned (__alignof__ (NAME##x)))); \
+  void NAME (void) { memcpy (&NAME##x, &NAME##y, sizeof (NAME##x)); }
+
+TEST (f, float);
+TEST (d, double);
+TEST (ld, long double);
+TEST (cf, _Complex float);
+TEST (cd, _Complex double);
+TEST (cld, _Complex long double);
+TEST (d8f, float __attribute__((vector_size (8))));
+TEST (d16f, float __attribute__((vector_size (16))));
+TEST (d32f, float __attribute__((vector_size (32))));
+TEST (d64f, float __attribute__((vector_size (64))));
+TEST (d128f, float __attribute__((vector_size (128))));
+TEST (d16d, double __attribute__((vector_size (16))));
+TEST (d32d, double __attribute__((vector_size (32))));
+TEST (d64d, double __attribute__((vector_size (64))));
+TEST (d128d, double __attribute__((vector_size (128))));
+
+/* { dg-final { scan-tree-dump-not "memcpy" "optimized" { target x86_64-*-* } } } */
+/* { dg-final { cleanup-tree-dump "optimized" } } */