summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSteven Bosscher <steven@gcc.gnu.org>2010-05-03 17:47:47 +0000
committerSteven Bosscher <steven@gcc.gnu.org>2010-05-03 17:47:47 +0000
commit42db504c2fb2b460e24ca0e73b8559fc33b3cf33 (patch)
treed6b919e11206907a280cef642b29741b31e6e929
parentd5ece0a1f59fd71e156bc58c8423eb7ea8d16480 (diff)
tm.texi (defmac SMALL_REGISTER_CLASSES): Remove.
* 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/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/i386/i386.h: Replace SMALL_REGISTER_CLASSES with new target hook definition. * config/m32c/m32c.h: Likewise. * 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. * config/rx/rx.h: Remove SMALL_REGISTER_CLASSES definition. From-SVN: r158997
-rw-r--r--gcc/ChangeLog66
-rw-r--r--gcc/calls.c6
-rw-r--r--gcc/cfgrtl.c8
-rw-r--r--gcc/config/arm/arm-protos.h1
-rw-r--r--gcc/config/arm/arm.c7
-rw-r--r--gcc/config/arm/arm.h5
-rw-r--r--gcc/config/avr/avr.h2
-rw-r--r--gcc/config/bfin/bfin.h9
-rw-r--r--gcc/config/h8300/h8300.h10
-rw-r--r--gcc/config/i386/i386.h10
-rw-r--r--gcc/config/iq2000/iq2000.h2
-rw-r--r--gcc/config/m32c/m32c.h2
-rw-r--r--gcc/config/m68hc11/m68hc11.h2
-rw-r--r--gcc/config/mcore/mcore.h9
-rw-r--r--gcc/config/mips/mips-protos.h1
-rw-r--r--gcc/config/mips/mips.c9
-rw-r--r--gcc/config/mips/mips.h6
-rw-r--r--gcc/config/mn10300/mn10300.h2
-rw-r--r--gcc/config/pdp11/pdp11.h2
-rw-r--r--gcc/config/rx/rx.h1
-rw-r--r--gcc/config/sh/sh-protos.h1
-rw-r--r--gcc/config/sh/sh.c12
-rw-r--r--gcc/config/sh/sh.h11
-rw-r--r--gcc/config/xtensa/xtensa.h8
-rw-r--r--gcc/cse.c4
-rw-r--r--gcc/doc/tm.texi51
-rw-r--r--gcc/gcse.c8
-rw-r--r--gcc/hooks.c7
-rw-r--r--gcc/hooks.h1
-rw-r--r--gcc/ifcvt.c10
-rw-r--r--gcc/regmove.c3
-rw-r--r--gcc/regs.h4
-rw-r--r--gcc/reload.c19
-rw-r--r--gcc/reload1.c11
-rw-r--r--gcc/sched-deps.c4
-rw-r--r--gcc/target-def.h7
-rw-r--r--gcc/target.h6
37 files changed, 229 insertions, 98 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 485dfbe4e5e..727f89724ce 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,69 @@
+2010-05-03 Steven Bosscher <steven@gcc.gnu.org>
+
+ * 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/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/i386/i386.h: Replace SMALL_REGISTER_CLASSES with new target
+ hook definition.
+ * config/m32c/m32c.h: Likewise.
+ * 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.
+ * config/rx/rx.h: Remove SMALL_REGISTER_CLASSES definition.
+
2010-05-03 Anatoly Sokolov <aesok@post.ru>
* double-int.h (tree_to_double_int): Remove macro.
diff --git a/gcc/calls.c b/gcc/calls.c
index 496ec602bc6..9c51f1a5a74 100644
--- a/gcc/calls.c
+++ b/gcc/calls.c
@@ -175,7 +175,8 @@ prepare_call_address (tree fndecl, rtx funexp, rtx static_chain_value,
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)
@@ -711,7 +712,8 @@ precompute_register_parameters (int num_actuals, struct arg_data *args,
&& 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);
}
diff --git a/gcc/cfgrtl.c b/gcc/cfgrtl.c
index 13e0e5c40d6..7fb1873f53b 100644
--- a/gcc/cfgrtl.c
+++ b/gcc/cfgrtl.c
@@ -3123,10 +3123,10 @@ insert_insn_end_bb_new (rtx pat, basic_block bb)
&& (!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
diff --git a/gcc/config/arm/arm-protos.h b/gcc/config/arm/arm-protos.h
index 5a42a259df5..2933201a1eb 100644
--- a/gcc/config/arm/arm-protos.h
+++ b/gcc/config/arm/arm-protos.h
@@ -45,6 +45,7 @@ extern void arm_output_fn_unwind (FILE *, bool);
#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,
diff --git a/gcc/config/arm/arm.c b/gcc/config/arm/arm.c
index 884a1bdace9..7f3cdfa239f 100644
--- a/gcc/config/arm/arm.c
+++ b/gcc/config/arm/arm.c
@@ -20944,6 +20944,13 @@ arm_vector_mode_supported_p (enum machine_mode mode)
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)
diff --git a/gcc/config/arm/arm.h b/gcc/config/arm/arm.h
index ca46db1cca2..b672535c1c8 100644
--- a/gcc/config/arm/arm.h
+++ b/gcc/config/arm/arm.h
@@ -1267,11 +1267,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.
diff --git a/gcc/config/avr/avr.h b/gcc/config/avr/avr.h
index 67e0c8f04f1..398b412dd91 100644
--- a/gcc/config/avr/avr.h
+++ b/gcc/config/avr/avr.h
@@ -333,7 +333,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)
diff --git a/gcc/config/bfin/bfin.h b/gcc/config/bfin/bfin.h
index 365680ee9fa..a1bd556003e 100644
--- a/gcc/config/bfin/bfin.h
+++ b/gcc/config/bfin/bfin.h
@@ -756,10 +756,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 \
diff --git a/gcc/config/h8300/h8300.h b/gcc/config/h8300/h8300.h
index f77dfa31407..1ce1585544e 100644
--- a/gcc/config/h8300/h8300.h
+++ b/gcc/config/h8300/h8300.h
@@ -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
diff --git a/gcc/config/i386/i386.h b/gcc/config/i386/i386.h
index ebe32388d80..18e3eb3b45a 100644
--- a/gcc/config/i386/i386.h
+++ b/gcc/config/i386/i386.h
@@ -1296,11 +1296,11 @@ 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 hook_bool_mode_true
#define QI_REG_P(X) (REG_P (X) && REGNO (X) <= BX_REG)
diff --git a/gcc/config/iq2000/iq2000.h b/gcc/config/iq2000/iq2000.h
index 0b207b5e8d4..fe97f206f96 100644
--- a/gcc/config/iq2000/iq2000.h
+++ b/gcc/config/iq2000/iq2000.h
@@ -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)
diff --git a/gcc/config/m32c/m32c.h b/gcc/config/m32c/m32c.h
index 78e3115c291..85dc2d1dce2 100644
--- a/gcc/config/m32c/m32c.h
+++ b/gcc/config/m32c/m32c.h
@@ -421,7 +421,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)
diff --git a/gcc/config/m68hc11/m68hc11.h b/gcc/config/m68hc11/m68hc11.h
index 278ba15c4fa..b9626e1ecca 100644
--- a/gcc/config/m68hc11/m68hc11.h
+++ b/gcc/config/m68hc11/m68hc11.h
@@ -707,7 +707,7 @@ extern enum reg_class m68hc11_tmp_regs_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
/* A C expression that is nonzero if hard register number REGNO2 can be
considered for use as a rename register for REGNO1 */
diff --git a/gcc/config/mcore/mcore.h b/gcc/config/mcore/mcore.h
index 630a11fda1e..8167400633f 100644
--- a/gcc/config/mcore/mcore.h
+++ b/gcc/config/mcore/mcore.h
@@ -406,10 +406,11 @@ enum reg_class
extern const enum reg_class 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
diff --git a/gcc/config/mips/mips-protos.h b/gcc/config/mips/mips-protos.h
index e4fbb32b959..89a00072839 100644
--- a/gcc/config/mips/mips-protos.h
+++ b/gcc/config/mips/mips-protos.h
@@ -291,6 +291,7 @@ 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);
+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);
diff --git a/gcc/config/mips/mips.c b/gcc/config/mips/mips.c
index eeff72d4b33..e246981222e 100644
--- a/gcc/config/mips/mips.c
+++ b/gcc/config/mips/mips.c
@@ -10718,6 +10718,15 @@ mips_cannot_change_mode_class (enum machine_mode from ATTRIBUTE_UNUSED,
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
diff --git a/gcc/config/mips/mips.h b/gcc/config/mips/mips.h
index f5f0bd4e4df..d5c98a6ffb8 100644
--- a/gcc/config/mips/mips.h
+++ b/gcc/config/mips/mips.h
@@ -2006,12 +2006,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.) */
diff --git a/gcc/config/mn10300/mn10300.h b/gcc/config/mn10300/mn10300.h
index 3d9933e18aa..12e78612014 100644
--- a/gcc/config/mn10300/mn10300.h
+++ b/gcc/config/mn10300/mn10300.h
@@ -237,7 +237,7 @@ extern enum processor_type mn10300_processor;
/* 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.
diff --git a/gcc/config/pdp11/pdp11.h b/gcc/config/pdp11/pdp11.h
index fe8c9e8aed3..a08f7239e10 100644
--- a/gcc/config/pdp11/pdp11.h
+++ b/gcc/config/pdp11/pdp11.h
@@ -290,7 +290,7 @@ enum reg_class { NO_REGS, MUL_REGS, GENERAL_REGS, LOAD_FPU_REGS, NO_LOAD_FPU_REG
#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. */
diff --git a/gcc/config/rx/rx.h b/gcc/config/rx/rx.h
index a053340c48a..8be66b53d9b 100644
--- a/gcc/config/rx/rx.h
+++ b/gcc/config/rx/rx.h
@@ -196,7 +196,6 @@ enum reg_class
GR_REGS, LIM_REG_CLASSES \
}
-#define SMALL_REGISTER_CLASSES 0
#define N_REG_CLASSES (int) LIM_REG_CLASSES
#define CLASS_MAX_NREGS(CLASS, MODE) ((GET_MODE_SIZE (MODE) \
+ UNITS_PER_WORD - 1) \
diff --git a/gcc/config/sh/sh-protos.h b/gcc/config/sh/sh-protos.h
index fdef756b164..d59cf6ab118 100644
--- a/gcc/config/sh/sh-protos.h
+++ b/gcc/config/sh/sh-protos.h
@@ -145,6 +145,7 @@ extern int sh_attr_renesas_p (const_tree);
extern int sh_cfun_attr_renesas_p (void);
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);
diff --git a/gcc/config/sh/sh.c b/gcc/config/sh/sh.c
index a3084b91a0b..c3293fe05a5 100644
--- a/gcc/config/sh/sh.c
+++ b/gcc/config/sh/sh.c
@@ -865,7 +865,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
@@ -9311,7 +9311,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);
@@ -11252,6 +11252,14 @@ sh_cannot_change_mode_class (enum machine_mode from, enum machine_mode to,
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. */
diff --git a/gcc/config/sh/sh.h b/gcc/config/sh/sh.h
index f870ba69e98..4eb8f397ef9 100644
--- a/gcc/config/sh/sh.h
+++ b/gcc/config/sh/sh.h
@@ -1209,11 +1209,12 @@ extern enum reg_class regno_reg_class[FIRST_PSEUDO_REGISTER];
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,
diff --git a/gcc/config/xtensa/xtensa.h b/gcc/config/xtensa/xtensa.h
index d7cab5a1ed2..80c296d930f 100644
--- a/gcc/config/xtensa/xtensa.h
+++ b/gcc/config/xtensa/xtensa.h
@@ -477,10 +477,10 @@ extern const enum reg_class xtensa_regno_to_class[FIRST_PSEUDO_REGISTER];
#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)
diff --git a/gcc/cse.c b/gcc/cse.c
index 585cce8efd0..98ef8d93d3c 100644
--- a/gcc/cse.c
+++ b/gcc/cse.c
@@ -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_mode mode,
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;
diff --git a/gcc/doc/tm.texi b/gcc/doc/tm.texi
index a20d48c9f9c..3a36314d00f 100644
--- a/gcc/doc/tm.texi
+++ b/gcc/doc/tm.texi
@@ -2868,25 +2868,6 @@ Do not define this macro if you do not define
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
@@ -4360,6 +4341,38 @@ insns involving vector mode @var{mode}. At the very least, it
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
diff --git a/gcc/gcse.c b/gcc/gcse.c
index 8e31ee11a58..033ec54f380 100644
--- a/gcc/gcse.c
+++ b/gcc/gcse.c
@@ -3479,10 +3479,10 @@ insert_insn_end_basic_block (struct expr *expr, basic_block bb, int pre)
&& (!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.
diff --git a/gcc/hooks.c b/gcc/hooks.c
index fd3c837fffe..aac44485898 100644
--- a/gcc/hooks.c
+++ b/gcc/hooks.c
@@ -70,6 +70,13 @@ hook_bool_mode_false (enum machine_mode mode ATTRIBUTE_UNUSED)
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,
diff --git a/gcc/hooks.h b/gcc/hooks.h
index 38296da2af9..5fd8296c75a 100644
--- a/gcc/hooks.h
+++ b/gcc/hooks.h
@@ -30,6 +30,7 @@ extern bool hook_bool_void_true (void);
extern bool hook_bool_bool_false (bool);
extern bool hook_bool_const_int_const_int_true (const int, const int);
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);
diff --git a/gcc/ifcvt.c b/gcc/ifcvt.c
index 1ef32414aaa..18c771bf51e 100644
--- a/gcc/ifcvt.c
+++ b/gcc/ifcvt.c
@@ -2405,8 +2405,8 @@ noce_process_if_block (struct noce_if_info *if_info)
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;
@@ -2605,7 +2605,8 @@ check_cond_move_block (basic_block bb, rtx *vals, VEC (int, heap) **regs,
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))
@@ -4061,7 +4062,8 @@ dead_or_predicable (basic_block test_bb, basic_block merge_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_noclobber, 0, i, bi)
{
diff --git a/gcc/regmove.c b/gcc/regmove.c
index 25fcc52b213..c9e947eae64 100644
--- a/gcc/regmove.c
+++ b/gcc/regmove.c
@@ -31,6 +31,7 @@ along with GCC; see the file COPYING3. If not see
#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"
@@ -239,7 +240,7 @@ optimize_reg_copy_1 (rtx insn, rtx dest, rtx src)
/* 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
diff --git a/gcc/regs.h b/gcc/regs.h
index 63235504e9c..01325b09e91 100644
--- a/gcc/regs.h
+++ b/gcc/regs.h
@@ -37,10 +37,6 @@ along with GCC; see the file COPYING3. If not see
#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;
diff --git a/gcc/reload.c b/gcc/reload.c
index 2406b6bc550..ac2fa46cb40 100644
--- a/gcc/reload.c
+++ b/gcc/reload.c
@@ -438,7 +438,8 @@ push_secondary_reload (int in_p, rtx x, int opnum, int optional,
|| (! 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))
{
@@ -731,9 +732,9 @@ find_reusable_reload (rtx *p_in, rtx out, enum reg_class rclass,
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)
@@ -747,7 +748,8 @@ find_reusable_reload (rtx *p_in, rtx out, enum reg_class rclass,
|| (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;
@@ -772,7 +774,8 @@ find_reusable_reload (rtx *p_in, rtx out, enum reg_class rclass,
&& 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))
{
@@ -1770,7 +1773,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)
@@ -1794,7 +1797,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
diff --git a/gcc/reload1.c b/gcc/reload1.c
index bd590cbc9c9..ce0b602a7cf 100644
--- a/gcc/reload1.c
+++ b/gcc/reload1.c
@@ -4281,7 +4281,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
@@ -6667,10 +6667,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
diff --git a/gcc/sched-deps.c b/gcc/sched-deps.c
index 974ffd779b0..34d20e5f654 100644
--- a/gcc/sched-deps.c
+++ b/gcc/sched-deps.c
@@ -3056,8 +3056,8 @@ sched_analyze_insn (struct deps *deps, rtx x, rtx insn)
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. */
diff --git a/gcc/target-def.h b/gcc/target-def.h
index feca6c5270c..1c734369c23 100644
--- a/gcc/target-def.h
+++ b/gcc/target-def.h
@@ -539,6 +539,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 \
@@ -975,6 +979,7 @@
TARGET_ADDR_SPACE_HOOKS, \
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, \
@@ -986,7 +991,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, \
diff --git a/gcc/target.h b/gcc/target.h
index 62a1bcc3d7e..6ff7d1d639e 100644
--- a/gcc/target.h
+++ b/gcc/target.h
@@ -762,6 +762,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. */