aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gcc/ChangeLog13
-rw-r--r--gcc/config/aarch64/aarch64.c21
-rw-r--r--gcc/config/mips/mips.c3
-rw-r--r--gcc/doc/tm.texi4
-rw-r--r--gcc/ira-costs.c2
-rw-r--r--gcc/target.def4
-rw-r--r--gcc/targhooks.c3
-rw-r--r--gcc/targhooks.h3
8 files changed, 41 insertions, 12 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 57a7df7..0e72ed1 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,5 +1,18 @@
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.
diff --git a/gcc/config/aarch64/aarch64.c b/gcc/config/aarch64/aarch64.c
index e7cfcb6..3ff12ff 100644
--- a/gcc/config/aarch64/aarch64.c
+++ b/gcc/config/aarch64/aarch64.c
@@ -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;
}
diff --git a/gcc/config/mips/mips.c b/gcc/config/mips/mips.c
index 9ec2dcb..697abc2 100644
--- a/gcc/config/mips/mips.c
+++ b/gcc/config/mips/mips.c
@@ -19916,7 +19916,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
diff --git a/gcc/doc/tm.texi b/gcc/doc/tm.texi
index 2392691..faf8bcb 100644
--- a/gcc/doc/tm.texi
+++ b/gcc/doc/tm.texi
@@ -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
diff --git a/gcc/ira-costs.c b/gcc/ira-costs.c
index 2b736c1..f3d31e1 100644
--- a/gcc/ira-costs.c
+++ b/gcc/ira-costs.c
@@ -1858,7 +1858,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],
diff --git a/gcc/target.def b/gcc/target.def
index fa0af67..f139ef9 100644
--- a/gcc/target.def
+++ b/gcc/target.def
@@ -4874,10 +4874,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. */
diff --git a/gcc/targhooks.c b/gcc/targhooks.c
index 8a162a1..fa6a43d 100644
--- a/gcc/targhooks.c
+++ b/gcc/targhooks.c
@@ -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;
}
diff --git a/gcc/targhooks.h b/gcc/targhooks.h
index 7ab647f..7687c39 100644
--- a/gcc/targhooks.h
+++ b/gcc/targhooks.h
@@ -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);