aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorAaron Sawdey <acsawdey@linux.ibm.com>2019-10-02 14:26:09 +0000
committerAaron Sawdey <acsawdey@gcc.gnu.org>2019-10-02 09:26:09 -0500
commitc8241327cd156ed15fb136e0b0eaace263aba717 (patch)
tree077e7990fb39b4ec5c3e90f8be904e43270bc957 /gcc
parent03a9b90aa6df28dde083efd17e8b7ae76b943fe7 (diff)
downloadgcc-c8241327cd156ed15fb136e0b0eaace263aba717.zip
gcc-c8241327cd156ed15fb136e0b0eaace263aba717.tar.gz
gcc-c8241327cd156ed15fb136e0b0eaace263aba717.tar.bz2
rs6000-protos.h (expand_block_move): Change prototype.
2019-10-02 Aaron Sawdey <acsawdey@linux.ibm.com> * 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
Diffstat (limited to 'gcc')
-rw-r--r--gcc/ChangeLog8
-rw-r--r--gcc/config/rs6000/rs6000-protos.h2
-rw-r--r--gcc/config/rs6000/rs6000-string.c51
-rw-r--r--gcc/config/rs6000/rs6000.md24
4 files changed, 51 insertions, 34 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index fe14577..5dc5331 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,5 +1,13 @@
2019-10-02 Aaron Sawdey <acsawdey@linux.ibm.com>
+ * 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 <acsawdey@linux.ibm.com>
+
* builtins.c (expand_builtin_memory_copy_args): Add might_overlap parm.
(expand_builtin_memcpy): Use might_overlap parm.
(expand_builtin_mempcpy_args): Use might_overlap parm.
diff --git a/gcc/config/rs6000/rs6000-protos.h b/gcc/config/rs6000/rs6000-protos.h
index c51b768..08dd88c 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 b939185..3bc359e 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 4f27f13..2dca269 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