Makefile.in (rtlanal.o): Depend on tree.h.

gcc/
	* Makefile.in (rtlanal.o): Depend on tree.h.
	* rtl.h (offset_within_section_p, split_const): Declare.
	* rtlanal.c: Include tree.h.
	(offset_within_block_p): New function, taken from
	mips_offset_within_object_p.
	(split_const): New function, taken from mips_split_const.
	* config/m68k/m68k-protos.h (m68k_illegitimate_symbolic_constant_p):
	Declare.
	* config/m68k/m68k.h (M68K_OFFSETS_MUST_BE_WITHIN_SECTIONS_P): Define.
	(CONSTANT_ADDRESS_P): Only accept legitimate constants.
	(LEGITIMATE_CONSTANT_P): Check m68k_illegitimate_symbolic_constant_p.
	* config/m68k/m68k.c (TARGET_CANNOT_FORCE_CONST_MEM): Define.
	(m68k_illegitimate_symbolic_constant_p): New function.
	* config/m68k/m68k.md (movsi): Remove misleading predicates.
	If M68K_OFFSETS_MUST_BE_WITHIN_SECTIONS_P and the source is a
	symbolic constant that might be outside the symbol's section,
	move the symbol first and then add the offset.
	* config/m68k/uclinux.h (M68K_OFFSETS_MUST_BE_WITHIN_SECTIONS_P):
	Override.
	* config/mips/mips.c (mips_split_const): Delete.
	(mips_offset_within_object_p): Delete.
	(mips_symbolic_constant_p): Use offset_within_section_p and
	split_const instead of mips_offset_within_object_p and
	mips_split_const.
	(mips_cannot_force_const_mem, mips_const_insns, mips_unspec_address)
	(mips_legitimize_const_move, print_operand_reloc)
	(mips_dangerous_for_la25_p): Use split_const instead of
	mips_split_const.

From-SVN: r122428
This commit is contained in:
Richard Sandiford 2007-03-01 09:58:12 +00:00 committed by Richard Sandiford
parent 96e7e5ad47
commit 7ffb5e7879
10 changed files with 175 additions and 93 deletions

View File

@ -1,3 +1,34 @@
2007-03-01 Richard Sandiford <richard@codesourcery.com>
* Makefile.in (rtlanal.o): Depend on tree.h.
* rtl.h (offset_within_section_p, split_const): Declare.
* rtlanal.c: Include tree.h.
(offset_within_block_p): New function, taken from
mips_offset_within_object_p.
(split_const): New function, taken from mips_split_const.
* config/m68k/m68k-protos.h (m68k_illegitimate_symbolic_constant_p):
Declare.
* config/m68k/m68k.h (M68K_OFFSETS_MUST_BE_WITHIN_SECTIONS_P): Define.
(CONSTANT_ADDRESS_P): Only accept legitimate constants.
(LEGITIMATE_CONSTANT_P): Check m68k_illegitimate_symbolic_constant_p.
* config/m68k/m68k.c (TARGET_CANNOT_FORCE_CONST_MEM): Define.
(m68k_illegitimate_symbolic_constant_p): New function.
* config/m68k/m68k.md (movsi): Remove misleading predicates.
If M68K_OFFSETS_MUST_BE_WITHIN_SECTIONS_P and the source is a
symbolic constant that might be outside the symbol's section,
move the symbol first and then add the offset.
* config/m68k/uclinux.h (M68K_OFFSETS_MUST_BE_WITHIN_SECTIONS_P):
Override.
* config/mips/mips.c (mips_split_const): Delete.
(mips_offset_within_object_p): Delete.
(mips_symbolic_constant_p): Use offset_within_section_p and
split_const instead of mips_offset_within_object_p and
mips_split_const.
(mips_cannot_force_const_mem, mips_const_insns, mips_unspec_address)
(mips_legitimize_const_move, print_operand_reloc)
(mips_dangerous_for_la25_p): Use split_const instead of
mips_split_const.
2007-02-28 Eric Christopher <echristo@apple.com> 2007-02-28 Eric Christopher <echristo@apple.com>
* Makefile.in (install-include-dir): Don't rm -rf include. * Makefile.in (install-include-dir): Don't rm -rf include.

View File

@ -2314,7 +2314,7 @@ print-rtl.o : print-rtl.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \
$(BCONFIG_H) $(REAL_H) $(BCONFIG_H) $(REAL_H)
rtlanal.o : rtlanal.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) toplev.h \ rtlanal.o : rtlanal.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) toplev.h \
$(RTL_H) hard-reg-set.h $(TM_P_H) insn-config.h $(RECOG_H) $(REAL_H) \ $(RTL_H) hard-reg-set.h $(TM_P_H) insn-config.h $(RECOG_H) $(REAL_H) \
$(FLAGS_H) $(REGS_H) output.h $(TARGET_H) $(FUNCTION_H) $(FLAGS_H) $(REGS_H) output.h $(TARGET_H) $(FUNCTION_H) $(TREE_H)
varasm.o : varasm.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(TREE_H) \ varasm.o : varasm.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(TREE_H) \
$(RTL_H) $(FLAGS_H) $(FUNCTION_H) $(EXPR_H) hard-reg-set.h $(REGS_H) \ $(RTL_H) $(FLAGS_H) $(FUNCTION_H) $(EXPR_H) hard-reg-set.h $(REGS_H) \

View File

@ -50,6 +50,7 @@ extern int standard_68881_constant_p (rtx);
extern void print_operand_address (FILE *, rtx); extern void print_operand_address (FILE *, rtx);
extern void print_operand (FILE *, rtx, int); extern void print_operand (FILE *, rtx, int);
extern void notice_update_cc (rtx, rtx); extern void notice_update_cc (rtx, rtx);
extern bool m68k_illegitimate_symbolic_constant_p (rtx);
extern rtx legitimize_pic_address (rtx, enum machine_mode, rtx); extern rtx legitimize_pic_address (rtx, enum machine_mode, rtx);
extern int valid_dbcc_comparison_p_2 (rtx, enum machine_mode); extern int valid_dbcc_comparison_p_2 (rtx, enum machine_mode);
extern rtx m68k_libcall_value (enum machine_mode); extern rtx m68k_libcall_value (enum machine_mode);

View File

@ -191,6 +191,9 @@ int m68k_last_compare_had_fp_operands;
#undef TARGET_STRUCT_VALUE_RTX #undef TARGET_STRUCT_VALUE_RTX
#define TARGET_STRUCT_VALUE_RTX m68k_struct_value_rtx #define TARGET_STRUCT_VALUE_RTX m68k_struct_value_rtx
#undef TARGET_CANNOT_FORCE_CONST_MEM
#define TARGET_CANNOT_FORCE_CONST_MEM m68k_illegitimate_symbolic_constant_p
static const struct attribute_spec m68k_attribute_table[] = static const struct attribute_spec m68k_attribute_table[] =
{ {
/* { name, min_len, max_len, decl_req, type_req, fn_type_req, handler } */ /* { name, min_len, max_len, decl_req, type_req, fn_type_req, handler } */
@ -1663,6 +1666,23 @@ output_btst (rtx *operands, rtx countop, rtx dataop, rtx insn, int signpos)
return "btst %0,%1"; return "btst %0,%1";
} }
/* Return true if X is an illegitimate symbolic constant. */
bool
m68k_illegitimate_symbolic_constant_p (rtx x)
{
rtx base, offset;
if (M68K_OFFSETS_MUST_BE_WITHIN_SECTIONS_P)
{
split_const (x, &base, &offset);
if (GET_CODE (base) == SYMBOL_REF
&& !offset_within_block_p (base, INTVAL (offset)))
return true;
}
return false;
}
/* Legitimize PIC addresses. If the address is already /* Legitimize PIC addresses. If the address is already
position-independent, we return ORIG. Newly generated position-independent, we return ORIG. Newly generated
position-independent addresses go to REG. If we need more position-independent addresses go to REG. If we need more

View File

@ -786,17 +786,25 @@ __transfer_from_trampoline () \
/* 1 if X is an address register */ /* 1 if X is an address register */
#define ADDRESS_REG_P(X) (REG_P (X) && REGNO_OK_FOR_BASE_P (REGNO (X))) #define ADDRESS_REG_P(X) (REG_P (X) && REGNO_OK_FOR_BASE_P (REGNO (X)))
/* True if SYMBOL + OFFSET constants must refer to something within
SYMBOL's section. */
#ifndef M68K_OFFSETS_MUST_BE_WITHIN_SECTIONS_P
#define M68K_OFFSETS_MUST_BE_WITHIN_SECTIONS_P 0
#endif
#define MAX_REGS_PER_ADDRESS 2 #define MAX_REGS_PER_ADDRESS 2
#define CONSTANT_ADDRESS_P(X) \ #define CONSTANT_ADDRESS_P(X) \
(GET_CODE (X) == LABEL_REF || GET_CODE (X) == SYMBOL_REF \ ((GET_CODE (X) == LABEL_REF || GET_CODE (X) == SYMBOL_REF \
|| GET_CODE (X) == CONST_INT || GET_CODE (X) == CONST \ || GET_CODE (X) == CONST_INT || GET_CODE (X) == CONST \
|| GET_CODE (X) == HIGH) || GET_CODE (X) == HIGH) \
&& LEGITIMATE_CONSTANT_P (X))
/* Nonzero if the constant value X is a legitimate general operand. /* Nonzero if the constant value X is a legitimate general operand.
It is given that X satisfies CONSTANT_P or is a CONST_DOUBLE. */ It is given that X satisfies CONSTANT_P or is a CONST_DOUBLE. */
#define LEGITIMATE_CONSTANT_P(X) (GET_MODE (X) != XFmode) #define LEGITIMATE_CONSTANT_P(X) \
(GET_MODE (X) != XFmode \
&& !m68k_illegitimate_symbolic_constant_p (X))
#ifndef REG_OK_STRICT #ifndef REG_OK_STRICT
#define PCREL_GENERAL_OPERAND_OK 0 #define PCREL_GENERAL_OPERAND_OK 0

View File

@ -627,10 +627,12 @@
;; In both the PIC and non-PIC cases the patterns generated will ;; In both the PIC and non-PIC cases the patterns generated will
;; matched by the next define_insn. ;; matched by the next define_insn.
(define_expand "movsi" (define_expand "movsi"
[(set (match_operand:SI 0 "nonimmediate_operand" "") [(set (match_operand:SI 0 "" "")
(match_operand:SI 1 "general_operand" ""))] (match_operand:SI 1 "" ""))]
"" ""
{ {
rtx tmp, base, offset;
if (flag_pic && !TARGET_PCREL && symbolic_operand (operands[1], SImode)) if (flag_pic && !TARGET_PCREL && symbolic_operand (operands[1], SImode))
{ {
/* The source is an address which requires PIC relocation. /* The source is an address which requires PIC relocation.
@ -651,6 +653,18 @@
operands[0] = gen_rtx_MEM (SImode, operands[0] = gen_rtx_MEM (SImode,
force_reg (SImode, XEXP (operands[0], 0))); force_reg (SImode, XEXP (operands[0], 0)));
} }
if (M68K_OFFSETS_MUST_BE_WITHIN_SECTIONS_P)
{
split_const (operands[1], &base, &offset);
if (GET_CODE (base) == SYMBOL_REF
&& !offset_within_block_p (base, INTVAL (offset)))
{
tmp = no_new_pseudos ? operands[0] : gen_reg_rtx (SImode);
emit_move_insn (tmp, base);
emit_insn (gen_addsi3 (operands[0], tmp, offset));
DONE;
}
}
}) })
;; General case of fullword move. The register constraints ;; General case of fullword move. The register constraints

View File

@ -65,3 +65,9 @@ Boston, MA 02110-1301, USA. */
/* -msep-data is the default PIC mode on this target. */ /* -msep-data is the default PIC mode on this target. */
#define DRIVER_SELF_SPECS \ #define DRIVER_SELF_SPECS \
"%{fpie|fPIE|fpic|fPIC:%{!msep-data:%{!mid-shared-library: -msep-data}}}" "%{fpie|fPIE|fpic|fPIC:%{!msep-data:%{!mid-shared-library: -msep-data}}}"
/* The uclinux binary format relies on relocations against a segment being
within that segment. Conservatively apply this rule to individual
sections. */
#undef M68K_OFFSETS_MUST_BE_WITHIN_SECTIONS_P
#define M68K_OFFSETS_MUST_BE_WITHIN_SECTIONS_P 1

View File

@ -267,8 +267,6 @@ struct mips_integer_op;
struct mips_sim; struct mips_sim;
static enum mips_symbol_type mips_classify_symbol (rtx); static enum mips_symbol_type mips_classify_symbol (rtx);
static void mips_split_const (rtx, rtx *, HOST_WIDE_INT *);
static bool mips_offset_within_object_p (rtx, HOST_WIDE_INT);
static bool mips_valid_base_register_p (rtx, enum machine_mode, int); static bool mips_valid_base_register_p (rtx, enum machine_mode, int);
static bool mips_symbolic_address_p (enum mips_symbol_type, enum machine_mode); static bool mips_symbolic_address_p (enum mips_symbol_type, enum machine_mode);
static bool mips_classify_address (struct mips_address_info *, rtx, static bool mips_classify_address (struct mips_address_info *, rtx,
@ -1292,58 +1290,6 @@ mips_classify_symbol (rtx x)
return SYMBOL_GENERAL; return SYMBOL_GENERAL;
} }
/* Split X into a base and a constant offset, storing them in *BASE
and *OFFSET respectively. */
static void
mips_split_const (rtx x, rtx *base, HOST_WIDE_INT *offset)
{
*offset = 0;
if (GET_CODE (x) == CONST)
{
x = XEXP (x, 0);
if (GET_CODE (x) == PLUS && GET_CODE (XEXP (x, 1)) == CONST_INT)
{
*offset += INTVAL (XEXP (x, 1));
x = XEXP (x, 0);
}
}
*base = x;
}
/* Return true if SYMBOL is a SYMBOL_REF and OFFSET + SYMBOL points
to the same object as SYMBOL, or to the same object_block. */
static bool
mips_offset_within_object_p (rtx symbol, HOST_WIDE_INT offset)
{
if (GET_CODE (symbol) != SYMBOL_REF)
return false;
if (CONSTANT_POOL_ADDRESS_P (symbol)
&& offset >= 0
&& offset < (int) GET_MODE_SIZE (get_pool_mode (symbol)))
return true;
if (SYMBOL_REF_DECL (symbol) != 0
&& offset >= 0
&& offset < int_size_in_bytes (TREE_TYPE (SYMBOL_REF_DECL (symbol))))
return true;
if (SYMBOL_REF_HAS_BLOCK_INFO_P (symbol)
&& SYMBOL_REF_BLOCK (symbol)
&& SYMBOL_REF_BLOCK_OFFSET (symbol) >= 0
&& ((unsigned HOST_WIDE_INT) offset + SYMBOL_REF_BLOCK_OFFSET (symbol)
< (unsigned HOST_WIDE_INT) SYMBOL_REF_BLOCK (symbol)->size))
return true;
return false;
}
/* Return true if X is a symbolic constant that can be calculated in /* Return true if X is a symbolic constant that can be calculated in
the same way as a bare symbol. If it is, store the type of the the same way as a bare symbol. If it is, store the type of the
symbol in *SYMBOL_TYPE. */ symbol in *SYMBOL_TYPE. */
@ -1351,9 +1297,9 @@ mips_offset_within_object_p (rtx symbol, HOST_WIDE_INT offset)
bool bool
mips_symbolic_constant_p (rtx x, enum mips_symbol_type *symbol_type) mips_symbolic_constant_p (rtx x, enum mips_symbol_type *symbol_type)
{ {
HOST_WIDE_INT offset; rtx offset;
mips_split_const (x, &x, &offset); split_const (x, &x, &offset);
if (UNSPEC_ADDRESS_P (x)) if (UNSPEC_ADDRESS_P (x))
*symbol_type = UNSPEC_ADDRESS_TYPE (x); *symbol_type = UNSPEC_ADDRESS_TYPE (x);
else if (GET_CODE (x) == SYMBOL_REF || GET_CODE (x) == LABEL_REF) else if (GET_CODE (x) == SYMBOL_REF || GET_CODE (x) == LABEL_REF)
@ -1365,7 +1311,7 @@ mips_symbolic_constant_p (rtx x, enum mips_symbol_type *symbol_type)
else else
return false; return false;
if (offset == 0) if (offset == const0_rtx)
return true; return true;
/* Check whether a nonzero offset is valid for the underlying /* Check whether a nonzero offset is valid for the underlying
@ -1381,7 +1327,7 @@ mips_symbolic_constant_p (rtx x, enum mips_symbol_type *symbol_type)
sign-extended. In this case we can't allow an arbitrary offset sign-extended. In this case we can't allow an arbitrary offset
in case the 32-bit value X + OFFSET has a different sign from X. */ in case the 32-bit value X + OFFSET has a different sign from X. */
if (Pmode == DImode && !ABI_HAS_64BIT_SYMBOLS) if (Pmode == DImode && !ABI_HAS_64BIT_SYMBOLS)
return mips_offset_within_object_p (x, offset); return offset_within_block_p (x, INTVAL (offset));
/* In other cases the relocations can handle any offset. */ /* In other cases the relocations can handle any offset. */
return true; return true;
@ -1397,15 +1343,15 @@ mips_symbolic_constant_p (rtx x, enum mips_symbol_type *symbol_type)
case SYMBOL_SMALL_DATA: case SYMBOL_SMALL_DATA:
/* Make sure that the offset refers to something within the /* Make sure that the offset refers to something within the
underlying object. This should guarantee that the final same object block. This should guarantee that the final
PC- or GP-relative offset is within the 16-bit limit. */ PC- or GP-relative offset is within the 16-bit limit. */
return mips_offset_within_object_p (x, offset); return offset_within_block_p (x, INTVAL (offset));
case SYMBOL_GOT_LOCAL: case SYMBOL_GOT_LOCAL:
case SYMBOL_GOTOFF_PAGE: case SYMBOL_GOTOFF_PAGE:
/* The linker should provide enough local GOT entries for a /* The linker should provide enough local GOT entries for a
16-bit offset. Larger offsets may lead to GOT overflow. */ 16-bit offset. Larger offsets may lead to GOT overflow. */
return SMALL_OPERAND (offset); return SMALL_INT (offset);
case SYMBOL_GOT_GLOBAL: case SYMBOL_GOT_GLOBAL:
case SYMBOL_GOTOFF_GLOBAL: case SYMBOL_GOTOFF_GLOBAL:
@ -1595,8 +1541,7 @@ mips_tls_symbol_ref_1 (rtx *x, void *data ATTRIBUTE_UNUSED)
static bool static bool
mips_cannot_force_const_mem (rtx x) mips_cannot_force_const_mem (rtx x)
{ {
rtx base; rtx base, offset;
HOST_WIDE_INT offset;
if (!TARGET_MIPS16) if (!TARGET_MIPS16)
{ {
@ -1612,8 +1557,8 @@ mips_cannot_force_const_mem (rtx x)
if (GET_CODE (x) == CONST_INT) if (GET_CODE (x) == CONST_INT)
return true; return true;
mips_split_const (x, &base, &offset); split_const (x, &base, &offset);
if (symbolic_operand (base, VOIDmode) && SMALL_OPERAND (offset)) if (symbolic_operand (base, VOIDmode) && SMALL_INT (offset))
return true; return true;
} }
@ -1800,7 +1745,7 @@ mips_const_insns (rtx x)
{ {
struct mips_integer_op codes[MIPS_MAX_INTEGER_OPS]; struct mips_integer_op codes[MIPS_MAX_INTEGER_OPS];
enum mips_symbol_type symbol_type; enum mips_symbol_type symbol_type;
HOST_WIDE_INT offset; rtx offset;
switch (GET_CODE (x)) switch (GET_CODE (x))
{ {
@ -1841,16 +1786,16 @@ mips_const_insns (rtx x)
/* Otherwise try splitting the constant into a base and offset. /* Otherwise try splitting the constant into a base and offset.
16-bit offsets can be added using an extra addiu. Larger offsets 16-bit offsets can be added using an extra addiu. Larger offsets
must be calculated separately and then added to the base. */ must be calculated separately and then added to the base. */
mips_split_const (x, &x, &offset); split_const (x, &x, &offset);
if (offset != 0) if (offset != 0)
{ {
int n = mips_const_insns (x); int n = mips_const_insns (x);
if (n != 0) if (n != 0)
{ {
if (SMALL_OPERAND (offset)) if (SMALL_INT (offset))
return n + 1; return n + 1;
else else
return n + 1 + mips_build_integer (codes, offset); return n + 1 + mips_build_integer (codes, INTVAL (offset));
} }
} }
return 0; return 0;
@ -1949,13 +1894,14 @@ mips_split_symbol (rtx temp, rtx addr)
rtx rtx
mips_unspec_address (rtx address, enum mips_symbol_type symbol_type) mips_unspec_address (rtx address, enum mips_symbol_type symbol_type)
{ {
rtx base; rtx base, offset;
HOST_WIDE_INT offset;
mips_split_const (address, &base, &offset); split_const (address, &base, &offset);
base = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, base), base = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, base),
UNSPEC_ADDRESS_FIRST + symbol_type); UNSPEC_ADDRESS_FIRST + symbol_type);
return plus_constant (gen_rtx_CONST (Pmode, base), offset); if (offset != const0_rtx)
base = gen_rtx_PLUS (Pmode, base, offset);
return gen_rtx_CONST (Pmode, base);
} }
@ -2303,8 +2249,7 @@ mips_move_integer (rtx dest, rtx temp, unsigned HOST_WIDE_INT value)
static void static void
mips_legitimize_const_move (enum machine_mode mode, rtx dest, rtx src) mips_legitimize_const_move (enum machine_mode mode, rtx dest, rtx src)
{ {
rtx base; rtx base, offset;
HOST_WIDE_INT offset;
/* Split moves of big integers into smaller pieces. */ /* Split moves of big integers into smaller pieces. */
if (splittable_const_int_operand (src, mode)) if (splittable_const_int_operand (src, mode))
@ -2329,13 +2274,13 @@ mips_legitimize_const_move (enum machine_mode mode, rtx dest, rtx src)
/* If we have (const (plus symbol offset)), load the symbol first /* If we have (const (plus symbol offset)), load the symbol first
and then add in the offset. This is usually better than forcing and then add in the offset. This is usually better than forcing
the constant into memory, at least in non-mips16 code. */ the constant into memory, at least in non-mips16 code. */
mips_split_const (src, &base, &offset); split_const (src, &base, &offset);
if (!TARGET_MIPS16 if (!TARGET_MIPS16
&& offset != 0 && offset != const0_rtx
&& (!no_new_pseudos || SMALL_OPERAND (offset))) && (!no_new_pseudos || SMALL_INT (offset)))
{ {
base = mips_force_temporary (dest, base); base = mips_force_temporary (dest, base);
emit_move_insn (dest, mips_add_offset (0, base, offset)); emit_move_insn (dest, mips_add_offset (0, base, INTVAL (offset)));
return; return;
} }
@ -5709,16 +5654,15 @@ print_operand_reloc (FILE *file, rtx op, const char **relocs)
{ {
enum mips_symbol_type symbol_type; enum mips_symbol_type symbol_type;
const char *p; const char *p;
rtx base; rtx base, offset;
HOST_WIDE_INT offset;
if (!mips_symbolic_constant_p (op, &symbol_type) || relocs[symbol_type] == 0) if (!mips_symbolic_constant_p (op, &symbol_type) || relocs[symbol_type] == 0)
fatal_insn ("PRINT_OPERAND, invalid operand for relocation", op); fatal_insn ("PRINT_OPERAND, invalid operand for relocation", op);
/* If OP uses an UNSPEC address, we want to print the inner symbol. */ /* If OP uses an UNSPEC address, we want to print the inner symbol. */
mips_split_const (op, &base, &offset); split_const (op, &base, &offset);
if (UNSPEC_ADDRESS_P (base)) if (UNSPEC_ADDRESS_P (base))
op = plus_constant (UNSPEC_ADDRESS (base), offset); op = plus_constant (UNSPEC_ADDRESS (base), INTVAL (offset));
fputs (relocs[symbol_type], file); fputs (relocs[symbol_type], file);
output_addr_const (file, op); output_addr_const (file, op);
@ -7640,12 +7584,12 @@ mips_cannot_change_mode_class (enum machine_mode from,
bool bool
mips_dangerous_for_la25_p (rtx x) mips_dangerous_for_la25_p (rtx x)
{ {
HOST_WIDE_INT offset; rtx offset;
if (TARGET_EXPLICIT_RELOCS) if (TARGET_EXPLICIT_RELOCS)
return false; return false;
mips_split_const (x, &x, &offset); split_const (x, &x, &offset);
return global_got_operand (x, VOIDmode); return global_got_operand (x, VOIDmode);
} }

View File

@ -1672,6 +1672,8 @@ extern int rtx_varies_p (rtx, int);
extern int rtx_addr_varies_p (rtx, int); extern int rtx_addr_varies_p (rtx, int);
extern HOST_WIDE_INT get_integer_term (rtx); extern HOST_WIDE_INT get_integer_term (rtx);
extern rtx get_related_value (rtx); extern rtx get_related_value (rtx);
extern bool offset_within_block_p (rtx, HOST_WIDE_INT);
extern void split_const (rtx, rtx *, rtx *);
extern int reg_mentioned_p (rtx, rtx); extern int reg_mentioned_p (rtx, rtx);
extern int count_occurrences (rtx, rtx, int); extern int count_occurrences (rtx, rtx, int);
extern int reg_referenced_p (rtx, rtx); extern int reg_referenced_p (rtx, rtx);

View File

@ -37,6 +37,7 @@ Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
#include "real.h" #include "real.h"
#include "regs.h" #include "regs.h"
#include "function.h" #include "function.h"
#include "tree.h"
/* Information about a subreg of a hard register. */ /* Information about a subreg of a hard register. */
struct subreg_info struct subreg_info
@ -496,6 +497,61 @@ get_related_value (rtx x)
return 0; return 0;
} }
/* Return true if SYMBOL is a SYMBOL_REF and OFFSET + SYMBOL points
to somewhere in the same object or object_block as SYMBOL. */
bool
offset_within_block_p (rtx symbol, HOST_WIDE_INT offset)
{
tree decl;
if (GET_CODE (symbol) != SYMBOL_REF)
return false;
if (offset == 0)
return true;
if (offset > 0)
{
if (CONSTANT_POOL_ADDRESS_P (symbol)
&& offset < (int) GET_MODE_SIZE (get_pool_mode (symbol)))
return true;
decl = SYMBOL_REF_DECL (symbol);
if (decl && offset < int_size_in_bytes (TREE_TYPE (decl)))
return true;
}
if (SYMBOL_REF_HAS_BLOCK_INFO_P (symbol)
&& SYMBOL_REF_BLOCK (symbol)
&& SYMBOL_REF_BLOCK_OFFSET (symbol) >= 0
&& ((unsigned HOST_WIDE_INT) offset + SYMBOL_REF_BLOCK_OFFSET (symbol)
< (unsigned HOST_WIDE_INT) SYMBOL_REF_BLOCK (symbol)->size))
return true;
return false;
}
/* Split X into a base and a constant offset, storing them in *BASE_OUT
and *OFFSET_OUT respectively. */
void
split_const (rtx x, rtx *base_out, rtx *offset_out)
{
if (GET_CODE (x) == CONST)
{
x = XEXP (x, 0);
if (GET_CODE (x) == PLUS && GET_CODE (XEXP (x, 1)) == CONST_INT)
{
*base_out = XEXP (x, 0);
*offset_out = XEXP (x, 1);
return;
}
}
*base_out = x;
*offset_out = const0_rtx;
}
/* Return the number of places FIND appears within X. If COUNT_DEST is /* Return the number of places FIND appears within X. If COUNT_DEST is
zero, we do not count occurrences inside the destination of a SET. */ zero, we do not count occurrences inside the destination of a SET. */