X-Git-Url: http://git.sourceforge.jp/view?a=blobdiff_plain;f=gcc%2Freload.c;h=8420c80807375f7e9bb4b9d5ffa1c722ba97eccf;hb=2dfa96e7dabc43d6f9ebf87461581e32a3f3cdcb;hp=d4b7982bc0a12789dba84f7873d9e943e0de7abe;hpb=4b987facd8ba658d00c277a7e9c46548b492854f;p=pf3gnuchains%2Fgcc-fork.git diff --git a/gcc/reload.c b/gcc/reload.c index d4b7982bc0a..8420c808073 100644 --- a/gcc/reload.c +++ b/gcc/reload.c @@ -1,6 +1,6 @@ /* Search an insn for pseudo regs that must be in hard regs and are not. Copyright (C) 1987, 1988, 1989, 1992, 1993, 1994, 1995, 1996, 1997, 1998, - 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 + 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010 Free Software Foundation, Inc. This file is part of GCC. @@ -94,7 +94,7 @@ a register with any other reload. */ #include "system.h" #include "coretypes.h" #include "tm.h" -#include "rtl.h" +#include "rtl-error.h" #include "tm_p.h" #include "insn-config.h" #include "expr.h" @@ -108,22 +108,28 @@ a register with any other reload. */ #include "flags.h" #include "output.h" #include "function.h" -#include "toplev.h" #include "params.h" #include "target.h" #include "ira.h" -/* True if X is a constant that can be forced into the constant pool. */ -#define CONST_POOL_OK_P(X) \ - (CONSTANT_P (X) \ +/* True if X is a constant that can be forced into the constant pool. + MODE is the mode of the operand, or VOIDmode if not known. */ +#define CONST_POOL_OK_P(MODE, X) \ + ((MODE) != VOIDmode \ + && CONSTANT_P (X) \ && GET_CODE (X) != HIGH \ - && !targetm.cannot_force_const_mem (X)) + && !targetm.cannot_force_const_mem (MODE, X)) /* True if C is a non-empty register class that has too few registers to be safely used as a reload target class. */ -#define SMALL_REGISTER_CLASS_P(C) \ - (reg_class_size [(C)] == 1 \ - || (reg_class_size [(C)] >= 1 && CLASS_LIKELY_SPILLED_P (C))) + +static inline bool +small_register_class_p (reg_class_t rclass) +{ + return (reg_class_size [(int) rclass] == 1 + || (reg_class_size [(int) rclass] >= 1 + && targetm.class_likely_spilled_p (rclass))); +} /* All reloads of the current insn are recorded here. See reload.h for @@ -152,8 +158,6 @@ static int replace_reloads; struct replacement { rtx *where; /* Location to store in */ - rtx *subreg_loc; /* Location of SUBREG if WHERE is inside - a SUBREG; 0 otherwise. */ int what; /* which reload this is for */ enum machine_mode mode; /* mode it must have */ }; @@ -252,14 +256,13 @@ static int push_secondary_reload (int, rtx, int, int, enum reg_class, enum insn_code *, secondary_reload_info *); static enum reg_class find_valid_class (enum machine_mode, enum machine_mode, int, unsigned int); -static int reload_inner_reg_of_subreg (rtx, enum machine_mode, int); static void push_replacement (rtx *, int, enum machine_mode); static void dup_replacements (rtx *, rtx *); static void combine_reloads (void); static int find_reusable_reload (rtx *, rtx, enum reg_class, enum reload_type, int, int); static rtx find_dummy_reload (rtx, rtx, rtx *, rtx *, enum machine_mode, - enum machine_mode, enum reg_class, int, int); + enum machine_mode, reg_class_t, int, int); static int hard_reg_set_here_p (unsigned int, unsigned int, rtx); static struct decomposition decompose (rtx); static int immune_p (rtx, rtx, struct decomposition); @@ -274,14 +277,14 @@ static int find_reloads_address (enum machine_mode, rtx *, rtx, rtx *, static rtx subst_reg_equivs (rtx, rtx); static rtx subst_indexed_address (rtx); static void update_auto_inc_notes (rtx, int, int); -static int find_reloads_address_1 (enum machine_mode, rtx, int, +static int find_reloads_address_1 (enum machine_mode, addr_space_t, rtx, int, enum rtx_code, enum rtx_code, rtx *, int, enum reload_type,int, rtx); static void find_reloads_address_part (rtx, rtx *, enum reg_class, enum machine_mode, int, enum reload_type, int); static rtx find_reloads_subreg_address (rtx, int, int, enum reload_type, - int, rtx); + int, rtx, int *); static void copy_replacements_1 (rtx *, rtx *, int); static int find_inc_amount (rtx, rtx); static int refers_to_mem_for_reload_p (rtx); @@ -296,13 +299,13 @@ push_reg_equiv_alt_mem (int regno, rtx mem) { rtx it; - for (it = reg_equiv_alt_mem_list [regno]; it; it = XEXP (it, 1)) + for (it = reg_equiv_alt_mem_list (regno); it; it = XEXP (it, 1)) if (rtx_equal_p (XEXP (it, 0), mem)) return; - reg_equiv_alt_mem_list [regno] + reg_equiv_alt_mem_list (regno) = alloc_EXPR_LIST (REG_EQUIV, mem, - reg_equiv_alt_mem_list [regno]); + reg_equiv_alt_mem_list (regno)); } /* Determine if any secondary reloads are needed for loading (if IN_P is @@ -343,9 +346,7 @@ push_secondary_reload (int in_p, rtx x, int opnum, int optional, /* If X is a paradoxical SUBREG, use the inner value to determine both the mode and object being reloaded. */ - if (GET_CODE (x) == SUBREG - && (GET_MODE_SIZE (GET_MODE (x)) - > GET_MODE_SIZE (GET_MODE (SUBREG_REG (x))))) + if (paradoxical_subreg_p (x)) { x = SUBREG_REG (x); reload_mode = GET_MODE (x); @@ -358,12 +359,13 @@ push_secondary_reload (int in_p, rtx x, int opnum, int optional, might be sensitive to the form of the MEM. */ if (REG_P (x) && REGNO (x) >= FIRST_PSEUDO_REGISTER - && reg_equiv_mem[REGNO (x)] != 0) - x = reg_equiv_mem[REGNO (x)]; + && reg_equiv_mem (REGNO (x))) + x = reg_equiv_mem (REGNO (x)); sri.icode = CODE_FOR_nothing; sri.prev_sri = prev_sri; - rclass = targetm.secondary_reload (in_p, x, reload_class, reload_mode, &sri); + rclass = (enum reg_class) targetm.secondary_reload (in_p, x, reload_class, + reload_mode, &sri); icode = (enum insn_code) sri.icode; /* If we don't need any secondary registers, done. */ @@ -437,7 +439,7 @@ push_secondary_reload (int in_p, rtx x, int opnum, int optional, || (! in_p && rld[s_reload].secondary_out_reload == t_reload)) && ((in_p && rld[s_reload].secondary_in_icode == t_icode) || (! in_p && rld[s_reload].secondary_out_icode == t_icode)) - && (SMALL_REGISTER_CLASS_P (rclass) + && (small_register_class_p (rclass) || targetm.small_register_classes_for_mode_p (VOIDmode)) && MERGABLE_RELOADS (secondary_type, rld[s_reload].when_needed, opnum, rld[s_reload].opnum)) @@ -517,16 +519,17 @@ push_secondary_reload (int in_p, rtx x, int opnum, int optional, /* If a secondary reload is needed, return its class. If both an intermediate register and a scratch register is needed, we return the class of the intermediate register. */ -enum reg_class -secondary_reload_class (bool in_p, enum reg_class rclass, - enum machine_mode mode, rtx x) +reg_class_t +secondary_reload_class (bool in_p, reg_class_t rclass, enum machine_mode mode, + rtx x) { enum insn_code icode; secondary_reload_info sri; sri.icode = CODE_FOR_nothing; sri.prev_sri = NULL; - rclass = targetm.secondary_reload (in_p, x, rclass, mode, &sri); + rclass + = (enum reg_class) targetm.secondary_reload (in_p, x, rclass, mode, &sri); icode = (enum insn_code) sri.icode; /* If there are no secondary reloads at all, we return NO_REGS. @@ -688,7 +691,7 @@ find_valid_class (enum machine_mode outer ATTRIBUTE_UNUSED, if (bad || !good) continue; - cost = REGISTER_MOVE_COST (outer, (enum reg_class) 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)) @@ -696,7 +699,7 @@ find_valid_class (enum machine_mode outer ATTRIBUTE_UNUSED, { best_class = (enum reg_class) rclass; best_size = reg_class_size[rclass]; - best_cost = REGISTER_MOVE_COST (outer, (enum reg_class) rclass, + best_cost = register_move_cost (outer, (enum reg_class) rclass, dest_class); } } @@ -747,7 +750,7 @@ find_reusable_reload (rtx *p_in, rtx out, enum reg_class rclass, || (out != 0 && MATCHES (rld[i].out, out) && (in == 0 || rld[i].in == 0 || MATCHES (rld[i].in, in)))) && (rld[i].out == 0 || ! earlyclobber_operand_p (rld[i].out)) - && (SMALL_REGISTER_CLASS_P (rclass) + && (small_register_class_p (rclass) || targetm.small_register_classes_for_mode_p (VOIDmode)) && MERGABLE_RELOADS (type, rld[i].when_needed, opnum, rld[i].opnum)) return i; @@ -773,7 +776,7 @@ find_reusable_reload (rtx *p_in, rtx out, enum reg_class rclass, && GET_RTX_CLASS (GET_CODE (in)) == RTX_AUTOINC && MATCHES (XEXP (in, 0), rld[i].in))) && (rld[i].out == 0 || ! earlyclobber_operand_p (rld[i].out)) - && (SMALL_REGISTER_CLASS_P (rclass) + && (small_register_class_p (rclass) || targetm.small_register_classes_for_mode_p (VOIDmode)) && MERGABLE_RELOADS (type, rld[i].when_needed, opnum, rld[i].opnum)) @@ -787,39 +790,39 @@ find_reusable_reload (rtx *p_in, rtx out, enum reg_class rclass, return n_reloads; } -/* Return nonzero if X is a SUBREG which will require reloading of its - SUBREG_REG expression. */ +/* Return true if X is a SUBREG that will need reloading of its SUBREG_REG + expression. MODE is the mode that X will be used in. OUTPUT is true if + the function is invoked for the output part of an enclosing reload. */ -static int -reload_inner_reg_of_subreg (rtx x, enum machine_mode mode, int output) +static bool +reload_inner_reg_of_subreg (rtx x, enum machine_mode mode, bool output) { rtx inner; /* Only SUBREGs are problematical. */ if (GET_CODE (x) != SUBREG) - return 0; + return false; inner = SUBREG_REG (x); - /* If INNER is a constant or PLUS, then INNER must be reloaded. */ + /* If INNER is a constant or PLUS, then INNER will need reloading. */ if (CONSTANT_P (inner) || GET_CODE (inner) == PLUS) - return 1; + return true; - /* If INNER is not a hard register, then INNER will not need to - be reloaded. */ - if (!REG_P (inner) - || REGNO (inner) >= FIRST_PSEUDO_REGISTER) - return 0; + /* If INNER is not a hard register, then INNER will not need reloading. */ + if (!(REG_P (inner) && HARD_REGISTER_P (inner))) + return false; /* If INNER is not ok for MODE, then INNER will need reloading. */ - if (! HARD_REGNO_MODE_OK (subreg_regno (x), mode)) - return 1; - - /* If the outer part is a word or smaller, INNER larger than a - word and the number of regs for INNER is not the same as the - number of words in INNER, then INNER will need reloading. */ - return (GET_MODE_SIZE (mode) <= UNITS_PER_WORD - && output + if (!HARD_REGNO_MODE_OK (subreg_regno (x), mode)) + return true; + + /* If this is for an output, and the outer part is a word or smaller, + INNER is larger than a word and the number of registers in INNER is + not the same as the number of words in INNER, then INNER will need + reloading (with an in-out reload). */ + return (output + && GET_MODE_SIZE (mode) <= UNITS_PER_WORD && GET_MODE_SIZE (GET_MODE (inner)) > UNITS_PER_WORD && ((GET_MODE_SIZE (GET_MODE (inner)) / UNITS_PER_WORD) != (int) hard_regno_nregs[REGNO (inner)][GET_MODE (inner)])); @@ -917,7 +920,9 @@ push_reload (rtx in, rtx out, rtx *inloc, rtx *outloc, int i; int dont_share = 0; int dont_remove_subreg = 0; +#ifdef LIMIT_RELOAD_CLASS rtx *in_subreg_loc = 0, *out_subreg_loc = 0; +#endif int secondary_in_reload = -1, secondary_out_reload = -1; enum insn_code secondary_in_icode = CODE_FOR_nothing; enum insn_code secondary_out_icode = CODE_FOR_nothing; @@ -943,7 +948,7 @@ push_reload (rtx in, rtx out, rtx *inloc, rtx *outloc, gcc_assert (regno < FIRST_PSEUDO_REGISTER || reg_renumber[regno] >= 0 - || reg_equiv_constant[regno] == NULL_RTX); + || reg_equiv_constant (regno) == NULL_RTX); } /* reg_equiv_constant only contains constants which are obviously @@ -956,7 +961,7 @@ push_reload (rtx in, rtx out, rtx *inloc, rtx *outloc, gcc_assert (regno < FIRST_PSEUDO_REGISTER || reg_renumber[regno] >= 0 - || reg_equiv_constant[regno] == NULL_RTX); + || reg_equiv_constant (regno) == NULL_RTX); } /* If we have a read-write operand with an address side-effect, @@ -984,9 +989,9 @@ push_reload (rtx in, rtx out, rtx *inloc, rtx *outloc, For machines that extend byte loads, do this for any SUBREG of a pseudo where both M1 and M2 are a word or smaller, M1 is wider than M2, and M2 is an integral mode that gets extended when loaded. - Similar issue for (SUBREG:M1 (REG:M2 ...) ...) for a hard register R where - either M1 is not valid for R or M2 is wider than a word but we only - need one word to store an M2-sized quantity in R. + Similar issue for (SUBREG:M1 (REG:M2 ...) ...) for a hard register R + where either M1 is not valid for R or M2 is wider than a word but we + only need one register to store an M2-sized quantity in R. (However, if OUT is nonzero, we need to reload the reg *and* the subreg, so do nothing here, and let following statement handle it.) @@ -1011,26 +1016,27 @@ push_reload (rtx in, rtx out, rtx *inloc, rtx *outloc, #ifdef CANNOT_CHANGE_MODE_CLASS && !CANNOT_CHANGE_MODE_CLASS (GET_MODE (SUBREG_REG (in)), inmode, rclass) #endif + && contains_reg_of_mode[(int) rclass][(int) GET_MODE (SUBREG_REG (in))] && (CONSTANT_P (SUBREG_REG (in)) || GET_CODE (SUBREG_REG (in)) == PLUS || strict_low || (((REG_P (SUBREG_REG (in)) && REGNO (SUBREG_REG (in)) >= FIRST_PSEUDO_REGISTER) || MEM_P (SUBREG_REG (in))) - && ((GET_MODE_SIZE (inmode) - > GET_MODE_SIZE (GET_MODE (SUBREG_REG (in)))) + && ((GET_MODE_PRECISION (inmode) + > GET_MODE_PRECISION (GET_MODE (SUBREG_REG (in)))) #ifdef LOAD_EXTEND_OP || (GET_MODE_SIZE (inmode) <= UNITS_PER_WORD && (GET_MODE_SIZE (GET_MODE (SUBREG_REG (in))) <= UNITS_PER_WORD) - && (GET_MODE_SIZE (inmode) - > GET_MODE_SIZE (GET_MODE (SUBREG_REG (in)))) + && (GET_MODE_PRECISION (inmode) + > GET_MODE_PRECISION (GET_MODE (SUBREG_REG (in)))) && INTEGRAL_MODE_P (GET_MODE (SUBREG_REG (in))) && LOAD_EXTEND_OP (GET_MODE (SUBREG_REG (in))) != UNKNOWN) #endif #ifdef WORD_REGISTER_OPERATIONS - || ((GET_MODE_SIZE (inmode) - < GET_MODE_SIZE (GET_MODE (SUBREG_REG (in)))) + || ((GET_MODE_PRECISION (inmode) + < GET_MODE_PRECISION (GET_MODE (SUBREG_REG (in)))) && ((GET_MODE_SIZE (inmode) - 1) / UNITS_PER_WORD == ((GET_MODE_SIZE (GET_MODE (SUBREG_REG (in))) - 1) / UNITS_PER_WORD))) @@ -1061,7 +1067,9 @@ push_reload (rtx in, rtx out, rtx *inloc, rtx *outloc, #endif )) { +#ifdef LIMIT_RELOAD_CLASS in_subreg_loc = inloc; +#endif inloc = &SUBREG_REG (in); in = *inloc; #if ! defined (LOAD_EXTEND_OP) && ! defined (WORD_REGISTER_OPERATIONS) @@ -1073,17 +1081,16 @@ push_reload (rtx in, rtx out, rtx *inloc, rtx *outloc, inmode = GET_MODE (in); } - /* Similar issue for (SUBREG:M1 (REG:M2 ...) ...) for a hard register R where - either M1 is not valid for R or M2 is wider than a word but we only - need one word to store an M2-sized quantity in R. + /* Similar issue for (SUBREG:M1 (REG:M2 ...) ...) for a hard register R + where M1 is not valid for R if it was not handled by the code above. + + Similar issue for (SUBREG constant ...) if it was not handled by the + code above. This can happen if SUBREG_BYTE != 0. However, we must reload the inner reg *as well as* the subreg in that case. */ - /* Similar issue for (SUBREG constant ...) if it was not handled by the - code above. This can happen if SUBREG_BYTE != 0. */ - - if (in != 0 && reload_inner_reg_of_subreg (in, inmode, 0)) + if (in != 0 && reload_inner_reg_of_subreg (in, inmode, false)) { enum reg_class in_class = rclass; @@ -1108,25 +1115,26 @@ push_reload (rtx in, rtx out, rtx *inloc, rtx *outloc, /* Similarly for paradoxical and problematical SUBREGs on the output. Note that there is no reason we need worry about the previous value - of SUBREG_REG (out); even if wider than out, - storing in a subreg is entitled to clobber it all - (except in the case of STRICT_LOW_PART, - and in that case the constraint should label it input-output.) */ + of SUBREG_REG (out); even if wider than out, storing in a subreg is + entitled to clobber it all (except in the case of a word mode subreg + or of a STRICT_LOW_PART, in that latter case the constraint should + label it input-output.) */ if (out != 0 && GET_CODE (out) == SUBREG && (subreg_lowpart_p (out) || strict_low) #ifdef CANNOT_CHANGE_MODE_CLASS && !CANNOT_CHANGE_MODE_CLASS (GET_MODE (SUBREG_REG (out)), outmode, rclass) #endif + && contains_reg_of_mode[(int) rclass][(int) GET_MODE (SUBREG_REG (out))] && (CONSTANT_P (SUBREG_REG (out)) || strict_low || (((REG_P (SUBREG_REG (out)) && REGNO (SUBREG_REG (out)) >= FIRST_PSEUDO_REGISTER) || MEM_P (SUBREG_REG (out))) - && ((GET_MODE_SIZE (outmode) - > GET_MODE_SIZE (GET_MODE (SUBREG_REG (out)))) + && ((GET_MODE_PRECISION (outmode) + > GET_MODE_PRECISION (GET_MODE (SUBREG_REG (out)))) #ifdef WORD_REGISTER_OPERATIONS - || ((GET_MODE_SIZE (outmode) - < GET_MODE_SIZE (GET_MODE (SUBREG_REG (out)))) + || ((GET_MODE_PRECISION (outmode) + < GET_MODE_PRECISION (GET_MODE (SUBREG_REG (out)))) && ((GET_MODE_SIZE (outmode) - 1) / UNITS_PER_WORD == ((GET_MODE_SIZE (GET_MODE (SUBREG_REG (out))) - 1) / UNITS_PER_WORD))) @@ -1134,14 +1142,12 @@ push_reload (rtx in, rtx out, rtx *inloc, rtx *outloc, )) || (REG_P (SUBREG_REG (out)) && REGNO (SUBREG_REG (out)) < FIRST_PSEUDO_REGISTER - && ((GET_MODE_SIZE (outmode) <= UNITS_PER_WORD - && (GET_MODE_SIZE (GET_MODE (SUBREG_REG (out))) - > UNITS_PER_WORD) - && ((GET_MODE_SIZE (GET_MODE (SUBREG_REG (out))) - / UNITS_PER_WORD) - != (int) hard_regno_nregs[REGNO (SUBREG_REG (out))] - [GET_MODE (SUBREG_REG (out))])) - || ! HARD_REGNO_MODE_OK (subreg_regno (out), outmode))) + /* The case of a word mode subreg + is handled differently in the following statement. */ + && ! (GET_MODE_SIZE (outmode) <= UNITS_PER_WORD + && (GET_MODE_SIZE (GET_MODE (SUBREG_REG (out))) + > UNITS_PER_WORD)) + && ! HARD_REGNO_MODE_OK (subreg_regno (out), outmode)) || (secondary_reload_class (0, rclass, outmode, out) != NO_REGS && (secondary_reload_class (0, rclass, GET_MODE (SUBREG_REG (out)), SUBREG_REG (out)) @@ -1155,7 +1161,9 @@ push_reload (rtx in, rtx out, rtx *inloc, rtx *outloc, #endif )) { +#ifdef LIMIT_RELOAD_CLASS out_subreg_loc = outloc; +#endif outloc = &SUBREG_REG (out); out = *outloc; #if ! defined (LOAD_EXTEND_OP) && ! defined (WORD_REGISTER_OPERATIONS) @@ -1166,31 +1174,32 @@ push_reload (rtx in, rtx out, rtx *inloc, rtx *outloc, outmode = GET_MODE (out); } - /* Similar issue for (SUBREG:M1 (REG:M2 ...) ...) for a hard register R where - either M1 is not valid for R or M2 is wider than a word but we only - need one word to store an M2-sized quantity in R. + /* Similar issue for (SUBREG:M1 (REG:M2 ...) ...) for a hard register R + where either M1 is not valid for R or M2 is wider than a word but we + only need one register to store an M2-sized quantity in R. However, we must reload the inner reg *as well as* the subreg in - that case. In this case, the inner reg is an in-out reload. */ + that case and the inner reg is an in-out reload. */ - if (out != 0 && reload_inner_reg_of_subreg (out, outmode, 1)) + if (out != 0 && reload_inner_reg_of_subreg (out, outmode, true)) { + enum reg_class in_out_class + = find_valid_class (outmode, GET_MODE (SUBREG_REG (out)), + subreg_regno_offset (REGNO (SUBREG_REG (out)), + GET_MODE (SUBREG_REG (out)), + SUBREG_BYTE (out), + GET_MODE (out)), + REGNO (SUBREG_REG (out))); + /* This relies on the fact that emit_reload_insns outputs the instructions for output reloads of type RELOAD_OTHER in reverse order of the reloads. Thus if the outer reload is also of type RELOAD_OTHER, we are guaranteed that this inner reload will be output after the outer reload. */ - dont_remove_subreg = 1; push_reload (SUBREG_REG (out), SUBREG_REG (out), &SUBREG_REG (out), - &SUBREG_REG (out), - find_valid_class (outmode, GET_MODE (SUBREG_REG (out)), - subreg_regno_offset (REGNO (SUBREG_REG (out)), - GET_MODE (SUBREG_REG (out)), - SUBREG_BYTE (out), - GET_MODE (out)), - REGNO (SUBREG_REG (out))), - VOIDmode, VOIDmode, 0, 0, - opnum, RELOAD_OTHER); + &SUBREG_REG (out), in_out_class, VOIDmode, VOIDmode, + 0, 0, opnum, RELOAD_OTHER); + dont_remove_subreg = 1; } /* If IN appears in OUT, we can't share any input-only reload for IN. */ @@ -1217,21 +1226,20 @@ push_reload (rtx in, rtx out, rtx *inloc, rtx *outloc, /* Narrow down the class of register wanted if that is desirable on this machine for efficiency. */ { - enum reg_class preferred_class = rclass; + reg_class_t preferred_class = rclass; if (in != 0) - preferred_class = PREFERRED_RELOAD_CLASS (in, rclass); + preferred_class = targetm.preferred_reload_class (in, rclass); - /* Output reloads may need analogous treatment, different in detail. */ -#ifdef PREFERRED_OUTPUT_RELOAD_CLASS + /* Output reloads may need analogous treatment, different in detail. */ if (out != 0) - preferred_class = PREFERRED_OUTPUT_RELOAD_CLASS (out, preferred_class); -#endif + preferred_class + = targetm.preferred_output_reload_class (out, preferred_class); /* Discard what the target said if we cannot do it. */ if (preferred_class != NO_REGS || (optional && type == RELOAD_FOR_OUTPUT)) - rclass = preferred_class; + rclass = (enum reg_class) preferred_class; } /* Make sure we use a class that can handle the actual pseudo @@ -1487,7 +1495,6 @@ push_reload (rtx in, rtx out, rtx *inloc, rtx *outloc, { struct replacement *r = &replacements[n_replacements++]; r->what = i; - r->subreg_loc = in_subreg_loc; r->where = inloc; r->mode = inmode; } @@ -1496,7 +1503,6 @@ push_reload (rtx in, rtx out, rtx *inloc, rtx *outloc, struct replacement *r = &replacements[n_replacements++]; r->what = i; r->where = outloc; - r->subreg_loc = out_subreg_loc; r->mode = outmode; } } @@ -1625,7 +1631,6 @@ push_replacement (rtx *loc, int reloadnum, enum machine_mode mode) struct replacement *r = &replacements[n_replacements++]; r->what = reloadnum; r->where = loc; - r->subreg_loc = 0; r->mode = mode; } } @@ -1759,9 +1764,9 @@ combine_reloads (void) && rld[i].when_needed != RELOAD_FOR_OUTPUT_ADDRESS && rld[i].when_needed != RELOAD_FOR_OUTADDR_ADDRESS && rld[i].when_needed != RELOAD_OTHER - && (CLASS_MAX_NREGS (rld[i].rclass, rld[i].inmode) - == CLASS_MAX_NREGS (rld[output_reload].rclass, - rld[output_reload].outmode)) + && (ira_reg_class_max_nregs [(int)rld[i].rclass][(int) rld[i].inmode] + == ira_reg_class_max_nregs [(int) rld[output_reload].rclass] + [(int) rld[output_reload].outmode]) && rld[i].inc == 0 && rld[i].reg_rtx == 0 #ifdef SECONDARY_MEMORY_NEEDED @@ -1913,7 +1918,7 @@ combine_reloads (void) static rtx find_dummy_reload (rtx real_in, rtx real_out, rtx *inloc, rtx *outloc, enum machine_mode inmode, enum machine_mode outmode, - enum reg_class rclass, int for_real, int earlyclobber) + reg_class_t rclass, int for_real, int earlyclobber) { rtx in = real_in; rtx out = real_out; @@ -1956,9 +1961,9 @@ find_dummy_reload (rtx real_in, rtx real_out, rtx *inloc, rtx *outloc, /* Narrow down the reg class, the same way push_reload will; otherwise we might find a dummy now, but push_reload won't. */ { - enum reg_class preferred_class = PREFERRED_RELOAD_CLASS (in, rclass); + reg_class_t preferred_class = targetm.preferred_reload_class (in, rclass); if (preferred_class != NO_REGS) - rclass = preferred_class; + rclass = (enum reg_class) preferred_class; } /* See if OUT will do. */ @@ -2210,15 +2215,15 @@ operands_match_p (rtx x, rtx y) else j = REGNO (y); - /* On a WORDS_BIG_ENDIAN machine, point to the last register of a + /* On a REG_WORDS_BIG_ENDIAN machine, point to the last register of a multiple hard register group of scalar integer registers, so that for example (reg:DI 0) and (reg:SI 1) will be considered the same register. */ - if (WORDS_BIG_ENDIAN && GET_MODE_SIZE (GET_MODE (x)) > UNITS_PER_WORD + if (REG_WORDS_BIG_ENDIAN && GET_MODE_SIZE (GET_MODE (x)) > UNITS_PER_WORD && SCALAR_INT_MODE_P (GET_MODE (x)) && i < FIRST_PSEUDO_REGISTER) i += hard_regno_nregs[i][GET_MODE (x)] - 1; - if (WORDS_BIG_ENDIAN && GET_MODE_SIZE (GET_MODE (y)) > UNITS_PER_WORD + if (REG_WORDS_BIG_ENDIAN && GET_MODE_SIZE (GET_MODE (y)) > UNITS_PER_WORD && SCALAR_INT_MODE_P (GET_MODE (y)) && j < FIRST_PSEUDO_REGISTER) j += hard_regno_nregs[j][GET_MODE (y)] - 1; @@ -2581,14 +2586,14 @@ find_reloads (rtx insn, int replace, int ind_levels, int live_known, 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; - enum reg_class this_alternative[MAX_RECOG_OPERANDS]; + reg_class_t 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]; char this_alternative_earlyclobber[MAX_RECOG_OPERANDS]; int this_alternative_matches[MAX_RECOG_OPERANDS]; int swapped; - int goal_alternative[MAX_RECOG_OPERANDS]; + reg_class_t goal_alternative[MAX_RECOG_OPERANDS]; int this_alternative_number; int goal_alternative_number = 0; int operand_reloadnum[MAX_RECOG_OPERANDS]; @@ -2600,7 +2605,6 @@ find_reloads (rtx insn, int replace, int ind_levels, int live_known, 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]; @@ -2651,7 +2655,7 @@ find_reloads (rtx insn, int replace, int ind_levels, int live_known, && REGNO (SET_DEST (body)) < FIRST_PSEUDO_REGISTER && REG_P (SET_SRC (body)) && REGNO (SET_SRC (body)) < FIRST_PSEUDO_REGISTER - && REGISTER_MOVE_COST (GET_MODE (SET_SRC (body)), + && register_move_cost (GET_MODE (SET_SRC (body)), REGNO_REG_CLASS (REGNO (SET_SRC (body))), REGNO_REG_CLASS (REGNO (SET_DEST (body)))) == 2) return 0; @@ -2818,6 +2822,13 @@ find_reloads (rtx insn, int replace, int ind_levels, int live_known, /* Address operands are reloaded in their existing mode, no matter what is specified in the machine description. */ operand_mode[i] = GET_MODE (recog_data.operand[i]); + + /* If the address is a single CONST_INT pick address mode + instead otherwise we will later not know in which mode + the reload should be performed. */ + if (operand_mode[i] == VOIDmode) + operand_mode[i] = Pmode; + } else if (code == MEM) { @@ -2851,10 +2862,10 @@ find_reloads (rtx insn, int replace, int ind_levels, int live_known, && REG_P (reg) && (GET_MODE_SIZE (GET_MODE (reg)) >= GET_MODE_SIZE (GET_MODE (op))) - && reg_equiv_constant[REGNO (reg)] == 0) + && reg_equiv_constant (REGNO (reg)) == 0) set_unique_reg_note (emit_insn_before (gen_rtx_USE (VOIDmode, reg), insn), - REG_EQUAL, reg_equiv_memory_loc[REGNO (reg)]); + REG_EQUAL, reg_equiv_memory_loc (REGNO (reg))); substed_operand[i] = recog_data.operand[i] = op; } @@ -2875,7 +2886,7 @@ find_reloads (rtx insn, int replace, int ind_levels, int live_known, that we don't try to replace it in the insn in which it is being set. */ int regno = REGNO (recog_data.operand[i]); - if (reg_equiv_constant[regno] != 0 + if (reg_equiv_constant (regno) != 0 && (set == 0 || &SET_DEST (set) != recog_data.operand_loc[i])) { /* Record the existing mode so that the check if constants are @@ -2885,10 +2896,10 @@ find_reloads (rtx insn, int replace, int ind_levels, int live_known, operand_mode[i] = GET_MODE (recog_data.operand[i]); substed_operand[i] = recog_data.operand[i] - = reg_equiv_constant[regno]; + = reg_equiv_constant (regno); } - if (reg_equiv_memory_loc[regno] != 0 - && (reg_equiv_address[regno] != 0 || num_not_at_initial_offset)) + if (reg_equiv_memory_loc (regno) != 0 + && (reg_equiv_address (regno) != 0 || num_not_at_initial_offset)) /* We need not give a valid is_set_dest argument since the case of a constant equivalence was checked above. */ substed_operand[i] = recog_data.operand[i] @@ -2926,7 +2937,6 @@ find_reloads (rtx insn, int replace, int ind_levels, int live_known, 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; @@ -3229,8 +3239,9 @@ find_reloads (rtx insn, int replace, int ind_levels, int live_known, case 'p': /* All necessary reloads for an address_operand were handled in find_reloads_address. */ - this_alternative[i] = base_reg_class (VOIDmode, ADDRESS, - SCRATCH); + this_alternative[i] + = base_reg_class (VOIDmode, ADDR_SPACE_GENERIC, + ADDRESS, SCRATCH); win = 1; badop = 0; break; @@ -3243,7 +3254,7 @@ find_reloads (rtx insn, int replace, int ind_levels, int live_known, && REGNO (operand) >= FIRST_PSEUDO_REGISTER && reg_renumber[REGNO (operand)] < 0)) win = 1; - if (CONST_POOL_OK_P (operand)) + if (CONST_POOL_OK_P (operand_mode[i], operand)) badop = 0; constmemok = 1; break; @@ -3277,7 +3288,7 @@ find_reloads (rtx insn, int replace, int ind_levels, int live_known, to override the handling of reg_equiv_address. */ && !(REG_P (XEXP (operand, 0)) && (ind_levels == 0 - || reg_equiv_address[REGNO (XEXP (operand, 0))] != 0))) + || reg_equiv_address (REGNO (XEXP (operand, 0))) != 0))) win = 1; break; @@ -3301,11 +3312,11 @@ find_reloads (rtx insn, int replace, int ind_levels, int live_known, loading it into a register; hence it will be offsettable, but we cannot say that reg_equiv_mem is offsettable without checking. */ - && ((reg_equiv_mem[REGNO (operand)] != 0 - && offsettable_memref_p (reg_equiv_mem[REGNO (operand)])) - || (reg_equiv_address[REGNO (operand)] != 0)))) + && ((reg_equiv_mem (REGNO (operand)) != 0 + && offsettable_memref_p (reg_equiv_mem (REGNO (operand)))) + || (reg_equiv_address (REGNO (operand)) != 0)))) win = 1; - if (CONST_POOL_OK_P (operand) + if (CONST_POOL_OK_P (operand_mode[i], operand) || MEM_P (operand)) badop = 0; constmemok = 1; @@ -3413,15 +3424,15 @@ find_reloads (rtx insn, int replace, int ind_levels, int live_known, else if (REG_P (operand) && REGNO (operand) >= FIRST_PSEUDO_REGISTER && reg_renumber[REGNO (operand)] < 0 - && ((reg_equiv_mem[REGNO (operand)] != 0 - && EXTRA_CONSTRAINT_STR (reg_equiv_mem[REGNO (operand)], c, p)) - || (reg_equiv_address[REGNO (operand)] != 0))) + && ((reg_equiv_mem (REGNO (operand)) != 0 + && EXTRA_CONSTRAINT_STR (reg_equiv_mem (REGNO (operand)), c, p)) + || (reg_equiv_address (REGNO (operand)) != 0))) win = 1; /* If we didn't already win, we can reload constants via force_const_mem, and other MEMs by reloading the address like for 'o'. */ - if (CONST_POOL_OK_P (operand) + if (CONST_POOL_OK_P (operand_mode[i], operand) || MEM_P (operand)) badop = 0; constmemok = 1; @@ -3435,9 +3446,9 @@ find_reloads (rtx insn, int replace, int ind_levels, int live_known, /* If we didn't already win, we can reload the address into a base register. */ - this_alternative[i] = base_reg_class (VOIDmode, - ADDRESS, - SCRATCH); + this_alternative[i] + = base_reg_class (VOIDmode, ADDR_SPACE_GENERIC, + ADDRESS, SCRATCH); badop = 0; break; } @@ -3468,7 +3479,8 @@ find_reloads (rtx insn, int replace, int ind_levels, int live_known, /* 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] != NO_REGS) + if (winreg && this_alternative[i] != NO_REGS + && (win || !class_only_fixed_regs[this_alternative[i]])) badop = 0; /* Record which operands fit this alternative. */ @@ -3499,11 +3511,11 @@ find_reloads (rtx insn, int replace, int ind_levels, int live_known, an early reload pass. Note that the test here is precisely the same as in the code below that calls force_const_mem. */ - if (CONST_POOL_OK_P (operand) - && ((PREFERRED_RELOAD_CLASS (operand, this_alternative[i]) + if (CONST_POOL_OK_P (operand_mode[i], operand) + && ((targetm.preferred_reload_class (operand, + this_alternative[i]) == NO_REGS) - || no_input_reloads) - && operand_mode[i] != VOIDmode) + || no_input_reloads)) { const_to_mem = 1; if (this_alternative[i] != NO_REGS) @@ -3528,17 +3540,15 @@ find_reloads (rtx insn, int replace, int ind_levels, int live_known, if (! CONSTANT_P (operand) && this_alternative[i] != NO_REGS) { - if (PREFERRED_RELOAD_CLASS (operand, this_alternative[i]) + if (targetm.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, - this_alternative[i]) + && (targetm.preferred_output_reload_class (operand, + this_alternative[i]) == NO_REGS)) reject = 600; -#endif } /* We prefer to reload pseudos over reloading other things, @@ -3587,7 +3597,7 @@ find_reloads (rtx insn, int replace, int ind_levels, int live_known, && 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])) + && ! small_register_class_p (preferred_class[i])) { if (! reg_class_subset_p (this_alternative[i], preferred_class[i])) @@ -3645,7 +3655,7 @@ find_reloads (rtx insn, int replace, int ind_levels, int live_known, { /* If the output is in a non-empty few-regs class, it's costly to reload it, so reload the input instead. */ - if (SMALL_REGISTER_CLASS_P (this_alternative[i]) + if (small_register_class_p (this_alternative[i]) && (REG_P (recog_data.operand[j]) || GET_CODE (recog_data.operand[j]) == SUBREG)) { @@ -3712,27 +3722,7 @@ find_reloads (rtx insn, int replace, int ind_levels, int live_known, record it as the chosen goal for reloading. */ if (! bad) { - bool change_p = false; - int small_class_operands_num = 0; - - if (best >= losers) - { - 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; - } - if (change_p) + if (best > losers) { for (i = 0; i < noperands; i++) { @@ -3748,7 +3738,6 @@ find_reloads (rtx insn, int replace, int ind_levels, int live_known, } 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; } @@ -3929,12 +3918,10 @@ find_reloads (rtx insn, int replace, int ind_levels, int live_known, op = XEXP (op, 1); } - if (CONST_POOL_OK_P (op) - && ((PREFERRED_RELOAD_CLASS (op, - (enum reg_class) goal_alternative[i]) + if (CONST_POOL_OK_P (mode, op) + && ((targetm.preferred_reload_class (op, goal_alternative[i]) == NO_REGS) - || no_input_reloads) - && mode != VOIDmode) + || no_input_reloads)) { int this_address_reloaded; rtx tem = force_const_mem (mode, op); @@ -3991,18 +3978,16 @@ find_reloads (rtx insn, int replace, int ind_levels, int live_known, /* If the address to be reloaded is a VOIDmode constant, use the default address mode as mode of the reload register, as would have been done by find_reloads_address. */ + addr_space_t as = MEM_ADDR_SPACE (recog_data.operand[i]); enum machine_mode address_mode; address_mode = GET_MODE (XEXP (recog_data.operand[i], 0)); if (address_mode == VOIDmode) - { - addr_space_t as = MEM_ADDR_SPACE (recog_data.operand[i]); - address_mode = targetm.addr_space.address_mode (as); - } + address_mode = targetm.addr_space.address_mode (as); operand_reloadnum[i] = push_reload (XEXP (recog_data.operand[i], 0), NULL_RTX, &XEXP (recog_data.operand[i], 0), (rtx*) 0, - base_reg_class (VOIDmode, MEM, SCRATCH), + base_reg_class (VOIDmode, as, MEM, SCRATCH), address_mode, VOIDmode, 0, 0, i, RELOAD_FOR_INPUT); rld[operand_reloadnum[i]].inc @@ -4109,7 +4094,7 @@ find_reloads (rtx insn, int replace, int ind_levels, int live_known, /* If this is only for an output, the optional reload would not actually cause us to use a register now, just note that something is stored here. */ - && ((enum reg_class) goal_alternative[i] != NO_REGS + && (goal_alternative[i] != NO_REGS || modified[i] == RELOAD_WRITE) && ! no_input_reloads /* An optional output reload might allow to delete INSN later. @@ -4183,8 +4168,7 @@ find_reloads (rtx insn, int replace, int ind_levels, int live_known, if ((MEM_P (operand) || (REG_P (operand) && REGNO (operand) >= FIRST_PSEUDO_REGISTER)) - && ((enum reg_class) goal_alternative[goal_alternative_matches[i]] - != NO_REGS)) + && (goal_alternative[goal_alternative_matches[i]] != NO_REGS)) operand_reloadnum[i] = operand_reloadnum[goal_alternative_matches[i]] = push_reload (recog_data.operand[goal_alternative_matches[i]], recog_data.operand[i], @@ -4224,7 +4208,12 @@ find_reloads (rtx insn, int replace, int ind_levels, int live_known, && (!JUMP_P (insn) || !label_is_jump_target_p (XEXP (substitution, 0), insn))) - add_reg_note (insn, REG_LABEL_OPERAND, XEXP (substitution, 0)); + { + add_reg_note (insn, REG_LABEL_OPERAND, XEXP (substitution, 0)); + if (LABEL_P (XEXP (substitution, 0))) + ++LABEL_NUSES (XEXP (substitution, 0)); + } + } else retval |= (substed_operand[i] != *recog_data.operand_loc[i]); @@ -4561,7 +4550,7 @@ find_reloads (rtx insn, int replace, int ind_levels, int live_known, > GET_MODE_SIZE (rld[i].inmode))) ? rld[i].outmode : rld[i].inmode; - rld[i].nregs = CLASS_MAX_NREGS (rld[i].rclass, rld[i].mode); + rld[i].nregs = ira_reg_class_max_nregs [rld[i].rclass][rld[i].mode]; } /* Special case a simple move with an input reload and a @@ -4610,7 +4599,8 @@ alternative_allows_const_pool_ref (rtx mem ATTRIBUTE_UNUSED, /* Skip alternatives before the one requested. */ while (altnum > 0) { - while (*constraint++ != ','); + while (*constraint++ != ',') + ; altnum--; } /* Scan the requested alternative for TARGET_MEM_CONSTRAINT or 'o'. @@ -4672,20 +4662,20 @@ find_reloads_toplev (rtx x, int opnum, enum reload_type type, { /* This code is duplicated for speed in find_reloads. */ int regno = REGNO (x); - if (reg_equiv_constant[regno] != 0 && !is_set_dest) - x = reg_equiv_constant[regno]; + if (reg_equiv_constant (regno) != 0 && !is_set_dest) + x = reg_equiv_constant (regno); #if 0 /* This creates (subreg (mem...)) which would cause an unnecessary reload of the mem. */ - else if (reg_equiv_mem[regno] != 0) - x = reg_equiv_mem[regno]; + else if (reg_equiv_mem (regno) != 0) + x = reg_equiv_mem (regno); #endif - else if (reg_equiv_memory_loc[regno] - && (reg_equiv_address[regno] != 0 || num_not_at_initial_offset)) + else if (reg_equiv_memory_loc (regno) + && (reg_equiv_address (regno) != 0 || num_not_at_initial_offset)) { rtx mem = make_memloc (x, regno); - if (reg_equiv_address[regno] - || ! rtx_equal_p (mem, reg_equiv_mem[regno])) + if (reg_equiv_address (regno) + || ! rtx_equal_p (mem, reg_equiv_mem (regno))) { /* If this is not a toplevel operand, find_reloads doesn't see this substitution. We have to emit a USE of the pseudo so @@ -4735,13 +4725,14 @@ find_reloads_toplev (rtx x, int opnum, enum reload_type type, if (regno >= FIRST_PSEUDO_REGISTER && reg_renumber[regno] < 0 - && reg_equiv_constant[regno] != 0) + && reg_equiv_constant (regno) != 0) { tem = - simplify_gen_subreg (GET_MODE (x), reg_equiv_constant[regno], + simplify_gen_subreg (GET_MODE (x), reg_equiv_constant (regno), GET_MODE (SUBREG_REG (x)), SUBREG_BYTE (x)); gcc_assert (tem); - if (CONSTANT_P (tem) && !LEGITIMATE_CONSTANT_P (tem)) + if (CONSTANT_P (tem) + && !targetm.legitimate_constant_p (GET_MODE (x), tem)) { tem = force_const_mem (GET_MODE (x), tem); i = find_reloads_address (GET_MODE (tem), &tem, XEXP (tem, 0), @@ -4768,18 +4759,17 @@ find_reloads_toplev (rtx x, int opnum, enum reload_type type, if (regno >= FIRST_PSEUDO_REGISTER #ifdef LOAD_EXTEND_OP - && (GET_MODE_SIZE (GET_MODE (x)) - <= GET_MODE_SIZE (GET_MODE (SUBREG_REG (x)))) + && !paradoxical_subreg_p (x) #endif - && (reg_equiv_address[regno] != 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])) - || ! offsettable_memref_p (reg_equiv_mem[regno]) - || num_not_at_initial_offset)))) + && (reg_equiv_address (regno) != 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))) + || ! offsettable_memref_p (reg_equiv_mem (regno)) + || num_not_at_initial_offset)))) x = find_reloads_subreg_address (x, 1, opnum, type, ind_levels, - insn); + insn, address_reloaded); } for (copied = 0, i = GET_RTX_LENGTH (code) - 1; i >= 0; i--) @@ -4814,7 +4804,7 @@ make_memloc (rtx ad, int regno) /* We must rerun eliminate_regs, in case the elimination offsets have changed. */ rtx tem - = XEXP (eliminate_regs (reg_equiv_memory_loc[regno], VOIDmode, NULL_RTX), + = XEXP (eliminate_regs (reg_equiv_memory_loc (regno), VOIDmode, NULL_RTX), 0); /* If TEM might contain a pseudo, we must copy it to avoid @@ -4822,12 +4812,12 @@ make_memloc (rtx ad, int regno) if (rtx_varies_p (tem, 0)) tem = copy_rtx (tem); - tem = replace_equiv_address_nv (reg_equiv_memory_loc[regno], tem); + tem = replace_equiv_address_nv (reg_equiv_memory_loc (regno), tem); tem = adjust_address_nv (tem, GET_MODE (ad), 0); /* Copy the result if it's still the same as the equivalence, to avoid modifying it when we do the substitution for the reload. */ - if (tem == reg_equiv_memory_loc[regno]) + if (tem == reg_equiv_memory_loc (regno)) tem = copy_rtx (tem); return tem; } @@ -4896,18 +4886,18 @@ find_reloads_address (enum machine_mode mode, rtx *memrefloc, rtx ad, { regno = REGNO (ad); - if (reg_equiv_constant[regno] != 0) + if (reg_equiv_constant (regno) != 0) { - find_reloads_address_part (reg_equiv_constant[regno], loc, - base_reg_class (mode, MEM, SCRATCH), + find_reloads_address_part (reg_equiv_constant (regno), loc, + base_reg_class (mode, as, MEM, SCRATCH), GET_MODE (ad), opnum, type, ind_levels); return 1; } - tem = reg_equiv_memory_loc[regno]; + tem = reg_equiv_memory_loc (regno); if (tem != 0) { - if (reg_equiv_address[regno] != 0 || num_not_at_initial_offset) + if (reg_equiv_address (regno) != 0 || num_not_at_initial_offset) { tem = make_memloc (ad, regno); if (! strict_memory_address_addr_space_p (GET_MODE (tem), @@ -4939,7 +4929,7 @@ find_reloads_address (enum machine_mode mode, rtx *memrefloc, rtx ad, in the final reload pass. */ if (replace_reloads && num_not_at_initial_offset - && ! rtx_equal_p (tem, reg_equiv_mem[regno])) + && ! rtx_equal_p (tem, reg_equiv_mem (regno))) { *loc = tem; /* We mark the USE with QImode so that we @@ -4962,12 +4952,13 @@ find_reloads_address (enum machine_mode mode, rtx *memrefloc, rtx ad, subject of a CLOBBER in this insn. */ else if (regno < FIRST_PSEUDO_REGISTER - && regno_ok_for_base_p (regno, mode, MEM, SCRATCH) + && regno_ok_for_base_p (regno, mode, as, MEM, SCRATCH) && ! regno_clobbered_p (regno, this_insn, mode, 0)) return 0; /* If we do not have one of the cases above, we must do the reload. */ - push_reload (ad, NULL_RTX, loc, (rtx*) 0, base_reg_class (mode, MEM, SCRATCH), + push_reload (ad, NULL_RTX, loc, (rtx*) 0, + base_reg_class (mode, as, MEM, SCRATCH), GET_MODE (ad), VOIDmode, 0, 0, opnum, type); return 1; } @@ -4985,7 +4976,7 @@ find_reloads_address (enum machine_mode mode, rtx *memrefloc, rtx ad, if (GET_CODE (ad) == PLUS && CONST_INT_P (XEXP (ad, 1)) && REG_P (XEXP (ad, 0)) - && reg_equiv_constant[REGNO (XEXP (ad, 0))] == 0) + && reg_equiv_constant (REGNO (XEXP (ad, 0))) == 0) return 0; subst_reg_equivs_changed = 0; @@ -5068,7 +5059,7 @@ find_reloads_address (enum machine_mode mode, rtx *memrefloc, rtx ad, /* Must use TEM here, not AD, since it is the one that will have any subexpressions reloaded, if needed. */ push_reload (tem, NULL_RTX, loc, (rtx*) 0, - base_reg_class (mode, MEM, SCRATCH), GET_MODE (tem), + base_reg_class (mode, as, MEM, SCRATCH), GET_MODE (tem), VOIDmode, 0, 0, opnum, type); return ! removed_and; @@ -5086,8 +5077,13 @@ find_reloads_address (enum machine_mode mode, rtx *memrefloc, rtx ad, && REG_P (XEXP (ad, 0)) && REGNO (XEXP (ad, 0)) < FIRST_PSEUDO_REGISTER && CONST_INT_P (XEXP (ad, 1)) - && regno_ok_for_base_p (REGNO (XEXP (ad, 0)), mode, PLUS, - CONST_INT)) + && (regno_ok_for_base_p (REGNO (XEXP (ad, 0)), mode, as, PLUS, + CONST_INT) + /* Similarly, if we were to reload the base register and the + mem+offset address is still invalid, then we want to reload + the whole address, not just the base register. */ + || ! maybe_memory_address_addr_space_p + (mode, ad, as, &(XEXP (ad, 0))))) { /* Unshare the MEM rtx so we can safely alter it. */ @@ -5099,7 +5095,9 @@ find_reloads_address (enum machine_mode mode, rtx *memrefloc, rtx ad, loc = &XEXP (*loc, 0); } - if (double_reg_address_ok) + if (double_reg_address_ok + && regno_ok_for_base_p (REGNO (XEXP (ad, 0)), mode, as, + PLUS, CONST_INT)) { /* Unshare the sum as well. */ *loc = ad = copy_rtx (ad); @@ -5117,7 +5115,7 @@ find_reloads_address (enum machine_mode mode, rtx *memrefloc, rtx ad, reload the sum into a base reg. That will at least work. */ find_reloads_address_part (ad, loc, - base_reg_class (mode, MEM, SCRATCH), + base_reg_class (mode, as, MEM, SCRATCH), GET_MODE (ad), opnum, type, ind_levels); } return ! removed_and; @@ -5169,10 +5167,10 @@ find_reloads_address (enum machine_mode mode, rtx *memrefloc, rtx ad, addend = XEXP (XEXP (ad, 0), 1 - op_index); - if ((regno_ok_for_base_p (REGNO (operand), mode, inner_code, + if ((regno_ok_for_base_p (REGNO (operand), mode, as, inner_code, GET_CODE (addend)) || operand == frame_pointer_rtx -#if FRAME_POINTER_REGNUM != HARD_FRAME_POINTER_REGNUM +#if !HARD_FRAME_POINTER_IS_FRAME_POINTER || operand == hard_frame_pointer_rtx #endif #if FRAME_POINTER_REGNUM != ARG_POINTER_REGNUM @@ -5198,11 +5196,11 @@ find_reloads_address (enum machine_mode mode, rtx *memrefloc, rtx ad, op_index == 0 ? addend : offset_reg); *loc = ad; - cls = base_reg_class (mode, MEM, GET_CODE (addend)); + cls = base_reg_class (mode, as, MEM, GET_CODE (addend)); 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, + find_reloads_address_1 (mode, as, XEXP (ad, 1 - op_index), 1, GET_CODE (ad), GET_CODE (XEXP (ad, op_index)), &XEXP (ad, 1 - op_index), opnum, @@ -5255,13 +5253,14 @@ find_reloads_address (enum machine_mode mode, rtx *memrefloc, rtx ad, loc = &XEXP (*loc, 0); } - find_reloads_address_part (ad, loc, base_reg_class (mode, MEM, SCRATCH), + find_reloads_address_part (ad, loc, + base_reg_class (mode, as, MEM, SCRATCH), address_mode, opnum, type, ind_levels); return ! removed_and; } - return find_reloads_address_1 (mode, ad, 0, MEM, SCRATCH, loc, opnum, type, - ind_levels, insn); + return find_reloads_address_1 (mode, as, ad, 0, MEM, SCRATCH, loc, + opnum, type, ind_levels, insn); } /* Find all pseudo regs appearing in AD @@ -5295,15 +5294,15 @@ subst_reg_equivs (rtx ad, rtx insn) { int regno = REGNO (ad); - if (reg_equiv_constant[regno] != 0) + if (reg_equiv_constant (regno) != 0) { subst_reg_equivs_changed = 1; - return reg_equiv_constant[regno]; + return reg_equiv_constant (regno); } - if (reg_equiv_memory_loc[regno] && num_not_at_initial_offset) + if (reg_equiv_memory_loc (regno) && num_not_at_initial_offset) { rtx mem = make_memloc (ad, regno); - if (! rtx_equal_p (mem, reg_equiv_mem[regno])) + if (! rtx_equal_p (mem, reg_equiv_mem (regno))) { subst_reg_equivs_changed = 1; /* We mark the USE with QImode so that we recognize it @@ -5406,13 +5405,13 @@ subst_indexed_address (rtx addr) if (REG_P (op0) && (regno = REGNO (op0)) >= FIRST_PSEUDO_REGISTER && reg_renumber[regno] < 0 - && reg_equiv_constant[regno] != 0) - op0 = reg_equiv_constant[regno]; + && reg_equiv_constant (regno) != 0) + op0 = reg_equiv_constant (regno); else if (REG_P (op1) && (regno = REGNO (op1)) >= FIRST_PSEUDO_REGISTER && reg_renumber[regno] < 0 - && reg_equiv_constant[regno] != 0) - op1 = reg_equiv_constant[regno]; + && reg_equiv_constant (regno) != 0) + op1 = reg_equiv_constant (regno); else if (GET_CODE (op0) == PLUS && (tem = subst_indexed_address (op0)) != op0) op0 = tem; @@ -5494,14 +5493,15 @@ update_auto_inc_notes (rtx insn ATTRIBUTE_UNUSED, int regno ATTRIBUTE_UNUSED, handles those cases gracefully. */ static int -find_reloads_address_1 (enum machine_mode mode, rtx x, int context, +find_reloads_address_1 (enum machine_mode mode, addr_space_t as, + rtx x, int context, enum rtx_code outer_code, enum rtx_code index_code, rtx *loc, int opnum, enum reload_type type, int ind_levels, rtx insn) { -#define REG_OK_FOR_CONTEXT(CONTEXT, REGNO, MODE, OUTER, INDEX) \ +#define REG_OK_FOR_CONTEXT(CONTEXT, REGNO, MODE, AS, OUTER, INDEX) \ ((CONTEXT) == 0 \ - ? regno_ok_for_base_p (REGNO, MODE, OUTER, INDEX) \ + ? regno_ok_for_base_p (REGNO, MODE, AS, OUTER, INDEX) \ : REGNO_OK_FOR_INDEX_P (REGNO)) enum reg_class context_reg_class; @@ -5510,7 +5510,7 @@ find_reloads_address_1 (enum machine_mode mode, rtx x, int context, if (context == 1) context_reg_class = INDEX_REG_CLASS; else - context_reg_class = base_reg_class (mode, outer_code, index_code); + context_reg_class = base_reg_class (mode, as, outer_code, index_code); switch (code) { @@ -5567,10 +5567,10 @@ find_reloads_address_1 (enum machine_mode mode, rtx x, int context, if (code0 == MULT || code0 == SIGN_EXTEND || code0 == TRUNCATE || code0 == ZERO_EXTEND || code1 == MEM) { - find_reloads_address_1 (mode, orig_op0, 1, PLUS, SCRATCH, + find_reloads_address_1 (mode, as, orig_op0, 1, PLUS, SCRATCH, &XEXP (x, 0), opnum, type, ind_levels, insn); - find_reloads_address_1 (mode, orig_op1, 0, PLUS, code0, + find_reloads_address_1 (mode, as, orig_op1, 0, PLUS, code0, &XEXP (x, 1), opnum, type, ind_levels, insn); } @@ -5578,56 +5578,56 @@ find_reloads_address_1 (enum machine_mode mode, rtx x, int context, else if (code1 == MULT || code1 == SIGN_EXTEND || code1 == TRUNCATE || code1 == ZERO_EXTEND || code0 == MEM) { - find_reloads_address_1 (mode, orig_op0, 0, PLUS, code1, + find_reloads_address_1 (mode, as, orig_op0, 0, PLUS, code1, &XEXP (x, 0), opnum, type, ind_levels, insn); - find_reloads_address_1 (mode, orig_op1, 1, PLUS, SCRATCH, + find_reloads_address_1 (mode, as, orig_op1, 1, PLUS, SCRATCH, &XEXP (x, 1), opnum, type, ind_levels, insn); } else if (code0 == CONST_INT || code0 == CONST || code0 == SYMBOL_REF || code0 == LABEL_REF) - find_reloads_address_1 (mode, orig_op1, 0, PLUS, code0, + find_reloads_address_1 (mode, as, orig_op1, 0, PLUS, code0, &XEXP (x, 1), opnum, type, ind_levels, insn); else if (code1 == CONST_INT || code1 == CONST || code1 == SYMBOL_REF || code1 == LABEL_REF) - find_reloads_address_1 (mode, orig_op0, 0, PLUS, code1, + find_reloads_address_1 (mode, as, orig_op0, 0, PLUS, code1, &XEXP (x, 0), opnum, type, ind_levels, insn); else if (code0 == REG && code1 == REG) { if (REGNO_OK_FOR_INDEX_P (REGNO (op1)) - && regno_ok_for_base_p (REGNO (op0), mode, PLUS, REG)) + && regno_ok_for_base_p (REGNO (op0), mode, as, PLUS, REG)) return 0; else if (REGNO_OK_FOR_INDEX_P (REGNO (op0)) - && regno_ok_for_base_p (REGNO (op1), mode, PLUS, REG)) + && regno_ok_for_base_p (REGNO (op1), mode, as, PLUS, REG)) return 0; - else if (regno_ok_for_base_p (REGNO (op0), mode, PLUS, REG)) - find_reloads_address_1 (mode, orig_op1, 1, PLUS, SCRATCH, + else if (regno_ok_for_base_p (REGNO (op0), mode, as, PLUS, REG)) + find_reloads_address_1 (mode, as, orig_op1, 1, PLUS, SCRATCH, &XEXP (x, 1), opnum, type, ind_levels, insn); else if (REGNO_OK_FOR_INDEX_P (REGNO (op1))) - find_reloads_address_1 (mode, orig_op0, 0, PLUS, REG, + find_reloads_address_1 (mode, as, orig_op0, 0, PLUS, REG, &XEXP (x, 0), opnum, type, ind_levels, insn); - else if (regno_ok_for_base_p (REGNO (op1), mode, PLUS, REG)) - find_reloads_address_1 (mode, orig_op0, 1, PLUS, SCRATCH, + else if (regno_ok_for_base_p (REGNO (op1), mode, as, PLUS, REG)) + find_reloads_address_1 (mode, as, orig_op0, 1, PLUS, SCRATCH, &XEXP (x, 0), opnum, type, ind_levels, insn); else if (REGNO_OK_FOR_INDEX_P (REGNO (op0))) - find_reloads_address_1 (mode, orig_op1, 0, PLUS, REG, + find_reloads_address_1 (mode, as, orig_op1, 0, PLUS, REG, &XEXP (x, 1), opnum, type, ind_levels, insn); else { - find_reloads_address_1 (mode, orig_op0, 0, PLUS, REG, + find_reloads_address_1 (mode, as, orig_op0, 0, PLUS, REG, &XEXP (x, 0), opnum, type, ind_levels, insn); - find_reloads_address_1 (mode, orig_op1, 1, PLUS, SCRATCH, + find_reloads_address_1 (mode, as, orig_op1, 1, PLUS, SCRATCH, &XEXP (x, 1), opnum, type, ind_levels, insn); } @@ -5635,20 +5635,20 @@ find_reloads_address_1 (enum machine_mode mode, rtx x, int context, else if (code0 == REG) { - find_reloads_address_1 (mode, orig_op0, 1, PLUS, SCRATCH, + find_reloads_address_1 (mode, as, orig_op0, 1, PLUS, SCRATCH, &XEXP (x, 0), opnum, type, ind_levels, insn); - find_reloads_address_1 (mode, orig_op1, 0, PLUS, REG, + find_reloads_address_1 (mode, as, orig_op1, 0, PLUS, REG, &XEXP (x, 1), opnum, type, ind_levels, insn); } else if (code1 == REG) { - find_reloads_address_1 (mode, orig_op1, 1, PLUS, SCRATCH, + find_reloads_address_1 (mode, as, orig_op1, 1, PLUS, SCRATCH, &XEXP (x, 1), opnum, type, ind_levels, insn); - find_reloads_address_1 (mode, orig_op0, 0, PLUS, REG, + find_reloads_address_1 (mode, as, orig_op0, 0, PLUS, REG, &XEXP (x, 0), opnum, type, ind_levels, insn); } @@ -5690,7 +5690,7 @@ find_reloads_address_1 (enum machine_mode mode, rtx x, int context, if ((REG_P (XEXP (op1, 1)) && !REGNO_OK_FOR_INDEX_P (REGNO (XEXP (op1, 1)))) || GET_CODE (XEXP (op1, 1)) == PLUS) - find_reloads_address_1 (mode, XEXP (op1, 1), 1, code, SCRATCH, + find_reloads_address_1 (mode, as, XEXP (op1, 1), 1, code, SCRATCH, &XEXP (op1, 1), opnum, RELOAD_OTHER, ind_levels, insn); @@ -5701,18 +5701,18 @@ find_reloads_address_1 (enum machine_mode mode, rtx x, int context, /* A register that is incremented cannot be constant! */ gcc_assert (regno < FIRST_PSEUDO_REGISTER - || reg_equiv_constant[regno] == 0); + || reg_equiv_constant (regno) == 0); /* Handle a register that is equivalent to a memory location which cannot be addressed directly. */ - if (reg_equiv_memory_loc[regno] != 0 - && (reg_equiv_address[regno] != 0 + if (reg_equiv_memory_loc (regno) != 0 + && (reg_equiv_address (regno) != 0 || num_not_at_initial_offset)) { rtx tem = make_memloc (XEXP (x, 0), regno); - if (reg_equiv_address[regno] - || ! rtx_equal_p (tem, reg_equiv_mem[regno])) + if (reg_equiv_address (regno) + || ! rtx_equal_p (tem, reg_equiv_mem (regno))) { rtx orig = tem; @@ -5732,8 +5732,8 @@ find_reloads_address_1 (enum machine_mode mode, rtx x, int context, register. */ reloadnum = push_reload (tem, tem, &XEXP (x, 0), &XEXP (op1, 0), - base_reg_class (mode, code, - index_code), + base_reg_class (mode, as, + code, index_code), GET_MODE (x), GET_MODE (x), 0, 0, opnum, RELOAD_OTHER); @@ -5746,11 +5746,12 @@ find_reloads_address_1 (enum machine_mode mode, rtx x, int context, regno = reg_renumber[regno]; /* We require a base register here... */ - if (!regno_ok_for_base_p (regno, GET_MODE (x), code, index_code)) + if (!regno_ok_for_base_p (regno, GET_MODE (x), as, code, index_code)) { reloadnum = push_reload (XEXP (op1, 0), XEXP (x, 0), &XEXP (op1, 0), &XEXP (x, 0), - base_reg_class (mode, code, index_code), + base_reg_class (mode, as, + code, index_code), GET_MODE (x), GET_MODE (x), 0, 0, opnum, RELOAD_OTHER); @@ -5772,16 +5773,16 @@ find_reloads_address_1 (enum machine_mode mode, rtx x, int context, /* A register that is incremented cannot be constant! */ gcc_assert (regno < FIRST_PSEUDO_REGISTER - || reg_equiv_constant[regno] == 0); + || reg_equiv_constant (regno) == 0); /* Handle a register that is equivalent to a memory location which cannot be addressed directly. */ - if (reg_equiv_memory_loc[regno] != 0 - && (reg_equiv_address[regno] != 0 || num_not_at_initial_offset)) + if (reg_equiv_memory_loc (regno) != 0 + && (reg_equiv_address (regno) != 0 || num_not_at_initial_offset)) { rtx tem = make_memloc (XEXP (x, 0), regno); - if (reg_equiv_address[regno] - || ! rtx_equal_p (tem, reg_equiv_mem[regno])) + if (reg_equiv_address (regno) + || ! rtx_equal_p (tem, reg_equiv_mem (regno))) { rtx orig = tem; @@ -5816,7 +5817,7 @@ find_reloads_address_1 (enum machine_mode mode, rtx x, int context, if (reg_renumber[regno] >= 0) regno = reg_renumber[regno]; if (regno >= FIRST_PSEUDO_REGISTER - || !REG_OK_FOR_CONTEXT (context, regno, mode, code, + || !REG_OK_FOR_CONTEXT (context, regno, mode, as, code, index_code)) { int reloadnum; @@ -5831,19 +5832,16 @@ find_reloads_address_1 (enum machine_mode mode, rtx x, int context, Also don't do this if we can probably update x directly. */ rtx equiv = (MEM_P (XEXP (x, 0)) ? XEXP (x, 0) - : reg_equiv_mem[regno]); - int icode - = (int) optab_handler (add_optab, GET_MODE (x))->insn_code; + : reg_equiv_mem (regno)); + enum insn_code icode = optab_handler (add_optab, GET_MODE (x)); if (insn && NONJUMP_INSN_P (insn) && equiv && memory_operand (equiv, GET_MODE (equiv)) #ifdef HAVE_cc0 && ! sets_cc0_p (PATTERN (insn)) #endif && ! (icode != CODE_FOR_nothing - && ((*insn_data[icode].operand[0].predicate) - (equiv, GET_MODE (x))) - && ((*insn_data[icode].operand[1].predicate) - (equiv, GET_MODE (x))))) + && insn_operand_matches (icode, 0, equiv) + && insn_operand_matches (icode, 1, equiv))) { /* We use the original pseudo for loc, so that emit_reload_insns() knows which pseudo this @@ -5888,7 +5886,7 @@ find_reloads_address_1 (enum machine_mode mode, rtx x, int context, reloaded. Targets that are better off reloading just either part (or perhaps even a different part of an outer expression), should define LEGITIMIZE_RELOAD_ADDRESS. */ - find_reloads_address_1 (GET_MODE (XEXP (x, 0)), XEXP (x, 0), + find_reloads_address_1 (GET_MODE (XEXP (x, 0)), as, XEXP (x, 0), context, code, SCRATCH, &XEXP (x, 0), opnum, type, ind_levels, insn); push_reload (x, NULL_RTX, loc, (rtx*) 0, @@ -5920,9 +5918,9 @@ find_reloads_address_1 (enum machine_mode mode, rtx x, int context, { int regno = REGNO (x); - if (reg_equiv_constant[regno] != 0) + if (reg_equiv_constant (regno) != 0) { - find_reloads_address_part (reg_equiv_constant[regno], loc, + find_reloads_address_part (reg_equiv_constant (regno), loc, context_reg_class, GET_MODE (x), opnum, type, ind_levels); return 1; @@ -5930,21 +5928,21 @@ find_reloads_address_1 (enum machine_mode mode, rtx x, int context, #if 0 /* This might screw code in reload1.c to delete prior output-reload that feeds this insn. */ - if (reg_equiv_mem[regno] != 0) + if (reg_equiv_mem (regno) != 0) { - push_reload (reg_equiv_mem[regno], NULL_RTX, loc, (rtx*) 0, + push_reload (reg_equiv_mem (regno), NULL_RTX, loc, (rtx*) 0, context_reg_class, GET_MODE (x), VOIDmode, 0, 0, opnum, type); return 1; } #endif - if (reg_equiv_memory_loc[regno] - && (reg_equiv_address[regno] != 0 || num_not_at_initial_offset)) + if (reg_equiv_memory_loc (regno) + && (reg_equiv_address (regno) != 0 || num_not_at_initial_offset)) { rtx tem = make_memloc (x, regno); - if (reg_equiv_address[regno] != 0 - || ! rtx_equal_p (tem, reg_equiv_mem[regno])) + if (reg_equiv_address (regno) != 0 + || ! rtx_equal_p (tem, reg_equiv_mem (regno))) { x = tem; find_reloads_address (GET_MODE (x), &x, XEXP (x, 0), @@ -5959,7 +5957,7 @@ find_reloads_address_1 (enum machine_mode mode, rtx x, int context, regno = reg_renumber[regno]; if (regno >= FIRST_PSEUDO_REGISTER - || !REG_OK_FOR_CONTEXT (context, regno, mode, outer_code, + || !REG_OK_FOR_CONTEXT (context, regno, mode, as, outer_code, index_code)) { push_reload (x, NULL_RTX, loc, (rtx*) 0, @@ -5992,7 +5990,7 @@ find_reloads_address_1 (enum machine_mode mode, rtx x, int context, { int regno ATTRIBUTE_UNUSED = subreg_regno (x); - if (!REG_OK_FOR_CONTEXT (context, regno, mode, outer_code, + if (!REG_OK_FOR_CONTEXT (context, regno, mode, as, outer_code, index_code)) { push_reload (x, NULL_RTX, loc, (rtx*) 0, @@ -6006,12 +6004,12 @@ find_reloads_address_1 (enum machine_mode mode, rtx x, int context, else { enum reg_class rclass = context_reg_class; - if ((unsigned) CLASS_MAX_NREGS (rclass, GET_MODE (SUBREG_REG (x))) - > reg_class_size[rclass]) + if (ira_reg_class_max_nregs [rclass][GET_MODE (SUBREG_REG (x))] + > reg_class_size[(int) rclass]) { x = find_reloads_subreg_address (x, 0, opnum, ADDR_TYPE (type), - ind_levels, insn); + ind_levels, insn, NULL); push_reload (x, NULL_RTX, loc, (rtx*) 0, rclass, GET_MODE (x), VOIDmode, 0, 0, opnum, type); return 1; @@ -6033,8 +6031,9 @@ find_reloads_address_1 (enum machine_mode mode, rtx x, int context, if (fmt[i] == 'e') /* Pass SCRATCH for INDEX_CODE, since CODE can never be a PLUS once we get here. */ - find_reloads_address_1 (mode, XEXP (x, i), context, code, SCRATCH, - &XEXP (x, i), opnum, type, ind_levels, insn); + find_reloads_address_1 (mode, as, XEXP (x, i), context, + code, SCRATCH, &XEXP (x, i), + opnum, type, ind_levels, insn); } } @@ -6063,8 +6062,8 @@ find_reloads_address_part (rtx x, rtx *loc, enum reg_class rclass, enum reload_type type, int ind_levels) { if (CONSTANT_P (x) - && (! LEGITIMATE_CONSTANT_P (x) - || PREFERRED_RELOAD_CLASS (x, rclass) == NO_REGS)) + && (!targetm.legitimate_constant_p (mode, x) + || targetm.preferred_reload_class (x, rclass) == NO_REGS)) { x = force_const_mem (mode, x); find_reloads_address (mode, &x, XEXP (x, 0), &XEXP (x, 0), @@ -6073,8 +6072,9 @@ find_reloads_address_part (rtx x, rtx *loc, enum reg_class rclass, else if (GET_CODE (x) == PLUS && CONSTANT_P (XEXP (x, 1)) - && (! LEGITIMATE_CONSTANT_P (XEXP (x, 1)) - || PREFERRED_RELOAD_CLASS (XEXP (x, 1), rclass) == NO_REGS)) + && (!targetm.legitimate_constant_p (GET_MODE (x), XEXP (x, 1)) + || targetm.preferred_reload_class (XEXP (x, 1), rclass) + == NO_REGS)) { rtx tem; @@ -6112,17 +6112,19 @@ find_reloads_address_part (rtx x, rtx *loc, enum reg_class rclass, static rtx find_reloads_subreg_address (rtx x, int force_replace, int opnum, - enum reload_type type, int ind_levels, rtx insn) + enum reload_type type, int ind_levels, rtx insn, + int *address_reloaded) { int regno = REGNO (SUBREG_REG (x)); + int reloaded = 0; - if (reg_equiv_memory_loc[regno]) + if (reg_equiv_memory_loc (regno)) { /* If the address is not directly addressable, or if the address is not offsettable, then it must be replaced. */ if (! force_replace - && (reg_equiv_address[regno] - || ! offsettable_memref_p (reg_equiv_mem[regno]))) + && (reg_equiv_address (regno) + || ! offsettable_memref_p (reg_equiv_mem (regno)))) force_replace = 1; if (force_replace || num_not_at_initial_offset) @@ -6132,13 +6134,12 @@ find_reloads_subreg_address (rtx x, int force_replace, int opnum, /* If the address changes because of register elimination, then it must be replaced. */ if (force_replace - || ! rtx_equal_p (tem, reg_equiv_mem[regno])) + || ! rtx_equal_p (tem, reg_equiv_mem (regno))) { unsigned outer_size = GET_MODE_SIZE (GET_MODE (x)); unsigned inner_size = GET_MODE_SIZE (GET_MODE (SUBREG_REG (x))); int offset; rtx orig = tem; - int reloaded; /* For big-endian paradoxical subregs, SUBREG_BYTE does not hold the correct (negative) byte offset. */ @@ -6149,11 +6150,11 @@ find_reloads_subreg_address (rtx x, int force_replace, int opnum, XEXP (tem, 0) = plus_constant (XEXP (tem, 0), offset); PUT_MODE (tem, GET_MODE (x)); - if (MEM_OFFSET (tem)) - set_mem_offset (tem, plus_constant (MEM_OFFSET (tem), offset)); - if (MEM_SIZE (tem) - && INTVAL (MEM_SIZE (tem)) != (HOST_WIDE_INT) outer_size) - set_mem_size (tem, GEN_INT (outer_size)); + if (MEM_OFFSET_KNOWN_P (tem)) + set_mem_offset (tem, MEM_OFFSET (tem) + offset); + if (MEM_SIZE_KNOWN_P (tem) + && MEM_SIZE (tem) != (HOST_WIDE_INT) outer_size) + set_mem_size (tem, outer_size); /* If this was a paradoxical subreg that we replaced, the resulting memory must be sufficiently aligned to allow @@ -6203,15 +6204,19 @@ find_reloads_subreg_address (rtx x, int force_replace, int opnum, If find_reloads_address already completed replaced the address, there is nothing further to do. */ if (reloaded == 0 - && reg_equiv_mem[regno] != 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, - opnum, type); - + (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_ADDR_SPACE (tem), + MEM, SCRATCH), + GET_MODE (XEXP (tem, 0)), VOIDmode, 0, 0, + opnum, type); + reloaded = 1; + } /* If this is not a toplevel operand, find_reloads doesn't see this substitution. We have to emit a USE of the pseudo so that delete_output_reload can see it. */ @@ -6226,6 +6231,9 @@ find_reloads_subreg_address (rtx x, int force_replace, int opnum, } } } + if (address_reloaded) + *address_reloaded = reloaded; + return x; } @@ -6264,14 +6272,14 @@ subst_reloads (rtx insn) for (check_regno = 0; check_regno < max_regno; check_regno++) { #define CHECK_MODF(ARRAY) \ - gcc_assert (!ARRAY[check_regno] \ + gcc_assert (!VEC_index (reg_equivs_t, reg_equivs, check_regno).ARRAY \ || !loc_mentioned_in_p (r->where, \ - ARRAY[check_regno])) + VEC_index (reg_equivs_t, reg_equivs, check_regno).ARRAY)) - CHECK_MODF (reg_equiv_constant); - CHECK_MODF (reg_equiv_memory_loc); - CHECK_MODF (reg_equiv_address); - CHECK_MODF (reg_equiv_mem); + CHECK_MODF (equiv_constant); + CHECK_MODF (equiv_memory_loc); + CHECK_MODF (equiv_address); + CHECK_MODF (equiv_mem); #undef CHECK_MODF } #endif /* DEBUG_RELOAD */ @@ -6293,33 +6301,7 @@ subst_reloads (rtx insn) if (GET_MODE (reloadreg) != r->mode && r->mode != VOIDmode) reloadreg = reload_adjust_reg_for_mode (reloadreg, r->mode); - /* If we are putting this into a SUBREG and RELOADREG is a - SUBREG, we would be making nested SUBREGs, so we have to fix - this up. Note that r->where == &SUBREG_REG (*r->subreg_loc). */ - - if (r->subreg_loc != 0 && GET_CODE (reloadreg) == SUBREG) - { - if (GET_MODE (*r->subreg_loc) - == GET_MODE (SUBREG_REG (reloadreg))) - *r->subreg_loc = SUBREG_REG (reloadreg); - else - { - int final_offset = - SUBREG_BYTE (*r->subreg_loc) + SUBREG_BYTE (reloadreg); - - /* When working with SUBREGs the rule is that the byte - offset must be a multiple of the SUBREG's mode. */ - final_offset = (final_offset / - GET_MODE_SIZE (GET_MODE (*r->subreg_loc))); - final_offset = (final_offset * - GET_MODE_SIZE (GET_MODE (*r->subreg_loc))); - - *r->where = SUBREG_REG (reloadreg); - SUBREG_BYTE (*r->subreg_loc) = final_offset; - } - } - else - *r->where = reloadreg; + *r->where = reloadreg; } /* If reload got no reg and isn't optional, something's wrong. */ else @@ -6333,10 +6315,6 @@ subst_reloads (rtx insn) void copy_replacements (rtx x, rtx y) { - /* We can't support X being a SUBREG because we might then need to know its - location if something inside it was replaced. */ - gcc_assert (GET_CODE (x) != SUBREG); - copy_replacements_1 (&x, &y, n_replacements); } @@ -6350,24 +6328,13 @@ copy_replacements_1 (rtx *px, rtx *py, int orig_replacements) const char *fmt; for (j = 0; j < orig_replacements; j++) - { - if (replacements[j].subreg_loc == px) - { - r = &replacements[n_replacements++]; - r->where = replacements[j].where; - r->subreg_loc = py; - r->what = replacements[j].what; - r->mode = replacements[j].mode; - } - else if (replacements[j].where == px) - { - r = &replacements[n_replacements++]; - r->where = py; - r->subreg_loc = 0; - r->what = replacements[j].what; - r->mode = replacements[j].mode; - } - } + if (replacements[j].where == px) + { + r = &replacements[n_replacements++]; + r->where = py; + r->what = replacements[j].what; + r->mode = replacements[j].mode; + } x = *px; y = *py; @@ -6393,13 +6360,8 @@ move_replacements (rtx *x, rtx *y) int i; for (i = 0; i < n_replacements; i++) - if (replacements[i].subreg_loc == x) - replacements[i].subreg_loc = y; - else if (replacements[i].where == x) - { - replacements[i].where = y; - replacements[i].subreg_loc = 0; - } + if (replacements[i].where == x) + replacements[i].where = y; } /* If LOC was scheduled to be replaced by something, return the replacement. @@ -6417,36 +6379,19 @@ find_replacement (rtx *loc) if (reloadreg && r->where == loc) { if (r->mode != VOIDmode && GET_MODE (reloadreg) != r->mode) - reloadreg = gen_rtx_REG (r->mode, REGNO (reloadreg)); + reloadreg = reload_adjust_reg_for_mode (reloadreg, r->mode); return reloadreg; } - else if (reloadreg && r->subreg_loc == loc) + else if (reloadreg && GET_CODE (*loc) == SUBREG + && r->where == &SUBREG_REG (*loc)) { - /* RELOADREG must be either a REG or a SUBREG. - - ??? Is it actually still ever a SUBREG? If so, why? */ - - if (REG_P (reloadreg)) - return gen_rtx_REG (GET_MODE (*loc), - (REGNO (reloadreg) + - subreg_regno_offset (REGNO (SUBREG_REG (*loc)), - GET_MODE (SUBREG_REG (*loc)), - SUBREG_BYTE (*loc), - GET_MODE (*loc)))); - else if (GET_MODE (reloadreg) == GET_MODE (*loc)) - return reloadreg; - else - { - int final_offset = SUBREG_BYTE (reloadreg) + SUBREG_BYTE (*loc); - - /* When working with SUBREGs the rule is that the byte - offset must be a multiple of the SUBREG's mode. */ - final_offset = (final_offset / GET_MODE_SIZE (GET_MODE (*loc))); - final_offset = (final_offset * GET_MODE_SIZE (GET_MODE (*loc))); - return gen_rtx_SUBREG (GET_MODE (*loc), SUBREG_REG (reloadreg), - final_offset); - } + if (r->mode != VOIDmode && GET_MODE (reloadreg) != r->mode) + reloadreg = reload_adjust_reg_for_mode (reloadreg, r->mode); + + return simplify_gen_subreg (GET_MODE (*loc), reloadreg, + GET_MODE (SUBREG_REG (*loc)), + SUBREG_BYTE (*loc)); } } @@ -6499,12 +6444,12 @@ refers_to_regno_for_reload_p (unsigned int regno, unsigned int endregno, X must therefore either be a constant or be in memory. */ if (r >= FIRST_PSEUDO_REGISTER) { - if (reg_equiv_memory_loc[r]) + if (reg_equiv_memory_loc (r)) return refers_to_regno_for_reload_p (regno, endregno, - reg_equiv_memory_loc[r], + reg_equiv_memory_loc (r), (rtx*) 0); - gcc_assert (reg_equiv_constant[r] || reg_equiv_invariant[r]); + gcc_assert (reg_equiv_constant (r) || reg_equiv_invariant (r)); return 0; } @@ -6634,9 +6579,9 @@ reg_overlap_mentioned_for_reload_p (rtx x, rtx in) if (regno >= FIRST_PSEUDO_REGISTER) { - if (reg_equiv_memory_loc[regno]) + if (reg_equiv_memory_loc (regno)) return refers_to_mem_for_reload_p (in); - gcc_assert (reg_equiv_constant[regno]); + gcc_assert (reg_equiv_constant (regno)); return 0; } @@ -6687,7 +6632,7 @@ refers_to_mem_for_reload_p (rtx x) if (REG_P (x)) return (REGNO (x) >= FIRST_PSEUDO_REGISTER - && reg_equiv_memory_loc[REGNO (x)]); + && reg_equiv_memory_loc (REGNO (x))); fmt = GET_RTX_FORMAT (GET_CODE (x)); for (i = GET_RTX_LENGTH (GET_CODE (x)) - 1; i >= 0; i--) @@ -6797,6 +6742,15 @@ find_equiv_reg (rtx goal, rtx insn, enum reg_class rclass, int other, || num > PARAM_VALUE (PARAM_MAX_RELOAD_SEARCH_INSNS)) return 0; + /* Don't reuse register contents from before a setjmp-type + function call; on the second return (from the longjmp) it + might have been clobbered by a later reuse. It doesn't + seem worthwhile to actually go and see if it is actually + reused even if that information would be readily available; + just don't reuse it across the setjmp call. */ + if (CALL_P (p) && find_reg_note (p, REG_SETJMP, NULL_RTX)) + return 0; + if (NONJUMP_INSN_P (p) /* If we don't want spill regs ... */ && (! (reload_reg_p != 0 @@ -7041,7 +6995,7 @@ find_equiv_reg (rtx goal, rtx insn, enum reg_class rclass, int other, && ! push_operand (dest, GET_MODE (dest))) return 0; else if (MEM_P (dest) && regno >= FIRST_PSEUDO_REGISTER - && reg_equiv_memory_loc[regno] != 0) + && reg_equiv_memory_loc (regno) != 0) return 0; else if (need_stable_sp && push_operand (dest, GET_MODE (dest))) return 0; @@ -7086,7 +7040,7 @@ find_equiv_reg (rtx goal, rtx insn, enum reg_class rclass, int other, && ! push_operand (dest, GET_MODE (dest))) return 0; else if (MEM_P (dest) && regno >= FIRST_PSEUDO_REGISTER - && reg_equiv_memory_loc[regno] != 0) + && reg_equiv_memory_loc (regno) != 0) return 0; else if (need_stable_sp && push_operand (dest, GET_MODE (dest))) @@ -7285,7 +7239,7 @@ regno_clobbered_p (unsigned int regno, rtx insn, enum machine_mode mode, { rtx elt = XVECEXP (PATTERN (insn), 0, i); if ((GET_CODE (elt) == CLOBBER - || (sets == 1 && GET_CODE (PATTERN (insn)) == SET)) + || (sets == 1 && GET_CODE (elt) == SET)) && REG_P (XEXP (elt, 0))) { unsigned int test = REGNO (XEXP (elt, 0)); @@ -7313,7 +7267,7 @@ reload_adjust_reg_for_mode (rtx reloadreg, enum machine_mode mode) regno = REGNO (reloadreg); - if (WORDS_BIG_ENDIAN) + if (REG_WORDS_BIG_ENDIAN) regno += (int) hard_regno_nregs[regno][GET_MODE (reloadreg)] - (int) hard_regno_nregs[regno][mode];