Commit c2586c82 by Dominik Vogt Committed by Andreas Krebbel

S/390: Enable wraparound in s390_contiguous_bitmask_p.

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
parent 822f18cd
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> 2016-09-23 Bin Cheng <bin.cheng@arm.com>
* tree-vect-loop-manip.c (create_intersect_range_checks_index): New. * tree-vect-loop-manip.c (create_intersect_range_checks_index): New.
......
...@@ -55,7 +55,12 @@ ...@@ -55,7 +55,12 @@
;; D,S,H: mode of the containing operand ;; D,S,H: mode of the containing operand
;; 0,F: value of the other parts (F - all bits set) ;; 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 ;; The constraint matches if the specified part of a constant
;; has a value different from its other parts. If the letter x ;; has a value different from its other parts. If the letter x
...@@ -346,15 +351,20 @@ ...@@ -346,15 +351,20 @@
(and (match_code "const_int") (and (match_code "const_int")
(match_test "s390_N_constraint_str (\"xQH0\", ival)"))) (match_test "s390_N_constraint_str (\"xQH0\", ival)")))
(define_constraint "NxxDq" (define_constraint "NxxDw"
"@internal" "@internal"
(and (match_code "const_int") (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" (define_constraint "NxxSq"
"@internal" "@internal"
(and (match_code "const_int") (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. ;; Double-letter constraints starting with O follow.
......
...@@ -176,10 +176,20 @@ ...@@ -176,10 +176,20 @@
return false; return false;
}) })
; Predicate that always allows wraparound of the one-bit range.
(define_predicate "contiguous_bitmask_operand" (define_predicate "contiguous_bitmask_operand"
(match_code "const_int") (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. ;; Return true if OP is ligitimate for any LOC instruction.
......
...@@ -73,7 +73,7 @@ extern int s390_const_ok_for_constraint_p (HOST_WIDE_INT, int, const char *); ...@@ -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_const_double_ok_for_constraint_p (rtx, int, const char *);
extern int s390_single_part (rtx, machine_mode, machine_mode, int); extern int s390_single_part (rtx, machine_mode, machine_mode, int);
extern unsigned HOST_WIDE_INT s390_extract_part (rtx, 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_contiguous_bitmask_vector_p (rtx, int *, int *);
extern bool s390_bytemask_vector_p (rtx, unsigned *); extern bool s390_bytemask_vector_p (rtx, unsigned *);
extern bool s390_split_ok_p (rtx, rtx, machine_mode, int); extern bool s390_split_ok_p (rtx, rtx, machine_mode, int);
......
...@@ -2260,67 +2260,107 @@ s390_single_part (rtx op, ...@@ -2260,67 +2260,107 @@ s390_single_part (rtx op,
} }
/* Return true if IN contains a contiguous bitfield in the lower SIZE /* 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 bits and no other bits are set in (the lower SIZE bits of) IN.
to obtain the start position and the length of the bitfield.
POS gives the position of the first bit of the bitfield counting PSTART and PEND can be used to obtain the start and end
from the lowest order bit starting with zero. In order to use this position (inclusive) of the bitfield relative to 64
value for S/390 instructions this has to be converted to "bits big bits. *PSTART / *PEND gives the position of the first/last bit
endian" style. */ of the bitfield counting from the highest order bit starting
with zero. */
bool bool
s390_contiguous_bitmask_p (unsigned HOST_WIDE_INT in, int size, s390_contiguous_bitmask_nowrap_p (unsigned HOST_WIDE_INT in, int size,
int *pos, int *length) int *pstart, int *pend)
{ {
int tmp_pos = 0; int start;
int tmp_length = 0; int end = -1;
int i; int lowbit = sizeof (HOST_WIDE_INT) * BITS_PER_UNIT - 1;
unsigned HOST_WIDE_INT mask = 1ULL; int highbit = sizeof (HOST_WIDE_INT) * BITS_PER_UNIT - size;
bool contiguous = false; 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) unsigned HOST_WIDE_INT mask;
{
if (mask & in) /* Calculate a mask for all bits beyond the contiguous bits. */
tmp_length++; mask = ((~(0ULL) >> highbit) & (~(0ULL) << (lowbit - start + 1)));
else if (mask & in)
break; /* There are more bits set beyond the first range of one bits. */
} return false;
else
{
if (mask & in)
{
contiguous = true;
tmp_length++;
}
else
tmp_pos++;
}
} }
if (!tmp_length) if (pstart)
return false; {
*pstart = start;
*pend = end;
}
return true;
}
/* Calculate a mask for all bits beyond the contiguous bits. */ /* Same as s390_contiguous_bitmask_nowrap_p but also returns true
mask = (-1LL & ~(((1ULL << (tmp_length + tmp_pos - 1)) << 1) - 1)); if ~IN contains a contiguous bitfield. In that case, *END is <
*START.
if ((unsigned)size < sizeof (HOST_WIDE_INT) * BITS_PER_UNIT) If WRAP_P is true, a bitmask that wraps around is also tested.
mask &= (HOST_WIDE_INT_1U << size) - 1; 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) bool
return false; 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; 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) gcc_assert (s >= 1);
*length = tmp_length; *start = ((e + 1) & (bs - 1));
*end = ((s - 1 + bs) & (bs - 1));
if (pos) }
*pos = tmp_pos;
return true; return b;
} }
/* Return true if OP contains the same contiguous bitfield in *all* /* Return true if OP contains the same contiguous bitfield in *all*
...@@ -2336,9 +2376,11 @@ bool ...@@ -2336,9 +2376,11 @@ bool
s390_contiguous_bitmask_vector_p (rtx op, int *start, int *end) s390_contiguous_bitmask_vector_p (rtx op, int *start, int *end)
{ {
unsigned HOST_WIDE_INT mask; unsigned HOST_WIDE_INT mask;
int length, size; int size;
rtx elt; rtx elt;
bool b;
gcc_assert (!!start == !!end);
if (!const_vec_duplicate_p (op, &elt) if (!const_vec_duplicate_p (op, &elt)
|| !CONST_INT_P (elt)) || !CONST_INT_P (elt))
return false; return false;
...@@ -2350,25 +2392,21 @@ s390_contiguous_bitmask_vector_p (rtx op, int *start, int *end) ...@@ -2350,25 +2392,21 @@ s390_contiguous_bitmask_vector_p (rtx op, int *start, int *end)
return false; return false;
mask = UINTVAL (elt); mask = UINTVAL (elt);
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 + 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))
{ {
if (end != NULL) if (start)
*end = *start - 1; {
if (start != NULL) int bs = sizeof (HOST_WIDE_INT) * BITS_PER_UNIT;
*start = *start + length;
*start -= (bs - size);
*end -= (bs - size);
}
return true; return true;
} }
return false; else
return false;
} }
/* Return true if C consists only of byte chunks being either 0 or /* 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) ...@@ -2422,14 +2460,21 @@ s390_bytemask_vector_p (rtx op, unsigned *mask)
bool bool
s390_extzv_shift_ok (int bitsize, int rotl, unsigned HOST_WIDE_INT contig) s390_extzv_shift_ok (int bitsize, int rotl, unsigned HOST_WIDE_INT contig)
{ {
int pos, len; int start, end;
bool ok; bool ok;
ok = s390_contiguous_bitmask_p (contig, bitsize, &pos, &len); ok = s390_contiguous_bitmask_nowrap_p (contig, bitsize, &start, &end);
gcc_assert (ok); gcc_assert (ok);
return ((rotl >= 0 && rotl <= pos) if (rotl >= 0)
|| (rotl < 0 && -rotl <= bitsize - len - pos)); 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 /* Check whether we can (and want to) split a double-word
...@@ -7441,16 +7486,17 @@ print_operand (FILE *file, rtx x, int code) ...@@ -7441,16 +7486,17 @@ print_operand (FILE *file, rtx x, int code)
case 'e': case 'f': case 'e': case 'f':
case 's': case 't': case 's': case 't':
{ {
int pos, len; int start, end;
int len;
bool ok; bool ok;
len = (code == 's' || code == 'e' ? 64 : 32); 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); gcc_assert (ok);
if (code == 's' || code == 't') if (code == 's' || code == 't')
ival = 64 - pos - len; ival = start;
else else
ival = 64 - 1 - pos; ival = end;
} }
break; break;
default: default:
...@@ -7490,16 +7536,12 @@ print_operand (FILE *file, rtx x, int code) ...@@ -7490,16 +7536,12 @@ print_operand (FILE *file, rtx x, int code)
case 'e': case 'e':
case 's': case 's':
{ {
int start, stop, inner_len; int start, end;
bool ok; bool ok;
inner_len = GET_MODE_UNIT_BITSIZE (GET_MODE (x)); ok = s390_contiguous_bitmask_vector_p (x, &start, &end);
ok = s390_contiguous_bitmask_vector_p (x, &start, &stop);
gcc_assert (ok); gcc_assert (ok);
if (code == 's' || code == 't') ival = (code == 's') ? start : end;
ival = inner_len - stop - 1;
else
ival = inner_len - start - 1;
fprintf (file, HOST_WIDE_INT_PRINT_DEC, ival); fprintf (file, HOST_WIDE_INT_PRINT_DEC, ival);
} }
break; break;
......
...@@ -6962,7 +6962,7 @@ ...@@ -6962,7 +6962,7 @@
[(set (reg CC_REGNUM) [(set (reg CC_REGNUM)
(compare (compare
(and:DI (match_operand:DI 1 "nonimmediate_operand" "%0,d,0, d") (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))) (const_int 0)))
(set (match_operand:DI 0 "register_operand" "=d,d,d, d") (set (match_operand:DI 0 "register_operand" "=d,d,d, d")
(and:DI (match_dup 1) (match_dup 2)))] (and:DI (match_dup 1) (match_dup 2)))]
...@@ -6980,7 +6980,7 @@ ...@@ -6980,7 +6980,7 @@
[(set (reg CC_REGNUM) [(set (reg CC_REGNUM)
(compare (compare
(and:DI (match_operand:DI 1 "nonimmediate_operand" "%0,d,0, d") (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))) (const_int 0)))
(clobber (match_scratch:DI 0 "=d,d,d, d"))] (clobber (match_scratch:DI 0 "=d,d,d, d"))]
"TARGET_ZARCH "TARGET_ZARCH
...@@ -7003,7 +7003,7 @@ ...@@ -7003,7 +7003,7 @@
(match_operand:DI 1 "nonimmediate_operand" (match_operand:DI 1 "nonimmediate_operand"
"%d,o, 0, 0, 0, 0, 0, 0,0,d,0, d, 0,0") "%d,o, 0, 0, 0, 0, 0, 0,0,d,0, d, 0,0")
(match_operand:DI 2 "general_operand" (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))] (clobber (reg:CC CC_REGNUM))]
"TARGET_ZARCH && s390_logical_operator_ok_p (operands)" "TARGET_ZARCH && s390_logical_operator_ok_p (operands)"
"@ "@
...@@ -7134,7 +7134,7 @@ ...@@ -7134,7 +7134,7 @@
(and:SI (match_operand:SI 1 "nonimmediate_operand" (and:SI (match_operand:SI 1 "nonimmediate_operand"
"%d,o, 0, 0, 0,0,d,0,0, d, 0,0") "%d,o, 0, 0, 0,0,d,0,0, d, 0,0")
(match_operand:SI 2 "general_operand" (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))] (clobber (reg:CC CC_REGNUM))]
"TARGET_ZARCH && s390_logical_operator_ok_p (operands)" "TARGET_ZARCH && s390_logical_operator_ok_p (operands)"
"@ "@
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment