re PR tree-optimization/42587 (bswap not recognized for memory)
authorRichard Biener <rguenther@suse.de>
Fri, 13 May 2016 12:27:18 +0000 (12:27 +0000)
committerRichard Biener <rguenth@gcc.gnu.org>
Fri, 13 May 2016 12:27:18 +0000 (12:27 +0000)
2016-05-13  Richard Biener  <rguenther@suse.de>

PR tree-optimization/42587
* tree-ssa-math-opts.c (perform_symbolic_merge): Handle BIT_FIELD_REF.
(find_bswap_or_nop_1): Likewise.
(bswap_replace): Likewise.

* gcc.dg/optimize-bswapsi-4.c: New testcase.

From-SVN: r236204

gcc/ChangeLog
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.dg/optimize-bswapsi-4.c [new file with mode: 0644]
gcc/tree-ssa-math-opts.c

index de06ddd299b6b2044bad93890c10242ba53fd313..9661e5108ecd4041299d526367e62d010d223843 100644 (file)
@@ -1,3 +1,10 @@
+2016-05-13  Richard Biener  <rguenther@suse.de>
+
+       PR tree-optimization/42587
+       * tree-ssa-math-opts.c (perform_symbolic_merge): Handle BIT_FIELD_REF.
+       (find_bswap_or_nop_1): Likewise.
+       (bswap_replace): Likewise.
+
 2016-05-13  Martin Liska  <mliska@suse.cz>
 
        * tree-vect-patterns.c (vect_recog_mask_conversion_pattern):
index a27da97d4e83daee658d1abcd2778c8e0c5edb39..57b7580edafe71637fe8c789934f35b5b0f34997 100644 (file)
@@ -1,3 +1,8 @@
+2016-05-13  Richard Biener  <rguenther@suse.de>
+
+       PR tree-optimization/42587
+       * gcc.dg/optimize-bswapsi-4.c: New testcase.
+
 2016-05-13  Martin Liska  <mliska@suse.cz>
 
        * g++.dg/tree-ssa/ivopts-3.C: Change test-case to follow
diff --git a/gcc/testsuite/gcc.dg/optimize-bswapsi-4.c b/gcc/testsuite/gcc.dg/optimize-bswapsi-4.c
new file mode 100644 (file)
index 0000000..a298486
--- /dev/null
@@ -0,0 +1,28 @@
+/* { dg-do compile } */
+/* { dg-require-effective-target bswap32 } */
+/* { dg-options "-O2 -fdump-tree-bswap" } */
+/* { dg-additional-options "-march=z900" { target s390-*-* } } */
+
+typedef unsigned char u8;
+typedef unsigned int u32;
+union __anonunion
+{
+  u32 value;
+  u8 bytes[4];
+};
+
+u32
+acpi_ut_dword_byte_swap (u32 value)
+{
+  union __anonunion in;
+  in.value = value;
+#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
+  return ((in.bytes[0] << 24) | (in.bytes[1] << 16)
+         | (in.bytes[2] << 8) | in.bytes[3]);
+#else
+  return ((in.bytes[3] << 24) | (in.bytes[2] << 16)
+         | (in.bytes[1] << 8) | in.bytes[0]);
+#endif
+}
+
+/* { dg-final { scan-tree-dump "32 bit bswap implementation found at" "bswap" } } */
index 3fcf24c4f9c20878c739cc4c92b63ccc1d4bc320..81688cd096c387532ceb155f168cde25b4a431e2 100644 (file)
@@ -2160,9 +2160,16 @@ perform_symbolic_merge (gimple *source_stmt1, struct symbolic_number *n1,
   gimple *source_stmt;
   struct symbolic_number *n_start;
 
+  tree rhs1 = gimple_assign_rhs1 (source_stmt1);
+  if (TREE_CODE (rhs1) == BIT_FIELD_REF)
+    rhs1 = TREE_OPERAND (rhs1, 0);
+  tree rhs2 = gimple_assign_rhs1 (source_stmt2);
+  if (TREE_CODE (rhs2) == BIT_FIELD_REF)
+    rhs2 = TREE_OPERAND (rhs2, 0);
+
   /* Sources are different, cancel bswap if they are not memory location with
      the same base (array, structure, ...).  */
-  if (gimple_assign_rhs1 (source_stmt1) != gimple_assign_rhs1 (source_stmt2))
+  if (rhs1 != rhs2)
     {
       uint64_t inc;
       HOST_WIDE_INT start_sub, end_sub, end1, end2, end;
@@ -2285,6 +2292,39 @@ find_bswap_or_nop_1 (gimple *stmt, struct symbolic_number *n, int limit)
   if (find_bswap_or_nop_load (stmt, rhs1, n))
     return stmt;
 
+  /* Handle BIT_FIELD_REF.  */
+  if (TREE_CODE (rhs1) == BIT_FIELD_REF
+      && TREE_CODE (TREE_OPERAND (rhs1, 0)) == SSA_NAME)
+    {
+      unsigned HOST_WIDE_INT bitsize = tree_to_uhwi (TREE_OPERAND (rhs1, 1));
+      unsigned HOST_WIDE_INT bitpos = tree_to_uhwi (TREE_OPERAND (rhs1, 2));
+      if (bitpos % BITS_PER_UNIT == 0
+         && bitsize % BITS_PER_UNIT == 0
+         && init_symbolic_number (n, TREE_OPERAND (rhs1, 0)))
+       {
+         /* Shift.  */
+         if (!do_shift_rotate (RSHIFT_EXPR, n, bitpos))
+           return NULL;
+
+         /* Mask.  */
+         uint64_t mask = 0;
+         uint64_t tmp = (1 << BITS_PER_UNIT) - 1;
+         for (unsigned i = 0; i < bitsize / BITS_PER_UNIT;
+              i++, tmp <<= BITS_PER_UNIT)
+           mask |= (uint64_t) MARKER_MASK << (i * BITS_PER_MARKER);
+         n->n &= mask;
+
+         /* Convert.  */
+         n->type = TREE_TYPE (rhs1);
+         if (!n->base_addr)
+           n->range = TYPE_PRECISION (n->type) / BITS_PER_UNIT;
+
+         return verify_symbolic_number_p (n, stmt) ? stmt : NULL;
+       }
+
+      return NULL;
+    }
+
   if (TREE_CODE (rhs1) != SSA_NAME)
     return NULL;
 
@@ -2683,6 +2723,8 @@ bswap_replace (gimple *cur_stmt, gimple *src_stmt, tree fndecl,
        }
       src = val_tmp;
     }
+  else if (TREE_CODE (src) == BIT_FIELD_REF)
+    src = TREE_OPERAND (src, 0);
 
   if (n->range == 16)
     bswap_stats.found_16bit++;