Index: doc/tm.texi
===================================================================
--- doc/tm.texi	(revision 165928)
+++ doc/tm.texi	(working copy)
@@ -4606,6 +4606,14 @@ This macro has effect in @option{-fpcc-s
 nothing when you use @option{-freg-struct-return} mode.
 @end defmac
 
+@deftypefn {Target Hook} {enum machine_mode} TARGET_GET_RAW_RESULT_MODE (int @var{regno})
+This target hook returns the mode to be used when accessing raw return registers in @code{__builtin_return}.  Define this macro if the value in @var{reg_raw_mode} is not correct.
+@end deftypefn
+
+@deftypefn {Target Hook} {enum machine_mode} TARGET_GET_RAW_ARG_MODE (int @var{regno})
+This target hook returns the mode to be used when accessing raw argument registers in @code{__builtin_apply_args}.  Define this macro if the value in @var{reg_raw_mode} is not correct.
+@end deftypefn
+
 @node Caller Saves
 @subsection Caller-Saves Register Allocation
 
Index: doc/tm.texi.in
===================================================================
--- doc/tm.texi.in	(revision 165928)
+++ doc/tm.texi.in	(working copy)
@@ -4600,6 +4600,10 @@ This macro has effect in @option{-fpcc-s
 nothing when you use @option{-freg-struct-return} mode.
 @end defmac
 
+@hook TARGET_GET_RAW_RESULT_MODE
+
+@hook TARGET_GET_RAW_ARG_MODE
+
 @node Caller Saves
 @subsection Caller-Saves Register Allocation
 
Index: targhooks.c
===================================================================
--- targhooks.c	(revision 165928)
+++ targhooks.c	(working copy)
@@ -64,6 +64,7 @@ along with GCC; see the file COPYING3.  
 #include "target-def.h"
 #include "ggc.h"
 #include "hard-reg-set.h"
+#include "regs.h"
 #include "reload.h"
 #include "optabs.h"
 #include "recog.h"
@@ -1333,6 +1334,15 @@ sjlj_except_unwind_info (void)
   return UI_SJLJ;
 }
 
+/* To be used by targets where reg_raw_mode doesn't return the right
+   mode for registers used in apply_builtin_return and apply_builtin_arg.  */
+
+enum machine_mode
+default_get_reg_raw_mode(int regno)
+{
+  return reg_raw_mode[regno];
+}
+
 const struct default_options empty_optimization_table[] =
   {
     { OPT_LEVELS_NONE, 0, NULL, 0 }
Index: targhooks.h
===================================================================
--- targhooks.h	(revision 165928)
+++ targhooks.h	(working copy)
@@ -168,4 +168,6 @@ extern int default_loop_align_max_skip (
 extern int default_label_align_max_skip (rtx);
 extern int default_jump_align_max_skip (rtx);
 
+extern enum machine_mode default_get_reg_raw_mode(int);
+
 extern const struct default_options empty_optimization_table[];
Index: target.def
===================================================================
--- target.def	(revision 165928)
+++ target.def	(working copy)
@@ -1982,6 +1982,26 @@ DEFHOOK
  int, (tree fundecl, tree funtype, int size),
  default_return_pops_args)
 
+/* Return a mode wide enough to copy any function value that might be
+   returned.  */
+DEFHOOK
+(get_raw_result_mode,
+ "This target hook returns the mode to be used when accessing raw return\
+ registers in @code{__builtin_return}.  Define this macro if the value\
+ in @var{reg_raw_mode} is not correct.",
+ enum machine_mode, (int regno),
+ default_get_reg_raw_mode)
+
+/* Return a mode wide enough to copy any argument value that might be
+   passed.  */
+DEFHOOK
+(get_raw_arg_mode,
+ "This target hook returns the mode to be used when accessing raw argument\
+ registers in @code{__builtin_apply_args}.  Define this macro if the value\
+ in @var{reg_raw_mode} is not correct.",
+ enum machine_mode, (int regno),
+ default_get_reg_raw_mode)
+
 HOOK_VECTOR_END (calls)
 
 /* Return the diagnostic message string if conversion from FROMTYPE
Index: builtins.c
===================================================================
--- builtins.c	(revision 165928)
+++ builtins.c	(working copy)
@@ -1334,7 +1334,7 @@ apply_args_size (void)
       for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
 	if (FUNCTION_ARG_REGNO_P (regno))
 	  {
-	    mode = reg_raw_mode[regno];
+	    mode = targetm.calls.get_raw_arg_mode (regno);
 
 	    gcc_assert (mode != VOIDmode);
 
@@ -1370,7 +1370,7 @@ apply_result_size (void)
       for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
 	if (targetm.calls.function_value_regno_p (regno))
 	  {
-	    mode = reg_raw_mode[regno];
+	    mode = targetm.calls.get_raw_result_mode (regno);
 
 	    gcc_assert (mode != VOIDmode);
 
Index: config/ia64/ia64.c
===================================================================
--- config/ia64/ia64.c	(revision 165928)
+++ config/ia64/ia64.c	(working copy)
@@ -325,6 +325,7 @@ static void ia64_dwarf_handle_frame_unsp
 static tree ia64_builtin_decl (unsigned, bool);
 
 static reg_class_t ia64_preferred_reload_class (rtx, reg_class_t);
+static enum machine_mode ia64_get_reg_raw_mode (int regno);
 
 /* Table of valid machine attributes.  */
 static const struct attribute_spec ia64_attribute_table[] =
@@ -545,6 +546,10 @@ static const struct default_options ia64
 #define TARGET_STRICT_ARGUMENT_NAMING hook_bool_CUMULATIVE_ARGS_true
 #undef TARGET_MUST_PASS_IN_STACK
 #define TARGET_MUST_PASS_IN_STACK must_pass_in_stack_var_size
+#undef TARGET_GET_RAW_RESULT_MODE
+#define TARGET_GET_RAW_RESULT_MODE ia64_get_reg_raw_mode
+#undef TARGET_GET_RAW_ARG_MODE
+#define TARGET_GET_RAW_ARG_MODE ia64_get_reg_raw_mode
 
 #undef TARGET_GIMPLIFY_VA_ARG_EXPR
 #define TARGET_GIMPLIFY_VA_ARG_EXPR ia64_gimplify_va_arg
@@ -10959,5 +10964,12 @@ ia64_dconst_0_375 (void)
   return ia64_dconst_0_375_rtx;
 }
 
+static enum machine_mode
+ia64_get_reg_raw_mode (int regno)
+{
+  if (FR_REGNO_P (regno))
+    return XFmode;
+  return default_get_reg_raw_mode(regno);
+}
 
 #include "gt-ia64.h"
