This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[PATCH 5/7] s390: Implement extzv for z10
- From: Richard Henderson <rth at redhat dot com>
- To: uweigand at de dot ibm dot com
- Cc: gcc-patches at gcc dot gnu dot org
- Date: Thu, 9 Aug 2012 19:31:59 -0700
- Subject: [PATCH 5/7] s390: Implement extzv for z10
- References: <1344565921-27852-1-git-send-email-rth@redhat.com>
---
gcc/config/s390/predicates.md | 4 +++
gcc/config/s390/s390-protos.h | 1 +
gcc/config/s390/s390.c | 16 ++++++++++++
gcc/config/s390/s390.md | 55 +++++++++++++++++++++++++++++++++++------
4 files changed, 68 insertions(+), 8 deletions(-)
diff --git a/gcc/config/s390/predicates.md b/gcc/config/s390/predicates.md
index 333457d..e4632b9 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 79673d6..97c378f 100644
--- a/gcc/config/s390/s390-protos.h
+++ b/gcc/config/s390/s390-protos.h
@@ -110,5 +110,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 4e22100..52138d7 100644
--- a/gcc/config/s390/s390.c
+++ b/gcc/config/s390/s390.c
@@ -1308,6 +1308,22 @@ 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. */
+
+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 <= pos || rotl >= pos + len + (64 - bitsize));
+}
+
/* 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 b6e1535..ae004ac 100644
--- a/gcc/config/s390/s390.md
+++ b/gcc/config/s390/s390.md
@@ -3298,15 +3298,25 @@
[(set_attr "op_type" "RS,RSY")
(set_attr "z10prop" "z10_super_E1,z10_super_E1")])
+(define_insn "extzv"
+ [(set (match_operand:DI 0 "register_operand" "=d")
+ (zero_extract:DI
+ (match_operand:DI 1 "register_operand" "d")
+ (match_operand 2 "const_int_operand" "")
+ (match_operand 3 "const_int_operand" "")))
+ (clobber (reg:CC CC_REGNUM))]
+ "TARGET_Z10"
+ "risbg\t%0,%1,63-%3-%2,128+63,63-%3-%2"
+ [(set_attr "op_type" "RIE")
+ (set_attr "z10prop" "z10_super_E1")])
-(define_insn_and_split "*extzv<mode>"
+(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
@@ -3324,14 +3334,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)"
+ "!TARGET_Z10"
"#"
"&& reload_completed"
[(parallel
@@ -6034,6 +6043,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:DSI 0 "register_operand" "=d")
+ (and:DSI (lshiftrt:DSI
+ (match_operand:DSI 1 "register_operand" "d")
+ (match_operand:DSI 2 "nonzero_shift_count_operand" ""))
+ (match_operand:DSI 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>, 64 - 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:DSI 0 "register_operand" "=d")
+ (and:DSI (ashift:DSI
+ (match_operand:DSI 1 "register_operand" "d")
+ (match_operand:DSI 2 "nonzero_shift_count_operand" ""))
+ (match_operand:DSI 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).
--
1.7.7.6