diff options
Diffstat (limited to 'gcc/lra-constraints.c')
-rw-r--r-- | gcc/lra-constraints.c | 131 |
1 files changed, 101 insertions, 30 deletions
diff --git a/gcc/lra-constraints.c b/gcc/lra-constraints.c index 4c88cca669d..14018849392 100644 --- a/gcc/lra-constraints.c +++ b/gcc/lra-constraints.c @@ -1,5 +1,5 @@ /* Code for RTL transformations to satisfy insn constraints. - Copyright (C) 2010-2013 Free Software Foundation, Inc. + Copyright (C) 2010-2014 Free Software Foundation, Inc. Contributed by Vladimir Makarov <vmakarov@redhat.com>. This file is part of GCC. @@ -271,9 +271,11 @@ in_class_p (rtx reg, enum reg_class cl, enum reg_class *new_class) where other reload pseudos are no longer allocatable. */ || (INSN_UID (curr_insn) >= new_insn_uid_start && curr_insn_set != NULL - && (OBJECT_P (SET_SRC (curr_insn_set)) + && ((OBJECT_P (SET_SRC (curr_insn_set)) + && ! CONSTANT_P (SET_SRC (curr_insn_set))) || (GET_CODE (SET_SRC (curr_insn_set)) == SUBREG - && OBJECT_P (SUBREG_REG (SET_SRC (curr_insn_set))))))) + && OBJECT_P (SUBREG_REG (SET_SRC (curr_insn_set))) + && ! CONSTANT_P (SUBREG_REG (SET_SRC (curr_insn_set))))))) /* When we don't know what class will be used finally for reload pseudos, we use ALL_REGS. */ return ((regno >= new_regno_start && rclass == ALL_REGS) @@ -315,10 +317,48 @@ in_mem_p (int regno) return get_reg_class (regno) == NO_REGS; } +/* Initiate equivalences for LRA. As we keep original equivalences + before any elimination, we need to make copies otherwise any change + in insns might change the equivalences. */ +void +lra_init_equiv (void) +{ + ira_expand_reg_equiv (); + for (int i = FIRST_PSEUDO_REGISTER; i < max_reg_num (); i++) + { + rtx res; + + if ((res = ira_reg_equiv[i].memory) != NULL_RTX) + ira_reg_equiv[i].memory = copy_rtx (res); + if ((res = ira_reg_equiv[i].invariant) != NULL_RTX) + ira_reg_equiv[i].invariant = copy_rtx (res); + } +} + +static rtx loc_equivalence_callback (rtx, const_rtx, void *); + +/* Update equivalence for REGNO. We need to this as the equivalence + might contain other pseudos which are changed by their + equivalences. */ +static void +update_equiv (int regno) +{ + rtx x; + + if ((x = ira_reg_equiv[regno].memory) != NULL_RTX) + ira_reg_equiv[regno].memory + = simplify_replace_fn_rtx (x, NULL_RTX, loc_equivalence_callback, + NULL_RTX); + if ((x = ira_reg_equiv[regno].invariant) != NULL_RTX) + ira_reg_equiv[regno].invariant + = simplify_replace_fn_rtx (x, NULL_RTX, loc_equivalence_callback, + NULL_RTX); +} + /* If we have decided to substitute X with another value, return that value, otherwise return X. */ static rtx -get_equiv_substitution (rtx x) +get_equiv (rtx x) { int regno; rtx res; @@ -337,6 +377,19 @@ get_equiv_substitution (rtx x) gcc_unreachable (); } +/* If we have decided to substitute X with the equivalent value, + return that value after elimination for INSN, otherwise return + X. */ +static rtx +get_equiv_with_elimination (rtx x, rtx insn) +{ + rtx res = get_equiv (x); + + if (x == res || CONSTANT_P (res)) + return res; + return lra_eliminate_regs_1 (insn, res, GET_MODE (res), false, false, true); +} + /* Set up curr_operand_mode. */ static void init_curr_operand_mode (void) @@ -1101,7 +1154,7 @@ process_addr_reg (rtx *loc, rtx *before, rtx *after, enum reg_class cl) { regno = REGNO (reg); rclass = get_reg_class (regno); - if ((*loc = get_equiv_substitution (reg)) != reg) + if ((*loc = get_equiv_with_elimination (reg, curr_insn)) != reg) { if (lra_dump_file != NULL) { @@ -2007,6 +2060,13 @@ process_alt_operands (int only_alternative) int const_to_mem = 0; bool no_regs_p; + /* Never do output reload of stack pointer. It makes + impossible to do elimination when SP is changed in + RTL. */ + if (op == stack_pointer_rtx && ! frame_pointer_needed + && curr_static_id->operand[nop].type != OP_IN) + goto fail; + /* If this alternative asks for a specific reg class, see if there is at least one allocatable register in that class. */ no_regs_p @@ -2517,7 +2577,7 @@ equiv_address_substitution (struct address_info *ad) else { base_reg = *base_term; - new_base_reg = get_equiv_substitution (base_reg); + new_base_reg = get_equiv_with_elimination (base_reg, curr_insn); } index_term = strip_subreg (ad->index_term); if (index_term == NULL) @@ -2525,7 +2585,7 @@ equiv_address_substitution (struct address_info *ad) else { index_reg = *index_term; - new_index_reg = get_equiv_substitution (index_reg); + new_index_reg = get_equiv_with_elimination (index_reg, curr_insn); } if (base_reg == new_base_reg && index_reg == new_index_reg) return false; @@ -3055,7 +3115,7 @@ curr_insn_transform (void) if (GET_CODE (old) == SUBREG) old = SUBREG_REG (old); - subst = get_equiv_substitution (old); + subst = get_equiv_with_elimination (old, curr_insn); if (subst != old) { subst = copy_rtx (subst); @@ -3260,6 +3320,9 @@ curr_insn_transform (void) if (INSN_CODE (curr_insn) >= 0 && (p = get_insn_name (INSN_CODE (curr_insn))) != NULL) fprintf (lra_dump_file, " {%s}", p); + if (curr_id->sp_offset != 0) + fprintf (lra_dump_file, " (sp_off=%" HOST_WIDE_INT_PRINT "d)", + curr_id->sp_offset); fprintf (lra_dump_file, "\n"); } @@ -3638,7 +3701,7 @@ loc_equivalence_change_p (rtx *loc) if (code == SUBREG) { reg = SUBREG_REG (x); - if ((subst = get_equiv_substitution (reg)) != reg + if ((subst = get_equiv_with_elimination (reg, curr_insn)) != reg && GET_MODE (subst) == VOIDmode) { /* We cannot reload debug location. Simplify subreg here @@ -3648,7 +3711,7 @@ loc_equivalence_change_p (rtx *loc) return true; } } - if (code == REG && (subst = get_equiv_substitution (x)) != x) + if (code == REG && (subst = get_equiv_with_elimination (x, curr_insn)) != x) { *loc = subst; return true; @@ -3669,14 +3732,16 @@ loc_equivalence_change_p (rtx *loc) } /* Similar to loc_equivalence_change_p, but for use as - simplify_replace_fn_rtx callback. */ + simplify_replace_fn_rtx callback. DATA is insn for which the + elimination is done. If it null we don't do the elimination. */ static rtx -loc_equivalence_callback (rtx loc, const_rtx, void *) +loc_equivalence_callback (rtx loc, const_rtx, void *data) { if (!REG_P (loc)) return NULL_RTX; - rtx subst = get_equiv_substitution (loc); + rtx subst = (data == NULL + ? get_equiv (loc) : get_equiv_with_elimination (loc, (rtx) data)); if (subst != loc) return subst; @@ -3848,21 +3913,27 @@ lra_constraints (bool first_p) lra_risky_transformations_p = false; new_insn_uid_start = get_max_uid (); new_regno_start = first_p ? lra_constraint_new_regno_start : max_reg_num (); + /* Mark used hard regs for target stack size calulations. */ + for (i = FIRST_PSEUDO_REGISTER; i < new_regno_start; i++) + if (lra_reg_info[i].nrefs != 0 + && (hard_regno = lra_get_regno_hard_regno (i)) >= 0) + { + int j, nregs; + + nregs = hard_regno_nregs[hard_regno][lra_reg_info[i].biggest_mode]; + for (j = 0; j < nregs; j++) + df_set_regs_ever_live (hard_regno + j, true); + } + /* Do elimination before the equivalence processing as we can spill + some pseudos during elimination. */ + lra_eliminate (false, first_p); bitmap_initialize (&equiv_insn_bitmap, ®_obstack); for (i = FIRST_PSEUDO_REGISTER; i < new_regno_start; i++) if (lra_reg_info[i].nrefs != 0) { ira_reg_equiv[i].profitable_p = true; reg = regno_reg_rtx[i]; - if ((hard_regno = lra_get_regno_hard_regno (i)) >= 0) - { - int j, nregs; - - nregs = hard_regno_nregs[hard_regno][lra_reg_info[i].biggest_mode]; - for (j = 0; j < nregs; j++) - df_set_regs_ever_live (hard_regno + j, true); - } - else if ((x = get_equiv_substitution (reg)) != reg) + if (lra_get_regno_hard_regno (i) < 0 && (x = get_equiv (reg)) != reg) { bool pseudo_p = contains_reg_p (x, false, false); @@ -3911,15 +3982,16 @@ lra_constraints (bool first_p) ira_reg_equiv[i].defined_p = false; if (contains_reg_p (x, false, true)) ira_reg_equiv[i].profitable_p = false; - if (get_equiv_substitution (reg) != reg) + if (get_equiv (reg) != reg) bitmap_ior_into (&equiv_insn_bitmap, &lra_reg_info[i].insn_bitmap); } } + for (i = FIRST_PSEUDO_REGISTER; i < new_regno_start; i++) + update_equiv (i); /* We should add all insns containing pseudos which should be substituted by their equivalences. */ EXECUTE_IF_SET_IN_BITMAP (&equiv_insn_bitmap, 0, uid, bi) lra_push_insn_by_uid (uid); - lra_eliminate (false); min_len = lra_insn_stack_length (); new_insns_num = 0; last_bb = NULL; @@ -3954,7 +4026,7 @@ lra_constraints (bool first_p) rtx old = *curr_id->operand_loc[0]; *curr_id->operand_loc[0] = simplify_replace_fn_rtx (old, NULL_RTX, - loc_equivalence_callback, NULL); + loc_equivalence_callback, curr_insn); if (old != *curr_id->operand_loc[0]) { lra_update_insn_regno_info (curr_insn); @@ -3973,7 +4045,7 @@ lra_constraints (bool first_p) if (GET_CODE (dest_reg) == SUBREG) dest_reg = SUBREG_REG (dest_reg); if ((REG_P (dest_reg) - && (x = get_equiv_substitution (dest_reg)) != dest_reg + && (x = get_equiv (dest_reg)) != dest_reg /* Remove insns which set up a pseudo whose value can not be changed. Such insns might be not in init_insns because we don't update equiv data @@ -3993,8 +4065,7 @@ lra_constraints (bool first_p) || in_list_p (curr_insn, ira_reg_equiv [REGNO (dest_reg)].init_insns))) - || (((x = get_equiv_substitution (SET_SRC (set))) - != SET_SRC (set)) + || (((x = get_equiv (SET_SRC (set))) != SET_SRC (set)) && in_list_p (curr_insn, ira_reg_equiv [REGNO (SET_SRC (set))].init_insns))) @@ -5273,7 +5344,7 @@ lra_inheritance (void) bitmap_initialize (&live_regs, ®_obstack); bitmap_initialize (&temp_bitmap, ®_obstack); bitmap_initialize (&ebb_global_regs, ®_obstack); - FOR_EACH_BB (bb) + FOR_EACH_BB_FN (bb, cfun) { start_bb = bb; if (lra_dump_file != NULL) @@ -5374,7 +5445,7 @@ remove_inheritance_pseudos (bitmap remove_pseudos) because we need to marks insns affected by previous inheritance/split pass for processing by the subsequent constraint pass. */ - FOR_EACH_BB (bb) + FOR_EACH_BB_FN (bb, cfun) { fix_bb_live_info (df_get_live_in (bb), remove_pseudos); fix_bb_live_info (df_get_live_out (bb), remove_pseudos); |