diff options
author | Jakub Jelinek <jakub@redhat.com> | 2003-06-03 10:57:55 +0200 |
---|---|---|
committer | Jakub Jelinek <jakub@gcc.gnu.org> | 2003-06-03 10:57:55 +0200 |
commit | 8fd3cf4e17c97036b4f9cecbe2f438a2da920351 (patch) | |
tree | 969f8e454fe8799c43c000ed725898b0593270ff /gcc/expr.c | |
parent | cc6a602b278d597095052e6de06f02d65b315a03 (diff) | |
download | gcc-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.c | 98 |
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 */ |