OSDN Git Service

* config/sh/t-sh (TARGET_LIBGCC2_CFLAGS): Define.
[pf3gnuchains/gcc-fork.git] / gcc / calls.c
index bbb9b76..cdb934a 100644 (file)
@@ -1,6 +1,6 @@
 /* Convert function calls to rtl insns, for GNU C compiler.
    Copyright (C) 1989, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
-   1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007
+   1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009
    Free Software Foundation, Inc.
 
 This file is part of GCC.
@@ -25,6 +25,7 @@ along with GCC; see the file COPYING3.  If not see
 #include "tm.h"
 #include "rtl.h"
 #include "tree.h"
+#include "gimple.h"
 #include "flags.h"
 #include "expr.h"
 #include "optabs.h"
@@ -41,6 +42,7 @@ along with GCC; see the file COPYING3.  If not see
 #include "cgraph.h"
 #include "except.h"
 #include "dbgcnt.h"
+#include "tree-flow.h"
 
 /* Like PREFERRED_STACK_BOUNDARY but in units of bytes, not bits.  */
 #define STACK_BYTES (PREFERRED_STACK_BOUNDARY / BITS_PER_UNIT)
@@ -129,12 +131,12 @@ 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 *, tree, int);
+static void precompute_arguments (int, struct arg_data *);
+static int compute_argument_block_size (int, struct args_size *, tree, tree, int);
 static void initialize_argument_information (int, struct arg_data *,
                                             struct args_size *, int,
                                             tree, tree,
-                                            tree, CUMULATIVE_ARGS *, int,
+                                            tree, tree, CUMULATIVE_ARGS *, int,
                                             rtx *, int *, int *, int *,
                                             bool *, bool);
 static void compute_argument_addresses (struct arg_data *, rtx, int);
@@ -377,27 +379,23 @@ emit_call_1 (rtx funexp, tree fntree, tree fndecl ATTRIBUTE_UNUSED,
   /* If this call can't throw, attach a REG_EH_REGION reg note to that
      effect.  */
   if (ecf_flags & ECF_NOTHROW)
-    REG_NOTES (call_insn) = gen_rtx_EXPR_LIST (REG_EH_REGION, const0_rtx,
-                                              REG_NOTES (call_insn));
+    add_reg_note (call_insn, REG_EH_REGION, const0_rtx);
   else
     {
-      int rn = lookup_stmt_eh_region (fntree);
+      int rn = lookup_expr_eh_region (fntree);
 
       /* If rn < 0, then either (1) tree-ssa not used or (2) doesn't
         throw, which we already took care of.  */
       if (rn > 0)
-       REG_NOTES (call_insn) = gen_rtx_EXPR_LIST (REG_EH_REGION, GEN_INT (rn),
-                                                  REG_NOTES (call_insn));
+       add_reg_note (call_insn, REG_EH_REGION, GEN_INT (rn));
     }
 
   if (ecf_flags & ECF_NORETURN)
-    REG_NOTES (call_insn) = gen_rtx_EXPR_LIST (REG_NORETURN, const0_rtx,
-                                              REG_NOTES (call_insn));
+    add_reg_note (call_insn, REG_NORETURN, const0_rtx);
 
   if (ecf_flags & ECF_RETURNS_TWICE)
     {
-      REG_NOTES (call_insn) = gen_rtx_EXPR_LIST (REG_SETJMP, const0_rtx,
-                                                REG_NOTES (call_insn));
+      add_reg_note (call_insn, REG_SETJMP, const0_rtx);
       cfun->calls_setjmp = 1;
     }
 
@@ -417,6 +415,10 @@ emit_call_1 (rtx funexp, tree fntree, tree fndecl ATTRIBUTE_UNUSED,
       rounded_stack_size -= n_popped;
       rounded_stack_size_rtx = GEN_INT (rounded_stack_size);
       stack_pointer_delta -= n_popped;
+
+      /* If popup is needed, stack realign must use DRAP  */
+      if (SUPPORTS_STACK_ALIGNMENT)
+        crtl->need_drap = true;
     }
 
   if (!ACCUMULATE_OUTGOING_ARGS)
@@ -496,10 +498,14 @@ special_function_p (const_tree fndecl, int flags)
               && ! strcmp (name, "__builtin_alloca"))))
        flags |= ECF_MAY_BE_ALLOCA;
 
-      /* Disregard prefix _, __ or __x.  */
+      /* Disregard prefix _, __, __x or __builtin_.  */
       if (name[0] == '_')
        {
-         if (name[1] == '_' && name[2] == 'x')
+         if (name[1] == '_'
+             && name[2] == 'b'
+             && !strncmp (name + 3, "uiltin_", 7))
+           tname += 10;
+         else if (name[1] == '_' && name[2] == 'x')
            tname += 3;
          else if (name[1] == '_')
            tname += 2;
@@ -546,7 +552,26 @@ setjmp_call_p (const_tree fndecl)
   return special_function_p (fndecl, 0) & ECF_RETURNS_TWICE;
 }
 
+
+/* Return true if STMT is an alloca call.  */
+
+bool
+gimple_alloca_call_p (const_gimple stmt)
+{
+  tree fndecl;
+
+  if (!is_gimple_call (stmt))
+    return false;
+
+  fndecl = gimple_call_fndecl (stmt);
+  if (fndecl && (special_function_p (fndecl, 0) & ECF_MAY_BE_ALLOCA))
+    return true;
+
+  return false;
+}
+
 /* Return true when exp contains alloca call.  */
+
 bool
 alloca_call_p (const_tree exp)
 {
@@ -692,7 +717,8 @@ precompute_register_parameters (int num_actuals, struct arg_data *args,
                     || (GET_CODE (args[i].value) == SUBREG
                         && REG_P (SUBREG_REG (args[i].value)))))
                 && args[i].mode != BLKmode
-                && rtx_cost (args[i].value, SET) > COSTS_N_INSNS (1)
+                && rtx_cost (args[i].value, SET, optimize_insn_for_speed_p ())
+                   > COSTS_N_INSNS (1)
                 && ((SMALL_REGISTER_CLASSES && *reg_parm_seen)
                     || optimize))
          args[i].value = copy_to_mode_reg (args[i].mode, args[i].value);
@@ -815,7 +841,8 @@ store_unaligned_arguments_into_pseudos (struct arg_data *args, int num_actuals)
   for (i = 0; i < num_actuals; i++)
     if (args[i].reg != 0 && ! args[i].pass_on_stack
        && args[i].mode == BLKmode
-       && (TYPE_ALIGN (TREE_TYPE (args[i].tree_value))
+       && MEM_P (args[i].value)
+       && (MEM_ALIGN (args[i].value)
            < (unsigned int) MIN (BIGGEST_ALIGNMENT, BITS_PER_WORD)))
       {
        int bytes = int_size_in_bytes (TREE_TYPE (args[i].tree_value));
@@ -915,13 +942,14 @@ initialize_argument_information (int num_actuals ATTRIBUTE_UNUSED,
                                 struct args_size *args_size,
                                 int n_named_args ATTRIBUTE_UNUSED,
                                 tree exp, tree struct_value_addr_value,
-                                tree fndecl,
+                                tree fndecl, tree fntype,
                                 CUMULATIVE_ARGS *args_so_far,
                                 int reg_parm_stack_space,
                                 rtx *old_stack_level, int *old_pending_adj,
                                 int *must_preallocate, int *ecf_flags,
                                 bool *may_tailcall, bool call_from_thunk_p)
 {
+  location_t loc = EXPR_LOCATION (exp);
   /* 1 if scanning parms front to back, -1 if scanning back to front.  */
   int inc;
 
@@ -969,7 +997,6 @@ initialize_argument_information (int num_actuals ATTRIBUTE_UNUSED,
            && targetm.calls.split_complex_arg (argtype))
          {
            tree subtype = TREE_TYPE (argtype);
-           arg = save_expr (arg);
            args[j].tree_value = build1 (REALPART_EXPR, subtype, arg);
            j += inc;
            args[j].tree_value = build1 (IMAGPART_EXPR, subtype, arg);
@@ -1028,6 +1055,7 @@ initialize_argument_information (int num_actuals ATTRIBUTE_UNUSED,
              || (callee_copies
                  && !TREE_ADDRESSABLE (type)
                  && (base = get_base_address (args[i].tree_value))
+                 && TREE_CODE (base) != SSA_NAME
                  && (!DECL_P (base) || MEM_P (DECL_RTL (base)))))
            {
              /* We can't use sibcalls if a callee-copied argument is
@@ -1035,12 +1063,12 @@ initialize_argument_information (int num_actuals ATTRIBUTE_UNUSED,
              if (!call_from_thunk_p && DECL_P (base) && !TREE_STATIC (base))
                *may_tailcall = false;
 
-             args[i].tree_value = build_fold_addr_expr (args[i].tree_value);
+             args[i].tree_value = build_fold_addr_expr_loc (loc,
+                                                        args[i].tree_value);
              type = TREE_TYPE (args[i].tree_value);
 
              if (*ecf_flags & ECF_CONST)
                *ecf_flags &= ~(ECF_CONST | ECF_LOOPING_CONST_OR_PURE);
-             *ecf_flags &= ~ECF_LIBCALL_BLOCK;
            }
          else
            {
@@ -1049,10 +1077,10 @@ initialize_argument_information (int num_actuals ATTRIBUTE_UNUSED,
              rtx copy;
 
              if (!COMPLETE_TYPE_P (type)
-                 || TREE_CODE (TYPE_SIZE (type)) != INTEGER_CST
-                 || (flag_stack_check && ! STACK_CHECK_BUILTIN
-                     && (0 < compare_tree_int (TYPE_SIZE_UNIT (type),
-                                               STACK_CHECK_MAX_VAR_SIZE))))
+                 || TREE_CODE (TYPE_SIZE_UNIT (type)) != INTEGER_CST
+                 || (flag_stack_check == GENERIC_STACK_CHECK
+                     && compare_tree_int (TYPE_SIZE_UNIT (type),
+                                          STACK_CHECK_MAX_VAR_SIZE) > 0))
                {
                  /* This is a variable-sized object.  Make space on the stack
                     for it.  */
@@ -1075,8 +1103,6 @@ initialize_argument_information (int num_actuals ATTRIBUTE_UNUSED,
 
              store_expr (args[i].tree_value, copy, 0, false);
 
-             *ecf_flags &= ~(ECF_LIBCALL_BLOCK);
-
              /* Just change the const function to pure and then let
                 the next test clear the pure based on
                 callee_copies.  */
@@ -1090,17 +1116,15 @@ initialize_argument_information (int num_actuals ATTRIBUTE_UNUSED,
                *ecf_flags &= ~(ECF_PURE | ECF_LOOPING_CONST_OR_PURE);
 
              args[i].tree_value
-               = build_fold_addr_expr (make_tree (type, copy));
+               = build_fold_addr_expr_loc (loc, make_tree (type, copy));
              type = TREE_TYPE (args[i].tree_value);
              *may_tailcall = false;
            }
        }
 
-      mode = TYPE_MODE (type);
       unsignedp = TYPE_UNSIGNED (type);
-
-      if (targetm.calls.promote_function_args (fndecl ? TREE_TYPE (fndecl) : 0))
-       mode = promote_mode (type, mode, &unsignedp, 1);
+      mode = promote_function_mode (type, TYPE_MODE (type), &unsignedp,
+                                   fndecl ? TREE_TYPE (fndecl) : fntype, 0);
 
       args[i].unsignedp = unsignedp;
       args[i].mode = mode;
@@ -1140,11 +1164,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
@@ -1190,6 +1209,7 @@ static int
 compute_argument_block_size (int reg_parm_stack_space,
                             struct args_size *args_size,
                             tree fndecl ATTRIBUTE_UNUSED,
+                            tree fntype ATTRIBUTE_UNUSED,
                             int preferred_stack_boundary ATTRIBUTE_UNUSED)
 {
   int unadjusted_args_size = args_size->constant;
@@ -1227,7 +1247,7 @@ compute_argument_block_size (int 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.  */
-         if (! OUTGOING_REG_PARM_STACK_SPACE ((!fndecl ? NULL_TREE : TREE_TYPE (fndecl))))
+         if (! OUTGOING_REG_PARM_STACK_SPACE ((!fndecl ? fntype : TREE_TYPE (fndecl))))
            args_size->var
              = size_binop (MINUS_EXPR, args_size->var,
                            ssize_int (reg_parm_stack_space));
@@ -1248,7 +1268,7 @@ compute_argument_block_size (int reg_parm_stack_space,
       args_size->constant = MAX (args_size->constant,
                                 reg_parm_stack_space);
 
-      if (! OUTGOING_REG_PARM_STACK_SPACE ((!fndecl ? NULL_TREE : TREE_TYPE (fndecl))))
+      if (! OUTGOING_REG_PARM_STACK_SPACE ((!fndecl ? fntype : TREE_TYPE (fndecl))))
        args_size->constant -= reg_parm_stack_space;
     }
   return unadjusted_args_size;
@@ -1265,7 +1285,7 @@ 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;
 
@@ -1279,35 +1299,38 @@ precompute_arguments (int flags, int num_actuals, struct arg_data *args)
      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 ((flags & ECF_LIBCALL_BLOCK) == 0 && !ACCUMULATE_OUTGOING_ARGS)
+  if (!ACCUMULATE_OUTGOING_ARGS)
     return;
 
   for (i = 0; i < num_actuals; i++)
     {
+      tree type;
       enum machine_mode mode;
 
-      if ((flags & ECF_LIBCALL_BLOCK) == 0
-         && TREE_CODE (args[i].tree_value) != CALL_EXPR)
+      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)));
+      type = TREE_TYPE (args[i].tree_value);
+      gcc_assert (!TREE_ADDRESSABLE (type));
 
       args[i].initial_value = args[i].value
        = expand_normal (args[i].tree_value);
 
-      mode = TYPE_MODE (TREE_TYPE (args[i].tree_value));
+      mode = TYPE_MODE (type);
       if (mode != args[i].mode)
        {
+         int unsignedp = args[i].unsignedp;
          args[i].value
            = convert_modes (args[i].mode, mode,
                             args[i].value, args[i].unsignedp);
-#if defined(PROMOTE_FUNCTION_MODE) && !defined(PROMOTE_MODE)
+
          /* CSE will replace this only if it contains args[i].value
             pseudo, so convert it down to the declared mode using
             a SUBREG.  */
          if (REG_P (args[i].value)
-             && GET_MODE_CLASS (args[i].mode) == MODE_INT)
+             && GET_MODE_CLASS (args[i].mode) == MODE_INT
+             && promote_mode (type, mode, &unsignedp) != args[i].mode)
            {
              args[i].initial_value
                = gen_lowpart_SUBREG (mode, args[i].value);
@@ -1315,7 +1338,6 @@ precompute_arguments (int flags, int num_actuals, struct arg_data *args)
              SUBREG_PROMOTED_UNSIGNED_SET (args[i].initial_value,
                                            args[i].unsignedp);
            }
-#endif
        }
     }
 }
@@ -1410,7 +1432,7 @@ compute_argument_addresses (struct arg_data *args, rtx argblock, int num_actuals
              && args[i].partial == 0)
            continue;
 
-         if (GET_CODE (offset) == CONST_INT)
+         if (CONST_INT_P (offset))
            addr = plus_constant (arg_reg, INTVAL (offset));
          else
            addr = gen_rtx_PLUS (Pmode, arg_reg, offset);
@@ -1437,14 +1459,14 @@ compute_argument_addresses (struct arg_data *args, rtx argblock, int num_actuals
          boundary = args[i].locate.boundary;
          if (args[i].locate.where_pad != downward)
            align = boundary;
-         else if (GET_CODE (offset) == CONST_INT)
+         else if (CONST_INT_P (offset))
            {
              align = INTVAL (offset) * BITS_PER_UNIT | boundary;
              align = align & -align;
            }
          set_mem_align (args[i].stack, align);
 
-         if (GET_CODE (slot_offset) == CONST_INT)
+         if (CONST_INT_P (slot_offset))
            addr = plus_constant (arg_reg, INTVAL (slot_offset));
          else
            addr = gen_rtx_PLUS (Pmode, arg_reg, slot_offset);
@@ -1528,7 +1550,7 @@ mem_overlaps_already_clobbered_arg_p (rtx addr, unsigned HOST_WIDE_INT size)
     i = 0;
   else if (GET_CODE (addr) == PLUS
           && XEXP (addr, 0) == crtl->args.internal_arg_pointer
-          && GET_CODE (XEXP (addr, 1)) == CONST_INT)
+          && CONST_INT_P (XEXP (addr, 1)))
     i = INTVAL (XEXP (addr, 1));
   /* Return true for arg pointer based indexed addressing.  */
   else if (GET_CODE (addr) == PLUS
@@ -1865,7 +1887,7 @@ shift_return_value (enum machine_mode mode, bool left_p, rtx value)
 static rtx
 avoid_likely_spilled_reg (rtx x)
 {
-  rtx new;
+  rtx new_rtx;
 
   if (REG_P (x)
       && HARD_REGISTER_P (x)
@@ -1876,10 +1898,10 @@ avoid_likely_spilled_reg (rtx x)
         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));
+      new_rtx = gen_reg_rtx (GET_MODE (x));
       generating_concat_p = 1;
-      emit_move_insn (new, x);
-      return new;
+      emit_move_insn (new_rtx, x);
+      return new_rtx;
     }
   return x;
 }
@@ -2063,21 +2085,20 @@ expand_call (tree exp, rtx target, int ignore)
     }
 
 #ifdef REG_PARM_STACK_SPACE
-  reg_parm_stack_space = REG_PARM_STACK_SPACE (fndecl);
+  reg_parm_stack_space = REG_PARM_STACK_SPACE (!fndecl ? fntype : fndecl);
 #endif
 
-  if (! OUTGOING_REG_PARM_STACK_SPACE ((!fndecl ? NULL_TREE : TREE_TYPE (fndecl)))
+  if (! OUTGOING_REG_PARM_STACK_SPACE ((!fndecl ? fntype : TREE_TYPE (fndecl)))
       && reg_parm_stack_space > 0 && PUSH_ARGS)
     must_preallocate = 1;
 
   /* Set up a place to return a structure.  */
 
   /* Cater to broken compilers.  */
-  if (aggregate_value_p (exp, fndecl))
+  if (aggregate_value_p (exp, (!fndecl ? fntype : fndecl)))
     {
       /* This call returns a big structure.  */
-      flags &= ~(ECF_CONST | ECF_PURE | ECF_LOOPING_CONST_OR_PURE 
-                | ECF_LIBCALL_BLOCK);
+      flags &= ~(ECF_CONST | ECF_PURE | ECF_LOOPING_CONST_OR_PURE);
 
 #ifdef PCC_STATIC_STRUCT_RETURN
       {
@@ -2109,7 +2130,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;
     }
 
@@ -2217,29 +2245,21 @@ expand_call (tree exp, rtx target, int ignore)
     n_named_args = num_actuals;
 
   /* Make a vector to hold all the information about each arg.  */
-  args = alloca (num_actuals * sizeof (struct arg_data));
+  args = XALLOCAVEC (struct arg_data, num_actuals);
   memset (args, 0, num_actuals * sizeof (struct arg_data));
 
   /* Build up entries in the ARGS array, compute the size of the
      arguments into ARGS_SIZE, etc.  */
   initialize_argument_information (num_actuals, args, &args_size,
                                   n_named_args, exp,
-                                  structure_value_addr_value, fndecl,
+                                  structure_value_addr_value, fndecl, fntype,
                                   &args_so_far, reg_parm_stack_space,
                                   &old_stack_level, &old_pending_adj,
                                   &must_preallocate, &flags,
                                   &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,
@@ -2266,7 +2286,7 @@ 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_expr_eh_region (exp) >= 0
       || dbg_cnt (tail_call) == false)
     try_tail_call = 0;
 
@@ -2283,6 +2303,12 @@ expand_call (tree exp, rtx target, int ignore)
         It does not seem worth the effort since few optimizable
         sibling calls will return a structure.  */
       || structure_value_addr != NULL_RTX
+#ifdef REG_PARM_STACK_SPACE
+      /* If outgoing reg parm stack space changes, we can not do sibcall.  */
+      || (OUTGOING_REG_PARM_STACK_SPACE (funtype)
+         != OUTGOING_REG_PARM_STACK_SPACE (TREE_TYPE (current_function_decl)))
+      || (reg_parm_stack_space != REG_PARM_STACK_SPACE (fndecl))
+#endif
       /* Check whether the target is able to optimize the call
         into a sibcall.  */
       || !targetm.function_ok_for_sibcall (fndecl, exp)
@@ -2309,12 +2335,44 @@ expand_call (tree exp, rtx target, int ignore)
       || !lang_hooks.decls.ok_for_sibcall (fndecl))
     try_tail_call = 0;
 
+  /* Check if caller and callee disagree in promotion of function
+     return value.  */
+  if (try_tail_call)
+    {
+      enum machine_mode caller_mode, caller_promoted_mode;
+      enum machine_mode callee_mode, callee_promoted_mode;
+      int caller_unsignedp, callee_unsignedp;
+      tree caller_res = DECL_RESULT (current_function_decl);
+
+      caller_unsignedp = TYPE_UNSIGNED (TREE_TYPE (caller_res));
+      caller_mode = DECL_MODE (caller_res);
+      callee_unsignedp = TYPE_UNSIGNED (TREE_TYPE (funtype));
+      callee_mode = TYPE_MODE (TREE_TYPE (funtype));
+      caller_promoted_mode
+       = promote_function_mode (TREE_TYPE (caller_res), caller_mode,
+                                &caller_unsignedp,
+                                TREE_TYPE (current_function_decl), 1);
+      callee_promoted_mode
+       = promote_function_mode (TREE_TYPE (funtype), callee_mode,
+                                &callee_unsignedp,
+                                funtype, 1);
+      if (caller_mode != VOIDmode
+         && (caller_promoted_mode != callee_promoted_mode
+             || ((caller_mode != caller_promoted_mode
+                  || callee_mode != callee_promoted_mode)
+                 && (caller_unsignedp != callee_unsignedp
+                     || GET_MODE_BITSIZE (caller_mode)
+                        < GET_MODE_BITSIZE (callee_mode)))))
+       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 (crtl->preferred_stack_boundary < preferred_stack_boundary
-      && fndecl != current_function_decl)
+     what we need.  Stack alignment may also increase preferred stack
+     boundary.  */
+  if (crtl->preferred_stack_boundary < preferred_stack_boundary)
     crtl->preferred_stack_boundary = preferred_stack_boundary;
+  else
+    preferred_stack_boundary = crtl->preferred_stack_boundary;
 
   preferred_unit_stack_boundary = preferred_stack_boundary / BITS_PER_UNIT;
 
@@ -2370,18 +2428,13 @@ expand_call (tree exp, rtx target, int ignore)
          || 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 && crtl->stack_protect_guard)
@@ -2396,7 +2449,7 @@ expand_call (tree exp, rtx target, int ignore)
       unadjusted_args_size
        = compute_argument_block_size (reg_parm_stack_space,
                                       &adjusted_args_size,
-                                      fndecl,
+                                      fndecl, fntype,
                                       (pass == 0 ? 0
                                        : preferred_stack_boundary));
 
@@ -2406,7 +2459,7 @@ expand_call (tree exp, rtx target, int ignore)
         incoming argument block.  */
       if (pass == 0)
        {
-         argblock = virtual_incoming_args_rtx;
+         argblock = crtl->args.internal_arg_pointer;
          argblock
 #ifdef STACK_GROWS_DOWNWARD
            = plus_constant (argblock, crtl->args.pretend_args_size);
@@ -2472,7 +2525,7 @@ expand_call (tree exp, rtx target, int ignore)
                  /* 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.  */
-                 if (! OUTGOING_REG_PARM_STACK_SPACE ((!fndecl ? NULL_TREE : TREE_TYPE (fndecl))))
+                 if (! OUTGOING_REG_PARM_STACK_SPACE ((!fndecl ? fntype : TREE_TYPE (fndecl))))
                    needed += reg_parm_stack_space;
 
 #ifdef ARGS_GROW_DOWNWARD
@@ -2571,7 +2624,7 @@ expand_call (tree exp, rtx target, int ignore)
            {
              rtx push_size
                = GEN_INT (adjusted_args_size.constant
-                          + (OUTGOING_REG_PARM_STACK_SPACE ((!fndecl ? NULL
+                          + (OUTGOING_REG_PARM_STACK_SPACE ((!fndecl ? fntype
                                                                      : TREE_TYPE (fndecl))) ? 0
                              : reg_parm_stack_space));
              if (old_stack_level == 0)
@@ -2619,7 +2672,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
@@ -2689,26 +2741,28 @@ expand_call (tree exp, rtx target, int ignore)
         but we do preallocate space here if they want that.  */
 
       for (i = 0; i < num_actuals; i++)
-       if (args[i].reg == 0 || args[i].pass_on_stack)
-         {
-           rtx before_arg = get_last_insn ();
-
-           if (store_one_arg (&args[i], argblock, flags,
-                              adjusted_args_size.var != 0,
-                              reg_parm_stack_space)
-               || (pass == 0
-                   && check_sibcall_argument_overlap (before_arg,
-                                                      &args[i], 1)))
-             sibcall_failure = 1;
-
-           if (flags & ECF_CONST
-               && args[i].stack
-               && args[i].value == args[i].stack)
-             call_fusage = gen_rtx_EXPR_LIST (VOIDmode,
-                                              gen_rtx_USE (VOIDmode,
-                                                           args[i].value),
-                                              call_fusage);
-         }
+       {
+         if (args[i].reg == 0 || args[i].pass_on_stack)
+           {
+             rtx before_arg = get_last_insn ();
+
+             if (store_one_arg (&args[i], argblock, flags,
+                                adjusted_args_size.var != 0,
+                                reg_parm_stack_space)
+                 || (pass == 0
+                     && check_sibcall_argument_overlap (before_arg,
+                                                        &args[i], 1)))
+               sibcall_failure = 1;
+             }
+
+         if (((flags & ECF_CONST)
+              || ((flags & ECF_PURE) && ACCUMULATE_OUTGOING_ARGS))
+             && args[i].stack)
+           call_fusage = gen_rtx_EXPR_LIST (VOIDmode,
+                                            gen_rtx_USE (VOIDmode,
+                                                         args[i].stack),
+                                            call_fusage);
+       }
 
       /* If we have a parm that is passed in registers but not in memory
         and whose alignment does not permit a direct copy into registers,
@@ -2743,7 +2797,7 @@ 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.  */
-      if (OUTGOING_REG_PARM_STACK_SPACE ((!fndecl ? NULL_TREE : TREE_TYPE (fndecl)))
+      if (OUTGOING_REG_PARM_STACK_SPACE ((!fndecl ? fntype : TREE_TYPE (fndecl)))
           && !ACCUMULATE_OUTGOING_ARGS
          && must_preallocate == 0 && reg_parm_stack_space > 0)
        anti_adjust_stack (GEN_INT (reg_parm_stack_space));
@@ -2819,65 +2873,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);
-               }
-             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;
@@ -2891,8 +2887,7 @@ expand_call (tree exp, rtx target, int ignore)
          /* The return value from a malloc-like function can not alias
             anything else.  */
          last = get_last_insn ();
-         REG_NOTES (last) =
-           gen_rtx_EXPR_LIST (REG_NOALIAS, temp, REG_NOTES (last));
+         add_reg_note (last, REG_NOALIAS, temp);
 
          /* Write out the sequence.  */
          insns = get_insns ();
@@ -3034,38 +3029,37 @@ expand_call (tree exp, rtx target, int ignore)
       else
        target = copy_to_reg (avoid_likely_spilled_reg (valreg));
 
-      if (targetm.calls.promote_function_return(funtype))
+      /* If we promoted this return value, make the proper SUBREG.
+         TARGET might be const0_rtx here, so be careful.  */
+      if (REG_P (target)
+         && TYPE_MODE (TREE_TYPE (exp)) != BLKmode
+         && GET_MODE (target) != TYPE_MODE (TREE_TYPE (exp)))
        {
-         /* If we promoted this return value, make the proper SUBREG.
-            TARGET might be const0_rtx here, so be careful.  */
-         if (REG_P (target)
-             && TYPE_MODE (TREE_TYPE (exp)) != BLKmode
-             && GET_MODE (target) != TYPE_MODE (TREE_TYPE (exp)))
+         tree type = TREE_TYPE (exp);
+         int unsignedp = TYPE_UNSIGNED (type);
+         int offset = 0;
+         enum machine_mode pmode;
+
+         /* Ensure we promote as expected, and get the new unsignedness.  */
+         pmode = promote_function_mode (type, TYPE_MODE (type), &unsignedp,
+                                        funtype, 1);
+         gcc_assert (GET_MODE (target) == pmode);
+
+         if ((WORDS_BIG_ENDIAN || BYTES_BIG_ENDIAN)
+             && (GET_MODE_SIZE (GET_MODE (target))
+                 > GET_MODE_SIZE (TYPE_MODE (type))))
            {
-             tree type = TREE_TYPE (exp);
-             int unsignedp = TYPE_UNSIGNED (type);
-             int offset = 0;
-             enum machine_mode pmode;
-
-             pmode = promote_mode (type, TYPE_MODE (type), &unsignedp, 1);
-             /* If we don't promote as expected, something is wrong.  */
-             gcc_assert (GET_MODE (target) == pmode);
-
-             if ((WORDS_BIG_ENDIAN || BYTES_BIG_ENDIAN)
-                 && (GET_MODE_SIZE (GET_MODE (target))
-                     > GET_MODE_SIZE (TYPE_MODE (type))))
-               {
-                 offset = GET_MODE_SIZE (GET_MODE (target))
-                   - GET_MODE_SIZE (TYPE_MODE (type));
-                 if (! BYTES_BIG_ENDIAN)
-                   offset = (offset / UNITS_PER_WORD) * UNITS_PER_WORD;
-                 else if (! WORDS_BIG_ENDIAN)
-                   offset %= UNITS_PER_WORD;
-               }
-             target = gen_rtx_SUBREG (TYPE_MODE (type), target, offset);
-             SUBREG_PROMOTED_VAR_P (target) = 1;
-             SUBREG_PROMOTED_UNSIGNED_SET (target, unsignedp);
+             offset = GET_MODE_SIZE (GET_MODE (target))
+               - GET_MODE_SIZE (TYPE_MODE (type));
+             if (! BYTES_BIG_ENDIAN)
+               offset = (offset / UNITS_PER_WORD) * UNITS_PER_WORD;
+             else if (! WORDS_BIG_ENDIAN)
+               offset %= UNITS_PER_WORD;
            }
+
+         target = gen_rtx_SUBREG (TYPE_MODE (type), target, offset);
+         SUBREG_PROMOTED_VAR_P (target) = 1;
+         SUBREG_PROMOTED_UNSIGNED_SET (target, unsignedp);
        }
 
       /* If size of args is variable or this was a constructor call for a stack
@@ -3282,6 +3276,7 @@ emit_library_call_value_1 (int retval, rtx orgfun, rtx value,
   /* 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 ? */
+  tree fntype ATTRIBUTE_UNUSED = NULL_TREE; /* library calls default to host calling abi ? */
   int inc;
   int count;
   rtx argblock = 0;
@@ -3311,7 +3306,7 @@ emit_library_call_value_1 (int retval, rtx orgfun, rtx value,
 #ifdef REG_PARM_STACK_SPACE
   /* Define the boundary of the register parm stack space that needs to be
      save, if any.  */
-  int low_to_save, high_to_save;
+  int low_to_save = 0, high_to_save = 0;
   rtx save_area = 0;            /* Place that it is saved.  */
 #endif
 
@@ -3339,12 +3334,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;
@@ -3384,8 +3373,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_LOOPING_CONST_OR_PURE 
-                    | ECF_LIBCALL_BLOCK);
+         flags &= ~(ECF_CONST | ECF_PURE | ECF_LOOPING_CONST_OR_PURE);
        }
     }
   else
@@ -3400,7 +3388,7 @@ emit_library_call_value_1 (int retval, rtx orgfun, rtx value,
      of the full argument passing conventions to limit complexity here since
      library functions shouldn't have many args.  */
 
-  argvec = alloca ((nargs + 1) * sizeof (struct arg));
+  argvec = XALLOCAVEC (struct arg, nargs + 1);
   memset (argvec, 0, (nargs + 1) * sizeof (struct arg));
 
 #ifdef INIT_CUMULATIVE_LIBCALL_ARGS
@@ -3414,11 +3402,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,
@@ -3462,7 +3445,7 @@ emit_library_call_value_1 (int retval, rtx orgfun, rtx value,
   for (; count < nargs; count++)
     {
       rtx val = va_arg (p, rtx);
-      enum machine_mode mode = va_arg (p, enum machine_mode);
+      enum machine_mode mode = (enum machine_mode) va_arg (p, int);
 
       /* We cannot convert the arg value to the mode the library wants here;
         must do it earlier where we know the signedness of the arg.  */
@@ -3480,15 +3463,6 @@ 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);
-           }
-
          /* If this was a CONST function, it is now PURE since it now
             reads memory.  */
          if (flags & ECF_CONST)
@@ -3497,7 +3471,7 @@ emit_library_call_value_1 (int retval, rtx orgfun, rtx value,
              flags |= ECF_PURE;
            }
 
-         if (GET_MODE (val) == MEM && !must_copy)
+         if (MEM_P (val) && !must_copy)
            slot = val;
          else
            {
@@ -3560,7 +3534,7 @@ emit_library_call_value_1 (int retval, rtx orgfun, rtx value,
   args_size.constant = MAX (args_size.constant,
                            reg_parm_stack_space);
 
-  if (! OUTGOING_REG_PARM_STACK_SPACE ((!fndecl ? NULL_TREE : TREE_TYPE (fndecl))))
+  if (! OUTGOING_REG_PARM_STACK_SPACE ((!fndecl ? fntype : TREE_TYPE (fndecl))))
     args_size.constant -= reg_parm_stack_space;
 
   if (args_size.constant > crtl->outgoing_args_size)
@@ -3585,7 +3559,7 @@ emit_library_call_value_1 (int retval, rtx orgfun, rtx value,
       /* 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.  */
-      if (! OUTGOING_REG_PARM_STACK_SPACE ((!fndecl ? NULL_TREE : TREE_TYPE (fndecl))))
+      if (! OUTGOING_REG_PARM_STACK_SPACE ((!fndecl ? fntype : TREE_TYPE (fndecl))))
        needed += reg_parm_stack_space;
 
 #ifdef ARGS_GROW_DOWNWARD
@@ -3661,6 +3635,7 @@ emit_library_call_value_1 (int retval, rtx orgfun, rtx value,
       rtx val = argvec[argnum].value;
       rtx reg = argvec[argnum].reg;
       int partial = argvec[argnum].partial;
+      unsigned int parm_align = argvec[argnum].locate.boundary;
       int lower_bound = 0, upper_bound = 0, i;
 
       if (! (reg != 0 && partial == 0))
@@ -3673,10 +3648,10 @@ emit_library_call_value_1 (int retval, rtx orgfun, rtx value,
 #ifdef ARGS_GROW_DOWNWARD
              /* stack_slot is negative, but we want to index stack_usage_map
                 with positive values.  */
-             upper_bound = -argvec[argnum].locate.offset.constant + 1;
+             upper_bound = -argvec[argnum].locate.slot_offset.constant + 1;
              lower_bound = upper_bound - argvec[argnum].locate.size.constant;
 #else
-             lower_bound = argvec[argnum].locate.offset.constant;
+             lower_bound = argvec[argnum].locate.slot_offset.constant;
              upper_bound = lower_bound + argvec[argnum].locate.size.constant;
 #endif
 
@@ -3722,7 +3697,7 @@ emit_library_call_value_1 (int retval, rtx orgfun, rtx value,
                }
            }
 
-         emit_push_insn (val, mode, NULL_TREE, NULL_RTX, PARM_BOUNDARY,
+         emit_push_insn (val, mode, NULL_TREE, NULL_RTX, parm_align,
                          partial, reg, 0, argblock,
                          GEN_INT (argvec[argnum].locate.offset.constant),
                          reg_parm_stack_space,
@@ -3735,7 +3710,8 @@ emit_library_call_value_1 (int retval, rtx orgfun, rtx value,
 
          NO_DEFER_POP;
 
-         if (flags & ECF_CONST)
+         if ((flags & ECF_CONST)
+             || ((flags & ECF_PURE) && ACCUMULATE_OUTGOING_ARGS))
            {
              rtx use;
 
@@ -3829,7 +3805,7 @@ emit_library_call_value_1 (int retval, rtx orgfun, rtx value,
      cse'ing of library calls could delete a call and leave the pop.  */
   NO_DEFER_POP;
   valreg = (mem_value == 0 && outmode != VOIDmode
-           ? hard_libcall_value (outmode) : NULL_RTX);
+           ? hard_libcall_value (outmode, orgfun) : NULL_RTX);
 
   /* Stack must be properly aligned now.  */
   gcc_assert (!(stack_pointer_delta
@@ -3878,49 +3854,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 ();
-         emit_libcall_block (insns, temp, valreg, note);
-
-         valreg = temp;
-       }
-    }
   pop_temp_slots ();
 
   /* Copy the value to the right place.  */
@@ -3941,15 +3874,14 @@ emit_library_call_value_1 (int retval, rtx orgfun, rtx value,
        }
       else
        {
-         /* Convert to the proper mode if PROMOTE_MODE has been active.  */
+         /* Convert to the proper mode if a promotion has been active.  */
          if (GET_MODE (valreg) != outmode)
            {
              int unsignedp = TYPE_UNSIGNED (tfom);
 
-             gcc_assert (targetm.calls.promote_function_return (tfom));
-             gcc_assert (promote_mode (tfom, outmode, &unsignedp, 0)
+             gcc_assert (promote_function_mode (tfom, outmode, &unsignedp,
+                                                fndecl ? TREE_TYPE (fndecl) : fntype, 1)
                          == GET_MODE (valreg));
-
              valreg = convert_modes (outmode, GET_MODE (valreg), valreg, 0);
            }
 
@@ -4004,12 +3936,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,
@@ -4304,7 +4233,8 @@ store_one_arg (struct arg_data *arg, rtx argblock, int flags,
                    - int_size_in_bytes (TREE_TYPE (pval))
                    + partial);
          size_rtx = expand_expr (size_in_bytes (TREE_TYPE (pval)),
-                                 NULL_RTX, TYPE_MODE (sizetype), 0);
+                                 NULL_RTX, TYPE_MODE (sizetype),
+                                 EXPAND_NORMAL);
        }
 
       parm_align = arg->locate.boundary;
@@ -4333,7 +4263,7 @@ store_one_arg (struct arg_data *arg, rtx argblock, int flags,
              || (GET_CODE (XEXP (x, 0)) == PLUS
                  && XEXP (XEXP (x, 0), 0) ==
                     crtl->args.internal_arg_pointer
-                 && GET_CODE (XEXP (XEXP (x, 0), 1)) == CONST_INT))
+                 && CONST_INT_P (XEXP (XEXP (x, 0), 1))))
            {
              if (XEXP (x, 0) != crtl->args.internal_arg_pointer)
                i = INTVAL (XEXP (XEXP (x, 0), 1));
@@ -4341,7 +4271,7 @@ store_one_arg (struct arg_data *arg, rtx argblock, int flags,
              /* expand_call should ensure this.  */
              gcc_assert (!arg->locate.offset.var
                          && arg->locate.size.var == 0
-                         && GET_CODE (size_rtx) == CONST_INT);
+                         && CONST_INT_P (size_rtx));
 
              if (arg->locate.offset.constant > i)
                {