From c2586c82cd3c03d20d5f00f5e4e8fded7652d4bc Mon Sep 17 00:00:00 2001 From: Dominik Vogt Date: Fri, 23 Sep 2016 09:49:58 +0000 Subject: [PATCH] S/390: Enable wraparound in s390_contiguous_bitmask_p. gcc/ChangeLog: 2016-09-23 Dominik Vogt * 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 | 25 +++++ gcc/config/s390/constraints.md | 18 ++- gcc/config/s390/predicates.md | 12 +- gcc/config/s390/s390-protos.h | 2 +- gcc/config/s390/s390.c | 200 ++++++++++++++++++++------------- gcc/config/s390/s390.md | 8 +- 6 files changed, 176 insertions(+), 89 deletions(-) diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 1befd086d06..f048efcdc08 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,28 @@ +2016-09-23 Dominik Vogt + + * 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 * tree-vect-loop-manip.c (create_intersect_range_checks_index): New. diff --git a/gcc/config/s390/constraints.md b/gcc/config/s390/constraints.md index 190cdc903d1..ee505d04f64 100644 --- a/gcc/config/s390/constraints.md +++ b/gcc/config/s390/constraints.md @@ -55,7 +55,12 @@ ;; 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 @@ -346,15 +351,20 @@ (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. diff --git a/gcc/config/s390/predicates.md b/gcc/config/s390/predicates.md index 75e4cb86b20..5b57344010f 100644 --- a/gcc/config/s390/predicates.md +++ b/gcc/config/s390/predicates.md @@ -176,10 +176,20 @@ 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. diff --git a/gcc/config/s390/s390-protos.h b/gcc/config/s390/s390-protos.h index 91dc0fffea6..7ae98d49cd5 100644 --- a/gcc/config/s390/s390-protos.h +++ b/gcc/config/s390/s390-protos.h @@ -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); diff --git a/gcc/config/s390/s390.c b/gcc/config/s390/s390.c index 60e2070d15d..0b0e3600c66 100644 --- a/gcc/config/s390/s390.c +++ b/gcc/config/s390/s390.c @@ -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; diff --git a/gcc/config/s390/s390.md b/gcc/config/s390/s390.md index 21ff33ed539..2848b416566 100644 --- a/gcc/config/s390/s390.md +++ b/gcc/config/s390/s390.md @@ -6962,7 +6962,7 @@ [(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)))] @@ -6980,7 +6980,7 @@ [(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 @@ -7003,7 +7003,7 @@ (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)" "@ @@ -7134,7 +7134,7 @@ (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)" "@ -- 2.30.2