diff options
author | bstarynk <bstarynk@138bc75d-0d04-0410-961f-82ee72b054a4> | 2012-10-31 10:18:27 +0000 |
---|---|---|
committer | bstarynk <bstarynk@138bc75d-0d04-0410-961f-82ee72b054a4> | 2012-10-31 10:18:27 +0000 |
commit | d42d3fad6998402ea943bc2a3159cad09eb288d5 (patch) | |
tree | d70dbc97eb104b1c403ef6d4cff46da1ebf52c76 /gcc/lra-constraints.c | |
parent | 8422fa6afbb619fc66678c664bfaf834691527fc (diff) | |
download | gcc-d42d3fad6998402ea943bc2a3159cad09eb288d5.tar.gz |
2012-10-31 Basile Starynkevitch <basile@starynkevitch.net>
MELT branch merged with trunk rev 193029 using svnmerge.py
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/branches/melt-branch@193030 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/lra-constraints.c')
-rw-r--r-- | gcc/lra-constraints.c | 922 |
1 files changed, 354 insertions, 568 deletions
diff --git a/gcc/lra-constraints.c b/gcc/lra-constraints.c index 4b357261bbe..7f19ad1f43c 100644 --- a/gcc/lra-constraints.c +++ b/gcc/lra-constraints.c @@ -87,7 +87,7 @@ r <- ... or ... <- r r <- ... or ... <- r ... s <- r (new insn -- save) - ... => + ... => ... r <- s (new insn -- restore) ... <- r ... <- r @@ -152,6 +152,13 @@ static enum machine_mode curr_operand_mode[MAX_RECOG_OPERANDS]; static int new_regno_start; static int new_insn_uid_start; +/* If LOC is nonnull, strip any outer subreg from it. */ +static inline rtx * +strip_subreg (rtx *loc) +{ + return loc && GET_CODE (*loc) == SUBREG ? &SUBREG_REG (*loc) : loc; +} + /* Return hard regno of REGNO or if it is was not assigned to a hard register, use a hard register from its allocno class. */ static int @@ -243,14 +250,14 @@ in_class_p (rtx reg, enum reg_class cl, enum reg_class *new_class) enum machine_mode reg_mode; int class_size, hard_regno, nregs, i, j; int regno = REGNO (reg); - + if (new_class != NULL) *new_class = NO_REGS; if (regno < FIRST_PSEUDO_REGISTER) { rtx final_reg = reg; rtx *final_loc = &final_reg; - + lra_eliminate_reg_if_possible (final_loc); return TEST_HARD_REG_BIT (reg_class_contents[cl], REGNO (*final_loc)); } @@ -435,34 +442,12 @@ get_reload_reg (enum op_type type, enum machine_mode mode, rtx original, /* The page contains code to extract memory address parts. */ -/* Info about base and index regs of an address. In some rare cases, - base/index register can be actually memory. In this case we will - reload it. */ -struct address -{ - /* NULL if there is no a base register. */ - rtx *base_reg_loc; - /* Second location of {post/pre}_modify, NULL otherwise. */ - rtx *base_reg_loc2; - /* NULL if there is no an index register. */ - rtx *index_reg_loc; - /* Location of index reg * scale or index_reg_loc otherwise. */ - rtx *index_loc; - /* NULL if there is no a displacement. */ - rtx *disp_loc; - /* Defined if base_reg_loc is not NULL. */ - enum rtx_code base_outer_code, index_code; - /* True if the base register is modified in the address, for - example, in PRE_INC. */ - bool base_modify_p; -}; - /* Wrapper around REGNO_OK_FOR_INDEX_P, to allow pseudos. */ static inline bool ok_for_index_p_nonstrict (rtx reg) { unsigned regno = REGNO (reg); - + return regno >= FIRST_PSEUDO_REGISTER || REGNO_OK_FOR_INDEX_P (regno); } @@ -479,283 +464,6 @@ ok_for_base_p_nonstrict (rtx reg, enum machine_mode mode, addr_space_t as, return ok_for_base_p_1 (regno, mode, as, outer_code, index_code); } -/* Process address part in space AS (or all address if TOP_P) with - location *LOC to extract address characteristics. - - If CONTEXT_P is false, we are looking at the base part of an - address, otherwise we are looking at the index part. - - MODE is the mode of the memory reference; OUTER_CODE and INDEX_CODE - give the context that the rtx appears in; MODIFY_P if *LOC is - modified. */ -static void -extract_loc_address_regs (bool top_p, enum machine_mode mode, addr_space_t as, - rtx *loc, bool context_p, enum rtx_code outer_code, - enum rtx_code index_code, - bool modify_p, struct address *ad) -{ - rtx x = *loc; - enum rtx_code code = GET_CODE (x); - bool base_ok_p; - - switch (code) - { - case CONST_INT: - case CONST: - case SYMBOL_REF: - case LABEL_REF: - if (! context_p) - { - lra_assert (top_p); - ad->disp_loc = loc; - } - return; - - case CC0: - case PC: - return; - - case ZERO_EXTEND: - /* Pass TOP_P for displacement. */ - extract_loc_address_regs (top_p, mode, as, &XEXP (*loc, 0), context_p, - code, index_code, modify_p, ad); - return; - - case PLUS: - case LO_SUM: - /* When we have an address that is a sum, we must determine - whether registers are "base" or "index" regs. If there is a - sum of two registers, we must choose one to be the - "base". */ - { - rtx *arg0_loc = &XEXP (x, 0); - rtx *arg1_loc = &XEXP (x, 1); - rtx *tloc; - rtx arg0 = *arg0_loc; - rtx arg1 = *arg1_loc; - enum rtx_code code0 = GET_CODE (arg0); - enum rtx_code code1 = GET_CODE (arg1); - - /* Look inside subregs. */ - if (code0 == SUBREG) - { - arg0_loc = &SUBREG_REG (arg0); - arg0 = *arg0_loc; - code0 = GET_CODE (arg0); - } - if (code1 == SUBREG) - { - arg1_loc = &SUBREG_REG (arg1); - arg1 = *arg1_loc; - code1 = GET_CODE (arg1); - } - - if (CONSTANT_P (arg0) - || code1 == PLUS || code1 == MULT || code1 == ASHIFT) - { - tloc = arg1_loc; - arg1_loc = arg0_loc; - arg0_loc = tloc; - arg0 = *arg0_loc; - code0 = GET_CODE (arg0); - arg1 = *arg1_loc; - code1 = GET_CODE (arg1); - } - /* If this machine only allows one register per address, it - must be in the first operand. */ - if (MAX_REGS_PER_ADDRESS == 1 || code == LO_SUM) - { - lra_assert (ad->disp_loc == NULL); - ad->disp_loc = arg1_loc; - extract_loc_address_regs (false, mode, as, arg0_loc, false, code, - code1, modify_p, ad); - } - /* Base + disp addressing */ - else if (code0 != PLUS && code0 != MULT && code0 != ASHIFT - && CONSTANT_P (arg1)) - { - lra_assert (ad->disp_loc == NULL); - ad->disp_loc = arg1_loc; - extract_loc_address_regs (false, mode, as, arg0_loc, false, PLUS, - code1, modify_p, ad); - } - /* If index and base registers are the same on this machine, - just record registers in any non-constant operands. We - assume here, as well as in the tests below, that all - addresses are in canonical form. */ - else if (INDEX_REG_CLASS - == base_reg_class (VOIDmode, as, PLUS, SCRATCH) - && code0 != PLUS && code0 != MULT && code0 != ASHIFT) - { - extract_loc_address_regs (false, mode, as, arg0_loc, false, PLUS, - code1, modify_p, ad); - lra_assert (! CONSTANT_P (arg1)); - extract_loc_address_regs (false, mode, as, arg1_loc, true, PLUS, - code0, modify_p, ad); - } - /* It might be [base + ]index * scale + disp. */ - else if (CONSTANT_P (arg1)) - { - lra_assert (ad->disp_loc == NULL); - ad->disp_loc = arg1_loc; - extract_loc_address_regs (false, mode, as, arg0_loc, context_p, - PLUS, code0, modify_p, ad); - } - /* If both operands are registers but one is already a hard - register of index or reg-base class, give the other the - class that the hard register is not. */ - else if (code0 == REG && code1 == REG - && REGNO (arg0) < FIRST_PSEUDO_REGISTER - && ((base_ok_p - = ok_for_base_p_nonstrict (arg0, mode, as, PLUS, REG)) - || ok_for_index_p_nonstrict (arg0))) - { - extract_loc_address_regs (false, mode, as, arg0_loc, ! base_ok_p, - PLUS, REG, modify_p, ad); - extract_loc_address_regs (false, mode, as, arg1_loc, base_ok_p, - PLUS, REG, modify_p, ad); - } - else if (code0 == REG && code1 == REG - && REGNO (arg1) < FIRST_PSEUDO_REGISTER - && ((base_ok_p - = ok_for_base_p_nonstrict (arg1, mode, as, PLUS, REG)) - || ok_for_index_p_nonstrict (arg1))) - { - extract_loc_address_regs (false, mode, as, arg0_loc, base_ok_p, - PLUS, REG, modify_p, ad); - extract_loc_address_regs (false, mode, as, arg1_loc, ! base_ok_p, - PLUS, REG, modify_p, ad); - } - /* Otherwise, count equal chances that each might be a base or - index register. This case should be rare. */ - else - { - extract_loc_address_regs (false, mode, as, arg0_loc, false, PLUS, - code1, modify_p, ad); - extract_loc_address_regs (false, mode, as, arg1_loc, - ad->base_reg_loc != NULL, PLUS, - code0, modify_p, ad); - } - } - break; - - case MULT: - case ASHIFT: - { - rtx *arg0_loc = &XEXP (x, 0); - enum rtx_code code0 = GET_CODE (*arg0_loc); - - if (code0 == CONST_INT) - arg0_loc = &XEXP (x, 1); - extract_loc_address_regs (false, mode, as, arg0_loc, true, - outer_code, code, modify_p, ad); - lra_assert (ad->index_loc == NULL); - ad->index_loc = loc; - break; - } - - case POST_MODIFY: - case PRE_MODIFY: - extract_loc_address_regs (false, mode, as, &XEXP (x, 0), false, - code, GET_CODE (XEXP (XEXP (x, 1), 1)), - true, ad); - lra_assert (rtx_equal_p (XEXP (XEXP (x, 1), 0), XEXP (x, 0))); - ad->base_reg_loc2 = &XEXP (XEXP (x, 1), 0); - if (REG_P (XEXP (XEXP (x, 1), 1))) - extract_loc_address_regs (false, mode, as, &XEXP (XEXP (x, 1), 1), - true, code, REG, modify_p, ad); - break; - - case POST_INC: - case PRE_INC: - case POST_DEC: - case PRE_DEC: - extract_loc_address_regs (false, mode, as, &XEXP (x, 0), false, code, - SCRATCH, true, ad); - break; - - /* We process memory as a register. That means we flatten - addresses. In other words, the final code will never - contains memory in an address even if the target supports - such addresses (it is too rare these days). Memory also can - occur in address as a result some previous transformations - like equivalence substitution. */ - case MEM: - case REG: - if (context_p) - { - lra_assert (ad->index_reg_loc == NULL); - ad->index_reg_loc = loc; - } - else - { - lra_assert (ad->base_reg_loc == NULL); - ad->base_reg_loc = loc; - ad->base_outer_code = outer_code; - ad->index_code = index_code; - ad->base_modify_p = modify_p; - } - break; - default: - { - const char *fmt = GET_RTX_FORMAT (code); - int i; - - if (GET_RTX_LENGTH (code) != 1 - || fmt[0] != 'e' || GET_CODE (XEXP (x, 0)) != UNSPEC) - { - for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--) - if (fmt[i] == 'e') - extract_loc_address_regs (false, mode, as, &XEXP (x, i), - context_p, code, SCRATCH, - modify_p, ad); - break; - } - /* fall through for case UNARY_OP (UNSPEC ...) */ - } - - case UNSPEC: - if (ad->disp_loc == NULL) - ad->disp_loc = loc; - else if (ad->base_reg_loc == NULL) - { - ad->base_reg_loc = loc; - ad->base_outer_code = outer_code; - ad->index_code = index_code; - ad->base_modify_p = modify_p; - } - else - { - lra_assert (ad->index_reg_loc == NULL); - ad->index_reg_loc = loc; - } - break; - - } -} - - -/* Describe address *LOC in AD. There are two cases: - - *LOC is the address in a (mem ...). In this case OUTER_CODE is MEM - and AS is the mem's address space. - - *LOC is matched to an address constraint such as 'p'. In this case - OUTER_CODE is ADDRESS and AS is ADDR_SPACE_GENERIC. */ -static void -extract_address_regs (enum machine_mode mem_mode, addr_space_t as, - rtx *loc, enum rtx_code outer_code, struct address *ad) -{ - ad->base_reg_loc = ad->base_reg_loc2 - = ad->index_reg_loc = ad->index_loc = ad->disp_loc = NULL; - ad->base_outer_code = SCRATCH; - ad->index_code = SCRATCH; - ad->base_modify_p = false; - extract_loc_address_regs (true, mem_mode, as, loc, false, outer_code, - SCRATCH, false, ad); - if (ad->index_loc == NULL) - /* SUBREG ??? */ - ad->index_loc = ad->index_reg_loc; -} - /* The page contains major code to choose the current insn alternative @@ -802,7 +510,7 @@ operands_match_p (rtx x, rtx y, int y_hard_regno) && (REG_P (y) || (GET_CODE (y) == SUBREG && REG_P (SUBREG_REG (y))))) { int j; - + i = get_hard_regno (x); if (i < 0) goto slow; @@ -830,7 +538,7 @@ operands_match_p (rtx x, rtx y, int y_hard_regno) if (GET_CODE (y) == PRE_DEC || GET_CODE (y) == PRE_INC || GET_CODE (y) == PRE_MODIFY) return operands_match_p (x, XEXP (y, 0), -1); - + slow: if (code == REG && GET_CODE (y) == SUBREG && REG_P (SUBREG_REG (y)) @@ -955,7 +663,7 @@ match_reload (signed char out, signed char *ins, enum reg_class goal_class, rtx *before, rtx *after) { int i, in; - rtx new_in_reg, new_out_reg, reg; + rtx new_in_reg, new_out_reg, reg, clobber; enum machine_mode inmode, outmode; rtx in_rtx = *curr_id->operand_loc[ins[0]]; rtx out_rtx = *curr_id->operand_loc[out]; @@ -986,8 +694,10 @@ match_reload (signed char out, signed char *ins, enum reg_class goal_class, new_in_reg = gen_rtx_SUBREG (inmode, reg, 0); /* NEW_IN_REG is non-paradoxical subreg. We don't want NEW_OUT_REG living above. We add clobber clause for - this. */ - emit_clobber (new_out_reg); + this. This is just a temporary clobber. We can remove + it at the end of LRA work. */ + clobber = emit_clobber (new_out_reg); + LRA_TEMP_CLOBBER_P (PATTERN (clobber)) = 1; } } else @@ -1001,13 +711,13 @@ match_reload (signed char out, signed char *ins, enum reg_class goal_class, pseudo which is wrong when the input pseudo lives after the insn and as the new pseudo value is changed by the insn output. Therefore we create the new pseudo from the output. - + We cannot reuse the current output register because we might have a situation like "a <- a op b", where the constraints force the second input operand ("b") to match the output operand ("a"). "b" must then be copied into a new register so that it doesn't clobber the current value of "a". */ - + new_in_reg = new_out_reg = lra_create_new_reg_with_unique_value (outmode, out_rtx, goal_class, ""); @@ -1063,12 +773,12 @@ reg_class_from_constraints (const char *p) [op_class][base_reg_class (VOIDmode, ADDR_SPACE_GENERIC, ADDRESS, SCRATCH)]); break; - + case 'g': case 'r': op_class = reg_class_subunion[op_class][GENERAL_REGS]; break; - + default: if (REG_CLASS_FROM_CONSTRAINT (c, p) == NO_REGS) { @@ -1081,7 +791,7 @@ reg_class_from_constraints (const char *p) #endif break; } - + op_class = reg_class_subunion[op_class][REG_CLASS_FROM_CONSTRAINT (c, p)]; break; @@ -1204,10 +914,8 @@ check_and_process_move (bool *change_p, bool *sec_mem_p) || ((secondary_class != NO_REGS || sri.icode != CODE_FOR_nothing) && dclass != NO_REGS)) { -#if ENABLE_ASSERT_CHECKING enum reg_class old_sclass = secondary_class; secondary_reload_info old_sri = sri; -#endif sri.prev_sri = NULL; sri.icode = CODE_FOR_nothing; @@ -1334,11 +1042,13 @@ process_addr_reg (rtx *loc, rtx *before, rtx *after, enum reg_class cl) { int regno; enum reg_class rclass, new_class; - rtx reg = *loc; + rtx reg; rtx new_reg; enum machine_mode mode; bool before_p = false; + loc = strip_subreg (loc); + reg = *loc; mode = GET_MODE (reg); if (! REG_P (reg)) { @@ -1397,10 +1107,6 @@ process_addr_reg (rtx *loc, rtx *before, rtx *after, enum reg_class cl) return true; } -#ifndef SLOW_UNALIGNED_ACCESS -#define SLOW_UNALIGNED_ACCESS(mode, align) 0 -#endif - /* Make reloads for subreg in operand NOP with internal subreg mode REG_MODE, add new reloads for further processing. Return true if any reload was generated. */ @@ -1417,15 +1123,14 @@ simplify_operand_subreg (int nop, enum machine_mode reg_mode) if (GET_CODE (operand) != SUBREG) return false; - + mode = GET_MODE (operand); reg = SUBREG_REG (operand); /* If we change address for paradoxical subreg of memory, the address might violate the necessary alignment or the access might be slow. So take this into consideration. */ if ((MEM_P (reg) - && ((! STRICT_ALIGNMENT - && ! SLOW_UNALIGNED_ACCESS (mode, MEM_ALIGN (reg))) + && (! SLOW_UNALIGNED_ACCESS (mode, MEM_ALIGN (reg)) || MEM_ALIGN (reg) >= GET_MODE_ALIGNMENT (mode))) || (REG_P (reg) && REGNO (reg) < FIRST_PSEUDO_REGISTER)) { @@ -1509,7 +1214,7 @@ uses_hard_regs_p (rtx x, HARD_REG_SET set) if (GET_MODE_SIZE (GET_MODE (x)) > GET_MODE_SIZE (mode)) mode = GET_MODE (x); } - + if (REG_P (x)) { x_hard_regno = get_hard_regno (x); @@ -1518,21 +1223,13 @@ uses_hard_regs_p (rtx x, HARD_REG_SET set) } if (MEM_P (x)) { - struct address ad; - enum machine_mode mode = GET_MODE (x); - rtx *addr_loc = &XEXP (x, 0); + struct address_info ad; - extract_address_regs (mode, MEM_ADDR_SPACE (x), addr_loc, MEM, &ad); - if (ad.base_reg_loc != NULL) - { - if (uses_hard_regs_p (*ad.base_reg_loc, set)) - return true; - } - if (ad.index_reg_loc != NULL) - { - if (uses_hard_regs_p (*ad.index_reg_loc, set)) - return true; - } + decompose_mem_address (&ad, x); + if (ad.base_term != NULL && uses_hard_regs_p (*ad.base_term, set)) + return true; + if (ad.index_term != NULL && uses_hard_regs_p (*ad.index_term, set)) + return true; } fmt = GET_RTX_FORMAT (code); for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--) @@ -1627,7 +1324,7 @@ process_alt_operands (int only_alternative) op = no_subreg_reg_operand[nop] = *curr_id->operand_loc[nop]; /* The real hard regno of the operand after the allocation. */ hard_regno[nop] = get_hard_regno (op); - + operand_reg[nop] = op; biggest_mode[nop] = GET_MODE (operand_reg[nop]); if (GET_CODE (operand_reg[nop]) == SUBREG) @@ -1700,16 +1397,16 @@ process_alt_operands (int only_alternative) curr_alt_matches[nop] = -1; continue; } - + op = no_subreg_reg_operand[nop]; mode = curr_operand_mode[nop]; win = did_match = winreg = offmemok = constmemok = false; badop = true; - + early_clobber_p = false; p = curr_static_id->operand_alternative[opalt_num].constraint; - + this_costly_alternative = this_alternative = NO_REGS; /* We update set of possible hard regs besides its class because reg class might be inaccurate. For example, @@ -1722,11 +1419,11 @@ process_alt_operands (int only_alternative) this_alternative_match_win = false; this_alternative_offmemok = false; this_alternative_matches = -1; - + /* An empty constraint should be excluded by the fast track. */ lra_assert (*p != 0 && *p != ','); - + /* Scan this alternative's specs for this operand; set WIN if the operand fits any letter in this alternative. Otherwise, clear BADOP if this operand could fit some @@ -1744,36 +1441,36 @@ process_alt_operands (int only_alternative) case ',': c = '\0'; break; - + case '=': case '+': case '?': case '*': case '!': case ' ': case '\t': break; - + case '%': /* We only support one commutative marker, the first one. We already set commutative above. */ break; - + case '&': early_clobber_p = true; break; - + case '#': /* Ignore rest of this alternative. */ c = '\0'; break; - + case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': { int m_hregno; bool match_p; - + m = strtoul (p, &end, 10); p = end; len = 0; lra_assert (nop > m); - + this_alternative_matches = m; m_hregno = get_hard_regno (*curr_id->operand_loc[m]); /* We are supposed to match a previous operand. @@ -1809,7 +1506,7 @@ process_alt_operands (int only_alternative) && MEM_P (*curr_id->operand_loc[m]) && curr_alt[m] == NO_REGS && ! curr_alt_win[m]) continue; - + } else { @@ -1831,7 +1528,7 @@ process_alt_operands (int only_alternative) += (ira_reg_class_max_nregs[curr_alt[m]] [GET_MODE (*curr_id->operand_loc[m])]); } - + /* We prefer no matching alternatives because it gives more freedom in RA. */ if (operand_reg[nop] == NULL_RTX @@ -1854,7 +1551,7 @@ process_alt_operands (int only_alternative) } else did_match = true; - + /* This can be fixed with reloads if the operand we are supposed to match can be fixed with reloads. */ @@ -1863,7 +1560,7 @@ process_alt_operands (int only_alternative) COPY_HARD_REG_SET (this_alternative_set, curr_alt_set[m]); break; } - + case 'p': cl = base_reg_class (VOIDmode, ADDR_SPACE_GENERIC, ADDRESS, SCRATCH); @@ -1880,7 +1577,7 @@ process_alt_operands (int only_alternative) win = true; badop = false; break; - + case TARGET_MEM_CONSTRAINT: if (MEM_P (op) || spilled_pseudo_p (op)) win = true; @@ -1888,28 +1585,28 @@ process_alt_operands (int only_alternative) badop = false; constmemok = true; break; - + case '<': if (MEM_P (op) && (GET_CODE (XEXP (op, 0)) == PRE_DEC || GET_CODE (XEXP (op, 0)) == POST_DEC)) win = true; break; - + case '>': if (MEM_P (op) && (GET_CODE (XEXP (op, 0)) == PRE_INC || GET_CODE (XEXP (op, 0)) == POST_INC)) win = true; break; - + /* Memory op whose address is not offsettable. */ case 'V': if (MEM_P (op) && ! offsettable_nonstrict_memref_p (op)) win = true; break; - + /* Memory operand whose address is offsettable. */ case 'o': if ((MEM_P (op) @@ -1921,7 +1618,7 @@ process_alt_operands (int only_alternative) constmemok = true; offmemok = true; break; - + case 'E': case 'F': if (GET_CODE (op) == CONST_DOUBLE @@ -1929,14 +1626,14 @@ process_alt_operands (int only_alternative) && (GET_MODE_CLASS (mode) == MODE_VECTOR_FLOAT))) win = true; break; - + case 'G': case 'H': if (GET_CODE (op) == CONST_DOUBLE && CONST_DOUBLE_OK_FOR_CONSTRAINT_P (op, c, p)) win = true; break; - + case 's': if (CONST_INT_P (op) || (GET_CODE (op) == CONST_DOUBLE && mode == VOIDmode)) @@ -1945,13 +1642,13 @@ process_alt_operands (int only_alternative) if (general_constant_p (op)) win = true; break; - + case 'n': if (CONST_INT_P (op) || (GET_CODE (op) == CONST_DOUBLE && mode == VOIDmode)) win = true; break; - + case 'I': case 'J': case 'K': @@ -1964,20 +1661,20 @@ process_alt_operands (int only_alternative) && CONST_OK_FOR_CONSTRAINT_P (INTVAL (op), c, p)) win = true; break; - + case 'X': /* This constraint should be excluded by the fast track. */ gcc_unreachable (); break; - + case 'g': if (MEM_P (op) || general_constant_p (op) || spilled_pseudo_p (op)) win = true; /* Drop through into 'r' case. */ - + case 'r': this_alternative = reg_class_subunion[this_alternative][GENERAL_REGS]; @@ -1992,7 +1689,7 @@ process_alt_operands (int only_alternative) reg_class_contents[GENERAL_REGS]); } goto reg; - + default: if (REG_CLASS_FROM_CONSTRAINT (c, p) == NO_REGS) { @@ -2003,7 +1700,7 @@ process_alt_operands (int only_alternative) win = true; else if (spilled_pseudo_p (op)) win = true; - + /* If we didn't already win, we can reload constants via force_const_mem, and other MEMs by reloading the address like for @@ -2018,7 +1715,7 @@ process_alt_operands (int only_alternative) { if (EXTRA_CONSTRAINT_STR (op, c, p)) win = true; - + /* If we didn't already win, we can reload the address into a base register. */ cl = base_reg_class (VOIDmode, ADDR_SPACE_GENERIC, @@ -2038,13 +1735,13 @@ process_alt_operands (int only_alternative) badop = false; break; } - + if (EXTRA_CONSTRAINT_STR (op, c, p)) win = true; #endif break; } - + cl = REG_CLASS_FROM_CONSTRAINT (c, p); this_alternative = reg_class_subunion[this_alternative][cl]; IOR_HARD_REG_SET (this_alternative_set, @@ -2076,7 +1773,7 @@ process_alt_operands (int only_alternative) costly_p = c == '*'; } while ((p += len), c); - + /* Record which operands fit this alternative. */ if (win) { @@ -2125,7 +1822,7 @@ process_alt_operands (int only_alternative) then this operand can be reloaded. */ if (winreg && !no_regs_p) badop = false; - + if (badop) goto fail; @@ -2178,7 +1875,7 @@ process_alt_operands (int only_alternative) if (! no_regs_p) losers++; } - + /* Alternative loses if it requires a type of reload not permitted for this insn. We can always reload objects with a REG_UNUSED note. */ @@ -2188,7 +1885,7 @@ process_alt_operands (int only_alternative) || (curr_static_id->operand[nop].type != OP_OUT && no_input_reloads_p && ! const_to_mem)) goto fail; - + /* If we can't reload this value at all, reject this alternative. Note that we could also lose due to LIMIT_RELOAD_CLASS, but we don't check that here. */ @@ -2197,13 +1894,13 @@ process_alt_operands (int only_alternative) if (targetm.preferred_reload_class (op, this_alternative) == NO_REGS) reject = MAX_OVERALL_COST_BOUND; - + if (curr_static_id->operand[nop].type == OP_OUT && (targetm.preferred_output_reload_class (op, this_alternative) == NO_REGS)) reject = MAX_OVERALL_COST_BOUND; } - + if (! ((const_to_mem && constmemok) || (MEM_P (op) && offmemok))) { @@ -2216,7 +1913,7 @@ process_alt_operands (int only_alternative) match then. */ if (! (REG_P (op) && REGNO (op) >= FIRST_PSEUDO_REGISTER)) reject += 2; - + if (! no_regs_p) reload_nregs += ira_reg_class_max_nregs[this_alternative][mode]; @@ -2228,7 +1925,7 @@ process_alt_operands (int only_alternative) if (!REG_P (op) || curr_static_id->operand[nop].type != OP_IN) reject++; } - + if (early_clobber_p) reject++; /* ??? We check early clobbers after processing all operands @@ -2246,11 +1943,11 @@ process_alt_operands (int only_alternative) curr_alt_match_win[nop] = this_alternative_match_win; curr_alt_offmemok[nop] = this_alternative_offmemok; curr_alt_matches[nop] = this_alternative_matches; - + if (this_alternative_matches >= 0 && !did_match && !this_alternative_win) curr_alt_win[this_alternative_matches] = false; - + if (early_clobber_p && operand_reg[nop] != NULL_RTX) early_clobbered_nops[early_clobbered_regs_num++] = nop; } @@ -2352,7 +2049,7 @@ process_alt_operands (int only_alternative) } if (losers == 0) /* Everything is satisfied. Do not process alternatives - anymore. */ + anymore. */ break; fail: ; @@ -2371,7 +2068,7 @@ valid_address_p (enum machine_mode mode ATTRIBUTE_UNUSED, lra_assert (ADDR_SPACE_GENERIC_P (as)); GO_IF_LEGITIMATE_ADDRESS (mode, addr, win); return 0; - + win: return 1; #else @@ -2379,46 +2076,92 @@ valid_address_p (enum machine_mode mode ATTRIBUTE_UNUSED, #endif } -/* Make reload base reg + disp from address AD in space AS of memory - with MODE into a new pseudo. Return the new pseudo. */ +/* Return whether address AD is valid. */ + +static bool +valid_address_p (struct address_info *ad) +{ + /* Some ports do not check displacements for eliminable registers, + so we replace them temporarily with the elimination target. */ + rtx saved_base_reg = NULL_RTX; + rtx saved_index_reg = NULL_RTX; + rtx *base_term = strip_subreg (ad->base_term); + rtx *index_term = strip_subreg (ad->index_term); + if (base_term != NULL) + { + saved_base_reg = *base_term; + lra_eliminate_reg_if_possible (base_term); + if (ad->base_term2 != NULL) + *ad->base_term2 = *ad->base_term; + } + if (index_term != NULL) + { + saved_index_reg = *index_term; + lra_eliminate_reg_if_possible (index_term); + } + bool ok_p = valid_address_p (ad->mode, *ad->outer, ad->as); + if (saved_base_reg != NULL_RTX) + { + *base_term = saved_base_reg; + if (ad->base_term2 != NULL) + *ad->base_term2 = *ad->base_term; + } + if (saved_index_reg != NULL_RTX) + *index_term = saved_index_reg; + return ok_p; +} + +/* Make reload base reg + disp from address AD. Return the new pseudo. */ static rtx -base_plus_disp_to_reg (enum machine_mode mode, addr_space_t as, - struct address *ad) +base_plus_disp_to_reg (struct address_info *ad) { enum reg_class cl; rtx new_reg; - lra_assert (ad->base_reg_loc != NULL && ad->disp_loc != NULL); - cl = base_reg_class (mode, as, ad->base_outer_code, ad->index_code); - new_reg = lra_create_new_reg (Pmode, NULL_RTX, cl, "base + disp"); - lra_emit_add (new_reg, *ad->base_reg_loc, *ad->disp_loc); + lra_assert (ad->base == ad->base_term && ad->disp == ad->disp_term); + cl = base_reg_class (ad->mode, ad->as, ad->base_outer_code, + get_index_code (ad)); + new_reg = lra_create_new_reg (GET_MODE (*ad->base_term), NULL_RTX, + cl, "base + disp"); + lra_emit_add (new_reg, *ad->base_term, *ad->disp_term); return new_reg; } -/* Make substitution in address AD in space AS with location ADDR_LOC. - Update AD and ADDR_LOC if it is necessary. Return true if a - substitution was made. */ +/* Return true if we can add a displacement to address AD, even if that + makes the address invalid. The fix-up code requires any new address + to be the sum of the BASE_TERM, INDEX and DISP_TERM fields. */ static bool -equiv_address_substitution (struct address *ad, rtx *addr_loc, - enum machine_mode mode, addr_space_t as, - enum rtx_code code) +can_add_disp_p (struct address_info *ad) { - rtx base_reg, new_base_reg, index_reg, new_index_reg; + return (!ad->autoinc_p + && ad->segment == NULL + && ad->base == ad->base_term + && ad->disp == ad->disp_term); +} + +/* Make equiv substitution in address AD. Return true if a substitution + was made. */ +static bool +equiv_address_substitution (struct address_info *ad) +{ + rtx base_reg, new_base_reg, index_reg, new_index_reg, *base_term, *index_term; HOST_WIDE_INT disp, scale; bool change_p; - if (ad->base_reg_loc == NULL) + base_term = strip_subreg (ad->base_term); + if (base_term == NULL) base_reg = new_base_reg = NULL_RTX; else { - base_reg = *ad->base_reg_loc; + base_reg = *base_term; new_base_reg = get_equiv_substitution (base_reg); } - if (ad->index_reg_loc == NULL) + index_term = strip_subreg (ad->index_term); + if (index_term == NULL) index_reg = new_index_reg = NULL_RTX; else { - index_reg = *ad->index_reg_loc; + index_reg = *index_term; new_index_reg = get_equiv_substitution (index_reg); } if (base_reg == new_base_reg && index_reg == new_index_reg) @@ -2429,56 +2172,53 @@ equiv_address_substitution (struct address *ad, rtx *addr_loc, { fprintf (lra_dump_file, "Changing address in insn %d ", INSN_UID (curr_insn)); - print_value_slim (lra_dump_file, *addr_loc, 1); + print_value_slim (lra_dump_file, *ad->outer, 1); } if (base_reg != new_base_reg) { if (REG_P (new_base_reg)) { - *ad->base_reg_loc = new_base_reg; + *base_term = new_base_reg; change_p = true; } else if (GET_CODE (new_base_reg) == PLUS && REG_P (XEXP (new_base_reg, 0)) - && CONST_INT_P (XEXP (new_base_reg, 1))) + && CONST_INT_P (XEXP (new_base_reg, 1)) + && can_add_disp_p (ad)) { disp += INTVAL (XEXP (new_base_reg, 1)); - *ad->base_reg_loc = XEXP (new_base_reg, 0); + *base_term = XEXP (new_base_reg, 0); change_p = true; } - if (ad->base_reg_loc2 != NULL) - *ad->base_reg_loc2 = *ad->base_reg_loc; - } - scale = 1; - if (ad->index_loc != NULL && GET_CODE (*ad->index_loc) == MULT) - { - lra_assert (CONST_INT_P (XEXP (*ad->index_loc, 1))); - scale = INTVAL (XEXP (*ad->index_loc, 1)); + if (ad->base_term2 != NULL) + *ad->base_term2 = *ad->base_term; } if (index_reg != new_index_reg) { if (REG_P (new_index_reg)) { - *ad->index_reg_loc = new_index_reg; + *index_term = new_index_reg; change_p = true; } else if (GET_CODE (new_index_reg) == PLUS && REG_P (XEXP (new_index_reg, 0)) - && CONST_INT_P (XEXP (new_index_reg, 1))) + && CONST_INT_P (XEXP (new_index_reg, 1)) + && can_add_disp_p (ad) + && (scale = get_index_scale (ad))) { disp += INTVAL (XEXP (new_index_reg, 1)) * scale; - *ad->index_reg_loc = XEXP (new_index_reg, 0); + *index_term = XEXP (new_index_reg, 0); change_p = true; } } if (disp != 0) { - if (ad->disp_loc != NULL) - *ad->disp_loc = plus_constant (Pmode, *ad->disp_loc, disp); + if (ad->disp != NULL) + *ad->disp = plus_constant (GET_MODE (*ad->inner), *ad->disp, disp); else { - *addr_loc = gen_rtx_PLUS (Pmode, *addr_loc, GEN_INT (disp)); - extract_address_regs (mode, as, addr_loc, code, ad); + *ad->inner = plus_constant (GET_MODE (*ad->inner), *ad->inner, disp); + update_address (ad); } change_p = true; } @@ -2489,143 +2229,118 @@ equiv_address_substitution (struct address *ad, rtx *addr_loc, else { fprintf (lra_dump_file, " on equiv "); - print_value_slim (lra_dump_file, *addr_loc, 1); + print_value_slim (lra_dump_file, *ad->outer, 1); fprintf (lra_dump_file, "\n"); } } return change_p; } -/* Major function to make reloads for address in operand NOP. Add to - reloads to the list *BEFORE and *AFTER. We might need to add +/* Major function to make reloads for an address in operand NOP. + The supported cases are: + + 1) an address that existed before LRA started, at which point it must + have been valid. These addresses are subject to elimination and + may have become invalid due to the elimination offset being out + of range. + + 2) an address created by forcing a constant to memory (force_const_to_mem). + The initial form of these addresses might not be valid, and it is this + function's job to make them valid. + + 3) a frame address formed from a register and a (possibly zero) + constant offset. As above, these addresses might not be valid + and this function must make them so. + + Add reloads to the lists *BEFORE and *AFTER. We might need to add reloads to *AFTER because of inc/dec, {pre, post} modify in the address. Return true for any RTL change. */ static bool process_address (int nop, rtx *before, rtx *after) { - struct address ad; - enum machine_mode mode; - rtx new_reg, *addr_loc, saved_index_reg, saved_base_reg; - bool ok_p; - addr_space_t as; + struct address_info ad; + rtx new_reg; rtx op = *curr_id->operand_loc[nop]; const char *constraint = curr_static_id->operand[nop].constraint; bool change_p; - enum rtx_code code; if (constraint[0] == 'p' || EXTRA_ADDRESS_CONSTRAINT (constraint[0], constraint)) - { - mode = VOIDmode; - addr_loc = curr_id->operand_loc[nop]; - as = ADDR_SPACE_GENERIC; - code = ADDRESS; - } + decompose_lea_address (&ad, curr_id->operand_loc[nop]); else if (MEM_P (op)) - { - mode = GET_MODE (op); - addr_loc = &XEXP (op, 0); - as = MEM_ADDR_SPACE (op); - code = MEM; - } + decompose_mem_address (&ad, op); else if (GET_CODE (op) == SUBREG && MEM_P (SUBREG_REG (op))) - { - mode = GET_MODE (SUBREG_REG (op)); - addr_loc = &XEXP (SUBREG_REG (op), 0); - as = MEM_ADDR_SPACE (SUBREG_REG (op)); - code = MEM; - } + decompose_mem_address (&ad, SUBREG_REG (op)); else return false; - if (GET_CODE (*addr_loc) == AND) - addr_loc = &XEXP (*addr_loc, 0); - extract_address_regs (mode, as, addr_loc, code, &ad); - change_p = equiv_address_substitution (&ad, addr_loc, mode, as, code); - if (ad.base_reg_loc != NULL + change_p = equiv_address_substitution (&ad); + if (ad.base_term != NULL && (process_addr_reg - (ad.base_reg_loc, before, - (ad.base_modify_p && REG_P (*ad.base_reg_loc) - && find_regno_note (curr_insn, REG_DEAD, - REGNO (*ad.base_reg_loc)) == NULL_RTX + (ad.base_term, before, + (ad.autoinc_p + && !(REG_P (*ad.base_term) + && find_regno_note (curr_insn, REG_DEAD, + REGNO (*ad.base_term)) != NULL_RTX) ? after : NULL), - base_reg_class (mode, as, ad.base_outer_code, ad.index_code)))) + base_reg_class (ad.mode, ad.as, ad.base_outer_code, + get_index_code (&ad))))) { change_p = true; - if (ad.base_reg_loc2 != NULL) - *ad.base_reg_loc2 = *ad.base_reg_loc; + if (ad.base_term2 != NULL) + *ad.base_term2 = *ad.base_term; } - if (ad.index_reg_loc != NULL - && process_addr_reg (ad.index_reg_loc, before, NULL, INDEX_REG_CLASS)) + if (ad.index_term != NULL + && process_addr_reg (ad.index_term, before, NULL, INDEX_REG_CLASS)) change_p = true; - /* The address was valid before LRA. We only change its form if the - address has a displacement, so if it has no displacement it must - still be valid. */ - if (ad.disp_loc == NULL) - return change_p; + /* There are three cases where the shape of *AD.INNER may now be invalid: - /* See whether the address is still valid. Some ports do not check - displacements for eliminable registers, so we replace them - temporarily with the elimination target. */ - saved_base_reg = saved_index_reg = NULL_RTX; - if (ad.base_reg_loc != NULL) - { - saved_base_reg = *ad.base_reg_loc; - lra_eliminate_reg_if_possible (ad.base_reg_loc); - if (ad.base_reg_loc2 != NULL) - *ad.base_reg_loc2 = *ad.base_reg_loc; - } - if (ad.index_reg_loc != NULL) - { - saved_index_reg = *ad.index_reg_loc; - lra_eliminate_reg_if_possible (ad.index_reg_loc); - } - /* Some ports do not check displacements for virtual registers -- so - we substitute them temporarily by real registers. */ - ok_p = valid_address_p (mode, *addr_loc, as); - if (saved_base_reg != NULL_RTX) - { - *ad.base_reg_loc = saved_base_reg; - if (ad.base_reg_loc2 != NULL) - *ad.base_reg_loc2 = saved_base_reg; - } - if (saved_index_reg != NULL_RTX) - *ad.index_reg_loc = saved_index_reg; + 1) the original address was valid, but either elimination or + equiv_address_substitution applied a displacement that made + it invalid. + + 2) the address is an invalid symbolic address created by + force_const_to_mem. - if (ok_p) + 3) the address is a frame address with an invalid offset. + + All these cases involve a displacement and a non-autoinc address, + so there is no point revalidating other types. */ + if (ad.disp == NULL || ad.autoinc_p || valid_address_p (&ad)) return change_p; - /* Addresses were legitimate before LRA. So if the address has - two registers than it can have two of them. We should also - not worry about scale for the same reason. */ + /* Any index existed before LRA started, so we can assume that the + presence and shape of the index is valid. */ push_to_sequence (*before); - if (ad.base_reg_loc == NULL) + gcc_assert (ad.segment == NULL); + gcc_assert (ad.disp == ad.disp_term); + if (ad.base == NULL) { - if (ad.index_reg_loc == NULL) + if (ad.index == NULL) { int code = -1; - enum reg_class cl = base_reg_class (mode, as, SCRATCH, SCRATCH); - + enum reg_class cl = base_reg_class (ad.mode, ad.as, + SCRATCH, SCRATCH); + rtx disp = *ad.disp; + new_reg = lra_create_new_reg (Pmode, NULL_RTX, cl, "disp"); #ifdef HAVE_lo_sum { rtx insn; rtx last = get_last_insn (); - /* disp => lo_sum (new_base, disp) */ + /* disp => lo_sum (new_base, disp), case (2) above. */ insn = emit_insn (gen_rtx_SET (VOIDmode, new_reg, - gen_rtx_HIGH (Pmode, copy_rtx (*ad.disp_loc)))); + gen_rtx_HIGH (Pmode, copy_rtx (disp)))); code = recog_memoized (insn); if (code >= 0) { - rtx save = *ad.disp_loc; - - *ad.disp_loc = gen_rtx_LO_SUM (Pmode, new_reg, *ad.disp_loc); - if (! valid_address_p (mode, *ad.disp_loc, as)) + *ad.disp = gen_rtx_LO_SUM (Pmode, new_reg, disp); + if (! valid_address_p (ad.mode, *ad.outer, ad.as)) { - *ad.disp_loc = save; + *ad.disp = disp; code = -1; } } @@ -2635,41 +2350,43 @@ process_address (int nop, rtx *before, rtx *after) #endif if (code < 0) { - /* disp => new_base */ - lra_emit_move (new_reg, *ad.disp_loc); - *ad.disp_loc = new_reg; + /* disp => new_base, case (2) above. */ + lra_emit_move (new_reg, disp); + *ad.disp = new_reg; } } else { - /* index * scale + disp => new base + index * scale */ - enum reg_class cl = base_reg_class (mode, as, SCRATCH, SCRATCH); + /* index * scale + disp => new base + index * scale, + case (1) above. */ + enum reg_class cl = base_reg_class (ad.mode, ad.as, PLUS, + GET_CODE (*ad.index)); lra_assert (INDEX_REG_CLASS != NO_REGS); new_reg = lra_create_new_reg (Pmode, NULL_RTX, cl, "disp"); - lra_assert (GET_CODE (*addr_loc) == PLUS); - lra_emit_move (new_reg, *ad.disp_loc); - if (CONSTANT_P (XEXP (*addr_loc, 1))) - XEXP (*addr_loc, 1) = XEXP (*addr_loc, 0); - XEXP (*addr_loc, 0) = new_reg; + lra_emit_move (new_reg, *ad.disp); + *ad.inner = simplify_gen_binary (PLUS, GET_MODE (new_reg), + new_reg, *ad.index); } } - else if (ad.index_reg_loc == NULL) + else if (ad.index == NULL) { - /* base + disp => new base */ + /* base + disp => new base, cases (1) and (3) above. */ /* Another option would be to reload the displacement into an index register. However, postreload has code to optimize address reloads that have the same base and different displacements, so reloading into an index register would not necessarily be a win. */ - new_reg = base_plus_disp_to_reg (mode, as, &ad); - *addr_loc = new_reg; + new_reg = base_plus_disp_to_reg (&ad); + *ad.inner = new_reg; } else { - /* base + scale * index + disp => new base + scale * index */ - new_reg = base_plus_disp_to_reg (mode, as, &ad); - *addr_loc = gen_rtx_PLUS (Pmode, new_reg, *ad.index_loc); + /* base + scale * index + disp => new base + scale * index, + case (1) above. */ + new_reg = base_plus_disp_to_reg (&ad); + *ad.inner = simplify_gen_binary (PLUS, GET_MODE (new_reg), + new_reg, *ad.index); } *before = get_insns (); end_sequence (); @@ -2938,7 +2655,7 @@ curr_insn_transform (void) change_p = true; lra_update_dup (curr_id, i); } - + if (change_p) /* If we've changed the instruction then any alternative that we chose previously may no longer be valid. */ @@ -3076,7 +2793,7 @@ curr_insn_transform (void) /* Right now, for any pair of operands I and J that are required to match, with J < I, goal_alt_matches[I] is J. Add I to goal_alt_matched[J]. */ - + for (i = 0; i < n_operands; i++) if ((j = goal_alt_matches[i]) >= 0) { @@ -3092,10 +2809,10 @@ curr_insn_transform (void) goal_alt_matched[j][k] = i; goal_alt_matched[j][k + 1] = -1; } - + for (i = 0; i < n_operands; i++) goal_alt_win[i] |= goal_alt_match_win[i]; - + /* Any constants that aren't allowed and can't be reloaded into registers are here changed into memory references. */ for (i = 0; i < n_operands; i++) @@ -3107,7 +2824,7 @@ curr_insn_transform (void) if (GET_CODE (reg) == SUBREG) reg = SUBREG_REG (reg); - + if (REG_P (reg) && (regno = REGNO (reg)) >= FIRST_PSEUDO_REGISTER) { bool ok_p = in_class_p (reg, goal_alt[i], &new_class); @@ -3126,29 +2843,29 @@ curr_insn_transform (void) rtx op = *curr_id->operand_loc[i]; rtx subreg = NULL_RTX; enum machine_mode mode = curr_operand_mode[i]; - + if (GET_CODE (op) == SUBREG) { subreg = op; op = SUBREG_REG (op); mode = GET_MODE (op); } - + if (CONST_POOL_OK_P (mode, op) && ((targetm.preferred_reload_class (op, (enum reg_class) goal_alt[i]) == NO_REGS) || no_input_reloads_p)) { rtx tem = force_const_mem (mode, op); - + change_p = true; if (subreg != NULL_RTX) tem = gen_rtx_SUBREG (mode, tem, SUBREG_BYTE (subreg)); - + *curr_id->operand_loc[i] = tem; lra_update_dup (curr_id, i); process_address (i, &before, &after); - + /* If the alternative accepts constant pool refs directly there will be no reload needed at all. */ if (subreg != NULL_RTX) @@ -3170,11 +2887,11 @@ curr_insn_transform (void) } if (c == '\0' || c == ',' || c == '#') continue; - + goal_alt_win[i] = true; } } - + for (i = 0; i < n_operands; i++) { rtx old, new_reg; @@ -3193,7 +2910,7 @@ curr_insn_transform (void) change_class (REGNO (op), NO_REGS, " Change", true); continue; } - + /* Operands that match previous ones have already been handled. */ if (goal_alt_matches[i] >= 0) continue; @@ -3450,10 +3167,10 @@ multi_block_pseudo_p (int regno) basic_block bb = NULL; unsigned int uid; bitmap_iterator bi; - + if (regno < FIRST_PSEUDO_REGISTER) return false; - + EXECUTE_IF_SET_IN_BITMAP (&lra_reg_info[regno].insn_bitmap, 0, uid, bi) if (bb == NULL) bb = BLOCK_FOR_INSN (lra_insn_recog_data[uid]->insn); @@ -3551,7 +3268,7 @@ lra_constraints (bool first_p) if ((hard_regno = lra_get_regno_hard_regno (i)) >= 0) { int j, nregs = hard_regno_nregs[hard_regno][PSEUDO_REGNO_MODE (i)]; - + for (j = 0; j < nregs; j++) df_set_regs_ever_live (hard_regno + j, true); } @@ -3604,7 +3321,7 @@ lra_constraints (bool first_p) { curr_insn = lra_pop_insn (); --new_min_len; - curr_bb = BLOCK_FOR_INSN (curr_insn); + curr_bb = BLOCK_FOR_INSN (curr_insn); if (curr_bb != last_bb) { last_bb = curr_bb; @@ -3644,7 +3361,7 @@ lra_constraints (bool first_p) can not be changed. Such insns might be not in init_insns because we don't update equiv data during insn transformations. - + As an example, let suppose that a pseudo got hard register and on the 1st pass was not changed to equivalent constant. We generate an @@ -3698,7 +3415,7 @@ lra_constraints (bool first_p) && (hard_regno = lra_get_regno_hard_regno (i)) >= 0) { int j, nregs = hard_regno_nregs[hard_regno][PSEUDO_REGNO_MODE (i)]; - + for (j = 0; j < nregs; j++) lra_assert (df_regs_ever_live_p (hard_regno + j)); } @@ -3782,7 +3499,7 @@ static void add_next_usage_insn (int regno, rtx insn, int reloads_num) { rtx next_usage_insns; - + if (usage_insns[regno].check == curr_usage_insns_check && (next_usage_insns = usage_insns[regno].insns) != NULL_RTX && DEBUG_INSN_P (insn)) @@ -3799,7 +3516,7 @@ add_next_usage_insn (int regno, rtx insn, int reloads_num) else usage_insns[regno].check = 0; } - + /* Replace all references to register OLD_REGNO in *LOC with pseudo register NEW_REG. Return true if any change was made. */ static bool @@ -3851,6 +3568,49 @@ substitute_pseudo (rtx *loc, int old_regno, rtx new_reg) return result; } +/* Return first non-debug insn in list USAGE_INSNS. */ +static rtx +skip_usage_debug_insns (rtx usage_insns) +{ + rtx insn; + + /* Skip debug insns. */ + for (insn = usage_insns; + insn != NULL_RTX && GET_CODE (insn) == INSN_LIST; + insn = XEXP (insn, 1)) + ; + return insn; +} + +/* Return true if we need secondary memory moves for insn in + USAGE_INSNS after inserting inherited pseudo of class INHER_CL + into the insn. */ +static bool +check_secondary_memory_needed_p (enum reg_class inher_cl ATTRIBUTE_UNUSED, + rtx usage_insns ATTRIBUTE_UNUSED) +{ +#ifndef SECONDARY_MEMORY_NEEDED + return false; +#else + rtx insn, set, dest; + enum reg_class cl; + + if (inher_cl == ALL_REGS + || (insn = skip_usage_debug_insns (usage_insns)) == NULL_RTX) + return false; + lra_assert (INSN_P (insn)); + if ((set = single_set (insn)) == NULL_RTX || ! REG_P (SET_DEST (set))) + return false; + dest = SET_DEST (set); + if (! REG_P (dest)) + return false; + lra_assert (inher_cl != NO_REGS); + cl = get_reg_class (REGNO (dest)); + return (cl != NO_REGS && cl != ALL_REGS + && SECONDARY_MEMORY_NEEDED (inher_cl, cl, GET_MODE (dest))); +#endif +} + /* Registers involved in inheritance/split in the current EBB (inheritance/split pseudos and original registers). */ static bitmap_head check_only_regs; @@ -3873,8 +3633,8 @@ static bitmap_head check_only_regs; ... => <- ... p ... <- ... i ... where p is a spilled original pseudo and i is a new inheritance pseudo. - - + + The inheritance pseudo has the smallest class of two classes CL and class of ORIGINAL REGNO. */ static bool @@ -3888,18 +3648,18 @@ inherit_reload_reg (bool def_p, int original_regno, lra_assert (! usage_insns[original_regno].after_p); if (lra_dump_file != NULL) fprintf (lra_dump_file, - " <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<\n"); + " <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<\n"); if (! ira_reg_classes_intersect_p[cl][rclass]) { if (lra_dump_file != NULL) { fprintf (lra_dump_file, - " Rejecting inheritance for %d " + " Rejecting inheritance for %d " "because of disjoint classes %s and %s\n", original_regno, reg_class_names[cl], reg_class_names[rclass]); fprintf (lra_dump_file, - " >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>\n"); + " >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>\n"); } return false; } @@ -3913,9 +3673,34 @@ inherit_reload_reg (bool def_p, int original_regno, if (lra_dump_file != NULL) fprintf (lra_dump_file, " Use smallest class of %s and %s\n", reg_class_names[cl], reg_class_names[rclass]); - + rclass = cl; } + if (check_secondary_memory_needed_p (cl, next_usage_insns)) + { + /* Reject inheritance resulting in secondary memory moves. + Otherwise, there is a danger in LRA cycling. Also such + transformation will be unprofitable. */ + if (lra_dump_file != NULL) + { + rtx insn = skip_usage_debug_insns (next_usage_insns); + rtx set = single_set (insn); + + lra_assert (set != NULL_RTX); + + rtx dest = SET_DEST (set); + + lra_assert (REG_P (dest)); + fprintf (lra_dump_file, + " Rejecting inheritance for insn %d(%s)<-%d(%s) " + "as secondary mem is needed\n", + REGNO (dest), reg_class_names[get_reg_class (REGNO (dest))], + original_regno, reg_class_names[cl]); + fprintf (lra_dump_file, + " >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>\n"); + } + return false; + } new_reg = lra_create_new_reg (GET_MODE (original_reg), original_reg, rclass, "inheritance"); start_sequence (); @@ -3930,7 +3715,7 @@ inherit_reload_reg (bool def_p, int original_regno, if (lra_dump_file != NULL) { fprintf (lra_dump_file, - " Rejecting inheritance %d->%d " + " Rejecting inheritance %d->%d " "as it results in 2 or more insns:\n", original_regno, REGNO (new_reg)); debug_rtl_slim (lra_dump_file, new_insns, NULL_RTX, -1, 0); @@ -3945,7 +3730,7 @@ inherit_reload_reg (bool def_p, int original_regno, /* We now have a new usage insn for original regno. */ setup_next_usage_insn (original_regno, new_insns, reloads_num, false); if (lra_dump_file != NULL) - fprintf (lra_dump_file, " Original reg change %d->%d (bb%d):\n", + fprintf (lra_dump_file, " Original reg change %d->%d (bb%d):\n", original_regno, REGNO (new_reg), BLOCK_FOR_INSN (insn)->index); lra_reg_info[REGNO (new_reg)].restore_regno = original_regno; bitmap_set_bit (&check_only_regs, REGNO (new_reg)); @@ -4067,8 +3852,9 @@ choose_split_class (enum reg_class allocno_class, #else int i; enum reg_class cl, best_cl = NO_REGS; - enum reg_class hard_reg_class = REGNO_REG_CLASS (hard_regno); - + enum reg_class hard_reg_class ATTRIBUTE_UNUSED + = REGNO_REG_CLASS (hard_regno); + if (! SECONDARY_MEMORY_NEEDED (allocno_class, allocno_class, mode) && TEST_HARD_REG_BIT (reg_class_contents[allocno_class], hard_regno)) return allocno_class; @@ -4139,7 +3925,7 @@ split_reg (bool before_p, int original_regno, rtx insn, rtx next_usage_insns) if (call_save_p) { enum machine_mode sec_mode; - + #ifdef SECONDARY_MEMORY_NEEDED_MODE sec_mode = SECONDARY_MEMORY_NEEDED_MODE (GET_MODE (original_reg)); #else @@ -4299,7 +4085,7 @@ update_ebb_live_info (rtx head, rtx tail) edge e; edge_iterator ei; - last_bb = BLOCK_FOR_INSN (tail); + last_bb = BLOCK_FOR_INSN (tail); prev_bb = NULL; for (curr_insn = tail; curr_insn != PREV_INSN (head); @@ -4447,7 +4233,7 @@ get_live_on_other_edges (basic_block from, basic_block to, bitmap res) if (reg->type != OP_IN) bitmap_set_bit (res, reg->regno); } - + /* Used as a temporary results of some bitmap calculations. */ static bitmap_head temp_bitmap; @@ -4498,7 +4284,7 @@ inherit_in_ebb (rtx head, rtx tail) pseudos for potential splitting. */ to_process = df_get_live_out (curr_bb); if (last_processed_bb != NULL) - { + { /* We are somewhere in the middle of EBB. */ get_live_on_other_edges (curr_bb, last_processed_bb, &temp_bitmap); @@ -4599,7 +4385,7 @@ inherit_in_ebb (rtx head, rtx tail) = usage_insns[dst_regno].insns) != NULL_RTX) { struct lra_insn_reg *r; - + for (r = curr_id->regs; r != NULL; r = r->next) if (r->type != OP_OUT && r->regno == dst_regno) break; @@ -4618,7 +4404,7 @@ inherit_in_ebb (rtx head, rtx tail) && ! reg->subreg_p && reg->type == OP_OUT) { HARD_REG_SET s; - + if (split_if_necessary (dst_regno, reg->biggest_mode, potential_reload_hard_regs, false, curr_insn, max_uid)) @@ -4765,7 +4551,7 @@ inherit_in_ebb (rtx head, rtx tail) rest of spliting in the current BB. */ to_process = df_get_live_in (curr_bb); if (BLOCK_FOR_INSN (head) != curr_bb) - { + { /* We are somewhere in the middle of EBB. */ get_live_on_other_edges (EDGE_PRED (curr_bb, 0)->src, curr_bb, &temp_bitmap); @@ -4802,7 +4588,7 @@ inherit_in_ebb (rtx head, rtx tail) /* This value affects EBB forming. If probability of edge from EBB to a BB is not greater than the following value, we don't add the BB - to EBB. */ + to EBB. */ #define EBB_PROBABILITY_CUTOFF (REG_BR_PROB_BASE / 2) /* Current number of inheritance/split iteration. */ @@ -4945,7 +4731,7 @@ remove_inheritance_pseudos (bitmap remove_pseudos) dregno = get_regno (SET_DEST (set)); sregno = get_regno (SET_SRC (set)); } - + if (sregno >= 0 && dregno >= 0) { if ((bitmap_bit_p (remove_pseudos, sregno) |