[PATCH] Fix IRA register preferencing
Wilco Dijkstra
wdijkstr@arm.com
Tue Dec 9 19:21:00 GMT 2014
This fixes a bug in register preferencing. When live range splitting creates a new register from
another, it copies most fields except for the register preferences. The preference GENERAL_REGS is
used as reg_pref[i].prefclass is initialized with GENERAL_REGS in allocate_reg_info () and
resize_reg_info ().
This initialization value is not innocuous like the comment suggests - if a new register has a
non-integer mode, it is forced to prefer GENERAL_REGS. This changes the register costs in pass 2 so
that they are incorrect. As a result the liverange is either spilled or allocated to an integer
register:
void g(double);
void f(double x)
{
if (x == 0)
return;
g (x);
g (x);
}
f:
fcmp d0, #0.0
bne .L6
ret
.L6:
stp x19, x30, [sp, -16]!
fmov x19, d0
bl g
fmov d0, x19
ldp x19, x30, [sp], 16
b g
With the fix it uses a floating point register as expected. Given a similar issue in
https://gcc.gnu.org/ml/gcc-patches/2014-11/msg02253.html, would it not be better to change the
initialization values of reg_pref to illegal register classes so this kind of issue can be trivially
found with an assert? Also would it not be a good idea to have a single register copy function that
ensures all data is copied?
ChangeLog: 2014-12-09 Wilco Dijkstra wdijkstr@arm.com
* gcc/ira-emit.c (ira_create_new_reg): Copy preference classes.
---
gcc/ira-emit.c | 11 ++++++++++-
1 file changed, 10 insertions(+), 1 deletion(-)
diff --git a/gcc/ira-emit.c b/gcc/ira-emit.c
index d246b7f..d736836 100644
--- a/gcc/ira-emit.c
+++ b/gcc/ira-emit.c
@@ -348,6 +348,7 @@ rtx
ira_create_new_reg (rtx original_reg)
{
rtx new_reg;
+ int original_regno = REGNO (original_reg);
new_reg = gen_reg_rtx (GET_MODE (original_reg));
ORIGINAL_REGNO (new_reg) = ORIGINAL_REGNO (original_reg);
@@ -356,8 +357,16 @@ ira_create_new_reg (rtx original_reg)
REG_ATTRS (new_reg) = REG_ATTRS (original_reg);
if (internal_flag_ira_verbose > 3 && ira_dump_file != NULL)
fprintf (ira_dump_file, " Creating newreg=%i from oldreg=%i\n",
- REGNO (new_reg), REGNO (original_reg));
+ REGNO (new_reg), original_regno);
ira_expand_reg_equiv ();
+
+ /* Copy the preference classes to new_reg. */
+ resize_reg_info ();
+ setup_reg_classes (REGNO (new_reg),
+ reg_preferred_class (original_regno),
+ reg_alternate_class (original_regno),
+ reg_allocno_class (original_regno));
+
return new_reg;
}
--
1.9.1
More information about the Gcc-patches
mailing list