@@ -726,18 +726,31 @@ aarch64_err_no_fpadvsimd (machine_mode mode, const char *msg)
/* 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;
}
@@ -19883,7 +19883,8 @@ mips_lra_p (void)
/* 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
@@ -2853,9 +2853,9 @@ value that the middle-end intended.
@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
@@ -1849,7 +1849,7 @@ find_costs_and_classes (FILE *dump_file)
}
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],
@@ -4891,10 +4891,10 @@ This is currently used only by the C and C++ front ends.",
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. */
@@ -148,7 +148,8 @@ extern rtx default_static_chain (const_tree, bool);
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);
@@ -899,7 +899,8 @@ default_branch_target_register_class (void)
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;
}