From: Stefan Schulze Frielinghaus Date: Tue, 16 May 2023 06:34:22 +0000 (+0200) Subject: s390: Add block operation movmem X-Git-Tag: basepoints/gcc-15~9267 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=5154171e1f3aa4aa120cee3ecf0347cd72a427fb;p=thirdparty%2Fgcc.git 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): New. (*mvcrl): New. (mvcrl): New. --- diff --git a/gcc/config/s390/s390-protos.h b/gcc/config/s390/s390-protos.h index 2c7495ca2473..65e4f97b41e4 100644 --- a/gcc/config/s390/s390-protos.h +++ b/gcc/config/s390/s390-protos.h @@ -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); diff --git a/gcc/config/s390/s390.cc b/gcc/config/s390/s390.cc index 95ea5e8d0091..553273f23fff 100644 --- a/gcc/config/s390/s390.cc +++ b/gcc/config/s390/s390.cc @@ -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. */ diff --git a/gcc/config/s390/s390.md b/gcc/config/s390/s390.md index d9ce287ab85f..abe3bbc5cd96 100644 --- a/gcc/config/s390/s390.md +++ b/gcc/config/s390/s390.md @@ -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" + [(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.