2016-02-02 Wilco Dijkstra <wdijkstr@arm.com>
+ * ira-costs.c (find_costs_and_classes): Add extra argument.
+ * target.def (ira_change_pseudo_allocno_class): Add parameter.
+ * targhooks.h (ira_change_pseudo_allocno_class): Likewise.
+ * targhooks.c (ira_change_pseudo_allocno_class): Likewise.
+ * config/aarch64/aarch64.c (aarch64_ira_change_pseudo_allocno_class)
+ Add best_class parameter, and return it if not ALL_REGS.
+ * config/mips/mips.c (mips_ira_change_pseudo_allocno_class):
+ Add parameter.
+ * doc/tm.texi (TARGET_IRA_CHANGE_PSEUDO_ALLOCNO_CLASS):
+ Update target hook.
+
+2016-02-02 Wilco Dijkstra <wdijkstr@arm.com>
+
* config/aarch64/aarch64.c
(TARGET_IRA_CHANGE_PSEUDO_ALLOCNO_CLASS): New define.
(aarch64_ira_change_pseudo_allocno_class): New function.
/* Implement TARGET_IRA_CHANGE_PSEUDO_ALLOCNO_CLASS.
The register allocator chooses ALL_REGS if FP_REGS and GENERAL_REGS have
- the same cost even if ALL_REGS has a much larger cost. This results in bad
- allocations and spilling. To avoid this we force the class to GENERAL_REGS
- if the mode is integer. */
+ the same cost even if ALL_REGS has a much larger cost. ALL_REGS is also
+ used if the cost of both FP_REGS and GENERAL_REGS is lower than the memory
+ cost (in this case the best class is the lowest cost one). Using ALL_REGS
+ irrespectively of its cost results in bad allocations with many redundant
+ int<->FP moves which are expensive on various cores.
+ To avoid this we don't allow ALL_REGS as the allocno class, but force a
+ decision between FP_REGS and GENERAL_REGS. We use the allocno class if it
+ isn't ALL_REGS. Similarly, use the best class if it isn't ALL_REGS.
+ Otherwise set the allocno class depending on the mode.
+ The result of this is that it is no longer inefficient to have a higher
+ memory move cost than the register move cost.
+*/
static reg_class_t
-aarch64_ira_change_pseudo_allocno_class (int regno, reg_class_t allocno_class)
+aarch64_ira_change_pseudo_allocno_class (int regno, reg_class_t allocno_class,
+ reg_class_t best_class)
{
enum machine_mode mode;
if (allocno_class != ALL_REGS)
return allocno_class;
+ if (best_class != ALL_REGS)
+ return best_class;
+
mode = PSEUDO_REGNO_MODE (regno);
return FLOAT_MODE_P (mode) || VECTOR_MODE_P (mode) ? FP_REGS : GENERAL_REGS;
}
/* Implement TARGET_IRA_CHANGE_PSEUDO_ALLOCNO_CLASS. */
static reg_class_t
-mips_ira_change_pseudo_allocno_class (int regno, reg_class_t allocno_class)
+mips_ira_change_pseudo_allocno_class (int regno, reg_class_t allocno_class,
+ reg_class_t best_class ATTRIBUTE_UNUSED)
{
/* LRA will allocate an FPR for an integer mode pseudo instead of spilling
to memory if an FPR is present in the allocno class. It is rare that
@end defmac
-@deftypefn {Target Hook} reg_class_t TARGET_IRA_CHANGE_PSEUDO_ALLOCNO_CLASS (int, @var{reg_class_t})
+@deftypefn {Target Hook} reg_class_t TARGET_IRA_CHANGE_PSEUDO_ALLOCNO_CLASS (int, @var{reg_class_t}, @var{reg_class_t})
A target hook which can change allocno class for given pseudo from
- allocno class calculated by IRA.
+ allocno and best class calculated by IRA.
The default version of this target hook always returns given class.
@end deftypefn
}
if ((new_class
= (reg_class) (targetm.ira_change_pseudo_allocno_class
- (i, regno_aclass[i]))) != regno_aclass[i])
+ (i, regno_aclass[i], best))) != regno_aclass[i])
{
regno_aclass[i] = new_class;
if (hard_reg_set_subset_p (reg_class_contents[new_class],
DEFHOOK
(ira_change_pseudo_allocno_class,
"A target hook which can change allocno class for given pseudo from\n\
- allocno class calculated by IRA.\n\
+ allocno and best class calculated by IRA.\n\
\n\
The default version of this target hook always returns given class.",
- reg_class_t, (int, reg_class_t),
+ reg_class_t, (int, reg_class_t, reg_class_t),
default_ira_change_pseudo_allocno_class)
/* Return true if we use LRA instead of reload. */
reg_class_t
default_ira_change_pseudo_allocno_class (int regno ATTRIBUTE_UNUSED,
- reg_class_t cl)
+ reg_class_t cl,
+ reg_class_t best_cl ATTRIBUTE_UNUSED)
{
return cl;
}
extern void default_trampoline_init (rtx, tree, rtx);
extern int default_return_pops_args (tree, tree, int);
extern reg_class_t default_branch_target_register_class (void);
-extern reg_class_t default_ira_change_pseudo_allocno_class (int, reg_class_t);
+extern reg_class_t default_ira_change_pseudo_allocno_class (int, reg_class_t,
+ reg_class_t);
extern bool default_lra_p (void);
extern int default_register_priority (int);
extern bool default_register_usage_leveling_p (void);