Ping of https://gcc.gnu.org/ml/gcc-patches/2014-12/msg00829.html:
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 wdijk...@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