bfin-protos.h (bfin_dsp_memref_p): Declare.

* 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.

From-SVN: r112248
This commit is contained in:
Bernd Schmidt 2006-03-21 13:07:33 +00:00 committed by Bernd Schmidt
parent 0002d5d2bc
commit c4963a0a32
16 changed files with 547 additions and 295 deletions

View File

@ -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

View File

@ -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) \

81
gcc/addresses.h Normal file
View File

@ -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);
}

View File

@ -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);

View File

@ -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);

View File

@ -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:

View File

@ -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 \

View File

@ -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"

View File

@ -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

View File

@ -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.

View File

@ -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;
}

View File

@ -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);
}
}
}

View File

@ -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);
}

View File

@ -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);
}
}

View File

@ -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)];

View File

@ -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]))