Commit 8fd3cf4e by Jakub Jelinek Committed by Jakub Jelinek

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
parent cc6a602b
2003-06-03 Jakub Jelinek <jakub@redhat.com>
* 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.
2003-06-03 Ben Elliston <bje@wasabisystems.com>
* doc/md.texi (Processor pipeline description): Improve wording.
......
......@@ -3821,7 +3821,7 @@ expand_block_move (operands)
else if (constp && bytes <= (unsigned)2 * MAX_MOVE_BYTES
&& align == (unsigned) UNITS_PER_WORD)
move_by_pieces (orig_dest, orig_src, bytes, align * BITS_PER_WORD);
move_by_pieces (orig_dest, orig_src, bytes, align * BITS_PER_WORD, 0);
else if (constp && bytes <= (unsigned)2 * MAX_MOVE_BYTES)
emit_insn (gen_movstrsi_internal (replace_equiv_address (orig_dest,
......
......@@ -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 */
......
......@@ -450,6 +450,11 @@ extern void use_group_regs PARAMS ((rtx *, rtx));
If OBJECT has BLKmode, SIZE is its length in bytes. */
extern rtx clear_storage PARAMS ((rtx, rtx));
/* Determine whether the LEN bytes can be moved by using several move
instructions. Return nonzero if a call to move_by_pieces should
succeed. */
extern int can_move_by_pieces PARAMS ((unsigned HOST_WIDE_INT, unsigned int));
/* Return nonzero if it is desirable to store LEN bytes generated by
CONSTFUN with several move instructions by store_by_pieces
function. CONSTFUNDATA is a pointer which will be passed as argument
......@@ -463,11 +468,12 @@ extern int can_store_by_pieces PARAMS ((unsigned HOST_WIDE_INT,
/* 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. */
extern void store_by_pieces PARAMS ((rtx, unsigned HOST_WIDE_INT,
ALIGN is maximum alignment we can assume.
Returns TO + LEN. */
extern rtx store_by_pieces PARAMS ((rtx, unsigned HOST_WIDE_INT,
rtx (*) (PTR, HOST_WIDE_INT,
enum machine_mode),
PTR, unsigned int));
PTR, unsigned int, int));
/* Emit insns to set X from Y. */
extern rtx emit_move_insn PARAMS ((rtx, rtx));
......
......@@ -2141,9 +2141,9 @@ extern void emit_jump PARAMS ((rtx));
extern int preserve_subexpressions_p PARAMS ((void));
/* In expr.c */
extern void move_by_pieces PARAMS ((rtx, rtx,
extern rtx move_by_pieces PARAMS ((rtx, rtx,
unsigned HOST_WIDE_INT,
unsigned int));
unsigned int, int));
/* In flow.c */
extern void recompute_reg_usage PARAMS ((rtx, int));
......
2003-06-03 Jakub Jelinek <jakub@redhat.com>
* 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.
2003-06-03 David Billinghurst (David.Billinghurst@riotinto.com)
PR fortran/10965
......
......@@ -23,7 +23,6 @@ void
main_test (void)
{
int i;
const char *s;
if (stpcpy (p, "abcde") != p + 5 || memcmp (p, "abcde", 6))
abort ();
......@@ -47,9 +46,8 @@ main_test (void)
if (stpcpy ((i++, p + 20 + 1), "23") != (p + 20 + 1 + 2) || i != 9 || memcmp (p + 20, "q23\0u", 6))
abort ();
s = s1; i = 3;
memcpy (p + 25, "QRSTU", 6);
if (mempcpy (p + 25 + 1, s++, i++) != (p + 25 + 1 + 3) || i != 4 || s != s1 + 1 || memcmp (p + 25, "Q123U", 6))
if (mempcpy (p + 25 + 1, s1, 3) != (p + 25 + 1 + 3) || memcmp (p + 25, "Q123U", 6))
abort ();
if (stpcpy (stpcpy (p, "ABCD"), "EFG") != p + 7 || memcmp (p, "ABCDEFG", 8))
......
/* Copyright (C) 2003 Free Software Foundation.
Ensure that builtin mempcpy and stpcpy perform correctly.
Written by Jakub Jelinek, 21/05/2003. */
extern void abort (void);
typedef __SIZE_TYPE__ size_t;
extern void *mempcpy (void *, const void *, size_t);
extern int memcmp (const void *, const void *, size_t);
extern char *stpcpy (char *, const char *);
long buf1[64];
char *buf2 = (char *) (buf1 + 32);
long buf5[20];
char buf7[20];
int
__attribute__((noinline))
test (long *buf3, char *buf4, char *buf6, int n)
{
int i = 0;
/* These should probably be handled by store_by_pieces on most arches. */
if (mempcpy (buf1, "ABCDEFGHI", 9) != (char *) buf1 + 9
|| memcmp (buf1, "ABCDEFGHI\0", 11))
abort ();
if (mempcpy (buf1, "abcdefghijklmnopq", 17) != (char *) buf1 + 17
|| memcmp (buf1, "abcdefghijklmnopq\0", 19))
abort ();
if (__builtin_mempcpy (buf3, "ABCDEF", 6) != (char *) buf1 + 6
|| memcmp (buf1, "ABCDEFghijklmnopq\0", 19))
abort ();
if (__builtin_mempcpy (buf3, "a", 1) != (char *) buf1 + 1
|| memcmp (buf1, "aBCDEFghijklmnopq\0", 19))
abort ();
if (mempcpy ((char *) buf3 + 2, "bcd" + ++i, 2) != (char *) buf1 + 4
|| memcmp (buf1, "aBcdEFghijklmnopq\0", 19)
|| i != 1)
abort ();
/* These should probably be handled by move_by_pieces on most arches. */
if (mempcpy ((char *) buf3 + 4, buf5, 6) != (char *) buf1 + 10
|| memcmp (buf1, "aBcdRSTUVWklmnopq\0", 19))
abort ();
if (__builtin_mempcpy ((char *) buf1 + ++i + 8, (char *) buf5 + 1, 1)
!= (char *) buf1 + 11
|| memcmp (buf1, "aBcdRSTUVWSlmnopq\0", 19)
|| i != 2)
abort ();
if (mempcpy ((char *) buf3 + 14, buf6, 2) != (char *) buf1 + 16
|| memcmp (buf1, "aBcdRSTUVWSlmnrsq\0", 19))
abort ();
if (mempcpy (buf3, buf5, 8) != (char *) buf1 + 8
|| memcmp (buf1, "RSTUVWXYVWSlmnrsq\0", 19))
abort ();
if (mempcpy (buf3, buf5, 17) != (char *) buf1 + 17
|| memcmp (buf1, "RSTUVWXYZ01234567\0", 19))
abort ();
__builtin_memcpy (buf3, "aBcdEFghijklmnopq\0", 19);
/* These should be handled either by movstrendM or mempcpy
call. */
if (mempcpy ((char *) buf3 + 4, buf5, n + 6) != (char *) buf1 + 10
|| memcmp (buf1, "aBcdRSTUVWklmnopq\0", 19))
abort ();
if (__builtin_mempcpy ((char *) buf1 + ++i + 8, (char *) buf5 + 1, n + 1)
!= (char *) buf1 + 12
|| memcmp (buf1, "aBcdRSTUVWkSmnopq\0", 19)
|| i != 3)
abort ();
if (mempcpy ((char *) buf3 + 14, buf6, n + 2) != (char *) buf1 + 16
|| memcmp (buf1, "aBcdRSTUVWkSmnrsq\0", 19))
abort ();
i = 1;
/* These might be handled by store_by_pieces. */
if (mempcpy (buf2, "ABCDEFGHI", 9) != buf2 + 9
|| memcmp (buf2, "ABCDEFGHI\0", 11))
abort ();
if (mempcpy (buf2, "abcdefghijklmnopq", 17) != buf2 + 17
|| memcmp (buf2, "abcdefghijklmnopq\0", 19))
abort ();
if (__builtin_mempcpy (buf4, "ABCDEF", 6) != buf2 + 6
|| memcmp (buf2, "ABCDEFghijklmnopq\0", 19))
abort ();
if (__builtin_mempcpy (buf4, "a", 1) != buf2 + 1
|| memcmp (buf2, "aBCDEFghijklmnopq\0", 19))
abort ();
if (mempcpy (buf4 + 2, "bcd" + i++, 2) != buf2 + 4
|| memcmp (buf2, "aBcdEFghijklmnopq\0", 19)
|| i != 2)
abort ();
/* These might be handled by move_by_pieces. */
if (mempcpy (buf4 + 4, buf7, 6) != buf2 + 10
|| memcmp (buf2, "aBcdRSTUVWklmnopq\0", 19))
abort ();
if (__builtin_mempcpy (buf2 + i++ + 8, buf7 + 1, 1)
!= buf2 + 11
|| memcmp (buf2, "aBcdRSTUVWSlmnopq\0", 19)
|| i != 3)
abort ();
if (mempcpy (buf4 + 14, buf6, 2) != buf2 + 16
|| memcmp (buf2, "aBcdRSTUVWSlmnrsq\0", 19))
abort ();
__builtin_memcpy (buf4, "aBcdEFghijklmnopq\0", 19);
/* These should be handled either by movstrendM or mempcpy
call. */
if (mempcpy (buf4 + 4, buf7, n + 6) != buf2 + 10
|| memcmp (buf2, "aBcdRSTUVWklmnopq\0", 19))
abort ();
if (__builtin_mempcpy (buf2 + i++ + 8, buf7 + 1, n + 1)
!= buf2 + 12
|| memcmp (buf2, "aBcdRSTUVWkSmnopq\0", 19)
|| i != 4)
abort ();
if (mempcpy (buf4 + 14, buf6, n + 2) != buf2 + 16
|| memcmp (buf2, "aBcdRSTUVWkSmnrsq\0", 19))
abort ();
/* Now stpcpy tests. */
if (stpcpy ((char *) buf3, "abcdefghijklmnop") != (char *) buf1 + 16
|| memcmp (buf1, "abcdefghijklmnop", 17))
abort ();
if (__builtin_stpcpy ((char *) buf3, "ABCDEFG") != (char *) buf1 + 7
|| memcmp (buf1, "ABCDEFG\0ijklmnop", 17))
abort ();
if (stpcpy ((char *) buf3 + i++, "x") != (char *) buf1 + 5
|| memcmp (buf1, "ABCDx\0G\0ijklmnop", 17))
abort ();
return 0;
}
int
main ()
{
__builtin_memcpy (buf5, "RSTUVWXYZ0123456789", 20);
__builtin_memcpy (buf7, "RSTUVWXYZ0123456789", 20);
return test (buf1, buf2, "rstuvwxyz", 0);
}
/* Ensure mempcpy is not "optimized" into memcpy followed by addition. */
/* { dg-do compile } */
/* { dg-options "-O2" } */
void *
fn (char *x, char *y, int z)
{
return __builtin_mempcpy (x, y, z);
}
/* { dg-final { scan-assembler-not "memcpy" } } */
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment