diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 3efc0680655..d2b93424722 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -21,6 +21,15 @@ (extend2, zero_extendsi2): Likewise. (zero_extenddi2, fixuns_trunc2): Likewise. + * 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_zEC12, *extzv_z10): New insns. + (*pre_z10_extzv): Rename from *extzv; simplify with + nonzero_shift_count_operand. + (*extzv__srl, *extzv__sll): New insns. + 2012-12-20 Thomas Schwinge PR bootstrap/55202 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 +; -(define_insn_and_split "*extzv" +; 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 "*extzv_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,+%3+%2" ; dst, src, start, end, shift + [(set_attr "op_type" "RIE")]) + +(define_insn "*extzv_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,+%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" [(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" +(define_insn_and_split "*pre_z10_extv" [(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__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 (, -INTVAL (operands[2]), + INTVAL (operands[3]))" + "risbg\t%0,%1,%3,128+%3,64-%2" + [(set_attr "op_type" "RIE") + (set_attr "z10prop" "z10_super_E1")]) + +(define_insn "*extzv__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 (, INTVAL (operands[2]), + INTVAL (operands[3]))" + "risbg\t%0,%1,%3,128+%3,%2" + [(set_attr "op_type" "RIE") + (set_attr "z10prop" "z10_super_E1")]) + ; ; andsi3 instruction pattern(s).