S/390: Enable wraparound in s390_contiguous_bitmask_p.
authorDominik Vogt <vogt@linux.vnet.ibm.com>
Fri, 23 Sep 2016 09:49:58 +0000 (09:49 +0000)
committerAndreas Krebbel <krebbel@gcc.gnu.org>
Fri, 23 Sep 2016 09:49:58 +0000 (09:49 +0000)
gcc/ChangeLog:

2016-09-23  Dominik Vogt  <vogt@linux.vnet.ibm.com>

* config/s390/predicates.md ("contiguous_bitmask_operand"): Adapt to new
interface of s390_contiguous_bitmask_p.
("contiguous_bitmask_nowrap_operand"): New predicate.
* ("*anddi3_cc", "*anddi3_cconly", "*anddi3"): Replace NxxDq with NxxDw.
* config/s390/constraints.md ("NxxDw", "NxxSq"): Adapt to new interface
of s390_contiguous_bitmask_p.
* ("NxxDw"): Rename NxxDq constraint to NxxDw.
("NxxSw"): New constraint.
* config/s390/s390.md ("*andsi3_zarch"): Enable bitmask wraparound.
* config/s390/s390-protos.h (s390_contiguous_bitmask_p): Updated
interface.
(s390_contiguous_bitmask_nowrap_p): Export.
* config/s390/s390.c (s390_contiguous_bitmask_nowrap_p): New name of
former s390_contiguous_bitmask_p.
(s390_contiguous_bitmask_p): Use s390_contiguous_bitmask_nowrap_p to
detect contiguous bit ranges with wraparound.  Change signature to
return START and END position instead of POS and LENGTH.
(s390_contiguous_bitmask_vector_p): Remove extra code for continous bit
ranges with wraparound.
(s390_extzv_shift_ok): Use s390_contiguous_bitmask_nowrap_p.
(s390_contiguous_bitmask_vector_p,s390_extzv_shift_ok,print_operand):
Adapt to new signature of s390_contiguous_bitmask_p.

From-SVN: r240413

gcc/ChangeLog
gcc/config/s390/constraints.md
gcc/config/s390/predicates.md
gcc/config/s390/s390-protos.h
gcc/config/s390/s390.c
gcc/config/s390/s390.md

index 1befd086d0647dde883270ab3cb48f927092027b..f048efcdc0884d17e73b55dac3a432ec84b290e5 100644 (file)
@@ -1,3 +1,28 @@
+2016-09-23  Dominik Vogt  <vogt@linux.vnet.ibm.com>
+
+       * config/s390/predicates.md ("contiguous_bitmask_operand"): Adapt to new
+       interface of s390_contiguous_bitmask_p.
+       ("contiguous_bitmask_nowrap_operand"): New predicate.
+       * ("*anddi3_cc", "*anddi3_cconly", "*anddi3"): Replace NxxDq with NxxDw.
+       * config/s390/constraints.md ("NxxDw", "NxxSq"): Adapt to new interface
+       of s390_contiguous_bitmask_p.
+       * ("NxxDw"): Rename NxxDq constraint to NxxDw.
+       ("NxxSw"): New constraint.
+       * config/s390/s390.md ("*andsi3_zarch"): Enable bitmask wraparound.
+       * config/s390/s390-protos.h (s390_contiguous_bitmask_p): Updated
+       interface.
+       (s390_contiguous_bitmask_nowrap_p): Export.
+       * config/s390/s390.c (s390_contiguous_bitmask_nowrap_p): New name of
+       former s390_contiguous_bitmask_p.
+       (s390_contiguous_bitmask_p): Use s390_contiguous_bitmask_nowrap_p to
+       detect contiguous bit ranges with wraparound.  Change signature to
+       return START and END position instead of POS and LENGTH.
+       (s390_contiguous_bitmask_vector_p): Remove extra code for continous bit
+       ranges with wraparound.
+       (s390_extzv_shift_ok): Use s390_contiguous_bitmask_nowrap_p.
+       (s390_contiguous_bitmask_vector_p,s390_extzv_shift_ok,print_operand):
+       Adapt to new signature of s390_contiguous_bitmask_p.
+
 2016-09-23  Bin Cheng  <bin.cheng@arm.com>
 
        * tree-vect-loop-manip.c (create_intersect_range_checks_index): New.
index 190cdc903d1095cfe1088d7475536c5dcb13fc00..ee505d04f6455ace452a9f73efb11c87435d3f66 100644 (file)
 ;;         D,S,H:   mode of the containing operand
 ;;         0,F:     value of the other parts (F - all bits set)
 ;;         --
-;;         xx[DS]q  satisfies s390_contiguous_bitmask_p for DImode or SImode
+;;         xxDq     satisfies s390_contiguous_bitmask_p for DImode
+;;                  (with possible wraparound of the one-bit range)
+;;         xxSw     satisfies s390_contiguous_bitmask_p for SImode
+;;                  (with possible wraparound of the one-bit range)
+;;         xxSq     satisfies s390_contiguous_bitmask_nowrap_p for SImode
+;;                  (without wraparound of the one-bit range)
 ;;
 ;;         The constraint matches if the specified part of a constant
 ;;         has a value different from its other parts.  If the letter x
   (and (match_code "const_int")
        (match_test "s390_N_constraint_str (\"xQH0\", ival)")))
 
-(define_constraint "NxxDq"
+(define_constraint "NxxDw"
   "@internal"
   (and (match_code "const_int")
-       (match_test "s390_contiguous_bitmask_p (ival, 64, NULL, NULL)")))
+       (match_test "s390_contiguous_bitmask_p (ival, true, 64, NULL, NULL)")))
 
 (define_constraint "NxxSq"
   "@internal"
   (and (match_code "const_int")
-       (match_test "s390_contiguous_bitmask_p (ival, 32, NULL, NULL)")))
+       (match_test "s390_contiguous_bitmask_p (ival, false, 32, NULL, NULL)")))
+
+(define_constraint "NxxSw"
+  "@internal"
+  (and (match_code "const_int")
+       (match_test "s390_contiguous_bitmask_p (ival, true, 32, NULL, NULL)")))
 
 ;;
 ;; Double-letter constraints starting with O follow.
index 75e4cb86b20b8c33b20cdf8d9a0ce3876829a87d..5b57344010f55ae996b98ae7035f41793df154e0 100644 (file)
   return false;
 })
 
+; Predicate that always allows wraparound of the one-bit range.
 (define_predicate "contiguous_bitmask_operand"
   (match_code "const_int")
 {
-  return s390_contiguous_bitmask_p (INTVAL (op), GET_MODE_BITSIZE (mode), NULL, NULL);
+  return s390_contiguous_bitmask_p (INTVAL (op), true,
+                                    GET_MODE_BITSIZE (mode), NULL, NULL);
+})
+
+; Same without wraparound.
+(define_predicate "contiguous_bitmask_nowrap_operand"
+  (match_code "const_int")
+{
+  return s390_contiguous_bitmask_p
+    (INTVAL (op), false, GET_MODE_BITSIZE (mode), NULL, NULL);
 })
 
 ;; Return true if OP is ligitimate for any LOC instruction.
index 91dc0fffea690a8056206c7ceb1dcf1ce9fc5091..7ae98d49cd59facdf1026a938496b3196dfb19f9 100644 (file)
@@ -73,7 +73,7 @@ extern int s390_const_ok_for_constraint_p (HOST_WIDE_INT, int, const char *);
 extern int s390_const_double_ok_for_constraint_p (rtx, int, const char *);
 extern int s390_single_part (rtx, machine_mode, machine_mode, int);
 extern unsigned HOST_WIDE_INT s390_extract_part (rtx, machine_mode, int);
-extern bool s390_contiguous_bitmask_p (unsigned HOST_WIDE_INT, int, int *, int *);
+extern bool s390_contiguous_bitmask_p (unsigned HOST_WIDE_INT, bool, int, int *, int *);
 extern bool s390_contiguous_bitmask_vector_p (rtx, int *, int *);
 extern bool s390_bytemask_vector_p (rtx, unsigned *);
 extern bool s390_split_ok_p (rtx, rtx, machine_mode, int);
index 60e2070d15d04d800a704eb3020060847e72eb97..0b0e3600c66c255492de6ebcc5a738c8cd673c23 100644 (file)
@@ -2260,67 +2260,107 @@ s390_single_part (rtx op,
 }
 
 /* Return true if IN contains a contiguous bitfield in the lower SIZE
-   bits and no other bits are set in IN.  POS and LENGTH can be used
-   to obtain the start position and the length of the bitfield.
+   bits and no other bits are set in (the lower SIZE bits of) IN.
 
-   POS gives the position of the first bit of the bitfield counting
-   from the lowest order bit starting with zero.  In order to use this
-   value for S/390 instructions this has to be converted to "bits big
-   endian" style.  */
+   PSTART and PEND can be used to obtain the start and end
+   position (inclusive) of the bitfield relative to 64
+   bits. *PSTART / *PEND gives the position of the first/last bit
+   of the bitfield counting from the highest order bit starting
+   with zero.  */
 
 bool
-s390_contiguous_bitmask_p (unsigned HOST_WIDE_INT in, int size,
-                          int *pos, int *length)
-{
-  int tmp_pos = 0;
-  int tmp_length = 0;
-  int i;
-  unsigned HOST_WIDE_INT mask = 1ULL;
-  bool contiguous = false;
+s390_contiguous_bitmask_nowrap_p (unsigned HOST_WIDE_INT in, int size,
+                                 int *pstart, int *pend)
+{
+  int start;
+  int end = -1;
+  int lowbit = sizeof (HOST_WIDE_INT) * BITS_PER_UNIT - 1;
+  int highbit = sizeof (HOST_WIDE_INT) * BITS_PER_UNIT - size;
+  unsigned HOST_WIDE_INT bitmask = 1ULL;
+
+  gcc_assert (!!pstart == !!pend);
+  for (start = lowbit; start >= highbit; bitmask <<= 1, start--)
+    if (end == -1)
+      {
+       /* Look for the rightmost bit of a contiguous range of ones.  */
+       if (bitmask & in)
+         /* Found it.  */
+         end = start;
+      }
+    else
+      {
+       /* Look for the firt zero bit after the range of ones.  */
+       if (! (bitmask & in))
+         /* Found it.  */
+         break;
+      }
+  /* We're one past the last one-bit.  */
+  start++;
 
-  for (i = 0; i < size; mask <<= 1, i++)
+  if (end == -1)
+    /* No one bits found.  */
+    return false;
+
+  if (start > highbit)
     {
-      if (contiguous)
-       {
-         if (mask & in)
-           tmp_length++;
-         else
-           break;
-       }
-      else
-       {
-         if (mask & in)
-           {
-             contiguous = true;
-             tmp_length++;
-           }
-         else
-           tmp_pos++;
-       }
+      unsigned HOST_WIDE_INT mask;
+
+      /* Calculate a mask for all bits beyond the contiguous bits.  */
+      mask = ((~(0ULL) >> highbit) & (~(0ULL) << (lowbit - start + 1)));
+      if (mask & in)
+       /* There are more bits set beyond the first range of one bits.  */
+       return false;
     }
 
-  if (!tmp_length)
-    return false;
+  if (pstart)
+    {
+      *pstart = start;
+      *pend = end;
+    }
+
+  return true;
+}
 
-  /* Calculate a mask for all bits beyond the contiguous bits.  */
-  mask = (-1LL & ~(((1ULL << (tmp_length + tmp_pos - 1)) << 1) - 1));
+/* Same as s390_contiguous_bitmask_nowrap_p but also returns true
+   if ~IN contains a contiguous bitfield.  In that case, *END is <
+   *START.
 
-  if ((unsigned)size < sizeof (HOST_WIDE_INT) * BITS_PER_UNIT)
-    mask &= (HOST_WIDE_INT_1U << size) - 1;
+   If WRAP_P is true, a bitmask that wraps around is also tested.
+   When a wraparoud occurs *START is greater than *END (in
+   non-null pointers), and the uppermost (64 - SIZE) bits are thus
+   part of the range.  If WRAP_P is false, no wraparound is
+   tested.  */
 
-  if (mask & in)
-    return false;
+bool
+s390_contiguous_bitmask_p (unsigned HOST_WIDE_INT in, bool wrap_p,
+                          int size, int *start, int *end)
+{
+  int bs = sizeof (HOST_WIDE_INT) * BITS_PER_UNIT;
+  bool b;
 
-  if (tmp_length + tmp_pos - 1 > size)
+  gcc_assert (!!start == !!end);
+  if ((in & ((~(0ULL)) >> (bs - size))) == 0)
+    /* This cannot be expressed as a contiguous bitmask.  Exit early because
+       the second call of s390_contiguous_bitmask_nowrap_p would accept this as
+       a valid bitmask.  */
     return false;
+  b = s390_contiguous_bitmask_nowrap_p (in, size, start, end);
+  if (b)
+    return true;
+  if (! wrap_p)
+    return false;
+  b = s390_contiguous_bitmask_nowrap_p (~in, size, start, end);
+  if (b && start)
+    {
+      int s = *start;
+      int e = *end;
 
-  if (length)
-    *length = tmp_length;
-
-  if (pos)
-    *pos = tmp_pos;
+      gcc_assert (s >= 1);
+      *start = ((e + 1) & (bs - 1));
+      *end = ((s - 1 + bs) & (bs - 1));
+    }
 
-  return true;
+  return b;
 }
 
 /* Return true if OP contains the same contiguous bitfield in *all*
@@ -2336,9 +2376,11 @@ bool
 s390_contiguous_bitmask_vector_p (rtx op, int *start, int *end)
 {
   unsigned HOST_WIDE_INT mask;
-  int length, size;
+  int size;
   rtx elt;
+  bool b;
 
+  gcc_assert (!!start == !!end);
   if (!const_vec_duplicate_p (op, &elt)
       || !CONST_INT_P (elt))
     return false;
@@ -2350,25 +2392,21 @@ s390_contiguous_bitmask_vector_p (rtx op, int *start, int *end)
     return false;
 
   mask = UINTVAL (elt);
-  if (s390_contiguous_bitmask_p (mask, size, start,
-                                end != NULL ? &length : NULL))
-    {
-      if (end != NULL)
-       *end = *start + length - 1;
-      return true;
-    }
-  /* 0xff00000f style immediates can be covered by swapping start and
-     end indices in vgm.  */
-  if (s390_contiguous_bitmask_p (~mask, size, start,
-                                end != NULL ? &length : NULL))
+
+  b = s390_contiguous_bitmask_p (mask, true, size, start, end);
+  if (b)
     {
-      if (end != NULL)
-       *end = *start - 1;
-      if (start != NULL)
-       *start = *start + length;
+      if (start)
+       {
+         int bs = sizeof (HOST_WIDE_INT) * BITS_PER_UNIT;
+
+         *start -= (bs - size);
+         *end -= (bs - size);
+       }
       return true;
     }
-  return false;
+  else
+    return false;
 }
 
 /* Return true if C consists only of byte chunks being either 0 or
@@ -2422,14 +2460,21 @@ s390_bytemask_vector_p (rtx op, unsigned *mask)
 bool
 s390_extzv_shift_ok (int bitsize, int rotl, unsigned HOST_WIDE_INT contig)
 {
-  int pos, len;
+  int start, end;
   bool ok;
 
-  ok = s390_contiguous_bitmask_p (contig, bitsize, &pos, &len);
+  ok = s390_contiguous_bitmask_nowrap_p (contig, bitsize, &start, &end);
   gcc_assert (ok);
 
-  return ((rotl >= 0 && rotl <= pos)
-         || (rotl < 0 && -rotl <= bitsize - len - pos));
+  if (rotl >= 0)
+    return (64 - end >= rotl);
+  else
+    {
+      /* Translate "- rotate right" in BITSIZE mode to "rotate left" in
+        DIMode.  */
+      rotl = -rotl + (64 - bitsize);
+      return (start >= rotl);
+    }
 }
 
 /* Check whether we can (and want to) split a double-word
@@ -7441,16 +7486,17 @@ print_operand (FILE *file, rtx x, int code)
        case 'e': case 'f':
        case 's': case 't':
          {
-           int pos, len;
+           int start, end;
+           int len;
            bool ok;
 
            len = (code == 's' || code == 'e' ? 64 : 32);
-           ok = s390_contiguous_bitmask_p (ival, len, &pos, &len);
+           ok = s390_contiguous_bitmask_p (ival, true, len, &start, &end);
            gcc_assert (ok);
            if (code == 's' || code == 't')
-             ival = 64 - pos - len;
+             ival = start;
            else
-             ival = 64 - 1 - pos;
+             ival = end;
          }
          break;
        default:
@@ -7490,16 +7536,12 @@ print_operand (FILE *file, rtx x, int code)
        case 'e':
        case 's':
          {
-           int start, stop, inner_len;
+           int start, end;
            bool ok;
 
-           inner_len = GET_MODE_UNIT_BITSIZE (GET_MODE (x));
-           ok = s390_contiguous_bitmask_vector_p (x, &start, &stop);
+           ok = s390_contiguous_bitmask_vector_p (x, &start, &end);
            gcc_assert (ok);
-           if (code == 's' || code == 't')
-             ival = inner_len - stop - 1;
-           else
-             ival = inner_len - start - 1;
+           ival = (code == 's') ? start : end;
            fprintf (file, HOST_WIDE_INT_PRINT_DEC, ival);
          }
          break;
index 21ff33ed53962dd75fa96bd95afa5f4e71c1aa38..2848b41656634cecbf135271ebb673fb0b6f609d 100644 (file)
   [(set (reg CC_REGNUM)
         (compare
          (and:DI (match_operand:DI 1 "nonimmediate_operand" "%0,d,0,    d")
-                  (match_operand:DI 2 "general_operand"      " d,d,T,NxxDq"))
+                  (match_operand:DI 2 "general_operand"      " d,d,T,NxxDw"))
           (const_int 0)))
    (set (match_operand:DI 0 "register_operand"               "=d,d,d,    d")
         (and:DI (match_dup 1) (match_dup 2)))]
   [(set (reg CC_REGNUM)
         (compare
          (and:DI (match_operand:DI 1 "nonimmediate_operand" "%0,d,0,    d")
-                  (match_operand:DI 2 "general_operand"      " d,d,T,NxxDq"))
+                  (match_operand:DI 2 "general_operand"      " d,d,T,NxxDw"))
                  (const_int 0)))
    (clobber (match_scratch:DI 0                              "=d,d,d,    d"))]
   "TARGET_ZARCH
          (match_operand:DI 1 "nonimmediate_operand"
             "%d,o,    0,    0,    0,    0,    0,    0,0,d,0,    d,    0,0")
           (match_operand:DI 2 "general_operand"
-            "M, M,N0HDF,N1HDF,N2HDF,N3HDF,N0SDF,N1SDF,d,d,T,NxxDq,NxQDF,Q")))
+            "M, M,N0HDF,N1HDF,N2HDF,N3HDF,N0SDF,N1SDF,d,d,T,NxxDw,NxQDF,Q")))
    (clobber (reg:CC CC_REGNUM))]
   "TARGET_ZARCH && s390_logical_operator_ok_p (operands)"
   "@
         (and:SI (match_operand:SI 1 "nonimmediate_operand"
                            "%d,o,    0,    0, 0,0,d,0,0,    d,    0,0")
                 (match_operand:SI 2 "general_operand"
-                           " M,M,N0HSF,N1HSF,Os,d,d,R,T,NxxSq,NxQSF,Q")))
+                           " M,M,N0HSF,N1HSF,Os,d,d,R,T,NxxSw,NxQSF,Q")))
    (clobber (reg:CC CC_REGNUM))]
   "TARGET_ZARCH && s390_logical_operator_ok_p (operands)"
   "@