2009-04-17 Paolo Bonzini <bonzini@gnu.org>
authorbonzini <bonzini@138bc75d-0d04-0410-961f-82ee72b054a4>
Sat, 1 Aug 2009 22:03:34 +0000 (22:03 +0000)
committerbonzini <bonzini@138bc75d-0d04-0410-961f-82ee72b054a4>
Sat, 1 Aug 2009 22:03:34 +0000 (22:03 +0000)
* expr.c (store_constructor): Use promote_decl_mode.  Remove
now write-only variable unsignedp.
(expand_expr_real_1): Use promote_decl_mode.
* expr.h (promote_function_mode, promote_decl_mode): New.
(promote_mode): Remove last argument.
* function.c (assign_temp): Drop last argument of promote_mode.
(assign_parm_find_data_types): Use promote_function_mode.
(assign_parm_setup_reg): Likewise.
(expand_function_end): Use promote_function_mode.
* calls.c (initialize_argument_information): Use promote_function_mode.
(precompute_arguments): Use promote_mode instead of checking if
only PROMOTE_FUNCTION_MODE is defined.
(expand_call): When making sibcall decisions, use promote_function_mode.
Below, remove an if for targetm.calls.promote_function_return and
and use promote_function_mode.
(emit_library_call_value_1): Use promote_function_mode, fix bug
where promote_mode was passed FOR_CALL == 0 for a return value in an
assertion.
* cfgexpand.c (expand_one_register_var): Use promote_decl_mode.
* explow.c (promote_function_mode, promote_decl_mode): New.
(promote_mode): Keep only the FOR_CALL == 0 case.
* combine.c (setup_incoming_promotion): Remove test of
promote_function_args.  Use promote_function_mode.
* stmt.c (expand_value_return): Use promote_decl_mode.
(expand_decl): Use promote_decl_mode.

* expr.c (store_constructor): Use promote_decl_mode.  Remove
now write-only variable unsignedp.
(expand_expr_real_1): Use promote_decl_mode.
* expr.h (promote_function_mode, promote_decl_mode): New.
(promote_mode): Remove last argument.
* function.c (assign_temp): Drop last argument of promote_mode.
(assign_parm_find_data_types): Use promote_function_mode.
(assign_parm_setup_reg): Likewise.
(expand_function_end): Use promote_function_mode.
* calls.c (initialize_argument_information): Use promote_function_mode.
(precompute_arguments): Use promote_mode instead of checking if
only PROMOTE_FUNCTION_MODE is defined.
(expand_call): When making sibcall decisions, use promote_function_mode.
Below, remove an if for targetm.calls.promote_function_return and
and use promote_function_mode.
(emit_library_call_value_1): Use promote_function_mode, fix bug
where promote_mode was passed FOR_CALL == 0 for a return value in an
assertion.
* cfgexpand.c (expand_one_register_var): Use promote_decl_mode.
* explow.c (promote_function_mode, promote_decl_mode): New.
(promote_mode): Keep only the FOR_CALL == 0 case.
* combine.c (setup_incoming_promotion): Remove test of
promote_function_args.  Use promote_function_mode.
* stmt.c (expand_value_return): Use promote_decl_mode.
(expand_decl): Use promote_decl_mode.

* 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.

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

48 files changed:
gcc/ChangeLog
gcc/calls.c
gcc/cfgexpand.c
gcc/combine.c
gcc/config/alpha/alpha.c
gcc/config/arc/arc.c
gcc/config/arm/arm.c
gcc/config/arm/arm.h
gcc/config/bfin/bfin.c
gcc/config/cris/cris.c
gcc/config/cris/cris.h
gcc/config/frv/frv.h
gcc/config/ia64/ia64.c
gcc/config/iq2000/iq2000.c
gcc/config/mcore/mcore.c
gcc/config/mips/mips-protos.h
gcc/config/mips/mips.c
gcc/config/mips/mips.h
gcc/config/mmix/mmix.c
gcc/config/mmix/mmix.h
gcc/config/pa/pa.c
gcc/config/picochip/picochip.c
gcc/config/rs6000/rs6000.c
gcc/config/s390/s390-protos.h
gcc/config/s390/s390.c
gcc/config/s390/s390.h
gcc/config/score/score.c
gcc/config/score/score3.c
gcc/config/score/score7.c
gcc/config/sh/sh-protos.h
gcc/config/sh/sh.c
gcc/config/sparc/sparc.c
gcc/config/sparc/sparc.h
gcc/config/stormy16/stormy16.c
gcc/config/xtensa/xtensa.c
gcc/config/xtensa/xtensa.h
gcc/doc/tm.texi
gcc/explow.c
gcc/expr.c
gcc/expr.h
gcc/function.c
gcc/stmt.c
gcc/system.h
gcc/target-def.h
gcc/target.h
gcc/targhooks.c
gcc/targhooks.h
gcc/tree-outof-ssa.c

index 2d3a15f..b75113f 100644 (file)
@@ -1,3 +1,130 @@
+2009-04-17  Paolo Bonzini  <bonzini@gnu.org>
+
+       * expr.c (store_constructor): Use promote_decl_mode.  Remove
+       now write-only variable unsignedp.
+       (expand_expr_real_1): Use promote_decl_mode.
+       * expr.h (promote_function_mode, promote_decl_mode): New.
+       (promote_mode): Remove last argument.
+       * function.c (assign_temp): Drop last argument of promote_mode.
+       (assign_parm_find_data_types): Use promote_function_mode.
+       (assign_parm_setup_reg): Likewise.
+       (expand_function_end): Use promote_function_mode.
+       * calls.c (initialize_argument_information): Use promote_function_mode.
+       (precompute_arguments): Use promote_mode instead of checking if
+       only PROMOTE_FUNCTION_MODE is defined.
+       (expand_call): When making sibcall decisions, use promote_function_mode.
+       Below, remove an if for targetm.calls.promote_function_return and
+       and use promote_function_mode.
+       (emit_library_call_value_1): Use promote_function_mode, fix bug
+       where promote_mode was passed FOR_CALL == 0 for a return value in an
+       assertion.
+       * cfgexpand.c (expand_one_register_var): Use promote_decl_mode.
+       * explow.c (promote_function_mode, promote_decl_mode): New.
+       (promote_mode): Keep only the FOR_CALL == 0 case.
+       * combine.c (setup_incoming_promotion): Remove test of
+       promote_function_args.  Use promote_function_mode.
+       * stmt.c (expand_value_return): Use promote_decl_mode.
+       (expand_decl): Use promote_decl_mode.
+
+       * expr.c (store_constructor): Use promote_decl_mode.  Remove
+       now write-only variable unsignedp.
+       (expand_expr_real_1): Use promote_decl_mode.
+       * expr.h (promote_function_mode, promote_decl_mode): New.
+       (promote_mode): Remove last argument.
+       * function.c (assign_temp): Drop last argument of promote_mode.
+       (assign_parm_find_data_types): Use promote_function_mode.
+       (assign_parm_setup_reg): Likewise.
+       (expand_function_end): Use promote_function_mode.
+       * calls.c (initialize_argument_information): Use promote_function_mode.
+       (precompute_arguments): Use promote_mode instead of checking if
+       only PROMOTE_FUNCTION_MODE is defined.
+       (expand_call): When making sibcall decisions, use promote_function_mode.
+       Below, remove an if for targetm.calls.promote_function_return and
+       and use promote_function_mode.
+       (emit_library_call_value_1): Use promote_function_mode, fix bug
+       where promote_mode was passed FOR_CALL == 0 for a return value in an
+       assertion.
+       * cfgexpand.c (expand_one_register_var): Use promote_decl_mode.
+       * explow.c (promote_function_mode, promote_decl_mode): New.
+       (promote_mode): Keep only the FOR_CALL == 0 case.
+       * combine.c (setup_incoming_promotion): Remove test of
+       promote_function_args.  Use promote_function_mode.
+       * stmt.c (expand_value_return): Use promote_decl_mode.
+       (expand_decl): Use promote_decl_mode.
+
+       * 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.
+
 2009-08-01  Sebastian Pop  <sebastian.pop@amd.com>
 
        * doc/invoke.texi (-fgraphite-force-parallel): Renamed
index bac4f8b..6d186c5 100644 (file)
@@ -1122,13 +1122,9 @@ initialize_argument_information (int num_actuals ATTRIBUTE_UNUSED,
            }
        }
 
-      mode = TYPE_MODE (type);
       unsignedp = TYPE_UNSIGNED (type);
-
-      if (targetm.calls.promote_function_args (fndecl
-                                              ? TREE_TYPE (fndecl)
-                                              : fntype))
-       mode = promote_mode (type, mode, &unsignedp, 1);
+      mode = promote_function_mode (type, TYPE_MODE (type), &unsignedp,
+                                   fndecl ? TREE_TYPE (fndecl) : fntype, 0);
 
       args[i].unsignedp = unsignedp;
       args[i].mode = mode;
@@ -1308,29 +1304,33 @@ precompute_arguments (int num_actuals, struct arg_data *args)
 
   for (i = 0; i < num_actuals; i++)
     {
+      tree type;
       enum machine_mode mode;
 
       if (TREE_CODE (args[i].tree_value) != CALL_EXPR)
        continue;
 
       /* If this is an addressable type, we cannot pre-evaluate it.  */
-      gcc_assert (!TREE_ADDRESSABLE (TREE_TYPE (args[i].tree_value)));
+      type = TREE_TYPE (args[i].tree_value);
+      gcc_assert (!TREE_ADDRESSABLE (type));
 
       args[i].initial_value = args[i].value
        = expand_normal (args[i].tree_value);
 
-      mode = TYPE_MODE (TREE_TYPE (args[i].tree_value));
+      mode = TYPE_MODE (type);
       if (mode != args[i].mode)
        {
+         int unsignedp = args[i].unsignedp;
          args[i].value
            = convert_modes (args[i].mode, mode,
                             args[i].value, args[i].unsignedp);
-#if defined(PROMOTE_FUNCTION_MODE) && !defined(PROMOTE_MODE)
+
          /* CSE will replace this only if it contains args[i].value
             pseudo, so convert it down to the declared mode using
             a SUBREG.  */
          if (REG_P (args[i].value)
-             && GET_MODE_CLASS (args[i].mode) == MODE_INT)
+             && GET_MODE_CLASS (args[i].mode) == MODE_INT
+             && promote_mode (type, mode, &unsignedp) != args[i].mode)
            {
              args[i].initial_value
                = gen_lowpart_SUBREG (mode, args[i].value);
@@ -1338,7 +1338,6 @@ precompute_arguments (int num_actuals, struct arg_data *args)
              SUBREG_PROMOTED_UNSIGNED_SET (args[i].initial_value,
                                            args[i].unsignedp);
            }
-#endif
        }
     }
 }
@@ -2346,17 +2345,17 @@ expand_call (tree exp, rtx target, int ignore)
       tree caller_res = DECL_RESULT (current_function_decl);
 
       caller_unsignedp = TYPE_UNSIGNED (TREE_TYPE (caller_res));
-      caller_mode = caller_promoted_mode = DECL_MODE (caller_res);
+      caller_mode = DECL_MODE (caller_res);
       callee_unsignedp = TYPE_UNSIGNED (TREE_TYPE (funtype));
-      callee_mode = callee_promoted_mode = TYPE_MODE (TREE_TYPE (funtype));
-      if (targetm.calls.promote_function_return (TREE_TYPE (current_function_decl)))
-       caller_promoted_mode
-         = promote_mode (TREE_TYPE (caller_res), caller_mode,
-                         &caller_unsignedp, 1);
-      if (targetm.calls.promote_function_return (funtype))
-       callee_promoted_mode
-         = promote_mode (TREE_TYPE (funtype), callee_mode,
-                         &callee_unsignedp, 1);
+      callee_mode = TYPE_MODE (TREE_TYPE (funtype));
+      caller_promoted_mode
+       = promote_function_mode (TREE_TYPE (caller_res), caller_mode,
+                                &caller_unsignedp,
+                                TREE_TYPE (current_function_decl), 1);
+      callee_promoted_mode
+       = promote_function_mode (TREE_TYPE (caller_res), callee_mode,
+                                &callee_unsignedp,
+                                TREE_TYPE (funtype), 1);
       if (caller_mode != VOIDmode
          && (caller_promoted_mode != callee_promoted_mode
              || ((caller_mode != caller_promoted_mode
@@ -3030,38 +3029,37 @@ expand_call (tree exp, rtx target, int ignore)
       else
        target = copy_to_reg (avoid_likely_spilled_reg (valreg));
 
-      if (targetm.calls.promote_function_return(funtype))
+      /* If we promoted this return value, make the proper SUBREG.
+         TARGET might be const0_rtx here, so be careful.  */
+      if (REG_P (target)
+         && TYPE_MODE (TREE_TYPE (exp)) != BLKmode
+         && GET_MODE (target) != TYPE_MODE (TREE_TYPE (exp)))
        {
-         /* If we promoted this return value, make the proper SUBREG.
-            TARGET might be const0_rtx here, so be careful.  */
-         if (REG_P (target)
-             && TYPE_MODE (TREE_TYPE (exp)) != BLKmode
-             && GET_MODE (target) != TYPE_MODE (TREE_TYPE (exp)))
+         tree type = TREE_TYPE (exp);
+         int unsignedp = TYPE_UNSIGNED (type);
+         int offset = 0;
+         enum machine_mode pmode;
+
+         /* Ensure we promote as expected, and get the new unsignedness.  */
+         pmode = promote_function_mode (type, TYPE_MODE (type), &unsignedp,
+                                        funtype, 1);
+         gcc_assert (GET_MODE (target) == pmode);
+
+         if ((WORDS_BIG_ENDIAN || BYTES_BIG_ENDIAN)
+             && (GET_MODE_SIZE (GET_MODE (target))
+                 > GET_MODE_SIZE (TYPE_MODE (type))))
            {
-             tree type = TREE_TYPE (exp);
-             int unsignedp = TYPE_UNSIGNED (type);
-             int offset = 0;
-             enum machine_mode pmode;
-
-             pmode = promote_mode (type, TYPE_MODE (type), &unsignedp, 1);
-             /* If we don't promote as expected, something is wrong.  */
-             gcc_assert (GET_MODE (target) == pmode);
-
-             if ((WORDS_BIG_ENDIAN || BYTES_BIG_ENDIAN)
-                 && (GET_MODE_SIZE (GET_MODE (target))
-                     > GET_MODE_SIZE (TYPE_MODE (type))))
-               {
-                 offset = GET_MODE_SIZE (GET_MODE (target))
-                   - GET_MODE_SIZE (TYPE_MODE (type));
-                 if (! BYTES_BIG_ENDIAN)
-                   offset = (offset / UNITS_PER_WORD) * UNITS_PER_WORD;
-                 else if (! WORDS_BIG_ENDIAN)
-                   offset %= UNITS_PER_WORD;
-               }
-             target = gen_rtx_SUBREG (TYPE_MODE (type), target, offset);
-             SUBREG_PROMOTED_VAR_P (target) = 1;
-             SUBREG_PROMOTED_UNSIGNED_SET (target, unsignedp);
+             offset = GET_MODE_SIZE (GET_MODE (target))
+               - GET_MODE_SIZE (TYPE_MODE (type));
+             if (! BYTES_BIG_ENDIAN)
+               offset = (offset / UNITS_PER_WORD) * UNITS_PER_WORD;
+             else if (! WORDS_BIG_ENDIAN)
+               offset %= UNITS_PER_WORD;
            }
+
+         target = gen_rtx_SUBREG (TYPE_MODE (type), target, offset);
+         SUBREG_PROMOTED_VAR_P (target) = 1;
+         SUBREG_PROMOTED_UNSIGNED_SET (target, unsignedp);
        }
 
       /* If size of args is variable or this was a constructor call for a stack
@@ -3876,15 +3874,14 @@ emit_library_call_value_1 (int retval, rtx orgfun, rtx value,
        }
       else
        {
-         /* Convert to the proper mode if PROMOTE_MODE has been active.  */
+         /* Convert to the proper mode if a promotion has been active.  */
          if (GET_MODE (valreg) != outmode)
            {
              int unsignedp = TYPE_UNSIGNED (tfom);
 
-             gcc_assert (targetm.calls.promote_function_return (tfom));
-             gcc_assert (promote_mode (tfom, outmode, &unsignedp, 0)
+             gcc_assert (promote_function_mode (tfom, outmode, &unsignedp,
+                                                fndecl ? TREE_TYPE (fndecl) : fntype, 1)
                          == GET_MODE (valreg));
-
              valreg = convert_modes (outmode, GET_MODE (valreg), valreg, 0);
            }
 
index c172c96..07d6dd3 100644 (file)
@@ -1202,9 +1202,7 @@ expand_one_register_var (tree var)
 {
   tree decl = SSAVAR (var);
   tree type = TREE_TYPE (decl);
-  int unsignedp = TYPE_UNSIGNED (type);
-  enum machine_mode reg_mode
-    = promote_mode (type, DECL_MODE (decl), &unsignedp, 0);
+  enum machine_mode reg_mode = promote_decl_mode (decl, NULL);
   rtx x = gen_reg_rtx (reg_mode);
 
   set_rtl (var, x);
index 3f39bc3..6a0e6ec 100644 (file)
@@ -1333,9 +1333,6 @@ setup_incoming_promotions (rtx first)
   tree arg;
   bool strictly_local = false;
 
-  if (!targetm.calls.promote_function_args (TREE_TYPE (cfun->decl)))
-    return;
-
   for (arg = DECL_ARGUMENTS (current_function_decl); arg;
        arg = TREE_CHAIN (arg))
     {
@@ -1365,7 +1362,8 @@ setup_incoming_promotions (rtx first)
 
       /* The mode and signedness of the argument as it is actually passed, 
          after any TARGET_PROMOTE_FUNCTION_ARGS-driven ABI promotions.  */
-      mode3 = promote_mode (DECL_ARG_TYPE (arg), mode2, &uns3, 1);
+      mode3 = promote_function_mode (DECL_ARG_TYPE (arg), mode2, &uns3,
+                                    TREE_TYPE (cfun->decl), 0);
 
       /* The mode of the register in which the argument is being passed.  */
       mode4 = GET_MODE (reg);
index a9f5fba..f250e14 100644 (file)
@@ -10818,10 +10818,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 66709c7..f53c898 100644 (file)
@@ -133,10 +133,8 @@ static const struct attribute_spec arc_attribute_table[] =
 #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 3be2126..83db0ec 100644 (file)
@@ -125,6 +125,8 @@ static int arm_adjust_cost (rtx, rtx, rtx, int);
 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);
@@ -329,10 +331,8 @@ static const struct attribute_spec arm_attribute_table[] =
 #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
@@ -3072,7 +3072,7 @@ arm_canonicalize_comparison (enum rtx_code code, enum machine_mode mode,
 /* 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;
@@ -3081,7 +3081,7 @@ arm_function_value(const_tree type, const_tree func ATTRIBUTE_UNUSED)
   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.  */
@@ -19094,6 +19094,19 @@ arm_promote_prototypes (const_tree t ATTRIBUTE_UNUSED)
     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 58ced2e..082b5fa 100644 (file)
@@ -501,11 +501,6 @@ extern int arm_arch_hwdiv;
       (MODE) = SImode;                         \
     }
 
-#define PROMOTE_FUNCTION_MODE(MODE, UNSIGNEDP, TYPE)   \
-  if (GET_MODE_CLASS (MODE) == MODE_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 4f21306..1388748 100644 (file)
@@ -6296,12 +6296,8 @@ bfin_expand_builtin (tree exp, rtx target ATTRIBUTE_UNUSED,
 #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 66fc05d..a9fe9de 100644 (file)
@@ -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 *);
@@ -166,8 +169,9 @@ int cris_cpu_version = CRIS_DEFAULT_CPU_VERSION;
 #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
@@ -3753,6 +3757,25 @@ cris_pass_by_reference (CUMULATIVE_ARGS *ca ATTRIBUTE_UNUSED,
          || 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 920e354..3929107 100644 (file)
@@ -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 483ed77..dfb3fb8 100644 (file)
@@ -1764,10 +1764,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 b2e950e..71acdab 100644 (file)
@@ -459,14 +459,8 @@ static const struct attribute_spec ia64_attribute_table[] =
 
 /* ??? 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 b99043e..ff0c868 100644 (file)
@@ -189,10 +189,8 @@ static bool iq2000_legitimate_address_p (enum machine_mode, rtx, bool);
 #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
 
@@ -2186,15 +2184,14 @@ iq2000_select_section (tree decl, int reloc ATTRIBUTE_UNUSED,
    FUNC.  */
 
 rtx
-iq2000_function_value (const_tree valtype, const_tree func ATTRIBUTE_UNUSED)
+iq2000_function_value (const_tree valtype, const_tree func)
 {
   int reg = GP_RETURN;
   enum machine_mode mode = TYPE_MODE (valtype);
   int unsignedp = TYPE_UNSIGNED (valtype);
 
-  /* Since we define TARGET_PROMOTE_FUNCTION_RETURN that returns true,
-     we must promote the mode just as PROMOTE_MODE does.  */
-  mode = promote_mode (valtype, mode, &unsignedp, 1);
+  /* Since we promote return types, we must promote the mode here too.  */
+  mode = promote_function_mode (valtype, mode, &unsignedp, func, 1);
 
   return gen_rtx_REG (mode, reg);
 }
index 3b0adef..170b4b0 100644 (file)
@@ -192,10 +192,8 @@ static const struct attribute_spec mcore_attribute_table[] =
 #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
 
@@ -2730,14 +2728,15 @@ handle_structs_in_regs (enum machine_mode mode, const_tree type, int reg)
 }
 
 rtx
-mcore_function_value (const_tree valtype, const_tree func ATTRIBUTE_UNUSED)
+mcore_function_value (const_tree valtype, const_tree func)
 {
   enum machine_mode mode;
   int unsigned_p;
   
   mode = TYPE_MODE (valtype);
 
-  mode = promote_mode (valtype, mode, &unsigned_p, 1);
+  /* Since we promote return types, we must promote the mode here too.  */
+  mode = promote_function_mode (valtype, mode, &unsignedp, func, 1);
   
   return handle_structs_in_regs (mode, valtype, FIRST_RET_REG);
 }
index d5d6eee..222cb89 100644 (file)
@@ -279,7 +279,7 @@ extern void mips_expand_prologue (void);
 extern void mips_expand_before_return (void);
 extern void mips_expand_epilogue (bool);
 extern bool mips_can_use_return_insn (void);
-extern rtx mips_function_value (const_tree, enum machine_mode);
+extern rtx mips_function_value (const_tree, const_tree, enum machine_mode);
 
 extern bool mips_cannot_change_mode_class (enum machine_mode,
                                           enum machine_mode, enum reg_class);
index 4a10fb4..083b253 100644 (file)
@@ -4976,7 +4976,7 @@ mips_return_fpr_pair (enum machine_mode mode,
    VALTYPE is null and MODE is the mode of the return value.  */
 
 rtx
-mips_function_value (const_tree valtype, enum machine_mode mode)
+mips_function_value (const_tree valtype, const_tree func, enum machine_mode mode)
 {
   if (valtype)
     {
@@ -4986,9 +4986,9 @@ mips_function_value (const_tree valtype, enum machine_mode mode)
       mode = TYPE_MODE (valtype);
       unsigned_p = TYPE_UNSIGNED (valtype);
 
-      /* Since TARGET_PROMOTE_FUNCTION_RETURN unconditionally returns true,
-        we must promote the mode just as PROMOTE_MODE does.  */
-      mode = promote_mode (valtype, mode, &unsigned_p, 1);
+      /* Since TARGET_PROMOTE_FUNCTION_MODE unconditionally promotes,
+        return values, promote the mode here too.  */
+      mode = promote_function_mode (valtype, mode, &unsigned_p, func, 1);
 
       /* Handle structures whose fields are returned in $f0/$f2.  */
       switch (mips_fpr_return_fields (valtype, fields))
@@ -14851,10 +14851,8 @@ mips_final_postscan_insn (FILE *file, rtx insn, rtx *opvec, int noperands)
 #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 a3ab2f8..8515ce1 100644 (file)
@@ -2204,10 +2204,10 @@ enum reg_class
 #define FP_ARG_LAST  (FP_ARG_FIRST + MAX_ARGS_IN_REGISTERS - 1)
 
 #define LIBCALL_VALUE(MODE) \
-  mips_function_value (NULL_TREE, MODE)
+  mips_function_value (NULL_TREE, NULL_TREE, MODE)
 
 #define FUNCTION_VALUE(VALTYPE, FUNC) \
-  mips_function_value (VALTYPE, VOIDmode)
+  mips_function_value (VALTYPE, FUNC, VOIDmode)
 
 /* 1 if N is a possible register number for a function value.
    On the MIPS, R2 R3 and F0 F2 are the only register thus used.
index 67b1b23..9e94279 100644 (file)
@@ -135,6 +135,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);
 static bool mmix_frame_pointer_required (void);
@@ -188,14 +191,9 @@ static bool mmix_frame_pointer_required (void);
 #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
@@ -2692,6 +2690,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 72e3568..4146654 100644 (file)
@@ -182,23 +182,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 8e8db86..bbd09f5 100644 (file)
@@ -285,8 +285,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
 
@@ -9187,11 +9187,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 358ef71..ecec1f7 100644 (file)
@@ -254,10 +254,8 @@ static char picochip_get_vliw_alu_id (void);
 #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
 
@@ -4144,7 +4142,7 @@ warn_of_byte_access (void)
 }
 \f
 rtx
-picochip_function_value (const_tree valtype, const_tree func ATTRIBUTE_UNUSED,
+picochip_function_value (const_tree valtype, const_tree func,
                          bool outgoing ATTRIBUTE_UNUSED)
 {
   enum machine_mode mode = TYPE_MODE (valtype);
@@ -4152,7 +4150,7 @@ picochip_function_value (const_tree valtype, const_tree func ATTRIBUTE_UNUSED,
 
   /* Since we define PROMOTE_FUNCTION_RETURN, we must promote the mode
      just as PROMOTE_MODE does.  */
-  mode = promote_mode (valtype, mode, &unsignedp, 1);
+  mode = promote_function_mode (valtype, mode, &unsignedp, func, 1);
 
   return gen_rtx_REG (mode, 0);
 
index 25cacc4..8c0feb5 100644 (file)
@@ -1347,10 +1347,8 @@ static const struct attribute_spec rs6000_attribute_table[] =
 
 /* 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 2329138..8b9ad5a 100644 (file)
@@ -125,6 +125,6 @@ extern void s390_function_arg_advance (CUMULATIVE_ARGS *, enum machine_mode,
                                       tree, int);
 #ifdef RTX_CODE
 extern rtx s390_function_arg (CUMULATIVE_ARGS *, enum machine_mode, tree, int);
-extern rtx s390_function_value (const_tree, enum machine_mode);
+extern rtx s390_function_value (const_tree, const_tree, enum machine_mode);
 #endif /* RTX_CODE */
 #endif /* TREE_CODE */
index f5b2fa7..25203ab 100644 (file)
@@ -8343,17 +8343,36 @@ s390_return_in_memory (const_tree type, const_tree fundecl ATTRIBUTE_UNUSED)
   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.  */
 
 rtx
-s390_function_value (const_tree type, enum machine_mode mode)
+s390_function_value (const_tree type, const_tree fn, enum machine_mode mode)
 {
   if (type)
     {
       int unsignedp = TYPE_UNSIGNED (type);
-      mode = promote_mode (type, TYPE_MODE (type), &unsignedp, 1);
+      mode = promote_function_mode (type, TYPE_MODE (type), &unsignedp, fn, 1);
     }
 
   gcc_assert (GET_MODE_CLASS (mode) == MODE_INT || SCALAR_FLOAT_MODE_P (mode));
@@ -9998,10 +10017,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 f34b7f2..4772367 100644 (file)
@@ -216,13 +216,6 @@ extern int s390_arch_flags;
 #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)
 
@@ -697,10 +690,10 @@ CUMULATIVE_ARGS;
 /* Scalar return values.  */
 
 #define FUNCTION_VALUE(VALTYPE, FUNC) \
-  s390_function_value ((VALTYPE), VOIDmode)
+  s390_function_value ((VALTYPE), (FUNC), VOIDmode)
 
 #define LIBCALL_VALUE(MODE) \
-  s390_function_value (NULL, (MODE))
+  s390_function_value (NULL, NULL, (MODE))
 
 /* Only gpr 2 and fpr 0 are ever used as return registers.  */
 #define FUNCTION_VALUE_REGNO_P(N) ((N) == 2 || (N) == 16)
index b75f3cf..0241383 100644 (file)
 #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 4258d29..385620d 100644 (file)
@@ -859,15 +859,14 @@ score3_function_arg (const CUMULATIVE_ARGS *cum, enum machine_mode mode,
    VALTYPE is the return type and MODE is VOIDmode.  For libcalls,
    VALTYPE is null and MODE is the mode of the return value.  */
 rtx
-score3_function_value (tree valtype, tree func ATTRIBUTE_UNUSED,
-                       enum machine_mode mode)
+score3_function_value (tree valtype, tree func, enum machine_mode mode)
 {
   if (valtype)
     {
       int unsignedp;
       mode = TYPE_MODE (valtype);
       unsignedp = TYPE_UNSIGNED (valtype);
-      mode = promote_mode (valtype, mode, &unsignedp, 1);
+      mode = promote_function_mode (valtype, mode, &unsignedp, func, 1);
     }
   return gen_rtx_REG (mode, RT_REGNUM);
 }
index 9ab6ebd..368ac03 100644 (file)
@@ -850,15 +850,14 @@ score7_function_arg (const CUMULATIVE_ARGS *cum, enum machine_mode mode,
    VALTYPE is the return type and MODE is VOIDmode.  For libcalls,
    VALTYPE is null and MODE is the mode of the return value.  */
 rtx
-score7_function_value (tree valtype, tree func ATTRIBUTE_UNUSED,
-                       enum machine_mode mode)
+score7_function_value (tree valtype, tree func, enum machine_mode mode)
 {
   if (valtype)
     {
       int unsignedp;
       mode = TYPE_MODE (valtype);
       unsignedp = TYPE_UNSIGNED (valtype);
-      mode = promote_mode (valtype, mode, &unsignedp, 1);
+      mode = promote_function_mode (valtype, mode, &unsignedp, func, 1);
     }
   return gen_rtx_REG (mode, RT_REGNUM);
 }
index 35cd730..dec662b 100644 (file)
@@ -166,6 +166,8 @@ 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 rtx sh_dwarf_register_span (rtx);
+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 5b555f8..9c919d0 100644 (file)
@@ -438,9 +438,7 @@ static const struct attribute_spec sh_attribute_table[] =
 #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
@@ -7896,6 +7894,16 @@ sh_dwarf_register_span (rtx reg)
                                              DBX_REGISTER_NUMBER (regno))));
 }
 
+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 baba1d9..52cbe70 100644 (file)
@@ -404,6 +404,8 @@ static int get_some_local_dynamic_name_1 (rtx *, void *);
 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);
@@ -524,17 +526,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
@@ -4642,6 +4635,36 @@ sparc_promote_prototypes (const_tree fntype ATTRIBUTE_UNUSED)
   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))
+    {
+      *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
@@ -5784,7 +5807,8 @@ function_value (const_tree type, enum machine_mode mode, int incoming_p)
            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 31c7409..3b71361 100644 (file)
@@ -636,16 +636,6 @@ extern struct sparc_cpu_select sparc_select[];
    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 2e646f9..06b96c7 100644 (file)
@@ -2640,10 +2640,8 @@ xstormy16_return_in_memory (const_tree type, const_tree fntype ATTRIBUTE_UNUSED)
 #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 38f300a..77ba2d9 100644 (file)
@@ -185,10 +185,8 @@ static const int reg_nonleaf_alloc_order[FIRST_PSEUDO_REGISTER] =
 #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 a9987c7..84d320b 100644 (file)
@@ -582,7 +582,7 @@ extern const enum reg_class xtensa_regno_to_class[FIRST_PSEUDO_REGISTER];
 
 /* 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 8157714..bb4f61b 100644 (file)
@@ -1039,27 +1039,20 @@ sign-extend the result to 64 bits.  On such machines, set
 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
index 198df22..0a26164 100644 (file)
@@ -749,63 +749,96 @@ copy_to_suggested_reg (rtx x, rtx target, enum machine_mode mode)
   return temp;
 }
 \f
-/* Return the mode to use to store a scalar of TYPE and MODE.
+/* Return the mode to use to pass or return 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.
 
-   FOR_CALL is nonzero if this call is promoting args for a call.  */
+   FOR_RETURN is nonzero if the caller is promoting the return value
+   of FNDECL, else it is for promoting args.  */
 
-#if defined(PROMOTE_MODE) && !defined(PROMOTE_FUNCTION_MODE)
-#define PROMOTE_FUNCTION_MODE PROMOTE_MODE
-#endif
+enum machine_mode
+promote_function_mode (const_tree type, enum machine_mode mode, int *punsignedp,
+                      const_tree funtype, int for_return)
+{
+  gcc_assert (GET_MODE_CLASS (mode) != MODE_COMPLEX_INT);
+  switch (TREE_CODE (type))
+    {
+    case INTEGER_TYPE:   case ENUMERAL_TYPE:   case BOOLEAN_TYPE:
+    case REAL_TYPE:      case OFFSET_TYPE:     case FIXED_POINT_TYPE:
+    case POINTER_TYPE:   case REFERENCE_TYPE:
+      return targetm.calls.promote_function_mode (type, mode, punsignedp, funtype,
+                                                 for_return);
+
+    default:
+      return mode;
+    }
+}
+/* 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.  */
 
 enum machine_mode
-promote_mode (const_tree type, enum machine_mode mode, int *punsignedp,
-             int for_call ATTRIBUTE_UNUSED)
+promote_mode (const_tree type, enum machine_mode mode, int *punsignedp)
 {
+  /* 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.  The affected targets are M32C, S390, SPARC.  */
+#ifdef PROMOTE_MODE
   const enum tree_code code = TREE_CODE (type);
   int unsignedp = *punsignedp;
 
-#ifndef PROMOTE_MODE
-  if (! for_call)
-    return mode;
-#endif
-
   switch (code)
     {
-#ifdef PROMOTE_FUNCTION_MODE
     case INTEGER_TYPE:   case ENUMERAL_TYPE:   case BOOLEAN_TYPE:
     case REAL_TYPE:      case OFFSET_TYPE:     case FIXED_POINT_TYPE:
-#ifdef PROMOTE_MODE
-      if (for_call)
-       {
-#endif
-         PROMOTE_FUNCTION_MODE (mode, unsignedp, type);
-#ifdef PROMOTE_MODE
-       }
-      else
-       {
-         PROMOTE_MODE (mode, unsignedp, type);
-       }
-#endif
+      PROMOTE_MODE (mode, unsignedp, type);
+      *punsignedp = unsignedp;
+      return mode;
       break;
-#endif
 
 #ifdef POINTERS_EXTEND_UNSIGNED
     case REFERENCE_TYPE:
     case POINTER_TYPE:
-      mode = Pmode;
-      unsignedp = POINTERS_EXTEND_UNSIGNED;
+      *punsignedp = POINTERS_EXTEND_UNSIGNED;
+      return Pmode;
       break;
 #endif
 
     default:
-      break;
+      return mode;
     }
-
-  *punsignedp = unsignedp;
+#else
   return mode;
+#endif
 }
+
+
+/* Use one of promote_mode or promote_function_mode to find the promoted
+   mode of DECL.  If PUNSIGNEDP is not NULL, store there the unsignedness
+   of DECL after promotion.  */
+
+enum machine_mode
+promote_decl_mode (const_tree decl, int *punsignedp)
+{
+  tree type = TREE_TYPE (decl);
+  int unsignedp = TYPE_UNSIGNED (type);
+  enum machine_mode mode = DECL_MODE (decl);
+  enum machine_mode pmode;
+
+  if (TREE_CODE (decl) == RESULT_DECL)
+    pmode = promote_function_mode (type, mode, &unsignedp,
+                                   TREE_TYPE (current_function_decl), 1);
+  else if (TREE_CODE (decl) == PARM_DECL)
+    pmode = promote_function_mode (type, mode, &unsignedp,
+                                   TREE_TYPE (current_function_decl), 0);
+  else
+    pmode = promote_mode (type, mode, &unsignedp);
+
+  if (punsignedp)
+    *punsignedp = unsignedp;
+  return pmode;
+}
+
 \f
 /* Adjust the stack pointer by ADJUST (an rtx for a number of bytes).
    This pops when ADJUST is positive.  ADJUST need not be constant.  */
index aafa1aa..08c747e 100644 (file)
@@ -5435,13 +5435,11 @@ store_constructor (tree exp, rtx target, int cleared, HOST_WIDE_INT size)
            enum machine_mode mode;
            HOST_WIDE_INT bitsize;
            HOST_WIDE_INT bitpos;
-           int unsignedp;
            rtx xtarget = target;
 
            if (cleared && initializer_zerop (value))
              continue;
 
-           unsignedp = TYPE_UNSIGNED (elttype);
            mode = TYPE_MODE (elttype);
            if (mode == BLKmode)
              bitsize = (host_integerp (TYPE_SIZE (elttype), 1)
@@ -5497,14 +5495,10 @@ store_constructor (tree exp, rtx target, int cleared, HOST_WIDE_INT size)
                    tree exit_cond;
 
                    expand_normal (hi_index);
-                   unsignedp = TYPE_UNSIGNED (domain);
 
                    index = build_decl (EXPR_LOCATION (exp),
                                        VAR_DECL, NULL_TREE, domain);
-
-                   index_r
-                     = gen_reg_rtx (promote_mode (domain, DECL_MODE (index),
-                                                  &unsignedp, 0));
+                   index_r = gen_reg_rtx (promote_decl_mode (index, NULL));
                    SET_DECL_RTL (index, index_r);
                    store_expr (lo_index, index_r, 0, false);
 
@@ -7429,9 +7423,7 @@ expand_expr_real_1 (tree exp, rtx target, enum machine_mode tmode,
 
          /* Get the signedness used for this variable.  Ensure we get the
             same mode we got when the variable was declared.  */
-         pmode = promote_mode (type, DECL_MODE (exp), &unsignedp,
-                               (TREE_CODE (exp) == RESULT_DECL
-                                || TREE_CODE (exp) == PARM_DECL) ? 1 : 0);
+         pmode = promote_decl_mode (exp, &unsignedp);
          gcc_assert (GET_MODE (decl_rtl) == pmode);
 
          temp = gen_lowpart_SUBREG (mode, decl_rtl);
index caf965e..8e23aec 100644 (file)
@@ -719,8 +719,17 @@ extern rtx force_reg (enum machine_mode, rtx);
 /* Return given rtx, copied into a new temp reg if it was in memory.  */
 extern rtx force_not_mem (rtx);
 
+/* Return mode and signedness to use when an argument or result in the
+   given mode is promoted.  */
+extern enum machine_mode promote_function_mode (const_tree, enum machine_mode, int *,
+                                               const_tree, int);
+
+/* Return mode and signedness to use when an object in the given mode
+   is promoted.  */
+extern enum machine_mode promote_mode (const_tree, enum machine_mode, int *);
+
 /* Return mode and signedness to use when object is promoted.  */
-extern enum machine_mode promote_mode (const_tree, enum machine_mode, int *, int);
+enum machine_mode promote_decl_mode (const_tree, int *);
 
 /* Remove some bytes from the stack.  An rtx says how many.  */
 extern void adjust_stack (rtx);
index e31c12a..2294b97 100644 (file)
@@ -922,7 +922,7 @@ assign_temp (tree type_or_decl, int keep, int memory_required,
 
 #ifdef PROMOTE_MODE
   if (! dont_promote)
-    mode = promote_mode (type, mode, &unsignedp, 0);
+    mode = promote_mode (type, mode, &unsignedp);
 #endif
 
   return gen_reg_rtx (mode);
@@ -2167,6 +2167,7 @@ assign_parm_find_data_types (struct assign_parm_data_all *all, tree parm,
 {
   tree nominal_type, passed_type;
   enum machine_mode nominal_mode, passed_mode, promoted_mode;
+  int unsignedp;
 
   memset (data, 0, sizeof (*data));
 
@@ -2219,13 +2220,9 @@ assign_parm_find_data_types (struct assign_parm_data_all *all, tree parm,
     }
 
   /* Find mode as it is passed by the ABI.  */
-  promoted_mode = passed_mode;
-  if (targetm.calls.promote_function_args (TREE_TYPE (current_function_decl)))
-    {
-      int unsignedp = TYPE_UNSIGNED (passed_type);
-      promoted_mode = promote_mode (passed_type, promoted_mode,
-                                   &unsignedp, 1);
-    }
+  unsignedp = TYPE_UNSIGNED (passed_type);
+  promoted_mode = promote_function_mode (passed_type, passed_mode, &unsignedp,
+                                        TREE_TYPE (current_function_decl), 0);
 
  egress:
   data->nominal_type = nominal_type;
@@ -2778,7 +2775,8 @@ assign_parm_setup_reg (struct assign_parm_data_all *all, tree parm,
   /* This is not really promoting for a call.  However we need to be
      consistent with assign_parm_find_data_types and expand_expr_real_1.  */
   promoted_nominal_mode
-    = promote_mode (data->nominal_type, data->nominal_mode, &unsignedp, 1);
+    = promote_function_mode (data->nominal_type, data->nominal_mode, &unsignedp,
+                            TREE_TYPE (current_function_decl), 0);
 
   parmreg = gen_reg_rtx (promoted_nominal_mode);
 
@@ -4722,10 +4720,9 @@ expand_function_end (void)
          else if (GET_MODE (real_decl_rtl) != GET_MODE (decl_rtl))
            {
              int unsignedp = TYPE_UNSIGNED (TREE_TYPE (decl_result));
-
-             if (targetm.calls.promote_function_return (TREE_TYPE (current_function_decl)))
-               promote_mode (TREE_TYPE (decl_result), GET_MODE (decl_rtl),
-                             &unsignedp, 1);
+             promote_function_mode (TREE_TYPE (decl_result),
+                                    GET_MODE (decl_rtl), &unsignedp,
+                                    TREE_TYPE (current_function_decl), 1);
 
              convert_move (real_decl_rtl, decl_rtl, unsignedp);
            }
index d544080..29bcf87 100644 (file)
@@ -1514,23 +1514,22 @@ expand_value_return (rtx val)
   /* Copy the value to the return location
      unless it's already there.  */
 
-  rtx return_reg = DECL_RTL (DECL_RESULT (current_function_decl));
+  tree decl = DECL_RESULT (current_function_decl);
+  rtx return_reg = DECL_RTL (decl);
   if (return_reg != val)
     {
-      tree type = TREE_TYPE (DECL_RESULT (current_function_decl));
-      if (targetm.calls.promote_function_return (TREE_TYPE (current_function_decl)))
-      {
-       int unsignedp = TYPE_UNSIGNED (type);
-       enum machine_mode old_mode
-         = DECL_MODE (DECL_RESULT (current_function_decl));
-       enum machine_mode mode
-         = promote_mode (type, old_mode, &unsignedp, 1);
-
-       if (mode != old_mode)
-         val = convert_modes (mode, old_mode, val, unsignedp);
-      }
+      int unsignedp;
+      enum machine_mode old_mode = DECL_MODE (decl);
+      enum machine_mode mode = promote_decl_mode (decl, &unsignedp);
+
+      if (mode != old_mode)
+       val = convert_modes (mode, old_mode, val, unsignedp);
+
       if (GET_CODE (return_reg) == PARALLEL)
-       emit_group_load (return_reg, val, type, int_size_in_bytes (type));
+       {
+          tree type = TREE_TYPE (decl);
+         emit_group_load (return_reg, val, type, int_size_in_bytes (type));
+       }
       else
        emit_move_insn (return_reg, val);
     }
@@ -1848,9 +1847,7 @@ expand_decl (tree decl)
   else if (use_register_for_decl (decl))
     {
       /* Automatic variable that can go in a register.  */
-      int unsignedp = TYPE_UNSIGNED (type);
-      enum machine_mode reg_mode
-       = promote_mode (type, DECL_MODE (decl), &unsignedp, 0);
+      enum machine_mode reg_mode = promote_decl_mode (decl, NULL);
 
       SET_DECL_RTL (decl, gen_reg_rtx (reg_mode));
 
index 7a9ca81..5d47f2e 100644 (file)
@@ -684,7 +684,7 @@ extern void fancy_abort (const char *, int, const char *) ATTRIBUTE_NORETURN;
        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                  \
@@ -754,7 +754,8 @@ extern void fancy_abort (const char *, int, const char *) ATTRIBUTE_NORETURN;
        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
index 54060f5..26464ed 100644 (file)
 
 #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
 #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 bd10717..27fd77b 100644 (file)
@@ -832,8 +832,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 7d5a092..8c3c2ab 100644 (file)
@@ -113,6 +113,27 @@ default_unspec_may_trap_p (const_rtx x, unsigned flags)
 }
 
 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 839f1c3..5564a79 100644 (file)
@@ -24,6 +24,10 @@ extern void default_external_libcall (rtx);
 extern rtx default_legitimize_address (rtx, rtx, enum machine_mode);
 
 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 696c725..420ee80 100644 (file)
@@ -566,9 +566,8 @@ get_temp_reg (tree name)
 {
   tree var = TREE_CODE (name) == SSA_NAME ? SSA_NAME_VAR (name) : name;
   tree type = TREE_TYPE (var);
-  int unsignedp = TYPE_UNSIGNED (type);
-  enum machine_mode reg_mode
-    = promote_mode (type, DECL_MODE (var), &unsignedp, 0);
+  int unsignedp;
+  enum machine_mode reg_mode = promote_decl_mode (var, &unsignedp);
   rtx x = gen_reg_rtx (reg_mode);
   if (POINTER_TYPE_P (type))
     mark_reg_pointer (x, TYPE_ALIGN (TREE_TYPE (TREE_TYPE (var))));