[PATCH RFC 3/3] Hookize PROMOTE_FUNCTION_MODE with provision for HFmode

Paolo Bonzini bonzini@gnu.org
Tue Apr 21 13:07:00 GMT 2009


The final patch turns the body of promote_function_mode into a hook.
The hook absorbs the checks on for_return and func done in
promote_function_mode.  This does not add any code in most ports
(it does in SH and PA) because most ports promote both
arguments and return values.  For S390, SPARC, ARM, CRIS, MMIX the
code in PROMOTE_FUNCTION_MODE is moved to a target hook.

There is a FIXME in SPARC regarding extension of the return value
when pointers are 32-bit.  This is not done by PROMOTE_FUNCTION_MODE
and is done by FUNCTION_VALUE.

For ARM, a bogus reference was found to MODE_COMPLEX_INT in
PROMOTE_FUNCTION_MODE.  To test its removal, the following
patch is being included in the bootstrap/regtest.

Index: gcc/explow.c
===================================================================
--- gcc/explow.c	(branch promote-function-mode)
+++ gcc/explow.c	(working copy)
@@ -755,4 +755,5 @@ promote_function_mode (const_tree type,
 {
+  gcc_assert (GET_MODE_CLASS (mode) != MODE_COMPLEX_INT);
   switch (TREE_CODE (type))
     {
     case INTEGER_TYPE:   case ENUMERAL_TYPE:   case BOOLEAN_TYPE:


Also, after this patch is in the following FIXME in explow.c should be
evaluated on S390 and/or SPARC

  /* FIXME: this is the same logic that was there until GCC 4.4, but we
     probably want to test POINTERS_EXTEND_UNSIGNED even if PROMOTE_MODE
     is not defined.  */

where promote_mode (the function in explow.c) is not extending pointers
for those targets that define POINTERS_EXTEND_UNSIGNED but not
PROMOTE_MODE.

Impressions, ideas, insults?

Paolo

2009-04-17  Paolo Bonzini  <bonzini@gnu.org>

	* explow.c (promote_function_mode): Just call the target hook.
	* targhooks.c (default_promote_function_mode,
	default_promote_function_mode_always_promote): New.
	* targhooks.h (default_promote_function_mode,
	default_promote_function_mode_always_promote): Declare.
	* target.h (promote_function_args, promote_function_return): Remove.
	(promote_function_mode): New.
	* target-def.h (TARGET_PROMOTE_FUNCTION_ARGS,
	TARGET_PROMOTE_FUNCTION_RETURN): Remove.
	(TARGET_PROMOTE_FUNCTION_MODE): New.
	(TARGET_CALLS): Adjust.
	* system.h (TARGET_PROMOTE_FUNCTION_ARGS,
	TARGET_PROMOTE_FUNCTION_RETURN, PROMOTE_FUNCTION_MODE): Poison.

	* config/s390/s390.h (PROMOTE_FUNCTION_MODE): Move...
	* config/s390/s390.c (s390_promote_function_mode): ... here,
	with pointer handling.
	(TARGET_PROMOTE_FUNCTION_MODE): Define.
	(TARGET_PROMOTE_FUNCTION_ARGS, TARGET_PROMOTE_FUNCTION_RETURN): Remove.

	* config/sparc/sparc.h (PROMOTE_FUNCTION_MODE): Move...
	* config/sparc/sparc.c (sparc_promote_function_mode): ... here,
	with pointer handling.
	(TARGET_PROMOTE_FUNCTION_MODE): Define.
	(TARGET_PROMOTE_FUNCTION_ARGS, TARGET_PROMOTE_FUNCTION_RETURN): Remove.
	
	* config/sh/sh-protos.h (sh_promote_function_mode): New.
	* config/sh/sh.c (sh_promote_function_mode): New.
	(TARGET_PROMOTE_FUNCTION_MODE): Define.
	(TARGET_PROMOTE_FUNCTION_ARGS, TARGET_PROMOTE_FUNCTION_RETURN): Remove.

	* config/cris/cris.h (PROMOTE_FUNCTION_MODE): Move...
	* config/cris/cris.c (cris_promote_function_mode): ... here.
	(TARGET_PROMOTE_FUNCTION_MODE): Define.
	(TARGET_PROMOTE_FUNCTION_ARGS): Remove.

	* config/mmix/mmix.h (PROMOTE_FUNCTION_MODE): Move...
	* config/mmix/mmix.c (mmix_promote_function_mode): ... here.
	(TARGET_PROMOTE_FUNCTION_MODE): Define.
	(TARGET_PROMOTE_FUNCTION_ARGS): Remove.

	* config/arm/arm.h (PROMOTE_FUNCTION_MODE): Move...
	* config/arm/arm.c (arm_promote_function_mode): ... here, without complex
	type handling.
	(TARGET_PROMOTE_FUNCTION_MODE): Define.
	(TARGET_PROMOTE_FUNCTION_ARGS, TARGET_PROMOTE_FUNCTION_RETURN): Remove.

	* config/pa/pa.c (pa_promote_function_mode): New.
	(TARGET_PROMOTE_FUNCTION_MODE): Define.
	(TARGET_PROMOTE_FUNCTION_RETURN): Remove.

	* config/alpha/alpha.c (TARGET_PROMOTE_FUNCTION_ARGS,
	TARGET_PROMOTE_FUNCTION_RETURN): Remove.
	(TARGET_PROMOTE_FUNCTION_MODE): Define equivalently.
	* config/xtensa/xtensa.c: Likewise.
	* config/stormy16/stormy16.c: Likewise.
	* config/iq2000/iq2000.c: Likewise.
	* config/rs6000/rs6000.c: Likewise.
	* config/picochip/picochip.c: Likewise.
	* config/arc/arc.c: Likewise.
	* config/mcore/mcore.c: Likewise.
	* config/score/score.c: Likewise.
	* config/mips/mips.c: Likewise.
	* config/bfin/bfin.c: Likewise.
	* config/ia64/ia64.c: Likewise (disabled though).

	* config/frv/frv.h: Remove pointless remark.

	* doc/tm.texi (PROMOTE_FUNCTION_MODE,
	TARGET_PROMOTE_FUNCTION_ARGS,
	TARGET_PROMOTE_FUNCTION_RETURN): Consolidate into...
	(TARGET_PROMOTE_FUNCTION_MODE): ... this.

Index: gcc/explow.c
===================================================================
--- gcc/explow.c	(branch promote-function-mode)
+++ gcc/explow.c	(working copy)
@@ -755,31 +755,18 @@ enum machine_mode
 promote_function_mode (const_tree type, enum machine_mode mode, int *punsignedp,
 		       tree funtype, int for_return)
 {
-  if (for_return && !targetm.calls.promote_function_return (funtype))
-    return mode;
-  if (!for_return && !targetm.calls.promote_function_args (funtype))
-    return mode;
-
-#ifdef PROMOTE_FUNCTION_MODE
   switch (TREE_CODE (type))
     {
     case INTEGER_TYPE:   case ENUMERAL_TYPE:   case BOOLEAN_TYPE:
     case REAL_TYPE:      case OFFSET_TYPE:     case FIXED_POINT_TYPE:
-      {
-	int unsignedp = *punsignedp;
-	PROMOTE_FUNCTION_MODE (mode, unsignedp, type);
-	*punsignedp = unsignedp;
-	return mode;
-      }
+    case POINTER_TYPE:   case REFERENCE_TYPE:
+      return targetm.calls.promote_function_mode (type, mode, punsignedp, funtype,
+						  for_return);
 
     default:
-      break;
+      return mode;
     }
-#endif
-
-  return promote_mode (type, mode, punsignedp);
 }
-
 /* Return the mode to use to store a scalar of TYPE and MODE.
    PUNSIGNEDP points to the signedness of the type and may be adjusted
    to show what signedness to use on extension operations.  */
Index: gcc/targhooks.c
===================================================================
--- gcc/targhooks.c	(branch promote-function-mode)
+++ gcc/targhooks.c	(working copy)
@@ -96,6 +96,27 @@ default_unspec_may_trap_p (const_rtx x, 
 }
 
 enum machine_mode
+default_promote_function_mode (const_tree type ATTRIBUTE_UNUSED,
+			       enum machine_mode mode,
+			       int *punsignedp ATTRIBUTE_UNUSED,
+			       const_tree funtype ATTRIBUTE_UNUSED,
+			       int for_return ATTRIBUTE_UNUSED)
+{
+  return mode;
+}
+
+enum machine_mode
+default_promote_function_mode_always_promote (const_tree type,
+					      enum machine_mode mode,
+					      int *punsignedp,
+					      const_tree funtype ATTRIBUTE_UNUSED,
+					      int for_return ATTRIBUTE_UNUSED)
+{
+  return promote_mode (type, mode, punsignedp);
+}
+
+
+enum machine_mode
 default_cc_modes_compatible (enum machine_mode m1, enum machine_mode m2)
 {
   if (m1 == m2)
Index: gcc/targhooks.h
===================================================================
--- gcc/targhooks.h	(branch promote-function-mode)
+++ gcc/targhooks.h	(working copy)
@@ -20,6 +20,10 @@ along with GCC; see the file COPYING3.  
 extern void default_external_libcall (rtx);
 
 extern int default_unspec_may_trap_p (const_rtx, unsigned);
+extern enum machine_mode default_promote_function_mode (const_tree, enum machine_mode,
+							int *, const_tree, int);
+extern enum machine_mode default_promote_function_mode_always_promote
+			(const_tree, enum machine_mode, int *, const_tree, int);
 
 extern enum machine_mode default_cc_modes_compatible (enum machine_mode,
 						      enum machine_mode);
Index: gcc/target.h
===================================================================
--- gcc/target.h	(branch promote-function-mode)
+++ gcc/target.h	(working copy)
@@ -813,8 +813,11 @@ struct gcc_target
 
   /* Functions relating to calls - argument passing, returns, etc.  */
   struct calls {
-    bool (*promote_function_args) (const_tree fntype);
-    bool (*promote_function_return) (const_tree fntype);
+    enum machine_mode (*promote_function_mode) (const_tree type,
+						enum machine_mode mode,
+						int *punsignedp,
+						const_tree fntype,
+						int for_return);
     bool (*promote_prototypes) (const_tree fntype);
     rtx (*struct_value_rtx) (tree fndecl, int incoming);
     bool (*return_in_memory) (const_tree type, const_tree fndecl);
Index: gcc/target-def.h
===================================================================
--- gcc/target-def.h	(branch promote-function-mode)
+++ gcc/target-def.h	(working copy)
@@ -565,8 +565,7 @@
 
 #define TARGET_ARM_EABI_UNWINDER false
 
-#define TARGET_PROMOTE_FUNCTION_ARGS hook_bool_const_tree_false
-#define TARGET_PROMOTE_FUNCTION_RETURN hook_bool_const_tree_false
+#define TARGET_PROMOTE_FUNCTION_MODE default_promote_function_mode
 #define TARGET_PROMOTE_PROTOTYPES hook_bool_const_tree_false
 
 #define TARGET_STRUCT_VALUE_RTX hook_rtx_tree_int_null
@@ -595,8 +595,7 @@
 #define TARGET_ALLOCATE_STACK_SLOTS_FOR_ARGS hook_bool_void_true
 
 #define TARGET_CALLS {						\
-   TARGET_PROMOTE_FUNCTION_ARGS,				\
-   TARGET_PROMOTE_FUNCTION_RETURN,				\
+   TARGET_PROMOTE_FUNCTION_MODE,				\
    TARGET_PROMOTE_PROTOTYPES,					\
    TARGET_STRUCT_VALUE_RTX,					\
    TARGET_RETURN_IN_MEMORY,					\
Index: gcc/config/alpha/alpha.c
===================================================================
--- gcc/config/alpha/alpha.c	(branch promote-function-mode)
+++ gcc/config/alpha/alpha.c	(working copy)
@@ -10780,10 +10780,8 @@ alpha_init_libfuncs (void)
 #undef TARGET_MACHINE_DEPENDENT_REORG
 #define TARGET_MACHINE_DEPENDENT_REORG alpha_reorg
 
-#undef TARGET_PROMOTE_FUNCTION_ARGS
-#define TARGET_PROMOTE_FUNCTION_ARGS hook_bool_const_tree_true
-#undef TARGET_PROMOTE_FUNCTION_RETURN
-#define TARGET_PROMOTE_FUNCTION_RETURN hook_bool_const_tree_true
+#undef TARGET_PROMOTE_FUNCTION_MODE
+#define TARGET_PROMOTE_FUNCTION_MODE default_promote_function_mode_always_promote
 #undef TARGET_PROMOTE_PROTOTYPES
 #define TARGET_PROMOTE_PROTOTYPES hook_bool_const_tree_false
 #undef TARGET_RETURN_IN_MEMORY
Index: gcc/config/s390/s390.c
===================================================================
--- gcc/config/s390/s390.c	(branch promote-function-mode)
+++ gcc/config/s390/s390.c	(working copy)
@@ -8305,6 +8305,25 @@ s390_return_in_memory (const_tree type, 
   return true;
 }
 
+/* Function arguments and return values are promoted to word size.  */
+
+static enum machine_mode
+s390_promote_function_mode (const_tree type, enum machine_mode mode,
+                            int *punsignedp,
+                            const_tree fntype ATTRIBUTE_UNUSED,
+                            int for_return ATTRIBUTE_UNUSED)
+{
+  if (INTEGRAL_MODE_P (mode)
+      && GET_MODE_SIZE (mode) < UNITS_PER_WORD)
+    {
+      if (POINTER_TYPE_P (type))
+	*punsignedp = POINTERS_EXTEND_UNSIGNED;
+      return Pmode;
+    }
+
+  return mode;
+}
+
 /* Define where to return a (scalar) value of type TYPE.
    If TYPE is null, define where to return a (scalar)
    value of mode MODE from a libcall.  */
@@ -9952,10 +9971,8 @@ s390_reorg (void)
 #undef TARGET_GIMPLIFY_VA_ARG_EXPR
 #define TARGET_GIMPLIFY_VA_ARG_EXPR s390_gimplify_va_arg
 
-#undef TARGET_PROMOTE_FUNCTION_ARGS
-#define TARGET_PROMOTE_FUNCTION_ARGS hook_bool_const_tree_true
-#undef TARGET_PROMOTE_FUNCTION_RETURN
-#define TARGET_PROMOTE_FUNCTION_RETURN hook_bool_const_tree_true
+#undef TARGET_PROMOTE_FUNCTION_MODE
+#define TARGET_PROMOTE_FUNCTION_MODE s390_promote_function_mode
 #undef TARGET_PASS_BY_REFERENCE
 #define TARGET_PASS_BY_REFERENCE s390_pass_by_reference
 
Index: gcc/config/s390/s390.h
===================================================================
--- gcc/config/s390/s390.h	(branch promote-function-mode)
+++ gcc/config/s390/s390.h	(working copy)
@@ -212,13 +212,6 @@ extern enum processor_flags s390_arch_fl
 #endif
 #define MAX_BITS_PER_WORD 64
 
-/* Function arguments and return values are promoted to word size.  */
-#define PROMOTE_FUNCTION_MODE(MODE, UNSIGNEDP, TYPE)		\
-if (INTEGRAL_MODE_P (MODE) &&	        	    	\
-    GET_MODE_SIZE (MODE) < UNITS_PER_WORD) { 		\
-  (MODE) = Pmode;					\
-	  }
-
 /* Allocation boundary (in *bits*) for storing arguments in argument list.  */
 #define PARM_BOUNDARY (TARGET_64BIT ? 64 : 32)
 
Index: gcc/config/sparc/sparc.c
===================================================================
--- gcc/config/sparc/sparc.c	(branch promote-function-mode)
+++ gcc/config/sparc/sparc.c	(working copy)
@@ -407,6 +407,8 @@ static int get_some_local_dynamic_name_1
 static bool sparc_rtx_costs (rtx, int, int, int *, bool);
 static bool sparc_promote_prototypes (const_tree);
 static rtx sparc_struct_value_rtx (tree, int);
+static enum machine_mode sparc_promote_function_mode (const_tree, enum machine_mode,
+						      int *, const_tree, int);
 static bool sparc_return_in_memory (const_tree, const_tree);
 static bool sparc_strict_argument_naming (CUMULATIVE_ARGS *);
 static void sparc_va_start (tree, rtx);
@@ -515,17 +517,8 @@ static bool fpu_option_set = false;
 #undef TARGET_ADDRESS_COST
 #define TARGET_ADDRESS_COST hook_int_rtx_bool_0
 
-/* This is only needed for TARGET_ARCH64, but since PROMOTE_FUNCTION_MODE is a
-   no-op for TARGET_ARCH32 this is ok.  Otherwise we'd need to add a runtime
-   test for this value.  */
-#undef TARGET_PROMOTE_FUNCTION_ARGS
-#define TARGET_PROMOTE_FUNCTION_ARGS hook_bool_const_tree_true
-
-/* This is only needed for TARGET_ARCH64, but since PROMOTE_FUNCTION_MODE is a
-   no-op for TARGET_ARCH32 this is ok.  Otherwise we'd need to add a runtime
-   test for this value.  */
-#undef TARGET_PROMOTE_FUNCTION_RETURN
-#define TARGET_PROMOTE_FUNCTION_RETURN hook_bool_const_tree_true
+#undef TARGET_PROMOTE_FUNCTION_MODE
+#define TARGET_PROMOTE_FUNCTION_MODE sparc_promote_function_mode
 
 #undef TARGET_PROMOTE_PROTOTYPES
 #define TARGET_PROMOTE_PROTOTYPES sparc_promote_prototypes
@@ -4528,6 +4521,37 @@ sparc_promote_prototypes (const_tree fnt
   return TARGET_ARCH32 ? true : false;
 }
 
+/* Handle promotion of pointer and integer arguments.  */
+
+static enum machine_mode
+sparc_promote_function_mode (const_tree type ATTRIBUTE_UNUSED,
+                             enum machine_mode mode,
+                             int *punsignedp ATTRIBUTE_UNUSED,
+                             const_tree fntype ATTRIBUTE_UNUSED,
+                             int for_return ATTRIBUTE_UNUSED)
+{
+  if (POINTER_TYPE_P (type)
+      && GET_MODE_SIZE (mode) < Pmode)
+    {
+      *punsignedp = POINTERS_EXTEND_UNSIGNED;
+      return Pmode;
+    }
+
+  /* For TARGET_ARCH64 we need this, as we don't have instructions
+     for arithmetic operations which do zero/sign extension at the same time,
+     so without this we end up with a srl/sra after every assignment to an
+     user variable,  which means very very bad code.  */
+
+  if (TARGET_ARCH64
+      && GET_MODE_CLASS (mode) == MODE_INT
+      && GET_MODE_SIZE (mode) < UNITS_PER_WORD)
+    return word_mode;
+
+  return mode;
+}
+
+
+
 /* Handle the TARGET_STRICT_ARGUMENT_NAMING target hook.  */
 
 static bool
@@ -5670,7 +5694,8 @@ function_value (const_tree type, enum ma
 	    mclass = MODE_INT;
 	}
 
-      /* This must match PROMOTE_FUNCTION_MODE.  */
+      /* This must match sparc_promote_function_mode.
+	 ??? Maybe 32-bit pointers should actually remain in Pmode?  */
       else if (mclass == MODE_INT && GET_MODE_SIZE (mode) < UNITS_PER_WORD)
 	mode = word_mode;
     }
Index: gcc/config/sparc/sparc.h
===================================================================
--- gcc/config/sparc/sparc.h	(branch promote-function-mode)
+++ gcc/config/sparc/sparc.h	(working copy)
@@ -634,16 +634,6 @@ extern struct sparc_cpu_select sparc_sel
    if ptr_mode and Pmode are the same.  */
 #define POINTERS_EXTEND_UNSIGNED 1
 
-/* For TARGET_ARCH64 we need this, as we don't have instructions
-   for arithmetic operations which do zero/sign extension at the same time,
-   so without this we end up with a srl/sra after every assignment to an
-   user variable,  which means very very bad code.  */
-#define PROMOTE_FUNCTION_MODE(MODE, UNSIGNEDP, TYPE) \
-if (TARGET_ARCH64				\
-    && GET_MODE_CLASS (MODE) == MODE_INT	\
-    && GET_MODE_SIZE (MODE) < UNITS_PER_WORD)	\
-  (MODE) = word_mode;
-
 /* Allocation boundary (in *bits*) for storing arguments in argument list.  */
 #define PARM_BOUNDARY (TARGET_ARCH64 ? 64 : 32)
 
Index: gcc/config/sh/sh-protos.h
===================================================================
--- gcc/config/sh/sh-protos.h	(branch promote-function-mode)
+++ gcc/config/sh/sh-protos.h	(working copy)
@@ -160,6 +160,8 @@ extern void sh_function_arg_advance (CUM
 extern int sh_pass_in_reg_p (CUMULATIVE_ARGS *, enum machine_mode, tree);
 extern void sh_init_cumulative_args (CUMULATIVE_ARGS *, tree, rtx, tree, signed int, enum machine_mode);
 extern bool sh_promote_prototypes (const_tree);
+extern enum machine_mode sh_promote_function_mode (const_tree, enum machine_mode,
+						   int *, const_tree, int);
 
 extern rtx replace_n_hard_rtx (rtx, rtx *, int , int);
 extern int shmedia_cleanup_truncate (rtx *, void *);
Index: gcc/config/sh/sh.c
===================================================================
--- gcc/config/sh/sh.c	(branch promote-function-mode)
+++ gcc/config/sh/sh.c	(working copy)
@@ -413,9 +413,7 @@ static int sh2a_function_vector_p (tree)
 #undef TARGET_PROMOTE_PROTOTYPES
 #define TARGET_PROMOTE_PROTOTYPES sh_promote_prototypes
 #undef TARGET_PROMOTE_FUNCTION_ARGS
-#define TARGET_PROMOTE_FUNCTION_ARGS sh_promote_prototypes
-#undef TARGET_PROMOTE_FUNCTION_RETURN
-#define TARGET_PROMOTE_FUNCTION_RETURN sh_promote_prototypes
+#define TARGET_PROMOTE_FUNCTION_ARGS sh_promote_function_mode
 
 #undef TARGET_STRUCT_VALUE_RTX
 #define TARGET_STRUCT_VALUE_RTX sh_struct_value_rtx
@@ -7424,6 +7422,16 @@ sh_gimplify_va_arg_expr (tree valist, tr
   return result;
 }
 
+enum machine_mode
+sh_promote_function_mode (const_tree type, enum machine_mode mode,
+			  int *punsignedp, const_tree funtype, int for_return)
+{
+  if (sh_promote_prototypes (funtype))
+    return promote_mode (type, machine_mode, punsignedp);
+  else
+    return mode;
+}
+
 bool
 sh_promote_prototypes (const_tree type)
 {
Index: gcc/config/xtensa/xtensa.c
===================================================================
--- gcc/config/xtensa/xtensa.c	(branch promote-function-mode)
+++ gcc/config/xtensa/xtensa.c	(working copy)
@@ -186,10 +186,8 @@ static const int reg_nonleaf_alloc_order
 #undef TARGET_EXPAND_BUILTIN_VA_START
 #define TARGET_EXPAND_BUILTIN_VA_START xtensa_va_start
 
-#undef TARGET_PROMOTE_FUNCTION_ARGS
-#define TARGET_PROMOTE_FUNCTION_ARGS hook_bool_const_tree_true
-#undef TARGET_PROMOTE_FUNCTION_RETURN
-#define TARGET_PROMOTE_FUNCTION_RETURN hook_bool_const_tree_true
+#undef TARGET_PROMOTE_FUNCTION_MODE
+#define TARGET_PROMOTE_FUNCTION_MODE default_promote_function_mode_always_promote
 #undef TARGET_PROMOTE_PROTOTYPES
 #define TARGET_PROMOTE_PROTOTYPES hook_bool_const_tree_true
 
Index: gcc/config/xtensa/xtensa.h
===================================================================
--- gcc/config/xtensa/xtensa.h	(branch promote-function-mode)
+++ gcc/config/xtensa/xtensa.h	(working copy)
@@ -601,7 +601,7 @@ extern const enum reg_class xtensa_regno
 
 /* Define how to find the value returned by a library function
    assuming the value has mode MODE.  Because we have defined
-   TARGET_PROMOTE_FUNCTION_RETURN that returns true, we have to
+   TARGET_PROMOTE_FUNCTION_MODE to promote everything, we have to
    perform the same promotions as PROMOTE_MODE.  */
 #define XTENSA_LIBCALL_VALUE(MODE, OUTGOINGP)				\
   gen_rtx_REG ((GET_MODE_CLASS (MODE) == MODE_INT			\
Index: gcc/config/stormy16/stormy16.c
===================================================================
--- gcc/config/stormy16/stormy16.c	(branch promote-function-mode)
+++ gcc/config/stormy16/stormy16.c	(working copy)
@@ -2643,10 +2643,8 @@ xstormy16_return_in_memory (const_tree t
 #undef  TARGET_GIMPLIFY_VA_ARG_EXPR
 #define TARGET_GIMPLIFY_VA_ARG_EXPR xstormy16_gimplify_va_arg_expr
 
-#undef  TARGET_PROMOTE_FUNCTION_ARGS
-#define TARGET_PROMOTE_FUNCTION_ARGS hook_bool_const_tree_true
-#undef  TARGET_PROMOTE_FUNCTION_RETURN
-#define TARGET_PROMOTE_FUNCTION_RETURN hook_bool_const_tree_true
+#undef  TARGET_PROMOTE_FUNCTION_MODE
+#define TARGET_PROMOTE_FUNCTION_MODE default_promote_function_mode_always_promote
 #undef  TARGET_PROMOTE_PROTOTYPES
 #define TARGET_PROMOTE_PROTOTYPES hook_bool_const_tree_true
 
Index: gcc/config/cris/cris.c
===================================================================
--- gcc/config/cris/cris.c	(branch promote-function-mode)
+++ gcc/config/cris/cris.c	(working copy)
@@ -85,6 +85,9 @@ static int in_code = 0;
 /* Fix for reg_overlap_mentioned_p.  */
 static int cris_reg_overlap_mentioned_p (rtx, rtx);
 
+static enum machine_mode cris_promote_function_mode (const_tree, enum machine_mode,
+						     int *, const_tree, int);
+
 static void cris_print_base (rtx, FILE *);
 
 static void cris_print_index (rtx, FILE *);
@@ -164,8 +167,9 @@ int cris_cpu_version = CRIS_DEFAULT_CPU_
 #undef TARGET_ADDRESS_COST
 #define TARGET_ADDRESS_COST cris_address_cost
 
-#undef TARGET_PROMOTE_FUNCTION_ARGS
-#define TARGET_PROMOTE_FUNCTION_ARGS hook_bool_const_tree_true
+#undef TARGET_PROMOTE_FUNCTION_MODE
+#define TARGET_PROMOTE_FUNCTION_MODE cris_promote_function_mode
+
 #undef TARGET_STRUCT_VALUE_RTX
 #define TARGET_STRUCT_VALUE_RTX cris_struct_value_rtx
 #undef TARGET_SETUP_INCOMING_VARARGS
@@ -3739,6 +3743,25 @@ cris_pass_by_reference (CUMULATIVE_ARGS 
 	  || CRIS_FUNCTION_ARG_SIZE (mode, type) > 8);
 }
 
+/* A combination of defining TARGET_PROMOTE_FUNCTION_MODE, promoting arguments
+   and *not* defining TARGET_PROMOTE_PROTOTYPES or PROMOTE_MODE gives the
+   best code size and speed for gcc, ipps and products in gcc-2.7.2.  */
+
+enum machine_mode
+cris_promote_function_mode (const_tree type ATTRIBUTE_UNUSED,
+                            enum machine_mode mode,
+                            int *punsignedp ATTRIBUTE_UNUSED,
+			    const_tree fntype ATTRIBUTE_UNUSED,
+                            int for_return)
+{
+  /* Defining PROMOTE_FUNCTION_RETURN in gcc-2.7.2 uncovered bug 981110 (even
+     when modifying FUNCTION_VALUE to return the promoted mode).  Maybe
+     pointless as of now, but let's keep the old behavior.  */
+  if (for_return)
+    return mode;
+  return CRIS_PROMOTED_MODE (mode, *punsignedp, type);
+} 
+
 
 static int
 cris_arg_partial_bytes (CUMULATIVE_ARGS *ca, enum machine_mode mode,
Index: gcc/config/cris/cris.h
===================================================================
--- gcc/config/cris/cris.h	(branch promote-function-mode)
+++ gcc/config/cris/cris.h	(working copy)
@@ -352,24 +352,10 @@ extern int target_flags;
 
 #define UNITS_PER_WORD 4
 
-/* A combination of defining PROMOTE_FUNCTION_MODE,
-   TARGET_PROMOTE_FUNCTION_ARGS that always returns true
-   and *not* defining TARGET_PROMOTE_PROTOTYPES or PROMOTE_MODE gives the
-   best code size and speed for gcc, ipps and products in gcc-2.7.2.  */
 #define CRIS_PROMOTED_MODE(MODE, UNSIGNEDP, TYPE) \
  (GET_MODE_CLASS (MODE) == MODE_INT && GET_MODE_SIZE (MODE) < 4) \
   ? SImode : MODE
 
-#define PROMOTE_FUNCTION_MODE(MODE, UNSIGNEDP, TYPE)  \
-  (MODE) = CRIS_PROMOTED_MODE (MODE, UNSIGNEDP, TYPE)
-
-/* Defining PROMOTE_FUNCTION_RETURN in gcc-2.7.2 uncovers bug 981110 (even
-   if defining FUNCTION_VALUE with MODE as PROMOTED_MODE ;-)
-
-   FIXME: Report this when cris.h is part of GCC, so others can easily
-   see the problem.  Maybe check other systems that define
-   TARGET_PROMOTE_FUNCTION_RETURN that always returns true.  */
-
 /* We will be using prototype promotion, so they will be 32 bit.  */
 #define PARM_BOUNDARY 32
 
Index: gcc/config/iq2000/iq2000.c
===================================================================
--- gcc/config/iq2000/iq2000.c	(branch promote-function-mode)
+++ gcc/config/iq2000/iq2000.c	(working copy)
@@ -191,10 +191,8 @@ static void iq2000_va_start	      (tree,
 #undef  TARGET_HAVE_SWITCHABLE_BSS_SECTIONS
 #define TARGET_HAVE_SWITCHABLE_BSS_SECTIONS false
 
-#undef  TARGET_PROMOTE_FUNCTION_ARGS
-#define TARGET_PROMOTE_FUNCTION_ARGS	hook_bool_const_tree_true
-#undef  TARGET_PROMOTE_FUNCTION_RETURN
-#define TARGET_PROMOTE_FUNCTION_RETURN	hook_bool_const_tree_true
+#undef  TARGET_PROMOTE_FUNCTION_MODE
+#define TARGET_PROMOTE_FUNCTION_MODE	default_promote_function_mode_always_promote
 #undef  TARGET_PROMOTE_PROTOTYPES
 #define TARGET_PROMOTE_PROTOTYPES	hook_bool_const_tree_true
 
Index: gcc/config/ia64/ia64.c
===================================================================
--- gcc/config/ia64/ia64.c	(branch promote-function-mode)
+++ gcc/config/ia64/ia64.c	(working copy)
@@ -464,14 +464,8 @@ static const struct attribute_spec ia64_
 
 /* ??? ABI doesn't allow us to define this.  */
 #if 0
-#undef TARGET_PROMOTE_FUNCTION_ARGS
-#define TARGET_PROMOTE_FUNCTION_ARGS hook_bool_tree_true
-#endif
-
-/* ??? ABI doesn't allow us to define this.  */
-#if 0
-#undef TARGET_PROMOTE_FUNCTION_RETURN
-#define TARGET_PROMOTE_FUNCTION_RETURN hook_bool_tree_true
+#undef TARGET_PROMOTE_FUNCTION_MODE
+#define TARGET_PROMOTE_FUNCTION_MODE default_promote_function_mode_always_promote
 #endif
 
 /* ??? Investigate.  */
Index: gcc/config/rs6000/rs6000.c
===================================================================
--- gcc/config/rs6000/rs6000.c	(branch promote-function-mode)
+++ gcc/config/rs6000/rs6000.c	(working copy)
@@ -1202,10 +1202,8 @@ static const char alt_reg_names[][8] =
 
 /* On rs6000, function arguments are promoted, as are function return
    values.  */
-#undef TARGET_PROMOTE_FUNCTION_ARGS
-#define TARGET_PROMOTE_FUNCTION_ARGS hook_bool_const_tree_true
-#undef TARGET_PROMOTE_FUNCTION_RETURN
-#define TARGET_PROMOTE_FUNCTION_RETURN hook_bool_const_tree_true
+#undef TARGET_PROMOTE_FUNCTION_MODE
+#define TARGET_PROMOTE_FUNCTION_MODE default_promote_function_mode_always_promote
 
 #undef TARGET_RETURN_IN_MEMORY
 #define TARGET_RETURN_IN_MEMORY rs6000_return_in_memory
Index: gcc/config/picochip/picochip.c
===================================================================
--- gcc/config/picochip/picochip.c	(branch promote-function-mode)
+++ gcc/config/picochip/picochip.c	(working copy)
@@ -253,10 +253,8 @@ static char picochip_get_vliw_alu_id (vo
 #undef TARGET_ARG_PARTIAL_BYTES
 #define TARGET_ARG_PARTIAL_BYTES picochip_arg_partial_bytes
 
-#undef TARGET_PROMOTE_FUNCTION_ARGS
-#define TARGET_PROMOTE_FUNCTION_ARGS hook_bool_const_tree_true
-#undef TARGET_PROMOTE_FUNCTION_RETURN
-#define TARGET_PROMOTE_FUNCTION_RETURN hook_bool_const_tree_true
+#undef TARGET_PROMOTE_FUNCTION_MODE
+#define TARGET_PROMOTE_FUNCTION_MODE default_promote_function_mode_always_promote
 #undef TARGET_PROMOTE_PROTOTYPES
 #define TARGET_PROMOTE_PROTOTYPES hook_bool_const_tree_true
 
Index: gcc/config/arc/arc.c
===================================================================
--- gcc/config/arc/arc.c	(branch promote-function-mode)
+++ gcc/config/arc/arc.c	(working copy)
@@ -128,10 +128,8 @@ static bool arc_pass_by_reference (CUMUL
 #undef TARGET_ADDRESS_COST
 #define TARGET_ADDRESS_COST arc_address_cost
 
-#undef TARGET_PROMOTE_FUNCTION_ARGS
-#define TARGET_PROMOTE_FUNCTION_ARGS hook_bool_const_tree_true
-#undef TARGET_PROMOTE_FUNCTION_RETURN
-#define TARGET_PROMOTE_FUNCTION_RETURN hook_bool_const_tree_true
+#undef TARGET_PROMOTE_FUNCTION_MODE
+#define TARGET_PROMOTE_FUNCTION_MODE default_promote_function_mode_always_promote
 #undef TARGET_PROMOTE_PROTOTYPES
 #define TARGET_PROMOTE_PROTOTYPES hook_bool_const_tree_true
 
Index: gcc/config/mcore/mcore.c
===================================================================
--- gcc/config/mcore/mcore.c	(branch promote-function-mode)
+++ gcc/config/mcore/mcore.c	(working copy)
@@ -187,10 +187,8 @@ static int        mcore_arg_partial_byte
 #undef  TARGET_MACHINE_DEPENDENT_REORG
 #define TARGET_MACHINE_DEPENDENT_REORG	mcore_reorg
 
-#undef  TARGET_PROMOTE_FUNCTION_ARGS
-#define TARGET_PROMOTE_FUNCTION_ARGS	hook_bool_const_tree_true
-#undef  TARGET_PROMOTE_FUNCTION_RETURN
-#define TARGET_PROMOTE_FUNCTION_RETURN	hook_bool_const_tree_true
+#undef  TARGET_PROMOTE_FUNCTION_MODE
+#define TARGET_PROMOTE_FUNCTION_MODE	default_promote_function_mode_always_promote
 #undef  TARGET_PROMOTE_PROTOTYPES
 #define TARGET_PROMOTE_PROTOTYPES	hook_bool_const_tree_true
 
Index: gcc/config/score/score.c
===================================================================
--- gcc/config/score/score.c	(branch promote-function-mode)
+++ gcc/config/score/score.c	(working copy)
@@ -86,11 +86,8 @@
 #undef TARGET_ASM_OUTPUT_MI_THUNK
 #define TARGET_ASM_OUTPUT_MI_THUNK      score_output_mi_thunk
 
-#undef TARGET_PROMOTE_FUNCTION_ARGS
-#define TARGET_PROMOTE_FUNCTION_ARGS    hook_bool_tree_true
-
-#undef TARGET_PROMOTE_FUNCTION_RETURN
-#define TARGET_PROMOTE_FUNCTION_RETURN  hook_bool_tree_true
+#undef TARGET_PROMOTE_FUNCTION_MODE
+#define TARGET_PROMOTE_FUNCTION_MODE    default_promote_function_mode_always_promote
 
 #undef TARGET_PROMOTE_PROTOTYPES
 #define TARGET_PROMOTE_PROTOTYPES       hook_bool_tree_true
Index: gcc/config/arm/arm.c
===================================================================
--- gcc/config/arm/arm.c	(branch promote-function-mode)
+++ gcc/config/arm/arm.c	(working copy)
@@ -123,6 +123,8 @@ static int arm_adjust_cost (rtx, rtx, rt
 static int count_insns_for_constant (HOST_WIDE_INT, int);
 static int arm_get_strip_length (int);
 static bool arm_function_ok_for_sibcall (tree, tree);
+static enum machine_mode arm_promote_function_mode (const_tree, enum machine_mode,
+						    int *, const_tree, int);
 static void arm_internal_label (FILE *, const char *, unsigned long);
 static void arm_output_mi_thunk (FILE *, tree, HOST_WIDE_INT, HOST_WIDE_INT,
 				 tree);
@@ -282,10 +284,8 @@ static bool arm_allocate_stack_slots_for
 #undef TARGET_INIT_LIBFUNCS
 #define TARGET_INIT_LIBFUNCS arm_init_libfuncs
 
-#undef TARGET_PROMOTE_FUNCTION_ARGS
-#define TARGET_PROMOTE_FUNCTION_ARGS hook_bool_const_tree_true
-#undef TARGET_PROMOTE_FUNCTION_RETURN
-#define TARGET_PROMOTE_FUNCTION_RETURN hook_bool_const_tree_true
+#undef TARGET_PROMOTE_FUNCTION_MODE
+#define TARGET_PROMOTE_FUNCTION_MODE arm_promote_function_mode
 #undef TARGET_PROMOTE_PROTOTYPES
 #define TARGET_PROMOTE_PROTOTYPES arm_promote_prototypes
 #undef TARGET_PASS_BY_REFERENCE
@@ -2874,7 +2874,7 @@ arm_canonicalize_comparison (enum rtx_co
 /* Define how to find the value returned by a function.  */
 
 rtx
-arm_function_value(const_tree type, const_tree func ATTRIBUTE_UNUSED)
+arm_function_value(const_tree type, const_tree func)
 {
   enum machine_mode mode;
   int unsignedp ATTRIBUTE_UNUSED;
@@ -2883,7 +2883,7 @@ arm_function_value(const_tree type, cons
   mode = TYPE_MODE (type);
   /* Promote integer types.  */
   if (INTEGRAL_TYPE_P (type))
-    PROMOTE_FUNCTION_MODE (mode, unsignedp, type);
+    mode = arm_promote_function_mode (type, mode, &unsignedp, func, 1);
 
   /* Promotes small structs returned in a register to full-word size
      for big-endian AAPCS.  */
@@ -18774,6 +18774,19 @@ arm_promote_prototypes (const_tree t ATT
     return !TARGET_AAPCS_BASED;
 }
 
+static enum machine_mode
+arm_promote_function_mode (const_tree type ATTRIBUTE_UNUSED,
+                           enum machine_mode mode,
+                           int *punsignedp ATTRIBUTE_UNUSED,
+                           const_tree fntype ATTRIBUTE_UNUSED,
+                           int for_return ATTRIBUTE_UNUSED)
+{
+  if (GET_MODE_CLASS (mode) == MODE_INT
+      && GET_MODE_SIZE (mode) < 4)
+    return SImode;
+
+  return mode;
+}
 
 /* AAPCS based ABIs use short enums by default.  */
 
Index: gcc/config/arm/arm.h
===================================================================
--- gcc/config/arm/arm.h	(branch promote-function-mode)
+++ gcc/config/arm/arm.h	(working copy)
@@ -483,12 +483,6 @@ extern int arm_arch_hwdiv;
       (MODE) = SImode;				\
     }
 
-#define PROMOTE_FUNCTION_MODE(MODE, UNSIGNEDP, TYPE)	\
-  if ((GET_MODE_CLASS (MODE) == MODE_INT		\
-       || GET_MODE_CLASS (MODE) == MODE_COMPLEX_INT)    \
-      && GET_MODE_SIZE (MODE) < 4)                      \
-    (MODE) = SImode;				        \
-
 /* Define this if most significant bit is lowest numbered
    in instructions that operate on numbered bit-fields.  */
 #define BITS_BIG_ENDIAN  0
Index: gcc/config/mips/mips.c
===================================================================
--- gcc/config/mips/mips.c	(branch promote-function-mode)
+++ gcc/config/mips/mips.c	(working copy)
@@ -14329,10 +14329,8 @@ mips_order_regs_for_local_alloc (void)
 #undef TARGET_GIMPLIFY_VA_ARG_EXPR
 #define TARGET_GIMPLIFY_VA_ARG_EXPR mips_gimplify_va_arg_expr
 
-#undef TARGET_PROMOTE_FUNCTION_ARGS
-#define TARGET_PROMOTE_FUNCTION_ARGS hook_bool_const_tree_true
-#undef TARGET_PROMOTE_FUNCTION_RETURN
-#define TARGET_PROMOTE_FUNCTION_RETURN hook_bool_const_tree_true
+#undef  TARGET_PROMOTE_FUNCTION_MODE
+#define TARGET_PROMOTE_FUNCTION_MODE default_promote_function_mode_always_promote
 #undef TARGET_PROMOTE_PROTOTYPES
 #define TARGET_PROMOTE_PROTOTYPES hook_bool_const_tree_true
 
Index: gcc/config/mmix/mmix.h
===================================================================
--- gcc/config/mmix/mmix.h	(branch promote-function-mode)
+++ gcc/config/mmix/mmix.h	(working copy)
@@ -187,23 +187,6 @@ extern int target_flags;
 #define FLOAT_WORDS_BIG_ENDIAN 1
 #define UNITS_PER_WORD 8
 
-/* FIXME: Promotion of modes currently generates slow code, extending
-   before every operation.  */
-/* I'm a little bit undecided about this one.  It might be beneficial to
-   promote all operations.  */
-
-#define PROMOTE_FUNCTION_MODE(MODE, UNSIGNEDP, TYPE)	\
- do {						\
-  if (GET_MODE_CLASS (MODE) == MODE_INT		\
-      && GET_MODE_SIZE (MODE) < 8)		\
-   {						\
-     (MODE) = DImode;				\
-     /* Do the following some time later,	\
-	scrutinizing differences.  */		\
-     if (0) (UNSIGNEDP) = 0;			\
-   }						\
- } while (0)
-
 /* We need to align everything to 64 bits that can affect the alignment
    of other types.  Since address N is interpreted in MMIX as (N modulo
    access_size), we must align.  */
Index: gcc/config/mmix/mmix.c
===================================================================
--- gcc/config/mmix/mmix.c	(branch promote-function-mode)
+++ gcc/config/mmix/mmix.c	(working copy)
@@ -134,6 +134,9 @@ static void mmix_file_start (void);
 static void mmix_file_end (void);
 static bool mmix_rtx_costs (rtx, int, int, int *, bool);
 static rtx mmix_struct_value_rtx (tree, int);
+static enum machine_mode mmix_promote_function_mode (const_tree,
+						     enum machine_mode,
+	                                             int *, const_tree, int);
 static bool mmix_pass_by_reference (CUMULATIVE_ARGS *,
 				    enum machine_mode, const_tree, bool);
 
@@ -186,14 +189,9 @@ static bool mmix_pass_by_reference (CUMU
 #undef TARGET_MACHINE_DEPENDENT_REORG
 #define TARGET_MACHINE_DEPENDENT_REORG mmix_reorg
 
-#undef TARGET_PROMOTE_FUNCTION_ARGS
-#define TARGET_PROMOTE_FUNCTION_ARGS hook_bool_const_tree_true
-#if 0
-/* Apparently not doing TRT if int < register-size.  FIXME: Perhaps
-   FUNCTION_VALUE and LIBCALL_VALUE needs tweaking as some ports say.  */
-#undef TARGET_PROMOTE_FUNCTION_RETURN
-#define TARGET_PROMOTE_FUNCTION_RETURN hook_bool_tree_true
-#endif
+#undef TARGET_PROMOTE_FUNCTION_MODE
+#define TARGET_PROMOTE_FUNCTION_MODE mmix_promote_function_mode
+
 
 #undef TARGET_STRUCT_VALUE_RTX
 #define TARGET_STRUCT_VALUE_RTX mmix_struct_value_rtx
@@ -2741,6 +2739,28 @@ mmix_intval (rtx x)
   fatal_insn ("MMIX Internal: This is not a constant:", x);
 }
 
+/* Worker function for TARGET_PROMOTE_FUNCTION_MODE.  */
+
+enum machine_mode
+mmix_promote_function_mode (const_tree type ATTRIBUTE_UNUSED,
+                            enum machine_mode mode,
+                            int *punsignedp ATTRIBUTE_UNUSED,
+                            const_tree fntype ATTRIBUTE_UNUSED,
+                            int for_return)
+{
+  /* Apparently not doing TRT if int < register-size.  FIXME: Perhaps
+     FUNCTION_VALUE and LIBCALL_VALUE needs tweaking as some ports say.  */
+  if (for_return)
+    return mode;
+
+  /* Promotion of modes currently generates slow code, extending before
+     operation, so we do it only for arguments.  */
+  if (GET_MODE_CLASS (mode) == MODE_INT
+      && GET_MODE_SIZE (mode) < 8)
+    return DImode;
+  else
+    return mode;
+}
 /* Worker function for TARGET_STRUCT_VALUE_RTX.  */
 
 static rtx
Index: gcc/config/bfin/bfin.c
===================================================================
--- gcc/config/bfin/bfin.c	(branch promote-function-mode)
+++ gcc/config/bfin/bfin.c	(working copy)
@@ -6233,12 +6233,8 @@ bfin_expand_builtin (tree exp, rtx targe
 #undef TARGET_SCHED_ISSUE_RATE
 #define TARGET_SCHED_ISSUE_RATE bfin_issue_rate
 
-#undef TARGET_PROMOTE_PROTOTYPES
-#define TARGET_PROMOTE_PROTOTYPES hook_bool_const_tree_true
-#undef TARGET_PROMOTE_FUNCTION_ARGS
-#define TARGET_PROMOTE_FUNCTION_ARGS hook_bool_const_tree_true
-#undef TARGET_PROMOTE_FUNCTION_RETURN
-#define TARGET_PROMOTE_FUNCTION_RETURN hook_bool_const_tree_true
+#undef TARGET_PROMOTE_FUNCTION_MODE
+#define TARGET_PROMOTE_FUNCTION_MODE default_promote_function_mode_always_promote
 
 #undef TARGET_ARG_PARTIAL_BYTES
 #define TARGET_ARG_PARTIAL_BYTES bfin_arg_partial_bytes
Index: gcc/config/frv/frv.h
===================================================================
--- gcc/config/frv/frv.h	(branch promote-function-mode)
+++ gcc/config/frv/frv.h	(working copy)
@@ -1784,10 +1784,6 @@ typedef struct frv_stack {
    (Actually, on most machines, scalar values are returned in the same place
    regardless of mode).
 
-   If `TARGET_PROMOTE_FUNCTION_RETURN' is defined to return true, you
-   must apply the same promotion rules specified in `PROMOTE_MODE' if
-   VALTYPE is a scalar type.
-
    If the precise function being called is known, FUNC is a tree node
    (`FUNCTION_DECL') for it; otherwise, FUNC is a null pointer.  This makes it
    possible to use a different value-returning convention for specific
Index: gcc/config/pa/pa.c
===================================================================
--- gcc/config/pa/pa.c	(branch promote-function-mode)
+++ gcc/config/pa/pa.c	(working copy)
@@ -286,8 +286,8 @@ static size_t n_deferred_plabels = 0;
 #define TARGET_INIT_LIBFUNCS pa_hpux_init_libfuncs
 #endif
 
-#undef TARGET_PROMOTE_FUNCTION_RETURN
-#define TARGET_PROMOTE_FUNCTION_RETURN hook_bool_const_tree_true
+#undef TARGET_PROMOTE_FUNCTION_MODE
+#define TARGET_PROMOTE_FUNCTION_MODE pa_promote_function_mode
 #undef TARGET_PROMOTE_PROTOTYPES
 #define TARGET_PROMOTE_PROTOTYPES hook_bool_const_tree_true
 
@@ -9125,11 +9125,25 @@ insn_refs_are_delayed (rtx insn)
 	   && get_attr_type (insn) == TYPE_MILLI));
 }
 
+/* Promote the return value, but not the arguments.  */
+
+enum machine_mode
+pa_promote_function_mode (const_tree type ATTRIBUTE_UNUSED,
+                          enum machine_mode mode,
+                          int *punsignedp ATTRIBUTE_UNUSED,
+                          const_tree fntype ATTRIBUTE_UNUSED,
+                          int for_return)
+{
+  if (!for_return)
+    return mode;
+  return promote_mode (mode, punsignedp, type);
+}
+
 /* On the HP-PA the value is found in register(s) 28(-29), unless
    the mode is SF or DF. Then the value is returned in fr4 (32).
 
-   This must perform the same promotions as PROMOTE_MODE, else
-   TARGET_PROMOTE_FUNCTION_RETURN will not work correctly.
+   This must perform the same promotions as PROMOTE_MODE, else promoting
+   return values in TARGET_PROMOTE_FUNCTION_MODE will not work correctly.
 
    Small structures must be returned in a PARALLEL on PA64 in order
    to match the HP Compiler ABI.  */
Index: gcc/doc/tm.texi
===================================================================
--- gcc/doc/tm.texi	(branch promote-function-mode)
+++ gcc/doc/tm.texi	(working copy)
@@ -1039,29 +1039,22 @@ sign-extend the result to 64 bits.  On s
 Do not define this macro if it would never modify @var{m}.
 @end defmac
 
-@defmac PROMOTE_FUNCTION_MODE
-Like @code{PROMOTE_MODE}, but is applied to outgoing function arguments or
-function return values, as specified by @code{TARGET_PROMOTE_FUNCTION_ARGS}
-and @code{TARGET_PROMOTE_FUNCTION_RETURN}, respectively.
-
-The default is @code{PROMOTE_MODE}.
-@end defmac
-
-@deftypefn {Target Hook} bool TARGET_PROMOTE_FUNCTION_ARGS (tree @var{fntype})
-This target hook should return @code{true} if the promotion described by
-@code{PROMOTE_FUNCTION_MODE} should be done for outgoing function
-arguments.
-@end deftypefn
-
-@deftypefn {Target Hook} bool TARGET_PROMOTE_FUNCTION_RETURN (tree @var{fntype})
-This target hook should return @code{true} if the promotion described by
-@code{PROMOTE_FUNCTION_MODE} should be done for the return value of
-functions.
-
-If this target hook returns @code{true}, @code{TARGET_FUNCTION_VALUE}
-must perform the same promotions done by @code{PROMOTE_FUNCTION_MODE}.
+@deftypefn {Target Hook} enum machine_mode TARGET_PROMOTE_FUNCTION_MODE (tree @var{type}, enum machine_mode @var{mode}, int *@var{punsignedp}, tree @var{funtype}, int @var{for_return})
+Like @code{PROMOTE_MODE}, but it is applied to outgoing function arguments or
+function return values.  The target hook should return the new mode
+and possibly change @code{*@var{punsignedp}} if the promotion should
+change signedness.  This function is called only for scalar @emph{or
+pointer} types.
+
+The default is to not promote arguments and return values.  You can
+also define the hook to @code{default_promote_function_mode_always_promote}
+if you would like to apply the same rules given by @code{PROMOTE_MODE}.
+
+@var{for_return} allows to distinguish the promotion of arguments and
+return values.  If this target hook promotes return values,
+@code{TARGET_FUNCTION_VALUE} must perform the same promotions done here.
 @end deftypefn
 
 @defmac PARM_BOUNDARY
 Normal alignment required for function parameters on the stack, in
 bits.  All stack parameters receive at least this much alignment
Index: gcc/system.h
===================================================================
--- gcc/system.h	(branch promote-function-mode)
+++ gcc/system.h	(working copy)
@@ -672,7 +672,7 @@ extern void fancy_abort (const char *, i
 	DIVDI3_LIBCALL UDIVSI3_LIBCALL UDIVDI3_LIBCALL MODSI3_LIBCALL	\
 	MODDI3_LIBCALL UMODSI3_LIBCALL UMODDI3_LIBCALL BUILD_VA_LIST_TYPE \
 	PRETEND_OUTGOING_VARARGS_NAMED STRUCT_VALUE_INCOMING_REGNUM	\
-	ASM_OUTPUT_SECTION_NAME PROMOTE_FUNCTION_ARGS			\
+	ASM_OUTPUT_SECTION_NAME PROMOTE_FUNCTION_ARGS PROMOTE_FUNCTION_MODE \
 	STRUCT_VALUE_INCOMING STRICT_ARGUMENT_NAMING			\
 	PROMOTE_FUNCTION_RETURN PROMOTE_PROTOTYPES STRUCT_VALUE_REGNUM	\
 	SETUP_INCOMING_VARARGS EXPAND_BUILTIN_SAVEREGS			\
@@ -742,7 +742,8 @@ extern void fancy_abort (const char *, i
 	LANG_HOOKS_TREE_INLINING_ESTIMATE_NUM_INSNS \
 	LANG_HOOKS_PUSHLEVEL LANG_HOOKS_SET_BLOCK \
 	LANG_HOOKS_MAYBE_BUILD_CLEANUP LANG_HOOKS_UPDATE_DECL_AFTER_SAVING \
-	LANG_HOOKS_POPLEVEL LANG_HOOKS_TRUTHVALUE_CONVERSION
+	LANG_HOOKS_POPLEVEL LANG_HOOKS_TRUTHVALUE_CONVERSION \
+	TARGET_PROMOTE_FUNCTION_ARGS TARGET_PROMOTE_FUNCTION_RETURN
 
 /* Miscellaneous macros that are no longer used.  */
  #pragma GCC poison USE_MAPPED_LOCATION



More information about the Gcc-patches mailing list