diff options
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/ChangeLog | 56 | ||||
-rw-r--r-- | gcc/Makefile.in | 13 | ||||
-rw-r--r-- | gcc/addresses.h | 81 | ||||
-rw-r--r-- | gcc/caller-save.c | 3 | ||||
-rw-r--r-- | gcc/config/bfin/bfin-protos.h | 1 | ||||
-rw-r--r-- | gcc/config/bfin/bfin.c | 30 | ||||
-rw-r--r-- | gcc/config/bfin/bfin.h | 39 | ||||
-rw-r--r-- | gcc/config/bfin/bfin.md | 41 | ||||
-rw-r--r-- | gcc/defaults.h | 34 | ||||
-rw-r--r-- | gcc/doc/tm.texi | 70 | ||||
-rw-r--r-- | gcc/recog.c | 6 | ||||
-rw-r--r-- | gcc/regclass.c | 140 | ||||
-rw-r--r-- | gcc/regrename.c | 88 | ||||
-rw-r--r-- | gcc/reload.c | 229 | ||||
-rw-r--r-- | gcc/reload1.c | 5 | ||||
-rw-r--r-- | gcc/rtl-factoring.c | 6 |
16 files changed, 547 insertions, 295 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index d62958aba47..288f1664b3b 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,59 @@ +2006-03-21 Bernd Schmidt <bernd.schmidt@analog.com> + + * config/bfin/bfin-protos.h (bfin_dsp_memref_p): Declare. + * config/bfin/bfin.c (bfin_dsp_memref_p): New function. + (bfin_valid_reg_p): Test for pseudos explicitly and use only + REGNO_MODE_CODE_OK_FOR_BASE_P. New args MODE and OUTER_CODE; all + callers changed. + * config/bfin/bfin.h (PREG_P): Use P_REGNO_P. + (IREG_P, P_REGNO_P, I_REGNO_P): New macros. + (enum reg_class, REG_CLASS_CONTENTS): Add IPREGS. + (BASE_REG_CLASS, REG_OK_FOR_BASE_P, REG_OK_FOR_INDEX_P, + REGNO_OK_FOR_BASE_STRICT_P, REGNO_OK_FOR_BASE_NONSTRICT_P): Delete + macros. + (IREG_POSSIBLE_P, MODE_CODE_BASE_REG_CLASS, + REGNO_MODE_CODE_OK_FOR_BASE_P): New macros. + (REGNO_REG_CLASS): ARGP is in PREGS. + * config/bfin/bfin.md (movhi_insn): Allow for addresses containing + IREGS. + (zero_extendhisi2, extendhisi2): Likewise; changed to define_and_split + to deal with those addresses. + * addresses.h: New file. + * caller-save.c: Include "addresses.h". + (init_caller_save): Use new base_reg_class function. + * rtl-factoring.c: Include "addresses.h". + (recompute_gain_for_pattern_seq): Use new function ok_for_base_p_1. + * recog.c: Include "addresses.h". + (preprocess_constraints): Use new base_reg_class function. + * regrename.c: Include "addresses.h". + (scan_rtx_address): Use new regno_ok_for_base_p and base_reg_class + functions. Keep track of a new var INDEX_CODE to compute valid + classes. + (replace_oldest_value_addr): Likewise. + (replace_oldest_value_mem): Use base_reg_class. + * reload.c: Include "addresses.h". + (REGNO_MODE_OK_FOR_BASE_P, REG_MODE_OK_FOR_BASE_P): Delete macros. + (find_reloads): Use new base_reg_class function. + (find_reloads_address): Likewise; also use regno_ok_for_base_p. + (find_reloads_address_1): Likewise. New args OUTER_CODE and INDEX_CODE; + all callers and prototype changed. + * reload1.c: Include "addresses.h". + (maybe_fix_stack_asms): Use base_reg_class. + * regclass.c: Include "addresses.h". + (ok_for_index_p_nonstrict, ok_for_base_p_nonstrict): New functions. + (init_reg_autoinc): Use new base_reg_class function. + (record_reg_classes): Likewise. + (record_address_regs): Delete arg CLASS; add args CONTEXT, MODE, + OUTER_CODE and INDEX_CODE. All callers and prototype changed. + Use new args to compute necessary class. + + * Makefile.in (regclass.o, reload.o, reload1.o, caller-save.o, recog.o, + regrename.o, rtl-factoring.o): Update dependencies. + * doc/tm.texi (MODE_CODE_BASE_REG_CLASS): Document. + (REGNO_MODE_CODE_OK_FOR_BASE_P): Likewise. + (REG_OK_FOR_BASE_P, REG_MODE_OK_FOR_BASE_P, REG_MODE_OK_FOR_REG_BASE_P, + REG_OK_FOR_INDEX_P): Delete documentation. + 2006-03-21 Alexey Starovoytov <alexey.starovoytov@sun.com> * config.gcc (sparc-*-solaris2*): Change the default CPU setting diff --git a/gcc/Makefile.in b/gcc/Makefile.in index ed09b88601f..4aa7e4d8e2c 100644 --- a/gcc/Makefile.in +++ b/gcc/Makefile.in @@ -1916,7 +1916,7 @@ tree-cfgcleanup.o : tree-cfgcleanup.c $(TREE_FLOW_H) $(CONFIG_H) $(SYSTEM_H) \ tree-ssa-propagate.h rtl-factoring.o : rtl-factoring.c $(CONFIG_H) $(SYSTEM_H) $(RTL_H) \ coretypes.h $(TM_H) $(BASIC_BLOCK_H) $(GGC_H) $(REGS_H) $(PARAMS_H) $(EXPR_H) \ - $(TM_P_H) tree-pass.h tree-flow.h timevar.h output.h + addresses.h $(TM_P_H) tree-pass.h tree-flow.h timevar.h output.h tree-tailcall.o : tree-tailcall.c $(TREE_FLOW_H) $(CONFIG_H) $(SYSTEM_H) \ $(RTL_H) $(TREE_H) $(TM_P_H) $(FUNCTION_H) $(TM_H) coretypes.h \ $(TREE_DUMP_H) $(DIAGNOSTIC_H) except.h tree-pass.h $(FLAGS_H) langhooks.h \ @@ -2468,11 +2468,12 @@ vec.o : vec.c $(CONFIG_H) $(SYSTEM_H) $(TREE_H) coretypes.h vec.h $(GGC_H) \ reload.o : reload.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_H) \ $(FLAGS_H) output.h $(EXPR_H) $(OPTABS_H) reload.h $(RECOG_H) \ hard-reg-set.h insn-config.h $(REGS_H) $(FUNCTION_H) toplev.h \ - $(TM_P_H) $(PARAMS_H) $(TARGET_H) $(REAL_H) + addresses.h $(TM_P_H) $(PARAMS_H) $(TARGET_H) $(REAL_H) reload1.o : reload1.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_H) \ $(EXPR_H) $(OPTABS_H) reload.h $(REGS_H) hard-reg-set.h insn-config.h \ $(BASIC_BLOCK_H) $(RECOG_H) output.h $(FUNCTION_H) toplev.h $(TM_P_H) \ - except.h $(TREE_H) $(REAL_H) $(FLAGS_H) $(MACHMODE_H) $(OBSTACK_H) + addresses.h except.h $(TREE_H) $(REAL_H) $(FLAGS_H) $(MACHMODE_H) \ + $(OBSTACK_H) rtlhooks.o : rtlhooks.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_H) \ rtlhooks-def.h $(EXPR_H) $(RECOG_H) postreload.o : postreload.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \ @@ -2487,7 +2488,7 @@ postreload-gcse.o : postreload-gcse.c $(CONFIG_H) $(SYSTEM_H) coretypes.h \ $(PARAMS_H) timevar.h tree-pass.h $(REAL_H) caller-save.o : caller-save.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_H) \ $(FLAGS_H) $(REGS_H) hard-reg-set.h insn-config.h $(BASIC_BLOCK_H) $(FUNCTION_H) \ - $(RECOG_H) reload.h $(EXPR_H) toplev.h $(TM_P_H) + addresses.h $(RECOG_H) reload.h $(EXPR_H) toplev.h $(TM_P_H) bt-load.o : bt-load.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) except.h \ $(RTL_H) hard-reg-set.h $(REGS_H) $(TM_P_H) $(FIBHEAP_H) output.h $(EXPR_H) \ $(TARGET_H) $(FLAGS_H) $(INSN_ATTR_H) $(FUNCTION_H) tree-pass.h toplev.h @@ -2543,7 +2544,7 @@ final.o : final.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_H) \ recog.o : recog.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_H) \ $(FUNCTION_H) $(BASIC_BLOCK_H) $(REGS_H) $(RECOG_H) $(EXPR_H) \ $(FLAGS_H) insn-config.h $(INSN_ATTR_H) toplev.h output.h reload.h \ - $(TM_P_H) timevar.h tree-pass.h hard-reg-set.h $(REAL_H) + addresses.h $(TM_P_H) timevar.h tree-pass.h hard-reg-set.h $(REAL_H) reg-stack.o : reg-stack.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \ $(RTL_H) $(TREE_H) $(RECOG_H) $(REGS_H) hard-reg-set.h $(FLAGS_H) \ insn-config.h toplev.h reload.h $(FUNCTION_H) $(TM_P_H) $(GGC_H) \ @@ -2575,7 +2576,7 @@ timevar.o : timevar.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \ regrename.o : regrename.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \ $(RTL_H) insn-config.h $(BASIC_BLOCK_H) $(REGS_H) hard-reg-set.h \ output.h $(RECOG_H) $(FUNCTION_H) $(OBSTACK_H) $(FLAGS_H) $(TM_P_H) \ - reload.h toplev.h timevar.h tree-pass.h + addresses.h reload.h toplev.h timevar.h tree-pass.h ifcvt.o : ifcvt.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_H) \ $(REGS_H) toplev.h $(FLAGS_H) insn-config.h $(FUNCTION_H) $(RECOG_H) \ $(TARGET_H) $(BASIC_BLOCK_H) $(EXPR_H) output.h except.h $(TM_P_H) \ diff --git a/gcc/addresses.h b/gcc/addresses.h new file mode 100644 index 00000000000..6741acac041 --- /dev/null +++ b/gcc/addresses.h @@ -0,0 +1,81 @@ +/* Inline functions to test validity of reg classes for addressing modes. + Copyright (C) 2006 Free Software Foundation, Inc. + +This file is part of GCC. + +GCC is free software; you can redistribute it and/or modify it under +the terms of the GNU General Public License as published by the Free +Software Foundation; either version 2, or (at your option) any later +version. + +GCC is distributed in the hope that it will be useful, but WITHOUT ANY +WARRANTY; without even the implied warranty of MERCHANTABILITY or +FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +for more details. + +You should have received a copy of the GNU General Public License +along with GCC; see the file COPYING. If not, write to the Free +Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301, USA. */ + +/* Wrapper function to unify target macros MODE_CODE_BASE_REG_CLASS, + MODE_BASE_REG_REG_CLASS, MODE_BASE_REG_CLASS and BASE_REG_CLASS. + Arguments as for the MODE_CODE_BASE_REG_CLASS macro. */ + +static inline enum reg_class +base_reg_class (enum machine_mode mode ATTRIBUTE_UNUSED, + enum rtx_code outer_code ATTRIBUTE_UNUSED, + enum rtx_code index_code ATTRIBUTE_UNUSED) +{ +#ifdef MODE_CODE_BASE_REG_CLASS + return MODE_CODE_BASE_REG_CLASS (mode, outer_code, index_code); +#else +#ifdef MODE_BASE_REG_REG_CLASS + if (index_code == REG) + return MODE_BASE_REG_REG_CLASS (mode); +#endif +#ifdef MODE_BASE_REG_CLASS + return MODE_BASE_REG_CLASS (mode); +#else + return BASE_REG_CLASS; +#endif +#endif +} + +/* Wrapper function to unify target macros REGNO_MODE_CODE_OK_FOR_BASE_P, + REGNO_MODE_OK_FOR_REG_BASE_P, REGNO_MODE_OK_FOR_BASE_P and + REGNO_OK_FOR_BASE_P. + Arguments as for the REGNO_MODE_CODE_OK_FOR_BASE_P macro. */ + +static inline bool +ok_for_base_p_1 (unsigned regno, enum machine_mode mode ATTRIBUTE_UNUSED, + enum rtx_code outer_code ATTRIBUTE_UNUSED, + enum rtx_code index_code ATTRIBUTE_UNUSED) +{ +#ifdef REGNO_MODE_CODE_OK_FOR_BASE_P + return REGNO_MODE_CODE_OK_FOR_BASE_P (regno, mode, outer_code, index_code); +#else +#ifdef REGNO_MODE_OK_FOR_REG_BASE_P + if (index_code == REG) + return REGNO_MODE_OK_FOR_REG_BASE_P (regno, mode); +#endif +#ifdef REGNO_MODE_OK_FOR_BASE_P + return REGNO_MODE_OK_FOR_BASE_P (regno, mode); +#else + return REGNO_OK_FOR_BASE_P (regno); +#endif +#endif +} + +/* Wrapper around ok_for_base_p_1, for use after register allocation is + complete. Arguments as for the called function. */ + +static inline bool +regno_ok_for_base_p (unsigned regno, enum machine_mode mode, + enum rtx_code outer_code, enum rtx_code index_code) +{ + if (regno >= FIRST_PSEUDO_REGISTER && reg_renumber[regno] >= 0) + regno = reg_renumber[regno]; + + return ok_for_base_p_1 (regno, mode, outer_code, index_code); +} diff --git a/gcc/caller-save.c b/gcc/caller-save.c index ea85044cfec..d0c33e3cf31 100644 --- a/gcc/caller-save.c +++ b/gcc/caller-save.c @@ -25,6 +25,7 @@ Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA #include "tm.h" #include "rtl.h" #include "regs.h" +#include "addresses.h" #include "insn-config.h" #include "flags.h" #include "hard-reg-set.h" @@ -153,7 +154,7 @@ init_caller_save (void) for (i = 0; i < FIRST_PSEUDO_REGISTER; i++) if (TEST_HARD_REG_BIT (reg_class_contents - [(int) MODE_BASE_REG_CLASS (regno_save_mode [i][1])], i)) + [(int) base_reg_class (regno_save_mode [i][1], PLUS, CONST_INT)], i)) break; gcc_assert (i < FIRST_PSEUDO_REGISTER); diff --git a/gcc/config/bfin/bfin-protos.h b/gcc/config/bfin/bfin-protos.h index ae38a07369d..4d586acb96e 100644 --- a/gcc/config/bfin/bfin-protos.h +++ b/gcc/config/bfin/bfin-protos.h @@ -47,6 +47,7 @@ extern rtx bfin_gen_compare (rtx, Mmode); extern void expand_move (rtx *, Mmode); extern void bfin_expand_call (rtx, rtx, rtx, rtx, int); extern bool bfin_longcall_p (rtx, int); +extern bool bfin_dsp_memref_p (rtx); extern bool bfin_expand_strmov (rtx, rtx, rtx, rtx); extern void conditional_register_usage (void); diff --git a/gcc/config/bfin/bfin.c b/gcc/config/bfin/bfin.c index 9e8bee6bc0c..692964083b2 100644 --- a/gcc/config/bfin/bfin.c +++ b/gcc/config/bfin/bfin.c @@ -1062,6 +1062,19 @@ effective_address_32bit_p (rtx op, enum machine_mode mode) return offset < 0 || offset > 30; } +/* Returns true if X is a memory reference using an I register. */ +bool +bfin_dsp_memref_p (rtx x) +{ + if (! MEM_P (x)) + return false; + x = XEXP (x, 0); + if (GET_CODE (x) == POST_INC || GET_CODE (x) == PRE_INC + || GET_CODE (x) == POST_DEC || GET_CODE (x) == PRE_DEC) + x = XEXP (x, 0); + return IREG_P (x); +} + /* Return cost of the memory address ADDR. All addressing modes are equally cheap on the Blackfin. */ @@ -2100,10 +2113,13 @@ bfin_valid_add (enum machine_mode mode, HOST_WIDE_INT value) } static bool -bfin_valid_reg_p (unsigned int regno, int strict) +bfin_valid_reg_p (unsigned int regno, int strict, enum machine_mode mode, + enum rtx_code outer_code) { - return ((strict && REGNO_OK_FOR_BASE_STRICT_P (regno)) - || (!strict && REGNO_OK_FOR_BASE_NONSTRICT_P (regno))); + if (strict) + return REGNO_OK_FOR_BASE_STRICT_P (regno, mode, outer_code, SCRATCH); + else + return REGNO_OK_FOR_BASE_NONSTRICT_P (regno, mode, outer_code, SCRATCH); } bool @@ -2111,12 +2127,12 @@ bfin_legitimate_address_p (enum machine_mode mode, rtx x, int strict) { switch (GET_CODE (x)) { case REG: - if (bfin_valid_reg_p (REGNO (x), strict)) + if (bfin_valid_reg_p (REGNO (x), strict, mode, MEM)) return true; break; case PLUS: if (REG_P (XEXP (x, 0)) - && bfin_valid_reg_p (REGNO (XEXP (x, 0)), strict) + && bfin_valid_reg_p (REGNO (XEXP (x, 0)), strict, mode, PLUS) && (GET_CODE (XEXP (x, 1)) == UNSPEC || (GET_CODE (XEXP (x, 1)) == CONST_INT && bfin_valid_add (mode, INTVAL (XEXP (x, 1)))))) @@ -2126,13 +2142,13 @@ bfin_legitimate_address_p (enum machine_mode mode, rtx x, int strict) case POST_DEC: if (LEGITIMATE_MODE_FOR_AUTOINC_P (mode) && REG_P (XEXP (x, 0)) - && bfin_valid_reg_p (REGNO (XEXP (x, 0)), strict)) + && bfin_valid_reg_p (REGNO (XEXP (x, 0)), strict, mode, POST_INC)) return true; case PRE_DEC: if (LEGITIMATE_MODE_FOR_AUTOINC_P (mode) && XEXP (x, 0) == stack_pointer_rtx && REG_P (XEXP (x, 0)) - && bfin_valid_reg_p (REGNO (XEXP (x, 0)), strict)) + && bfin_valid_reg_p (REGNO (XEXP (x, 0)), strict, mode, PRE_DEC)) return true; break; default: diff --git a/gcc/config/bfin/bfin.h b/gcc/config/bfin/bfin.h index 0e931cdc015..3d2f1bbe009 100644 --- a/gcc/config/bfin/bfin.h +++ b/gcc/config/bfin/bfin.h @@ -215,9 +215,13 @@ extern const char *bfin_library_id_string; #define FIRST_PSEUDO_REGISTER 44 -#define PREG_P(X) (REG_P (X) && REGNO (X) >= REG_P0 && REGNO (X) <= REG_P7) +#define PREG_P(X) (REG_P (X) && P_REGNO_P (REGNO (X))) +#define IREG_P(X) (REG_P (X) && I_REGNO_P (REGNO (X))) #define ADDRESS_REGNO_P(X) ((X) >= REG_P0 && (X) <= REG_M3) #define D_REGNO_P(X) ((X) <= REG_R7) +#define P_REGNO_P(X) ((X) >= REG_P0 && (X) <= REG_P7) +#define I_REGNO_P(X) \ + ((X) == REG_I0 || (X) == REG_I1 || (X) == REG_I2 || (X) == REG_I3) #define REGISTER_NAMES { \ "R0", "R1", "R2", "R3", "R4", "R5", "R6", "R7", \ @@ -344,6 +348,7 @@ enum reg_class DREGS, PREGS_CLOBBERED, PREGS, + IPREGS, DPREGS, MOST_REGS, PROLOGUE_REGS, @@ -374,6 +379,7 @@ enum reg_class "DREGS", \ "PREGS_CLOBBERED", \ "PREGS", \ + "IPREGS", \ "DPREGS", \ "MOST_REGS", \ "PROLOGUE_REGS", \ @@ -412,27 +418,40 @@ enum reg_class { 0x000000ff, 0 }, /* DREGS */ \ { 0x00004700, 0x800 }, /* PREGS_CLOBBERED */ \ { 0x0000ff00, 0x800 }, /* PREGS */ \ + { 0x000fff00, 0x800 }, /* IPREGS */ \ { 0x0000ffff, 0x800 }, /* DPREGS */ \ { 0xffffffff, 0x800 }, /* MOST_REGS */\ { 0x00000000, 0x7f8 }, /* PROLOGUE_REGS */\ { 0xffffffff, 0xff8 }, /* NON_A_CC_REGS */\ { 0xffffffff, 0xfff }} /* ALL_REGS */ -#define BASE_REG_CLASS PREGS +#define IREG_POSSIBLE_P(OUTER) \ + ((OUTER) == POST_INC || (OUTER) == PRE_INC \ + || (OUTER) == POST_DEC || (OUTER) == PRE_DEC \ + || (OUTER) == MEM || (OUTER) == ADDRESS) + +#define MODE_CODE_BASE_REG_CLASS(MODE, OUTER, INDEX) \ + ((MODE) == HImode && IREG_POSSIBLE_P (OUTER) ? IPREGS : PREGS) + #define INDEX_REG_CLASS PREGS -#define REGNO_OK_FOR_BASE_STRICT_P(X) (REGNO_REG_CLASS (X) == BASE_REG_CLASS) -#define REGNO_OK_FOR_BASE_NONSTRICT_P(X) \ - (((X) >= FIRST_PSEUDO_REGISTER) || REGNO_REG_CLASS (X) == BASE_REG_CLASS) +#define REGNO_OK_FOR_BASE_STRICT_P(X, MODE, OUTER, INDEX) \ + (P_REGNO_P (X) || (X) == REG_ARGP \ + || (IREG_POSSIBLE_P (OUTER) && (MODE) == HImode \ + && I_REGNO_P (X))) + +#define REGNO_OK_FOR_BASE_NONSTRICT_P(X, MODE, OUTER, INDEX) \ + ((X) >= FIRST_PSEUDO_REGISTER \ + || REGNO_OK_FOR_BASE_STRICT_P (X, MODE, OUTER, INDEX)) #ifdef REG_OK_STRICT -#define REGNO_OK_FOR_BASE_P(X) REGNO_OK_FOR_BASE_STRICT_P (X) +#define REGNO_MODE_CODE_OK_FOR_BASE_P(X, MODE, OUTER, INDEX) \ + REGNO_OK_FOR_BASE_STRICT_P (X, MODE, OUTER, INDEX) #else -#define REGNO_OK_FOR_BASE_P(X) REGNO_OK_FOR_BASE_NONSTRICT_P (X) +#define REGNO_MODE_CODE_OK_FOR_BASE_P(X, MODE, OUTER, INDEX) \ + REGNO_OK_FOR_BASE_NONSTRICT_P (X, MODE, OUTER, INDEX) #endif -#define REG_OK_FOR_BASE_P(X) (REG_P (X) && REGNO_OK_FOR_BASE_P (REGNO (X))) -#define REG_OK_FOR_INDEX_P(X) 0 #define REGNO_OK_FOR_INDEX_P(X) 0 /* Get reg_class from a letter such as appears in the machine description. */ @@ -464,7 +483,7 @@ enum reg_class #define REGNO_REG_CLASS(REGNO) \ ((REGNO) < REG_P0 ? DREGS \ : (REGNO) < REG_I0 ? PREGS \ - : (REGNO) == REG_ARGP ? BASE_REG_CLASS \ + : (REGNO) == REG_ARGP ? PREGS \ : (REGNO) >= REG_I0 && (REGNO) <= REG_I3 ? IREGS \ : (REGNO) >= REG_L0 && (REGNO) <= REG_L3 ? LREGS \ : (REGNO) >= REG_B0 && (REGNO) <= REG_B3 ? BREGS \ diff --git a/gcc/config/bfin/bfin.md b/gcc/config/bfin/bfin.md index 2b125b5fc63..221e0ceed82 100644 --- a/gcc/config/bfin/bfin.md +++ b/gcc/config/bfin/bfin.md @@ -418,12 +418,23 @@ [(set (match_operand:HI 0 "nonimmediate_operand" "=x,da,x,d,mr") (match_operand:HI 1 "general_operand" "x,xKs7,xKsh,mr,d"))] "GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM" - "@ - %0 = %1; - %0 = %1 (X); - %0 = %1 (X); - %0 = W %1 (X); - W %0 = %1;" +{ + static const char *templates[] = { + "%0 = %1;", + "%0 = %1 (X);", + "%0 = %1 (X);", + "%0 = W %1 (X);", + "W %0 = %1;", + "%h0 = W %1;", + "W %0 = %h1;" + }; + int alt = which_alternative; + rtx mem = (MEM_P (operands[0]) ? operands[0] + : MEM_P (operands[1]) ? operands[1] : NULL_RTX); + if (mem && bfin_dsp_memref_p (mem)) + alt += 2; + return templates[alt]; +} [(set_attr "type" "move,mvi,mvi,mcld,mcst") (set_attr "length" "2,2,4,*,*")]) @@ -588,22 +599,34 @@ ;; Sign and zero extensions -(define_insn "extendhisi2" +(define_insn_and_split "extendhisi2" [(set (match_operand:SI 0 "register_operand" "=d, d") (sign_extend:SI (match_operand:HI 1 "nonimmediate_operand" "d, m")))] "" "@ %0 = %h1 (X); %0 = W %h1 (X);" + "reload_completed && bfin_dsp_memref_p (operands[1])" + [(set (match_dup 2) (match_dup 1)) + (set (match_dup 0) (sign_extend:SI (match_dup 2)))] +{ + operands[2] = gen_lowpart (HImode, operands[0]); +} [(set_attr "type" "alu0,mcld")]) -(define_insn "zero_extendhisi2" +(define_insn_and_split "zero_extendhisi2" [(set (match_operand:SI 0 "register_operand" "=d, d") (zero_extend:SI (match_operand:HI 1 "nonimmediate_operand" "d, m")))] "" "@ %0 = %h1 (Z); - %0 = W%h1 (Z);" + %0 = W %h1 (Z);" + "reload_completed && bfin_dsp_memref_p (operands[1])" + [(set (match_dup 2) (match_dup 1)) + (set (match_dup 0) (zero_extend:SI (match_dup 2)))] +{ + operands[2] = gen_lowpart (HImode, operands[0]); +} [(set_attr "type" "alu0,mcld")]) (define_insn "zero_extendbisi2" diff --git a/gcc/defaults.h b/gcc/defaults.h index 624f039dfea..3d470e94730 100644 --- a/gcc/defaults.h +++ b/gcc/defaults.h @@ -631,40 +631,6 @@ Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA #define TARGET_FLOAT_FORMAT IEEE_FLOAT_FORMAT #endif -/* Some macros can be defined by the backend in either a mode-dependent - or mode-independent form. The compiler proper should only use the - mode-dependent form, providing VOIDmode when the mode is unknown. - We can't poison the macros because the backend may reference them. */ - -#ifndef REGNO_MODE_OK_FOR_BASE_P -#define REGNO_MODE_OK_FOR_BASE_P(REGNO, MODE) REGNO_OK_FOR_BASE_P (REGNO) -#endif - -#ifndef REG_MODE_OK_FOR_BASE_P -#define REG_MODE_OK_FOR_BASE_P(REG, MODE) REG_OK_FOR_BASE_P (REG) -#endif - -/* Determine the register class for registers suitable to be the base - address register in a MEM. Allow the choice to be dependent upon - the mode of the memory access. */ -#ifndef MODE_BASE_REG_CLASS -#define MODE_BASE_REG_CLASS(MODE) BASE_REG_CLASS -#endif - -/* Some machines require a different base register class if the index - is a register. By default, assume that a base register is acceptable. */ -#ifndef MODE_BASE_REG_REG_CLASS -#define MODE_BASE_REG_REG_CLASS(MODE) MODE_BASE_REG_CLASS(MODE) -#endif - -#ifndef REGNO_MODE_OK_FOR_REG_BASE_P -#define REGNO_MODE_OK_FOR_REG_BASE_P(REGNO, MODE) REGNO_MODE_OK_FOR_BASE_P (REGNO, MODE) -#endif - -#ifndef REG_MODE_OK_FOR_REG_BASE_P -#define REG_MODE_OK_FOR_REG_BASE_P(REGNO, MODE) REG_MODE_OK_FOR_BASE_P (REGNO, MODE) -#endif - #ifndef LARGEST_EXPONENT_IS_NORMAL #define LARGEST_EXPONENT_IS_NORMAL(SIZE) 0 #endif diff --git a/gcc/doc/tm.texi b/gcc/doc/tm.texi index e65a9eacc21..708a5af4085 100644 --- a/gcc/doc/tm.texi +++ b/gcc/doc/tm.texi @@ -2294,6 +2294,16 @@ register address. You should define this macro if base plus index addresses have different requirements than other base register uses. @end defmac +@defmac MODE_CODE_BASE_REG_CLASS (@var{mode}, @var{outer_code}, @var{index_code}) +A C expression whose value is the register class to which a valid +base register must belong. @var{outer_code} and @var{index_code} define the +context in which the base register occurs. @var{outer_code} is the code of +the immediately enclosing expression (@code{MEM} for the top level of an +address, @code{ADDRESS} for something that occurs in an +@code{address_operand}). @var{index_code} is the code of the corresponding +index expression if @var{outer_code} is @code{PLUS}; @code{SCRATCH} otherwise. +@end defmac + @defmac INDEX_REG_CLASS A macro whose definition is the name of the class to which a valid index register must belong. An index register is one used in an @@ -2314,7 +2324,9 @@ that expression may examine the mode of the memory reference in @var{mode}. You should define this macro if the mode of the memory reference affects whether a register may be used as a base register. If you define this macro, the compiler will use it instead of -@code{REGNO_OK_FOR_BASE_P}. +@code{REGNO_OK_FOR_BASE_P}. The mode may be @code{VOIDmode} for addresses +that appear outside a @code{MEM}, i.e. as an @code{address_operand}. + @end defmac @defmac REGNO_MODE_OK_FOR_REG_BASE_P (@var{num}, @var{mode}) @@ -2324,6 +2336,20 @@ memory in mode @var{mode}. It may be either a suitable hard register or a pseudo register that has been allocated such a hard register. You should define this macro if base plus index addresses have different requirements than other base register uses. + +Use of this macro is deprecated; please use the more general +@code{REGNO_MODE_CODE_OK_FOR_BASE_P}. +@end defmac + +@defmac REGNO_MODE_CODE_OK_FOR_BASE_P (@var{num}, @var{mode}, @var{outer_code}, @var{index_code}) +A C expression that is just like @code{REGNO_MODE_OK_FOR_BASE_P}, except that +that expression may examine the context in which the register appears in the +memory reference. @var{outer_code} is the code of the immediately enclosing +expression (@code{MEM} if at the top level of the address, @code{ADDRESS} for +something that occurs in an @code{address_operand}). @var{index_code} is the +code of the corresponding index expression if @var{outer_code} is @code{PLUS}; +@code{SCRATCH} otherwise. The mode may be @code{VOIDmode} for addresses +that appear outside a @code{MEM}, i.e. as an @code{address_operand}. @end defmac @defmac REGNO_OK_FOR_INDEX_P (@var{num}) @@ -5056,48 +5082,6 @@ into the @code{symbol_ref}, and then check for it here. When you see a Format}. @end defmac -@defmac REG_OK_FOR_BASE_P (@var{x}) -A C expression that is nonzero if @var{x} (assumed to be a @code{reg} -RTX) is valid for use as a base register. For hard registers, it -should always accept those which the hardware permits and reject the -others. Whether the macro accepts or rejects pseudo registers must be -controlled by @code{REG_OK_STRICT} as described above. This usually -requires two variant definitions, of which @code{REG_OK_STRICT} -controls the one actually used. -@end defmac - -@defmac REG_MODE_OK_FOR_BASE_P (@var{x}, @var{mode}) -A C expression that is just like @code{REG_OK_FOR_BASE_P}, except that -that expression may examine the mode of the memory reference in -@var{mode}. You should define this macro if the mode of the memory -reference affects whether a register may be used as a base register. If -you define this macro, the compiler will use it instead of -@code{REG_OK_FOR_BASE_P}. -@end defmac - -@defmac REG_MODE_OK_FOR_REG_BASE_P (@var{x}, @var{mode}) -A C expression which is nonzero if @var{x} (assumed to be a @code{reg} RTX) -is suitable for use as a base register in base plus index operand addresses, -accessing memory in mode @var{mode}. It may be either a suitable hard -register or a pseudo register that has been allocated such a hard register. -You should define this macro if base plus index addresses have different -requirements than other base register uses. -@end defmac - -@defmac REG_OK_FOR_INDEX_P (@var{x}) -A C expression that is nonzero if @var{x} (assumed to be a @code{reg} -RTX) is valid for use as an index register. - -The difference between an index register and a base register is that -the index register may be scaled. If an address involves the sum of -two registers, neither one of them scaled, then either one may be -labeled the ``base'' and the other the ``index''; but whichever -labeling is used must fit the machine's constraints of which registers -may serve in each capacity. The compiler will try both labelings, -looking for one that is valid, and will reload one or both registers -only if neither labeling works. -@end defmac - @defmac FIND_BASE_TERM (@var{x}) A C expression to determine the base term of address @var{x}. This macro is used in only one place: `find_base_term' in alias.c. diff --git a/gcc/recog.c b/gcc/recog.c index 82cacfed50d..342699f71e9 100644 --- a/gcc/recog.c +++ b/gcc/recog.c @@ -31,6 +31,7 @@ Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA #include "hard-reg-set.h" #include "recog.h" #include "regs.h" +#include "addresses.h" #include "expr.h" #include "function.h" #include "flags.h" @@ -2157,7 +2158,7 @@ preprocess_constraints (void) case 'p': op_alt[j].is_address = 1; op_alt[j].cl = reg_class_subunion[(int) op_alt[j].cl] - [(int) MODE_BASE_REG_CLASS (VOIDmode)]; + [(int) base_reg_class (VOIDmode, ADDRESS, SCRATCH)]; break; case 'g': @@ -2178,7 +2179,8 @@ preprocess_constraints (void) op_alt[j].cl = (reg_class_subunion [(int) op_alt[j].cl] - [(int) MODE_BASE_REG_CLASS (VOIDmode)]); + [(int) base_reg_class (VOIDmode, ADDRESS, + SCRATCH)]); break; } diff --git a/gcc/regclass.c b/gcc/regclass.c index 0b9fd321f21..f76fdcd77cf 100644 --- a/gcc/regclass.c +++ b/gcc/regclass.c @@ -36,6 +36,7 @@ Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA #include "flags.h" #include "basic-block.h" #include "regs.h" +#include "addresses.h" #include "function.h" #include "insn-config.h" #include "recog.h" @@ -852,12 +853,36 @@ static void record_reg_classes (int, int, rtx *, enum machine_mode *, struct reg_pref *); static int copy_cost (rtx, enum machine_mode, enum reg_class, int, secondary_reload_info *); -static void record_address_regs (rtx, enum reg_class, int); +static void record_address_regs (enum machine_mode, rtx, int, enum rtx_code, + enum rtx_code, int); #ifdef FORBIDDEN_INC_DEC_CLASSES static int auto_inc_dec_reg_p (rtx, enum machine_mode); #endif static void reg_scan_mark_refs (rtx, rtx, int); +/* Wrapper around REGNO_OK_FOR_INDEX_P, to allow pseudo registers. */ + +static inline bool +ok_for_index_p_nonstrict (rtx reg) +{ + unsigned regno = REGNO (reg); + return regno >= FIRST_PSEUDO_REGISTER || REGNO_OK_FOR_INDEX_P (regno); +} + +/* A version of regno_ok_for_base_p for use during regclass, when all pseudos + should count as OK. Arguments as for regno_ok_for_base_p. */ + +static inline bool +ok_for_base_p_nonstrict (rtx reg, enum machine_mode mode, + enum rtx_code outer_code, enum rtx_code index_code) +{ + unsigned regno = REGNO (reg); + if (regno >= FIRST_PSEUDO_REGISTER) + return true; + + return ok_for_base_p_1 (regno, mode, outer_code, index_code); +} + /* Return the reg_class in which pseudo reg number REGNO is best allocated. This function is sometimes called before the info has been computed. When that happens, just return GENERAL_REGS, which is innocuous. */ @@ -958,12 +983,13 @@ record_operand_costs (rtx insn, struct costs *op_costs, recog_data.operand[i] = SUBREG_REG (recog_data.operand[i]); if (MEM_P (recog_data.operand[i])) - record_address_regs (XEXP (recog_data.operand[i], 0), - MODE_BASE_REG_CLASS (modes[i]), frequency * 2); + record_address_regs (GET_MODE (recog_data.operand[i]), + XEXP (recog_data.operand[i], 0), + 0, MEM, SCRATCH, frequency * 2); else if (constraints[i][0] == 'p' || EXTRA_ADDRESS_CONSTRAINT (constraints[i][0], constraints[i])) - record_address_regs (recog_data.operand[i], - MODE_BASE_REG_CLASS (modes[i]), frequency * 2); + record_address_regs (VOIDmode, recog_data.operand[i], 0, ADDRESS, + SCRATCH, frequency * 2); } /* Check for commutative in a separate loop so everything will @@ -1037,8 +1063,8 @@ scan_one_insn (rtx insn, int pass) -= (MEMORY_MOVE_COST (GET_MODE (SET_DEST (set)), GENERAL_REGS, 1) * frequency); - record_address_regs (XEXP (SET_SRC (set), 0), - MODE_BASE_REG_CLASS (VOIDmode), frequency * 2); + record_address_regs (GET_MODE (SET_SRC (set)), XEXP (SET_SRC (set), 0), + 0, MEM, SCRATCH, frequency * 2); return insn; } @@ -1148,7 +1174,12 @@ init_reg_autoinc (void) m = (enum machine_mode) ((int) m + 1)) if (HARD_REGNO_MODE_OK (j, m)) { - enum reg_class base_class = MODE_BASE_REG_CLASS (VOIDmode); + /* ??? There are two assumptions here; that the base class does not + depend on the exact outer code (POST_INC vs. PRE_INC etc.), and + that it does not depend on the machine mode of the memory + reference. */ + enum reg_class base_class + = base_reg_class (VOIDmode, POST_INC, SCRATCH); PUT_MODE (r, m); @@ -1544,7 +1575,7 @@ record_reg_classes (int n_alts, int n_ops, rtx *ops, address, i.e. BASE_REG_CLASS. */ classes[i] = reg_class_subunion[(int) classes[i]] - [(int) MODE_BASE_REG_CLASS (VOIDmode)]; + [(int) base_reg_class (VOIDmode, ADDRESS, SCRATCH)]; break; case 'm': case 'o': case 'V': @@ -1658,7 +1689,7 @@ record_reg_classes (int n_alts, int n_ops, rtx *ops, address, i.e. BASE_REG_CLASS. */ classes[i] = reg_class_subunion[(int) classes[i]] - [(int) MODE_BASE_REG_CLASS (VOIDmode)]; + [(int) base_reg_class (VOIDmode, ADDRESS, SCRATCH)]; } #endif break; @@ -1890,16 +1921,28 @@ copy_cost (rtx x, enum machine_mode mode, enum reg_class class, int to_p, /* Record the pseudo registers we must reload into hard registers in a subexpression of a memory address, X. - CLASS is the class that the register needs to be in and is either - BASE_REG_CLASS or INDEX_REG_CLASS. + If CONTEXT is 0, we are looking at the base part of an address, otherwise we + are looking at the index part. + + MODE is the mode of the memory reference; OUTER_CODE and INDEX_CODE + give the context that the rtx appears in. These three arguments are + passed down to base_reg_class. SCALE is twice the amount to multiply the cost by (it is twice so we can represent half-cost adjustments). */ static void -record_address_regs (rtx x, enum reg_class class, int scale) +record_address_regs (enum machine_mode mode, rtx x, int context, + enum rtx_code outer_code, enum rtx_code index_code, + int scale) { enum rtx_code code = GET_CODE (x); + enum reg_class class; + + if (context == 1) + class = INDEX_REG_CLASS; + else + class = base_reg_class (mode, outer_code, index_code); switch (code) { @@ -1940,31 +1983,31 @@ record_address_regs (rtx x, enum reg_class class, int scale) be in the first operand. */ if (MAX_REGS_PER_ADDRESS == 1) - record_address_regs (arg0, class, scale); + record_address_regs (mode, arg0, 0, PLUS, code1, scale); /* If index and base registers are the same on this machine, just record registers in any non-constant operands. We assume here, as well as in the tests below, that all addresses are in canonical form. */ - else if (INDEX_REG_CLASS == MODE_BASE_REG_CLASS (VOIDmode)) + else if (INDEX_REG_CLASS == base_reg_class (VOIDmode, PLUS, SCRATCH)) { - record_address_regs (arg0, class, scale); + record_address_regs (mode, arg0, context, PLUS, code1, scale); if (! CONSTANT_P (arg1)) - record_address_regs (arg1, class, scale); + record_address_regs (mode, arg1, context, PLUS, code0, scale); } /* If the second operand is a constant integer, it doesn't change what class the first operand must be. */ else if (code1 == CONST_INT || code1 == CONST_DOUBLE) - record_address_regs (arg0, class, scale); + record_address_regs (mode, arg0, context, PLUS, code1, scale); /* If the second operand is a symbolic constant, the first operand must be an index register. */ else if (code1 == SYMBOL_REF || code1 == CONST || code1 == LABEL_REF) - record_address_regs (arg0, INDEX_REG_CLASS, scale); + record_address_regs (mode, arg0, 1, PLUS, code1, scale); /* If both operands are registers but one is already a hard register of index or reg-base class, give the other the class that the @@ -1972,22 +2015,20 @@ record_address_regs (rtx x, enum reg_class class, int scale) else if (code0 == REG && code1 == REG && REGNO (arg0) < FIRST_PSEUDO_REGISTER - && (REG_MODE_OK_FOR_REG_BASE_P (arg0, VOIDmode) - || REG_OK_FOR_INDEX_P (arg0))) - record_address_regs (arg1, - REG_MODE_OK_FOR_REG_BASE_P (arg0, VOIDmode) - ? INDEX_REG_CLASS - : MODE_BASE_REG_REG_CLASS (VOIDmode), - scale); + && (ok_for_base_p_nonstrict (arg0, mode, PLUS, REG) + || ok_for_index_p_nonstrict (arg0))) + record_address_regs (mode, arg1, + ok_for_base_p_nonstrict (arg0, mode, PLUS, REG) + ? 1 : 0, + PLUS, REG, scale); else if (code0 == REG && code1 == REG && REGNO (arg1) < FIRST_PSEUDO_REGISTER - && (REG_MODE_OK_FOR_REG_BASE_P (arg1, VOIDmode) - || REG_OK_FOR_INDEX_P (arg1))) - record_address_regs (arg0, - REG_MODE_OK_FOR_REG_BASE_P (arg1, VOIDmode) - ? INDEX_REG_CLASS - : MODE_BASE_REG_REG_CLASS (VOIDmode), - scale); + && (ok_for_base_p_nonstrict (arg1, mode, PLUS, REG) + || ok_for_index_p_nonstrict (arg1))) + record_address_regs (mode, arg0, + ok_for_base_p_nonstrict (arg1, mode, PLUS, REG) + ? 1 : 0, + PLUS, REG, scale); /* If one operand is known to be a pointer, it must be the base with the other operand the index. Likewise if the other operand @@ -1996,16 +2037,14 @@ record_address_regs (rtx x, enum reg_class class, int scale) else if ((code0 == REG && REG_POINTER (arg0)) || code1 == MULT) { - record_address_regs (arg0, MODE_BASE_REG_REG_CLASS (VOIDmode), - scale); - record_address_regs (arg1, INDEX_REG_CLASS, scale); + record_address_regs (mode, arg0, 0, PLUS, code1, scale); + record_address_regs (mode, arg1, 1, PLUS, code0, scale); } else if ((code1 == REG && REG_POINTER (arg1)) || code0 == MULT) { - record_address_regs (arg0, INDEX_REG_CLASS, scale); - record_address_regs (arg1, MODE_BASE_REG_REG_CLASS (VOIDmode), - scale); + record_address_regs (mode, arg0, 1, PLUS, code1, scale); + record_address_regs (mode, arg1, 0, PLUS, code0, scale); } /* Otherwise, count equal chances that each might be a base @@ -2013,12 +2052,10 @@ record_address_regs (rtx x, enum reg_class class, int scale) else { - record_address_regs (arg0, MODE_BASE_REG_REG_CLASS (VOIDmode), - scale / 2); - record_address_regs (arg0, INDEX_REG_CLASS, scale / 2); - record_address_regs (arg1, MODE_BASE_REG_REG_CLASS (VOIDmode), - scale / 2); - record_address_regs (arg1, INDEX_REG_CLASS, scale / 2); + record_address_regs (mode, arg0, 0, PLUS, code1, scale / 2); + record_address_regs (mode, arg0, 1, PLUS, code1, scale / 2); + record_address_regs (mode, arg1, 0, PLUS, code0, scale / 2); + record_address_regs (mode, arg1, 1, PLUS, code0, scale / 2); } } break; @@ -2028,11 +2065,11 @@ record_address_regs (rtx x, enum reg_class class, int scale) if it ends up in the wrong place. */ case POST_MODIFY: case PRE_MODIFY: - record_address_regs (XEXP (x, 0), MODE_BASE_REG_CLASS (VOIDmode), - 2 * scale); + record_address_regs (mode, XEXP (x, 0), 0, code, + GET_CODE (XEXP (XEXP (x, 1), 1)), 2 * scale); if (REG_P (XEXP (XEXP (x, 1), 1))) - record_address_regs (XEXP (XEXP (x, 1), 1), - INDEX_REG_CLASS, 2 * scale); + record_address_regs (mode, XEXP (XEXP (x, 1), 1), 1, code, REG, + 2 * scale); break; case POST_INC: @@ -2050,7 +2087,7 @@ record_address_regs (rtx x, enum reg_class class, int scale) in_inc_dec[REGNO (XEXP (x, 0))] = 1; #endif - record_address_regs (XEXP (x, 0), class, 2 * scale); + record_address_regs (mode, XEXP (x, 0), 0, code, SCRATCH, 2 * scale); break; case REG: @@ -2071,7 +2108,8 @@ record_address_regs (rtx x, enum reg_class class, int scale) int i; for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--) if (fmt[i] == 'e') - record_address_regs (XEXP (x, i), class, scale); + record_address_regs (mode, XEXP (x, i), context, code, SCRATCH, + scale); } } } diff --git a/gcc/regrename.c b/gcc/regrename.c index 49e18c4a7c2..ebb7cbb5fab 100644 --- a/gcc/regrename.c +++ b/gcc/regrename.c @@ -27,6 +27,7 @@ #include "tm_p.h" #include "insn-config.h" #include "regs.h" +#include "addresses.h" #include "hard-reg-set.h" #include "basic-block.h" #include "reload.h" @@ -528,7 +529,7 @@ scan_rtx_address (rtx insn, rtx *loc, enum reg_class cl, rtx op1 = orig_op1; rtx *locI = NULL; rtx *locB = NULL; - rtx *locB_reg = NULL; + enum rtx_code index_code; if (GET_CODE (op0) == SUBREG) { @@ -547,59 +548,70 @@ scan_rtx_address (rtx insn, rtx *loc, enum reg_class cl, { locI = &XEXP (x, 0); locB = &XEXP (x, 1); + index_code = GET_CODE (*locI); } else if (code1 == MULT || code1 == SIGN_EXTEND || code1 == TRUNCATE || code1 == ZERO_EXTEND || code0 == MEM) { locI = &XEXP (x, 1); locB = &XEXP (x, 0); + index_code = GET_CODE (*locI); } else if (code0 == CONST_INT || code0 == CONST || code0 == SYMBOL_REF || code0 == LABEL_REF) - locB = &XEXP (x, 1); + { + locB = &XEXP (x, 1); + index_code = GET_CODE (XEXP (x, 0)); + } else if (code1 == CONST_INT || code1 == CONST || code1 == SYMBOL_REF || code1 == LABEL_REF) - locB = &XEXP (x, 0); + { + locB = &XEXP (x, 0); + index_code = GET_CODE (XEXP (x, 1)); + } else if (code0 == REG && code1 == REG) { int index_op; + unsigned regno0 = REGNO (op0), regno1 = REGNO (op1); - if (REG_OK_FOR_INDEX_P (op0) - && REG_MODE_OK_FOR_REG_BASE_P (op1, mode)) + if (REGNO_OK_FOR_INDEX_P (regno0) + && regno_ok_for_base_p (regno1, mode, PLUS, REG)) index_op = 0; - else if (REG_OK_FOR_INDEX_P (op1) - && REG_MODE_OK_FOR_REG_BASE_P (op0, mode)) + else if (REGNO_OK_FOR_INDEX_P (regno1) + && regno_ok_for_base_p (regno0, mode, PLUS, REG)) index_op = 1; - else if (REG_MODE_OK_FOR_REG_BASE_P (op1, mode)) + else if (regno_ok_for_base_p (regno1, mode, PLUS, REG)) index_op = 0; - else if (REG_MODE_OK_FOR_REG_BASE_P (op0, mode)) + else if (regno_ok_for_base_p (regno0, mode, PLUS, REG)) index_op = 1; - else if (REG_OK_FOR_INDEX_P (op1)) + else if (REGNO_OK_FOR_INDEX_P (regno1)) index_op = 1; else index_op = 0; locI = &XEXP (x, index_op); - locB_reg = &XEXP (x, !index_op); + locB = &XEXP (x, !index_op); + index_code = GET_CODE (*locI); } else if (code0 == REG) { locI = &XEXP (x, 0); locB = &XEXP (x, 1); + index_code = GET_CODE (*locI); } else if (code1 == REG) { locI = &XEXP (x, 1); locB = &XEXP (x, 0); + index_code = GET_CODE (*locI); } if (locI) scan_rtx_address (insn, locI, INDEX_REG_CLASS, action, mode); if (locB) - scan_rtx_address (insn, locB, MODE_BASE_REG_CLASS (mode), action, mode); - if (locB_reg) - scan_rtx_address (insn, locB_reg, MODE_BASE_REG_REG_CLASS (mode), + scan_rtx_address (insn, locB, base_reg_class (mode, PLUS, index_code), action, mode); + return; } @@ -618,7 +630,7 @@ scan_rtx_address (rtx insn, rtx *loc, enum reg_class cl, case MEM: scan_rtx_address (insn, &XEXP (x, 0), - MODE_BASE_REG_CLASS (GET_MODE (x)), action, + base_reg_class (GET_MODE (x), MEM, SCRATCH), action, GET_MODE (x)); return; @@ -669,7 +681,7 @@ scan_rtx (rtx insn, rtx *loc, enum reg_class cl, case MEM: scan_rtx_address (insn, &XEXP (x, 0), - MODE_BASE_REG_CLASS (GET_MODE (x)), action, + base_reg_class (GET_MODE (x), MEM, SCRATCH), action, GET_MODE (x)); return; @@ -1441,7 +1453,7 @@ replace_oldest_value_addr (rtx *loc, enum reg_class cl, rtx op1 = orig_op1; rtx *locI = NULL; rtx *locB = NULL; - rtx *locB_reg = NULL; + enum rtx_code index_code; if (GET_CODE (op0) == SUBREG) { @@ -1460,50 +1472,62 @@ replace_oldest_value_addr (rtx *loc, enum reg_class cl, { locI = &XEXP (x, 0); locB = &XEXP (x, 1); + index_code = GET_CODE (*locI); } else if (code1 == MULT || code1 == SIGN_EXTEND || code1 == TRUNCATE || code1 == ZERO_EXTEND || code0 == MEM) { locI = &XEXP (x, 1); locB = &XEXP (x, 0); + index_code = GET_CODE (*locI); } else if (code0 == CONST_INT || code0 == CONST || code0 == SYMBOL_REF || code0 == LABEL_REF) - locB = &XEXP (x, 1); + { + locB = &XEXP (x, 1); + index_code = GET_CODE (XEXP (x, 0)); + } else if (code1 == CONST_INT || code1 == CONST || code1 == SYMBOL_REF || code1 == LABEL_REF) - locB = &XEXP (x, 0); + { + locB = &XEXP (x, 0); + index_code = GET_CODE (XEXP (x, 1)); + } else if (code0 == REG && code1 == REG) { int index_op; + unsigned regno0 = REGNO (op0), regno1 = REGNO (op1); - if (REG_OK_FOR_INDEX_P (op0) - && REG_MODE_OK_FOR_REG_BASE_P (op1, mode)) + if (REGNO_OK_FOR_INDEX_P (regno0) + && regno_ok_for_base_p (regno1, mode, PLUS, REG)) index_op = 0; - else if (REG_OK_FOR_INDEX_P (op1) - && REG_MODE_OK_FOR_REG_BASE_P (op0, mode)) + else if (REGNO_OK_FOR_INDEX_P (regno1) + && regno_ok_for_base_p (regno0, mode, PLUS, REG)) index_op = 1; - else if (REG_MODE_OK_FOR_REG_BASE_P (op1, mode)) + else if (regno_ok_for_base_p (regno1, mode, PLUS, REG)) index_op = 0; - else if (REG_MODE_OK_FOR_REG_BASE_P (op0, mode)) + else if (regno_ok_for_base_p (regno0, mode, PLUS, REG)) index_op = 1; - else if (REG_OK_FOR_INDEX_P (op1)) + else if (REGNO_OK_FOR_INDEX_P (regno1)) index_op = 1; else index_op = 0; locI = &XEXP (x, index_op); - locB_reg = &XEXP (x, !index_op); + locB = &XEXP (x, !index_op); + index_code = GET_CODE (*locI); } else if (code0 == REG) { locI = &XEXP (x, 0); locB = &XEXP (x, 1); + index_code = GET_CODE (*locI); } else if (code1 == REG) { locI = &XEXP (x, 1); locB = &XEXP (x, 0); + index_code = GET_CODE (*locI); } if (locI) @@ -1511,11 +1535,8 @@ replace_oldest_value_addr (rtx *loc, enum reg_class cl, insn, vd); if (locB) changed |= replace_oldest_value_addr (locB, - MODE_BASE_REG_CLASS (mode), - mode, insn, vd); - if (locB_reg) - changed |= replace_oldest_value_addr (locB_reg, - MODE_BASE_REG_REG_CLASS (mode), + base_reg_class (mode, PLUS, + index_code), mode, insn, vd); return changed; } @@ -1559,7 +1580,8 @@ static bool replace_oldest_value_mem (rtx x, rtx insn, struct value_data *vd) { return replace_oldest_value_addr (&XEXP (x, 0), - MODE_BASE_REG_CLASS (GET_MODE (x)), + base_reg_class (GET_MODE (x), MEM, + SCRATCH), GET_MODE (x), insn, vd); } diff --git a/gcc/reload.c b/gcc/reload.c index 31d79ae8578..9bfb74854ca 100644 --- a/gcc/reload.c +++ b/gcc/reload.c @@ -100,6 +100,7 @@ a register with any other reload. */ #include "recog.h" #include "reload.h" #include "regs.h" +#include "addresses.h" #include "hard-reg-set.h" #include "flags.h" #include "real.h" @@ -269,7 +270,8 @@ 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, rtx *, +static int find_reloads_address_1 (enum machine_mode, 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, @@ -3119,7 +3121,8 @@ 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] = (int) MODE_BASE_REG_CLASS (VOIDmode); + this_alternative[i] + = (int) base_reg_class (VOIDmode, ADDRESS, SCRATCH); win = 1; badop = 0; break; @@ -3323,7 +3326,8 @@ 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] = (int) MODE_BASE_REG_CLASS (VOIDmode); + this_alternative[i] + = (int) base_reg_class (VOIDmode, ADDRESS, SCRATCH); badop = 0; break; } @@ -3826,7 +3830,7 @@ find_reloads (rtx insn, int replace, int ind_levels, int live_known, operand_reloadnum[i] = push_reload (XEXP (recog_data.operand[i], 0), NULL_RTX, &XEXP (recog_data.operand[i], 0), (rtx*) 0, - MODE_BASE_REG_CLASS (VOIDmode), + base_reg_class (VOIDmode, MEM, SCRATCH), GET_MODE (XEXP (recog_data.operand[i], 0)), VOIDmode, 0, 0, i, RELOAD_FOR_INPUT); rld[operand_reloadnum[i]].inc @@ -4745,12 +4749,12 @@ 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_MODE_OK_FOR_BASE_P (regno, mode) + && regno_ok_for_base_p (regno, mode, 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, MODE_BASE_REG_CLASS (mode), + push_reload (ad, NULL_RTX, loc, (rtx*) 0, base_reg_class (mode, MEM, SCRATCH), GET_MODE (ad), VOIDmode, 0, 0, opnum, type); return 1; } @@ -4851,7 +4855,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, - MODE_BASE_REG_CLASS (mode), GET_MODE (tem), + base_reg_class (mode, MEM, SCRATCH), GET_MODE (tem), VOIDmode, 0, 0, opnum, type); return ! removed_and; @@ -4868,8 +4872,10 @@ 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 - && REG_MODE_OK_FOR_BASE_P (XEXP (ad, 0), mode) - && GET_CODE (XEXP (ad, 1)) == CONST_INT) + && GET_CODE (XEXP (ad, 1)) == CONST_INT + && regno_ok_for_base_p (REGNO (XEXP (ad, 0)), mode, PLUS, + CONST_INT)) + { /* Unshare the MEM rtx so we can safely alter it. */ if (memrefloc) @@ -4897,7 +4903,8 @@ find_reloads_address (enum machine_mode mode, rtx *memrefloc, rtx ad, /* If the sum of two regs is not necessarily valid, reload the sum into a base reg. That will at least work. */ - find_reloads_address_part (ad, loc, MODE_BASE_REG_CLASS (mode), + find_reloads_address_part (ad, loc, + base_reg_class (mode, MEM, SCRATCH), Pmode, opnum, type, ind_levels); } return ! removed_and; @@ -4931,19 +4938,26 @@ find_reloads_address (enum machine_mode mode, rtx *memrefloc, rtx ad, for (op_index = 0; op_index < 2; ++op_index) { - rtx operand; + rtx operand, addend; + enum rtx_code inner_code; + + if (GET_CODE (ad) != PLUS) + continue; + inner_code = GET_CODE (XEXP (ad, 0)); if (!(GET_CODE (ad) == PLUS && GET_CODE (XEXP (ad, 1)) == CONST_INT - && (GET_CODE (XEXP (ad, 0)) == PLUS - || GET_CODE (XEXP (ad, 0)) == LO_SUM))) + && (inner_code == PLUS || inner_code == LO_SUM))) continue; operand = XEXP (XEXP (ad, 0), op_index); if (!REG_P (operand) || REGNO (operand) >= FIRST_PSEUDO_REGISTER) continue; - if ((REG_MODE_OK_FOR_BASE_P (operand, mode) + addend = XEXP (XEXP (ad, 0), 1 - op_index); + + if ((regno_ok_for_base_p (REGNO (operand), mode, inner_code, + GET_CODE (addend)) || operand == frame_pointer_rtx #if FRAME_POINTER_REGNUM != HARD_FRAME_POINTER_REGNUM || operand == hard_frame_pointer_rtx @@ -4956,11 +4970,10 @@ find_reloads_address (enum machine_mode mode, rtx *memrefloc, rtx ad, &XEXP (XEXP (ad, 0), 1 - op_index))) { rtx offset_reg; - rtx addend; + enum reg_class cls; offset_reg = plus_constant (operand, INTVAL (XEXP (ad, 1))); - addend = XEXP (XEXP (ad, 0), 1 - op_index); - + /* Form the adjusted address. */ if (GET_CODE (XEXP (ad, 0)) == PLUS) ad = gen_rtx_PLUS (GET_MODE (ad), @@ -4972,12 +4985,13 @@ 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)); find_reloads_address_part (XEXP (ad, op_index), - &XEXP (ad, op_index), - MODE_BASE_REG_CLASS (mode), + &XEXP (ad, op_index), cls, GET_MODE (ad), opnum, type, ind_levels); - find_reloads_address_1 (mode, - XEXP (ad, 1 - op_index), 1, + find_reloads_address_1 (mode, + XEXP (ad, 1 - op_index), 1, GET_CODE (ad), + GET_CODE (XEXP (ad, op_index)), &XEXP (ad, 1 - op_index), opnum, type, 0, insn); @@ -5023,13 +5037,13 @@ find_reloads_address (enum machine_mode mode, rtx *memrefloc, rtx ad, loc = &XEXP (*loc, 0); } - find_reloads_address_part (ad, loc, MODE_BASE_REG_CLASS (mode), + find_reloads_address_part (ad, loc, base_reg_class (mode, MEM, SCRATCH), Pmode, opnum, type, ind_levels); return ! removed_and; } - return find_reloads_address_1 (mode, ad, 0, loc, opnum, type, ind_levels, - insn); + return find_reloads_address_1 (mode, ad, 0, MEM, SCRATCH, loc, opnum, type, + ind_levels, insn); } /* Find all pseudo regs appearing in AD @@ -5240,9 +5254,12 @@ update_auto_inc_notes (rtx insn ATTRIBUTE_UNUSED, int regno ATTRIBUTE_UNUSED, is strictly valid.) CONTEXT = 1 means we are considering regs as index regs, - = 0 means we are considering them as base regs, = 2 means we - are considering them as base regs for REG + REG. - + = 0 means we are considering them as base regs. + OUTER_CODE is the code of the enclosing RTX, typically a MEM, a PLUS, + or an autoinc code. + If CONTEXT == 0 and OUTER_CODE is a PLUS or LO_SUM, then INDEX_CODE + is the code of the index part of the address. Otherwise, pass SCRATCH + for this argument. OPNUM and TYPE specify the purpose of any reloads made. IND_LEVELS says how many levels of indirect addressing are @@ -5263,25 +5280,22 @@ update_auto_inc_notes (rtx insn ATTRIBUTE_UNUSED, int regno ATTRIBUTE_UNUSED, static int find_reloads_address_1 (enum machine_mode mode, 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) \ - ((CONTEXT) == 2 \ - ? REGNO_MODE_OK_FOR_REG_BASE_P (REGNO, MODE) \ - : (CONTEXT) == 1 \ - ? REGNO_OK_FOR_INDEX_P (REGNO) \ - : REGNO_MODE_OK_FOR_BASE_P (REGNO, MODE)) +#define REG_OK_FOR_CONTEXT(CONTEXT, REGNO, MODE, OUTER, INDEX) \ + ((CONTEXT) == 0 \ + ? regno_ok_for_base_p (REGNO, MODE, OUTER, INDEX) \ + : REGNO_OK_FOR_INDEX_P (REGNO)) enum reg_class context_reg_class; RTX_CODE code = GET_CODE (x); - if (context == 2) - context_reg_class = MODE_BASE_REG_REG_CLASS (mode); - else if (context == 1) + if (context == 1) context_reg_class = INDEX_REG_CLASS; else - context_reg_class = MODE_BASE_REG_CLASS (mode); + context_reg_class = base_reg_class (mode, outer_code, index_code); switch (code) { @@ -5338,74 +5352,90 @@ 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, &XEXP (x, 0), opnum, - type, ind_levels, insn); - find_reloads_address_1 (mode, orig_op1, 0, &XEXP (x, 1), opnum, - type, ind_levels, insn); + find_reloads_address_1 (mode, orig_op0, 1, PLUS, SCRATCH, + &XEXP (x, 0), opnum, type, ind_levels, + insn); + find_reloads_address_1 (mode, orig_op1, 0, PLUS, code0, + &XEXP (x, 1), opnum, type, ind_levels, + insn); } else if (code1 == MULT || code1 == SIGN_EXTEND || code1 == TRUNCATE || code1 == ZERO_EXTEND || code0 == MEM) { - find_reloads_address_1 (mode, orig_op0, 0, &XEXP (x, 0), opnum, - type, ind_levels, insn); - find_reloads_address_1 (mode, orig_op1, 1, &XEXP (x, 1), opnum, - type, ind_levels, insn); + find_reloads_address_1 (mode, orig_op0, 0, PLUS, code1, + &XEXP (x, 0), opnum, type, ind_levels, + insn); + find_reloads_address_1 (mode, 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, &XEXP (x, 1), opnum, - type, ind_levels, insn); + find_reloads_address_1 (mode, 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, &XEXP (x, 0), opnum, - type, ind_levels, insn); + find_reloads_address_1 (mode, orig_op0, 0, PLUS, code1, + &XEXP (x, 0), opnum, type, ind_levels, + insn); else if (code0 == REG && code1 == REG) { - if (REG_OK_FOR_INDEX_P (op0) - && REG_MODE_OK_FOR_REG_BASE_P (op1, mode)) + if (REGNO_OK_FOR_INDEX_P (REGNO (op0)) + && regno_ok_for_base_p (REGNO (op1), mode, PLUS, REG)) return 0; - else if (REG_OK_FOR_INDEX_P (op1) - && REG_MODE_OK_FOR_REG_BASE_P (op0, mode)) + else if (REGNO_OK_FOR_INDEX_P (REGNO (op1)) + && regno_ok_for_base_p (REGNO (op0), mode, PLUS, REG)) return 0; - else if (REG_MODE_OK_FOR_REG_BASE_P (op1, mode)) - find_reloads_address_1 (mode, orig_op0, 1, &XEXP (x, 0), opnum, - type, ind_levels, insn); - else if (REG_MODE_OK_FOR_REG_BASE_P (op0, mode)) - find_reloads_address_1 (mode, orig_op1, 1, &XEXP (x, 1), opnum, - type, ind_levels, insn); - else if (REG_OK_FOR_INDEX_P (op1)) - find_reloads_address_1 (mode, orig_op0, 2, &XEXP (x, 0), opnum, - type, ind_levels, insn); - else if (REG_OK_FOR_INDEX_P (op0)) - find_reloads_address_1 (mode, orig_op1, 2, &XEXP (x, 1), 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, + &XEXP (x, 0), opnum, type, ind_levels, + insn); + else if (regno_ok_for_base_p (REGNO (op0), mode, PLUS, REG)) + find_reloads_address_1 (mode, 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, + &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, + &XEXP (x, 1), opnum, type, ind_levels, + insn); else { - find_reloads_address_1 (mode, orig_op0, 1, &XEXP (x, 0), opnum, - type, ind_levels, insn); - find_reloads_address_1 (mode, orig_op1, 0, &XEXP (x, 1), opnum, - type, ind_levels, insn); + find_reloads_address_1 (mode, orig_op0, 1, PLUS, SCRATCH, + &XEXP (x, 0), opnum, type, ind_levels, + insn); + find_reloads_address_1 (mode, orig_op1, 0, PLUS, REG, + &XEXP (x, 1), opnum, type, ind_levels, + insn); } } else if (code0 == REG) { - find_reloads_address_1 (mode, orig_op0, 1, &XEXP (x, 0), opnum, - type, ind_levels, insn); - find_reloads_address_1 (mode, orig_op1, 0, &XEXP (x, 1), opnum, - type, ind_levels, insn); + find_reloads_address_1 (mode, orig_op0, 1, PLUS, SCRATCH, + &XEXP (x, 0), opnum, type, ind_levels, + insn); + find_reloads_address_1 (mode, 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, &XEXP (x, 1), opnum, - type, ind_levels, insn); - find_reloads_address_1 (mode, orig_op0, 0, &XEXP (x, 0), opnum, - type, ind_levels, insn); + find_reloads_address_1 (mode, orig_op1, 1, PLUS, SCRATCH, + &XEXP (x, 1), opnum, type, ind_levels, + insn); + find_reloads_address_1 (mode, orig_op0, 0, PLUS, REG, + &XEXP (x, 0), opnum, type, ind_levels, + insn); } } @@ -5416,6 +5446,7 @@ find_reloads_address_1 (enum machine_mode mode, rtx x, int context, { rtx op0 = XEXP (x, 0); rtx op1 = XEXP (x, 1); + enum rtx_code index_code; int regno; int reloadnum; @@ -5434,12 +5465,14 @@ find_reloads_address_1 (enum machine_mode mode, rtx x, int context, register with its equivalent constant where applicable. */ if (REG_P (XEXP (op1, 1))) if (!REGNO_OK_FOR_INDEX_P (REGNO (XEXP (op1, 1)))) - find_reloads_address_1 (mode, XEXP (op1, 1), 1, &XEXP (op1, 1), - opnum, type, ind_levels, insn); + find_reloads_address_1 (mode, XEXP (op1, 1), 1, code, SCRATCH, + &XEXP (op1, 1), opnum, type, ind_levels, + insn); gcc_assert (REG_P (XEXP (op1, 0))); regno = REGNO (XEXP (op1, 0)); + index_code = GET_CODE (XEXP (op1, 1)); /* A register that is incremented cannot be constant! */ gcc_assert (regno < FIRST_PSEUDO_REGISTER @@ -5466,12 +5499,13 @@ find_reloads_address_1 (enum machine_mode mode, rtx x, int context, ind_levels, insn); /* Then reload the memory location into a base - register. */ + register. */ reloadnum = push_reload (tem, tem, &XEXP (x, 0), - &XEXP (op1, 0), - MODE_BASE_REG_CLASS (mode), - GET_MODE (x), GET_MODE (x), 0, - 0, opnum, RELOAD_OTHER); + &XEXP (op1, 0), + base_reg_class (mode, code, + index_code), + GET_MODE (x), GET_MODE (x), 0, + 0, opnum, RELOAD_OTHER); update_auto_inc_notes (this_insn, regno, reloadnum); return 0; @@ -5482,13 +5516,13 @@ find_reloads_address_1 (enum machine_mode mode, rtx x, int context, regno = reg_renumber[regno]; /* We require a base register here... */ - if (!REGNO_MODE_OK_FOR_BASE_P (regno, GET_MODE (x))) + if (!regno_ok_for_base_p (regno, GET_MODE (x), code, index_code)) { reloadnum = push_reload (XEXP (op1, 0), XEXP (x, 0), - &XEXP (op1, 0), &XEXP (x, 0), - MODE_BASE_REG_CLASS (mode), - GET_MODE (x), GET_MODE (x), 0, 0, - opnum, RELOAD_OTHER); + &XEXP (op1, 0), &XEXP (x, 0), + base_reg_class (mode, code, index_code), + GET_MODE (x), GET_MODE (x), 0, 0, + opnum, RELOAD_OTHER); update_auto_inc_notes (this_insn, regno, reloadnum); return 0; @@ -5546,7 +5580,8 @@ 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)) + || !REG_OK_FOR_CONTEXT (context, regno, mode, outer_code, + index_code)) { int reloadnum; @@ -5654,7 +5689,7 @@ find_reloads_address_1 (enum machine_mode mode, rtx x, int context, (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), - context, &XEXP (x, 0), opnum, + context, code, SCRATCH, &XEXP (x, 0), opnum, type, ind_levels, insn); push_reload (x, NULL_RTX, loc, (rtx*) 0, context_reg_class, @@ -5722,7 +5757,8 @@ 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)) + || !REG_OK_FOR_CONTEXT (context, regno, mode, outer_code, + index_code)) { push_reload (x, NULL_RTX, loc, (rtx*) 0, context_reg_class, @@ -5754,7 +5790,8 @@ 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)) + if (!REG_OK_FOR_CONTEXT (context, regno, mode, outer_code, + index_code)) { push_reload (x, NULL_RTX, loc, (rtx*) 0, context_reg_class, @@ -5792,8 +5829,10 @@ find_reloads_address_1 (enum machine_mode mode, rtx x, int context, for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--) { if (fmt[i] == 'e') - find_reloads_address_1 (mode, XEXP (x, i), context, &XEXP (x, i), - opnum, type, ind_levels, insn); + /* 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); } } diff --git a/gcc/reload1.c b/gcc/reload1.c index d7f59d89b29..a735cfed00f 100644 --- a/gcc/reload1.c +++ b/gcc/reload1.c @@ -36,6 +36,7 @@ Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA #include "expr.h" #include "optabs.h" #include "regs.h" +#include "addresses.h" #include "basic-block.h" #include "reload.h" #include "recog.h" @@ -1375,7 +1376,7 @@ maybe_fix_stack_asms (void) case 'p': cls = (int) reg_class_subunion[cls] - [(int) MODE_BASE_REG_CLASS (VOIDmode)]; + [(int) base_reg_class (VOIDmode, ADDRESS, SCRATCH)]; break; case 'g': @@ -1386,7 +1387,7 @@ maybe_fix_stack_asms (void) default: if (EXTRA_ADDRESS_CONSTRAINT (c, p)) cls = (int) reg_class_subunion[cls] - [(int) MODE_BASE_REG_CLASS (VOIDmode)]; + [(int) base_reg_class (VOIDmode, ADDRESS, SCRATCH)]; else cls = (int) reg_class_subunion[cls] [(int) REG_CLASS_FROM_CONSTRAINT (c, p)]; diff --git a/gcc/rtl-factoring.c b/gcc/rtl-factoring.c index 021a802a4d7..8113306e0e8 100644 --- a/gcc/rtl-factoring.c +++ b/gcc/rtl-factoring.c @@ -36,6 +36,7 @@ Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA #include "tree-flow.h" #include "timevar.h" #include "output.h" +#include "addresses.h" /* Sequence abstraction: @@ -689,8 +690,9 @@ recompute_gain_for_pattern_seq (pattern_seq pseq) #ifdef REGNO_OK_FOR_INDIRECT_JUMP_P || (!REGNO_OK_FOR_INDIRECT_JUMP_P (i, Pmode)) #else - || (!REGNO_MODE_OK_FOR_BASE_P (i, Pmode)) - || (!reg_class_subset_p (REGNO_REG_CLASS (i), BASE_REG_CLASS)) + || (!ok_for_base_p_1 (i, Pmode, MEM, SCRATCH)) + || (!reg_class_subset_p (REGNO_REG_CLASS (i), + base_reg_class (VOIDmode, MEM, SCRATCH))) #endif || (hascall && call_used_regs[i]) || (!call_used_regs[i] && !regs_ever_live[i])) |