+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.
;; 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.
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.
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);
}
/* 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*
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;
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
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
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:
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;
[(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)"
"@