OSDN Git Service

* config/i386/i386.c (ix86_function_regparm): Early exit for 64-bit;
authorrth <rth@138bc75d-0d04-0410-961f-82ee72b054a4>
Fri, 23 Mar 2007 02:02:38 +0000 (02:02 +0000)
committerrth <rth@138bc75d-0d04-0410-961f-82ee72b054a4>
Fri, 23 Mar 2007 02:02:38 +0000 (02:02 +0000)
        don't increase local_regparm with force_align_arg_pointer check.
        (ix86_function_sseregparm): Assert 32-bit.
        (type_has_variadic_args_p): New.
        (ix86_return_pops_args): Early exit for 64-bit.  Reindent; use
        type_has_variadic_args_p.
        (ix86_function_arg_regno_p): Use == 0 instead of ! test for eax.
        (init_cumulative_args): Remove TARGET_DEBUG_ARG.  Remove zero_cum;
        use memset instead.  Do maybe_vaarg check first; skip attribute
        tests if true; skip attribute tests for 64-bit.
        (construct_container): Remove TARGET_DEBUG_ARG.
        (function_arg_advance_32, function_arg_advance_64): Split out ...
        (function_arg_advance): ... from here.
        (function_arg_32, function_arg_64): Split out ...
        (function_arg): ... from here.
        (ix86_pass_by_reference): Tidy.
        (ix86_function_value_regno_p): Rearrange w/ switch on regno.
        (function_value_32): New, from parts of ix86_function_value
        and ix86_value_regno.
        (function_value_64): New, from parts of ix86_function_value
        and ix86_libcall_value.
        (ix86_function_value_1): New.
        (ix86_function_value, ix86_libcall_value): Use it.
        (return_in_memory_32, return_in_memory_64): Split out ...
        (ix86_return_in_memory): ... from here.
        (ix86_struct_value_rtx): Skip for 64-bit.
        (ix86_libcall_value, ix86_value_regno): Remove.
        (setup_incoming_varargs_64): Split out ...
        (ix86_setup_incoming_varargs): ... from here.
        (ix86_va_start): Remove TARGET_DEBUG_ARG.
        (legitimate_address_p, legitimize_address): Remove TARGET_DEBUG_ADDR.
        * config/i386/i386-protos.h (ix86_function_value): Remove.
        * config/i386/i386.opt (TARGET_DEBUG_ADDR, TARGET_DEBUG_ARG): Remove.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@123146 138bc75d-0d04-0410-961f-82ee72b054a4

gcc/ChangeLog
gcc/config/i386/i386-protos.h
gcc/config/i386/i386.c
gcc/config/i386/i386.opt

index 0ce3c38..6b56a44 100644 (file)
@@ -1,3 +1,39 @@
+2007-03-22  Richard Henderson  <rth@redhat.com>
+
+       * config/i386/i386.c (ix86_function_regparm): Early exit for 64-bit;
+       don't increase local_regparm with force_align_arg_pointer check.
+       (ix86_function_sseregparm): Assert 32-bit.
+       (type_has_variadic_args_p): New.
+       (ix86_return_pops_args): Early exit for 64-bit.  Reindent; use
+       type_has_variadic_args_p.
+       (ix86_function_arg_regno_p): Use == 0 instead of ! test for eax.
+       (init_cumulative_args): Remove TARGET_DEBUG_ARG.  Remove zero_cum;
+       use memset instead.  Do maybe_vaarg check first; skip attribute
+       tests if true; skip attribute tests for 64-bit.
+       (construct_container): Remove TARGET_DEBUG_ARG.
+       (function_arg_advance_32, function_arg_advance_64): Split out ...
+       (function_arg_advance): ... from here.
+       (function_arg_32, function_arg_64): Split out ...
+       (function_arg): ... from here.
+       (ix86_pass_by_reference): Tidy.
+       (ix86_function_value_regno_p): Rearrange w/ switch on regno.
+       (function_value_32): New, from parts of ix86_function_value
+       and ix86_value_regno.
+       (function_value_64): New, from parts of ix86_function_value
+       and ix86_libcall_value.
+       (ix86_function_value_1): New.
+       (ix86_function_value, ix86_libcall_value): Use it.
+       (return_in_memory_32, return_in_memory_64): Split out ...
+       (ix86_return_in_memory): ... from here.
+       (ix86_struct_value_rtx): Skip for 64-bit.
+       (ix86_libcall_value, ix86_value_regno): Remove.
+       (setup_incoming_varargs_64): Split out ...
+       (ix86_setup_incoming_varargs): ... from here.
+       (ix86_va_start): Remove TARGET_DEBUG_ARG.
+       (legitimate_address_p, legitimize_address): Remove TARGET_DEBUG_ADDR.
+       * config/i386/i386-protos.h (ix86_function_value): Remove.
+       * config/i386/i386.opt (TARGET_DEBUG_ADDR, TARGET_DEBUG_ARG): Remove.
+
 2007-03-22  Manuel Lopez-Ibanez  <manu@gcc.gnu.org>
 
        PR other/23572
index a3a0f66..aad4724 100644 (file)
@@ -179,7 +179,6 @@ extern void init_cumulative_args (CUMULATIVE_ARGS *, tree, rtx, tree);
 extern rtx function_arg (CUMULATIVE_ARGS *, enum machine_mode, tree, int);
 extern void function_arg_advance (CUMULATIVE_ARGS *, enum machine_mode,
                                  tree, int);
-extern rtx ix86_function_value (tree, tree, bool);
 #endif
 
 #endif
index 62e9f86..70a1bb9 100644 (file)
@@ -1562,7 +1562,6 @@ static int ix86_function_regparm (tree, tree);
 const struct attribute_spec ix86_attribute_table[];
 static bool ix86_function_ok_for_sibcall (tree, tree);
 static tree ix86_handle_cconv_attribute (tree *, tree, tree, int, bool *);
-static int ix86_value_regno (enum machine_mode, tree, tree);
 static bool contains_128bit_aligned_vector_p (tree);
 static rtx ix86_struct_value_rtx (tree, int);
 static bool ix86_ms_bitfield_layout_p (tree);
@@ -1584,6 +1583,7 @@ static rtx ix86_internal_arg_pointer (void);
 static void ix86_dwarf_handle_frame_unspec (const char *, rtx, int);
 static bool ix86_expand_vector_init_one_nonzero (bool, enum machine_mode,
                                                 rtx, rtx, int);
+static rtx ix86_function_value (tree, tree, bool);
 
 /* This function is only used on Solaris.  */
 static void i386_solaris_elf_named_section (const char *, unsigned int, tree)
@@ -2997,69 +2997,64 @@ ix86_function_regparm (tree type, tree decl)
 {
   tree attr;
   int regparm = ix86_regparm;
-  bool user_convention = false;
 
-  if (!TARGET_64BIT)
-    {
-      attr = lookup_attribute ("regparm", TYPE_ATTRIBUTES (type));
-      if (attr)
-       {
-         regparm = TREE_INT_CST_LOW (TREE_VALUE (TREE_VALUE (attr)));
-         user_convention = true;
-       }
+  if (TARGET_64BIT)
+    return regparm;
 
-      if (lookup_attribute ("fastcall", TYPE_ATTRIBUTES (type)))
-       {
-         regparm = 2;
-         user_convention = true;
-       }
+  attr = lookup_attribute ("regparm", TYPE_ATTRIBUTES (type));
+  if (attr)
+    return TREE_INT_CST_LOW (TREE_VALUE (TREE_VALUE (attr)));
+
+  if (lookup_attribute ("fastcall", TYPE_ATTRIBUTES (type)))
+    return 2;
 
-      /* Use register calling convention for local functions when possible.  */
-      if (!TARGET_64BIT && !user_convention && decl
-         && flag_unit_at_a_time && !profile_flag)
+  /* Use register calling convention for local functions when possible.  */
+  if (decl && flag_unit_at_a_time && !profile_flag)
+    {
+      struct cgraph_local_info *i = cgraph_local_info (decl);
+      if (i && i->local)
        {
-         struct cgraph_local_info *i = cgraph_local_info (decl);
-         if (i && i->local)
-           {
-             int local_regparm, globals = 0, regno;
+         int local_regparm, globals = 0, regno;
+         struct function *f;
 
-             /* Make sure no regparm register is taken by a global register
-                variable.  */
-             for (local_regparm = 0; local_regparm < 3; local_regparm++)
-               if (global_regs[local_regparm])
-                 break;
-             /* We can't use regparm(3) for nested functions as these use
-                static chain pointer in third argument.  */
-             if (local_regparm == 3
-                 && decl_function_context (decl)
-                 && !DECL_NO_STATIC_CHAIN (decl))
-               local_regparm = 2;
-             /* If the function realigns its stackpointer, the
-                prologue will clobber %ecx.  If we've already
-                generated code for the callee, the callee
-                DECL_STRUCT_FUNCTION is gone, so we fall back to
-                scanning the attributes for the self-realigning
-                property.  */
-             if ((DECL_STRUCT_FUNCTION (decl)
-                  && DECL_STRUCT_FUNCTION (decl)->machine->force_align_arg_pointer)
-                 || (!DECL_STRUCT_FUNCTION (decl)
-                     && lookup_attribute (ix86_force_align_arg_pointer_string,
-                                          TYPE_ATTRIBUTES (TREE_TYPE (decl)))))
-               local_regparm = 2;
-             /* Each global register variable increases register preassure,
-                so the more global reg vars there are, the smaller regparm
-                optimization use, unless requested by the user explicitly.  */
-             for (regno = 0; regno < 6; regno++)
-               if (global_regs[regno])
-                 globals++;
-             local_regparm
-               = globals < local_regparm ? local_regparm - globals : 0;
-
-             if (local_regparm > regparm)
-               regparm = local_regparm;
-           }
+         /* Make sure no regparm register is taken by a
+            global register variable.  */
+         for (local_regparm = 0; local_regparm < 3; local_regparm++)
+           if (global_regs[local_regparm])
+             break;
+
+         /* We can't use regparm(3) for nested functions as these use
+            static chain pointer in third argument.  */
+         if (local_regparm == 3
+             && decl_function_context (decl)
+             && !DECL_NO_STATIC_CHAIN (decl))
+           local_regparm = 2;
+
+         /* If the function realigns its stackpointer, the prologue will
+            clobber %ecx.  If we've already generated code for the callee,
+            the callee DECL_STRUCT_FUNCTION is gone, so we fall back to
+            scanning the attributes for the self-realigning property.  */
+         f = DECL_STRUCT_FUNCTION (decl);
+         if (local_regparm == 3
+             && (f ? !!f->machine->force_align_arg_pointer
+                 : !!lookup_attribute (ix86_force_align_arg_pointer_string,
+                                       TYPE_ATTRIBUTES (TREE_TYPE (decl)))))
+           local_regparm = 2;
+
+         /* Each global register variable increases register preassure,
+            so the more global reg vars there are, the smaller regparm
+            optimization use, unless requested by the user explicitly.  */
+         for (regno = 0; regno < 6; regno++)
+           if (global_regs[regno])
+             globals++;
+         local_regparm
+           = globals < local_regparm ? local_regparm - globals : 0;
+
+         if (local_regparm > regparm)
+           regparm = local_regparm;
        }
     }
+
   return regparm;
 }
 
@@ -3071,11 +3066,12 @@ ix86_function_regparm (tree type, tree decl)
 static int
 ix86_function_sseregparm (tree type, tree decl)
 {
+  gcc_assert (!TARGET_64BIT);
+
   /* Use SSE registers to pass SFmode and DFmode arguments if requested
      by the sseregparm attribute.  */
   if (TARGET_SSEREGPARM
-      || (type
-         && lookup_attribute ("sseregparm", TYPE_ATTRIBUTES (type))))
+      || (type && lookup_attribute ("sseregparm", TYPE_ATTRIBUTES (type))))
     {
       if (!TARGET_SSE)
        {
@@ -3092,10 +3088,8 @@ ix86_function_sseregparm (tree type, tree decl)
     }
 
   /* For local functions, pass up to SSE_REGPARM_MAX SFmode
-     (and DFmode for SSE2) arguments in SSE registers,
-     even for 32-bit targets.  */
-  if (!TARGET_64BIT && decl
-      && TARGET_SSE_MATH && flag_unit_at_a_time && !profile_flag)
+     (and DFmode for SSE2) arguments in SSE registers.  */
+  if (decl && TARGET_SSE_MATH && flag_unit_at_a_time && !profile_flag)
     {
       struct cgraph_local_info *i = cgraph_local_info (decl);
       if (i && i->local)
@@ -3121,6 +3115,19 @@ ix86_eax_live_at_start_p (void)
   return REGNO_REG_SET_P (ENTRY_BLOCK_PTR->il.rtl->global_live_at_end, 0);
 }
 
+/* Return true if TYPE has a variable argument list.  */
+
+static bool
+type_has_variadic_args_p (tree type)
+{
+  tree t;
+
+  for (t = TYPE_ARG_TYPES (type); t; t = TREE_CHAIN (t))
+    if (t == void_list_node)
+      return false;
+  return true;
+}
+
 /* Value is the number of bytes of arguments automatically
    popped when returning from a subroutine call.
    FUNDECL is the declaration node of the function (as a tree),
@@ -3141,32 +3148,33 @@ ix86_eax_live_at_start_p (void)
 int
 ix86_return_pops_args (tree fundecl, tree funtype, int size)
 {
-  int rtd = TARGET_RTD && (!fundecl || TREE_CODE (fundecl) != IDENTIFIER_NODE);
+  int rtd;
+
+  /* None of the 64-bit ABIs pop arguments.  */
+  if (TARGET_64BIT)
+    return 0;
+
+  rtd = TARGET_RTD && (!fundecl || TREE_CODE (fundecl) != IDENTIFIER_NODE);
 
   /* Cdecl functions override -mrtd, and never pop the stack.  */
-  if (! lookup_attribute ("cdecl", TYPE_ATTRIBUTES (funtype))) {
-
-    /* Stdcall and fastcall functions will pop the stack if not
-       variable args.  */
-    if (lookup_attribute ("stdcall", TYPE_ATTRIBUTES (funtype))
-        || lookup_attribute ("fastcall", TYPE_ATTRIBUTES (funtype)))
-      rtd = 1;
-
-    if (rtd
-        && (TYPE_ARG_TYPES (funtype) == NULL_TREE
-           || (TREE_VALUE (tree_last (TYPE_ARG_TYPES (funtype)))
-               == void_type_node)))
-      return size;
-  }
+  if (! lookup_attribute ("cdecl", TYPE_ATTRIBUTES (funtype)))
+    {
+      /* Stdcall and fastcall functions will pop the stack if not
+         variable args.  */
+      if (lookup_attribute ("stdcall", TYPE_ATTRIBUTES (funtype))
+          || lookup_attribute ("fastcall", TYPE_ATTRIBUTES (funtype)))
+       rtd = 1;
+
+      if (rtd && ! type_has_variadic_args_p (funtype))
+       return size;
+    }
 
   /* Lose any fake structure return argument if it is passed on the stack.  */
   if (aggregate_value_p (TREE_TYPE (funtype), fundecl)
-      && !TARGET_64BIT
       && !KEEP_AGGREGATE_RETURN_POINTER)
     {
       int nregs = ix86_function_regparm (funtype, fundecl);
-
-      if (!nregs)
+      if (nregs == 0)
        return GET_MODE_SIZE (Pmode);
     }
 
@@ -3180,6 +3188,7 @@ bool
 ix86_function_arg_regno_p (int regno)
 {
   int i;
+
   if (!TARGET_64BIT)
     {
       if (TARGET_MACHO)
@@ -3204,9 +3213,11 @@ ix86_function_arg_regno_p (int regno)
           && (regno < FIRST_SSE_REG + SSE_REGPARM_MAX))
         return true;
     }
+
   /* RAX is used as hidden argument to va_arg functions.  */
-  if (!regno)
+  if (regno == 0)
     return true;
+
   for (i = 0; i < REGPARM_MAX; i++)
     if (regno == x86_64_int_parameter_registers[i])
       return true;
@@ -3238,24 +3249,7 @@ init_cumulative_args (CUMULATIVE_ARGS *cum,  /* Argument info to initialize */
                      rtx libname,      /* SYMBOL_REF of library name or 0 */
                      tree fndecl)
 {
-  static CUMULATIVE_ARGS zero_cum;
-  tree param, next_param;
-
-  if (TARGET_DEBUG_ARG)
-    {
-      fprintf (stderr, "\ninit_cumulative_args (");
-      if (fntype)
-       fprintf (stderr, "fntype code = %s, ret code = %s",
-                tree_code_name[(int) TREE_CODE (fntype)],
-                tree_code_name[(int) TREE_CODE (TREE_TYPE (fntype))]);
-      else
-       fprintf (stderr, "no fntype");
-
-      if (libname)
-       fprintf (stderr, ", libname = %s", XSTR (libname, 0));
-    }
-
-  *cum = zero_cum;
+  memset (cum, 0, sizeof (*cum));
 
   /* Set up the number of registers to use for passing arguments.  */
   cum->nregs = ix86_regparm;
@@ -3265,60 +3259,39 @@ init_cumulative_args (CUMULATIVE_ARGS *cum,  /* Argument info to initialize */
     cum->mmx_nregs = MMX_REGPARM_MAX;
   cum->warn_sse = true;
   cum->warn_mmx = true;
-  cum->maybe_vaarg = false;
+  cum->maybe_vaarg = (fntype ? type_has_variadic_args_p (fntype) : !libname);
 
-  /* Use ecx and edx registers if function has fastcall attribute,
-     else look for regparm information.  */
-  if (fntype && !TARGET_64BIT)
+  if (!TARGET_64BIT)
     {
-      if (lookup_attribute ("fastcall", TYPE_ATTRIBUTES (fntype)))
+      /* If there are variable arguments, then we won't pass anything
+         in registers in 32-bit mode. */
+      if (cum->maybe_vaarg)
        {
-         cum->nregs = 2;
-         cum->fastcall = 1;
+         cum->nregs = 0;
+         cum->sse_nregs = 0;
+         cum->mmx_nregs = 0;
+         cum->warn_sse = 0;
+         cum->warn_mmx = 0;
+         return;
        }
-      else
-       cum->nregs = ix86_function_regparm (fntype, fndecl);
-    }
 
-  /* Set up the number of SSE registers used for passing SFmode
-     and DFmode arguments.  Warn for mismatching ABI.  */
-  cum->float_in_sse = ix86_function_sseregparm (fntype, fndecl);
-
-  /* Determine if this function has variable arguments.  This is
-     indicated by the last argument being 'void_type_mode' if there
-     are no variable arguments.  If there are variable arguments, then
-     we won't pass anything in registers in 32-bit mode. */
-
-  if (cum->nregs || cum->mmx_nregs || cum->sse_nregs)
-    {
-      for (param = (fntype) ? TYPE_ARG_TYPES (fntype) : 0;
-          param != 0; param = next_param)
+      /* Use ecx and edx registers if function has fastcall attribute,
+        else look for regparm information.  */
+      if (fntype)
        {
-         next_param = TREE_CHAIN (param);
-         if (next_param == 0 && TREE_VALUE (param) != void_type_node)
+         if (lookup_attribute ("fastcall", TYPE_ATTRIBUTES (fntype)))
            {
-             if (!TARGET_64BIT)
-               {
-                 cum->nregs = 0;
-                 cum->sse_nregs = 0;
-                 cum->mmx_nregs = 0;
-                 cum->warn_sse = 0;
-                 cum->warn_mmx = 0;
-                 cum->fastcall = 0;
-                 cum->float_in_sse = 0;
-               }
-             cum->maybe_vaarg = true;
+             cum->nregs = 2;
+             cum->fastcall = 1;
            }
+         else
+           cum->nregs = ix86_function_regparm (fntype, fndecl);
        }
-    }
-  if ((!fntype && !libname)
-      || (fntype && !TYPE_ARG_TYPES (fntype)))
-    cum->maybe_vaarg = true;
-
-  if (TARGET_DEBUG_ARG)
-    fprintf (stderr, ", nregs=%d )\n", cum->nregs);
 
-  return;
+      /* Set up the number of SSE registers used for passing SFmode
+        and DFmode arguments.  Warn for mismatching ABI.  */
+      cum->float_in_sse = ix86_function_sseregparm (fntype, fndecl);
+    }
 }
 
 /* Return the "natural" mode for TYPE.  In most cases, this is just TYPE_MODE.
@@ -3781,20 +3754,6 @@ construct_container (enum machine_mode mode, enum machine_mode orig_mode,
   rtx ret;
 
   n = classify_argument (mode, type, class, 0);
-  if (TARGET_DEBUG_ARG)
-    {
-      if (!n)
-       fprintf (stderr, "Memory class\n");
-      else
-       {
-         fprintf (stderr, "Classes:");
-         for (i = 0; i < n; i++)
-           {
-             fprintf (stderr, " %s", x86_64_reg_class_name[class[i]]);
-           }
-          fprintf (stderr, "\n");
-       }
-    }
   if (!n)
     return NULL;
   if (!examine_argument (mode, type, in_return, &needed_intregs,
@@ -3863,6 +3822,7 @@ construct_container (enum machine_mode mode, enum machine_mode orig_mode,
   if (n == 2 && class[0] == X86_64_SSE_CLASS && class[1] == X86_64_SSEUP_CLASS
       && mode != BLKmode)
     return gen_rtx_REG (mode, SSE_REGNO (sse_regno));
+
   if (n == 2
       && class[0] == X86_64_X87_CLASS && class[1] == X86_64_X87UP_CLASS)
     return gen_rtx_REG (XFmode, FIRST_STACK_REG);
@@ -3938,115 +3898,124 @@ construct_container (enum machine_mode mode, enum machine_mode orig_mode,
   return ret;
 }
 
-/* Update the data in CUM to advance over an argument
-   of mode MODE and data type TYPE.
-   (TYPE is null for libcalls where that information may not be available.)  */
+/* Update the data in CUM to advance over an argument of mode MODE
+   and data type TYPE.  (TYPE is null for libcalls where that information
+   may not be available.)  */
 
-void
-function_arg_advance (CUMULATIVE_ARGS *cum, enum machine_mode mode,
-                     tree type, int named)
+static void
+function_arg_advance_32 (CUMULATIVE_ARGS *cum, enum machine_mode mode,
+                        tree type, HOST_WIDE_INT bytes, HOST_WIDE_INT words)
 {
-  int bytes =
-    (mode == BLKmode) ? int_size_in_bytes (type) : (int) GET_MODE_SIZE (mode);
-  int words = (bytes + UNITS_PER_WORD - 1) / UNITS_PER_WORD;
+  switch (mode)
+    {
+    default:
+      break;
 
-  if (type)
-    mode = type_natural_mode (type);
+    case BLKmode:
+      if (bytes < 0)
+       break;
+      /* FALLTHRU */
 
-  if (TARGET_DEBUG_ARG)
-    fprintf (stderr, "function_adv (sz=%d, wds=%2d, nregs=%d, ssenregs=%d, "
-            "mode=%s, named=%d)\n\n",
-            words, cum->words, cum->nregs, cum->sse_nregs,
-            GET_MODE_NAME (mode), named);
+    case DImode:
+    case SImode:
+    case HImode:
+    case QImode:
+      cum->words += words;
+      cum->nregs -= words;
+      cum->regno += words;
 
-  if (TARGET_64BIT)
-    {
-      int int_nregs, sse_nregs;
-      if (!examine_argument (mode, type, 0, &int_nregs, &sse_nregs))
-       cum->words += words;
-      else if (sse_nregs <= cum->sse_nregs && int_nregs <= cum->nregs)
+      if (cum->nregs <= 0)
        {
-         cum->nregs -= int_nregs;
-         cum->sse_nregs -= sse_nregs;
-         cum->regno += int_nregs;
-         cum->sse_regno += sse_nregs;
+         cum->nregs = 0;
+         cum->regno = 0;
        }
-      else
-       cum->words += words;
-    }
-  else
-    {
-      switch (mode)
-       {
-       default:
-         break;
-
-       case BLKmode:
-         if (bytes < 0)
-           break;
-         /* FALLTHRU */
-
-       case DImode:
-       case SImode:
-       case HImode:
-       case QImode:
-         cum->words += words;
-         cum->nregs -= words;
-         cum->regno += words;
-
-         if (cum->nregs <= 0)
-           {
-             cum->nregs = 0;
-             cum->regno = 0;
-           }
-         break;
+      break;
 
-       case DFmode:
-         if (cum->float_in_sse < 2)
-           break;
-       case SFmode:
-         if (cum->float_in_sse < 1)
-           break;
-         /* FALLTHRU */
+    case DFmode:
+      if (cum->float_in_sse < 2)
+       break;
+    case SFmode:
+      if (cum->float_in_sse < 1)
+       break;
+      /* FALLTHRU */
 
-       case TImode:
-       case V16QImode:
-       case V8HImode:
-       case V4SImode:
-       case V2DImode:
-       case V4SFmode:
-       case V2DFmode:
-         if (!type || !AGGREGATE_TYPE_P (type))
+    case TImode:
+    case V16QImode:
+    case V8HImode:
+    case V4SImode:
+    case V2DImode:
+    case V4SFmode:
+    case V2DFmode:
+      if (!type || !AGGREGATE_TYPE_P (type))
+       {
+         cum->sse_words += words;
+         cum->sse_nregs -= 1;
+         cum->sse_regno += 1;
+         if (cum->sse_nregs <= 0)
            {
-             cum->sse_words += words;
-             cum->sse_nregs -= 1;
-             cum->sse_regno += 1;
-             if (cum->sse_nregs <= 0)
-               {
-                 cum->sse_nregs = 0;
-                 cum->sse_regno = 0;
-               }
+             cum->sse_nregs = 0;
+             cum->sse_regno = 0;
            }
-         break;
+       }
+      break;
 
-       case V8QImode:
-       case V4HImode:
-       case V2SImode:
-       case V2SFmode:
-         if (!type || !AGGREGATE_TYPE_P (type))
+    case V8QImode:
+    case V4HImode:
+    case V2SImode:
+    case V2SFmode:
+      if (!type || !AGGREGATE_TYPE_P (type))
+       {
+         cum->mmx_words += words;
+         cum->mmx_nregs -= 1;
+         cum->mmx_regno += 1;
+         if (cum->mmx_nregs <= 0)
            {
-             cum->mmx_words += words;
-             cum->mmx_nregs -= 1;
-             cum->mmx_regno += 1;
-             if (cum->mmx_nregs <= 0)
-               {
-                 cum->mmx_nregs = 0;
-                 cum->mmx_regno = 0;
-               }
+             cum->mmx_nregs = 0;
+             cum->mmx_regno = 0;
            }
-         break;
        }
+      break;
+    }
+}
+
+static void
+function_arg_advance_64 (CUMULATIVE_ARGS *cum, enum machine_mode mode,
+                        tree type, HOST_WIDE_INT words)
+{
+  int int_nregs, sse_nregs;
+
+  if (!examine_argument (mode, type, 0, &int_nregs, &sse_nregs))
+    cum->words += words;
+  else if (sse_nregs <= cum->sse_nregs && int_nregs <= cum->nregs)
+    {
+      cum->nregs -= int_nregs;
+      cum->sse_nregs -= sse_nregs;
+      cum->regno += int_nregs;
+      cum->sse_regno += sse_nregs;
     }
+  else
+    cum->words += words;
+}
+
+void
+function_arg_advance (CUMULATIVE_ARGS *cum, enum machine_mode mode,
+                     tree type, int named ATTRIBUTE_UNUSED)
+{
+  HOST_WIDE_INT bytes, words;
+
+  if (mode == BLKmode)
+    bytes = int_size_in_bytes (type);
+  else
+    bytes = GET_MODE_SIZE (mode);
+  words = (bytes + UNITS_PER_WORD - 1) / UNITS_PER_WORD;
+
+  if (type)
+    mode = type_natural_mode (type);
+
+  if (TARGET_64BIT)
+    function_arg_advance_64 (cum, mode, type, words);
+  else
+    function_arg_advance_32 (cum, mode, type, bytes, words);
 }
 
 /* Define where to put the arguments to a function.
@@ -4062,135 +4031,140 @@ function_arg_advance (CUMULATIVE_ARGS *cum, enum machine_mode mode,
    NAMED is nonzero if this argument is a named parameter
     (otherwise it is an extra parameter matching an ellipsis).  */
 
-rtx
-function_arg (CUMULATIVE_ARGS *cum, enum machine_mode orig_mode,
-             tree type, int named)
+static rtx
+function_arg_32 (CUMULATIVE_ARGS *cum, enum machine_mode mode,
+                enum machine_mode orig_mode, tree type,
+                HOST_WIDE_INT bytes, HOST_WIDE_INT words)
 {
-  enum machine_mode mode = orig_mode;
-  rtx ret = NULL_RTX;
-  int bytes =
-    (mode == BLKmode) ? int_size_in_bytes (type) : (int) GET_MODE_SIZE (mode);
-  int words = (bytes + UNITS_PER_WORD - 1) / UNITS_PER_WORD;
   static bool warnedsse, warnedmmx;
 
-  /* To simplify the code below, represent vector types with a vector mode
-     even if MMX/SSE are not active.  */
-  if (type && TREE_CODE (type) == VECTOR_TYPE)
-    mode = type_natural_mode (type);
-
-  /* Handle a hidden AL argument containing number of registers for varargs
-     x86-64 functions.  For i386 ABI just return constm1_rtx to avoid
-     any AL settings.  */
+  /* Avoid the AL settings for the Unix64 ABI.  */
   if (mode == VOIDmode)
+    return constm1_rtx;
+
+  switch (mode)
     {
-      if (TARGET_64BIT)
-       return GEN_INT (cum->maybe_vaarg
-                       ? (cum->sse_nregs < 0
-                          ? SSE_REGPARM_MAX
-                          : cum->sse_regno)
-                       : -1);
-      else
-       return constm1_rtx;
-    }
-  if (TARGET_64BIT)
-    ret = construct_container (mode, orig_mode, type, 0, cum->nregs,
-                              cum->sse_nregs,
-                              &x86_64_int_parameter_registers [cum->regno],
-                              cum->sse_regno);
-  else
-    switch (mode)
-      {
-       /* For now, pass fp/complex values on the stack.  */
-      default:
+    default:
+      break;
+
+    case BLKmode:
+      if (bytes < 0)
        break;
+      /* FALLTHRU */
+    case DImode:
+    case SImode:
+    case HImode:
+    case QImode:
+      if (words <= cum->nregs)
+       {
+         int regno = cum->regno;
 
-      case BLKmode:
-       if (bytes < 0)
-         break;
-       /* FALLTHRU */
-      case DImode:
-      case SImode:
-      case HImode:
-      case QImode:
-       if (words <= cum->nregs)
-         {
-           int regno = cum->regno;
+         /* Fastcall allocates the first two DWORD (SImode) or
+            smaller arguments to ECX and EDX.  */
+         if (cum->fastcall)
+           {
+             if (mode == BLKmode || mode == DImode)
+               break;
 
-           /* Fastcall allocates the first two DWORD (SImode) or
-              smaller arguments to ECX and EDX.  */
-           if (cum->fastcall)
-             {
-               if (mode == BLKmode || mode == DImode)
-                 break;
+             /* ECX not EAX is the first allocated register.  */
+             if (regno == 0)
+               regno = 2;
+           }
+         return gen_rtx_REG (mode, regno);
+       }
+      break;
 
-               /* ECX not EAX is the first allocated register.  */
-               if (regno == 0)
-                 regno = 2;
-             }
-           ret = gen_rtx_REG (mode, regno);
-         }
-       break;
-      case DFmode:
-       if (cum->float_in_sse < 2)
-         break;
-      case SFmode:
-       if (cum->float_in_sse < 1)
-         break;
-       /* FALLTHRU */
-      case TImode:
-      case V16QImode:
-      case V8HImode:
-      case V4SImode:
-      case V2DImode:
-      case V4SFmode:
-      case V2DFmode:
-       if (!type || !AGGREGATE_TYPE_P (type))
-         {
-           if (!TARGET_SSE && !warnedsse && cum->warn_sse)
-             {
-               warnedsse = true;
-               warning (0, "SSE vector argument without SSE enabled "
-                        "changes the ABI");
-             }
-           if (cum->sse_nregs)
-             ret = gen_reg_or_parallel (mode, orig_mode,
-                                        cum->sse_regno + FIRST_SSE_REG);
-         }
+    case DFmode:
+      if (cum->float_in_sse < 2)
        break;
-      case V8QImode:
-      case V4HImode:
-      case V2SImode:
-      case V2SFmode:
-       if (!type || !AGGREGATE_TYPE_P (type))
-         {
-           if (!TARGET_MMX && !warnedmmx && cum->warn_mmx)
-             {
-               warnedmmx = true;
-               warning (0, "MMX vector argument without MMX enabled "
-                        "changes the ABI");
-             }
-           if (cum->mmx_nregs)
-             ret = gen_reg_or_parallel (mode, orig_mode,
-                                        cum->mmx_regno + FIRST_MMX_REG);
-         }
+    case SFmode:
+      if (cum->float_in_sse < 1)
        break;
-      }
+      /* FALLTHRU */
+    case TImode:
+    case V16QImode:
+    case V8HImode:
+    case V4SImode:
+    case V2DImode:
+    case V4SFmode:
+    case V2DFmode:
+      if (!type || !AGGREGATE_TYPE_P (type))
+       {
+         if (!TARGET_SSE && !warnedsse && cum->warn_sse)
+           {
+             warnedsse = true;
+             warning (0, "SSE vector argument without SSE enabled "
+                      "changes the ABI");
+           }
+         if (cum->sse_nregs)
+           return gen_reg_or_parallel (mode, orig_mode,
+                                       cum->sse_regno + FIRST_SSE_REG);
+       }
+      break;
 
-  if (TARGET_DEBUG_ARG)
-    {
-      fprintf (stderr,
-              "function_arg (size=%d, wds=%2d, nregs=%d, mode=%4s, named=%d, ",
-              words, cum->words, cum->nregs, GET_MODE_NAME (mode), named);
+    case V8QImode:
+    case V4HImode:
+    case V2SImode:
+    case V2SFmode:
+      if (!type || !AGGREGATE_TYPE_P (type))
+       {
+         if (!TARGET_MMX && !warnedmmx && cum->warn_mmx)
+           {
+             warnedmmx = true;
+             warning (0, "MMX vector argument without MMX enabled "
+                      "changes the ABI");
+           }
+         if (cum->mmx_nregs)
+           return gen_reg_or_parallel (mode, orig_mode,
+                                       cum->mmx_regno + FIRST_MMX_REG);
+       }
+      break;
+    }
 
-      if (ret)
-       print_simple_rtl (stderr, ret);
-      else
-       fprintf (stderr, ", stack");
+  return NULL_RTX;
+}
 
-      fprintf (stderr, " )\n");
-    }
+static rtx
+function_arg_64 (CUMULATIVE_ARGS *cum, enum machine_mode mode,
+                enum machine_mode orig_mode, tree type)
+{
+  /* Handle a hidden AL argument containing number of registers
+     for varargs x86-64 functions.  */
+  if (mode == VOIDmode)
+    return GEN_INT (cum->maybe_vaarg
+                   ? (cum->sse_nregs < 0
+                      ? SSE_REGPARM_MAX
+                      : cum->sse_regno)
+                   : -1);
 
-  return ret;
+  return construct_container (mode, orig_mode, type, 0, cum->nregs,
+                             cum->sse_nregs,
+                             &x86_64_int_parameter_registers [cum->regno],
+                             cum->sse_regno);
+}
+
+rtx
+function_arg (CUMULATIVE_ARGS *cum, enum machine_mode omode,
+             tree type, int named ATTRIBUTE_UNUSED)
+{
+  enum machine_mode mode = omode;
+  HOST_WIDE_INT bytes, words;
+
+  if (mode == BLKmode)
+    bytes = int_size_in_bytes (type);
+  else
+    bytes = GET_MODE_SIZE (mode);
+  words = (bytes + UNITS_PER_WORD - 1) / UNITS_PER_WORD;
+
+  /* To simplify the code below, represent vector types with a vector mode
+     even if MMX/SSE are not active.  */
+  if (type && TREE_CODE (type) == VECTOR_TYPE)
+    mode = type_natural_mode (type);
+
+  if (TARGET_64BIT)
+    return function_arg_64 (cum, mode, omode, type);
+  else
+    return function_arg_32 (cum, mode, omode, type, bytes, words);
 }
 
 /* A C expression that indicates when an argument must be passed by
@@ -4204,15 +4178,8 @@ ix86_pass_by_reference (CUMULATIVE_ARGS *cum ATTRIBUTE_UNUSED,
                        enum machine_mode mode ATTRIBUTE_UNUSED,
                        tree type, bool named ATTRIBUTE_UNUSED)
 {
-  if (!TARGET_64BIT)
-    return 0;
-
-  if (type && int_size_in_bytes (type) == -1)
-    {
-      if (TARGET_DEBUG_ARG)
-       fprintf (stderr, "function_arg_pass_by_reference\n");
-      return 1;
-    }
+  if (TARGET_64BIT && type && int_size_in_bytes (type) == -1)
+    return 1;
 
   return 0;
 }
@@ -4304,78 +4271,162 @@ ix86_function_arg_boundary (enum machine_mode mode, tree type)
 }
 
 /* Return true if N is a possible register number of function value.  */
+
 bool
 ix86_function_value_regno_p (int regno)
 {
-  if (TARGET_MACHO)
-    {
-      if (!TARGET_64BIT)
-        {
-          return ((regno) == 0
-                  || ((regno) == FIRST_FLOAT_REG && TARGET_FLOAT_RETURNS_IN_80387)
-                  || ((regno) == FIRST_SSE_REG && TARGET_SSE));
-        }
-      return ((regno) == 0 || (regno) == FIRST_FLOAT_REG
-              || ((regno) == FIRST_SSE_REG && TARGET_SSE)
-              || ((regno) == FIRST_FLOAT_REG && TARGET_FLOAT_RETURNS_IN_80387));
-      }
-  else
+  switch (regno)
     {
-      if (regno == 0
-          || (regno == FIRST_FLOAT_REG && TARGET_FLOAT_RETURNS_IN_80387)
-          || (regno == FIRST_SSE_REG && TARGET_SSE))
-        return true;
+    case 0:
+      return true;
 
-      if (!TARGET_64BIT
-          && (regno == FIRST_MMX_REG && TARGET_MMX))
-           return true;
+    case FIRST_FLOAT_REG:
+      return TARGET_FLOAT_RETURNS_IN_80387;
 
-      return false;
+    case FIRST_SSE_REG:
+      return TARGET_SSE;
+
+    case FIRST_MMX_REG:
+      if (TARGET_MACHO || TARGET_64BIT)
+       return false;
+      return TARGET_MMX;
     }
+
+  return false;
 }
 
 /* Define how to find the value returned by a function.
    VALTYPE is the data type of the value (as a tree).
    If the precise function being called is known, FUNC is its FUNCTION_DECL;
    otherwise, FUNC is 0.  */
-rtx
-ix86_function_value (tree valtype, tree fntype_or_decl,
-                    bool outgoing ATTRIBUTE_UNUSED)
+
+static rtx
+function_value_32 (enum machine_mode orig_mode, enum machine_mode mode,
+                  tree fntype, tree fn)
 {
-  enum machine_mode natmode = type_natural_mode (valtype);
+  unsigned int regno;
 
-  if (TARGET_64BIT)
+  /* 8-byte vector modes in %mm0. See ix86_return_in_memory for where
+     we normally prevent this case when mmx is not available.  However
+     some ABIs may require the result to be returned like DImode.  */
+  if (VECTOR_MODE_P (mode) && GET_MODE_SIZE (mode) == 8)
+    regno = TARGET_MMX ? FIRST_MMX_REG : 0;
+
+  /* 16-byte vector modes in %xmm0.  See ix86_return_in_memory for where
+     we prevent this case when sse is not available.  However some ABIs
+     may require the result to be returned like integer TImode.  */
+  else if (mode == TImode
+          || (VECTOR_MODE_P (mode) && GET_MODE_SIZE (mode) == 16))
+    regno = TARGET_SSE ? FIRST_SSE_REG : 0;
+
+  /* Decimal floating point values can go in %eax, unlike other float modes.  */
+  else if (DECIMAL_FLOAT_MODE_P (mode))
+    regno = 0;
+
+  /* Most things go in %eax, except (unless -mno-fp-ret-in-387) fp values.  */
+  else if (!SCALAR_FLOAT_MODE_P (mode) || !TARGET_FLOAT_RETURNS_IN_80387)
+    regno = 0;
+
+  /* Floating point return values in %st(0), except for local functions when
+     SSE math is enabled or for functions with sseregparm attribute.  */
+  else
     {
-      rtx ret = construct_container (natmode, TYPE_MODE (valtype), valtype,
-                                    1, REGPARM_MAX, SSE_REGPARM_MAX,
-                                    x86_64_int_return_registers, 0);
-      /* For zero sized structures, construct_container return NULL, but we
-        need to keep rest of compiler happy by returning meaningful value.  */
-      if (!ret)
-       ret = gen_rtx_REG (TYPE_MODE (valtype), 0);
-      return ret;
+      regno = FIRST_FLOAT_REG;
+
+      if ((fn || fntype) && (mode == SFmode || mode == DFmode))
+       {
+         int sse_level = ix86_function_sseregparm (fntype, fn);
+         if ((sse_level >= 1 && mode == SFmode)
+             || (sse_level == 2 && mode == DFmode))
+           regno = FIRST_SSE_REG;
+       }
     }
-  else
+
+  return gen_rtx_REG (orig_mode, regno);
+}
+
+static rtx
+function_value_64 (enum machine_mode orig_mode, enum machine_mode mode,
+                  tree valtype)
+{
+  rtx ret;
+
+  /* Handle libcalls, which don't provide a type node.  */
+  if (valtype == NULL)
     {
-      tree fn = NULL_TREE, fntype;
-      if (fntype_or_decl
-         && DECL_P (fntype_or_decl))
-        fn = fntype_or_decl;
-      fntype = fn ? TREE_TYPE (fn) : fntype_or_decl;
-      return gen_rtx_REG (TYPE_MODE (valtype),
-                         ix86_value_regno (natmode, fn, fntype));
+      switch (mode)
+       {
+       case SFmode:
+       case SCmode:
+       case DFmode:
+       case DCmode:
+       case TFmode:
+       case SDmode:
+       case DDmode:
+       case TDmode:
+         return gen_rtx_REG (mode, FIRST_SSE_REG);
+       case XFmode:
+       case XCmode:
+         return gen_rtx_REG (mode, FIRST_FLOAT_REG);
+       case TCmode:
+         return NULL;
+       default:
+         return gen_rtx_REG (mode, 0);
+       }
     }
+
+  ret = construct_container (mode, orig_mode, valtype, 1,
+                            REGPARM_MAX, SSE_REGPARM_MAX,
+                            x86_64_int_return_registers, 0);
+
+  /* For zero sized structures, construct_container returns NULL, but we
+     need to keep rest of compiler happy by returning meaningful value.  */
+  if (!ret)
+    ret = gen_rtx_REG (orig_mode, 0);
+
+  return ret;
 }
 
-/* Return true iff type is returned in memory.  */
-int
-ix86_return_in_memory (tree type)
+static rtx
+ix86_function_value_1 (tree valtype, tree fntype_or_decl,
+                      enum machine_mode orig_mode, enum machine_mode mode)
 {
-  int needed_intregs, needed_sseregs, size;
-  enum machine_mode mode = type_natural_mode (type);
+  tree fn, fntype;
+
+  fn = NULL_TREE;
+  if (fntype_or_decl && DECL_P (fntype_or_decl))
+    fn = fntype_or_decl;
+  fntype = fn ? TREE_TYPE (fn) : fntype_or_decl;
 
   if (TARGET_64BIT)
-    return !examine_argument (mode, type, 1, &needed_intregs, &needed_sseregs);
+    return function_value_64 (orig_mode, mode, valtype);
+  else
+    return function_value_32 (orig_mode, mode, fntype, fn);
+}
+
+static rtx
+ix86_function_value (tree valtype, tree fntype_or_decl,
+                    bool outgoing ATTRIBUTE_UNUSED)
+{
+  enum machine_mode mode, orig_mode;
+
+  orig_mode = TYPE_MODE (valtype);
+  mode = type_natural_mode (valtype);
+  return ix86_function_value_1 (valtype, fntype_or_decl, orig_mode, mode);
+}
+
+rtx
+ix86_libcall_value (enum machine_mode mode)
+{
+  return ix86_function_value_1 (NULL, NULL, mode, mode);
+}
+
+/* Return true iff type is returned in memory.  */
+
+static int
+return_in_memory_32 (tree type, enum machine_mode mode)
+{
+  HOST_WIDE_INT size;
 
   if (mode == BLKmode)
     return 1;
@@ -4412,6 +4463,24 @@ ix86_return_in_memory (tree type)
   return 0;
 }
 
+static int
+return_in_memory_64 (tree type, enum machine_mode mode)
+{
+  int needed_intregs, needed_sseregs;
+  return !examine_argument (mode, type, 1, &needed_intregs, &needed_sseregs);
+}
+
+int
+ix86_return_in_memory (tree type)
+{
+  enum machine_mode mode = type_natural_mode (type);
+
+  if (TARGET_64BIT)
+    return return_in_memory_64 (type, mode);
+  else
+    return return_in_memory_32 (type, mode);
+}
+
 /* When returning SSE vector types, we have a choice of either
      (1) being abi incompatible with a -march switch, or
      (2) generating an error.
@@ -4428,7 +4497,7 @@ ix86_struct_value_rtx (tree type, int incoming ATTRIBUTE_UNUSED)
 {
   static bool warnedsse, warnedmmx;
 
-  if (type)
+  if (!TARGET_64BIT && type)
     {
       /* Look at the return type of the function, not the function type.  */
       enum machine_mode mode = TYPE_MODE (TREE_TYPE (type));
@@ -4458,77 +4527,6 @@ ix86_struct_value_rtx (tree type, int incoming ATTRIBUTE_UNUSED)
   return NULL;
 }
 
-/* Define how to find the value returned by a library function
-   assuming the value has mode MODE.  */
-rtx
-ix86_libcall_value (enum machine_mode mode)
-{
-  if (TARGET_64BIT)
-    {
-      switch (mode)
-       {
-       case SFmode:
-       case SCmode:
-       case DFmode:
-       case DCmode:
-       case TFmode:
-       case SDmode:
-       case DDmode:
-       case TDmode:
-         return gen_rtx_REG (mode, FIRST_SSE_REG);
-       case XFmode:
-       case XCmode:
-         return gen_rtx_REG (mode, FIRST_FLOAT_REG);
-       case TCmode:
-         return NULL;
-       default:
-         return gen_rtx_REG (mode, 0);
-       }
-    }
-  else
-    return gen_rtx_REG (mode, ix86_value_regno (mode, NULL, NULL));
-}
-
-/* Given a mode, return the register to use for a return value.  */
-
-static int
-ix86_value_regno (enum machine_mode mode, tree func, tree fntype)
-{
-  gcc_assert (!TARGET_64BIT);
-
-  /* 8-byte vector modes in %mm0. See ix86_return_in_memory for where
-     we normally prevent this case when mmx is not available.  However
-     some ABIs may require the result to be returned like DImode.  */
-  if (VECTOR_MODE_P (mode) && GET_MODE_SIZE (mode) == 8)
-    return TARGET_MMX ? FIRST_MMX_REG : 0;
-
-  /* 16-byte vector modes in %xmm0.  See ix86_return_in_memory for where
-     we prevent this case when sse is not available.  However some ABIs
-     may require the result to be returned like integer TImode.  */
-  if (mode == TImode || (VECTOR_MODE_P (mode) && GET_MODE_SIZE (mode) == 16))
-    return TARGET_SSE ? FIRST_SSE_REG : 0;
-
-  /* Decimal floating point values can go in %eax, unlike other float modes.  */
-  if (DECIMAL_FLOAT_MODE_P (mode))
-    return 0;
-
-  /* Most things go in %eax, except (unless -mno-fp-ret-in-387) fp values.  */
-  if (!SCALAR_FLOAT_MODE_P (mode) || !TARGET_FLOAT_RETURNS_IN_80387)
-    return 0;
-
-  /* Floating point return values in %st(0), except for local functions when
-     SSE math is enabled or for functions with sseregparm attribute.  */
-  if ((func || fntype)
-      && (mode == SFmode || mode == DFmode))
-    {
-      int sse_level = ix86_function_sseregparm (fntype, func);
-      if ((sse_level >= 1 && mode == SFmode)
-         || (sse_level == 2 && mode == DFmode))
-        return FIRST_SSE_REG;
-    }
-
-  return FIRST_FLOAT_REG;
-}
 \f
 /* Create the va_list data type.  */
 
@@ -4577,51 +4575,29 @@ ix86_build_builtin_va_list (void)
 /* Worker function for TARGET_SETUP_INCOMING_VARARGS.  */
 
 static void
-ix86_setup_incoming_varargs (CUMULATIVE_ARGS *cum, enum machine_mode mode,
-                            tree type, int *pretend_size ATTRIBUTE_UNUSED,
-                            int no_rtl)
+setup_incoming_varargs_64 (CUMULATIVE_ARGS *cum)
 {
-  CUMULATIVE_ARGS next_cum;
-  rtx save_area = NULL_RTX, mem;
+  rtx save_area, mem;
   rtx label;
   rtx label_ref;
   rtx tmp_reg;
   rtx nsse_reg;
   int set;
-  tree fntype;
-  int stdarg_p;
   int i;
 
-  if (!TARGET_64BIT)
-    return;
-
   if (! cfun->va_list_gpr_size && ! cfun->va_list_fpr_size)
     return;
 
   /* Indicate to allocate space on the stack for varargs save area.  */
   ix86_save_varrargs_registers = 1;
-
   cfun->stack_alignment_needed = 128;
 
-  fntype = TREE_TYPE (current_function_decl);
-  stdarg_p = (TYPE_ARG_TYPES (fntype) != 0
-             && (TREE_VALUE (tree_last (TYPE_ARG_TYPES (fntype)))
-                 != void_type_node));
-
-  /* For varargs, we do not want to skip the dummy va_dcl argument.
-     For stdargs, we do want to skip the last named argument.  */
-  next_cum = *cum;
-  if (stdarg_p)
-    function_arg_advance (&next_cum, mode, type, 1);
-
-  if (!no_rtl)
-    save_area = frame_pointer_rtx;
-
+  save_area = frame_pointer_rtx;
   set = get_varargs_alias_set ();
 
-  for (i = next_cum.regno;
+  for (i = cum->regno;
        i < ix86_regparm
-       && i < next_cum.regno + cfun->va_list_gpr_size / UNITS_PER_WORD;
+       && i < cum->regno + cfun->va_list_gpr_size / UNITS_PER_WORD;
        i++)
     {
       mem = gen_rtx_MEM (Pmode,
@@ -4632,7 +4608,7 @@ ix86_setup_incoming_varargs (CUMULATIVE_ARGS *cum, enum machine_mode mode,
                                        x86_64_int_parameter_registers[i]));
     }
 
-  if (next_cum.sse_nregs && cfun->va_list_fpr_size)
+  if (cum->sse_nregs && cfun->va_list_fpr_size)
     {
       /* Now emit code to save SSE registers.  The AX parameter contains number
         of SSE parameter registers used to call this function.  We use
@@ -4650,13 +4626,13 @@ ix86_setup_incoming_varargs (CUMULATIVE_ARGS *cum, enum machine_mode mode,
       emit_insn (gen_rtx_SET (VOIDmode, tmp_reg,
                              gen_rtx_MULT (Pmode, nsse_reg,
                                            GEN_INT (4))));
-      if (next_cum.sse_regno)
+      if (cum->sse_regno)
        emit_move_insn
          (nsse_reg,
           gen_rtx_CONST (DImode,
                          gen_rtx_PLUS (DImode,
                                        label_ref,
-                                       GEN_INT (next_cum.sse_regno * 4))));
+                                       GEN_INT (cum->sse_regno * 4))));
       else
        emit_move_insn (nsse_reg, label_ref);
       emit_insn (gen_subdi3 (nsse_reg, nsse_reg, tmp_reg));
@@ -4675,9 +4651,38 @@ ix86_setup_incoming_varargs (CUMULATIVE_ARGS *cum, enum machine_mode mode,
 
       /* And finally do the dirty job!  */
       emit_insn (gen_sse_prologue_save (mem, nsse_reg,
-                                       GEN_INT (next_cum.sse_regno), label));
+                                       GEN_INT (cum->sse_regno), label));
     }
+}
 
+static void
+ix86_setup_incoming_varargs (CUMULATIVE_ARGS *cum, enum machine_mode mode,
+                            tree type, int *pretend_size ATTRIBUTE_UNUSED,
+                            int no_rtl)
+{
+  CUMULATIVE_ARGS next_cum;
+  tree fntype;
+  int stdarg_p;
+
+  /* This argument doesn't appear to be used anymore.  Which is good,
+     because the old code here didn't suppress rtl generation.  */
+  gcc_assert (!no_rtl);
+
+  if (!TARGET_64BIT)
+    return;
+
+  fntype = TREE_TYPE (current_function_decl);
+  stdarg_p = (TYPE_ARG_TYPES (fntype) != 0
+             && (TREE_VALUE (tree_last (TYPE_ARG_TYPES (fntype)))
+                 != void_type_node));
+
+  /* For varargs, we do not want to skip the dummy va_dcl argument.
+     For stdargs, we do want to skip the last named argument.  */
+  next_cum = *cum;
+  if (stdarg_p)
+    function_arg_advance (&next_cum, mode, type, 1);
+
+  setup_incoming_varargs_64 (&next_cum);
 }
 
 /* Implement va_start.  */
@@ -4713,10 +4718,6 @@ ix86_va_start (tree valist, rtx nextarg)
   n_gpr = current_function_args_info.regno;
   n_fpr = current_function_args_info.sse_regno;
 
-  if (TARGET_DEBUG_ARG)
-    fprintf (stderr, "va_start: words = %d, n_gpr = %d, n_fpr = %d\n",
-            (int) words, (int) n_gpr, (int) n_fpr);
-
   if (cfun->va_list_gpr_size)
     {
       type = TREE_TYPE (gpr);
@@ -6851,7 +6852,8 @@ legitimate_pic_address_disp_p (rtx disp)
    be recognized.  */
 
 int
-legitimate_address_p (enum machine_mode mode, rtx addr, int strict)
+legitimate_address_p (enum machine_mode mode ATTRIBUTE_UNUSED,
+                     rtx addr, int strict)
 {
   struct ix86_address parts;
   rtx base, index, disp;
@@ -6859,14 +6861,6 @@ legitimate_address_p (enum machine_mode mode, rtx addr, int strict)
   const char *reason = NULL;
   rtx reason_rtx = NULL_RTX;
 
-  if (TARGET_DEBUG_ADDR)
-    {
-      fprintf (stderr,
-              "\n======\nGO_IF_LEGITIMATE_ADDRESS, mode = %s, strict = %d\n",
-              GET_MODE_NAME (mode), strict);
-      debug_rtx (addr);
-    }
-
   if (ix86_decompose_address (addr, &parts) <= 0)
     {
       reason = "decomposition failed";
@@ -7077,16 +7071,9 @@ legitimate_address_p (enum machine_mode mode, rtx addr, int strict)
     }
 
   /* Everything looks valid.  */
-  if (TARGET_DEBUG_ADDR)
-    fprintf (stderr, "Success.\n");
   return TRUE;
 
  report_error:
-  if (TARGET_DEBUG_ADDR)
-    {
-      fprintf (stderr, "Error: %s\n", reason);
-      debug_rtx (reason_rtx);
-    }
   return FALSE;
 }
 \f
@@ -7524,13 +7511,6 @@ legitimize_address (rtx x, rtx oldx ATTRIBUTE_UNUSED, enum machine_mode mode)
   int changed = 0;
   unsigned log;
 
-  if (TARGET_DEBUG_ADDR)
-    {
-      fprintf (stderr, "\n==========\nLEGITIMIZE_ADDRESS, mode = %s\n",
-              GET_MODE_NAME (mode));
-      debug_rtx (x);
-    }
-
   log = GET_CODE (x) == SYMBOL_REF ? SYMBOL_REF_TLS_MODEL (x) : 0;
   if (log)
     return legitimize_tls_address (x, log, false);
index d8955ae..7eafe4e 100644 (file)
@@ -95,12 +95,6 @@ mcmodel=
 Target RejectNegative Joined Var(ix86_cmodel_string)
 Use given x86-64 code model
 
-mdebug-addr
-Target RejectNegative Var(TARGET_DEBUG_ADDR) Undocumented
-
-mdebug-arg
-Target RejectNegative Var(TARGET_DEBUG_ARG) Undocumented
-
 mfancy-math-387
 Target RejectNegative Report InverseMask(NO_FANCY_MATH_387, USE_FANCY_MATH_387)
 Generate sin, cos, sqrt for FPU