diff options
Diffstat (limited to 'gcc/lra-constraints.c')
-rw-r--r-- | gcc/lra-constraints.c | 131 |
1 files changed, 129 insertions, 2 deletions
diff --git a/gcc/lra-constraints.c b/gcc/lra-constraints.c index f667512337f..e9cb1adeff4 100644 --- a/gcc/lra-constraints.c +++ b/gcc/lra-constraints.c @@ -1228,7 +1228,7 @@ simplify_operand_subreg (int nop, enum machine_mode reg_mode) if (get_reload_reg (curr_static_id->operand[nop].type, reg_mode, reg, rclass, "subreg reg", &new_reg)) { - bitmap_set_bit (&lra_optional_reload_pseudos, REGNO (new_reg)); + bitmap_set_bit (&lra_subreg_reload_pseudos, REGNO (new_reg)); if (type != OP_OUT || GET_MODE_SIZE (GET_MODE (reg)) > GET_MODE_SIZE (mode)) { @@ -3183,6 +3183,8 @@ curr_insn_transform (void) for (i = 0; i < n_operands; i++) { + int regno; + bool optional_p = false; rtx old, new_reg; rtx op = *curr_id->operand_loc[i]; @@ -3205,7 +3207,22 @@ curr_insn_transform (void) current one. */ reg_renumber[regno] = -1; } - continue; + /* We can do an optional reload. If the pseudo got a hard + reg, we might improve the code through inheritance. If + it does not get a hard register we coalesce memory/memory + moves later. Ignore move insns to avoid cycling. */ + if (0 && ! lra_simple_p + && lra_undo_inheritance_iter < LRA_MAX_INHERITANCE_PASSES + && goal_alt[i] != NO_REGS && REG_P (op) + && (regno = REGNO (op)) >= FIRST_PSEUDO_REGISTER + && reg_renumber[regno] < 0 + && (curr_insn_set == NULL_RTX + || !(REG_P (SET_SRC (curr_insn_set)) + || MEM_P (SET_SRC (curr_insn_set)) + || GET_CODE (SET_SRC (curr_insn_set)) == SUBREG))) + optional_p = true; + else + continue; } /* Operands that match previous ones have already been handled. */ @@ -3328,6 +3345,21 @@ curr_insn_transform (void) /* We must generate code in any case when function process_alt_operands decides that it is possible. */ gcc_unreachable (); + if (optional_p) + { + lra_assert (REG_P (op)); + regno = REGNO (op); + op = *curr_id->operand_loc[i]; /* Substitution. */ + if (GET_CODE (op) == SUBREG) + op = SUBREG_REG (op); + gcc_assert (REG_P (op) && (int) REGNO (op) >= new_regno_start); + bitmap_set_bit (&lra_optional_reload_pseudos, REGNO (op)); + lra_reg_info[REGNO (op)].restore_regno = regno; + if (lra_dump_file != NULL) + fprintf (lra_dump_file, + " Making reload reg %d for reg %d optional\n", + REGNO (op), regno); + } } if (before != NULL_RTX || after != NULL_RTX || max_regno_before != max_reg_num ()) @@ -5273,6 +5305,100 @@ remove_inheritance_pseudos (bitmap remove_pseudos) return change_p; } +/* If optional reload pseudos failed to get a hard register or was not + inherited, it is better to remove optional reloads. We do this + transformation after undoing inheritance to figure out necessity to + remove optional reloads easier. Return true if we do any + change. */ +static bool +undo_optional_reloads (void) +{ + bool change_p; + unsigned int regno, uid; + bitmap_iterator bi, bi2; + rtx insn, set, src, dest; + bitmap_head removed_optional_reload_pseudos, insn_bitmap; + + bitmap_initialize (&removed_optional_reload_pseudos, ®_obstack); + bitmap_copy (&removed_optional_reload_pseudos, &lra_optional_reload_pseudos); + EXECUTE_IF_SET_IN_BITMAP (&lra_optional_reload_pseudos, 0, regno, bi) + if (reg_renumber[regno] >= 0) + EXECUTE_IF_SET_IN_BITMAP (&lra_reg_info[regno].insn_bitmap, 0, uid, bi2) + { + insn = lra_insn_recog_data[uid]->insn; + if ((set = single_set (insn)) == NULL_RTX) + continue; + src = SET_SRC (set); + dest = SET_DEST (set); + if (! REG_P (src) || ! REG_P (dest)) + continue; + if ((REGNO (src) == regno + && lra_reg_info[regno].restore_regno != (int) REGNO (dest)) + || (REGNO (dest) == regno + && lra_reg_info[regno].restore_regno != (int) REGNO (src))) + { + /* Optional reload was inherited. Keep it. */ + bitmap_clear_bit (&removed_optional_reload_pseudos, regno); + if (lra_dump_file != NULL) + fprintf (lra_dump_file, "Keep optional reload reg %d\n", regno); + } + } + change_p = ! bitmap_empty_p (&removed_optional_reload_pseudos); + bitmap_initialize (&insn_bitmap, ®_obstack); + EXECUTE_IF_SET_IN_BITMAP (&removed_optional_reload_pseudos, 0, regno, bi) + { + if (lra_dump_file != NULL) + fprintf (lra_dump_file, "Remove optional reload reg %d\n", regno); + bitmap_copy (&insn_bitmap, &lra_reg_info[regno].insn_bitmap); + EXECUTE_IF_SET_IN_BITMAP (&insn_bitmap, 0, uid, bi2) + { + insn = lra_insn_recog_data[uid]->insn; + if ((set = single_set (insn)) != NULL_RTX) + { + src = SET_SRC (set); + dest = SET_DEST (set); + if (REG_P (src) && REG_P (dest) + && ((REGNO (src) == regno + && (lra_reg_info[regno].restore_regno + == (int) REGNO (dest))) + || (REGNO (dest) == regno + && (lra_reg_info[regno].restore_regno + == (int) REGNO (src))))) + { + if (lra_dump_file != NULL) + { + fprintf (lra_dump_file, " Deleting move %u\n", + INSN_UID (insn)); + dump_insn_slim (lra_dump_file, insn); + } + lra_set_insn_deleted (insn); + continue; + } + /* We should not worry about generation memory-memory + moves here as if the corresponding inheritance did + not work (inheritance pseudo did not get a hard reg), + we remove the inheritance pseudo and the optional + reload. */ + } + substitute_pseudo (&insn, regno, + regno_reg_rtx[lra_reg_info[regno].restore_regno]); + lra_update_insn_regno_info (insn); + if (lra_dump_file != NULL) + { + fprintf (lra_dump_file, + " Restoring original insn:\n"); + dump_insn_slim (lra_dump_file, insn); + } + } + } + /* Clear restore_regnos. */ + EXECUTE_IF_SET_IN_BITMAP (&lra_optional_reload_pseudos, 0, regno, bi) + lra_reg_info[regno].restore_regno = -1; + bitmap_clear (&insn_bitmap); + bitmap_clear (&removed_optional_reload_pseudos); + return change_p; +} + /* Entry function for undoing inheritance/split transformation. Return true if we did any RTL change in this pass. */ bool @@ -5335,5 +5461,6 @@ lra_undo_inheritance (void) lra_reg_info[regno].restore_regno = -1; EXECUTE_IF_SET_IN_BITMAP (&lra_split_regs, 0, regno, bi) lra_reg_info[regno].restore_regno = -1; + change_p = undo_optional_reloads () || change_p; return change_p; } |