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> 2003-06-03 Ben Elliston <bje@wasabisystems.com>
* doc/md.texi (Processor pipeline description): Improve wording. * doc/md.texi (Processor pipeline description): Improve wording.
......
...@@ -3821,7 +3821,7 @@ expand_block_move (operands) ...@@ -3821,7 +3821,7 @@ expand_block_move (operands)
else if (constp && bytes <= (unsigned)2 * MAX_MOVE_BYTES else if (constp && bytes <= (unsigned)2 * MAX_MOVE_BYTES
&& align == (unsigned) UNITS_PER_WORD) && 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) else if (constp && bytes <= (unsigned)2 * MAX_MOVE_BYTES)
emit_insn (gen_movstrsi_internal (replace_equiv_address (orig_dest, emit_insn (gen_movstrsi_internal (replace_equiv_address (orig_dest,
......
...@@ -1456,6 +1456,18 @@ convert_modes (mode, oldmode, x, unsignedp) ...@@ -1456,6 +1456,18 @@ convert_modes (mode, oldmode, x, unsignedp)
#define STORE_MAX_PIECES MIN (MOVE_MAX_PIECES, 2 * sizeof (HOST_WIDE_INT)) #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 /* 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 block TO. (These are MEM rtx's with BLKmode). The caller must pass FROM
and TO through protect_from_queue before calling. and TO through protect_from_queue before calling.
...@@ -1463,13 +1475,18 @@ convert_modes (mode, oldmode, x, unsignedp) ...@@ -1463,13 +1475,18 @@ convert_modes (mode, oldmode, x, unsignedp)
If PUSH_ROUNDING is defined and TO is NULL, emit_single_push_insn is If PUSH_ROUNDING is defined and TO is NULL, emit_single_push_insn is
used to push FROM to the stack. used to push FROM to the stack.
ALIGN is maximum stack alignment we can assume. */ ALIGN is maximum stack alignment we can assume.
void If ENDP is 0 return to, if ENDP is 1 return memory at the end ala
move_by_pieces (to, from, len, align) 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; rtx to, from;
unsigned HOST_WIDE_INT len; unsigned HOST_WIDE_INT len;
unsigned int align; unsigned int align;
int endp;
{ {
struct move_by_pieces data; struct move_by_pieces data;
rtx to_addr, from_addr = XEXP (from, 0); rtx to_addr, from_addr = XEXP (from, 0);
...@@ -1583,6 +1600,36 @@ move_by_pieces (to, from, len, align) ...@@ -1583,6 +1600,36 @@ move_by_pieces (to, from, len, align)
/* The code above should have handled everything. */ /* The code above should have handled everything. */
if (data.len > 0) if (data.len > 0)
abort (); 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. /* Return number of insns required to move L bytes by pieces.
...@@ -1760,7 +1807,7 @@ emit_block_move (x, y, size, method) ...@@ -1760,7 +1807,7 @@ emit_block_move (x, y, size, method)
} }
if (GET_CODE (size) == CONST_INT && MOVE_BY_PIECES_P (INTVAL (size), align)) 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 (emit_block_move_via_movstr (x, y, size, align))
; ;
else if (may_use_call) else if (may_use_call)
...@@ -2014,7 +2061,7 @@ init_block_move_fn (asmspec) ...@@ -2014,7 +2061,7 @@ init_block_move_fn (asmspec)
{ {
if (!block_move_fn) if (!block_move_fn)
{ {
tree fn, args; tree args, fn;
if (TARGET_MEM_FUNCTIONS) if (TARGET_MEM_FUNCTIONS)
{ {
...@@ -2738,15 +2785,19 @@ can_store_by_pieces (len, constfun, constfundata, align) ...@@ -2738,15 +2785,19 @@ can_store_by_pieces (len, constfun, constfundata, align)
/* Generate several move instructions to store LEN bytes generated by /* Generate several move instructions to store LEN bytes generated by
CONSTFUN to block TO. (A MEM rtx with BLKmode). CONSTFUNDATA is a CONSTFUN to block TO. (A MEM rtx with BLKmode). CONSTFUNDATA is a
pointer which will be passed as argument in every CONSTFUN call. 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 rtx
store_by_pieces (to, len, constfun, constfundata, align) store_by_pieces (to, len, constfun, constfundata, align, endp)
rtx to; rtx to;
unsigned HOST_WIDE_INT len; unsigned HOST_WIDE_INT len;
rtx (*constfun) PARAMS ((PTR, HOST_WIDE_INT, enum machine_mode)); rtx (*constfun) PARAMS ((PTR, HOST_WIDE_INT, enum machine_mode));
PTR constfundata; PTR constfundata;
unsigned int align; unsigned int align;
int endp;
{ {
struct store_by_pieces data; struct store_by_pieces data;
...@@ -2758,6 +2809,35 @@ store_by_pieces (to, len, constfun, constfundata, align) ...@@ -2758,6 +2809,35 @@ store_by_pieces (to, len, constfun, constfundata, align)
data.len = len; data.len = len;
data.to = to; data.to = to;
store_by_pieces_1 (&data, align); 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 /* 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, ...@@ -3872,7 +3952,7 @@ emit_push_insn (x, mode, type, size, align, partial, reg, extra,
&& where_pad != none && where_pad != stack_direction) && where_pad != none && where_pad != stack_direction)
anti_adjust_stack (GEN_INT (extra)); 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 else
#endif /* PUSH_ROUNDING */ #endif /* PUSH_ROUNDING */
......
...@@ -450,6 +450,11 @@ extern void use_group_regs PARAMS ((rtx *, rtx)); ...@@ -450,6 +450,11 @@ extern void use_group_regs PARAMS ((rtx *, rtx));
If OBJECT has BLKmode, SIZE is its length in bytes. */ If OBJECT has BLKmode, SIZE is its length in bytes. */
extern rtx clear_storage PARAMS ((rtx, rtx)); 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 /* Return nonzero if it is desirable to store LEN bytes generated by
CONSTFUN with several move instructions by store_by_pieces CONSTFUN with several move instructions by store_by_pieces
function. CONSTFUNDATA is a pointer which will be passed as argument 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, ...@@ -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 /* Generate several move instructions to store LEN bytes generated by
CONSTFUN to block TO. (A MEM rtx with BLKmode). CONSTFUNDATA is a CONSTFUN to block TO. (A MEM rtx with BLKmode). CONSTFUNDATA is a
pointer which will be passed as argument in every CONSTFUN call. 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.
extern void store_by_pieces PARAMS ((rtx, unsigned HOST_WIDE_INT, Returns TO + LEN. */
rtx (*) (PTR, HOST_WIDE_INT, extern rtx store_by_pieces PARAMS ((rtx, unsigned HOST_WIDE_INT,
enum machine_mode), rtx (*) (PTR, HOST_WIDE_INT,
PTR, unsigned int)); enum machine_mode),
PTR, unsigned int, int));
/* Emit insns to set X from Y. */ /* Emit insns to set X from Y. */
extern rtx emit_move_insn PARAMS ((rtx, rtx)); extern rtx emit_move_insn PARAMS ((rtx, rtx));
......
...@@ -2141,9 +2141,9 @@ extern void emit_jump PARAMS ((rtx)); ...@@ -2141,9 +2141,9 @@ extern void emit_jump PARAMS ((rtx));
extern int preserve_subexpressions_p PARAMS ((void)); extern int preserve_subexpressions_p PARAMS ((void));
/* In expr.c */ /* In expr.c */
extern void move_by_pieces PARAMS ((rtx, rtx, extern rtx move_by_pieces PARAMS ((rtx, rtx,
unsigned HOST_WIDE_INT, unsigned HOST_WIDE_INT,
unsigned int)); unsigned int, int));
/* In flow.c */ /* In flow.c */
extern void recompute_reg_usage PARAMS ((rtx, int)); 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) 2003-06-03 David Billinghurst (David.Billinghurst@riotinto.com)
PR fortran/10965 PR fortran/10965
......
...@@ -23,7 +23,6 @@ void ...@@ -23,7 +23,6 @@ void
main_test (void) main_test (void)
{ {
int i; int i;
const char *s;
if (stpcpy (p, "abcde") != p + 5 || memcmp (p, "abcde", 6)) if (stpcpy (p, "abcde") != p + 5 || memcmp (p, "abcde", 6))
abort (); abort ();
...@@ -47,9 +46,8 @@ main_test (void) ...@@ -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)) if (stpcpy ((i++, p + 20 + 1), "23") != (p + 20 + 1 + 2) || i != 9 || memcmp (p + 20, "q23\0u", 6))
abort (); abort ();
s = s1; i = 3;
memcpy (p + 25, "QRSTU", 6); 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 (); abort ();
if (stpcpy (stpcpy (p, "ABCD"), "EFG") != p + 7 || memcmp (p, "ABCDEFG", 8)) 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