diff options
author | rth <rth@138bc75d-0d04-0410-961f-82ee72b054a4> | 2012-12-20 18:05:11 +0000 |
---|---|---|
committer | rth <rth@138bc75d-0d04-0410-961f-82ee72b054a4> | 2012-12-20 18:05:11 +0000 |
commit | 6bc2865555843fddf74e8618574ee3923deb91ee (patch) | |
tree | 13b6b3e56d5eb65f78862c1cf017f280fe0d0020 /gcc/config/s390 | |
parent | 35842b4e24851ae0cbcfdd86a8bc34cfe98721e1 (diff) | |
download | gcc-6bc2865555843fddf74e8618574ee3923deb91ee.tar.gz |
s390: Implement extzv for z10
* config/s390/predicates.md (nonzero_shift_count_operand): New.
* config/s390/s390-protos.h (s390_extzv_shift_ok): Declare.
* config/s390/s390.c (s390_extzv_shift_ok): New function.
* config/s390/s390.md (extzv): New expander.
(*extzv<GPR>_zEC12, *extzv<GPR>_z10): New insns.
(*pre_z10_extzv<GPR>): Rename from *extzv<GPR>; simplify with
nonzero_shift_count_operand.
(*extzv_<mode>_srl, *extzv_<mode>_sll): New insns.
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@194644 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/config/s390')
-rw-r--r-- | gcc/config/s390/predicates.md | 4 | ||||
-rw-r--r-- | gcc/config/s390/s390-protos.h | 1 | ||||
-rw-r--r-- | gcc/config/s390/s390.c | 18 | ||||
-rw-r--r-- | gcc/config/s390/s390.md | 94 |
4 files changed, 109 insertions, 8 deletions
diff --git a/gcc/config/s390/predicates.md b/gcc/config/s390/predicates.md index b9524ecc664..d5e185d5ac7 100644 --- a/gcc/config/s390/predicates.md +++ b/gcc/config/s390/predicates.md @@ -101,6 +101,10 @@ return true; }) +(define_predicate "nonzero_shift_count_operand" + (and (match_code "const_int") + (match_test "IN_RANGE (INTVAL (op), 1, GET_MODE_BITSIZE (mode) - 1)"))) + ;; Return true if OP a valid operand for the LARL instruction. (define_predicate "larl_operand" diff --git a/gcc/config/s390/s390-protos.h b/gcc/config/s390/s390-protos.h index 9b87914e471..a494ba22893 100644 --- a/gcc/config/s390/s390-protos.h +++ b/gcc/config/s390/s390-protos.h @@ -109,5 +109,6 @@ extern bool s390_legitimate_address_without_index_p (rtx); extern bool s390_decompose_shift_count (rtx, rtx *, HOST_WIDE_INT *); extern int s390_branch_condition_mask (rtx); extern int s390_compare_and_branch_condition_mask (rtx); +extern bool s390_extzv_shift_ok (int, int, unsigned HOST_WIDE_INT); #endif /* RTX_CODE */ diff --git a/gcc/config/s390/s390.c b/gcc/config/s390/s390.c index d38ba7f79fb..2edc8ab78f2 100644 --- a/gcc/config/s390/s390.c +++ b/gcc/config/s390/s390.c @@ -1347,6 +1347,24 @@ s390_contiguous_bitmask_p (unsigned HOST_WIDE_INT in, int size, return true; } +/* Check whether a rotate of ROTL followed by an AND of CONTIG is + equivalent to a shift followed by the AND. In particular, CONTIG + should not overlap the (rotated) bit 0/bit 63 gap. Negative values + for ROTL indicate a rotate to the right. */ + +bool +s390_extzv_shift_ok (int bitsize, int rotl, unsigned HOST_WIDE_INT contig) +{ + int pos, len; + bool ok; + + ok = s390_contiguous_bitmask_p (contig, bitsize, &pos, &len); + gcc_assert (ok); + + return ((rotl >= 0 && rotl <= pos) + || (rotl < 0 && -rotl <= bitsize - len - pos)); +} + /* Check whether we can (and want to) split a double-word move in mode MODE from SRC to DST into two single-word moves, moving the subword FIRST_SUBWORD first. */ diff --git a/gcc/config/s390/s390.md b/gcc/config/s390/s390.md index d7adde5e724..f32004c328c 100644 --- a/gcc/config/s390/s390.md +++ b/gcc/config/s390/s390.md @@ -3307,15 +3307,64 @@ [(set_attr "op_type" "RS,RSY") (set_attr "z10prop" "z10_super_E1,z10_super_E1")]) +; +; extv instruction patterns +; + +; FIXME: This expander needs to be converted from DI to GPR as well +; after resolving some issues with it. + +(define_expand "extzv" + [(parallel + [(set (match_operand:DI 0 "register_operand" "=d") + (zero_extract:DI + (match_operand:DI 1 "register_operand" "d") + (match_operand 2 "const_int_operand" "") ; size + (match_operand 3 "const_int_operand" ""))) ; start + (clobber (reg:CC CC_REGNUM))])] + "TARGET_Z10" +{ + /* Starting with zEC12 there is risbgn not clobbering CC. */ + if (TARGET_ZEC12) + { + emit_move_insn (operands[0], + gen_rtx_ZERO_EXTRACT (DImode, + operands[1], + operands[2], + operands[3])); + DONE; + } +}) -(define_insn_and_split "*extzv<mode>" +(define_insn "*extzv<mode>_zEC12" + [(set (match_operand:GPR 0 "register_operand" "=d") + (zero_extract:GPR + (match_operand:GPR 1 "register_operand" "d") + (match_operand 2 "const_int_operand" "") ; size + (match_operand 3 "const_int_operand" "")))] ; start] + "TARGET_ZEC12" + "risbgn\t%0,%1,64-%2,128+63,<bitsize>+%3+%2" ; dst, src, start, end, shift + [(set_attr "op_type" "RIE")]) + +(define_insn "*extzv<mode>_z10" + [(set (match_operand:GPR 0 "register_operand" "=d") + (zero_extract:GPR + (match_operand:GPR 1 "register_operand" "d") + (match_operand 2 "const_int_operand" "") ; size + (match_operand 3 "const_int_operand" ""))) ; start + (clobber (reg:CC CC_REGNUM))] + "TARGET_Z10" + "risbg\t%0,%1,64-%2,128+63,<bitsize>+%3+%2" ; dst, src, start, end, shift + [(set_attr "op_type" "RIE") + (set_attr "z10prop" "z10_super_E1")]) + +(define_insn_and_split "*pre_z10_extzv<mode>" [(set (match_operand:GPR 0 "register_operand" "=d") (zero_extract:GPR (match_operand:QI 1 "s_operand" "QS") - (match_operand 2 "const_int_operand" "n") + (match_operand 2 "nonzero_shift_count_operand" "") (const_int 0))) (clobber (reg:CC CC_REGNUM))] - "INTVAL (operands[2]) > 0 - && INTVAL (operands[2]) <= GET_MODE_BITSIZE (SImode)" + "!TARGET_Z10" "#" "&& reload_completed" [(parallel @@ -3333,14 +3382,13 @@ operands[3] = GEN_INT (mask); }) -(define_insn_and_split "*extv<mode>" +(define_insn_and_split "*pre_z10_extv<mode>" [(set (match_operand:GPR 0 "register_operand" "=d") (sign_extract:GPR (match_operand:QI 1 "s_operand" "QS") - (match_operand 2 "const_int_operand" "n") + (match_operand 2 "nonzero_shift_count_operand" "") (const_int 0))) (clobber (reg:CC CC_REGNUM))] - "INTVAL (operands[2]) > 0 - && INTVAL (operands[2]) <= GET_MODE_BITSIZE (SImode)" + "" "#" "&& reload_completed" [(parallel @@ -6067,6 +6115,36 @@ (clobber (reg:CC CC_REGNUM))])] "s390_narrow_logical_operator (AND, &operands[0], &operands[1]);") +;; These two are what combine generates for (ashift (zero_extract)). +(define_insn "*extzv_<mode>_srl" + [(set (match_operand:GPR 0 "register_operand" "=d") + (and:GPR (lshiftrt:GPR + (match_operand:GPR 1 "register_operand" "d") + (match_operand:GPR 2 "nonzero_shift_count_operand" "")) + (match_operand:GPR 3 "contiguous_bitmask_operand" ""))) + (clobber (reg:CC CC_REGNUM))] + "TARGET_Z10 + /* Note that even for the SImode pattern, the rotate is always DImode. */ + && s390_extzv_shift_ok (<bitsize>, -INTVAL (operands[2]), + INTVAL (operands[3]))" + "risbg\t%0,%1,%<bfstart>3,128+%<bfend>3,64-%2" + [(set_attr "op_type" "RIE") + (set_attr "z10prop" "z10_super_E1")]) + +(define_insn "*extzv_<mode>_sll" + [(set (match_operand:GPR 0 "register_operand" "=d") + (and:GPR (ashift:GPR + (match_operand:GPR 1 "register_operand" "d") + (match_operand:GPR 2 "nonzero_shift_count_operand" "")) + (match_operand:GPR 3 "contiguous_bitmask_operand" ""))) + (clobber (reg:CC CC_REGNUM))] + "TARGET_Z10 + && s390_extzv_shift_ok (<bitsize>, INTVAL (operands[2]), + INTVAL (operands[3]))" + "risbg\t%0,%1,%<bfstart>3,128+%<bfend>3,%2" + [(set_attr "op_type" "RIE") + (set_attr "z10prop" "z10_super_E1")]) + ; ; andsi3 instruction pattern(s). |