diff options
author | ebotcazou <ebotcazou@138bc75d-0d04-0410-961f-82ee72b054a4> | 2016-05-13 08:49:20 +0000 |
---|---|---|
committer | ebotcazou <ebotcazou@138bc75d-0d04-0410-961f-82ee72b054a4> | 2016-05-13 08:49:20 +0000 |
commit | 61ffc71aadedd5dd408837317609fcfaca1213e9 (patch) | |
tree | 4b89253c5567cb98e1c4a7e0dbbf1e5628ac0cc2 /gcc/expr.c | |
parent | 8c9721e6acdbf8a008716b90cda61dc68d0671ac (diff) |
* builtins.c (expand_builtin_memcmp): Do not emit the call here.
(expand_builtin_trap): Emit a regular call.
(set_builtin_user_assembler_name): Remove obsolete cases.
* dse.c (scan_insn): Adjust.
* except.c: Include calls.h.
(sjlj_emit_function_enter): If DONT_USE_BUILTIN_SETJMP is defined,
emit a regular call to setjmp.
* expr.c (emit_block_move_hints): Call emit_block_copy_via_libcall.
(block_move_libcall_safe_for_call_parm): Use memcpy builtin.
(emit_block_move_via_libcall): Delete.
(block_move_fn): Delete.
(init_block_move_fn): Likewise.
(emit_block_move_libcall_fn): Likewise.
(emit_block_op_via_libcall): New function.
(set_storage_via_libcall): Tidy up and use memset builtin.
(block_clear_fn): Delete.
(init_block_clear_fn): Likewise.
(clear_storage_libcall_fn): Likewise.
(expand_assignment): Call emit_block_move_via_libcall.
Do not include gt-expr.h.
* expr.h (emit_block_op_via_libcall): Declare.
(emit_block_copy_via_libcall): New inline function.
(emit_block_move_via_libcall): Likewise.
(emit_block_comp_via_libcall): Likewise.
(block_clear_fn): Delete.
(init_block_move_fn): Likewise.
(init_block_clear_fn): Likewise.
(emit_block_move_via_libcall): Likewise.
(set_storage_via_libcall): Add default parameter value.
* libfuncs.h (enum libfunc_index): Remove obsolete values.
(abort_libfunc): Delete.
(memcpy_libfunc): Likewise.
(memmove_libfunc): Likewise.
(memcmp_libfunc): Likewise.
(memset_libfunc): Likewise.
(setbits_libfunc): Likewise.
(setjmp_libfunc): Likewise.
(longjmp_libfunc): Likewise.
(profile_function_entry_libfunc): Likewise.
(profile_function_exit_libfunc): Likewise.
(gcov_flush_libfunc): Likewise.
* optabs-libfuncs.c (build_libfunc_function): Set DECL_ARTIFICIAL
and DECL_VISIBILITY on the declaration.
(init_optabs): Do not initialize obsolete libfuncs.
* optabs.c (prepare_cmp_insn): Call emit_block_comp_via_libcall.
* tree-core.h (ECF_RET1): Define.
(ECF_TM_PURE): Adjust.
(ECF_TM_BUILTIN): Likewise.
* tree.c (set_call_expr_flags): Deal with ECF_RET1.
(build_common_builtin_nodes): Initialize abort builtin.
Add ECF_RET1 on memcpy, memmove and memset builtins.
Pass final flags for alloca and alloca_with_align builtins.
* config/alpha/alpha.c (alpha_init_libfuncs): Do not initialize
obsolete builtins.
* config/ia64/ia64.c (ia64_vms_init_libfuncs): Likewise.
* config/i386/i386.c (ix86_expand_set_or_movmem): Adjust call to
set_storage_via_libcall and call emit_block_copy_via_libcall.
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@236195 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/expr.c')
-rw-r--r-- | gcc/expr.c | 227 |
1 files changed, 46 insertions, 181 deletions
diff --git a/gcc/expr.c b/gcc/expr.c index 812c5445278..2f5a895015a 100644 --- a/gcc/expr.c +++ b/gcc/expr.c @@ -109,14 +109,12 @@ static bool block_move_libcall_safe_for_call_parm (void); static bool emit_block_move_via_movmem (rtx, rtx, rtx, unsigned, unsigned, HOST_WIDE_INT, unsigned HOST_WIDE_INT, unsigned HOST_WIDE_INT, unsigned HOST_WIDE_INT); -static tree emit_block_move_libcall_fn (int); static void emit_block_move_via_loop (rtx, rtx, rtx, unsigned); static rtx clear_by_pieces_1 (void *, HOST_WIDE_INT, machine_mode); static void clear_by_pieces (rtx, unsigned HOST_WIDE_INT, unsigned int); static void store_by_pieces_1 (struct store_by_pieces_d *, unsigned int); static void store_by_pieces_2 (insn_gen_fn, machine_mode, struct store_by_pieces_d *); -static tree clear_storage_libcall_fn (int); static rtx_insn *compress_float_constant (rtx, rtx); static rtx get_subtarget (rtx); static void store_constructor_field (rtx, unsigned HOST_WIDE_INT, @@ -1132,7 +1130,7 @@ emit_block_move_hints (rtx x, rtx y, rtx size, enum block_op_methods method, mark_addressable (y_expr); if (x_expr) mark_addressable (x_expr); - retval = emit_block_move_via_libcall (x, y, size, + retval = emit_block_copy_via_libcall (x, y, size, method == BLOCK_OP_TAILCALL); } @@ -1175,7 +1173,7 @@ block_move_libcall_safe_for_call_parm (void) /* If registers go on the stack anyway, any argument is sure to clobber an outgoing argument. */ #if defined (REG_PARM_STACK_SPACE) - fn = emit_block_move_libcall_fn (false); + fn = builtin_decl_implicit (BUILT_IN_MEMCPY); /* Avoid set but not used warning if *REG_PARM_STACK_SPACE doesn't depend on its argument. */ (void) fn; @@ -1191,7 +1189,7 @@ block_move_libcall_safe_for_call_parm (void) cumulative_args_t args_so_far; tree fn, arg; - fn = emit_block_move_libcall_fn (false); + fn = builtin_decl_implicit (BUILT_IN_MEMCPY); INIT_CUMULATIVE_ARGS (args_so_far_v, TREE_TYPE (fn), NULL_RTX, 0, 3); args_so_far = pack_cumulative_args (&args_so_far_v); @@ -1310,106 +1308,6 @@ emit_block_move_via_movmem (rtx x, rtx y, rtx size, unsigned int align, return false; } -/* A subroutine of emit_block_move. Expand a call to memcpy. - Return the return value from memcpy, 0 otherwise. */ - -rtx -emit_block_move_via_libcall (rtx dst, rtx src, rtx size, bool tailcall) -{ - rtx dst_addr, src_addr; - tree call_expr, fn, src_tree, dst_tree, size_tree; - machine_mode size_mode; - rtx retval; - - /* Emit code to copy the addresses of DST and SRC and SIZE into new - pseudos. We can then place those new pseudos into a VAR_DECL and - use them later. */ - - dst_addr = copy_addr_to_reg (XEXP (dst, 0)); - src_addr = copy_addr_to_reg (XEXP (src, 0)); - - dst_addr = convert_memory_address (ptr_mode, dst_addr); - src_addr = convert_memory_address (ptr_mode, src_addr); - - dst_tree = make_tree (ptr_type_node, dst_addr); - src_tree = make_tree (ptr_type_node, src_addr); - - size_mode = TYPE_MODE (sizetype); - - size = convert_to_mode (size_mode, size, 1); - size = copy_to_mode_reg (size_mode, size); - - /* It is incorrect to use the libcall calling conventions to call - memcpy in this context. This could be a user call to memcpy and - the user may wish to examine the return value from memcpy. For - targets where libcalls and normal calls have different conventions - for returning pointers, we could end up generating incorrect code. */ - - size_tree = make_tree (sizetype, size); - - fn = emit_block_move_libcall_fn (true); - call_expr = build_call_expr (fn, 3, dst_tree, src_tree, size_tree); - CALL_EXPR_TAILCALL (call_expr) = tailcall; - - retval = expand_normal (call_expr); - - return retval; -} - -/* A subroutine of emit_block_move_via_libcall. Create the tree node - for the function we use for block copies. */ - -static GTY(()) tree block_move_fn; - -void -init_block_move_fn (const char *asmspec) -{ - if (!block_move_fn) - { - tree args, fn, attrs, attr_args; - - fn = get_identifier ("memcpy"); - args = build_function_type_list (ptr_type_node, ptr_type_node, - const_ptr_type_node, sizetype, - NULL_TREE); - - fn = build_decl (UNKNOWN_LOCATION, FUNCTION_DECL, fn, args); - DECL_EXTERNAL (fn) = 1; - TREE_PUBLIC (fn) = 1; - DECL_ARTIFICIAL (fn) = 1; - TREE_NOTHROW (fn) = 1; - DECL_VISIBILITY (fn) = VISIBILITY_DEFAULT; - DECL_VISIBILITY_SPECIFIED (fn) = 1; - - attr_args = build_tree_list (NULL_TREE, build_string (1, "1")); - attrs = tree_cons (get_identifier ("fn spec"), attr_args, NULL); - - decl_attributes (&fn, attrs, ATTR_FLAG_BUILT_IN); - - block_move_fn = fn; - } - - if (asmspec) - set_user_assembler_name (block_move_fn, asmspec); -} - -static tree -emit_block_move_libcall_fn (int for_call) -{ - static bool emitted_extern; - - if (!block_move_fn) - init_block_move_fn (NULL); - - if (for_call && !emitted_extern) - { - emitted_extern = true; - make_decl_rtl (block_move_fn); - } - - return block_move_fn; -} - /* A subroutine of emit_block_move. Copy the data via an explicit loop. This is used only when libcalls are forbidden. */ /* ??? It'd be nice to copy in hunks larger than QImode. */ @@ -1464,6 +1362,39 @@ emit_block_move_via_loop (rtx x, rtx y, rtx size, true, top_label, REG_BR_PROB_BASE * 90 / 100); } +/* Expand a call to memcpy or memmove or memcmp, and return the result. + TAILCALL is true if this is a tail call. */ + +rtx +emit_block_op_via_libcall (enum built_in_function fncode, rtx dst, rtx src, + rtx size, bool tailcall) +{ + rtx dst_addr, src_addr; + tree call_expr, dst_tree, src_tree, size_tree; + machine_mode size_mode; + + dst_addr = copy_addr_to_reg (XEXP (dst, 0)); + dst_addr = convert_memory_address (ptr_mode, dst_addr); + dst_tree = make_tree (ptr_type_node, dst_addr); + + src_addr = copy_addr_to_reg (XEXP (src, 0)); + src_addr = convert_memory_address (ptr_mode, src_addr); + src_tree = make_tree (ptr_type_node, src_addr); + + size_mode = TYPE_MODE (sizetype); + size = convert_to_mode (size_mode, size, 1); + size = copy_to_mode_reg (size_mode, size); + size_tree = make_tree (sizetype, size); + + /* It is incorrect to use the libcall calling conventions for calls to + memcpy/memmove/memcmp because they can be provided by the user. */ + tree fn = builtin_decl_implicit (fncode); + call_expr = build_call_expr (fn, 3, dst_tree, src_tree, size_tree); + CALL_EXPR_TAILCALL (call_expr) = tailcall; + + return expand_call (call_expr, NULL_RTX, false); +} + /* Copy all or part of a value X into registers starting at REGNO. The number of registers to be filled is NREGS. */ @@ -2784,85 +2715,26 @@ set_storage_via_libcall (rtx object, rtx size, rtx val, bool tailcall) { tree call_expr, fn, object_tree, size_tree, val_tree; machine_mode size_mode; - rtx retval; - - /* Emit code to copy OBJECT and SIZE into new pseudos. We can then - place those into new pseudos into a VAR_DECL and use them later. */ object = copy_addr_to_reg (XEXP (object, 0)); + object_tree = make_tree (ptr_type_node, object); + + if (!CONST_INT_P (val)) + val = convert_to_mode (TYPE_MODE (integer_type_node), val, 1); + val_tree = make_tree (integer_type_node, val); size_mode = TYPE_MODE (sizetype); size = convert_to_mode (size_mode, size, 1); size = copy_to_mode_reg (size_mode, size); - - /* It is incorrect to use the libcall calling conventions to call - memset in this context. This could be a user call to memset and - the user may wish to examine the return value from memset. For - targets where libcalls and normal calls have different conventions - for returning pointers, we could end up generating incorrect code. */ - - object_tree = make_tree (ptr_type_node, object); - if (!CONST_INT_P (val)) - val = convert_to_mode (TYPE_MODE (integer_type_node), val, 1); size_tree = make_tree (sizetype, size); - val_tree = make_tree (integer_type_node, val); - fn = clear_storage_libcall_fn (true); + /* It is incorrect to use the libcall calling conventions for calls to + memset because it can be provided by the user. */ + fn = builtin_decl_implicit (BUILT_IN_MEMSET); call_expr = build_call_expr (fn, 3, object_tree, val_tree, size_tree); CALL_EXPR_TAILCALL (call_expr) = tailcall; - retval = expand_normal (call_expr); - - return retval; -} - -/* A subroutine of set_storage_via_libcall. Create the tree node - for the function we use for block clears. */ - -tree block_clear_fn; - -void -init_block_clear_fn (const char *asmspec) -{ - if (!block_clear_fn) - { - tree fn, args; - - fn = get_identifier ("memset"); - args = build_function_type_list (ptr_type_node, ptr_type_node, - integer_type_node, sizetype, - NULL_TREE); - - fn = build_decl (UNKNOWN_LOCATION, FUNCTION_DECL, fn, args); - DECL_EXTERNAL (fn) = 1; - TREE_PUBLIC (fn) = 1; - DECL_ARTIFICIAL (fn) = 1; - TREE_NOTHROW (fn) = 1; - DECL_VISIBILITY (fn) = VISIBILITY_DEFAULT; - DECL_VISIBILITY_SPECIFIED (fn) = 1; - - block_clear_fn = fn; - } - - if (asmspec) - set_user_assembler_name (block_clear_fn, asmspec); -} - -static tree -clear_storage_libcall_fn (int for_call) -{ - static bool emitted_extern; - - if (!block_clear_fn) - init_block_clear_fn (NULL); - - if (for_call && !emitted_extern) - { - emitted_extern = true; - make_decl_rtl (block_clear_fn); - } - - return block_clear_fn; + return expand_call (call_expr, NULL_RTX, false); } /* Expand a setmem pattern; return true if successful. */ @@ -5157,12 +5029,7 @@ expand_assignment (tree to, tree from, bool nontemporal) size = expr_size (from); from_rtx = expand_normal (from); - emit_library_call (memmove_libfunc, LCT_NORMAL, - VOIDmode, 3, XEXP (to_rtx, 0), Pmode, - XEXP (from_rtx, 0), Pmode, - convert_to_mode (TYPE_MODE (sizetype), - size, TYPE_UNSIGNED (sizetype)), - TYPE_MODE (sizetype)); + emit_block_move_via_libcall (XEXP (to_rtx, 0), XEXP (from_rtx, 0), size); preserve_temp_slots (to_rtx); pop_temp_slots (); @@ -11653,5 +11520,3 @@ int_expr_size (tree exp) return tree_to_shwi (size); } - -#include "gt-expr.h" |