aboutsummaryrefslogtreecommitdiff
path: root/gcc/expr.c
diff options
context:
space:
mode:
authorOlivier Hainque <hainque@act-europe.fr>2003-05-03 16:25:22 +0200
committerRichard Kenner <kenner@gcc.gnu.org>2003-05-03 10:25:22 -0400
commitee9609391b6e1bd4d026b86cf79bced76e1baa5b (patch)
tree7ad4bd29e44c9c37b87311753f154d5fa72e515b /gcc/expr.c
parent3923e4102fcfa593de9148a4855ca54d8466fbe7 (diff)
downloadgcc-ee9609391b6e1bd4d026b86cf79bced76e1baa5b.zip
gcc-ee9609391b6e1bd4d026b86cf79bced76e1baa5b.tar.gz
gcc-ee9609391b6e1bd4d026b86cf79bced76e1baa5b.tar.bz2
emit-rtl.c (last_call_insn, [...]): New functions.
* emit-rtl.c (last_call_insn, add_function_usage_to): New functions. * rtl.h (last_call_insn, add_function_usage_to): New prototypes. * builtins.c (expand_builtin_apply): Use the new emit-rtl functions. * calls.c (emit_call_1): Likewise. (expand_call): For calls initializing constant memory, replace emission of standalone mem /u clobber with function usage entry. * expr.c (emit_block_move_via_libcall): Likewise. * cse.c (count_reg_usage, case EXPR_LIST): New case. * flow.c (propagate_one_insn): Pass entire operand of CALL_INSN_FUNCTION_USAGE to mark_used_regs. * integrate.c (try_constants): For CALL_INSNs, substitute constants within the FUNCTION_USAGE also. * loop.c (prescan_loop): Note clobbers of const mem mentioned in FUNCTION_USAGE lists. * reload1.c (replace_pseudos_in): Renamed. (reload): Use it for clobbers surviving until the end of the reload. From-SVN: r66429
Diffstat (limited to 'gcc/expr.c')
-rw-r--r--gcc/expr.c66
1 files changed, 39 insertions, 27 deletions
diff --git a/gcc/expr.c b/gcc/expr.c
index bc316b3..b64319a 100644
--- a/gcc/expr.c
+++ b/gcc/expr.c
@@ -1839,16 +1839,16 @@ emit_block_move_via_movstr (x, y, size, align)
rtx x, y, size;
unsigned int align;
{
- /* Try the most limited insn first, because there's no point
- including more than one in the machine description unless
- the more limited one has some advantage. */
-
rtx opalign = GEN_INT (align / BITS_PER_UNIT);
enum machine_mode mode;
/* Since this is a move insn, we don't care about volatility. */
volatile_ok = 1;
+ /* Try the most limited insn first, because there's no point
+ including more than one in the machine description unless
+ the more limited one has some advantage. */
+
for (mode = GET_CLASS_NARROWEST_MODE (MODE_INT); mode != VOIDmode;
mode = GET_MODE_WIDER_MODE (mode))
{
@@ -1908,38 +1908,48 @@ static rtx
emit_block_move_via_libcall (dst, src, size)
rtx dst, src, size;
{
+ rtx dst_addr, src_addr;
tree call_expr, arg_list, fn, src_tree, dst_tree, size_tree;
enum machine_mode size_mode;
rtx retval;
/* DST, SRC, or SIZE may have been passed through protect_from_queue.
- It is unsafe to save the value generated by protect_from_queue
- and reuse it later. Consider what happens if emit_queue is
- called before the return value from protect_from_queue is used.
+ It is unsafe to save the value generated by protect_from_queue and reuse
+ it later. Consider what happens if emit_queue is called before the
+ return value from protect_from_queue is used.
- Expansion of the CALL_EXPR below will call emit_queue before
- we are finished emitting RTL for argument setup. So if we are
- not careful we could get the wrong value for an argument.
+ Expansion of the CALL_EXPR below will call emit_queue before we are
+ finished emitting RTL for argument setup. So if we are not careful we
+ could get the wrong value for an argument.
- To avoid this problem we go ahead and emit code to copy X, Y &
- SIZE into new pseudos. We can then place those new pseudos
- into an RTL_EXPR and use them later, even after a call to
+ To avoid this problem we go ahead and emit code to copy the addresses of
+ DST and SRC and SIZE into new pseudos. We can then place those new
+ pseudos into an RTL_EXPR and use them later, even after a call to
emit_queue.
- Note this is not strictly needed for library calls since they
- do not call emit_queue before loading their arguments. However,
- we may need to have library calls call emit_queue in the future
- since failing to do so could cause problems for targets which
- define SMALL_REGISTER_CLASSES and pass arguments in registers. */
+ Note this is not strictly needed for library calls since they do not call
+ emit_queue before loading their arguments. However, we may need to have
+ library calls call emit_queue in the future since failing to do so could
+ cause problems for targets which define SMALL_REGISTER_CLASSES and pass
+ arguments in registers. */
+
+ dst_addr = copy_to_mode_reg (Pmode, XEXP (dst, 0));
+ src_addr = copy_to_mode_reg (Pmode, XEXP (src, 0));
+
+#ifdef POINTERS_EXTEND_UNSIGNED
+ dst_addr = convert_memory_address (ptr_mode, dst_addr);
+ src_addr = convert_memory_address (ptr_mode, src_addr);
+#endif
- dst = copy_to_mode_reg (Pmode, XEXP (dst, 0));
- src = copy_to_mode_reg (Pmode, XEXP (src, 0));
+ dst_tree = make_tree (ptr_type_node, dst_addr);
+ src_tree = make_tree (ptr_type_node, src_addr);
if (TARGET_MEM_FUNCTIONS)
size_mode = TYPE_MODE (sizetype);
else
size_mode = TYPE_MODE (unsigned_type_node);
+
size = convert_to_mode (size_mode, size, 1);
size = copy_to_mode_reg (size_mode, size);
@@ -1951,8 +1961,6 @@ emit_block_move_via_libcall (dst, src, size)
For convenience, we generate the call to bcopy this way as well. */
- dst_tree = make_tree (ptr_type_node, dst);
- src_tree = make_tree (ptr_type_node, src);
if (TARGET_MEM_FUNCTIONS)
size_tree = make_tree (sizetype, size);
else
@@ -1979,13 +1987,17 @@ emit_block_move_via_libcall (dst, src, size)
retval = expand_expr (call_expr, NULL_RTX, VOIDmode, 0);
- /* If we are initializing a readonly value, show the above call
- clobbered it. Otherwise, a load from it may erroneously be
- hoisted from a loop. */
+ /* If we are initializing a readonly value, show the above call clobbered
+ it. Otherwise, a load from it may erroneously be hoisted from a loop, or
+ the delay slot scheduler might overlook conflicts and take nasty
+ decisions. */
if (RTX_UNCHANGING_P (dst))
- emit_insn (gen_rtx_CLOBBER (VOIDmode, dst));
+ add_function_usage_to
+ (last_call_insn (), gen_rtx_EXPR_LIST (VOIDmode,
+ gen_rtx_CLOBBER (VOIDmode, dst),
+ NULL_RTX));
- return (TARGET_MEM_FUNCTIONS ? retval : NULL_RTX);
+ return TARGET_MEM_FUNCTIONS ? retval : NULL_RTX;
}
/* A subroutine of emit_block_move_via_libcall. Create the tree node