builtins.c (expand_builtin_memcmp): Do not emit the call here.
authorEric Botcazou <ebotcazou@adacore.com>
Fri, 13 May 2016 08:49:20 +0000 (08:49 +0000)
committerEric Botcazou <ebotcazou@gcc.gnu.org>
Fri, 13 May 2016 08:49:20 +0000 (08:49 +0000)
* 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.

From-SVN: r236195

14 files changed:
gcc/ChangeLog
gcc/builtins.c
gcc/config/alpha/alpha.c
gcc/config/i386/i386.c
gcc/config/ia64/ia64.c
gcc/dse.c
gcc/except.c
gcc/expr.c
gcc/expr.h
gcc/libfuncs.h
gcc/optabs-libfuncs.c
gcc/optabs.c
gcc/tree-core.h
gcc/tree.c

index 65014e939bf504112bf67a982841a0c39e6d84e1..d21e5da771577b7ecf7a16ee8cd1ae584d1500b0 100644 (file)
@@ -1,3 +1,63 @@
+2016-05-13  Eric Botcazou  <ebotcazou@adacore.com>
+
+       * 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.
+
 2016-05-12  Uros Bizjak  <ubizjak@gmail.com>
 
        * config/i386/i386.md (*call_got_x32): Change operand 0 to
index 476feb1eb164e4c5cdd22e2526bd1786f115dca6..931d4a6b7bc24b57c7f5d9b10bc8bff5027e18a6 100644 (file)
@@ -3757,20 +3757,7 @@ expand_builtin_memcmp (tree exp, rtx target)
       return convert_to_mode (mode, result, 0);
     }
 
-  result = target;
-  if (! (result != 0
-        && REG_P (result) && GET_MODE (result) == mode
-        && REGNO (result) >= FIRST_PSEUDO_REGISTER))
-    result = gen_reg_rtx (mode);
-
-  emit_library_call_value (memcmp_libfunc, result, LCT_PURE,
-                          TYPE_MODE (integer_type_node), 3,
-                          XEXP (arg1_rtx, 0), Pmode,
-                          XEXP (arg2_rtx, 0), Pmode,
-                          convert_to_mode (TYPE_MODE (sizetype), arg3_rtx,
-                                           TYPE_UNSIGNED (sizetype)),
-                          TYPE_MODE (sizetype));
-  return result;
+  return NULL_RTX;
 }
 
 /* Expand expression EXP, which is a call to the strcmp builtin.  Return NULL_RTX
@@ -4455,7 +4442,12 @@ expand_builtin_trap (void)
        add_reg_note (insn, REG_ARGS_SIZE, GEN_INT (stack_pointer_delta));
     }
   else
-    emit_library_call (abort_libfunc, LCT_NORETURN, VOIDmode, 0);
+    {
+      tree fn = builtin_decl_implicit (BUILT_IN_ABORT);
+      tree call_expr = build_call_expr (fn, 0);
+      expand_call (call_expr, NULL_RTX, false);
+    }
+
   emit_barrier ();
 }
 
@@ -9888,42 +9880,19 @@ fold_call_stmt (gcall *stmt, bool ignore)
 void
 set_builtin_user_assembler_name (tree decl, const char *asmspec)
 {
-  tree builtin;
   gcc_assert (TREE_CODE (decl) == FUNCTION_DECL
              && DECL_BUILT_IN_CLASS (decl) == BUILT_IN_NORMAL
              && asmspec != 0);
 
-  builtin = builtin_decl_explicit (DECL_FUNCTION_CODE (decl));
+  tree builtin = builtin_decl_explicit (DECL_FUNCTION_CODE (decl));
   set_user_assembler_name (builtin, asmspec);
-  switch (DECL_FUNCTION_CODE (decl))
+
+  if (DECL_FUNCTION_CODE (decl) == BUILT_IN_FFS
+      && INT_TYPE_SIZE < BITS_PER_WORD)
     {
-    case BUILT_IN_MEMCPY:
-      init_block_move_fn (asmspec);
-      memcpy_libfunc = set_user_assembler_libfunc ("memcpy", asmspec);
-      break;
-    case BUILT_IN_MEMSET:
-      init_block_clear_fn (asmspec);
-      memset_libfunc = set_user_assembler_libfunc ("memset", asmspec);
-      break;
-    case BUILT_IN_MEMMOVE:
-      memmove_libfunc = set_user_assembler_libfunc ("memmove", asmspec);
-      break;
-    case BUILT_IN_MEMCMP:
-      memcmp_libfunc = set_user_assembler_libfunc ("memcmp", asmspec);
-      break;
-    case BUILT_IN_ABORT:
-      abort_libfunc = set_user_assembler_libfunc ("abort", asmspec);
-      break;
-    case BUILT_IN_FFS:
-      if (INT_TYPE_SIZE < BITS_PER_WORD)
-       {
-         set_user_assembler_libfunc ("ffs", asmspec);
-         set_optab_libfunc (ffs_optab, mode_for_size (INT_TYPE_SIZE,
-                                                      MODE_INT, 0), "ffs");
-       }
-      break;
-    default:
-      break;
+      set_user_assembler_libfunc ("ffs", asmspec);
+      set_optab_libfunc (ffs_optab, mode_for_size (INT_TYPE_SIZE, MODE_INT, 0),
+                        "ffs");
     }
 }
 
index e023d3bc2787625cdfc0bcff31c1f062f6a66473..94fed1029ba21c342274de9d00f5f27a7eb80dd9 100644 (file)
@@ -9752,8 +9752,6 @@ alpha_init_libfuncs (void)
       set_optab_libfunc (smod_optab, DImode, "OTS$REM_L");
       set_optab_libfunc (umod_optab, SImode, "OTS$REM_UI");
       set_optab_libfunc (umod_optab, DImode, "OTS$REM_UL");
-      abort_libfunc = init_one_libfunc ("decc$abort");
-      memcmp_libfunc = init_one_libfunc ("decc$memcmp");
 #ifdef MEM_LIBFUNCS_INIT
       MEM_LIBFUNCS_INIT;
 #endif
index 046717bae45df34cc13878230701c19d4b9dfc9e..44580149f3966ff690dfad20ecce59761df59d74 100644 (file)
@@ -26908,7 +26908,7 @@ ix86_expand_set_or_movmem (rtx dst, rtx src, rtx count_exp, rtx val_exp,
        {
          if (UINTVAL (count_exp) >= (unsigned HOST_WIDE_INT)dynamic_check)
            {
-             emit_block_move_via_libcall (dst, src, count_exp, false);
+             emit_block_copy_via_libcall (dst, src, count_exp);
              count_exp = const0_rtx;
              goto epilogue;
            }
@@ -26923,9 +26923,9 @@ ix86_expand_set_or_movmem (rtx dst, rtx src, rtx count_exp, rtx val_exp,
                                   1, hot_label);
          predict_jump (REG_BR_PROB_BASE * 90 / 100);
          if (issetmem)
-           set_storage_via_libcall (dst, count_exp, val_exp, false);
+           set_storage_via_libcall (dst, count_exp, val_exp);
          else
-           emit_block_move_via_libcall (dst, src, count_exp, false);
+           emit_block_copy_via_libcall (dst, src, count_exp);
          emit_jump (jump_around_label);
          emit_label (hot_label);
        }
index 3fcc3b5385d6af73c1fb227c04bcca3142c30544..742123f401e044bdb593775ebf2da4093e8ca9cd 100644 (file)
@@ -10624,8 +10624,6 @@ ia64_vms_init_libfuncs (void)
   set_optab_libfunc (smod_optab, DImode, "OTS$REM_L");
   set_optab_libfunc (umod_optab, SImode, "OTS$REM_UI");
   set_optab_libfunc (umod_optab, DImode, "OTS$REM_UL");
-  abort_libfunc = init_one_libfunc ("decc$abort");
-  memcmp_libfunc = init_one_libfunc ("decc$memcmp");
 #ifdef MEM_LIBFUNCS_INIT
   MEM_LIBFUNCS_INIT;
 #endif
index b03616102b5137138966becb851c8058d358f42a..68d06bb444fcb65aad165e79ddffae1aecccf5d6 100644 (file)
--- a/gcc/dse.c
+++ b/gcc/dse.c
@@ -2269,6 +2269,7 @@ scan_insn (bb_info_t bb_info, rtx_insn *insn)
   if (CALL_P (insn))
     {
       bool const_call;
+      rtx call, sym;
       tree memset_call = NULL_TREE;
 
       insn_info->cannot_delete = true;
@@ -2278,24 +2279,16 @@ scan_insn (bb_info_t bb_info, rtx_insn *insn)
         been pushed onto the stack.
         memset and bzero don't read memory either.  */
       const_call = RTL_CONST_CALL_P (insn);
-      if (!const_call)
-       {
-         rtx call = get_call_rtx_from (insn);
-         if (call && GET_CODE (XEXP (XEXP (call, 0), 0)) == SYMBOL_REF)
-           {
-             rtx symbol = XEXP (XEXP (call, 0), 0);
-             if (SYMBOL_REF_DECL (symbol)
-                 && TREE_CODE (SYMBOL_REF_DECL (symbol)) == FUNCTION_DECL)
-               {
-                 if ((DECL_BUILT_IN_CLASS (SYMBOL_REF_DECL (symbol))
-                      == BUILT_IN_NORMAL
-                      && (DECL_FUNCTION_CODE (SYMBOL_REF_DECL (symbol))
-                          == BUILT_IN_MEMSET))
-                     || SYMBOL_REF_DECL (symbol) == block_clear_fn)
-                   memset_call = SYMBOL_REF_DECL (symbol);
-               }
-           }
-       }
+      if (!const_call
+         && (call = get_call_rtx_from (insn))
+         && (sym = XEXP (XEXP (call, 0), 0))
+         && GET_CODE (sym) == SYMBOL_REF
+         && SYMBOL_REF_DECL (sym)
+         && TREE_CODE (SYMBOL_REF_DECL (sym)) == FUNCTION_DECL
+         && DECL_BUILT_IN_CLASS (SYMBOL_REF_DECL (sym)) == BUILT_IN_NORMAL
+         && DECL_FUNCTION_CODE (SYMBOL_REF_DECL (sym)) == BUILT_IN_MEMSET)
+       memset_call = SYMBOL_REF_DECL (sym);
+
       if (const_call || memset_call)
        {
          insn_info_t i_ptr = active_local_stores;
index cf1df8cc6ecb9a7354a03f6b5fdc6b45b1b7c467..e494915514f464634278fafa09bc0608f1f30ccd 100644 (file)
@@ -130,6 +130,7 @@ along with GCC; see the file COPYING3.  If not see
 #include "explow.h"
 #include "stmt.h"
 #include "expr.h"
+#include "calls.h"
 #include "libfuncs.h"
 #include "except.h"
 #include "output.h"
@@ -1173,20 +1174,22 @@ sjlj_emit_function_enter (rtx_code_label *dispatch_label)
 
   if (dispatch_label)
     {
+      rtx addr = plus_constant (Pmode, XEXP (fc, 0), sjlj_fc_jbuf_ofs);
+
 #ifdef DONT_USE_BUILTIN_SETJMP
-      rtx x;
-      x = emit_library_call_value (setjmp_libfunc, NULL_RTX, LCT_RETURNS_TWICE,
-                                  TYPE_MODE (integer_type_node), 1,
-                                  plus_constant (Pmode, XEXP (fc, 0),
-                                                 sjlj_fc_jbuf_ofs), Pmode);
+      addr = copy_addr_to_reg (addr);
+      addr = convert_memory_address (ptr_mode, addr);
+      tree addr_tree = make_tree (ptr_type_node, addr);
+
+      tree fn = builtin_decl_implicit (BUILT_IN_SETJMP);
+      tree call_expr = build_call_expr (fn, 1, addr_tree);
+      rtx x = expand_call (call_expr, NULL_RTX, false);
 
       emit_cmp_and_jump_insns (x, const0_rtx, NE, 0,
                               TYPE_MODE (integer_type_node), 0,
                               dispatch_label, REG_BR_PROB_BASE / 100);
 #else
-      expand_builtin_setjmp_setup (plus_constant (Pmode, XEXP (fc, 0),
-                                                 sjlj_fc_jbuf_ofs),
-                                  dispatch_label);
+      expand_builtin_setjmp_setup (addr, dispatch_label);
 #endif
     }
 
index 812c5445278dd61972fe20702232def7075e4a7c..2f5a895015a9fef653f7803b70eeadac512f6bec 100644 (file)
@@ -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);
 }
 \f
+/* 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);
+}
+\f
 /* 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);
 }
 \f
 /* 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"
index c5b302a383bf4c6cf5c79559cc2e16cd7cee5a49..fea69a27e3aa29819b52b682a99936ea65234ac5 100644 (file)
@@ -71,8 +71,29 @@ extern rtx convert_to_mode (machine_mode, rtx, int);
 /* Convert an rtx to MODE from OLDMODE and return the result.  */
 extern rtx convert_modes (machine_mode, machine_mode, rtx, int);
 
-/* Emit code to move a block Y to a block X.  */
+/* Expand a call to memcpy or memmove or memcmp, and return the result.  */
+extern rtx emit_block_op_via_libcall (enum built_in_function, rtx, rtx, rtx,
+                                     bool);
+
+static inline rtx
+emit_block_copy_via_libcall (rtx dst, rtx src, rtx size, bool tailcall = false)
+{
+  return emit_block_op_via_libcall (BUILT_IN_MEMCPY, dst, src, size, tailcall);
+}
 
+static inline rtx
+emit_block_move_via_libcall (rtx dst, rtx src, rtx size, bool tailcall = false)
+{
+  return emit_block_op_via_libcall (BUILT_IN_MEMMOVE, dst, src, size, tailcall);
+}
+
+static inline rtx
+emit_block_comp_via_libcall (rtx dst, rtx src, rtx size, bool tailcall = false)
+{
+  return emit_block_op_via_libcall (BUILT_IN_MEMCMP, dst, src, size, tailcall);
+}
+
+/* Emit code to move a block Y to a block X.  */
 enum block_op_methods
 {
   BLOCK_OP_NORMAL,
@@ -82,12 +103,7 @@ enum block_op_methods
   BLOCK_OP_TAILCALL
 };
 
-extern GTY(()) tree block_clear_fn;
-extern void init_block_move_fn (const char *);
-extern void init_block_clear_fn (const char *);
-
 extern rtx emit_block_move (rtx, rtx, rtx, enum block_op_methods);
-extern rtx emit_block_move_via_libcall (rtx, rtx, rtx, bool);
 extern rtx emit_block_move_hints (rtx, rtx, rtx, enum block_op_methods,
                                  unsigned int, HOST_WIDE_INT,
                                  unsigned HOST_WIDE_INT,
@@ -166,7 +182,7 @@ extern rtx clear_storage_hints (rtx, rtx, enum block_op_methods,
                                unsigned HOST_WIDE_INT,
                                unsigned HOST_WIDE_INT);
 /* The same, but always output an library call.  */
-rtx set_storage_via_libcall (rtx, rtx, rtx, bool);
+extern rtx set_storage_via_libcall (rtx, rtx, rtx, bool = false);
 
 /* Expand a setmem pattern; return true if successful.  */
 extern bool set_storage_via_setmem (rtx, rtx, rtx, unsigned int,
index 4211a457df5cfa4a27e419c80a8d450e7241538e..8250d5b001795b30f2575c2ea30ae229d76939c0 100644 (file)
@@ -24,25 +24,9 @@ along with GCC; see the file COPYING3.  If not see
 /* Enumeration of indexes into libfunc_table.  */
 enum libfunc_index
 {
-  LTI_abort,
-  LTI_memcpy,
-  LTI_memmove,
-  LTI_memcmp,
-  LTI_memset,
-  LTI_setbits,
-
-  LTI_setjmp,
-  LTI_longjmp,
   LTI_unwind_sjlj_register,
   LTI_unwind_sjlj_unregister,
-
-  LTI_profile_function_entry,
-  LTI_profile_function_exit,
-
   LTI_synchronize,
-
-  LTI_gcov_flush,
-
   LTI_MAX
 };
 
@@ -89,26 +73,11 @@ extern struct target_libfuncs *this_target_libfuncs;
 
 /* Accessor macros for libfunc_table.  */
 
-#define abort_libfunc  (libfunc_table[LTI_abort])
-#define memcpy_libfunc (libfunc_table[LTI_memcpy])
-#define memmove_libfunc        (libfunc_table[LTI_memmove])
-#define memcmp_libfunc (libfunc_table[LTI_memcmp])
-#define memset_libfunc (libfunc_table[LTI_memset])
-#define setbits_libfunc        (libfunc_table[LTI_setbits])
-
-#define setjmp_libfunc (libfunc_table[LTI_setjmp])
-#define longjmp_libfunc        (libfunc_table[LTI_longjmp])
 #define unwind_sjlj_register_libfunc (libfunc_table[LTI_unwind_sjlj_register])
 #define unwind_sjlj_unregister_libfunc \
   (libfunc_table[LTI_unwind_sjlj_unregister])
-
-#define profile_function_entry_libfunc (libfunc_table[LTI_profile_function_entry])
-#define profile_function_exit_libfunc  (libfunc_table[LTI_profile_function_exit])
-
 #define synchronize_libfunc    (libfunc_table[LTI_synchronize])
 
-#define gcov_flush_libfunc     (libfunc_table[LTI_gcov_flush])
-
 /* In explow.c */
 extern void set_stack_check_libfunc (const char *);
 
index b300096baa08a7cbe77e8cfa2b6160bd4feb840d..79a07d68b2c90a941392bef4281d765e6338de79 100644 (file)
@@ -731,14 +731,15 @@ static GTY (()) hash_table<libfunc_decl_hasher> *libfunc_decls;
 tree
 build_libfunc_function (const char *name)
 {
+  /* ??? We don't have any type information; pretend this is "int foo ()".  */
   tree decl = build_decl (UNKNOWN_LOCATION, FUNCTION_DECL,
                          get_identifier (name),
                          build_function_type (integer_type_node, NULL_TREE));
-  /* ??? We don't have any type information except for this is
-     a function.  Pretend this is "int foo ()".  */
-  DECL_ARTIFICIAL (decl) = 1;
   DECL_EXTERNAL (decl) = 1;
   TREE_PUBLIC (decl) = 1;
+  DECL_ARTIFICIAL (decl) = 1;
+  DECL_VISIBILITY (decl) = VISIBILITY_DEFAULT;
+  DECL_VISIBILITY_SPECIFIED (decl) = 1;
   gcc_assert (DECL_ASSEMBLER_NAME (decl));
 
   /* Zap the nonsensical SYMBOL_REF_DECL for this.  What we're left with
@@ -887,32 +888,10 @@ init_optabs (void)
     set_optab_libfunc (abs_optab, TYPE_MODE (complex_double_type_node),
                       "cabs");
 
-  abort_libfunc = init_one_libfunc ("abort");
-  memcpy_libfunc = init_one_libfunc ("memcpy");
-  memmove_libfunc = init_one_libfunc ("memmove");
-  memcmp_libfunc = init_one_libfunc ("memcmp");
-  memset_libfunc = init_one_libfunc ("memset");
-  setbits_libfunc = init_one_libfunc ("__setbits");
-
-#ifndef DONT_USE_BUILTIN_SETJMP
-  setjmp_libfunc = init_one_libfunc ("__builtin_setjmp");
-  longjmp_libfunc = init_one_libfunc ("__builtin_longjmp");
-#else
-  setjmp_libfunc = init_one_libfunc ("setjmp");
-  longjmp_libfunc = init_one_libfunc ("longjmp");
-#endif
   unwind_sjlj_register_libfunc = init_one_libfunc ("_Unwind_SjLj_Register");
   unwind_sjlj_unregister_libfunc
     = init_one_libfunc ("_Unwind_SjLj_Unregister");
 
-  /* For function entry/exit instrumentation.  */
-  profile_function_entry_libfunc
-    = init_one_libfunc ("__cyg_profile_func_enter");
-  profile_function_exit_libfunc
-    = init_one_libfunc ("__cyg_profile_func_exit");
-
-  gcov_flush_libfunc = init_one_libfunc ("__gcov_flush");
-
   /* Allow the target to add more libcalls or rename some, etc.  */
   targetm.init_libfuncs ();
 }
index a6d8822b87edc4f6cfe404e9a9e1bba707926e7d..2bd81db5166201f68c2fbf40e6a2a2e0e7442785 100644 (file)
@@ -3776,8 +3776,6 @@ prepare_cmp_insn (rtx x, rtx y, enum rtx_code comparison, rtx size,
     {
       machine_mode result_mode;
       enum insn_code cmp_code;
-      tree length_type;
-      rtx libfunc;
       rtx result;
       rtx opalign
        = GEN_INT (MIN (MEM_ALIGN (x), MEM_ALIGN (y)) / BITS_PER_UNIT);
@@ -3818,22 +3816,12 @@ prepare_cmp_insn (rtx x, rtx y, enum rtx_code comparison, rtx size,
       if (methods != OPTAB_LIB && methods != OPTAB_LIB_WIDEN)
        goto fail;
 
-      /* Otherwise call a library function, memcmp.  */
-      libfunc = memcmp_libfunc;
-      length_type = sizetype;
-      result_mode = TYPE_MODE (integer_type_node);
-      cmp_mode = TYPE_MODE (length_type);
-      size = convert_to_mode (TYPE_MODE (length_type), size,
-                             TYPE_UNSIGNED (length_type));
-
-      result = emit_library_call_value (libfunc, 0, LCT_PURE,
-                                       result_mode, 3,
-                                       XEXP (x, 0), Pmode,
-                                       XEXP (y, 0), Pmode,
-                                       size, cmp_mode);
+      /* Otherwise call a library function.  */
+      result = emit_block_comp_via_libcall (XEXP (x, 0), XEXP (y, 0), size);
+
       x = result;
       y = const0_rtx;
-      mode = result_mode;
+      mode = TYPE_MODE (integer_type_node);
       methods = OPTAB_LIB_WIDEN;
       unsignedp = false;
     }
index ea832fa5344ebad466bfab02054fb090212b8f7b..e4c5068241b1781943f8a2ca87375acb649cfcd8 100644 (file)
@@ -81,11 +81,14 @@ struct die_struct;
 /* The function does not lead to calls within current function unit.  */
 #define ECF_LEAF                 (1 << 10)
 
+/* Nonzero if this call returns its first argument.  */
+#define ECF_RET1                 (1 << 11)
+
 /* Nonzero if this call does not affect transactions.  */
-#define ECF_TM_PURE              (1 << 11)
+#define ECF_TM_PURE              (1 << 12)
 
 /* Nonzero if this call is into the transaction runtime library.  */
-#define ECF_TM_BUILTIN           (1 << 12)
+#define ECF_TM_BUILTIN           (1 << 13)
 
 /* Call argument flags.  */
 /* Nonzero if the argument is not dereferenced recursively, thus only
index b63f64cd96d5add2ce4ea3283a5f069d0ba19d2d..4e0000416d860b6d43b9502f6bf633af299007b7 100644 (file)
@@ -10451,6 +10451,11 @@ set_call_expr_flags (tree decl, int flags)
   if (flags & ECF_LEAF)
     DECL_ATTRIBUTES (decl) = tree_cons (get_identifier ("leaf"),
                                        NULL, DECL_ATTRIBUTES (decl));
+  if (flags & ECF_RET1)
+    DECL_ATTRIBUTES (decl)
+      = tree_cons (get_identifier ("fn spec"),
+                  build_tree_list (NULL_TREE, build_string (1, "1")),
+                  DECL_ATTRIBUTES (decl));
   if ((flags & ECF_TM_PURE) && flag_tm)
     apply_tm_attr (decl, get_identifier ("transaction_pure"));
   /* Looping const or pure is implied by noreturn.
@@ -10486,13 +10491,20 @@ build_common_builtin_nodes (void)
   tree tmp, ftype;
   int ecf_flags;
 
-  if (!builtin_decl_explicit_p (BUILT_IN_UNREACHABLE))
+  if (!builtin_decl_explicit_p (BUILT_IN_UNREACHABLE)
+      || !builtin_decl_explicit_p (BUILT_IN_ABORT))
     {
       ftype = build_function_type (void_type_node, void_list_node);
-      local_define_builtin ("__builtin_unreachable", ftype, BUILT_IN_UNREACHABLE,
-                           "__builtin_unreachable",
-                           ECF_NOTHROW | ECF_LEAF | ECF_NORETURN
-                           | ECF_CONST);
+      if (!builtin_decl_explicit_p (BUILT_IN_UNREACHABLE))
+       local_define_builtin ("__builtin_unreachable", ftype,
+                             BUILT_IN_UNREACHABLE,
+                             "__builtin_unreachable",
+                             ECF_NOTHROW | ECF_LEAF | ECF_NORETURN
+                             | ECF_CONST);
+      if (!builtin_decl_explicit_p (BUILT_IN_ABORT))
+       local_define_builtin ("__builtin_abort", ftype, BUILT_IN_ABORT,
+                             "abort",
+                             ECF_LEAF | ECF_NORETURN | ECF_CONST);
     }
 
   if (!builtin_decl_explicit_p (BUILT_IN_MEMCPY)
@@ -10504,10 +10516,10 @@ build_common_builtin_nodes (void)
 
       if (!builtin_decl_explicit_p (BUILT_IN_MEMCPY))
        local_define_builtin ("__builtin_memcpy", ftype, BUILT_IN_MEMCPY,
-                             "memcpy", ECF_NOTHROW | ECF_LEAF);
+                             "memcpy", ECF_NOTHROW | ECF_LEAF | ECF_RET1);
       if (!builtin_decl_explicit_p (BUILT_IN_MEMMOVE))
        local_define_builtin ("__builtin_memmove", ftype, BUILT_IN_MEMMOVE,
-                             "memmove", ECF_NOTHROW | ECF_LEAF);
+                             "memmove", ECF_NOTHROW | ECF_LEAF | ECF_RET1);
     }
 
   if (!builtin_decl_explicit_p (BUILT_IN_MEMCMP))
@@ -10525,15 +10537,19 @@ build_common_builtin_nodes (void)
                                        ptr_type_node, integer_type_node,
                                        size_type_node, NULL_TREE);
       local_define_builtin ("__builtin_memset", ftype, BUILT_IN_MEMSET,
-                           "memset", ECF_NOTHROW | ECF_LEAF);
+                           "memset", ECF_NOTHROW | ECF_LEAF | ECF_RET1);
     }
 
+  /* If we're checking the stack, `alloca' can throw.  */
+  const int alloca_flags
+    = ECF_MALLOC | ECF_LEAF | (flag_stack_check ? 0 : ECF_NOTHROW);
+
   if (!builtin_decl_explicit_p (BUILT_IN_ALLOCA))
     {
       ftype = build_function_type_list (ptr_type_node,
                                        size_type_node, NULL_TREE);
       local_define_builtin ("__builtin_alloca", ftype, BUILT_IN_ALLOCA,
-                           "alloca", ECF_MALLOC | ECF_NOTHROW | ECF_LEAF);
+                           "alloca", alloca_flags);
     }
 
   ftype = build_function_type_list (ptr_type_node, size_type_node,
@@ -10541,14 +10557,7 @@ build_common_builtin_nodes (void)
   local_define_builtin ("__builtin_alloca_with_align", ftype,
                        BUILT_IN_ALLOCA_WITH_ALIGN,
                        "__builtin_alloca_with_align",
-                       ECF_MALLOC | ECF_NOTHROW | ECF_LEAF);
-
-  /* If we're checking the stack, `alloca' can throw.  */
-  if (flag_stack_check)
-    {
-      TREE_NOTHROW (builtin_decl_explicit (BUILT_IN_ALLOCA)) = 0;
-      TREE_NOTHROW (builtin_decl_explicit (BUILT_IN_ALLOCA_WITH_ALIGN)) = 0;
-    }
+                       alloca_flags);
 
   ftype = build_function_type_list (void_type_node,
                                    ptr_type_node, ptr_type_node,