OSDN Git Service

* ggc.h (GGC_RESIZEVAR): New, reorder macros.
[pf3gnuchains/gcc-fork.git] / gcc / calls.c
index d9ba08c..e7799f0 100644 (file)
@@ -7,7 +7,7 @@ This file is part of GCC.
 
 GCC is free software; you can redistribute it and/or modify it under
 the terms of the GNU General Public License as published by the Free
-Software Foundation; either version 2, or (at your option) any later
+Software Foundation; either version 3, or (at your option) any later
 version.
 
 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
@@ -16,9 +16,8 @@ FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 for more details.
 
 You should have received a copy of the GNU General Public License
-along with GCC; see the file COPYING.  If not, write to the Free
-Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
-02110-1301, USA.  */
+along with GCC; see the file COPYING3.  If not see
+<http://www.gnu.org/licenses/>.  */
 
 #include "config.h"
 #include "system.h"
@@ -41,6 +40,7 @@ Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
 #include "target.h"
 #include "cgraph.h"
 #include "except.h"
+#include "dbgcnt.h"
 
 /* Like PREFERRED_STACK_BOUNDARY but in units of bytes, not bits.  */
 #define STACK_BYTES (PREFERRED_STACK_BOUNDARY / BITS_PER_UNIT)
@@ -129,8 +129,8 @@ static int store_one_arg (struct arg_data *, rtx, int, int, int);
 static void store_unaligned_arguments_into_pseudos (struct arg_data *, int);
 static int finalize_must_preallocate (int, int, struct arg_data *,
                                      struct args_size *);
-static void precompute_arguments (int, int, struct arg_data *);
-static int compute_argument_block_size (int, struct args_size *, int);
+static void precompute_arguments (int, struct arg_data *);
+static int compute_argument_block_size (int, struct args_size *, tree, int);
 static void initialize_argument_information (int, struct arg_data *,
                                             struct args_size *, int,
                                             tree, tree,
@@ -143,7 +143,7 @@ static void load_register_parameters (struct arg_data *, int, rtx *, int,
                                      int, int *);
 static rtx emit_library_call_value_1 (int, rtx, rtx, enum libcall_type,
                                      enum machine_mode, int, va_list);
-static int special_function_p (tree, int);
+static int special_function_p (const_tree, int);
 static int check_sibcall_argument_overlap_1 (rtx);
 static int check_sibcall_argument_overlap (rtx, struct arg_data *, int);
 
@@ -297,7 +297,7 @@ emit_call_1 (rtx funexp, tree fntree, tree fndecl ATTRIBUTE_UNUSED,
      even if the call has no arguments to pop.  */
 #if defined (HAVE_call) && defined (HAVE_call_value)
   if (HAVE_call && HAVE_call_value && HAVE_call_pop && HAVE_call_value_pop
-      && n_popped > 0 && ! (ecf_flags & ECF_SP_DEPRESSED))
+      && n_popped > 0)
 #else
   if (HAVE_call_pop && HAVE_call_value_pop)
 #endif
@@ -359,21 +359,20 @@ emit_call_1 (rtx funexp, tree fntree, tree fndecl ATTRIBUTE_UNUSED,
   /* Find the call we just emitted.  */
   call_insn = last_call_insn ();
 
-  /* Mark memory as used for "pure" function call.  */
-  if (ecf_flags & ECF_PURE)
-    call_fusage
-      = gen_rtx_EXPR_LIST
-       (VOIDmode,
-        gen_rtx_USE (VOIDmode,
-                     gen_rtx_MEM (BLKmode, gen_rtx_SCRATCH (VOIDmode))),
-        call_fusage);
-
   /* Put the register usage information there.  */
   add_function_usage_to (call_insn, call_fusage);
 
   /* If this is a const call, then set the insn's unchanging bit.  */
-  if (ecf_flags & (ECF_CONST | ECF_PURE))
-    CONST_OR_PURE_CALL_P (call_insn) = 1;
+  if (ecf_flags & ECF_CONST)
+    RTL_CONST_CALL_P (call_insn) = 1;
+
+  /* If this is a pure call, then set the insn's unchanging bit.  */
+  if (ecf_flags & ECF_PURE)
+    RTL_PURE_CALL_P (call_insn) = 1;
+
+  /* If this is a const call, then set the insn's unchanging bit.  */
+  if (ecf_flags & ECF_LOOPING_CONST_OR_PURE)
+    RTL_LOOPING_CONST_OR_PURE_CALL_P (call_insn) = 1;
 
   /* If this call can't throw, attach a REG_EH_REGION reg note to that
      effect.  */
@@ -389,7 +388,6 @@ emit_call_1 (rtx funexp, tree fntree, tree fndecl ATTRIBUTE_UNUSED,
       if (rn > 0)
        REG_NOTES (call_insn) = gen_rtx_EXPR_LIST (REG_EH_REGION, GEN_INT (rn),
                                                   REG_NOTES (call_insn));
-      note_current_region_may_contain_throw ();
     }
 
   if (ecf_flags & ECF_NORETURN)
@@ -400,7 +398,7 @@ emit_call_1 (rtx funexp, tree fntree, tree fndecl ATTRIBUTE_UNUSED,
     {
       REG_NOTES (call_insn) = gen_rtx_EXPR_LIST (REG_SETJMP, const0_rtx,
                                                 REG_NOTES (call_insn));
-      current_function_calls_setjmp = 1;
+      cfun->calls_setjmp = 1;
     }
 
   SIBLING_CALL_P (call_insn) = ((ecf_flags & ECF_SIBCALL) != 0);
@@ -432,7 +430,7 @@ emit_call_1 (rtx funexp, tree fntree, tree fndecl ATTRIBUTE_UNUSED,
 
       if (rounded_stack_size != 0)
        {
-         if (ecf_flags & (ECF_SP_DEPRESSED | ECF_NORETURN))
+         if (ecf_flags & ECF_NORETURN)
            /* Just pretend we did the pop.  */
            stack_pointer_delta -= rounded_stack_size;
          else if (flag_defer_pop && inhibit_defer_pop == 0
@@ -469,7 +467,7 @@ emit_call_1 (rtx funexp, tree fntree, tree fndecl ATTRIBUTE_UNUSED,
    space from the stack such as alloca.  */
 
 static int
-special_function_p (tree fndecl, int flags)
+special_function_p (const_tree fndecl, int flags)
 {
   if (fndecl && DECL_NAME (fndecl)
       && IDENTIFIER_LENGTH (DECL_NAME (fndecl)) <= 17
@@ -543,14 +541,14 @@ special_function_p (tree fndecl, int flags)
 /* Return nonzero when FNDECL represents a call to setjmp.  */
 
 int
-setjmp_call_p (tree fndecl)
+setjmp_call_p (const_tree fndecl)
 {
   return special_function_p (fndecl, 0) & ECF_RETURNS_TWICE;
 }
 
 /* Return true when exp contains alloca call.  */
 bool
-alloca_call_p (tree exp)
+alloca_call_p (const_tree exp)
 {
   if (TREE_CODE (exp) == CALL_EXPR
       && TREE_CODE (CALL_EXPR_FN (exp)) == ADDR_EXPR
@@ -564,10 +562,10 @@ alloca_call_p (tree exp)
 /* Detect flags (function attributes) from the function decl or type node.  */
 
 int
-flags_from_decl_or_type (tree exp)
+flags_from_decl_or_type (const_tree exp)
 {
   int flags = 0;
-  tree type = exp;
+  const_tree type = exp;
 
   if (DECL_P (exp))
     {
@@ -581,9 +579,13 @@ flags_from_decl_or_type (tree exp)
       if (DECL_IS_RETURNS_TWICE (exp))
        flags |= ECF_RETURNS_TWICE;
 
-      /* The function exp may have the `pure' attribute.  */
-      if (DECL_IS_PURE (exp))
+      /* Process the pure and const attributes.  */
+      if (TREE_READONLY (exp) && ! TREE_THIS_VOLATILE (exp))
+       flags |= ECF_CONST;
+      if (DECL_PURE_P (exp))
        flags |= ECF_PURE;
+      if (DECL_LOOPING_CONST_OR_PURE_P (exp))
+       flags |= ECF_LOOPING_CONST_OR_PURE;
 
       if (DECL_IS_NOVOPS (exp))
        flags |= ECF_NOVOPS;
@@ -591,9 +593,6 @@ flags_from_decl_or_type (tree exp)
       if (TREE_NOTHROW (exp))
        flags |= ECF_NOTHROW;
 
-      if (TREE_READONLY (exp) && ! TREE_THIS_VOLATILE (exp))
-       flags |= ECF_CONST;
-
       flags = special_function_p (exp, flags);
     }
   else if (TYPE_P (exp) && TYPE_READONLY (exp) && ! TREE_THIS_VOLATILE (exp))
@@ -602,21 +601,13 @@ flags_from_decl_or_type (tree exp)
   if (TREE_THIS_VOLATILE (exp))
     flags |= ECF_NORETURN;
 
-  /* Mark if the function returns with the stack pointer depressed.   We
-     cannot consider it pure or constant in that case.  */
-  if (TREE_CODE (type) == FUNCTION_TYPE && TYPE_RETURNS_STACK_DEPRESSED (type))
-    {
-      flags |= ECF_SP_DEPRESSED;
-      flags &= ~(ECF_PURE | ECF_CONST);
-    }
-
   return flags;
 }
 
 /* Detect flags from a CALL_EXPR.  */
 
 int
-call_expr_flags (tree t)
+call_expr_flags (const_tree t)
 {
   int flags;
   tree decl = get_callee_fndecl (t);
@@ -1047,7 +1038,8 @@ initialize_argument_information (int num_actuals ATTRIBUTE_UNUSED,
              args[i].tree_value = build_fold_addr_expr (args[i].tree_value);
              type = TREE_TYPE (args[i].tree_value);
 
-             *ecf_flags &= ~(ECF_CONST | ECF_LIBCALL_BLOCK);
+             if (*ecf_flags & ECF_CONST)
+               *ecf_flags &= ~(ECF_CONST | ECF_LOOPING_CONST_OR_PURE);
            }
          else
            {
@@ -1080,12 +1072,19 @@ initialize_argument_information (int num_actuals ATTRIBUTE_UNUSED,
              else
                copy = assign_temp (type, 0, 1, 0);
 
-             store_expr (args[i].tree_value, copy, 0);
+             store_expr (args[i].tree_value, copy, 0, false);
 
-             if (callee_copies)
-               *ecf_flags &= ~(ECF_CONST | ECF_LIBCALL_BLOCK);
-             else
-               *ecf_flags &= ~(ECF_CONST | ECF_PURE | ECF_LIBCALL_BLOCK);
+             /* Just change the const function to pure and then let
+                the next test clear the pure based on
+                callee_copies.  */
+             if (*ecf_flags & ECF_CONST)
+               {
+                 *ecf_flags &= ~ECF_CONST;
+                 *ecf_flags |= ECF_PURE;
+               }
+
+             if (!callee_copies && *ecf_flags & ECF_PURE)
+               *ecf_flags &= ~(ECF_PURE | ECF_LOOPING_CONST_OR_PURE);
 
              args[i].tree_value
                = build_fold_addr_expr (make_tree (type, copy));
@@ -1138,11 +1137,6 @@ initialize_argument_information (int num_actuals ATTRIBUTE_UNUSED,
          || (args[i].pass_on_stack && args[i].reg != 0))
        *must_preallocate = 1;
 
-      /* If this is an addressable type, we cannot pre-evaluate it.  Thus,
-        we cannot consider this function call constant.  */
-      if (TREE_ADDRESSABLE (type))
-       *ecf_flags &= ~ECF_LIBCALL_BLOCK;
-
       /* Compute the stack-size of this argument.  */
       if (args[i].reg == 0 || args[i].partial != 0
          || reg_parm_stack_space > 0
@@ -1187,6 +1181,7 @@ initialize_argument_information (int num_actuals ATTRIBUTE_UNUSED,
 static int
 compute_argument_block_size (int reg_parm_stack_space,
                             struct args_size *args_size,
+                            tree fndecl ATTRIBUTE_UNUSED,
                             int preferred_stack_boundary ATTRIBUTE_UNUSED)
 {
   int unadjusted_args_size = args_size->constant;
@@ -1222,13 +1217,12 @@ compute_argument_block_size (int reg_parm_stack_space,
            = size_binop (MAX_EXPR, args_size->var,
                          ssize_int (reg_parm_stack_space));
 
-#ifndef OUTGOING_REG_PARM_STACK_SPACE
          /* The area corresponding to register parameters is not to count in
             the size of the block we need.  So make the adjustment.  */
-         args_size->var
-           = size_binop (MINUS_EXPR, args_size->var,
-                         ssize_int (reg_parm_stack_space));
-#endif
+         if (! OUTGOING_REG_PARM_STACK_SPACE ((!fndecl ? NULL_TREE : TREE_TYPE (fndecl))))
+           args_size->var
+             = size_binop (MINUS_EXPR, args_size->var,
+                           ssize_int (reg_parm_stack_space));
        }
     }
   else
@@ -1246,9 +1240,8 @@ compute_argument_block_size (int reg_parm_stack_space,
       args_size->constant = MAX (args_size->constant,
                                 reg_parm_stack_space);
 
-#ifndef OUTGOING_REG_PARM_STACK_SPACE
-      args_size->constant -= reg_parm_stack_space;
-#endif
+      if (! OUTGOING_REG_PARM_STACK_SPACE ((!fndecl ? NULL_TREE : TREE_TYPE (fndecl))))
+       args_size->constant -= reg_parm_stack_space;
     }
   return unadjusted_args_size;
 }
@@ -1264,19 +1257,30 @@ compute_argument_block_size (int reg_parm_stack_space,
    precomputed argument.  */
 
 static void
-precompute_arguments (int flags, int num_actuals, struct arg_data *args)
+precompute_arguments (int num_actuals, struct arg_data *args)
 {
   int i;
 
   /* If this is a libcall, then precompute all arguments so that we do not
      get extraneous instructions emitted as part of the libcall sequence.  */
-  if ((flags & ECF_LIBCALL_BLOCK) == 0)
+
+  /* If we preallocated the stack space, and some arguments must be passed
+     on the stack, then we must precompute any parameter which contains a
+     function call which will store arguments on the stack.
+     Otherwise, evaluating the parameter may clobber previous parameters
+     which have already been stored into the stack.  (we have code to avoid
+     such case by saving the outgoing stack arguments, but it results in
+     worse code)  */
+  if (!ACCUMULATE_OUTGOING_ARGS)
     return;
 
   for (i = 0; i < num_actuals; i++)
     {
       enum machine_mode mode;
 
+      if (TREE_CODE (args[i].tree_value) != CALL_EXPR)
+       continue;
+
       /* If this is an addressable type, we cannot pre-evaluate it.  */
       gcc_assert (!TREE_ADDRESSABLE (TREE_TYPE (args[i].tree_value)));
 
@@ -1482,7 +1486,7 @@ rtx_for_function_call (tree fndecl, tree addr)
     {
       /* If this is the first use of the function, see if we need to
         make an external definition for it.  */
-      if (! TREE_USED (fndecl))
+      if (!TREE_USED (fndecl) && fndecl != current_function_decl)
        {
          assemble_external (fndecl);
          TREE_USED (fndecl) = 1;
@@ -1511,16 +1515,16 @@ mem_overlaps_already_clobbered_arg_p (rtx addr, unsigned HOST_WIDE_INT size)
 {
   HOST_WIDE_INT i;
 
-  if (addr == current_function_internal_arg_pointer)
+  if (addr == crtl->args.internal_arg_pointer)
     i = 0;
   else if (GET_CODE (addr) == PLUS
-          && XEXP (addr, 0) == current_function_internal_arg_pointer
+          && XEXP (addr, 0) == crtl->args.internal_arg_pointer
           && GET_CODE (XEXP (addr, 1)) == CONST_INT)
     i = INTVAL (XEXP (addr, 1));
   /* Return true for arg pointer based indexed addressing.  */
   else if (GET_CODE (addr) == PLUS
-          && (XEXP (addr, 0) == current_function_internal_arg_pointer
-              || XEXP (addr, 1) == current_function_internal_arg_pointer))
+          && (XEXP (addr, 0) == crtl->args.internal_arg_pointer
+              || XEXP (addr, 1) == crtl->args.internal_arg_pointer))
     return true;
   else
     return false;
@@ -1846,6 +1850,31 @@ shift_return_value (enum machine_mode mode, bool left_p, rtx value)
   return true;
 }
 
+/* If X is a likely-spilled register value, copy it to a pseudo
+   register and return that register.  Return X otherwise.  */
+
+static rtx
+avoid_likely_spilled_reg (rtx x)
+{
+  rtx new;
+
+  if (REG_P (x)
+      && HARD_REGISTER_P (x)
+      && CLASS_LIKELY_SPILLED_P (REGNO_REG_CLASS (REGNO (x))))
+    {
+      /* Make sure that we generate a REG rather than a CONCAT.
+        Moves into CONCATs can need nontrivial instructions,
+        and the whole point of this function is to avoid
+        using the hard register directly in such a situation.  */
+      generating_concat_p = 0;
+      new = gen_reg_rtx (GET_MODE (x));
+      generating_concat_p = 1;
+      emit_move_insn (new, x);
+      return new;
+    }
+  return x;
+}
+
 /* Generate all the code for a CALL_EXPR exp
    and return an rtx for its value.
    Store the value in TARGET (specified as an rtx) if convenient.
@@ -1996,10 +2025,12 @@ expand_call (tree exp, rtx target, int ignore)
   if (AGGREGATE_TYPE_P (TREE_TYPE (exp)))
     warning (OPT_Waggregate_return, "function call has aggregate value");
 
-  /* If the result of a pure or const function call is ignored (or void),
-     and none of its arguments are volatile, we can avoid expanding the
-     call and just evaluate the arguments for side-effects.  */
+  /* If the result of a non looping pure or const function call is
+     ignored (or void), and none of its arguments are volatile, we can
+     avoid expanding the call and just evaluate the arguments for
+     side-effects.  */
   if ((flags & (ECF_CONST | ECF_PURE))
+      && (!(flags & ECF_LOOPING_CONST_OR_PURE))
       && (ignore || target == const0_rtx
          || TYPE_MODE (TREE_TYPE (exp)) == VOIDmode))
     {
@@ -2026,10 +2057,9 @@ expand_call (tree exp, rtx target, int ignore)
   reg_parm_stack_space = REG_PARM_STACK_SPACE (fndecl);
 #endif
 
-#ifndef OUTGOING_REG_PARM_STACK_SPACE
-  if (reg_parm_stack_space > 0 && PUSH_ARGS)
+  if (! OUTGOING_REG_PARM_STACK_SPACE ((!fndecl ? NULL_TREE : TREE_TYPE (fndecl)))
+      && reg_parm_stack_space > 0 && PUSH_ARGS)
     must_preallocate = 1;
-#endif
 
   /* Set up a place to return a structure.  */
 
@@ -2037,7 +2067,7 @@ expand_call (tree exp, rtx target, int ignore)
   if (aggregate_value_p (exp, fndecl))
     {
       /* This call returns a big structure.  */
-      flags &= ~(ECF_CONST | ECF_PURE | ECF_LIBCALL_BLOCK);
+      flags &= ~(ECF_CONST | ECF_PURE | ECF_LOOPING_CONST_OR_PURE);
 
 #ifdef PCC_STATIC_STRUCT_RETURN
       {
@@ -2069,7 +2099,14 @@ expand_call (tree exp, rtx target, int ignore)
   if (fndecl)
     {
       struct cgraph_rtl_info *i = cgraph_rtl_info (fndecl);
-      if (i && i->preferred_incoming_stack_boundary)
+      /* Without automatic stack alignment, we can't increase preferred
+        stack boundary.  With automatic stack alignment, it is
+        unnecessary since unless we can guarantee that all callers will
+        align the outgoing stack properly, callee has to align its
+        stack anyway.  */
+      if (i
+         && i->preferred_incoming_stack_boundary
+         && i->preferred_incoming_stack_boundary < preferred_stack_boundary)
        preferred_stack_boundary = i->preferred_incoming_stack_boundary;
     }
 
@@ -2098,7 +2135,7 @@ expand_call (tree exp, rtx target, int ignore)
     type_arg_types = TYPE_ARG_TYPES (funtype);
 
   if (flags & ECF_MAY_BE_ALLOCA)
-    current_function_calls_alloca = 1;
+    cfun->calls_alloca = 1;
 
   /* If struct_value_rtx is 0, it means pass the address
      as if it were an extra parameter.  Put the argument expression
@@ -2191,15 +2228,7 @@ expand_call (tree exp, rtx target, int ignore)
                                   &try_tail_call, CALL_FROM_THUNK_P (exp));
 
   if (args_size.var)
-    {
-      /* If this function requires a variable-sized argument list, don't
-        try to make a cse'able block for this call.  We may be able to
-        do this eventually, but it is too complicated to keep track of
-        what insns go in the cse'able block and which don't.  */
-
-      flags &= ~ECF_LIBCALL_BLOCK;
-      must_preallocate = 1;
-    }
+    must_preallocate = 1;
 
   /* Now make final decision about preallocating stack space.  */
   must_preallocate = finalize_must_preallocate (must_preallocate,
@@ -2226,7 +2255,8 @@ expand_call (tree exp, rtx target, int ignore)
   if (currently_expanding_call++ != 0
       || !flag_optimize_sibling_calls
       || args_size.var
-      || lookup_stmt_eh_region (exp) >= 0)
+      || lookup_stmt_eh_region (exp) >= 0
+      || dbg_cnt (tail_call) == false)
     try_tail_call = 0;
 
   /*  Rest of purposes for tail call optimizations to fail.  */
@@ -2255,27 +2285,25 @@ expand_call (tree exp, rtx target, int ignore)
       || (fndecl && decl_function_context (fndecl) == current_function_decl)
       /* If this function requires more stack slots than the current
         function, we cannot change it into a sibling call.
-        current_function_pretend_args_size is not part of the
+        crtl->args.pretend_args_size is not part of the
         stack allocated by our caller.  */
-      || args_size.constant > (current_function_args_size
-                              - current_function_pretend_args_size)
+      || args_size.constant > (crtl->args.size
+                              - crtl->args.pretend_args_size)
       /* If the callee pops its own arguments, then it must pop exactly
         the same number of arguments as the current function.  */
       || (RETURN_POPS_ARGS (fndecl, funtype, args_size.constant)
          != RETURN_POPS_ARGS (current_function_decl,
                               TREE_TYPE (current_function_decl),
-                              current_function_args_size))
+                              crtl->args.size))
       || !lang_hooks.decls.ok_for_sibcall (fndecl))
     try_tail_call = 0;
 
   /* Ensure current function's preferred stack boundary is at least
      what we need.  We don't have to increase alignment for recursive
      functions.  */
-  if (cfun->preferred_stack_boundary < preferred_stack_boundary
+  if (crtl->preferred_stack_boundary < preferred_stack_boundary
       && fndecl != current_function_decl)
-    cfun->preferred_stack_boundary = preferred_stack_boundary;
-  if (fndecl == current_function_decl)
-    cfun->recursive_call_emit = true;
+    crtl->preferred_stack_boundary = preferred_stack_boundary;
 
   preferred_unit_stack_boundary = preferred_stack_boundary / BITS_PER_UNIT;
 
@@ -2292,7 +2320,7 @@ expand_call (tree exp, rtx target, int ignore)
       int save_pending_stack_adjust = 0;
       int save_stack_pointer_delta = 0;
       rtx insns;
-      rtx before_call, next_arg_reg;
+      rtx before_call, next_arg_reg, after_args;
 
       if (pass == 0)
        {
@@ -2320,33 +2348,27 @@ expand_call (tree exp, rtx target, int ignore)
       /* Don't let pending stack adjusts add up to too much.
         Also, do all pending adjustments now if there is any chance
         this might be a call to alloca or if we are expanding a sibling
-        call sequence or if we are calling a function that is to return
-        with stack pointer depressed.
+        call sequence.
         Also do the adjustments before a throwing call, otherwise
         exception handling can fail; PR 19225. */
       if (pending_stack_adjust >= 32
          || (pending_stack_adjust > 0
-             && (flags & (ECF_MAY_BE_ALLOCA | ECF_SP_DEPRESSED)))
+             && (flags & ECF_MAY_BE_ALLOCA))
          || (pending_stack_adjust > 0
              && flag_exceptions && !(flags & ECF_NOTHROW))
          || pass == 0)
        do_pending_stack_adjust ();
 
-      /* When calling a const function, we must pop the stack args right away,
-        so that the pop is deleted or moved with the call.  */
-      if (pass && (flags & ECF_LIBCALL_BLOCK))
-       NO_DEFER_POP;
-
       /* Precompute any arguments as needed.  */
       if (pass)
-       precompute_arguments (flags, num_actuals, args);
+       precompute_arguments (num_actuals, args);
 
       /* Now we are about to start emitting insns that can be deleted
         if a libcall is deleted.  */
-      if (pass && (flags & (ECF_LIBCALL_BLOCK | ECF_MALLOC)))
+      if (pass && (flags & ECF_MALLOC))
        start_sequence ();
 
-      if (pass == 0 && cfun->stack_protect_guard)
+      if (pass == 0 && crtl->stack_protect_guard)
        stack_protect_epilogue ();
 
       adjusted_args_size = args_size;
@@ -2358,6 +2380,7 @@ expand_call (tree exp, rtx target, int ignore)
       unadjusted_args_size
        = compute_argument_block_size (reg_parm_stack_space,
                                       &adjusted_args_size,
+                                      fndecl,
                                       (pass == 0 ? 0
                                        : preferred_stack_boundary));
 
@@ -2370,9 +2393,9 @@ expand_call (tree exp, rtx target, int ignore)
          argblock = virtual_incoming_args_rtx;
          argblock
 #ifdef STACK_GROWS_DOWNWARD
-           = plus_constant (argblock, current_function_pretend_args_size);
+           = plus_constant (argblock, crtl->args.pretend_args_size);
 #else
-           = plus_constant (argblock, -current_function_pretend_args_size);
+           = plus_constant (argblock, -crtl->args.pretend_args_size);
 #endif
          stored_args_map = sbitmap_alloc (args_size.constant);
          sbitmap_zero (stored_args_map);
@@ -2409,8 +2432,8 @@ expand_call (tree exp, rtx target, int ignore)
             the prologue (if ACCUMULATE_OUTGOING_ARGS, or stack overflow
             checking).  */
 
-         if (needed > current_function_outgoing_args_size)
-           current_function_outgoing_args_size = needed;
+         if (needed > crtl->outgoing_args_size)
+           crtl->outgoing_args_size = needed;
 
          if (must_preallocate)
            {
@@ -2430,12 +2453,11 @@ expand_call (tree exp, rtx target, int ignore)
                     Another approach might be to try to reorder the argument
                     evaluations to avoid this conflicting stack usage.  */
 
-#ifndef OUTGOING_REG_PARM_STACK_SPACE
                  /* Since we will be writing into the entire argument area,
                     the map must be allocated for its entire size, not just
                     the part that is the responsibility of the caller.  */
-                 needed += reg_parm_stack_space;
-#endif
+                 if (! OUTGOING_REG_PARM_STACK_SPACE ((!fndecl ? NULL_TREE : TREE_TYPE (fndecl))))
+                   needed += reg_parm_stack_space;
 
 #ifdef ARGS_GROW_DOWNWARD
                  highest_outgoing_arg_in_use = MAX (initial_highest_arg_in_use,
@@ -2531,12 +2553,11 @@ expand_call (tree exp, rtx target, int ignore)
             an argument.  */
          if (stack_arg_under_construction)
            {
-#ifndef OUTGOING_REG_PARM_STACK_SPACE
-             rtx push_size = GEN_INT (reg_parm_stack_space
-                                      + adjusted_args_size.constant);
-#else
-             rtx push_size = GEN_INT (adjusted_args_size.constant);
-#endif
+             rtx push_size
+               = GEN_INT (adjusted_args_size.constant
+                          + (OUTGOING_REG_PARM_STACK_SPACE ((!fndecl ? NULL
+                                                                     : TREE_TYPE (fndecl))) ? 0
+                             : reg_parm_stack_space));
              if (old_stack_level == 0)
                {
                  emit_stack_save (SAVE_BLOCK, &old_stack_level,
@@ -2582,7 +2603,6 @@ expand_call (tree exp, rtx target, int ignore)
          /* When the stack adjustment is pending, we get better code
             by combining the adjustments.  */
          if (pending_stack_adjust
-             && ! (flags & ECF_LIBCALL_BLOCK)
              && ! inhibit_defer_pop)
            {
              pending_stack_adjust
@@ -2706,11 +2726,10 @@ expand_call (tree exp, rtx target, int ignore)
       /* If register arguments require space on the stack and stack space
         was not preallocated, allocate stack space here for arguments
         passed in registers.  */
-#ifdef OUTGOING_REG_PARM_STACK_SPACE
-      if (!ACCUMULATE_OUTGOING_ARGS
+      if (OUTGOING_REG_PARM_STACK_SPACE ((!fndecl ? NULL_TREE : TREE_TYPE (fndecl)))
+          && !ACCUMULATE_OUTGOING_ARGS
          && must_preallocate == 0 && reg_parm_stack_space > 0)
        anti_adjust_stack (GEN_INT (reg_parm_stack_space));
-#endif
 
       /* Pass the function the address in which to return a
         structure value.  */
@@ -2727,6 +2746,7 @@ expand_call (tree exp, rtx target, int ignore)
            use_reg (&call_fusage, struct_value);
        }
 
+      after_args = get_last_insn ();
       funexp = prepare_call_address (funexp, static_chain_value,
                                     &call_fusage, reg_parm_seen, pass == 0);
 
@@ -2761,6 +2781,13 @@ expand_call (tree exp, rtx target, int ignore)
                   next_arg_reg, valreg, old_inhibit_defer_pop, call_fusage,
                   flags, & args_so_far);
 
+      /* If the call setup or the call itself overlaps with anything
+        of the argument setup we probably clobbered our call address.
+        In that case we can't do sibcalls.  */
+      if (pass == 0
+         && check_sibcall_argument_overlap (after_args, 0, 0))
+       sibcall_failure = 1;
+
       /* If a non-BLKmode value is returned at the most significant end
         of a register, shift the register right by the appropriate amount
         and update VALREG accordingly.  BLKmode values are handled by the
@@ -2775,72 +2802,7 @@ expand_call (tree exp, rtx target, int ignore)
          valreg = gen_rtx_REG (TYPE_MODE (TREE_TYPE (exp)), REGNO (valreg));
        }
 
-      /* If call is cse'able, make appropriate pair of reg-notes around it.
-        Test valreg so we don't crash; may safely ignore `const'
-        if return type is void.  Disable for PARALLEL return values, because
-        we have no way to move such values into a pseudo register.  */
-      if (pass && (flags & ECF_LIBCALL_BLOCK))
-       {
-         rtx insns;
-         rtx insn;
-         bool failed = valreg == 0 || GET_CODE (valreg) == PARALLEL;
-
-         insns = get_insns ();
-
-         /* Expansion of block moves possibly introduced a loop that may
-            not appear inside libcall block.  */
-         for (insn = insns; insn; insn = NEXT_INSN (insn))
-           if (JUMP_P (insn))
-             failed = true;
-
-         if (failed)
-           {
-             end_sequence ();
-             emit_insn (insns);
-           }
-         else
-           {
-             rtx note = 0;
-             rtx temp = gen_reg_rtx (GET_MODE (valreg));
-
-             /* Mark the return value as a pointer if needed.  */
-             if (TREE_CODE (TREE_TYPE (exp)) == POINTER_TYPE)
-               mark_reg_pointer (temp,
-                                 TYPE_ALIGN (TREE_TYPE (TREE_TYPE (exp))));
-
-             end_sequence ();
-             if (flag_unsafe_math_optimizations
-                 && fndecl
-                 && DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_NORMAL
-                 && (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_SQRT
-                     || DECL_FUNCTION_CODE (fndecl) == BUILT_IN_SQRTF
-                     || DECL_FUNCTION_CODE (fndecl) == BUILT_IN_SQRTL))
-               note = gen_rtx_fmt_e (SQRT,
-                                     GET_MODE (temp),
-                                     args[0].initial_value);
-             else
-               {
-                 /* Construct an "equal form" for the value which
-                    mentions all the arguments in order as well as
-                    the function name.  */
-                 for (i = 0; i < num_actuals; i++)
-                   note = gen_rtx_EXPR_LIST (VOIDmode,
-                                             args[i].initial_value, note);
-                 note = gen_rtx_EXPR_LIST (VOIDmode, funexp, note);
-
-                 if (flags & ECF_PURE)
-                   note = gen_rtx_EXPR_LIST (VOIDmode,
-                       gen_rtx_USE (VOIDmode,
-                                    gen_rtx_MEM (BLKmode,
-                                                 gen_rtx_SCRATCH (VOIDmode))),
-                       note);
-               }
-             emit_libcall_block (insns, temp, valreg, note);
-
-             valreg = temp;
-           }
-       }
-      else if (pass && (flags & ECF_MALLOC))
+      if (pass && (flags & ECF_MALLOC))
        {
          rtx temp = gen_reg_rtx (GET_MODE (valreg));
          rtx last, insns;
@@ -2864,9 +2826,10 @@ expand_call (tree exp, rtx target, int ignore)
          valreg = temp;
        }
 
-      /* For calls to `setjmp', etc., inform flow.c it should complain
-        if nonvolatile values are live.  For functions that cannot return,
-        inform flow that control does not fall through.  */
+      /* For calls to `setjmp', etc., inform
+        function.c:setjmp_warnings that it should complain if
+        nonvolatile values are live.  For functions that cannot
+        return, inform flow that control does not fall through.  */
 
       if ((flags & ECF_NORETURN) || pass == 0)
        {
@@ -2948,11 +2911,8 @@ expand_call (tree exp, rtx target, int ignore)
 
          /* We have to copy a return value in a CLASS_LIKELY_SPILLED hard
             reg to a plain register.  */
-         if (REG_P (valreg)
-             && HARD_REGISTER_P (valreg)
-             && CLASS_LIKELY_SPILLED_P (REGNO_REG_CLASS (REGNO (valreg)))
-             && !(REG_P (target) && !HARD_REGISTER_P (target)))
-           valreg = copy_to_reg (valreg);
+         if (!REG_P (target) || HARD_REGISTER_P (target))
+           valreg = avoid_likely_spilled_reg (valreg);
 
          /* If TARGET is a MEM in the argument area, and we have
             saved part of the argument area, then we can't store
@@ -2997,7 +2957,7 @@ expand_call (tree exp, rtx target, int ignore)
          sibcall_failure = 1;
        }
       else
-       target = copy_to_reg (valreg);
+       target = copy_to_reg (avoid_likely_spilled_reg (valreg));
 
       if (targetm.calls.promote_function_return(funtype))
        {
@@ -3036,7 +2996,7 @@ expand_call (tree exp, rtx target, int ignore)
       /* If size of args is variable or this was a constructor call for a stack
         argument, restore saved stack-pointer value.  */
 
-      if (old_stack_level && ! (flags & ECF_SP_DEPRESSED))
+      if (old_stack_level)
        {
          emit_stack_restore (SAVE_BLOCK, old_stack_level, NULL_RTX);
          stack_pointer_delta = old_stack_pointer_delta;
@@ -3135,23 +3095,13 @@ expand_call (tree exp, rtx target, int ignore)
   if (tail_call_insns)
     {
       emit_insn (tail_call_insns);
-      cfun->tail_call_emit = true;
+      crtl->tail_call_emit = true;
     }
   else
     emit_insn (normal_call_insns);
 
   currently_expanding_call--;
 
-  /* If this function returns with the stack pointer depressed, ensure
-     this block saves and restores the stack pointer, show it was
-     changed, and adjust for any outgoing arg space.  */
-  if (flags & ECF_SP_DEPRESSED)
-    {
-      clear_pending_stack_adjust ();
-      emit_insn (gen_rtx_CLOBBER (VOIDmode, stack_pointer_rtx));
-      emit_move_insn (virtual_stack_dynamic_rtx, stack_pointer_rtx);
-    }
-
   if (stack_usage_map_buf)
     free (stack_usage_map_buf);
 
@@ -3182,7 +3132,7 @@ fixup_tail_calls (void)
       /* There are never REG_EQUIV notes for the incoming arguments
         after the NOTE_INSN_FUNCTION_BEG note, so stop if we see it.  */
       if (NOTE_P (insn)
-         && NOTE_LINE_NUMBER (insn) == NOTE_INSN_FUNCTION_BEG)
+         && NOTE_KIND (insn) == NOTE_INSN_FUNCTION_BEG)
        break;
 
       note = find_reg_note (insn, REG_EQUIV, 0);
@@ -3254,6 +3204,9 @@ emit_library_call_value_1 (int retval, rtx orgfun, rtx value,
   struct args_size original_args_size;
   int argnum;
   rtx fun;
+  /* Todo, choose the correct decl type of orgfun. Sadly this information
+     isn't present here, so we default to native calling abi here.  */
+  tree fndecl ATTRIBUTE_UNUSED = NULL_TREE; /* library calls default to host calling abi ? */
   int inc;
   int count;
   rtx argblock = 0;
@@ -3311,12 +3264,6 @@ emit_library_call_value_1 (int retval, rtx orgfun, rtx value,
     case LCT_PURE:
       flags |= ECF_PURE;
       break;
-    case LCT_CONST_MAKE_BLOCK:
-      flags |= ECF_CONST | ECF_LIBCALL_BLOCK;
-      break;
-    case LCT_PURE_MAKE_BLOCK:
-      flags |= ECF_PURE | ECF_LIBCALL_BLOCK;
-      break;
     case LCT_NORETURN:
       flags |= ECF_NORETURN;
       break;
@@ -3331,8 +3278,8 @@ emit_library_call_value_1 (int retval, rtx orgfun, rtx value,
 
   /* Ensure current function's preferred stack boundary is at least
      what we need.  */
-  if (cfun->preferred_stack_boundary < PREFERRED_STACK_BOUNDARY)
-    cfun->preferred_stack_boundary = PREFERRED_STACK_BOUNDARY;
+  if (crtl->preferred_stack_boundary < PREFERRED_STACK_BOUNDARY)
+    crtl->preferred_stack_boundary = PREFERRED_STACK_BOUNDARY;
 
   /* If this kind of value comes back in memory,
      decide where in memory it should come back.  */
@@ -3356,7 +3303,7 @@ emit_library_call_value_1 (int retval, rtx orgfun, rtx value,
            mem_value = assign_temp (tfom, 0, 1, 1);
 #endif
          /* This call returns a big structure.  */
-         flags &= ~(ECF_CONST | ECF_PURE | ECF_LIBCALL_BLOCK);
+         flags &= ~(ECF_CONST | ECF_PURE | ECF_LOOPING_CONST_OR_PURE);
        }
     }
   else
@@ -3385,11 +3332,6 @@ emit_library_call_value_1 (int retval, rtx orgfun, rtx value,
 
   count = 0;
 
-  /* Now we are about to start emitting insns that can be deleted
-     if a libcall is deleted.  */
-  if (flags & ECF_LIBCALL_BLOCK)
-    start_sequence ();
-
   push_temp_slots ();
 
   /* If there's a structure value address to be passed,
@@ -3451,18 +3393,8 @@ emit_library_call_value_1 (int retval, rtx orgfun, rtx value,
          int must_copy
            = !reference_callee_copied (&args_so_far, mode, NULL_TREE, 1);
 
-         /* loop.c won't look at CALL_INSN_FUNCTION_USAGE of const/pure
-            functions, so we have to pretend this isn't such a function.  */
-         if (flags & ECF_LIBCALL_BLOCK)
-           {
-             rtx insns = get_insns ();
-             end_sequence ();
-             emit_insn (insns);
-           }
-         flags &= ~(ECF_CONST | ECF_PURE | ECF_LIBCALL_BLOCK);
-
-         /* If this was a CONST function, it is now PURE since
-            it now reads memory.  */
+         /* If this was a CONST function, it is now PURE since it now
+            reads memory.  */
          if (flags & ECF_CONST)
            {
              flags &= ~ECF_CONST;
@@ -3532,12 +3464,11 @@ emit_library_call_value_1 (int retval, rtx orgfun, rtx value,
   args_size.constant = MAX (args_size.constant,
                            reg_parm_stack_space);
 
-#ifndef OUTGOING_REG_PARM_STACK_SPACE
-  args_size.constant -= reg_parm_stack_space;
-#endif
+  if (! OUTGOING_REG_PARM_STACK_SPACE ((!fndecl ? NULL_TREE : TREE_TYPE (fndecl))))
+    args_size.constant -= reg_parm_stack_space;
 
-  if (args_size.constant > current_function_outgoing_args_size)
-    current_function_outgoing_args_size = args_size.constant;
+  if (args_size.constant > crtl->outgoing_args_size)
+    crtl->outgoing_args_size = args_size.constant;
 
   if (ACCUMULATE_OUTGOING_ARGS)
     {
@@ -3555,12 +3486,11 @@ emit_library_call_value_1 (int retval, rtx orgfun, rtx value,
 
       needed = args_size.constant;
 
-#ifndef OUTGOING_REG_PARM_STACK_SPACE
       /* Since we will be writing into the entire argument area, the
         map must be allocated for its entire size, not just the part that
         is the responsibility of the caller.  */
-      needed += reg_parm_stack_space;
-#endif
+      if (! OUTGOING_REG_PARM_STACK_SPACE ((!fndecl ? NULL_TREE : TREE_TYPE (fndecl))))
+       needed += reg_parm_stack_space;
 
 #ifdef ARGS_GROW_DOWNWARD
       highest_outgoing_arg_in_use = MAX (initial_highest_arg_in_use,
@@ -3774,7 +3704,18 @@ emit_library_call_value_1 (int retval, rtx orgfun, rtx value,
       if (reg != 0 && GET_CODE (reg) == PARALLEL)
        use_group_regs (&call_fusage, reg);
       else if (reg != 0)
-       use_reg (&call_fusage, reg);
+        {
+         int partial = argvec[count].partial;
+         if (partial)
+           {
+             int nregs;
+              gcc_assert (partial % UNITS_PER_WORD == 0);
+             nregs = partial / UNITS_PER_WORD;
+             use_regs (&call_fusage, REGNO (reg), nregs);
+           }
+         else
+           use_reg (&call_fusage, reg);
+       }
     }
 
   /* Pass the function the address in which to return a structure value.  */
@@ -3816,9 +3757,10 @@ emit_library_call_value_1 (int retval, rtx orgfun, rtx value,
               valreg,
               old_inhibit_defer_pop + 1, call_fusage, flags, & args_so_far);
 
-  /* For calls to `setjmp', etc., inform flow.c it should complain
-     if nonvolatile values are live.  For functions that cannot return,
-     inform flow that control does not fall through.  */
+  /* For calls to `setjmp', etc., inform function.c:setjmp_warnings
+     that it should complain if nonvolatile values are live.  For
+     functions that cannot return, inform flow that control does not
+     fall through.  */
 
   if (flags & ECF_NORETURN)
     {
@@ -3840,57 +3782,6 @@ emit_library_call_value_1 (int retval, rtx orgfun, rtx value,
   /* Now restore inhibit_defer_pop to its actual original value.  */
   OK_DEFER_POP;
 
-  /* If call is cse'able, make appropriate pair of reg-notes around it.
-     Test valreg so we don't crash; may safely ignore `const'
-     if return type is void.  Disable for PARALLEL return values, because
-     we have no way to move such values into a pseudo register.  */
-  if (flags & ECF_LIBCALL_BLOCK)
-    {
-      rtx insns;
-
-      if (valreg == 0)
-       {
-         insns = get_insns ();
-         end_sequence ();
-         emit_insn (insns);
-       }
-      else
-       {
-         rtx note = 0;
-         rtx temp;
-         int i;
-
-         if (GET_CODE (valreg) == PARALLEL)
-           {
-             temp = gen_reg_rtx (outmode);
-             emit_group_store (temp, valreg, NULL_TREE,
-                               GET_MODE_SIZE (outmode));
-             valreg = temp;
-           }
-
-         temp = gen_reg_rtx (GET_MODE (valreg));
-
-         /* Construct an "equal form" for the value which mentions all the
-            arguments in order as well as the function name.  */
-         for (i = 0; i < nargs; i++)
-           note = gen_rtx_EXPR_LIST (VOIDmode, argvec[i].value, note);
-         note = gen_rtx_EXPR_LIST (VOIDmode, fun, note);
-
-         insns = get_insns ();
-         end_sequence ();
-
-         if (flags & ECF_PURE)
-           note = gen_rtx_EXPR_LIST (VOIDmode,
-                       gen_rtx_USE (VOIDmode,
-                                    gen_rtx_MEM (BLKmode,
-                                                 gen_rtx_SCRATCH (VOIDmode))),
-                       note);
-
-         emit_libcall_block (insns, temp, valreg, note);
-
-         valreg = temp;
-       }
-    }
   pop_temp_slots ();
 
   /* Copy the value to the right place.  */
@@ -3974,12 +3865,9 @@ emit_library_call_value_1 (int retval, rtx orgfun, rtx value,
    with NARGS different arguments, passed as alternating rtx values
    and machine_modes to convert them to.
 
-   FN_TYPE should be LCT_NORMAL for `normal' calls, LCT_CONST for `const'
-   calls, LCT_PURE for `pure' calls, LCT_CONST_MAKE_BLOCK for `const' calls
-   which should be enclosed in REG_LIBCALL/REG_RETVAL notes,
-   LCT_PURE_MAKE_BLOCK for `purep' calls which should be enclosed in
-   REG_LIBCALL/REG_RETVAL notes with extra (use (memory (scratch)),
-   or other LCT_ value for other types of library calls.  */
+   FN_TYPE should be LCT_NORMAL for `normal' calls, LCT_CONST for
+   `const' calls, LCT_PURE for `pure' calls, or other LCT_ value for
+   other types of library calls.  */
 
 void
 emit_library_call (rtx orgfun, enum libcall_type fn_type,
@@ -4299,17 +4187,18 @@ store_one_arg (struct arg_data *arg, rtx argblock, int flags,
          rtx x = arg->value;
          int i = 0;
 
-         if (XEXP (x, 0) == current_function_internal_arg_pointer
+         if (XEXP (x, 0) == crtl->args.internal_arg_pointer
              || (GET_CODE (XEXP (x, 0)) == PLUS
                  && XEXP (XEXP (x, 0), 0) ==
-                    current_function_internal_arg_pointer
+                    crtl->args.internal_arg_pointer
                  && GET_CODE (XEXP (XEXP (x, 0), 1)) == CONST_INT))
            {
-             if (XEXP (x, 0) != current_function_internal_arg_pointer)
+             if (XEXP (x, 0) != crtl->args.internal_arg_pointer)
                i = INTVAL (XEXP (XEXP (x, 0), 1));
 
              /* expand_call should ensure this.  */
              gcc_assert (!arg->locate.offset.var
+                         && arg->locate.size.var == 0
                          && GET_CODE (size_rtx) == CONST_INT);
 
              if (arg->locate.offset.constant > i)
@@ -4319,7 +4208,21 @@ store_one_arg (struct arg_data *arg, rtx argblock, int flags,
                }
              else if (arg->locate.offset.constant < i)
                {
-                 if (i < arg->locate.offset.constant + INTVAL (size_rtx))
+                 /* Use arg->locate.size.constant instead of size_rtx
+                    because we only care about the part of the argument
+                    on the stack.  */
+                 if (i < (arg->locate.offset.constant
+                          + arg->locate.size.constant))
+                   sibcall_failure = 1;
+               }
+             else
+               {
+                 /* Even though they appear to be at the same location,
+                    if part of the outgoing argument is in registers,
+                    they aren't really at the same location.  Check for
+                    this by making sure that the incoming size is the
+                    same as the outgoing size.  */
+                 if (arg->locate.size.constant != INTVAL (size_rtx))
                    sibcall_failure = 1;
                }
            }
@@ -4374,7 +4277,7 @@ store_one_arg (struct arg_data *arg, rtx argblock, int flags,
 
 bool
 must_pass_in_stack_var_size (enum machine_mode mode ATTRIBUTE_UNUSED,
-                            tree type)
+                            const_tree type)
 {
   if (!type)
     return false;
@@ -4396,7 +4299,7 @@ must_pass_in_stack_var_size (enum machine_mode mode ATTRIBUTE_UNUSED,
 /* ??? Should be able to merge these two by examining BLOCK_REG_PADDING.  */
 
 bool
-must_pass_in_stack_var_size_or_pad (enum machine_mode mode, tree type)
+must_pass_in_stack_var_size_or_pad (enum machine_mode mode, const_tree type)
 {
   if (!type)
     return false;