This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[patch] Hookize SMALL_REGISTER_CLASSES, make SSE register classes not small


Hi,

Attached is a patch to hookize the SMALL_REGISTER_CLASSES target
macro.  The purpose of the patch is to make it possible to have
SMALL_REGISTER_CLASSES be false for some register classes but not for
all. This was discussed before in a RFC posting here:
http://gcc.gnu.org/ml/gcc-patches/2008-12/msg00590.html

Bootstrapped and tested (-m32/-m64) on x86-64_unknown-linux-gnu.  OK for trunk?

Ciao!
Steven
	* doc/tm.texi (defmac SMALL_REGISTER_CLASSES): Remove.
	(TARGET_SMALL_REGISTER_CLASSES_FOR_MODE_P): Add documentation,
	based on the above, for new target hook.

	* hooks.c (hook_bool_mode_true): New generic hook.
	* hooks.h (hook_bool_mode_true): Add prototype.

	* target.h (struct gcc_target): Add small_register_classes_for_mode_p
	target hook.
	* target-def.h (TARGET_SMALL_REGISTER_CLASSES_FOR_MODE_P): New default
	target hook, set to hook_bool_mode_false.
	* regs.h: Remove default definition of SMALL_REGISTER_CLASSES.
	* reload.c (push_secondary_reload): Replace SMALL_REGISTER_CLASSES
	with targetm.small_register_classes_for_mode_p.
	(find_reusable_reload): Likewise.
	(combine_reloads): Likewise.
	* reload1.c (reload_as_needed): Likewise.
	* cse.c (approx_reg_cost_1, hash_rtx_cb): Likewise.
	* ifcvt.c (noce_process_if_block, check_cond_move_block,
	dead_or_predicable): Likewise.
	* regmove.c (optimize_reg_copy_1): Likewise.
	* calls.c (prepare_call_address): Likewise.
	(precompute_register_parameters): Likewise.

	* config/i386/i386.h: Replace SMALL_REGISTER_CLASSES with new target
	hook definition.
	* config/i386/i386.c (ix86_small_register_classes_for_mode_p): Add
	implementation of the hook that considers SSE and 64-bit integer
	register classes "not small".
	* config/i386/i386-protos.h (ix86_small_register_classes_for_mode_p):
	Add prototype.

	* config/sh/sh.h: Replace SMALL_REGISTER_CLASSES with new target
	hook definition.
	* config/sh/sh.c (sh_small_register_classes_for_mode_p): Add
	implementation of the hook that considers all register classes
	small except for SH64.
	(sh_override_options): Use the new hook.
	* config/sh/sh-protos.h (sh_small_register_classes_for_mode_p):
	Add prototype.

	* config/arm/arm.h: Replace SMALL_REGISTER_CLASSES with new target
	hook definition.
	* config/arm/arm.c (arm_small_register_classes_for_mode_p): Add
	implementation of the hook that considers all register classes
	small for THUMB1.
	* config/arm/arm-protos.h (arm_small_register_classes_for_mode_p):
	Add prototype.

	* config/mips/mips.h: Replace SMALL_REGISTER_CLASSES with new target
	hook definition.
	* config/mips/mips.c (mips_small_register_classes_for_mode_p): Add
	implementation of the hook that considers all register classes
	small for MIPS16.
	* config/mips/mips-protos.h (mips_small_register_classes_for_mode_p):
	Add prototype.

	* config/m32c/m32c.h: Replace SMALL_REGISTER_CLASSES with new target
	hook definition.
	* config/pdp11/pdp11.h: Likewise.
	* config/avr/avr.h: Likewise.
	* config/xtensa/xtensa.h: Likewise.
	* config/m68hc11/m68hc11.h: Likewise.
	* config/mn10300/mn10300.h: Likewise.
	* config/mcore/mcore.h: Likewise.
	* config/h8300/h8300.h: Likewise.
	* config/bfin/bfin.h: Likewise.

	* config/iq2000/iq2000.h: Remove SMALL_REGISTER_CLASSES definition.

Index: doc/tm.texi
===================================================================
--- doc/tm.texi	(revision 148467)
+++ doc/tm.texi	(working copy)
@@ -2829,25 +2829,6 @@ Do not define this macro if you do not d
 is @code{BITS_PER_WORD} bits wide is correct for your machine.
 @end defmac
 
-@defmac SMALL_REGISTER_CLASSES
-On some machines, it is risky to let hard registers live across arbitrary
-insns.  Typically, these machines have instructions that require values
-to be in specific registers (like an accumulator), and reload will fail
-if the required hard register is used for another purpose across such an
-insn.
-
-Define @code{SMALL_REGISTER_CLASSES} to be an expression with a nonzero
-value on these machines.  When this macro has a nonzero value, the
-compiler will try to minimize the lifetime of hard registers.
-
-It is always safe to define this macro with a nonzero value, but if you
-unnecessarily define it, you will reduce the amount of optimizations
-that can be performed in some cases.  If you do not define this macro
-with a nonzero value when it is required, the compiler will run out of
-spill registers and print a fatal error message.  For most machines, you
-should not define this macro at all.
-@end defmac
-
 @defmac CLASS_LIKELY_SPILLED_P (@var{class})
 A C expression whose value is nonzero if pseudos that have been assigned
 to registers of class @var{class} would likely be spilled because
@@ -4307,6 +4288,38 @@ insns involving vector mode @var{mode}. 
 must have move patterns for this mode.
 @end deftypefn
 
+@deftypefn {Target Hook} bool TARGET_SMALL_REGISTER_CLASSES_FOR_MODE_P (enum machine_mode @var{mode})
+Define this to return nonzero for machine modes for which the port has
+small register classes.  If this target hook returns nonzero for a given
+@var{mode}, the compiler will try to minimize the lifetime of registers
+in @var{mode}.  The hook may be called with @code{VOIDmode} as argument.
+In this case, the hook is expected to return nonzero if it returns nonzero
+for any mode.
+
+On some machines, it is risky to let hard registers live across arbitrary
+insns.  Typically, these machines have instructions that require values
+to be in specific registers (like an accumulator), and reload will fail
+if the required hard register is used for another purpose across such an
+insn.
+
+Passes before reload do not know which hard registers will be used
+in an instruction, but the machine modes of the registers set or used in
+the instruction are already known.  And for some machines, register
+classes are small for, say, integer registers but not for floating point
+registers.  For example, the AMD x86-64 architecture requires specific
+registers for the legacy x86 integer instructions, but there are many
+SSE registers for floating point operations.  On such targets, a good
+strategy may be to return nonzero from this hook for @code{INTEGRAL_MODE_P}
+machine modes but zero for the SSE register classes.
+
+The default version of this hook retuns false for any mode.  It is always
+safe to redefine this hook to return with a nonzero value.  But if you
+unnecessarily define it, you will reduce the amount of optimizations
+that can be performed in some cases.  If you do not define this hook
+to return a nonzero value when it is required, the compiler will run out
+of spill registers and print a fatal error message.
+@end deftypefn
+
 @node Scalar Return
 @subsection How Scalar Function Values Are Returned
 @cindex return values in registers
Index: hooks.c
===================================================================
--- hooks.c	(revision 148467)
+++ hooks.c	(working copy)
@@ -63,6 +63,13 @@ hook_bool_mode_false (enum machine_mode 
   return false;
 }
 
+/* Generic hook that takes (enum machine_mode) and returns true.  */
+bool
+hook_bool_mode_true (enum machine_mode mode ATTRIBUTE_UNUSED)
+{
+  return true;
+}
+
 /* Generic hook that takes (enum machine_mode, rtx) and returns false.  */
 bool
 hook_bool_mode_const_rtx_false (enum machine_mode mode ATTRIBUTE_UNUSED,
Index: hooks.h
===================================================================
--- hooks.h	(revision 148467)
+++ hooks.h	(working copy)
@@ -29,6 +29,7 @@ extern bool hook_bool_void_false (void);
 extern bool hook_bool_void_true (void);
 extern bool hook_bool_bool_false (bool);
 extern bool hook_bool_mode_false (enum machine_mode);
+extern bool hook_bool_mode_true (enum machine_mode);
 extern bool hook_bool_mode_const_rtx_false (enum machine_mode, const_rtx);
 extern bool hook_bool_mode_const_rtx_true (enum machine_mode, const_rtx);
 extern bool hook_bool_tree_false (tree);
Index: target.h
===================================================================
--- target.h	(revision 148467)
+++ target.h	(working copy)
@@ -690,6 +690,12 @@ struct gcc_target
      for further details.  */
   bool (* vector_mode_supported_p) (enum machine_mode mode);
 
+  /* True for MODE if the target expects that registers in this mode will
+     be allocated to registers in a small register class.  The compiler is
+     allowed to use registers explicitly used in the rtl as spill registers
+     but it should prevent extending the lifetime of these registers.  */
+  bool (* small_register_classes_for_mode_p) (enum machine_mode mode);
+
   /* Compute a (partial) cost for rtx X.  Return true if the complete
      cost has been computed, and false if subexpressions should be
      scanned.  In either case, *TOTAL contains the cost result.  */
Index: target-def.h
===================================================================
--- target-def.h	(revision 148467)
+++ target-def.h	(working copy)
@@ -479,6 +479,10 @@
 #define TARGET_VECTOR_MODE_SUPPORTED_P hook_bool_mode_false
 #endif
 
+#ifndef TARGET_SMALL_REGISTER_CLASSES_FOR_MODE_P
+#define TARGET_SMALL_REGISTER_CLASSES_FOR_MODE_P hook_bool_mode_false
+#endif
+
 /* In hooks.c.  */
 #define TARGET_CANNOT_MODIFY_JUMPS_P hook_bool_void_false
 #define TARGET_BRANCH_TARGET_REGISTER_CLASS \
@@ -896,6 +900,7 @@
   TARGET_VALID_POINTER_MODE,                    \
   TARGET_SCALAR_MODE_SUPPORTED_P,		\
   TARGET_VECTOR_MODE_SUPPORTED_P,               \
+  TARGET_SMALL_REGISTER_CLASSES_FOR_MODE_P,	\
   TARGET_RTX_COSTS,				\
   TARGET_ADDRESS_COST,				\
   TARGET_ALLOCATE_INITIAL_VALUE,		\
@@ -907,7 +912,7 @@
   TARGET_MACHINE_DEPENDENT_REORG,		\
   TARGET_BUILD_BUILTIN_VA_LIST,			\
   TARGET_FN_ABI_VA_LIST,			\
-  TARGET_CANONICAL_VA_LIST_TYPE,			\
+  TARGET_CANONICAL_VA_LIST_TYPE,		\
   TARGET_EXPAND_BUILTIN_VA_START,		\
   TARGET_GIMPLIFY_VA_ARG_EXPR,			\
   TARGET_GET_PCH_VALIDITY,			\
Index: regs.h
===================================================================
--- regs.h	(revision 148467)
+++ regs.h	(working copy)
@@ -38,10 +38,6 @@ along with GCC; see the file COPYING3.  
 #define REGMODE_NATURAL_SIZE(MODE)	UNITS_PER_WORD
 #endif
 
-#ifndef SMALL_REGISTER_CLASSES
-#define SMALL_REGISTER_CLASSES 0
-#endif
-
 /* Maximum register number used in this function, plus one.  */
 
 extern int max_regno;
Index: reload.c
===================================================================
--- reload.c	(revision 148467)
+++ reload.c	(working copy)
@@ -436,7 +436,8 @@ push_secondary_reload (int in_p, rtx x, 
 	    || (! in_p && rld[s_reload].secondary_out_reload == t_reload))
 	&& ((in_p && rld[s_reload].secondary_in_icode == t_icode)
 	    || (! in_p && rld[s_reload].secondary_out_icode == t_icode))
-	&& (SMALL_REGISTER_CLASS_P (rclass) || SMALL_REGISTER_CLASSES)
+	&& (SMALL_REGISTER_CLASS_P (rclass)
+	    || targetm.small_register_classes_for_mode_p (VOIDmode))
 	&& MERGABLE_RELOADS (secondary_type, rld[s_reload].when_needed,
 			     opnum, rld[s_reload].opnum))
       {
@@ -728,9 +729,9 @@ find_reusable_reload (rtx *p_in, rtx out
      and the other is at worst neutral.
      (A zero compared against anything is neutral.)
 
-     If SMALL_REGISTER_CLASSES, don't use existing reloads unless they are
-     for the same thing since that can cause us to need more reload registers
-     than we otherwise would.  */
+     For targets with small register classes, don't use existing reloads
+     unless they are for the same thing since that can cause us to need
+     more reload registers than we otherwise would.  */
 
   for (i = 0; i < n_reloads; i++)
     if ((reg_class_subset_p (rclass, rld[i].rclass)
@@ -744,7 +745,8 @@ find_reusable_reload (rtx *p_in, rtx out
 	    || (out != 0 && MATCHES (rld[i].out, out)
 		&& (in == 0 || rld[i].in == 0 || MATCHES (rld[i].in, in))))
 	&& (rld[i].out == 0 || ! earlyclobber_operand_p (rld[i].out))
-	&& (SMALL_REGISTER_CLASS_P (rclass) || SMALL_REGISTER_CLASSES)
+	&& (SMALL_REGISTER_CLASS_P (rclass)
+	    || targetm.small_register_classes_for_mode_p (VOIDmode))
 	&& MERGABLE_RELOADS (type, rld[i].when_needed, opnum, rld[i].opnum))
       return i;
 
@@ -769,7 +771,8 @@ find_reusable_reload (rtx *p_in, rtx out
 		&& GET_RTX_CLASS (GET_CODE (in)) == RTX_AUTOINC
 		&& MATCHES (XEXP (in, 0), rld[i].in)))
 	&& (rld[i].out == 0 || ! earlyclobber_operand_p (rld[i].out))
-	&& (SMALL_REGISTER_CLASS_P (rclass) || SMALL_REGISTER_CLASSES)
+	&& (SMALL_REGISTER_CLASS_P (rclass)
+	    || targetm.small_register_classes_for_mode_p (VOIDmode))
 	&& MERGABLE_RELOADS (type, rld[i].when_needed,
 			     opnum, rld[i].opnum))
       {
@@ -1767,7 +1770,7 @@ combine_reloads (void)
 	    || rtx_equal_p (secondary_memlocs_elim[(int) rld[output_reload].outmode][rld[i].opnum],
 			    secondary_memlocs_elim[(int) rld[output_reload].outmode][rld[output_reload].opnum]))
 #endif
-	&& (SMALL_REGISTER_CLASSES
+	&& (targetm.small_register_classes_for_mode_p (VOIDmode)
 	    ? (rld[i].rclass == rld[output_reload].rclass)
 	    : (reg_class_subset_p (rld[i].rclass,
 				   rld[output_reload].rclass)
@@ -1791,7 +1794,7 @@ combine_reloads (void)
 	&& ! reload_inner_reg_of_subreg (rld[i].in, rld[i].inmode,
 					 rld[i].when_needed != RELOAD_FOR_INPUT)
 	&& (reg_class_size[(int) rld[i].rclass]
-	    || SMALL_REGISTER_CLASSES)
+	    || targetm.small_register_classes_for_mode_p (VOIDmode))
 	/* We will allow making things slightly worse by combining an
 	   input and an output, but no worse than that.  */
 	&& (rld[i].when_needed == RELOAD_FOR_INPUT
Index: reload1.c
===================================================================
--- reload1.c	(revision 148467)
+++ reload1.c	(working copy)
@@ -4210,7 +4210,7 @@ reload_as_needed (int live_known)
 	      /* Merge any reloads that we didn't combine for fear of
 		 increasing the number of spill registers needed but now
 		 discover can be safely merged.  */
-	      if (SMALL_REGISTER_CLASSES)
+	      if (targetm.small_register_classes_for_mode_p (VOIDmode))
 		merge_assigned_reloads (insn);
 
 	      /* Generate the insns to reload operands into or out of
@@ -6590,10 +6590,11 @@ deallocate_reload_reg (int r)
   reload_spill_index[r] = -1;
 }
 
-/* If SMALL_REGISTER_CLASSES is nonzero, we may not have merged two
-   reloads of the same item for fear that we might not have enough reload
-   registers. However, normally they will get the same reload register
-   and hence actually need not be loaded twice.
+/* If the small_register_classes_for_mode_p target hook returns true for
+   some machine modes, we may not have merged two reloads of the same item
+   for fear that we might not have enough reload registers.  However,
+   normally they will get the same reload register and hence actually need
+   not be loaded twice.
 
    Here we check for the most common case of this phenomenon: when we have
    a number of reloads for the same object, each of which were allocated
Index: cse.c
===================================================================
--- cse.c	(revision 148467)
+++ cse.c	(working copy)
@@ -686,7 +686,7 @@ approx_reg_cost_1 (rtx *xp, void *data)
 	{
 	  if (regno < FIRST_PSEUDO_REGISTER)
 	    {
-	      if (SMALL_REGISTER_CLASSES)
+	      if (targetm.small_register_classes_for_mode_p (GET_MODE (x)))
 		return 1;
 	      *cost_p += 2;
 	    }
@@ -2304,7 +2304,7 @@ hash_rtx_cb (const_rtx x, enum machine_m
 	      record = true;
 	    else if (GET_MODE_CLASS (GET_MODE (x)) == MODE_CC)
 	      record = true;
-	    else if (SMALL_REGISTER_CLASSES)
+	    else if (targetm.small_register_classes_for_mode_p (GET_MODE (x)))
 	      record = false;
 	    else if (CLASS_LIKELY_SPILLED_P (REGNO_REG_CLASS (regno)))
 	      record = false;
Index: ifcvt.c
===================================================================
--- ifcvt.c	(revision 148467)
+++ ifcvt.c	(working copy)
@@ -2291,8 +2291,8 @@ noce_process_if_block (struct noce_if_in
      the lifetime of hard registers on small register class machines.  */
   orig_x = x;
   if (!REG_P (x)
-      || (SMALL_REGISTER_CLASSES
-	  && REGNO (x) < FIRST_PSEUDO_REGISTER))
+      || (HARD_REGISTER_P (x)
+	  && targetm.small_register_classes_for_mode_p (GET_MODE (x))))
     {
       if (GET_MODE (x) == BLKmode)
 	return FALSE;
@@ -2490,7 +2490,8 @@ check_cond_move_block (basic_block bb, r
       dest = SET_DEST (set);
       src = SET_SRC (set);
       if (!REG_P (dest)
-	  || (SMALL_REGISTER_CLASSES && HARD_REGISTER_P (dest)))
+	  || (HARD_REGISTER_P (dest)
+	      && targetm.small_register_classes_for_mode_p (GET_MODE (dest))))
 	return FALSE;
 
       if (!CONSTANT_P (src) && !register_operand (src, VOIDmode))
@@ -3931,7 +3932,8 @@ dead_or_predicable (basic_block test_bb,
 
       /* For small register class machines, don't lengthen lifetimes of
 	 hard registers before reload.  */
-      if (SMALL_REGISTER_CLASSES && ! reload_completed)
+      if (! reload_completed
+	  && targetm.small_register_classes_for_mode_p (VOIDmode))
 	{
           EXECUTE_IF_SET_IN_BITMAP (merge_set, 0, i, bi)
 	    {
Index: regmove.c
===================================================================
--- regmove.c	(revision 148467)
+++ regmove.c	(working copy)
@@ -31,6 +31,7 @@ along with GCC; see the file COPYING3.  
 #include "tm_p.h"
 #include "insn-config.h"
 #include "recog.h"
+#include "target.h"
 #include "output.h"
 #include "regs.h"
 #include "hard-reg-set.h"
@@ -236,7 +237,7 @@ optimize_reg_copy_1 (rtx insn, rtx dest,
 
   /* We don't want to mess with hard regs if register classes are small.  */
   if (sregno == dregno
-      || (SMALL_REGISTER_CLASSES
+      || (targetm.small_register_classes_for_mode_p (GET_MODE (src))
 	  && (sregno < FIRST_PSEUDO_REGISTER
 	      || dregno < FIRST_PSEUDO_REGISTER))
       /* We don't see all updates to SP if they are in an auto-inc memory
Index: gcse.c
===================================================================
--- gcse.c	(revision 148467)
+++ gcse.c	(working copy)
@@ -3487,10 +3487,10 @@ insert_insn_end_basic_block (struct expr
 	   && (!single_succ_p (bb)
 	       || single_succ_edge (bb)->flags & EDGE_ABNORMAL))
     {
-      /* Keeping in mind SMALL_REGISTER_CLASSES and parameters in registers,
-	 we search backward and place the instructions before the first
-	 parameter is loaded.  Do this for everyone for consistency and a
-	 presumption that we'll get better code elsewhere as well.
+      /* Keeping in mind targets with small register classes and parameters
+         in registers, we search backward and place the instructions before
+	 the first parameter is loaded.  Do this for everyone for consistency
+	 and a presumption that we'll get better code elsewhere as well.
 
 	 It should always be the case that we can put these instructions
 	 anywhere in the basic block with performing PRE optimizations.
Index: calls.c
===================================================================
--- calls.c	(revision 148467)
+++ calls.c	(working copy)
@@ -174,7 +174,8 @@ prepare_call_address (rtx funexp, rtx st
   if (GET_CODE (funexp) != SYMBOL_REF)
     /* If we are using registers for parameters, force the
        function address into a register now.  */
-    funexp = ((SMALL_REGISTER_CLASSES && reg_parm_seen)
+    funexp = ((reg_parm_seen
+	       && targetm.small_register_classes_for_mode_p (FUNCTION_MODE))
 	      ? force_not_mem (memory_address (FUNCTION_MODE, funexp))
 	      : memory_address (FUNCTION_MODE, funexp));
   else if (! sibcallp)
@@ -719,7 +720,8 @@ precompute_register_parameters (int num_
 		 && args[i].mode != BLKmode
 		 && rtx_cost (args[i].value, SET, optimize_insn_for_speed_p ())
 		    > COSTS_N_INSNS (1)
-		 && ((SMALL_REGISTER_CLASSES && *reg_parm_seen)
+		 && ((*reg_parm_seen
+		      && targetm.small_register_classes_for_mode_p (args[i].mode))
 		     || optimize))
 	  args[i].value = copy_to_mode_reg (args[i].mode, args[i].value);
       }
Index: sched-deps.c
===================================================================
--- sched-deps.c	(revision 148467)
+++ sched-deps.c	(working copy)
@@ -2546,8 +2546,8 @@ sched_analyze_insn (struct deps *deps, r
      This insn must be a simple move of a hard reg to a pseudo or
      vice-versa.
 
-     We must avoid moving these insns for correctness on
-     SMALL_REGISTER_CLASS machines, and for special registers like
+     We must avoid moving these insns for correctness on targets
+     with small register classes, and for special registers like
      PIC_OFFSET_TABLE_REGNUM.  For simplicity, extend this to all
      hard regs for all targets.  */
 
Index: cfgrtl.c
===================================================================
--- cfgrtl.c	(revision 148467)
+++ cfgrtl.c	(working copy)
@@ -3061,10 +3061,10 @@ insert_insn_end_bb_new (rtx pat, basic_b
            && (!single_succ_p (bb)
                || single_succ_edge (bb)->flags & EDGE_ABNORMAL))
     {
-      /* Keeping in mind SMALL_REGISTER_CLASSES and parameters in registers,
-         we search backward and place the instructions before the first
-         parameter is loaded.  Do this for everyone for consistency and a
-         presumption that we'll get better code elsewhere as well.  */
+      /* Keeping in mind targets with small register classes and parameters
+         in registers, we search backward and place the instructions before
+	 the first parameter is loaded.  Do this for everyone for consistency
+	 and a presumption that we'll get better code elsewhere as well.  */
 
       /* Since different machines initialize their parameter registers
          in different orders, assume nothing.  Collect the set of all
Index: config/i386/i386.h
===================================================================
--- config/i386/i386.h	(revision 148467)
+++ config/i386/i386.h	(working copy)
@@ -1345,11 +1345,12 @@ enum reg_class
 
 #define REGNO_REG_CLASS(REGNO) (regclass_map[REGNO])
 
-/* When defined, the compiler allows registers explicitly used in the
-   rtl to be used as spill registers but prevents the compiler from
-   extending the lifetime of these registers.  */
-
-#define SMALL_REGISTER_CLASSES 1
+/* When this hook returns true for MODE, the compiler allows
+   registers explicitly used in the rtl to be used as spill registers
+   but prevents the compiler from extending the lifetime of these
+   registers.  */
+#define TARGET_SMALL_REGISTER_CLASSES_FOR_MODE_P \
+  ix86_small_register_classes_for_mode_p 
 
 #define QI_REG_P(X) (REG_P (X) && REGNO (X) <= BX_REG)
 
Index: config/i386/i386-protos.h
===================================================================
--- config/i386/i386-protos.h	(revision 148467)
+++ config/i386/i386-protos.h	(working copy)
@@ -157,6 +157,7 @@ extern int ix86_secondary_memory_needed 
 					 enum machine_mode, int);
 extern bool ix86_cannot_change_mode_class (enum machine_mode,
 					   enum machine_mode, enum reg_class);
+extern bool ix86_small_register_classes_for_mode_p (enum machine_mode);
 extern enum reg_class ix86_preferred_reload_class (rtx, enum reg_class);
 extern enum reg_class ix86_preferred_output_reload_class (rtx, enum reg_class);
 extern int ix86_memory_move_cost (enum machine_mode, enum reg_class, int);
Index: config/i386/i386.c
===================================================================
--- config/i386/i386.c	(revision 148467)
+++ config/i386/i386.c	(working copy)
@@ -26430,6 +26430,31 @@ ix86_cannot_change_mode_class (enum mach
   return false;
 }
 
+/* Implement target hook small_register_classes_for_mode_p.  */
+
+bool
+ix86_small_register_classes_for_mode_p (enum machine_mode mode)
+{
+  /* On 32-bits x86, all register classes are considered small.  */
+  if (! TARGET_64BIT)
+    return true;
+
+  /* Any mode that is OK for SSE or AVX registers is not likely
+     to be allocated to a small class.  */
+  if (TARGET_SSE_MATH
+      && (SSE_FLOAT_MODE_P (mode) || VECTOR_MODE_P (mode)))
+    return false;
+
+  /* AMD64 has 16 registers for >=32 bits integers.  This is not
+     large compared to RISC/VLIW architectures, but it is big
+     enough for us to consider it non-small.  */
+  if (SCALAR_INT_MODE_P (mode) && GET_MODE_SIZE (mode) >= 32)
+    return false;
+
+  /* Otherwise, consider all modes small.  */
+  return true;
+}
+
 /* Return the cost of moving data of mode M between a
    register and memory.  A value of 2 is the default; this cost is
    relative to those in `REGISTER_MOVE_COST'.
Index: config/sh/sh.h
===================================================================
--- config/sh/sh.h	(revision 148467)
+++ config/sh/sh.h	(working copy)
@@ -1204,11 +1204,12 @@ extern enum reg_class regno_reg_class[FI
   FPUL_REGS, LIM_REG_CLASSES						     \
 }
 
-/* When defined, the compiler allows registers explicitly used in the
-   rtl to be used as spill registers but prevents the compiler from
-   extending the lifetime of these registers.  */
-
-#define SMALL_REGISTER_CLASSES (! TARGET_SHMEDIA)
+/* When this hook returns true for MODE, the compiler allows
+   registers explicitly used in the rtl to be used as spill registers
+   but prevents the compiler from extending the lifetime of these
+   registers.  */
+#define TARGET_SMALL_REGISTER_CLASSES_FOR_MODE_P \
+  sh_small_register_classes_for_mode_p
 
 /* The order in which register should be allocated.  */
 /* Sometimes FP0_REGS becomes the preferred class of a floating point pseudo,
Index: config/sh/sh-protos.h
===================================================================
--- config/sh/sh-protos.h	(revision 148467)
+++ config/sh/sh-protos.h	(working copy)
@@ -145,6 +145,7 @@ extern int sh_cfun_attr_renesas_p (void)
 extern void sh_initialize_trampoline (rtx, rtx, rtx);
 extern bool sh_cannot_change_mode_class
 	      (enum machine_mode, enum machine_mode, enum reg_class);
+extern bool sh_small_register_classes_for_mode_p (enum machine_mode);
 extern void sh_mark_label (rtx, int);
 extern int sh_register_move_cost
   (enum machine_mode mode, enum reg_class, enum reg_class);
Index: config/sh/sh.c
===================================================================
--- config/sh/sh.c	(revision 148467)
+++ config/sh/sh.c	(working copy)
@@ -826,7 +826,7 @@ sh_override_options (void)
       || (TARGET_SHMEDIA && !TARGET_PT_FIXED))
     flag_no_function_cse = 1;
 
-  if (SMALL_REGISTER_CLASSES)
+  if (targetm.small_register_classes_for_mode_p (VOIDmode))		\
     {
       /* Never run scheduling before reload, since that can
 	 break global alloc, and generates slower code anyway due
@@ -9133,7 +9133,7 @@ get_free_reg (HARD_REG_SET regs_live)
   if (! TEST_HARD_REG_BIT (regs_live, 1))
     return gen_rtx_REG (Pmode, 1);
 
-  /* Hard reg 1 is live; since this is a SMALL_REGISTER_CLASSES target,
+  /* Hard reg 1 is live; since this is a small register classes target,
      there shouldn't be anything but a jump before the function end.  */
   gcc_assert (!TEST_HARD_REG_BIT (regs_live, 7));
   return gen_rtx_REG (Pmode, 7);
@@ -10947,6 +10947,14 @@ sh_cannot_change_mode_class (enum machin
   return 0;
 }
 
+/* Return true if registers in machine mode MODE will likely be
+   allocated to registers in small register classes.  */
+
+static bool
+sh_small_register_classes_for_mode_p (enum machine_mode mode ATTRIBUTE_UNUSED)
+{
+  return (! TARGET_SHMEDIA);
+}
 
 /* If ADDRESS refers to a CODE_LABEL, add NUSES to the number of times
    that label is used.  */
Index: config/arm/arm.h
===================================================================
--- config/arm/arm.h	(revision 148467)
+++ config/arm/arm.h	(working copy)
@@ -1247,11 +1247,12 @@ enum reg_class
    instead of BASE_REGS.  */
 #define MODE_BASE_REG_REG_CLASS(MODE) BASE_REG_CLASS
 
-/* When SMALL_REGISTER_CLASSES is nonzero, the compiler allows
+/* When this hook returns true for MODE, the compiler allows
    registers explicitly used in the rtl to be used as spill registers
    but prevents the compiler from extending the lifetime of these
    registers.  */
-#define SMALL_REGISTER_CLASSES   TARGET_THUMB1
+#define TARGET_SMALL_REGISTER_CLASSES_FOR_MODE_P \
+  arm_small_register_classes_for_mode_p 
 
 /* Given an rtx X being reloaded into a reg required to be
    in class CLASS, return the class of reg to actually use.
Index: config/arm/arm.c
===================================================================
--- config/arm/arm.c	(revision 148467)
+++ config/arm/arm.c	(working copy)
@@ -19136,6 +19136,13 @@ arm_vector_mode_supported_p (enum machin
   return false;
 }
 
+/* Implements target hook small_register_classes_for_mode_p.  */
+bool
+arm_small_register_classes_for_mode_p (enum machine_mode mode ATTRIBUTE_UNUSED)
+{
+  return TARGET_THUMB1;
+}
+
 /* Implement TARGET_SHIFT_TRUNCATION_MASK.  SImode shifts use normal
    ARM insns and therefore guarantee that the shift count is modulo 256.
    DImode shifts (those implemented by lib1funcs.asm or by optabs.c)
Index: config/arm/arm-protos.h
===================================================================
--- config/arm/arm-protos.h	(revision 148467)
+++ config/arm/arm-protos.h	(working copy)
@@ -45,6 +45,7 @@ extern void arm_output_fn_unwind (FILE *
 
 #ifdef RTX_CODE
 extern bool arm_vector_mode_supported_p (enum machine_mode);
+extern bool arm_small_register_classes_for_mode_p (enum machine_mode);
 extern int arm_hard_regno_mode_ok (unsigned int, enum machine_mode);
 extern int const_ok_for_arm (HOST_WIDE_INT);
 extern int arm_split_constant (RTX_CODE, enum machine_mode, rtx,
Index: config/mips/mips.h
===================================================================
--- config/mips/mips.h	(revision 148467)
+++ config/mips/mips.h	(working copy)
@@ -1973,12 +1973,12 @@ enum reg_class
 
 #define INDEX_REG_CLASS NO_REGS
 
-/* When SMALL_REGISTER_CLASSES is nonzero, the compiler allows
+/* When this hook returns true for MODE, the compiler allows
    registers explicitly used in the rtl to be used as spill registers
    but prevents the compiler from extending the lifetime of these
    registers.  */
-
-#define SMALL_REGISTER_CLASSES (TARGET_MIPS16)
+#define TARGET_SMALL_REGISTER_CLASSES_FOR_MODE_P \
+  mips_small_register_classes_for_mode_p
 
 /* We generally want to put call-clobbered registers ahead of
    call-saved ones.  (IRA expects this.)  */
Index: config/mips/mips.c
===================================================================
--- config/mips/mips.c	(revision 148467)
+++ config/mips/mips.c	(working copy)
@@ -10124,6 +10124,15 @@ mips_cannot_change_mode_class (enum mach
   return reg_classes_intersect_p (FP_REGS, rclass);
 }
 
+/* Implement target hook small_register_classes_for_mode_p.  */
+
+static bool
+mips_small_register_classes_for_mode_p (enum machine_mode mode
+					ATTRIBUTE_UNUSED)
+{
+  return TARGET_MIPS16;
+}
+
 /* Return true if moves in mode MODE can use the FPU's mov.fmt instruction.  */
 
 static bool
Index: config/mips/mips-protos.h
===================================================================
--- config/mips/mips-protos.h	(revision 148467)
+++ config/mips/mips-protos.h	(working copy)
@@ -284,6 +284,7 @@ extern rtx mips_function_value (const_tr
 
 extern bool mips_cannot_change_mode_class (enum machine_mode,
 					   enum machine_mode, enum reg_class);
+extern bool mips_small_register_classes_for_mode_p (enum machine_mode);
 extern bool mips_dangerous_for_la25_p (rtx);
 extern bool mips_modes_tieable_p (enum machine_mode, enum machine_mode);
 extern enum reg_class mips_preferred_reload_class (rtx, enum reg_class);
Index: config/m32c/m32c.h
===================================================================
--- config/m32c/m32c.h	(revision 148467)
+++ config/m32c/m32c.h	(working copy)
@@ -418,7 +418,7 @@ enum reg_class
 
 #define SECONDARY_RELOAD_CLASS(CLASS,MODE,X) m32c_secondary_reload_class (CLASS, MODE, X)
 
-#define SMALL_REGISTER_CLASSES 1
+#define TARGET_SMALL_REGISTER_CLASSES_FOR_MODE_P hook_bool_mode_true
 
 #define CLASS_LIKELY_SPILLED_P(C) m32c_class_likely_spilled_p (C)
 
Index: config/pdp11/pdp11.h
===================================================================
--- config/pdp11/pdp11.h	(revision 148467)
+++ config/pdp11/pdp11.h	(working copy)
@@ -290,7 +290,7 @@ enum reg_class { NO_REGS, MUL_REGS, GENE
 #define N_REG_CLASSES (int) LIM_REG_CLASSES
 
 /* have to allow this till cmpsi/tstsi are fixed in a better way !! */
-#define SMALL_REGISTER_CLASSES 1
+#define TARGET_SMALL_REGISTER_CLASSES_FOR_MODE_P hook_bool_mode_true
 
 /* Since GENERAL_REGS is the same class as ALL_REGS,
    don't give it a different class number; just make it an alias.  */
Index: config/avr/avr.h
===================================================================
--- config/avr/avr.h	(revision 148467)
+++ config/avr/avr.h	(working copy)
@@ -324,7 +324,7 @@ enum reg_class {
 
 #define PREFERRED_RELOAD_CLASS(X, CLASS) preferred_reload_class(X,CLASS)
 
-#define SMALL_REGISTER_CLASSES 1
+#define TARGET_SMALL_REGISTER_CLASSES_FOR_MODE_P hook_bool_mode_true
 
 #define CLASS_LIKELY_SPILLED_P(c) class_likely_spilled_p(c)
 
Index: config/xtensa/xtensa.h
===================================================================
--- config/xtensa/xtensa.h	(revision 148467)
+++ config/xtensa/xtensa.h	(working copy)
@@ -494,10 +494,10 @@ extern const enum reg_class xtensa_regno
 #define BASE_REG_CLASS AR_REGS
 #define INDEX_REG_CLASS NO_REGS
 
-/* SMALL_REGISTER_CLASSES is required for Xtensa, because all of the
-   16 AR registers may be explicitly used in the RTL, as either
-   incoming or outgoing arguments.  */
-#define SMALL_REGISTER_CLASSES 1
+/* The small_register_classes_for_mode_p hook must always return true for
+   Xtrnase, because all of the 16 AR registers may be explicitly used in
+   the RTL, as either incoming or outgoing arguments.  */
+#define TARGET_SMALL_REGISTER_CLASSES_FOR_MODE_P hook_bool_mode_true
 
 #define PREFERRED_RELOAD_CLASS(X, CLASS)				\
   xtensa_preferred_reload_class (X, CLASS, 0)
Index: config/stormy16/stormy16.h
===================================================================
--- config/stormy16/stormy16.h	(revision 148467)
+++ config/stormy16/stormy16.h	(working copy)
@@ -279,25 +279,6 @@ enum reg_class
 #define SECONDARY_RELOAD_CLASS(CLASS, MODE, X)			\
   xstormy16_secondary_reload_class (CLASS, MODE, X)
 
-/* Normally the compiler avoids choosing registers that have been explicitly
-   mentioned in the rtl as spill registers (these registers are normally those
-   used to pass parameters and return values).  However, some machines have so
-   few registers of certain classes that there would not be enough registers to
-   use as spill registers if this were done.
-
-   Define `SMALL_REGISTER_CLASSES' to be an expression with a nonzero value on
-   these machines.  When this macro has a nonzero value, the compiler allows
-   registers explicitly used in the rtl to be used as spill registers but
-   avoids extending the lifetime of these registers.
-
-   It is always safe to define this macro with a nonzero value, but if you
-   unnecessarily define it, you will reduce the amount of optimizations that
-   can be performed in some cases.  If you do not define this macro with a
-   nonzero value when it is required, the compiler will run out of spill
-   registers and print a fatal error message.  For most machines, you should
-   not define this macro at all.  */
-/* #define SMALL_REGISTER_CLASSES */
-
 /* This declaration is required.  */
 #define CLASS_MAX_NREGS(CLASS, MODE) \
   ((GET_MODE_SIZE (MODE) + UNITS_PER_WORD - 1) / UNITS_PER_WORD)
Index: config/m68hc11/m68hc11.h
===================================================================
--- config/m68hc11/m68hc11.h	(revision 148467)
+++ config/m68hc11/m68hc11.h	(working copy)
@@ -707,7 +707,7 @@ extern enum reg_class m68hc11_tmp_regs_c
 
 #define PREFERRED_RELOAD_CLASS(X,CLASS)	preferred_reload_class(X,CLASS)
 
-#define SMALL_REGISTER_CLASSES 1
+#define TARGET_SMALL_REGISTER_CLASSES_FOR_MODE_P hook_bool_mode_true
 
 /* A C expression that is nonzero if hard register number REGNO2 can be
    considered for use as a rename register for REGNO1 */
Index: config/mn10300/mn10300.h
===================================================================
--- config/mn10300/mn10300.h	(revision 148467)
+++ config/mn10300/mn10300.h	(working copy)
@@ -236,7 +236,7 @@ extern enum processor_type mn10300_proce
 
 /* 4 data, and effectively 3 address registers is small as far as I'm
    concerned.  */
-#define SMALL_REGISTER_CLASSES 1
+#define TARGET_SMALL_REGISTER_CLASSES_FOR_MODE_P hook_bool_mode_true
 
 /* Define the classes of registers for register constraints in the
    machine description.  Also define ranges of constants.
Index: config/mcore/mcore.h
===================================================================
--- config/mcore/mcore.h	(revision 148467)
+++ config/mcore/mcore.h	(working copy)
@@ -411,10 +411,11 @@ enum reg_class
 extern const int regno_reg_class[FIRST_PSEUDO_REGISTER];
 #define REGNO_REG_CLASS(REGNO) regno_reg_class[REGNO]
 
-/* When defined, the compiler allows registers explicitly used in the
-   rtl to be used as spill registers but prevents the compiler from
-   extending the lifetime of these registers.  */
-#define SMALL_REGISTER_CLASSES 1
+/* When this hook returns true for MODE, the compiler allows
+   registers explicitly used in the rtl to be used as spill registers
+   but prevents the compiler from extending the lifetime of these
+   registers.  */
+#define TARGET_SMALL_REGISTER_CLASSES_FOR_MODE_P hook_bool_mode_true
  
 /* The class value for index registers, and the one for base regs.  */
 #define INDEX_REG_CLASS  NO_REGS
Index: config/h8300/h8300.h
===================================================================
--- config/h8300/h8300.h	(revision 148467)
+++ config/h8300/h8300.h	(working copy)
@@ -608,11 +608,11 @@ enum reg_class {
 
 #define FUNCTION_ARG_REGNO_P(N) (TARGET_QUICKCALL ? N < 3 : 0)
 
-/* When defined, the compiler allows registers explicitly used in the
-   rtl to be used as spill registers but prevents the compiler from
-   extending the lifetime of these registers.  */
-
-#define SMALL_REGISTER_CLASSES 1
+/* When this hook returns true for MODE, the compiler allows
+   registers explicitly used in the rtl to be used as spill registers
+   but prevents the compiler from extending the lifetime of these
+   registers.  */
+#define TARGET_SMALL_REGISTER_CLASSES_FOR_MODE_P hook_bool_mode_true
 
 /* Define a data type for recording info about an argument list
    during the scan of that argument list.  This data type should
Index: config/bfin/bfin.h
===================================================================
--- config/bfin/bfin.h	(revision 148467)
+++ config/bfin/bfin.h	(working copy)
@@ -742,10 +742,11 @@ enum reg_class
     MOST_REGS, AREGS, CCREGS, LIM_REG_CLASSES		\
 }
 
-/* When defined, the compiler allows registers explicitly used in the
-   rtl to be used as spill registers but prevents the compiler from
-   extending the lifetime of these registers. */
-#define SMALL_REGISTER_CLASSES 1
+/* When this hook returns true for MODE, the compiler allows
+   registers explicitly used in the rtl to be used as spill registers
+   but prevents the compiler from extending the lifetime of these
+   registers.  */
+#define TARGET_SMALL_REGISTER_CLASSES_FOR_MODE_P hook_bool_mode_true
 
 #define CLASS_LIKELY_SPILLED_P(CLASS) \
     ((CLASS) == PREGS_CLOBBERED \
Index: config/iq2000/iq2000.h
===================================================================
--- config/iq2000/iq2000.h	(revision 148467)
+++ config/iq2000/iq2000.h	(working copy)
@@ -247,8 +247,6 @@ enum reg_class
 	 ? (GR_REGS)						\
 	 : (CLASS))))
 
-#define SMALL_REGISTER_CLASSES 0
-
 #define CLASS_MAX_NREGS(CLASS, MODE)    \
   ((GET_MODE_SIZE (MODE) + UNITS_PER_WORD - 1) / UNITS_PER_WORD)
 

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]