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>
* 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)
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) \
$(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) \
$(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 (FILE *, rtx, int);
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 int valid_dbcc_comparison_p_2 (rtx, 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
#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[] =
{
/* { 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 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
position-independent, we return ORIG. Newly generated
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 */
#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 CONSTANT_ADDRESS_P(X) \
(GET_CODE (X) == LABEL_REF || GET_CODE (X) == SYMBOL_REF \
|| GET_CODE (X) == CONST_INT || GET_CODE (X) == CONST \
|| GET_CODE (X) == HIGH)
#define CONSTANT_ADDRESS_P(X) \
((GET_CODE (X) == LABEL_REF || GET_CODE (X) == SYMBOL_REF \
|| GET_CODE (X) == CONST_INT || GET_CODE (X) == CONST \
|| GET_CODE (X) == HIGH) \
&& LEGITIMATE_CONSTANT_P (X))
/* Nonzero if the constant value X is a legitimate general operand.
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
#define PCREL_GENERAL_OPERAND_OK 0

View File

@ -627,10 +627,12 @@
;; In both the PIC and non-PIC cases the patterns generated will
;; matched by the next define_insn.
(define_expand "movsi"
[(set (match_operand:SI 0 "nonimmediate_operand" "")
(match_operand:SI 1 "general_operand" ""))]
[(set (match_operand:SI 0 "" "")
(match_operand:SI 1 "" ""))]
""
{
rtx tmp, base, offset;
if (flag_pic && !TARGET_PCREL && symbolic_operand (operands[1], SImode))
{
/* The source is an address which requires PIC relocation.
@ -651,6 +653,18 @@
operands[0] = gen_rtx_MEM (SImode,
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

View File

@ -65,3 +65,9 @@ Boston, MA 02110-1301, USA. */
/* -msep-data is the default PIC mode on this target. */
#define DRIVER_SELF_SPECS \
"%{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;
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_symbolic_address_p (enum mips_symbol_type, enum machine_mode);
static bool mips_classify_address (struct mips_address_info *, rtx,
@ -1292,58 +1290,6 @@ mips_classify_symbol (rtx x)
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
the same way as a bare symbol. If it is, store the type of the
symbol in *SYMBOL_TYPE. */
@ -1351,9 +1297,9 @@ mips_offset_within_object_p (rtx symbol, HOST_WIDE_INT offset)
bool
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))
*symbol_type = UNSPEC_ADDRESS_TYPE (x);
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
return false;
if (offset == 0)
if (offset == const0_rtx)
return true;
/* 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
in case the 32-bit value X + OFFSET has a different sign from X. */
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. */
return true;
@ -1397,15 +1343,15 @@ mips_symbolic_constant_p (rtx x, enum mips_symbol_type *symbol_type)
case SYMBOL_SMALL_DATA:
/* 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. */
return mips_offset_within_object_p (x, offset);
return offset_within_block_p (x, INTVAL (offset));
case SYMBOL_GOT_LOCAL:
case SYMBOL_GOTOFF_PAGE:
/* The linker should provide enough local GOT entries for a
16-bit offset. Larger offsets may lead to GOT overflow. */
return SMALL_OPERAND (offset);
return SMALL_INT (offset);
case SYMBOL_GOT_GLOBAL:
case SYMBOL_GOTOFF_GLOBAL:
@ -1595,8 +1541,7 @@ mips_tls_symbol_ref_1 (rtx *x, void *data ATTRIBUTE_UNUSED)
static bool
mips_cannot_force_const_mem (rtx x)
{
rtx base;
HOST_WIDE_INT offset;
rtx base, offset;
if (!TARGET_MIPS16)
{
@ -1612,8 +1557,8 @@ mips_cannot_force_const_mem (rtx x)
if (GET_CODE (x) == CONST_INT)
return true;
mips_split_const (x, &base, &offset);
if (symbolic_operand (base, VOIDmode) && SMALL_OPERAND (offset))
split_const (x, &base, &offset);
if (symbolic_operand (base, VOIDmode) && SMALL_INT (offset))
return true;
}
@ -1800,7 +1745,7 @@ mips_const_insns (rtx x)
{
struct mips_integer_op codes[MIPS_MAX_INTEGER_OPS];
enum mips_symbol_type symbol_type;
HOST_WIDE_INT offset;
rtx offset;
switch (GET_CODE (x))
{
@ -1841,16 +1786,16 @@ mips_const_insns (rtx x)
/* Otherwise try splitting the constant into a base and offset.
16-bit offsets can be added using an extra addiu. Larger offsets
must be calculated separately and then added to the base. */
mips_split_const (x, &x, &offset);
split_const (x, &x, &offset);
if (offset != 0)
{
int n = mips_const_insns (x);
if (n != 0)
{
if (SMALL_OPERAND (offset))
if (SMALL_INT (offset))
return n + 1;
else
return n + 1 + mips_build_integer (codes, offset);
return n + 1 + mips_build_integer (codes, INTVAL (offset));
}
}
return 0;
@ -1949,13 +1894,14 @@ mips_split_symbol (rtx temp, rtx addr)
rtx
mips_unspec_address (rtx address, enum mips_symbol_type symbol_type)
{
rtx base;
HOST_WIDE_INT offset;
rtx base, offset;
mips_split_const (address, &base, &offset);
split_const (address, &base, &offset);
base = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, base),
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
mips_legitimize_const_move (enum machine_mode mode, rtx dest, rtx src)
{
rtx base;
HOST_WIDE_INT offset;
rtx base, offset;
/* Split moves of big integers into smaller pieces. */
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
and then add in the offset. This is usually better than forcing
the constant into memory, at least in non-mips16 code. */
mips_split_const (src, &base, &offset);
split_const (src, &base, &offset);
if (!TARGET_MIPS16
&& offset != 0
&& (!no_new_pseudos || SMALL_OPERAND (offset)))
&& offset != const0_rtx
&& (!no_new_pseudos || SMALL_INT (offset)))
{
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;
}
@ -5709,16 +5654,15 @@ print_operand_reloc (FILE *file, rtx op, const char **relocs)
{
enum mips_symbol_type symbol_type;
const char *p;
rtx base;
HOST_WIDE_INT offset;
rtx base, offset;
if (!mips_symbolic_constant_p (op, &symbol_type) || relocs[symbol_type] == 0)
fatal_insn ("PRINT_OPERAND, invalid operand for relocation", op);
/* 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))
op = plus_constant (UNSPEC_ADDRESS (base), offset);
op = plus_constant (UNSPEC_ADDRESS (base), INTVAL (offset));
fputs (relocs[symbol_type], file);
output_addr_const (file, op);
@ -7640,12 +7584,12 @@ mips_cannot_change_mode_class (enum machine_mode from,
bool
mips_dangerous_for_la25_p (rtx x)
{
HOST_WIDE_INT offset;
rtx offset;
if (TARGET_EXPLICIT_RELOCS)
return false;
mips_split_const (x, &x, &offset);
split_const (x, &x, &offset);
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 HOST_WIDE_INT get_integer_term (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 count_occurrences (rtx, rtx, int);
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 "regs.h"
#include "function.h"
#include "tree.h"
/* Information about a subreg of a hard register. */
struct subreg_info
@ -496,6 +497,61 @@ get_related_value (rtx x)
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
zero, we do not count occurrences inside the destination of a SET. */