Mercurial > hg > CbC > CbC_gcc
diff gcc/reload.c @ 55:77e2b8dfacca gcc-4.4.5
update it from 4.4.3 to 4.5.0
author | ryoma <e075725@ie.u-ryukyu.ac.jp> |
---|---|
date | Fri, 12 Feb 2010 23:39:51 +0900 |
parents | 3bfb6c00c1e0 |
children | b7f97abdc517 |
line wrap: on
line diff
--- a/gcc/reload.c Sun Feb 07 18:28:00 2010 +0900 +++ b/gcc/reload.c Fri Feb 12 23:39:51 2010 +0900 @@ -112,6 +112,7 @@ #include "params.h" #include "target.h" #include "df.h" +#include "ira.h" /* True if X is a constant that can be forced into the constant pool. */ #define CONST_POOL_OK_P(X) \ @@ -267,7 +268,8 @@ static rtx find_reloads_toplev (rtx, int, enum reload_type, int, int, rtx, int *); static rtx make_memloc (rtx, int); -static int maybe_memory_address_p (enum machine_mode, rtx, rtx *); +static int maybe_memory_address_addr_space_p (enum machine_mode, rtx, + addr_space_t, rtx *); static int find_reloads_address (enum machine_mode, rtx *, rtx, rtx *, int, enum reload_type, int, rtx); static rtx subst_reg_equivs (rtx, rtx); @@ -363,7 +365,7 @@ sri.icode = CODE_FOR_nothing; sri.prev_sri = prev_sri; rclass = targetm.secondary_reload (in_p, x, reload_class, reload_mode, &sri); - icode = sri.icode; + icode = (enum insn_code) sri.icode; /* If we don't need any secondary registers, done. */ if (rclass == NO_REGS && icode == CODE_FOR_nothing) @@ -525,7 +527,7 @@ sri.icode = CODE_FOR_nothing; sri.prev_sri = NULL; rclass = targetm.secondary_reload (in_p, x, rclass, mode, &sri); - icode = sri.icode; + icode = (enum insn_code) sri.icode; /* If there are no secondary reloads at all, we return NO_REGS. If an intermediate register is needed, we return its class. */ @@ -611,7 +613,8 @@ didn't give us a new MEM, make a new one if it isn't valid. */ loc = eliminate_regs (secondary_memlocs[(int) mode], VOIDmode, NULL_RTX); - mem_valid = strict_memory_address_p (mode, XEXP (loc, 0)); + mem_valid = strict_memory_address_addr_space_p (mode, XEXP (loc, 0), + MEM_ADDR_SPACE (loc)); if (! mem_valid && loc == secondary_memlocs[(int) mode]) loc = copy_rtx (loc); @@ -685,15 +688,16 @@ if (bad || !good) continue; - cost = REGISTER_MOVE_COST (outer, rclass, dest_class); + cost = REGISTER_MOVE_COST (outer, (enum reg_class) rclass, dest_class); if ((reg_class_size[rclass] > best_size && (best_cost < 0 || best_cost >= cost)) || best_cost > cost) { - best_class = rclass; + best_class = (enum reg_class) rclass; best_size = reg_class_size[rclass]; - best_cost = REGISTER_MOVE_COST (outer, rclass, dest_class); + best_cost = REGISTER_MOVE_COST (outer, (enum reg_class) rclass, + dest_class); } } @@ -1282,7 +1286,7 @@ Returning zero here ought to be safe as we take care in find_reloads to not process the reloads when instruction was replaced by USE. */ - + return 0; } } @@ -1516,7 +1520,7 @@ value for the incoming operand (same as outgoing one). */ if (rld[i].reg_rtx == out && (REG_P (in) || CONSTANT_P (in)) - && 0 != find_equiv_reg (in, this_insn, 0, REGNO (out), + && 0 != find_equiv_reg (in, this_insn, NO_REGS, REGNO (out), static_reload_reg_p, i, inmode)) rld[i].in = out; } @@ -2127,18 +2131,24 @@ return 0; } -/* Return 1 if ADDR is a valid memory address for mode MODE, - and check that each pseudo reg has the proper kind of - hard reg. */ +/* Return 1 if ADDR is a valid memory address for mode MODE + in address space AS, and check that each pseudo reg has the + proper kind of hard reg. */ int -strict_memory_address_p (enum machine_mode mode ATTRIBUTE_UNUSED, rtx addr) +strict_memory_address_addr_space_p (enum machine_mode mode ATTRIBUTE_UNUSED, + rtx addr, addr_space_t as) { +#ifdef GO_IF_LEGITIMATE_ADDRESS + gcc_assert (ADDR_SPACE_GENERIC_P (as)); GO_IF_LEGITIMATE_ADDRESS (mode, addr, win); return 0; win: return 1; +#else + return targetm.addr_space.legitimate_address_p (mode, addr, 1, as); +#endif } /* Like rtx_equal_p except that it allows a REG and a SUBREG to match @@ -2241,6 +2251,10 @@ if (GET_MODE (x) != GET_MODE (y)) return 0; + /* MEMs refering to different address space are not equivalent. */ + if (code == MEM && MEM_ADDR_SPACE (x) != MEM_ADDR_SPACE (y)) + return 0; + switch (code) { case CONST_INT: @@ -2335,7 +2349,7 @@ { rtx base = NULL_RTX, offset = 0; rtx addr = XEXP (x, 0); - + if (GET_CODE (addr) == PRE_DEC || GET_CODE (addr) == PRE_INC || GET_CODE (addr) == POST_DEC || GET_CODE (addr) == POST_INC) { @@ -2345,7 +2359,7 @@ val.safe = REGNO (val.base) == STACK_POINTER_REGNUM; return val; } - + if (GET_CODE (addr) == PRE_MODIFY || GET_CODE (addr) == POST_MODIFY) { if (GET_CODE (XEXP (addr, 1)) == PLUS @@ -2359,7 +2373,7 @@ return val; } } - + if (GET_CODE (addr) == CONST) { addr = XEXP (addr, 0); @@ -2378,7 +2392,7 @@ offset = XEXP (addr, 1); } } - + if (offset == 0) { base = addr; @@ -2388,12 +2402,12 @@ offset = XEXP (offset, 0); if (GET_CODE (offset) == PLUS) { - if (GET_CODE (XEXP (offset, 0)) == CONST_INT) + if (CONST_INT_P (XEXP (offset, 0))) { base = gen_rtx_PLUS (GET_MODE (base), base, XEXP (offset, 1)); offset = XEXP (offset, 0); } - else if (GET_CODE (XEXP (offset, 1)) == CONST_INT) + else if (CONST_INT_P (XEXP (offset, 1))) { base = gen_rtx_PLUS (GET_MODE (base), base, XEXP (offset, 0)); offset = XEXP (offset, 1); @@ -2404,23 +2418,23 @@ offset = const0_rtx; } } - else if (GET_CODE (offset) != CONST_INT) + else if (!CONST_INT_P (offset)) { base = gen_rtx_PLUS (GET_MODE (base), base, offset); offset = const0_rtx; } - + if (all_const && GET_CODE (base) == PLUS) base = gen_rtx_CONST (GET_MODE (base), base); - - gcc_assert (GET_CODE (offset) == CONST_INT); - + + gcc_assert (CONST_INT_P (offset)); + val.start = INTVAL (offset); val.end = val.start + GET_MODE_SIZE (GET_MODE (x)); val.base = base; } break; - + case REG: val.reg_flag = 1; val.start = true_regnum (x); @@ -2551,7 +2565,7 @@ a register. */ enum reg_class preferred_class[MAX_RECOG_OPERANDS]; char pref_or_nothing[MAX_RECOG_OPERANDS]; - /* Nonzero for a MEM operand whose entire address needs a reload. + /* Nonzero for a MEM operand whose entire address needs a reload. May be -1 to indicate the entire address may or may not need a reload. */ int address_reloaded[MAX_RECOG_OPERANDS]; /* Nonzero for an address operand that needs to be completely reloaded. @@ -2565,7 +2579,7 @@ enum reload_usage { RELOAD_READ, RELOAD_READ_WRITE, RELOAD_WRITE } modified[MAX_RECOG_OPERANDS]; int no_input_reloads = 0, no_output_reloads = 0; int n_alternatives; - int this_alternative[MAX_RECOG_OPERANDS]; + enum reg_class this_alternative[MAX_RECOG_OPERANDS]; char this_alternative_match_win[MAX_RECOG_OPERANDS]; char this_alternative_win[MAX_RECOG_OPERANDS]; char this_alternative_offmemok[MAX_RECOG_OPERANDS]; @@ -2584,6 +2598,7 @@ char goal_alternative_earlyclobber[MAX_RECOG_OPERANDS]; int goal_alternative_swapped; int best; + int best_small_class_operands_num; int commutative; char operands_match[MAX_RECOG_OPERANDS][MAX_RECOG_OPERANDS]; rtx substed_operand[MAX_RECOG_OPERANDS]; @@ -2909,6 +2924,7 @@ all the operands together against the register constraints. */ best = MAX_RECOG_OPERANDS * 2 + 600; + best_small_class_operands_num = 0; swapped = 0; goal_alternative_swapped = 0; @@ -3059,7 +3075,7 @@ force_reload = 1; } - this_alternative[i] = (int) NO_REGS; + this_alternative[i] = NO_REGS; this_alternative_win[i] = 0; this_alternative_match_win[i] = 0; this_alternative_offmemok[i] = 0; @@ -3146,7 +3162,7 @@ this combination, because we can't reload it. */ if (this_alternative_offmemok[m] && MEM_P (recog_data.operand[m]) - && this_alternative[m] == (int) NO_REGS + && this_alternative[m] == NO_REGS && ! this_alternative_win[m]) bad = 1; @@ -3162,7 +3178,7 @@ if (this_alternative_win[m]) losers++; this_alternative_win[m] = 0; - if (this_alternative[m] == (int) NO_REGS) + if (this_alternative[m] == NO_REGS) bad = 1; /* But count the pair only once in the total badness of this alternative, if the pair can be a dummy reload. @@ -3211,8 +3227,8 @@ case 'p': /* All necessary reloads for an address_operand were handled in find_reloads_address. */ - this_alternative[i] - = (int) base_reg_class (VOIDmode, ADDRESS, SCRATCH); + this_alternative[i] = base_reg_class (VOIDmode, ADDRESS, + SCRATCH); win = 1; badop = 0; break; @@ -3317,7 +3333,7 @@ break; case 's': - if (GET_CODE (operand) == CONST_INT + if (CONST_INT_P (operand) || (GET_CODE (operand) == CONST_DOUBLE && GET_MODE (operand) == VOIDmode)) break; @@ -3328,7 +3344,7 @@ break; case 'n': - if (GET_CODE (operand) == CONST_INT + if (CONST_INT_P (operand) || (GET_CODE (operand) == CONST_DOUBLE && GET_MODE (operand) == VOIDmode)) win = 1; @@ -3342,7 +3358,7 @@ case 'N': case 'O': case 'P': - if (GET_CODE (operand) == CONST_INT + if (CONST_INT_P (operand) && CONST_OK_FOR_CONSTRAINT_P (INTVAL (operand), c, p)) win = 1; break; @@ -3371,7 +3387,7 @@ case 'r': this_alternative[i] - = (int) reg_class_subunion[this_alternative[i]][(int) GENERAL_REGS]; + = reg_class_subunion[this_alternative[i]][(int) GENERAL_REGS]; goto reg; default: @@ -3417,8 +3433,9 @@ /* If we didn't already win, we can reload the address into a base register. */ - this_alternative[i] - = (int) base_reg_class (VOIDmode, ADDRESS, SCRATCH); + this_alternative[i] = base_reg_class (VOIDmode, + ADDRESS, + SCRATCH); badop = 0; break; } @@ -3430,9 +3447,9 @@ } this_alternative[i] - = (int) (reg_class_subunion - [this_alternative[i]] - [(int) REG_CLASS_FROM_CONSTRAINT (c, p)]); + = (reg_class_subunion + [this_alternative[i]] + [(int) REG_CLASS_FROM_CONSTRAINT (c, p)]); reg: if (GET_MODE (operand) == BLKmode) break; @@ -3449,7 +3466,7 @@ /* If this operand could be handled with a reg, and some reg is allowed, then this operand can be handled. */ - if (winreg && this_alternative[i] != (int) NO_REGS) + if (winreg && this_alternative[i] != NO_REGS) badop = 0; /* Record which operands fit this alternative. */ @@ -3468,7 +3485,7 @@ bad = 1; /* Alternative loses if it has no regs for a reg operand. */ if (REG_P (operand) - && this_alternative[i] == (int) NO_REGS + && this_alternative[i] == NO_REGS && this_alternative_matches[i] < 0) bad = 1; @@ -3481,14 +3498,13 @@ precisely the same as in the code below that calls force_const_mem. */ if (CONST_POOL_OK_P (operand) - && ((PREFERRED_RELOAD_CLASS (operand, - (enum reg_class) this_alternative[i]) + && ((PREFERRED_RELOAD_CLASS (operand, this_alternative[i]) == NO_REGS) || no_input_reloads) && operand_mode[i] != VOIDmode) { const_to_mem = 1; - if (this_alternative[i] != (int) NO_REGS) + if (this_alternative[i] != NO_REGS) losers++; } @@ -3508,19 +3524,17 @@ LIMIT_RELOAD_CLASS, but we don't check that here. */ - if (! CONSTANT_P (operand) - && (enum reg_class) this_alternative[i] != NO_REGS) + if (! CONSTANT_P (operand) && this_alternative[i] != NO_REGS) { - if (PREFERRED_RELOAD_CLASS - (operand, (enum reg_class) this_alternative[i]) + if (PREFERRED_RELOAD_CLASS (operand, this_alternative[i]) == NO_REGS) reject = 600; #ifdef PREFERRED_OUTPUT_RELOAD_CLASS if (operand_type[i] == RELOAD_FOR_OUTPUT - && PREFERRED_OUTPUT_RELOAD_CLASS - (operand, (enum reg_class) this_alternative[i]) - == NO_REGS) + && (PREFERRED_OUTPUT_RELOAD_CLASS (operand, + this_alternative[i]) + == NO_REGS)) reject = 600; #endif } @@ -3568,7 +3582,7 @@ because we might otherwise exhaust the class. */ if (! win && ! did_match - && this_alternative[i] != (int) NO_REGS + && this_alternative[i] != NO_REGS && GET_MODE_SIZE (operand_mode[i]) <= UNITS_PER_WORD && reg_class_size [(int) preferred_class[i]] > 0 && ! SMALL_REGISTER_CLASS_P (preferred_class[i])) @@ -3582,7 +3596,7 @@ common case anyway. */ if (reg_class_subset_p (preferred_class[i], this_alternative[i])) - this_alternative[i] = (int) preferred_class[i]; + this_alternative[i] = preferred_class[i]; else reject += (2 + 2 * pref_or_nothing[i]); } @@ -3694,22 +3708,48 @@ /* If this alternative can be made to work by reloading, and it needs less reloading than the others checked so far, record it as the chosen goal for reloading. */ - if (! bad && best > losers) + if (! bad) { - for (i = 0; i < noperands; i++) + bool change_p = false; + int small_class_operands_num = 0; + + if (best >= losers) { - goal_alternative[i] = this_alternative[i]; - goal_alternative_win[i] = this_alternative_win[i]; - goal_alternative_match_win[i] = this_alternative_match_win[i]; - goal_alternative_offmemok[i] = this_alternative_offmemok[i]; - goal_alternative_matches[i] = this_alternative_matches[i]; - goal_alternative_earlyclobber[i] - = this_alternative_earlyclobber[i]; + for (i = 0; i < noperands; i++) + small_class_operands_num + += SMALL_REGISTER_CLASS_P (this_alternative[i]) ? 1 : 0; + if (best > losers + || (best == losers + /* If the cost of the reloads is the same, + prefer alternative which requires minimal + number of small register classes for the + operands. This improves chances of reloads + for insn requiring small register + classes. */ + && (small_class_operands_num + < best_small_class_operands_num))) + change_p = true; } - goal_alternative_swapped = swapped; - best = losers; - goal_alternative_number = this_alternative_number; - goal_earlyclobber = this_earlyclobber; + if (change_p) + { + for (i = 0; i < noperands; i++) + { + goal_alternative[i] = this_alternative[i]; + goal_alternative_win[i] = this_alternative_win[i]; + goal_alternative_match_win[i] + = this_alternative_match_win[i]; + goal_alternative_offmemok[i] + = this_alternative_offmemok[i]; + goal_alternative_matches[i] = this_alternative_matches[i]; + goal_alternative_earlyclobber[i] + = this_alternative_earlyclobber[i]; + } + goal_alternative_swapped = swapped; + best = losers; + best_small_class_operands_num = small_class_operands_num; + goal_alternative_number = this_alternative_number; + goal_earlyclobber = this_earlyclobber; + } } } @@ -3947,12 +3987,15 @@ && MEM_P (recog_data.operand[i])) { /* If the address to be reloaded is a VOIDmode constant, - use Pmode as mode of the reload register, as would have - been done by find_reloads_address. */ + use the default address mode as mode of the reload register, + as would have been done by find_reloads_address. */ enum machine_mode address_mode; address_mode = GET_MODE (XEXP (recog_data.operand[i], 0)); if (address_mode == VOIDmode) - address_mode = Pmode; + { + addr_space_t as = MEM_ADDR_SPACE (recog_data.operand[i]); + address_mode = targetm.addr_space.address_mode (as); + } operand_reloadnum[i] = push_reload (XEXP (recog_data.operand[i], 0), NULL_RTX, @@ -4230,7 +4273,7 @@ /* If we detected error and replaced asm instruction by USE, forget about the reloads. */ if (GET_CODE (PATTERN (insn)) == USE - && GET_CODE (XEXP (PATTERN (insn), 0)) == CONST_INT) + && CONST_INT_P (XEXP (PATTERN (insn), 0))) n_reloads = 0; /* Perhaps an output reload can be combined with another @@ -4557,7 +4600,8 @@ is null. */ static bool -alternative_allows_const_pool_ref (rtx mem, const char *constraint, int altnum) +alternative_allows_const_pool_ref (rtx mem ATTRIBUTE_UNUSED, + const char *constraint, int altnum) { int c; @@ -4727,8 +4771,9 @@ #endif && (reg_equiv_address[regno] != 0 || (reg_equiv_mem[regno] != 0 - && (! strict_memory_address_p (GET_MODE (x), - XEXP (reg_equiv_mem[regno], 0)) + && (! strict_memory_address_addr_space_p + (GET_MODE (x), XEXP (reg_equiv_mem[regno], 0), + MEM_ADDR_SPACE (reg_equiv_mem[regno])) || ! offsettable_memref_p (reg_equiv_mem[regno]) || num_not_at_initial_offset)))) x = find_reloads_subreg_address (x, 1, opnum, type, ind_levels, @@ -4767,7 +4812,8 @@ /* We must rerun eliminate_regs, in case the elimination offsets have changed. */ rtx tem - = XEXP (eliminate_regs (reg_equiv_memory_loc[regno], 0, NULL_RTX), 0); + = XEXP (eliminate_regs (reg_equiv_memory_loc[regno], VOIDmode, NULL_RTX), + 0); /* If TEM might contain a pseudo, we must copy it to avoid modifying it when we do the substitution for the reload. */ @@ -4785,18 +4831,19 @@ } /* Returns true if AD could be turned into a valid memory reference - to mode MODE by reloading the part pointed to by PART into a - register. */ + to mode MODE in address space AS by reloading the part pointed to + by PART into a register. */ static int -maybe_memory_address_p (enum machine_mode mode, rtx ad, rtx *part) +maybe_memory_address_addr_space_p (enum machine_mode mode, rtx ad, + addr_space_t as, rtx *part) { int retv; rtx tem = *part; rtx reg = gen_rtx_REG (GET_MODE (tem), max_reg_num ()); *part = reg; - retv = memory_address_p (mode, ad); + retv = memory_address_addr_space_p (mode, ad, as); *part = tem; return retv; @@ -4832,6 +4879,8 @@ rtx *loc, int opnum, enum reload_type type, int ind_levels, rtx insn) { + addr_space_t as = memrefloc? MEM_ADDR_SPACE (*memrefloc) + : ADDR_SPACE_GENERIC; int regno; int removed_and = 0; int op_index; @@ -4859,7 +4908,9 @@ if (reg_equiv_address[regno] != 0 || num_not_at_initial_offset) { tem = make_memloc (ad, regno); - if (! strict_memory_address_p (GET_MODE (tem), XEXP (tem, 0))) + if (! strict_memory_address_addr_space_p (GET_MODE (tem), + XEXP (tem, 0), + MEM_ADDR_SPACE (tem))) { rtx orig = tem; @@ -4875,7 +4926,7 @@ address: only reg or reg+constant. */ if (ind_levels > 0 - && strict_memory_address_p (mode, tem) + && strict_memory_address_addr_space_p (mode, tem, as) && (REG_P (XEXP (tem, 0)) || (GET_CODE (XEXP (tem, 0)) == PLUS && REG_P (XEXP (XEXP (tem, 0), 0)) @@ -4919,7 +4970,7 @@ return 1; } - if (strict_memory_address_p (mode, ad)) + if (strict_memory_address_addr_space_p (mode, ad, as)) { /* The address appears valid, so reloads are not needed. But the address may contain an eliminable register. @@ -4930,7 +4981,7 @@ /* But first quickly dispose of a common case. */ if (GET_CODE (ad) == PLUS - && GET_CODE (XEXP (ad, 1)) == CONST_INT + && CONST_INT_P (XEXP (ad, 1)) && REG_P (XEXP (ad, 0)) && reg_equiv_constant[REGNO (XEXP (ad, 0))] == 0) return 0; @@ -4942,14 +4993,14 @@ return 0; /* Check result for validity after substitution. */ - if (strict_memory_address_p (mode, ad)) + if (strict_memory_address_addr_space_p (mode, ad, as)) return 0; } #ifdef LEGITIMIZE_RELOAD_ADDRESS do { - if (memrefloc) + if (memrefloc && ADDR_SPACE_GENERIC_P (as)) { LEGITIMIZE_RELOAD_ADDRESS (ad, GET_MODE (*memrefloc), opnum, type, ind_levels, win); @@ -5010,7 +5061,7 @@ || ! (REG_P (XEXP (tem, 0)) || (GET_CODE (XEXP (tem, 0)) == PLUS && REG_P (XEXP (XEXP (tem, 0), 0)) - && GET_CODE (XEXP (XEXP (tem, 0), 1)) == CONST_INT))) + && CONST_INT_P (XEXP (XEXP (tem, 0), 1))))) { /* Must use TEM here, not AD, since it is the one that will have any subexpressions reloaded, if needed. */ @@ -5032,7 +5083,7 @@ else if (GET_CODE (ad) == PLUS && REG_P (XEXP (ad, 0)) && REGNO (XEXP (ad, 0)) < FIRST_PSEUDO_REGISTER - && GET_CODE (XEXP (ad, 1)) == CONST_INT + && CONST_INT_P (XEXP (ad, 1)) && regno_ok_for_base_p (REGNO (XEXP (ad, 0)), mode, PLUS, CONST_INT)) @@ -5065,7 +5116,7 @@ That will at least work. */ find_reloads_address_part (ad, loc, base_reg_class (mode, MEM, SCRATCH), - Pmode, opnum, type, ind_levels); + GET_MODE (ad), opnum, type, ind_levels); } return ! removed_and; } @@ -5105,8 +5156,8 @@ continue; inner_code = GET_CODE (XEXP (ad, 0)); - if (!(GET_CODE (ad) == PLUS - && GET_CODE (XEXP (ad, 1)) == CONST_INT + if (!(GET_CODE (ad) == PLUS + && CONST_INT_P (XEXP (ad, 1)) && (inner_code == PLUS || inner_code == LO_SUM))) continue; @@ -5126,8 +5177,8 @@ || operand == arg_pointer_rtx #endif || operand == stack_pointer_rtx) - && ! maybe_memory_address_p (mode, ad, - &XEXP (XEXP (ad, 0), 1 - op_index))) + && ! maybe_memory_address_addr_space_p + (mode, ad, as, &XEXP (XEXP (ad, 0), 1 - op_index))) { rtx offset_reg; enum reg_class cls; @@ -5136,17 +5187,17 @@ /* Form the adjusted address. */ if (GET_CODE (XEXP (ad, 0)) == PLUS) - ad = gen_rtx_PLUS (GET_MODE (ad), - op_index == 0 ? offset_reg : addend, + ad = gen_rtx_PLUS (GET_MODE (ad), + op_index == 0 ? offset_reg : addend, op_index == 0 ? addend : offset_reg); else - ad = gen_rtx_LO_SUM (GET_MODE (ad), - op_index == 0 ? offset_reg : addend, + ad = gen_rtx_LO_SUM (GET_MODE (ad), + op_index == 0 ? offset_reg : addend, op_index == 0 ? addend : offset_reg); *loc = ad; cls = base_reg_class (mode, MEM, GET_CODE (addend)); - find_reloads_address_part (XEXP (ad, op_index), + find_reloads_address_part (XEXP (ad, op_index), &XEXP (ad, op_index), cls, GET_MODE (ad), opnum, type, ind_levels); find_reloads_address_1 (mode, @@ -5165,7 +5216,7 @@ tem = ad; if (GET_CODE (ad) == PLUS) tem = subst_indexed_address (ad); - if (tem != ad && strict_memory_address_p (mode, tem)) + if (tem != ad && strict_memory_address_addr_space_p (mode, tem, as)) { /* Ok, we win that way. Replace any additional eliminable registers. */ @@ -5175,7 +5226,8 @@ /* Make sure that didn't make the address invalid again. */ - if (! subst_reg_equivs_changed || strict_memory_address_p (mode, tem)) + if (! subst_reg_equivs_changed + || strict_memory_address_addr_space_p (mode, tem, as)) { *loc = tem; return 0; @@ -5184,8 +5236,12 @@ /* If constants aren't valid addresses, reload the constant address into a register. */ - if (CONSTANT_P (ad) && ! strict_memory_address_p (mode, ad)) + if (CONSTANT_P (ad) && ! strict_memory_address_addr_space_p (mode, ad, as)) { + enum machine_mode address_mode = GET_MODE (ad); + if (address_mode == VOIDmode) + address_mode = targetm.addr_space.address_mode (as); + /* If AD is an address in the constant pool, the MEM rtx may be shared. Unshare it so we can safely alter it. */ if (memrefloc && GET_CODE (ad) == SYMBOL_REF @@ -5198,7 +5254,7 @@ } find_reloads_address_part (ad, loc, base_reg_class (mode, MEM, SCRATCH), - Pmode, opnum, type, ind_levels); + address_mode, opnum, type, ind_levels); return ! removed_and; } @@ -5262,7 +5318,7 @@ case PLUS: /* Quickly dispose of a common case. */ if (XEXP (ad, 0) == frame_pointer_rtx - && GET_CODE (XEXP (ad, 1)) == CONST_INT) + && CONST_INT_P (XEXP (ad, 1))) return ad; break; @@ -5285,31 +5341,27 @@ This routine assumes both inputs are already in canonical form. */ rtx -form_sum (rtx x, rtx y) +form_sum (enum machine_mode mode, rtx x, rtx y) { rtx tem; - enum machine_mode mode = GET_MODE (x); - - if (mode == VOIDmode) - mode = GET_MODE (y); - - if (mode == VOIDmode) - mode = Pmode; - - if (GET_CODE (x) == CONST_INT) + + gcc_assert (GET_MODE (x) == mode || GET_MODE (x) == VOIDmode); + gcc_assert (GET_MODE (y) == mode || GET_MODE (y) == VOIDmode); + + if (CONST_INT_P (x)) return plus_constant (y, INTVAL (x)); - else if (GET_CODE (y) == CONST_INT) + else if (CONST_INT_P (y)) return plus_constant (x, INTVAL (y)); else if (CONSTANT_P (x)) tem = x, x = y, y = tem; if (GET_CODE (x) == PLUS && CONSTANT_P (XEXP (x, 1))) - return form_sum (XEXP (x, 0), form_sum (XEXP (x, 1), y)); + return form_sum (mode, XEXP (x, 0), form_sum (mode, XEXP (x, 1), y)); /* Note that if the operands of Y are specified in the opposite order in the recursive calls below, infinite recursion will occur. */ if (GET_CODE (y) == PLUS && CONSTANT_P (XEXP (y, 1))) - return form_sum (form_sum (x, XEXP (y, 0)), XEXP (y, 1)); + return form_sum (mode, form_sum (mode, x, XEXP (y, 0)), XEXP (y, 1)); /* If both constant, encapsulate sum. Otherwise, just form sum. A constant will have been placed second. */ @@ -5376,9 +5428,9 @@ /* Compute the sum. */ if (op2 != 0) - op1 = form_sum (op1, op2); + op1 = form_sum (GET_MODE (addr), op1, op2); if (op1 != 0) - op0 = form_sum (op0, op1); + op0 = form_sum (GET_MODE (addr), op0, op1); return op0; } @@ -5448,7 +5500,7 @@ #define REG_OK_FOR_CONTEXT(CONTEXT, REGNO, MODE, OUTER, INDEX) \ ((CONTEXT) == 0 \ ? regno_ok_for_base_p (REGNO, MODE, OUTER, INDEX) \ - : REGNO_OK_FOR_INDEX_P (REGNO)) + : REGNO_OK_FOR_INDEX_P (REGNO)) enum reg_class context_reg_class; RTX_CODE code = GET_CODE (x); @@ -5778,7 +5830,8 @@ rtx equiv = (MEM_P (XEXP (x, 0)) ? XEXP (x, 0) : reg_equiv_mem[regno]); - int icode = (int) optab_handler (add_optab, Pmode)->insn_code; + int icode + = (int) optab_handler (add_optab, GET_MODE (x))->insn_code; if (insn && NONJUMP_INSN_P (insn) && equiv && memory_operand (equiv, GET_MODE (equiv)) #ifdef HAVE_cc0 @@ -5786,9 +5839,9 @@ #endif && ! (icode != CODE_FOR_nothing && ((*insn_data[icode].operand[0].predicate) - (equiv, Pmode)) + (equiv, GET_MODE (x))) && ((*insn_data[icode].operand[1].predicate) - (equiv, Pmode)))) + (equiv, GET_MODE (x))))) { /* We use the original pseudo for loc, so that emit_reload_insns() knows which pseudo this @@ -5954,7 +6007,7 @@ if ((unsigned) CLASS_MAX_NREGS (rclass, GET_MODE (SUBREG_REG (x))) > reg_class_size[rclass]) { - x = find_reloads_subreg_address (x, 0, opnum, + x = find_reloads_subreg_address (x, 0, opnum, ADDR_TYPE (type), ind_levels, insn); push_reload (x, NULL_RTX, loc, (rtx*) 0, rclass, @@ -6110,7 +6163,7 @@ base = XEXP (tem, 0); if (GET_CODE (base) == PLUS) { - if (GET_CODE (XEXP (base, 1)) == CONST_INT + if (CONST_INT_P (XEXP (base, 1)) && INTVAL (XEXP (base, 1)) % outer_size != 0) return x; base = XEXP (base, 0); @@ -6131,18 +6184,27 @@ /* For some processors an address may be valid in the original mode but not in a smaller mode. For example, ARM accepts a scaled index register in - SImode but not in HImode. Similarly, the address may - have been valid before the subreg offset was added, - but not afterwards. find_reloads_address - assumes that we pass it a valid address, and doesn't - force a reload. This will probably be fine if - find_reloads_address finds some reloads. But if it - doesn't find any, then we may have just converted a - valid address into an invalid one. Check for that - here. */ + SImode but not in HImode. Note that this is only + a problem if the address in reg_equiv_mem is already + invalid in the new mode; other cases would be fixed + by find_reloads_address as usual. + + ??? We attempt to handle such cases here by doing an + additional reload of the full address after the + usual processing by find_reloads_address. Note that + this may not work in the general case, but it seems + to cover the cases where this situation currently + occurs. A more general fix might be to reload the + *value* instead of the address, but this would not + be expected by the callers of this routine as-is. + + If find_reloads_address already completed replaced + the address, there is nothing further to do. */ if (reloaded == 0 - && !strict_memory_address_p (GET_MODE (tem), - XEXP (tem, 0))) + && reg_equiv_mem[regno] != 0 + && !strict_memory_address_addr_space_p + (GET_MODE (x), XEXP (reg_equiv_mem[regno], 0), + MEM_ADDR_SPACE (reg_equiv_mem[regno]))) push_reload (XEXP (tem, 0), NULL_RTX, &XEXP (tem, 0), (rtx*) 0, base_reg_class (GET_MODE (tem), MEM, SCRATCH), GET_MODE (XEXP (tem, 0)), VOIDmode, 0, 0, @@ -6546,7 +6608,7 @@ /* If either argument is a constant, then modifying X can not affect IN. */ if (CONSTANT_P (x) || CONSTANT_P (in)) return 0; - else if (GET_CODE (x) == SUBREG && GET_CODE (SUBREG_REG (x)) == MEM) + else if (GET_CODE (x) == SUBREG && MEM_P (SUBREG_REG (x))) return refers_to_mem_for_reload_p (in); else if (GET_CODE (x) == SUBREG) { @@ -6585,7 +6647,7 @@ else if (GET_CODE (x) == SCRATCH || GET_CODE (x) == PC || GET_CODE (x) == CC0) return reg_mentioned_p (x, in); - else + else { gcc_assert (GET_CODE (x) == PLUS); @@ -6726,6 +6788,8 @@ while (1) { p = PREV_INSN (p); + if (p && DEBUG_INSN_P (p)) + continue; num++; if (p == 0 || LABEL_P (p) || num > PARAM_VALUE (PARAM_MAX_RELOAD_SEARCH_INSNS)) @@ -6780,7 +6844,7 @@ || (REG_P (SET_DEST (pat)) && GET_CODE (XEXP (tem, 0)) == CONST_DOUBLE && SCALAR_FLOAT_MODE_P (GET_MODE (XEXP (tem, 0))) - && GET_CODE (goal) == CONST_INT + && CONST_INT_P (goal) && 0 != (goaltry = operand_subword (XEXP (tem, 0), 0, 0, VOIDmode)) @@ -6794,7 +6858,7 @@ && REG_P (SET_DEST (pat)) && GET_CODE (XEXP (tem, 0)) == CONST_DOUBLE && SCALAR_FLOAT_MODE_P (GET_MODE (XEXP (tem, 0))) - && GET_CODE (goal) == CONST_INT + && CONST_INT_P (goal) && 0 != (goaltry = operand_subword (XEXP (tem, 0), 1, 0, VOIDmode)) && rtx_equal_p (goal, goaltry) @@ -7122,7 +7186,7 @@ && GET_CODE (XEXP (addr, 1)) == PLUS && XEXP (addr, 0) == XEXP (XEXP (addr, 1), 0) && XEXP (addr, 0) == inced - && GET_CODE (XEXP (XEXP (addr, 1), 1)) == CONST_INT) + && CONST_INT_P (XEXP (XEXP (addr, 1), 1))) { i = INTVAL (XEXP (XEXP (addr, 1), 1)); return i < 0 ? -i : i; @@ -7157,7 +7221,7 @@ REG_INC note in insn INSN. REGNO must refer to a hard register. */ #ifdef AUTO_INC_DEC -static int +static int reg_inc_found_and_valid_p (unsigned int regno, unsigned int endregno, rtx insn) { @@ -7167,13 +7231,13 @@ if (! INSN_P (insn)) return 0; - + for (link = REG_NOTES (insn); link; link = XEXP (link, 1)) if (REG_NOTE_KIND (link) == REG_INC) { unsigned int test = (int) REGNO (XEXP (link, 0)); if (test >= regno && test < endregno) - return 1; + return 1; } return 0; } @@ -7181,7 +7245,7 @@ #define reg_inc_found_and_valid_p(regno,endregno,insn) 0 -#endif +#endif /* Return 1 if register REGNO is the subject of a clobber in insn INSN. If SETS is 1, also consider SETs. If SETS is 2, enable checking @@ -7209,8 +7273,8 @@ } if (sets == 2 && reg_inc_found_and_valid_p (regno, endregno, insn)) - return 1; - + return 1; + if (GET_CODE (PATTERN (insn)) == PARALLEL) { int i = XVECLEN (PATTERN (insn), 0) - 1; @@ -7229,7 +7293,7 @@ } if (sets == 2 && reg_inc_found_and_valid_p (regno, endregno, elt)) - return 1; + return 1; } }