http://gcc.gnu.org/bugzilla/show_bug.cgi?id=59535
--- Comment #10 from Vladimir Makarov <vmakarov at gcc dot gnu.org> --- ./cc1 -Os -mthumb -mcpu=arm7tdmi -fno-short-enums test.i -m{no-}lra -fno-schedule-insns2 original reload reload with change lra with change reg moves 104 86 101 all moves 210 192 207 loads 561 569 541 stores 234 231 210 overall 1005 992 958 mov/ldr/str First of all, I can not compile the test with LRA because of its crash. The problem is in choosing alternatives different from reload. For some insn alternatives, LRA needs two hi regs for reloads. But there is only one 12, all others hi-regs are fixed. To be honest, I don't know why 12 is not fixed. It results in using 12 by IRA and bigger code when even reload is used. I believe it should fixed too. Second, big number of moves is not a bad thing. It should considered with # ld/st. LRA generates 15 more reg moves but 28 less loads and 21 less stores. It means LRA with the patch generates smaller and faster code than reload. Here is the patch improving code size for reload and fixing LRA crash and improving code for LRA. If arm part of the patch is ok, please let me know. I'll commit the patch then. The rest of the patch does not affect the test code generation but it might affect other code generated with -Os. Index: config/arm/arm.c =================================================================== --- config/arm/arm.c (revision 206089) +++ config/arm/arm.c (working copy) @@ -29236,6 +29236,7 @@ arm_conditional_register_usage (void) for (regno = FIRST_HI_REGNUM; regno <= LAST_HI_REGNUM; ++regno) fixed_regs[regno] = call_used_regs[regno] = 1; + fixed_regs[12] = call_used_regs[12] = 1; } /* The link register can be clobbered by any branch insn, Index: lra-assigns.c =================================================================== --- lra-assigns.c (revision 206089) +++ lra-assigns.c (working copy) @@ -612,7 +612,9 @@ find_hard_regno_for (int regno, int *cos && ! df_regs_ever_live_p (hard_regno + j)) /* It needs save restore. */ hard_regno_costs[hard_regno] - += 2 * ENTRY_BLOCK_PTR_FOR_FN (cfun)->next_bb->frequency + 1; + += (2 + * REG_FREQ_FROM_BB (ENTRY_BLOCK_PTR_FOR_FN (cfun)->next_bb) + + 1); priority = targetm.register_priority (hard_regno); if (best_hard_regno < 0 || hard_regno_costs[hard_regno] < best_cost || (hard_regno_costs[hard_regno] == best_cost Index: lra-coalesce.c =================================================================== --- lra-coalesce.c (revision 206089) +++ lra-coalesce.c (working copy) @@ -79,8 +79,8 @@ move_freq_compare_func (const void *v1p, rtx mv2 = *(const rtx *) v2p; int pri1, pri2; - pri1 = BLOCK_FOR_INSN (mv1)->frequency; - pri2 = BLOCK_FOR_INSN (mv2)->frequency; + pri1 = REG_FREQ_FROM_BB (BLOCK_FOR_INSN (mv1)); + pri2 = REG_FREQ_FROM_BB (BLOCK_FOR_INSN (mv2)); if (pri2 - pri1) return pri2 - pri1; @@ -277,7 +277,7 @@ lra_coalesce (void) fprintf (lra_dump_file, " Coalescing move %i:r%d-r%d (freq=%d)\n", INSN_UID (mv), sregno, dregno, - BLOCK_FOR_INSN (mv)->frequency); + REG_FREQ_FROM_BB (BLOCK_FOR_INSN (mv))); /* We updated involved_insns_bitmap when doing the merge. */ } else if (!(lra_intersected_live_ranges_p @@ -291,7 +291,7 @@ lra_coalesce (void) " Coalescing move %i:r%d(%d)-r%d(%d) (freq=%d)\n", INSN_UID (mv), sregno, ORIGINAL_REGNO (SET_SRC (set)), dregno, ORIGINAL_REGNO (SET_DEST (set)), - BLOCK_FOR_INSN (mv)->frequency); + REG_FREQ_FROM_BB (BLOCK_FOR_INSN (mv))); bitmap_ior_into (&involved_insns_bitmap, &lra_reg_info[sregno].insn_bitmap); bitmap_ior_into (&involved_insns_bitmap, @@ -316,7 +316,8 @@ lra_coalesce (void) /* Coalesced move. */ if (lra_dump_file != NULL) fprintf (lra_dump_file, " Removing move %i (freq=%d)\n", - INSN_UID (insn), BLOCK_FOR_INSN (insn)->frequency); + INSN_UID (insn), + REG_FREQ_FROM_BB (BLOCK_FOR_INSN (insn))); lra_set_insn_deleted (insn); } } Index: lra-constraints.c =================================================================== --- lra-constraints.c (revision 206089) +++ lra-constraints.c (working copy) @@ -4077,7 +4077,7 @@ lra_constraints (bool first_p) fprintf (lra_dump_file, " Removing equiv init insn %i (freq=%d)\n", INSN_UID (curr_insn), - BLOCK_FOR_INSN (curr_insn)->frequency); + REG_FREQ_FROM_BB (BLOCK_FOR_INSN (curr_insn))); dump_insn_slim (lra_dump_file, curr_insn); } if (contains_reg_p (x, true, false))