summaryrefslogtreecommitdiff
path: root/gcc/expr.c
diff options
context:
space:
mode:
authorJakub Jelinek <jakub@redhat.com>2003-06-03 10:57:55 +0200
committerJakub Jelinek <jakub@gcc.gnu.org>2003-06-03 10:57:55 +0200
commit8fd3cf4e17c97036b4f9cecbe2f438a2da920351 (patch)
tree969f8e454fe8799c43c000ed725898b0593270ff /gcc/expr.c
parentcc6a602b278d597095052e6de06f02d65b315a03 (diff)
downloadgcc-8fd3cf4e17c97036b4f9cecbe2f438a2da920351.tar.gz
builtins.c (expand_builtin_memcpy): Remove endp argument and endp != 0 handling.
* builtins.c (expand_builtin_memcpy): Remove endp argument and endp != 0 handling. Pass 0 to store_by_pieces. (expand_builtin_mempcpy): Add endp argument. Don't call expand_builtin_memcpy, call store_by_pieces resp. move_by_pieces directly. If ignoring result, only do expand_call. (expand_builtin_stpcpy): Likewise. Call expand_builtin_mempcpy otherwise. (expand_builtin_strncpy, expand_builtin_memset): Adjust store_by_pices callers. (expand_builtin): Adjust expand_builtin_memcpy and expand_builtin_mempcpy callers. * expr.c (can_move_by_pieces): New function. (move_by_pieces): Add endp argument, return to resp. memory at end or one byte earlier depending on endp. (store_by_pieces): Likewise. (emit_block_move): Adjust call to move_by_pieces. (emit_push_insn): Adjust move_by_pieces caller. * expr.h (can_move_by_pieces): New prototype. (store_by_pieces): Adjust prototypes. * rtl.h (move_by_pieces): Adjust prototype. * config/mips/mips.c (expand_block_move): Adjust move_by_pieces caller. * gcc.c-torture/execute/builtins/string-4.c (main_test): Remove mempcpy test with post-increments. * gcc.c-torture/execute/string-opt-3.c: New test. * gcc.dg/string-opt-1.c: New test. From-SVN: r67358
Diffstat (limited to 'gcc/expr.c')
-rw-r--r--gcc/expr.c98
1 files changed, 89 insertions, 9 deletions
diff --git a/gcc/expr.c b/gcc/expr.c
index e3872e8e269..f340335515b 100644
--- a/gcc/expr.c
+++ b/gcc/expr.c
@@ -1456,6 +1456,18 @@ convert_modes (mode, oldmode, x, unsignedp)
#define STORE_MAX_PIECES MIN (MOVE_MAX_PIECES, 2 * sizeof (HOST_WIDE_INT))
+/* Determine whether the LEN bytes can be moved by using several move
+ instructions. Return nonzero if a call to move_by_pieces should
+ succeed. */
+
+int
+can_move_by_pieces (len, align)
+ unsigned HOST_WIDE_INT len;
+ unsigned int align;
+{
+ return MOVE_BY_PIECES_P (len, align);
+}
+
/* Generate several move instructions to copy LEN bytes from block FROM to
block TO. (These are MEM rtx's with BLKmode). The caller must pass FROM
and TO through protect_from_queue before calling.
@@ -1463,13 +1475,18 @@ convert_modes (mode, oldmode, x, unsignedp)
If PUSH_ROUNDING is defined and TO is NULL, emit_single_push_insn is
used to push FROM to the stack.
- ALIGN is maximum stack alignment we can assume. */
+ ALIGN is maximum stack alignment we can assume.
-void
-move_by_pieces (to, from, len, align)
+ If ENDP is 0 return to, if ENDP is 1 return memory at the end ala
+ mempcpy, and if ENDP is 2 return memory the end minus one byte ala
+ stpcpy. */
+
+rtx
+move_by_pieces (to, from, len, align, endp)
rtx to, from;
unsigned HOST_WIDE_INT len;
unsigned int align;
+ int endp;
{
struct move_by_pieces data;
rtx to_addr, from_addr = XEXP (from, 0);
@@ -1583,6 +1600,36 @@ move_by_pieces (to, from, len, align)
/* The code above should have handled everything. */
if (data.len > 0)
abort ();
+
+ if (endp)
+ {
+ rtx to1;
+
+ if (data.reverse)
+ abort ();
+ if (data.autinc_to)
+ {
+ if (endp == 2)
+ {
+ if (HAVE_POST_INCREMENT && data.explicit_inc_to > 0)
+ emit_insn (gen_add2_insn (data.to_addr, constm1_rtx));
+ else
+ data.to_addr = copy_addr_to_reg (plus_constant (data.to_addr,
+ -1));
+ }
+ to1 = adjust_automodify_address (data.to, QImode, data.to_addr,
+ data.offset);
+ }
+ else
+ {
+ if (endp == 2)
+ --data.offset;
+ to1 = adjust_address (data.to, QImode, data.offset);
+ }
+ return to1;
+ }
+ else
+ return data.to;
}
/* Return number of insns required to move L bytes by pieces.
@@ -1760,7 +1807,7 @@ emit_block_move (x, y, size, method)
}
if (GET_CODE (size) == CONST_INT && MOVE_BY_PIECES_P (INTVAL (size), align))
- move_by_pieces (x, y, INTVAL (size), align);
+ move_by_pieces (x, y, INTVAL (size), align, 0);
else if (emit_block_move_via_movstr (x, y, size, align))
;
else if (may_use_call)
@@ -2014,7 +2061,7 @@ init_block_move_fn (asmspec)
{
if (!block_move_fn)
{
- tree fn, args;
+ tree args, fn;
if (TARGET_MEM_FUNCTIONS)
{
@@ -2738,15 +2785,19 @@ can_store_by_pieces (len, constfun, constfundata, align)
/* Generate several move instructions to store LEN bytes generated by
CONSTFUN to block TO. (A MEM rtx with BLKmode). CONSTFUNDATA is a
pointer which will be passed as argument in every CONSTFUN call.
- ALIGN is maximum alignment we can assume. */
+ ALIGN is maximum alignment we can assume.
+ If ENDP is 0 return to, if ENDP is 1 return memory at the end ala
+ mempcpy, and if ENDP is 2 return memory the end minus one byte ala
+ stpcpy. */
-void
-store_by_pieces (to, len, constfun, constfundata, align)
+rtx
+store_by_pieces (to, len, constfun, constfundata, align, endp)
rtx to;
unsigned HOST_WIDE_INT len;
rtx (*constfun) PARAMS ((PTR, HOST_WIDE_INT, enum machine_mode));
PTR constfundata;
unsigned int align;
+ int endp;
{
struct store_by_pieces data;
@@ -2758,6 +2809,35 @@ store_by_pieces (to, len, constfun, constfundata, align)
data.len = len;
data.to = to;
store_by_pieces_1 (&data, align);
+ if (endp)
+ {
+ rtx to1;
+
+ if (data.reverse)
+ abort ();
+ if (data.autinc_to)
+ {
+ if (endp == 2)
+ {
+ if (HAVE_POST_INCREMENT && data.explicit_inc_to > 0)
+ emit_insn (gen_add2_insn (data.to_addr, constm1_rtx));
+ else
+ data.to_addr = copy_addr_to_reg (plus_constant (data.to_addr,
+ -1));
+ }
+ to1 = adjust_automodify_address (data.to, QImode, data.to_addr,
+ data.offset);
+ }
+ else
+ {
+ if (endp == 2)
+ --data.offset;
+ to1 = adjust_address (data.to, QImode, data.offset);
+ }
+ return to1;
+ }
+ else
+ return data.to;
}
/* Generate several move instructions to clear LEN bytes of block TO. (A MEM
@@ -3872,7 +3952,7 @@ emit_push_insn (x, mode, type, size, align, partial, reg, extra,
&& where_pad != none && where_pad != stack_direction)
anti_adjust_stack (GEN_INT (extra));
- move_by_pieces (NULL, xinner, INTVAL (size) - used, align);
+ move_by_pieces (NULL, xinner, INTVAL (size) - used, align, 0);
}
else
#endif /* PUSH_ROUNDING */