rs6000.h (ASM_OUTPUT_SPECIAL_POOL_ENTRY_P): All constants of size no larger than a pointer should go in the TOC.
* config/rs6000/rs6000.h (ASM_OUTPUT_SPECIAL_POOL_ENTRY_P): All constants of size no larger than a pointer should go in the TOC. Add 'MODE' parameter. (LEGITIMIZE_RELOAD_ADDRESS): Add MODE parameter to ASM_OUTPUT_SPECIAL_POOL_ENTRY_P. (ASM_OUTPUT_SPECIAL_POOL_ENTRY): Likewise. * config/rs6000/aix.h (SELECT_RTX_SECTION): Likewise. * config/rs6000/netware.h (SELECT_RTX_SECTION): Likewise. * config/rs6000/rs6000.c (constant_pool_expr_1): Likewise. (rs6000_legitimize_address): Likewise. (rs6000_emit_move): Likewise. (rs6000_select_rtx_section): Likewise. (output_toc): Deal properly with outputting small constants like HImode, and SFmode in 32-bit mode, and DFmode in 64-bit mode. * config/rs6000/sysv4.h (ASM_OUTPUT_SPECIAL_POOL_ENTRY_P): Add MODE parameter. Put small constants in the TOC. * config/rs6000/rs6000.c (easy_fp_constant_p): All constants are easy in SImode. (rs6000_emit_move): When reload calls us with an illegitimate address, exit early. Move the change_address calls to one place at the end of the routine. Merge the SImode and DImode expanders. When called by reload to put an integer into a FP register, force it to memory. * config/rs6000/rs6000.c (struct toc_hash_struct): Add 'key_mode' field. (rs6000_hash_constant): Hash mode too. (toc_hash_function): Allow for key_mode. (toc_hash_eq): Structures are different if key_mode differs. (output_toc): Add 'mode' parameter. Save key_mode. * config/rs6000/rs6000.h (ASM_OUTPUT_SPECIAL_POOL_ENTRY): Pass 'mode' parameter. * config/rs6000/rs6000-protos.h (output_toc): Add 'mode' param. From-SVN: r35164
This commit is contained in:
parent
89c01f0e75
commit
a9098fd024
@ -1,5 +1,40 @@
|
||||
2000-07-20 Geoff Keating <geoffk@cygnus.com>
|
||||
|
||||
* config/rs6000/rs6000.h (ASM_OUTPUT_SPECIAL_POOL_ENTRY_P): All
|
||||
constants of size no larger than a pointer should go in the TOC.
|
||||
Add 'MODE' parameter.
|
||||
(LEGITIMIZE_RELOAD_ADDRESS): Add MODE parameter to
|
||||
ASM_OUTPUT_SPECIAL_POOL_ENTRY_P.
|
||||
(ASM_OUTPUT_SPECIAL_POOL_ENTRY): Likewise.
|
||||
* config/rs6000/aix.h (SELECT_RTX_SECTION): Likewise.
|
||||
* config/rs6000/netware.h (SELECT_RTX_SECTION): Likewise.
|
||||
* config/rs6000/rs6000.c (constant_pool_expr_1): Likewise.
|
||||
(rs6000_legitimize_address): Likewise.
|
||||
(rs6000_emit_move): Likewise.
|
||||
(rs6000_select_rtx_section): Likewise.
|
||||
(output_toc): Deal properly with outputting small constants like
|
||||
HImode, and SFmode in 32-bit mode, and DFmode in 64-bit mode.
|
||||
* config/rs6000/sysv4.h (ASM_OUTPUT_SPECIAL_POOL_ENTRY_P): Add
|
||||
MODE parameter. Put small constants in the TOC.
|
||||
|
||||
* config/rs6000/rs6000.c (easy_fp_constant_p): All constants are
|
||||
easy in SImode.
|
||||
(rs6000_emit_move): When reload calls us with an illegitimate
|
||||
address, exit early. Move the change_address calls to one place
|
||||
at the end of the routine. Merge the SImode and DImode expanders.
|
||||
When called by reload to put an integer into a FP register, force
|
||||
it to memory.
|
||||
|
||||
* config/rs6000/rs6000.c (struct toc_hash_struct): Add 'key_mode'
|
||||
field.
|
||||
(rs6000_hash_constant): Hash mode too.
|
||||
(toc_hash_function): Allow for key_mode.
|
||||
(toc_hash_eq): Structures are different if key_mode differs.
|
||||
(output_toc): Add 'mode' parameter. Save key_mode.
|
||||
* config/rs6000/rs6000.h (ASM_OUTPUT_SPECIAL_POOL_ENTRY):
|
||||
Pass 'mode' parameter.
|
||||
* config/rs6000/rs6000-protos.h (output_toc): Add 'mode' param.
|
||||
|
||||
* config/rs6000/rs6000.c (output_toc): Use RS6000_OUTPUT_BASENAME
|
||||
for vtable references.
|
||||
|
||||
|
@ -100,14 +100,14 @@ Boston, MA 02111-1307, USA. */
|
||||
/* Define the options for the binder: Start text at 512, align all segments
|
||||
to 512 bytes, and warn if there is text relocation.
|
||||
|
||||
The -bhalt:4 option supposedly changes the level at which ld will abort,
|
||||
The -bhalt:4 option supposedly changes the level at which ld will abort,
|
||||
but it also suppresses warnings about multiply defined symbols and is
|
||||
used by the AIX cc command. So we use it here.
|
||||
|
||||
-bnodelcsect undoes a poor choice of default relating to multiply-defined
|
||||
csects. See AIX documentation for more information about this.
|
||||
|
||||
-bM:SRE tells the linker that the output file is Shared REusable. Note
|
||||
-bM:SRE tells the linker that the output file is Shared REusable. Note
|
||||
that to actually build a shared library you will also need to specify an
|
||||
export list with the -Wl,-bE option. */
|
||||
|
||||
@ -233,11 +233,11 @@ toc_section () \
|
||||
However, if this is being placed in the TOC it must be output as a
|
||||
toc entry. */
|
||||
|
||||
#define SELECT_RTX_SECTION(MODE, X) \
|
||||
{ if (ASM_OUTPUT_SPECIAL_POOL_ENTRY_P (X)) \
|
||||
toc_section (); \
|
||||
else \
|
||||
read_only_private_data_section (); \
|
||||
#define SELECT_RTX_SECTION(MODE, X) \
|
||||
{ if (ASM_OUTPUT_SPECIAL_POOL_ENTRY_P (X, MODE)) \
|
||||
toc_section (); \
|
||||
else \
|
||||
read_only_private_data_section (); \
|
||||
}
|
||||
|
||||
/* Indicate that jump tables go in the text section. */
|
||||
|
@ -162,11 +162,11 @@ toc_section () \
|
||||
/* Use the TOC section for TOC entries. */
|
||||
|
||||
#undef SELECT_RTX_SECTION
|
||||
#define SELECT_RTX_SECTION(MODE, X) \
|
||||
{ if (ASM_OUTPUT_SPECIAL_POOL_ENTRY_P (X)) \
|
||||
toc_section (); \
|
||||
else \
|
||||
const_section (); \
|
||||
#define SELECT_RTX_SECTION(MODE, X) \
|
||||
{ if (ASM_OUTPUT_SPECIAL_POOL_ENTRY_P (X, MODE)) \
|
||||
toc_section (); \
|
||||
else \
|
||||
const_section (); \
|
||||
}
|
||||
|
||||
/* How to renumber registers for dbx and gdb. */
|
||||
|
@ -86,7 +86,7 @@ extern int ccr_bit PARAMS ((rtx, int));
|
||||
extern void print_operand PARAMS ((FILE *, rtx, int));
|
||||
extern void print_operand_address PARAMS ((FILE *, rtx));
|
||||
extern char * output_cbranch PARAMS ((rtx, const char *, int, rtx));
|
||||
extern void output_toc PARAMS ((FILE *, rtx, int));
|
||||
extern void output_toc PARAMS ((FILE *, rtx, int, enum machine_mode));
|
||||
extern int rs6000_adjust_cost PARAMS ((rtx, rtx, rtx, int));
|
||||
extern int rs6000_adjust_priority PARAMS ((rtx, int));
|
||||
extern void rs6000_initialize_trampoline PARAMS ((rtx, rtx, rtx));
|
||||
|
@ -119,6 +119,7 @@ static int rs6000_sr_alias_set;
|
||||
static void rs6000_add_gc_roots PARAMS ((void));
|
||||
static int num_insns_constant_wide PARAMS ((HOST_WIDE_INT));
|
||||
static rtx expand_block_move_mem PARAMS ((enum machine_mode, rtx, rtx));
|
||||
static void rs6000_maybe_dead PARAMS ((rtx));
|
||||
static void rs6000_emit_stack_tie PARAMS ((void));
|
||||
static void rs6000_frame_related PARAMS ((rtx, rtx, HOST_WIDE_INT, rtx, rtx));
|
||||
static void rs6000_emit_allocate_stack PARAMS ((HOST_WIDE_INT, int));
|
||||
@ -890,6 +891,8 @@ easy_fp_constant (op, mode)
|
||||
&& GET_CODE (op) == CONST_DOUBLE && CONST_DOUBLE_LOW (op) == 0)
|
||||
|| (num_insns_constant (op, DImode) <= 2));
|
||||
|
||||
else if (mode == SImode)
|
||||
return 1;
|
||||
else
|
||||
abort ();
|
||||
}
|
||||
@ -1339,7 +1342,7 @@ constant_pool_expr_1 (op, have_sym, have_toc)
|
||||
case SYMBOL_REF:
|
||||
if (CONSTANT_POOL_ADDRESS_P (op))
|
||||
{
|
||||
if (ASM_OUTPUT_SPECIAL_POOL_ENTRY_P (get_pool_constant (op)))
|
||||
if (ASM_OUTPUT_SPECIAL_POOL_ENTRY_P (get_pool_constant (op), Pmode))
|
||||
{
|
||||
*have_sym = 1;
|
||||
return 1;
|
||||
@ -1451,7 +1454,7 @@ rs6000_legitimize_address (x, oldx, mode)
|
||||
}
|
||||
else if (TARGET_TOC
|
||||
&& CONSTANT_POOL_EXPR_P (x)
|
||||
&& ASM_OUTPUT_SPECIAL_POOL_ENTRY_P (get_pool_constant (x)))
|
||||
&& ASM_OUTPUT_SPECIAL_POOL_ENTRY_P (get_pool_constant (x), Pmode))
|
||||
{
|
||||
return create_TOC_reference (x);
|
||||
}
|
||||
@ -1491,7 +1494,7 @@ rs6000_emit_move (dest, source, mode)
|
||||
|
||||
if (! no_new_pseudos && GET_CODE (operands[0]) != REG)
|
||||
operands[1] = force_reg (mode, operands[1]);
|
||||
|
||||
|
||||
if (mode == SFmode && ! TARGET_POWERPC && TARGET_HARD_FLOAT
|
||||
&& GET_CODE (operands[0]) == MEM)
|
||||
{
|
||||
@ -1516,13 +1519,16 @@ rs6000_emit_move (dest, source, mode)
|
||||
}
|
||||
}
|
||||
|
||||
/* Only a tiny bit of handling for CONSTANT_P_RTX is necessary. */
|
||||
if (GET_CODE (operands[1]) == CONSTANT_P_RTX)
|
||||
/* Handle the case where reload calls us with an invalid address;
|
||||
and the case of CONSTANT_P_RTX. */
|
||||
if (! general_operand (operands[1], mode)
|
||||
|| ! nonimmediate_operand (operands[0], mode)
|
||||
|| GET_CODE (operands[1]) == CONSTANT_P_RTX)
|
||||
{
|
||||
emit_insn (gen_rtx_SET (VOIDmode, operands[0], operands[1]));
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
/* FIXME: In the long term, this switch statement should go away
|
||||
and be replaced by a sequence of tests based on things like
|
||||
mode == Pmode. */
|
||||
@ -1532,53 +1538,45 @@ rs6000_emit_move (dest, source, mode)
|
||||
case QImode:
|
||||
if (CONSTANT_P (operands[1])
|
||||
&& GET_CODE (operands[1]) != CONST_INT)
|
||||
{
|
||||
operands[1] = force_const_mem (mode, operands[1]);
|
||||
if (! memory_address_p (mode, XEXP (operands[1], 0))
|
||||
&& ! reload_in_progress)
|
||||
operands[1] = change_address (operands[1], mode,
|
||||
XEXP (operands[1], 0));
|
||||
}
|
||||
operands[1] = force_const_mem (mode, operands[1]);
|
||||
break;
|
||||
|
||||
case DFmode:
|
||||
case SFmode:
|
||||
if (CONSTANT_P (operands[1])
|
||||
&& ! easy_fp_constant (operands[1], mode))
|
||||
{
|
||||
operands[1] = force_const_mem (mode, operands[1]);
|
||||
if (! memory_address_p (mode, XEXP (operands[1], 0))
|
||||
&& ! reload_in_progress)
|
||||
operands[1] = change_address (operands[1], mode,
|
||||
XEXP (operands[1], 0));
|
||||
}
|
||||
operands[1] = force_const_mem (mode, operands[1]);
|
||||
break;
|
||||
|
||||
case SImode:
|
||||
case DImode:
|
||||
/* Use default pattern for address of ELF small data */
|
||||
if (TARGET_ELF
|
||||
&& mode == Pmode
|
||||
&& (DEFAULT_ABI == ABI_V4 || DEFAULT_ABI == ABI_SOLARIS)
|
||||
&& (GET_CODE (operands[1]) == SYMBOL_REF || GET_CODE (operands[1]) == CONST)
|
||||
&& small_data_operand (operands[1], SImode))
|
||||
&& (GET_CODE (operands[1]) == SYMBOL_REF
|
||||
|| GET_CODE (operands[1]) == CONST)
|
||||
&& small_data_operand (operands[1], mode))
|
||||
{
|
||||
emit_insn (gen_rtx_SET (VOIDmode, operands[0], operands[1]));
|
||||
return;
|
||||
}
|
||||
|
||||
if ((DEFAULT_ABI == ABI_V4 || DEFAULT_ABI == ABI_SOLARIS)
|
||||
&& flag_pic == 1 && got_operand (operands[1], SImode))
|
||||
&& mode == Pmode && mode == SImode
|
||||
&& flag_pic == 1 && got_operand (operands[1], mode))
|
||||
{
|
||||
emit_insn (gen_movsi_got (operands[0], operands[1]));
|
||||
return;
|
||||
}
|
||||
|
||||
if (TARGET_ELF && TARGET_NO_TOC && ! TARGET_64BIT
|
||||
&& ! flag_pic
|
||||
if (TARGET_ELF && TARGET_NO_TOC && ! flag_pic
|
||||
&& mode == Pmode
|
||||
&& CONSTANT_P (operands[1])
|
||||
&& GET_CODE (operands[1]) != HIGH
|
||||
&& GET_CODE (operands[1]) != CONST_INT)
|
||||
{
|
||||
rtx target = (no_new_pseudos ? operands[0] : gen_reg_rtx (SImode));
|
||||
rtx target = (no_new_pseudos ? operands[0] : gen_reg_rtx (mode));
|
||||
|
||||
/* If this is a function address on -mcall-aixdesc,
|
||||
convert it to the address of the descriptor. */
|
||||
@ -1603,70 +1601,30 @@ rs6000_emit_move (dest, source, mode)
|
||||
return;
|
||||
}
|
||||
|
||||
if (CONSTANT_P (operands[1])
|
||||
&& GET_CODE (operands[1]) != CONST_INT
|
||||
&& GET_CODE (operands[1]) != HIGH
|
||||
&& ! LEGITIMATE_CONSTANT_POOL_ADDRESS_P (operands[1])
|
||||
&& ! TOC_RELATIVE_EXPR_P (operands[1]))
|
||||
/* If this is a SYMBOL_REF that refers to a constant pool entry,
|
||||
and we have put it in the TOC, we just need to make a TOC-relative
|
||||
reference to it. */
|
||||
if (TARGET_TOC
|
||||
&& GET_CODE (operands[1]) == SYMBOL_REF
|
||||
&& CONSTANT_POOL_EXPR_P (operands[1])
|
||||
&& ASM_OUTPUT_SPECIAL_POOL_ENTRY_P (get_pool_constant (operands[1]),
|
||||
get_pool_mode (operands[1])))
|
||||
{
|
||||
/* Emit a USE operation so that the constant isn't deleted if
|
||||
expensive optimizations are turned on because nobody
|
||||
references it. This should only be done for operands that
|
||||
contain SYMBOL_REFs with CONSTANT_POOL_ADDRESS_P set.
|
||||
This should not be done for operands that contain LABEL_REFs.
|
||||
For now, we just handle the obvious case. */
|
||||
if (GET_CODE (operands[1]) != LABEL_REF)
|
||||
emit_insn (gen_rtx_USE (VOIDmode, operands[1]));
|
||||
|
||||
/* If we are to limit the number of things we put in the TOC and
|
||||
this is a symbol plus a constant we can add in one insn,
|
||||
just put the symbol in the TOC and add the constant. Don't do
|
||||
this if reload is in progress. */
|
||||
if (GET_CODE (operands[1]) == CONST
|
||||
&& TARGET_NO_SUM_IN_TOC && ! reload_in_progress
|
||||
&& GET_CODE (XEXP (operands[1], 0)) == PLUS
|
||||
&& add_operand (XEXP (XEXP (operands[1], 0), 1), SImode)
|
||||
&& (GET_CODE (XEXP (XEXP (operands[1], 0), 0)) == LABEL_REF
|
||||
|| GET_CODE (XEXP (XEXP (operands[1], 0), 0)) == SYMBOL_REF)
|
||||
&& ! side_effects_p (operands[0]))
|
||||
{
|
||||
rtx sym = force_const_mem (SImode, XEXP (XEXP (operands[1], 0), 0));
|
||||
rtx other = XEXP (XEXP (operands[1], 0), 1);
|
||||
|
||||
emit_insn (gen_addsi3 (operands[0], force_reg (SImode, sym), other));
|
||||
return;
|
||||
}
|
||||
|
||||
operands[1] = force_const_mem (SImode, operands[1]);
|
||||
|
||||
if (TARGET_TOC
|
||||
&& CONSTANT_POOL_EXPR_P (XEXP (operands[1], 0))
|
||||
&& ASM_OUTPUT_SPECIAL_POOL_ENTRY_P (get_pool_constant (
|
||||
XEXP (operands[1], 0))))
|
||||
{
|
||||
operands[1] = gen_rtx_MEM (SImode,
|
||||
create_TOC_reference (XEXP (operands[1], 0)));
|
||||
MEM_ALIAS_SET (operands[1]) = get_TOC_alias_set ();
|
||||
RTX_UNCHANGING_P (operands[1]) = 1;
|
||||
}
|
||||
|
||||
if (! memory_address_p (SImode, XEXP (operands[1], 0))
|
||||
&& ! reload_in_progress)
|
||||
operands[1] = change_address (operands[1], SImode,
|
||||
XEXP (operands[1], 0));
|
||||
operands[1] = create_TOC_reference (operands[1]);
|
||||
}
|
||||
break;
|
||||
|
||||
case DImode:
|
||||
if (TARGET_64BIT
|
||||
&& CONSTANT_P (operands[1])
|
||||
#if HOST_BITS_PER_WIDE_INT == 32
|
||||
&& GET_CODE (operands[1]) != CONST_INT
|
||||
#endif
|
||||
&& ! easy_fp_constant (operands[1], DImode)
|
||||
&& ! LEGITIMATE_CONSTANT_POOL_ADDRESS_P (operands[1])
|
||||
&& ! TOC_RELATIVE_EXPR_P (operands[1]))
|
||||
else if (mode == Pmode
|
||||
&& CONSTANT_P (operands[1])
|
||||
&& (((HOST_BITS_PER_WIDE_INT != 32
|
||||
|| GET_CODE (operands[1]) != CONST_INT)
|
||||
&& ! easy_fp_constant (operands[1], mode))
|
||||
|| (GET_CODE (operands[0]) == REG
|
||||
&& FP_REGNO_P (REGNO (operands[0]))))
|
||||
&& GET_CODE (operands[1]) != HIGH
|
||||
&& ! LEGITIMATE_CONSTANT_POOL_ADDRESS_P (operands[1])
|
||||
&& ! TOC_RELATIVE_EXPR_P (operands[1]))
|
||||
{
|
||||
int special_constant_p = 0;
|
||||
|
||||
/* Emit a USE operation so that the constant isn't deleted if
|
||||
expensive optimizations are turned on because nobody
|
||||
references it. This should only be done for operands that
|
||||
@ -1683,39 +1641,46 @@ rs6000_emit_move (dest, source, mode)
|
||||
if (GET_CODE (operands[1]) == CONST
|
||||
&& TARGET_NO_SUM_IN_TOC && ! reload_in_progress
|
||||
&& GET_CODE (XEXP (operands[1], 0)) == PLUS
|
||||
&& add_operand (XEXP (XEXP (operands[1], 0), 1), DImode)
|
||||
&& add_operand (XEXP (XEXP (operands[1], 0), 1), mode)
|
||||
&& (GET_CODE (XEXP (XEXP (operands[1], 0), 0)) == LABEL_REF
|
||||
|| GET_CODE (XEXP (XEXP (operands[1], 0), 0)) == SYMBOL_REF)
|
||||
&& ! side_effects_p (operands[0]))
|
||||
{
|
||||
rtx sym = force_const_mem (DImode, XEXP (XEXP (operands[1], 0), 0));
|
||||
rtx sym = force_const_mem (mode, XEXP (XEXP (operands[1], 0), 0));
|
||||
rtx other = XEXP (XEXP (operands[1], 0), 1);
|
||||
|
||||
emit_insn (gen_adddi3 (operands[0], force_reg (DImode, sym), other));
|
||||
sym = force_reg (mode, sym);
|
||||
if (mode == SImode)
|
||||
emit_insn (gen_addsi3 (operands[0], sym, other));
|
||||
else
|
||||
emit_insn (gen_adddi3 (operands[0], sym, other));
|
||||
return;
|
||||
}
|
||||
|
||||
operands[1] = force_const_mem (DImode, operands[1]);
|
||||
operands[1] = force_const_mem (mode, operands[1]);
|
||||
|
||||
if (TARGET_TOC
|
||||
&& CONSTANT_POOL_EXPR_P (XEXP (operands[1], 0))
|
||||
&& ASM_OUTPUT_SPECIAL_POOL_ENTRY_P (get_pool_constant (
|
||||
XEXP (operands[1], 0))))
|
||||
&& CONSTANT_POOL_EXPR_P (XEXP (operands[1], 0)))
|
||||
{
|
||||
operands[1] = gen_rtx_MEM (DImode,
|
||||
create_TOC_reference (XEXP (operands[1], 0)));
|
||||
rtx constant;
|
||||
enum machine_mode cmode;
|
||||
|
||||
constant = get_pool_constant (XEXP (operands[1], 0));
|
||||
cmode = get_pool_mode (XEXP (operands[1], 0));
|
||||
special_constant_p =
|
||||
ASM_OUTPUT_SPECIAL_POOL_ENTRY_P (constant, cmode);
|
||||
}
|
||||
|
||||
if (special_constant_p)
|
||||
{
|
||||
operands[1] = gen_rtx_MEM (mode,
|
||||
create_TOC_reference (XEXP (operands[1], 0)));
|
||||
MEM_ALIAS_SET (operands[1]) = get_TOC_alias_set ();
|
||||
RTX_UNCHANGING_P (operands[1]) = 1;
|
||||
}
|
||||
|
||||
if (! memory_address_p (DImode, XEXP (operands[1], 0))
|
||||
&& ! reload_in_progress)
|
||||
operands[1] = change_address (operands[1], DImode,
|
||||
XEXP (operands[1], 0));
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
|
||||
case TImode:
|
||||
if (GET_CODE (operands[0]) == MEM
|
||||
&& GET_CODE (XEXP (operands[0], 0)) != REG
|
||||
@ -1734,6 +1699,15 @@ rs6000_emit_move (dest, source, mode)
|
||||
abort ();
|
||||
}
|
||||
|
||||
/* Above, we may have called force_const_mem which may have returned
|
||||
an invalid address. If we can, fix this up; otherwise, reload will
|
||||
have to deal with it. */
|
||||
if (GET_CODE (operands[1]) == MEM
|
||||
&& ! memory_address_p (mode, XEXP (operands[1], 0))
|
||||
&& ! reload_in_progress)
|
||||
operands[1] = change_address (operands[1], mode,
|
||||
XEXP (operands[1], 0));
|
||||
|
||||
emit_insn (gen_rtx_SET (VOIDmode, operands[0], operands[1]));
|
||||
}
|
||||
|
||||
@ -6309,6 +6283,7 @@ struct toc_hash_struct
|
||||
/* `key' will satisfy CONSTANT_P; in fact, it will satisfy
|
||||
ASM_OUTPUT_SPECIAL_POOL_ENTRY_P. */
|
||||
rtx key;
|
||||
enum machine_mode key_mode;
|
||||
int labelno;
|
||||
};
|
||||
|
||||
@ -6320,7 +6295,7 @@ static unsigned
|
||||
rs6000_hash_constant (k)
|
||||
rtx k;
|
||||
{
|
||||
unsigned result = GET_CODE (k);
|
||||
unsigned result = (GET_CODE (k) << 3) ^ GET_MODE (k);
|
||||
const char *format = GET_RTX_FORMAT (GET_CODE (k));
|
||||
int flen = strlen (format);
|
||||
int fidx;
|
||||
@ -6377,8 +6352,9 @@ static unsigned
|
||||
toc_hash_function (hash_entry)
|
||||
const void * hash_entry;
|
||||
{
|
||||
return rs6000_hash_constant (((const struct toc_hash_struct *)
|
||||
hash_entry)->key);
|
||||
const struct toc_hash_struct *thc =
|
||||
(const struct toc_hash_struct *) hash_entry;
|
||||
return rs6000_hash_constant (thc->key) ^ thc->key_mode;
|
||||
}
|
||||
|
||||
/* Compare H1 and H2 for equivalence. */
|
||||
@ -6391,6 +6367,10 @@ toc_hash_eq (h1, h2)
|
||||
rtx r1 = ((const struct toc_hash_struct *) h1)->key;
|
||||
rtx r2 = ((const struct toc_hash_struct *) h2)->key;
|
||||
|
||||
if (((const struct toc_hash_struct *) h1)->key_mode
|
||||
!= ((const struct toc_hash_struct *) h2)->key_mode)
|
||||
return 0;
|
||||
|
||||
/* Gotcha: One of these const_doubles will be in memory.
|
||||
The other may be on the constant-pool chain.
|
||||
So rtx_equal_p will think they are different... */
|
||||
@ -6453,10 +6433,11 @@ toc_hash_mark_table (vht)
|
||||
being written. */
|
||||
|
||||
void
|
||||
output_toc (file, x, labelno)
|
||||
output_toc (file, x, labelno, mode)
|
||||
FILE *file;
|
||||
rtx x;
|
||||
int labelno;
|
||||
enum machine_mode mode;
|
||||
{
|
||||
char buf[256];
|
||||
const char *name = buf;
|
||||
@ -6479,6 +6460,7 @@ output_toc (file, x, labelno)
|
||||
|
||||
h = ggc_alloc (sizeof (*h));
|
||||
h->key = x;
|
||||
h->key_mode = mode;
|
||||
h->labelno = labelno;
|
||||
|
||||
found = htab_find_slot (toc_hash_table, h, 1);
|
||||
@ -6501,7 +6483,7 @@ output_toc (file, x, labelno)
|
||||
aligned properly when strict alignment is on. */
|
||||
if (GET_CODE (x) == CONST_DOUBLE
|
||||
&& STRICT_ALIGNMENT
|
||||
&& GET_MODE (x) == DFmode
|
||||
&& GET_MODE_BITSIZE (mode) >= 64
|
||||
&& ! (TARGET_NO_FP_IN_TOC && ! TARGET_MINIMAL_TOC)) {
|
||||
ASM_OUTPUT_ALIGN (file, 3);
|
||||
}
|
||||
@ -6511,8 +6493,7 @@ output_toc (file, x, labelno)
|
||||
/* Handle FP constants specially. Note that if we have a minimal
|
||||
TOC, things we put here aren't actually in the TOC, so we can allow
|
||||
FP constants. */
|
||||
if (GET_CODE (x) == CONST_DOUBLE && GET_MODE (x) == DFmode
|
||||
&& ! (TARGET_NO_FP_IN_TOC && ! TARGET_MINIMAL_TOC))
|
||||
if (GET_CODE (x) == CONST_DOUBLE && GET_MODE (x) == DFmode)
|
||||
{
|
||||
REAL_VALUE_TYPE rv;
|
||||
long k[2];
|
||||
@ -6539,8 +6520,7 @@ output_toc (file, x, labelno)
|
||||
return;
|
||||
}
|
||||
}
|
||||
else if (GET_CODE (x) == CONST_DOUBLE && GET_MODE (x) == SFmode
|
||||
&& ! (TARGET_NO_FP_IN_TOC && ! TARGET_MINIMAL_TOC))
|
||||
else if (GET_CODE (x) == CONST_DOUBLE && GET_MODE (x) == SFmode)
|
||||
{
|
||||
REAL_VALUE_TYPE rv;
|
||||
long l;
|
||||
@ -6566,8 +6546,7 @@ output_toc (file, x, labelno)
|
||||
}
|
||||
}
|
||||
else if (GET_MODE (x) == VOIDmode
|
||||
&& (GET_CODE (x) == CONST_INT || GET_CODE (x) == CONST_DOUBLE)
|
||||
&& ! (TARGET_NO_FP_IN_TOC && ! TARGET_MINIMAL_TOC))
|
||||
&& (GET_CODE (x) == CONST_INT || GET_CODE (x) == CONST_DOUBLE))
|
||||
{
|
||||
HOST_WIDE_INT low;
|
||||
HOST_WIDE_INT high;
|
||||
@ -6590,6 +6569,18 @@ output_toc (file, x, labelno)
|
||||
}
|
||||
#endif
|
||||
|
||||
/* TOC entries are always Pmode-sized, but since this
|
||||
is a bigendian machine then if we're putting smaller
|
||||
integer constants in the TOC we have to pad them.
|
||||
(This is still a win over putting the constants in
|
||||
a separate constant pool, because then we'd have
|
||||
to have both a TOC entry _and_ the actual constant.) */
|
||||
if (POINTER_SIZE < GET_MODE_BITSIZE (mode))
|
||||
abort ();/* It would be easy to make this work, but it doesn't now. */
|
||||
if (mode != Pmode)
|
||||
lshift_double (low, high, POINTER_SIZE - GET_MODE_BITSIZE (mode),
|
||||
POINTER_SIZE, &low, &high, 0);
|
||||
|
||||
if (TARGET_64BIT)
|
||||
{
|
||||
if (TARGET_MINIMAL_TOC)
|
||||
@ -7191,10 +7182,10 @@ rs6000_longcall_ref (call_ref)
|
||||
|
||||
void
|
||||
rs6000_select_rtx_section (mode, x)
|
||||
enum machine_mode mode ATTRIBUTE_UNUSED;
|
||||
enum machine_mode mode;
|
||||
rtx x;
|
||||
{
|
||||
if (ASM_OUTPUT_SPECIAL_POOL_ENTRY_P (x))
|
||||
if (ASM_OUTPUT_SPECIAL_POOL_ENTRY_P (x, mode))
|
||||
toc_section ();
|
||||
else
|
||||
const_section ();
|
||||
@ -7219,7 +7210,7 @@ rs6000_select_section (decl, reloc)
|
||||
else
|
||||
data_section ();
|
||||
}
|
||||
else if (TREE_CODE (decl) == VAR_DECL || TREE_CODE (decl) == CONSTRUCTOR)
|
||||
else if (TREE_CODE (decl) == VAR_DECL)
|
||||
{
|
||||
if ((flag_pic && reloc)
|
||||
|| ! TREE_READONLY (decl)
|
||||
|
@ -1934,55 +1934,55 @@ typedef struct rs6000_args
|
||||
register by splitting the addend across an addiu/addis and the mem insn.
|
||||
This cuts number of extra insns needed from 3 to 1. */
|
||||
|
||||
#define LEGITIMIZE_RELOAD_ADDRESS(X,MODE,OPNUM,TYPE,IND_LEVELS,WIN) \
|
||||
do { \
|
||||
/* We must recognize output that we have already generated ourselves. */ \
|
||||
if (GET_CODE (X) == PLUS \
|
||||
&& GET_CODE (XEXP (X, 0)) == PLUS \
|
||||
&& GET_CODE (XEXP (XEXP (X, 0), 0)) == REG \
|
||||
&& GET_CODE (XEXP (XEXP (X, 0), 1)) == CONST_INT \
|
||||
&& GET_CODE (XEXP (X, 1)) == CONST_INT) \
|
||||
{ \
|
||||
push_reload (XEXP (X, 0), NULL_RTX, &XEXP (X, 0), NULL_PTR, \
|
||||
BASE_REG_CLASS, GET_MODE (X), VOIDmode, 0, 0, \
|
||||
OPNUM, TYPE); \
|
||||
goto WIN; \
|
||||
} \
|
||||
if (GET_CODE (X) == PLUS \
|
||||
&& GET_CODE (XEXP (X, 0)) == REG \
|
||||
&& REGNO (XEXP (X, 0)) < FIRST_PSEUDO_REGISTER \
|
||||
&& REG_MODE_OK_FOR_BASE_P (XEXP (X, 0), MODE) \
|
||||
&& GET_CODE (XEXP (X, 1)) == CONST_INT) \
|
||||
{ \
|
||||
HOST_WIDE_INT val = INTVAL (XEXP (X, 1)); \
|
||||
HOST_WIDE_INT low = ((val & 0xffff) ^ 0x8000) - 0x8000; \
|
||||
unsigned HOST_WIDE_INT high \
|
||||
= (((val - low) & 0xffffffffu) ^ 0x80000000u) - 0x80000000u; \
|
||||
\
|
||||
/* Check for 32-bit overflow. */ \
|
||||
if (high + low != val) \
|
||||
break; \
|
||||
\
|
||||
/* Reload the high part into a base reg; leave the low part \
|
||||
in the mem directly. */ \
|
||||
\
|
||||
X = gen_rtx_PLUS (GET_MODE (X), \
|
||||
gen_rtx_PLUS (GET_MODE (X), XEXP (X, 0), \
|
||||
GEN_INT (high)), \
|
||||
GEN_INT (low)); \
|
||||
\
|
||||
push_reload (XEXP (X, 0), NULL_RTX, &XEXP (X, 0), NULL_PTR, \
|
||||
BASE_REG_CLASS, GET_MODE (X), VOIDmode, 0, 0, \
|
||||
OPNUM, TYPE); \
|
||||
goto WIN; \
|
||||
} \
|
||||
else if (TARGET_TOC \
|
||||
&& CONSTANT_POOL_EXPR_P (X) \
|
||||
&& ASM_OUTPUT_SPECIAL_POOL_ENTRY_P (get_pool_constant (X))) \
|
||||
{ \
|
||||
(X) = create_TOC_reference (X); \
|
||||
goto WIN; \
|
||||
} \
|
||||
#define LEGITIMIZE_RELOAD_ADDRESS(X,MODE,OPNUM,TYPE,IND_LEVELS,WIN) \
|
||||
do { \
|
||||
/* We must recognize output that we have already generated ourselves. */ \
|
||||
if (GET_CODE (X) == PLUS \
|
||||
&& GET_CODE (XEXP (X, 0)) == PLUS \
|
||||
&& GET_CODE (XEXP (XEXP (X, 0), 0)) == REG \
|
||||
&& GET_CODE (XEXP (XEXP (X, 0), 1)) == CONST_INT \
|
||||
&& GET_CODE (XEXP (X, 1)) == CONST_INT) \
|
||||
{ \
|
||||
push_reload (XEXP (X, 0), NULL_RTX, &XEXP (X, 0), NULL_PTR, \
|
||||
BASE_REG_CLASS, GET_MODE (X), VOIDmode, 0, 0, \
|
||||
OPNUM, TYPE); \
|
||||
goto WIN; \
|
||||
} \
|
||||
if (GET_CODE (X) == PLUS \
|
||||
&& GET_CODE (XEXP (X, 0)) == REG \
|
||||
&& REGNO (XEXP (X, 0)) < FIRST_PSEUDO_REGISTER \
|
||||
&& REG_MODE_OK_FOR_BASE_P (XEXP (X, 0), MODE) \
|
||||
&& GET_CODE (XEXP (X, 1)) == CONST_INT) \
|
||||
{ \
|
||||
HOST_WIDE_INT val = INTVAL (XEXP (X, 1)); \
|
||||
HOST_WIDE_INT low = ((val & 0xffff) ^ 0x8000) - 0x8000; \
|
||||
HOST_WIDE_INT high \
|
||||
= (((val - low) & 0xffffffffu) ^ 0x80000000u) - 0x80000000u; \
|
||||
\
|
||||
/* Check for 32-bit overflow. */ \
|
||||
if (high + low != val) \
|
||||
break; \
|
||||
\
|
||||
/* Reload the high part into a base reg; leave the low part \
|
||||
in the mem directly. */ \
|
||||
\
|
||||
X = gen_rtx_PLUS (GET_MODE (X), \
|
||||
gen_rtx_PLUS (GET_MODE (X), XEXP (X, 0), \
|
||||
GEN_INT (high)), \
|
||||
GEN_INT (low)); \
|
||||
\
|
||||
push_reload (XEXP (X, 0), NULL_RTX, &XEXP (X, 0), NULL_PTR, \
|
||||
BASE_REG_CLASS, GET_MODE (X), VOIDmode, 0, 0, \
|
||||
OPNUM, TYPE); \
|
||||
goto WIN; \
|
||||
} \
|
||||
else if (TARGET_TOC \
|
||||
&& CONSTANT_POOL_EXPR_P (X) \
|
||||
&& ASM_OUTPUT_SPECIAL_POOL_ENTRY_P (get_pool_constant (X), MODE)) \
|
||||
{ \
|
||||
(X) = create_TOC_reference (X); \
|
||||
goto WIN; \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
/* Go to LABEL if ADDR (a legitimate address expression)
|
||||
@ -2359,39 +2359,41 @@ extern int rs6000_trunc_used;
|
||||
/* Flag to say the TOC is initialized */
|
||||
extern int toc_initialized;
|
||||
|
||||
/* Return non-zero if this entry is to be written into the constant pool
|
||||
in a special way. We do so if this is a SYMBOL_REF, LABEL_REF or a CONST
|
||||
containing one of them. If -mfp-in-toc (the default), we also do
|
||||
this for floating-point constants. We actually can only do this
|
||||
if the FP formats of the target and host machines are the same, but
|
||||
we can't check that since not every file that uses
|
||||
GO_IF_LEGITIMATE_ADDRESS_P includes real.h. */
|
||||
/* Return non-zero if this entry is to be written into the constant
|
||||
pool in a special way. We do so if this is a SYMBOL_REF, LABEL_REF
|
||||
or a CONST containing one of them. If -mfp-in-toc (the default),
|
||||
we also do this for floating-point constants. We actually can only
|
||||
do this if the FP formats of the target and host machines are the
|
||||
same, but we can't check that since not every file that uses
|
||||
GO_IF_LEGITIMATE_ADDRESS_P includes real.h. We also do this when
|
||||
we can write the entry into the TOC and the entry is not larger
|
||||
than a TOC entry. */
|
||||
|
||||
#define ASM_OUTPUT_SPECIAL_POOL_ENTRY_P(X) \
|
||||
#define ASM_OUTPUT_SPECIAL_POOL_ENTRY_P(X, MODE) \
|
||||
(TARGET_TOC \
|
||||
&& (GET_CODE (X) == SYMBOL_REF \
|
||||
|| (GET_CODE (X) == CONST && GET_CODE (XEXP (X, 0)) == PLUS \
|
||||
&& GET_CODE (XEXP (XEXP (X, 0), 0)) == SYMBOL_REF) \
|
||||
|| GET_CODE (X) == LABEL_REF \
|
||||
|| (! (TARGET_NO_FP_IN_TOC && ! TARGET_MINIMAL_TOC) \
|
||||
&& GET_CODE (X) == CONST_DOUBLE \
|
||||
&& (GET_MODE_CLASS (GET_MODE (X)) == MODE_FLOAT \
|
||||
|| TARGET_POWERPC64))))
|
||||
#if 0
|
||||
&& BITS_PER_WORD == HOST_BITS_PER_INT)))
|
||||
#endif
|
||||
|| (GET_CODE (X) == CONST_INT \
|
||||
&& GET_MODE_BITSIZE (MODE) <= GET_MODE_BITSIZE (Pmode)) \
|
||||
|| (GET_CODE (X) == CONST_DOUBLE \
|
||||
&& (TARGET_POWERPC64 \
|
||||
|| TARGET_MINIMAL_TOC \
|
||||
|| (GET_MODE_CLASS (GET_MODE (X)) == MODE_FLOAT \
|
||||
&& ! TARGET_NO_FP_IN_TOC)))))
|
||||
|
||||
/* Macro to output a special constant pool entry. Go to WIN if we output
|
||||
it. Otherwise, it is written the usual way.
|
||||
|
||||
On the RS/6000, toc entries are handled this way. */
|
||||
|
||||
#define ASM_OUTPUT_SPECIAL_POOL_ENTRY(FILE, X, MODE, ALIGN, LABELNO, WIN) \
|
||||
{ if (ASM_OUTPUT_SPECIAL_POOL_ENTRY_P (X)) \
|
||||
{ \
|
||||
output_toc (FILE, X, LABELNO); \
|
||||
goto WIN; \
|
||||
} \
|
||||
#define ASM_OUTPUT_SPECIAL_POOL_ENTRY(FILE, X, MODE, ALIGN, LABELNO, WIN) \
|
||||
{ if (ASM_OUTPUT_SPECIAL_POOL_ENTRY_P (X, MODE)) \
|
||||
{ \
|
||||
output_toc (FILE, X, LABELNO, MODE); \
|
||||
goto WIN; \
|
||||
} \
|
||||
}
|
||||
|
||||
/* This is how we tell the assembler that two symbols have the same value. */
|
||||
|
@ -563,12 +563,14 @@ fini_section () \
|
||||
allow floating point constants in the TOC if -mrelocatable. */
|
||||
|
||||
#undef ASM_OUTPUT_SPECIAL_POOL_ENTRY_P
|
||||
#define ASM_OUTPUT_SPECIAL_POOL_ENTRY_P(X) \
|
||||
#define ASM_OUTPUT_SPECIAL_POOL_ENTRY_P(X, MODE) \
|
||||
(TARGET_TOC \
|
||||
&& (GET_CODE (X) == SYMBOL_REF \
|
||||
|| (GET_CODE (X) == CONST && GET_CODE (XEXP (X, 0)) == PLUS \
|
||||
&& GET_CODE (XEXP (XEXP (X, 0), 0)) == SYMBOL_REF) \
|
||||
|| GET_CODE (X) == LABEL_REF \
|
||||
|| (GET_CODE (X) == CONST_INT \
|
||||
&& GET_MODE_BITSIZE (MODE) <= GET_MODE_BITSIZE (Pmode)) \
|
||||
|| (!TARGET_NO_FP_IN_TOC \
|
||||
&& !TARGET_RELOCATABLE \
|
||||
&& GET_CODE (X) == CONST_DOUBLE \
|
||||
|
Loading…
x
Reference in New Issue
Block a user