X-Git-Url: http://git.sourceforge.jp/view?a=blobdiff_plain;f=gcc%2Freload.c;h=8420c80807375f7e9bb4b9d5ffa1c722ba97eccf;hb=09b261578fbb8fece1971913fb94367495762f0d;hp=6181224e74784fb774dbf92e79ec7484f6df8871;hpb=b9c74b4dc40904cbb3882d1c245d4eeae24139f4;p=pf3gnuchains%2Fgcc-fork.git diff --git a/gcc/reload.c b/gcc/reload.c index 6181224e747..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,36 +94,42 @@ 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" #include "optabs.h" #include "recog.h" +#include "df.h" #include "reload.h" #include "regs.h" #include "addresses.h" #include "hard-reg-set.h" #include "flags.h" -#include "real.h" #include "output.h" #include "function.h" -#include "toplev.h" #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) \ - (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); @@ -267,20 +270,21 @@ static bool alternative_allows_const_pool_ref (rtx, const char *, int); 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); 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); @@ -295,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 @@ -342,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); @@ -357,13 +359,14 @@ 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); - icode = sri.icode; + 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. */ if (rclass == NO_REGS && icode == CODE_FOR_nothing) @@ -436,7 +439,8 @@ 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_CLASSES) + && (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)) { @@ -515,17 +519,18 @@ 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); - icode = sri.icode; + 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. If an intermediate register is needed, we return its class. */ @@ -611,7 +616,8 @@ get_secondary_mem (rtx x ATTRIBUTE_UNUSED, enum machine_mode mode, 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 +691,15 @@ 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)) || best_cost > cost) { - best_class = rclass; + 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); } } @@ -728,9 +734,9 @@ find_reusable_reload (rtx *p_in, rtx out, enum reg_class rclass, and the other is at worst neutral. (A zero compared against anything is neutral.) - If SMALL_REGISTER_CLASSES, don't use existing reloads unless they are - for the same thing since that can cause us to need more reload registers - than we otherwise would. */ + For targets with small register classes, don't use existing reloads + unless they are for the same thing since that can cause us to need + more reload registers than we otherwise would. */ for (i = 0; i < n_reloads; i++) if ((reg_class_subset_p (rclass, rld[i].rclass) @@ -744,7 +750,8 @@ 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_CLASSES) + && (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; @@ -769,7 +776,8 @@ 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_CLASSES) + && (small_register_class_p (rclass) + || targetm.small_register_classes_for_mode_p (VOIDmode)) && MERGABLE_RELOADS (type, rld[i].when_needed, opnum, rld[i].opnum)) { @@ -782,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)])); @@ -912,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; @@ -938,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 @@ -951,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, @@ -979,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.) @@ -1006,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))) @@ -1056,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) @@ -1068,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; @@ -1103,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))) @@ -1129,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)) @@ -1150,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) @@ -1161,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. */ @@ -1212,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 @@ -1283,7 +1296,7 @@ push_reload (rtx in, rtx out, rtx *inloc, rtx *outloc, 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; } } @@ -1482,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; } @@ -1491,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; } } @@ -1620,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; } } @@ -1754,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 @@ -1767,7 +1777,7 @@ combine_reloads (void) || rtx_equal_p (secondary_memlocs_elim[(int) rld[output_reload].outmode][rld[i].opnum], secondary_memlocs_elim[(int) rld[output_reload].outmode][rld[output_reload].opnum])) #endif - && (SMALL_REGISTER_CLASSES + && (targetm.small_register_classes_for_mode_p (VOIDmode) ? (rld[i].rclass == rld[output_reload].rclass) : (reg_class_subset_p (rld[i].rclass, rld[output_reload].rclass) @@ -1791,7 +1801,7 @@ combine_reloads (void) && ! reload_inner_reg_of_subreg (rld[i].in, rld[i].inmode, rld[i].when_needed != RELOAD_FOR_INPUT) && (reg_class_size[(int) rld[i].rclass] - || SMALL_REGISTER_CLASSES) + || targetm.small_register_classes_for_mode_p (VOIDmode)) /* We will allow making things slightly worse by combining an input and an output, but no worse than that. */ && (rld[i].when_needed == RELOAD_FOR_INPUT @@ -1908,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; @@ -1951,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. */ @@ -2128,18 +2138,24 @@ hard_reg_set_here_p (unsigned int beg_regno, unsigned int end_regno, rtx x) 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 @@ -2199,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; @@ -2242,6 +2258,10 @@ operands_match_p (rtx x, rtx y) 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: @@ -2336,7 +2356,7 @@ decompose (rtx x) { 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) { @@ -2346,7 +2366,7 @@ decompose (rtx x) 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 @@ -2360,7 +2380,7 @@ decompose (rtx x) return val; } } - + if (GET_CODE (addr) == CONST) { addr = XEXP (addr, 0); @@ -2379,7 +2399,7 @@ decompose (rtx x) offset = XEXP (addr, 1); } } - + if (offset == 0) { base = addr; @@ -2389,12 +2409,12 @@ decompose (rtx x) 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); @@ -2405,23 +2425,23 @@ decompose (rtx x) 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); @@ -2552,7 +2572,7 @@ find_reloads (rtx insn, int replace, int ind_levels, int live_known, 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. @@ -2566,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]; @@ -2635,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; @@ -2802,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) { @@ -2835,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; } @@ -2859,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 @@ -2869,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] @@ -3212,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; @@ -3226,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; @@ -3260,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; @@ -3284,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; @@ -3318,7 +3346,7 @@ find_reloads (rtx insn, int replace, int ind_levels, int live_known, break; case 's': - if (GET_CODE (operand) == CONST_INT + if (CONST_INT_P (operand) || (GET_CODE (operand) == CONST_DOUBLE && GET_MODE (operand) == VOIDmode)) break; @@ -3329,7 +3357,7 @@ find_reloads (rtx insn, int replace, int ind_levels, int live_known, 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; @@ -3343,7 +3371,7 @@ find_reloads (rtx insn, int replace, int ind_levels, int live_known, 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; @@ -3396,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; @@ -3418,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; } @@ -3451,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. */ @@ -3482,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) @@ -3511,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, @@ -3570,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])) @@ -3616,7 +3643,7 @@ find_reloads (rtx insn, int replace, int ind_levels, int live_known, || modified[j] != RELOAD_WRITE) && j != i /* Ignore things like match_operator operands. */ - && *recog_data.constraints[j] != 0 + && !recog_data.is_operator[j] /* Don't count an input operand that is constrained to match the early clobber operand. */ && ! (this_alternative_matches[j] == i @@ -3628,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)) { @@ -3693,22 +3720,27 @@ find_reloads (rtx insn, int replace, int ind_levels, int live_known, /* 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++) + 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++) + { + 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; + goal_alternative_number = this_alternative_number; + goal_earlyclobber = this_earlyclobber; } - goal_alternative_swapped = swapped; - best = losers; - goal_alternative_number = this_alternative_number; - goal_earlyclobber = this_earlyclobber; } } @@ -3886,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); @@ -3946,17 +3976,18 @@ find_reloads (rtx insn, int replace, int ind_levels, int live_known, && 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. */ + 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) - address_mode = Pmode; + 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 @@ -4063,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. @@ -4137,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], @@ -4178,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]); @@ -4229,7 +4264,7 @@ find_reloads (rtx insn, int replace, int ind_levels, int live_known, /* 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 @@ -4515,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 @@ -4556,14 +4591,16 @@ find_reloads (rtx insn, int replace, int ind_levels, int live_known, 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; /* Skip alternatives before the one requested. */ while (altnum > 0) { - while (*constraint++ != ','); + while (*constraint++ != ',') + ; altnum--; } /* Scan the requested alternative for TARGET_MEM_CONSTRAINT or 'o'. @@ -4625,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 @@ -4688,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), @@ -4721,17 +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_p (GET_MODE (x), - XEXP (reg_equiv_mem[regno], 0)) - || ! 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--) @@ -4766,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 @@ -4774,29 +4812,30 @@ 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; } /* 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 +4871,8 @@ find_reloads_address (enum machine_mode mode, rtx *memrefloc, rtx ad, 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; @@ -4845,21 +4886,23 @@ 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_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 +4918,7 @@ find_reloads_address (enum machine_mode mode, rtx *memrefloc, rtx ad, 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)) @@ -4886,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 @@ -4909,17 +4952,18 @@ 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; } - 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,9 +4974,9 @@ find_reloads_address (enum machine_mode mode, rtx *memrefloc, rtx ad, /* 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) + && reg_equiv_constant (REGNO (XEXP (ad, 0))) == 0) return 0; subst_reg_equivs_changed = 0; @@ -4942,14 +4986,14 @@ find_reloads_address (enum machine_mode mode, rtx *memrefloc, rtx ad, 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,12 +5054,12 @@ find_reloads_address (enum machine_mode mode, rtx *memrefloc, rtx ad, || ! (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. */ 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; @@ -5032,9 +5076,14 @@ find_reloads_address (enum machine_mode mode, rtx *memrefloc, rtx ad, 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 - && regno_ok_for_base_p (REGNO (XEXP (ad, 0)), mode, PLUS, - CONST_INT)) + && CONST_INT_P (XEXP (ad, 1)) + && (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. */ @@ -5046,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); @@ -5064,8 +5115,8 @@ 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), - Pmode, opnum, type, ind_levels); + base_reg_class (mode, as, MEM, SCRATCH), + GET_MODE (ad), opnum, type, ind_levels); } return ! removed_and; } @@ -5105,8 +5156,8 @@ find_reloads_address (enum machine_mode mode, rtx *memrefloc, rtx ad, 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; @@ -5116,18 +5167,18 @@ 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 || 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,20 +5187,20 @@ find_reloads_address (enum machine_mode mode, rtx *memrefloc, rtx ad, /* 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), + 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, @@ -5165,7 +5216,7 @@ find_reloads_address (enum machine_mode mode, rtx *memrefloc, rtx ad, 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 @@ find_reloads_address (enum machine_mode mode, rtx *memrefloc, rtx ad, /* 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 @@ find_reloads_address (enum machine_mode mode, rtx *memrefloc, rtx ad, /* 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 @@ -5197,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), - Pmode, opnum, type, ind_levels); + 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 @@ -5237,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 @@ -5262,7 +5319,7 @@ subst_reg_equivs (rtx ad, rtx insn) 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 +5342,27 @@ subst_reg_equivs (rtx ad, rtx insn) 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; + gcc_assert (GET_MODE (x) == mode || GET_MODE (x) == VOIDmode); + gcc_assert (GET_MODE (y) == mode || GET_MODE (y) == VOIDmode); - if (GET_CODE (x) == CONST_INT) + 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. */ @@ -5352,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; @@ -5376,9 +5429,9 @@ subst_indexed_address (rtx addr) /* 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; } @@ -5440,15 +5493,16 @@ 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_INDEX_P (REGNO)) + ? regno_ok_for_base_p (REGNO, MODE, AS, OUTER, INDEX) \ + : REGNO_OK_FOR_INDEX_P (REGNO)) enum reg_class context_reg_class; RTX_CODE code = GET_CODE (x); @@ -5456,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) { @@ -5513,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); } @@ -5524,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); } @@ -5581,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); } @@ -5636,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); @@ -5647,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; @@ -5678,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); @@ -5692,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); @@ -5718,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; @@ -5762,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; @@ -5777,18 +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, Pmode)->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, Pmode)) - && ((*insn_data[icode].operand[1].predicate) - (equiv, Pmode)))) + && 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 @@ -5833,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, @@ -5865,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; @@ -5875,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), @@ -5904,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, @@ -5937,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, @@ -5951,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, + 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; @@ -5978,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); } } @@ -6008,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), @@ -6018,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; @@ -6057,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) @@ -6077,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. */ @@ -6094,8 +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_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 @@ -6107,7 +6166,7 @@ find_reloads_subreg_address (rtx x, int force_replace, int opnum, 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); @@ -6128,23 +6187,36 @@ find_reloads_subreg_address (rtx x, int force_replace, int opnum, /* 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))) - 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); - + && 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_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. */ @@ -6159,6 +6231,9 @@ find_reloads_subreg_address (rtx x, int force_replace, int opnum, } } } + if (address_reloaded) + *address_reloaded = reloaded; + return x; } @@ -6197,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 */ @@ -6226,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 @@ -6266,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); } @@ -6283,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; @@ -6326,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. @@ -6350,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)); } } @@ -6432,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; } @@ -6543,7 +6555,7 @@ reg_overlap_mentioned_for_reload_p (rtx x, rtx in) /* 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) { @@ -6567,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; } @@ -6582,7 +6594,7 @@ reg_overlap_mentioned_for_reload_p (rtx x, rtx in) 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); @@ -6620,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--) @@ -6723,11 +6735,22 @@ find_equiv_reg (rtx goal, rtx insn, enum reg_class rclass, int other, 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)) 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 @@ -6777,7 +6800,7 @@ find_equiv_reg (rtx goal, rtx insn, enum reg_class rclass, int other, || (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)) @@ -6791,7 +6814,7 @@ find_equiv_reg (rtx goal, rtx insn, enum reg_class rclass, int other, && 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) @@ -6972,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; @@ -7017,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))) @@ -7119,7 +7142,7 @@ find_inc_amount (rtx x, rtx inced) && 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; @@ -7154,7 +7177,7 @@ find_inc_amount (rtx x, rtx inced) 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) { @@ -7164,13 +7187,13 @@ reg_inc_found_and_valid_p (unsigned int regno, unsigned int endregno, 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; } @@ -7178,7 +7201,7 @@ reg_inc_found_and_valid_p (unsigned int regno, unsigned int endregno, #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 @@ -7206,8 +7229,8 @@ regno_clobbered_p (unsigned int regno, rtx insn, enum machine_mode mode, } 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; @@ -7216,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)); @@ -7226,7 +7249,7 @@ regno_clobbered_p (unsigned int regno, rtx insn, enum machine_mode mode, } if (sets == 2 && reg_inc_found_and_valid_p (regno, endregno, elt)) - return 1; + return 1; } } @@ -7244,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]; @@ -7268,7 +7291,7 @@ static const char *const reload_when_needed_name[] = /* These functions are used to print the variables set by 'find_reloads' */ -void +DEBUG_FUNCTION void debug_reload_to_stream (FILE *f) { int r; @@ -7363,7 +7386,7 @@ debug_reload_to_stream (FILE *f) } } -void +DEBUG_FUNCTION void debug_reload (void) { debug_reload_to_stream (stderr);