From c8241327cd156ed15fb136e0b0eaace263aba717 Mon Sep 17 00:00:00 2001 From: Aaron Sawdey Date: Wed, 2 Oct 2019 14:26:09 +0000 Subject: [PATCH] rs6000-protos.h (expand_block_move): Change prototype. 2019-10-02 Aaron Sawdey * config/rs6000/rs6000-protos.h (expand_block_move): Change prototype. * config/rs6000/rs6000-string.c (expand_block_move): Add might_overlap parm. * config/rs6000/rs6000.md (movmemsi): Add new pattern. (cpymemsi): Add might_overlap parm to expand_block_move() call. From-SVN: r276462 --- gcc/ChangeLog | 8 +++++ gcc/config/rs6000/rs6000-protos.h | 2 +- gcc/config/rs6000/rs6000-string.c | 51 ++++++++++++------------------- gcc/config/rs6000/rs6000.md | 24 +++++++++++++-- 4 files changed, 51 insertions(+), 34 deletions(-) diff --git a/gcc/ChangeLog b/gcc/ChangeLog index fe1457769db..5dc53312b67 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,11 @@ +2019-10-02 Aaron Sawdey + + * config/rs6000/rs6000-protos.h (expand_block_move): Change prototype. + * config/rs6000/rs6000-string.c (expand_block_move): Add + might_overlap parm. + * config/rs6000/rs6000.md (movmemsi): Add new pattern. + (cpymemsi): Add might_overlap parm to expand_block_move() call. + 2019-10-02 Aaron Sawdey * builtins.c (expand_builtin_memory_copy_args): Add might_overlap parm. diff --git a/gcc/config/rs6000/rs6000-protos.h b/gcc/config/rs6000/rs6000-protos.h index c51b768d964..08dd88c3e4d 100644 --- a/gcc/config/rs6000/rs6000-protos.h +++ b/gcc/config/rs6000/rs6000-protos.h @@ -69,7 +69,7 @@ extern void rs6000_generate_float2_code (bool, rtx, rtx, rtx); extern void rs6000_generate_float2_double_code (rtx, rtx, rtx); extern void rs6000_generate_vsigned2_code (bool, rtx, rtx, rtx); extern int expand_block_clear (rtx[]); -extern int expand_block_move (rtx[]); +extern int expand_block_move (rtx[], bool); extern bool expand_block_compare (rtx[]); extern bool expand_strn_compare (rtx[], int); extern bool rs6000_is_valid_mask (rtx, int *, int *, machine_mode); diff --git a/gcc/config/rs6000/rs6000-string.c b/gcc/config/rs6000/rs6000-string.c index b9391855e16..3bc359e33cc 100644 --- a/gcc/config/rs6000/rs6000-string.c +++ b/gcc/config/rs6000/rs6000-string.c @@ -2719,7 +2719,7 @@ gen_lvx_v4si_move (rtx dest, rtx src) #define MAX_MOVE_REG 4 int -expand_block_move (rtx operands[]) +expand_block_move (rtx operands[], bool might_overlap) { rtx orig_dest = operands[0]; rtx orig_src = operands[1]; @@ -2730,6 +2730,7 @@ expand_block_move (rtx operands[]) int bytes; int offset; int move_bytes; + rtx loads[MAX_MOVE_REG]; rtx stores[MAX_MOVE_REG]; int num_reg = 0; @@ -2817,47 +2818,35 @@ expand_block_move (rtx operands[]) gen_func.mov = gen_movqi; } + /* Mode is always set to something other than BLKmode by one of the + cases of the if statement above. */ + gcc_assert (mode != BLKmode); + src = adjust_address (orig_src, mode, offset); dest = adjust_address (orig_dest, mode, offset); - if (mode != BLKmode) - { - rtx tmp_reg = gen_reg_rtx (mode); + rtx tmp_reg = gen_reg_rtx (mode); + + loads[num_reg] = (*gen_func.mov) (tmp_reg, src); + stores[num_reg++] = (*gen_func.mov) (dest, tmp_reg); - emit_insn ((*gen_func.mov) (tmp_reg, src)); - stores[num_reg++] = (*gen_func.mov) (dest, tmp_reg); - } + /* If we didn't succeed in doing it in one pass, we can't do it in the + might_overlap case. Bail out and return failure. */ + if (might_overlap && num_reg >= MAX_MOVE_REG + && bytes > move_bytes) + return 0; - if (mode == BLKmode || num_reg >= MAX_MOVE_REG || bytes == move_bytes) + /* Emit loads and stores saved up. */ + if (num_reg >= MAX_MOVE_REG || bytes == move_bytes) { int i; + for (i = 0; i < num_reg; i++) + emit_insn (loads[i]); for (i = 0; i < num_reg; i++) emit_insn (stores[i]); num_reg = 0; } - - if (mode == BLKmode) - { - /* Move the address into scratch registers. The movmemsi - patterns require zero offset. */ - if (!REG_P (XEXP (src, 0))) - { - rtx src_reg = copy_addr_to_reg (XEXP (src, 0)); - src = replace_equiv_address (src, src_reg); - } - set_mem_size (src, move_bytes); - - if (!REG_P (XEXP (dest, 0))) - { - rtx dest_reg = copy_addr_to_reg (XEXP (dest, 0)); - dest = replace_equiv_address (dest, dest_reg); - } - set_mem_size (dest, move_bytes); - - emit_insn ((*gen_func.movmemsi) (dest, src, - GEN_INT (move_bytes & 31), - align_rtx)); - } + } return 1; diff --git a/gcc/config/rs6000/rs6000.md b/gcc/config/rs6000/rs6000.md index 4f27f13772b..2dca269744f 100644 --- a/gcc/config/rs6000/rs6000.md +++ b/gcc/config/rs6000/rs6000.md @@ -9107,7 +9107,7 @@ FAIL; }) -;; String/block move insn. +;; String/block copy insn (source and destination must not overlap). ;; Argument 0 is the destination ;; Argument 1 is the source ;; Argument 2 is the length @@ -9120,11 +9120,31 @@ (use (match_operand:SI 3 ""))])] "" { - if (expand_block_move (operands)) + if (expand_block_move (operands, false)) DONE; else FAIL; }) + +;; String/block move insn (source and destination may overlap). +;; Argument 0 is the destination +;; Argument 1 is the source +;; Argument 2 is the length +;; Argument 3 is the alignment + +(define_expand "movmemsi" + [(parallel [(set (match_operand:BLK 0 "") + (match_operand:BLK 1 "")) + (use (match_operand:SI 2 "")) + (use (match_operand:SI 3 ""))])] + "" +{ + if (expand_block_move (operands, true)) + DONE; + else + FAIL; +}) + ;; Define insns that do load or store with update. Some of these we can ;; get by using pre-decrement or pre-increment, but the hardware can also -- 2.30.2