tree-ssa-math-opts.c (find_bswap_or_nop): Zero out bytes in cmpxchg and cmpnop in...
authorThomas Preud'homme <thomas.preudhomme@arm.com>
Mon, 14 Nov 2016 18:55:05 +0000 (18:55 +0000)
committerThomas Preud'homme <thopre01@gcc.gnu.org>
Mon, 14 Nov 2016 18:55:05 +0000 (18:55 +0000)
2016-11-14  Thomas Preud'homme  <thomas.preudhomme@arm.com>

    gcc/
    * tree-ssa-math-opts.c (find_bswap_or_nop): Zero out bytes in cmpxchg
    and cmpnop in two steps: first the ones not accessed in original gimple
    expression in a endian independent way and then the ones not accessed
    in the final result in an endian-specific way.
    (bswap_replace): Stop doing big endian adjustment.

From-SVN: r242394

gcc/ChangeLog
gcc/tree-ssa-math-opts.c

index 7f1cbd8..f259470 100644 (file)
@@ -1,3 +1,11 @@
+2016-11-14  Thomas Preud'homme  <thomas.preudhomme@arm.com>
+
+        * tree-ssa-math-opts.c (find_bswap_or_nop): Zero out bytes in cmpxchg
+       and cmpnop in two steps: first the ones not accessed in original gimple
+       expression in a endian independent way and then the ones not accessed
+       in the final result in an endian-specific way.
+       (bswap_replace): Stop doing big endian adjustment.
+
 2016-11-14  Uros Bizjak  <ubizjak@gmail.com>
 
        * config/i386/i386.md (*andndi3_doubleword): Merge operand constraints.
index c315da8..b28c808 100644 (file)
@@ -2504,9 +2504,11 @@ find_bswap_or_nop_1 (gimple *stmt, struct symbolic_number *n, int limit)
 static gimple *
 find_bswap_or_nop (gimple *stmt, struct symbolic_number *n, bool *bswap)
 {
-  /* The number which the find_bswap_or_nop_1 result should match in order
-     to have a full byte swap.  The number is shifted to the right
-     according to the size of the symbolic number before using it.  */
+  unsigned rsize;
+  uint64_t tmpn, mask;
+/* The number which the find_bswap_or_nop_1 result should match in order
+   to have a full byte swap.  The number is shifted to the right
+   according to the size of the symbolic number before using it.  */
   uint64_t cmpxchg = CMPXCHG;
   uint64_t cmpnop = CMPNOP;
 
@@ -2527,28 +2529,38 @@ find_bswap_or_nop (gimple *stmt, struct symbolic_number *n, bool *bswap)
 
   /* Find real size of result (highest non-zero byte).  */
   if (n->base_addr)
-    {
-      unsigned HOST_WIDE_INT rsize;
-      uint64_t tmpn;
-
-      for (tmpn = n->n, rsize = 0; tmpn; tmpn >>= BITS_PER_MARKER, rsize++);
-      if (BYTES_BIG_ENDIAN && n->range != rsize)
-       /* This implies an offset, which is currently not handled by
-          bswap_replace.  */
-       return NULL;
-      n->range = rsize;
-    }
+    for (tmpn = n->n, rsize = 0; tmpn; tmpn >>= BITS_PER_MARKER, rsize++);
+  else
+    rsize = n->range;
 
-  /* Zero out the extra bits of N and CMP*.  */
+  /* Zero out the bits corresponding to untouched bytes in original gimple
+     expression.  */
   if (n->range < (int) sizeof (int64_t))
     {
-      uint64_t mask;
-
       mask = ((uint64_t) 1 << (n->range * BITS_PER_MARKER)) - 1;
       cmpxchg >>= (64 / BITS_PER_MARKER - n->range) * BITS_PER_MARKER;
       cmpnop &= mask;
     }
 
+  /* Zero out the bits corresponding to unused bytes in the result of the
+     gimple expression.  */
+  if (rsize < n->range)
+    {
+      if (BYTES_BIG_ENDIAN)
+       {
+         mask = ((uint64_t) 1 << (rsize * BITS_PER_MARKER)) - 1;
+         cmpxchg &= mask;
+         cmpnop >>= (n->range - rsize) * BITS_PER_MARKER;
+       }
+      else
+       {
+         mask = ((uint64_t) 1 << (rsize * BITS_PER_MARKER)) - 1;
+         cmpxchg >>= (n->range - rsize) * BITS_PER_MARKER;
+         cmpnop &= mask;
+       }
+      n->range = rsize;
+    }
+
   /* A complete byte swap should make the symbolic number to start with
      the largest digit in the highest order byte. Unchanged symbolic
      number indicates a read with same endianness as target architecture.  */
@@ -2636,26 +2648,6 @@ bswap_replace (gimple *cur_stmt, gimple *src_stmt, tree fndecl,
       HOST_WIDE_INT load_offset = 0;
 
       align = get_object_alignment (src);
-      /* If the new access is smaller than the original one, we need
-        to perform big endian adjustment.  */
-      if (BYTES_BIG_ENDIAN)
-       {
-         HOST_WIDE_INT bitsize, bitpos;
-         machine_mode mode;
-         int unsignedp, reversep, volatilep;
-         tree offset;
-
-         get_inner_reference (src, &bitsize, &bitpos, &offset, &mode,
-                              &unsignedp, &reversep, &volatilep);
-         if (n->range < (unsigned HOST_WIDE_INT) bitsize)
-           {
-             load_offset = (bitsize - n->range) / BITS_PER_UNIT;
-             unsigned HOST_WIDE_INT l
-               = (load_offset * BITS_PER_UNIT) & (align - 1);
-             if (l)
-               align = least_bit_hwi (l);
-           }
-       }
 
       if (bswap
          && align < GET_MODE_ALIGNMENT (TYPE_MODE (load_type))