s390: Add block operation movmem
gcc/ChangeLog: * config/s390/s390-protos.h (s390_expand_movmem): New. * config/s390/s390.cc (s390_expand_movmem): New. * config/s390/s390.md (movmem<mode>): New. (*mvcrl): New. (mvcrl): New.
This commit is contained in:
parent
0cc6d0e7e2
commit
5154171e1f
3 changed files with 124 additions and 0 deletions
|
@ -108,6 +108,7 @@ extern void s390_expand_plus_operand (rtx, rtx, rtx);
|
|||
extern void emit_symbolic_move (rtx *);
|
||||
extern void s390_load_address (rtx, rtx);
|
||||
extern bool s390_expand_cpymem (rtx, rtx, rtx, rtx, rtx);
|
||||
extern bool s390_expand_movmem (rtx, rtx, rtx, rtx, rtx);
|
||||
extern void s390_expand_setmem (rtx, rtx, rtx);
|
||||
extern bool s390_expand_cmpmem (rtx, rtx, rtx, rtx);
|
||||
extern void s390_expand_vec_strlen (rtx, rtx, rtx);
|
||||
|
|
|
@ -5818,6 +5818,94 @@ s390_expand_cpymem (rtx dst, rtx src, rtx len, rtx min_len_rtx, rtx max_len_rtx)
|
|||
return false;
|
||||
}
|
||||
|
||||
bool
|
||||
s390_expand_movmem (rtx dst, rtx src, rtx len, rtx min_len_rtx, rtx max_len_rtx)
|
||||
{
|
||||
/* Exit early in case nothing has to be done. */
|
||||
if (CONST_INT_P (len) && UINTVAL (len) == 0)
|
||||
return true;
|
||||
/* Exit early in case length is not upper bounded. */
|
||||
else if (max_len_rtx == NULL)
|
||||
return false;
|
||||
|
||||
unsigned HOST_WIDE_INT min_len = UINTVAL (min_len_rtx);
|
||||
unsigned HOST_WIDE_INT max_len = UINTVAL (max_len_rtx);
|
||||
|
||||
/* At most 16 bytes. */
|
||||
if (max_len <= 16 && TARGET_VX)
|
||||
{
|
||||
rtx_code_label *end_label;
|
||||
|
||||
if (min_len == 0)
|
||||
{
|
||||
end_label = gen_label_rtx ();
|
||||
emit_cmp_and_jump_insns (len, const0_rtx, EQ, NULL_RTX,
|
||||
GET_MODE (len), 1, end_label,
|
||||
profile_probability::very_unlikely ());
|
||||
}
|
||||
|
||||
rtx lenm1;
|
||||
if (CONST_INT_P (len))
|
||||
{
|
||||
lenm1 = gen_reg_rtx (SImode);
|
||||
emit_move_insn (lenm1, GEN_INT (UINTVAL (len) - 1));
|
||||
}
|
||||
else
|
||||
lenm1
|
||||
= expand_binop (SImode, add_optab, convert_to_mode (SImode, len, 1),
|
||||
constm1_rtx, NULL_RTX, 1, OPTAB_DIRECT);
|
||||
|
||||
rtx tmp = gen_reg_rtx (V16QImode);
|
||||
emit_insn (gen_vllv16qi (tmp, lenm1, src));
|
||||
emit_insn (gen_vstlv16qi (tmp, lenm1, dst));
|
||||
|
||||
if (min_len == 0)
|
||||
emit_label (end_label);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/* At most 256 bytes. */
|
||||
else if (max_len <= 256 && TARGET_Z15)
|
||||
{
|
||||
rtx_code_label *end_label = gen_label_rtx ();
|
||||
|
||||
if (min_len == 0)
|
||||
emit_cmp_and_jump_insns (len, const0_rtx, EQ, NULL_RTX, GET_MODE (len),
|
||||
1, end_label,
|
||||
profile_probability::very_unlikely ());
|
||||
|
||||
rtx dst_addr = gen_reg_rtx (Pmode);
|
||||
rtx src_addr = gen_reg_rtx (Pmode);
|
||||
emit_move_insn (dst_addr, force_operand (XEXP (dst, 0), NULL_RTX));
|
||||
emit_move_insn (src_addr, force_operand (XEXP (src, 0), NULL_RTX));
|
||||
|
||||
rtx lenm1 = CONST_INT_P (len)
|
||||
? GEN_INT (UINTVAL (len) - 1)
|
||||
: expand_binop (GET_MODE (len), add_optab, len, constm1_rtx,
|
||||
NULL_RTX, 1, OPTAB_DIRECT);
|
||||
|
||||
rtx_code_label *right_to_left_label = gen_label_rtx ();
|
||||
emit_cmp_and_jump_insns (src_addr, dst_addr, LT, NULL_RTX, GET_MODE (len),
|
||||
1, right_to_left_label);
|
||||
|
||||
// MVC
|
||||
emit_insn (
|
||||
gen_cpymem_short (dst, src, convert_to_mode (Pmode, lenm1, 1)));
|
||||
emit_jump (end_label);
|
||||
|
||||
// MVCRL
|
||||
emit_label (right_to_left_label);
|
||||
emit_insn (gen_mvcrl (dst, src, convert_to_mode (SImode, lenm1, 1)));
|
||||
|
||||
emit_label (end_label);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Emit code to set LEN bytes at DST to VAL.
|
||||
Make use of clrmem if VAL is zero. */
|
||||
|
||||
|
|
|
@ -61,6 +61,7 @@
|
|||
UNSPEC_ROUND
|
||||
UNSPEC_ICM
|
||||
UNSPEC_TIE
|
||||
UNSPEC_MVCRL
|
||||
|
||||
; Convert CC into a str comparison result and copy it into an
|
||||
; integer register
|
||||
|
@ -3496,6 +3497,40 @@
|
|||
[(set_attr "length" "8")
|
||||
(set_attr "type" "vs")])
|
||||
|
||||
(define_expand "movmem<mode>"
|
||||
[(set (match_operand:BLK 0 "memory_operand") ; destination
|
||||
(match_operand:BLK 1 "memory_operand")) ; source
|
||||
(use (match_operand:GPR 2 "general_operand")) ; size
|
||||
(match_operand 3 "") ; align
|
||||
(match_operand 4 "") ; expected align
|
||||
(match_operand 5 "") ; expected size
|
||||
(match_operand 6 "") ; minimal size
|
||||
(match_operand 7 "")] ; maximal size
|
||||
""
|
||||
{
|
||||
if (s390_expand_movmem (operands[0], operands[1], operands[2], operands[6], operands[7]))
|
||||
DONE;
|
||||
else
|
||||
FAIL;
|
||||
})
|
||||
|
||||
(define_insn "*mvcrl"
|
||||
[(set (match_operand:BLK 0 "memory_operand" "=Q")
|
||||
(unspec:BLK [(match_operand:BLK 1 "memory_operand" "Q")
|
||||
(reg:SI GPR0_REGNUM)]
|
||||
UNSPEC_MVCRL))]
|
||||
"TARGET_Z15"
|
||||
"mvcrl\t%0,%1"
|
||||
[(set_attr "op_type" "SSE")])
|
||||
|
||||
(define_expand "mvcrl"
|
||||
[(set (reg:SI GPR0_REGNUM) (match_operand:SI 2 "general_operand"))
|
||||
(set (match_operand:BLK 0 "memory_operand" "=Q")
|
||||
(unspec:BLK [(match_operand:BLK 1 "memory_operand" "Q")
|
||||
(reg:SI GPR0_REGNUM)]
|
||||
UNSPEC_MVCRL))]
|
||||
"TARGET_Z15"
|
||||
"")
|
||||
|
||||
;
|
||||
; Test data class.
|
||||
|
|
Loading…
Add table
Reference in a new issue