mirror of
git://gcc.gnu.org/git/gcc.git
synced 2025-02-10 05:59:30 +08:00
i386.c (ix86_output_function_epilogue): New.
* config/i386/i386.c (ix86_output_function_epilogue): New. (TARGET_ASM_FUNCTION_EPILOGUE): New. (pic_label_name): Remove. (pic_labels_used): New. (ix86_asm_file_end): Emit one pc load stub for each register used. (output_set_got): Generate deep pc load to any register. (ix86_select_alt_pic_regnum): New. (ix86_save_reg): Don't save pic register if we can find a valid call-clobbered replacement. (ix86_expand_prologue): If we found a valid replacement, renumber pic_offset_table_rtx. * config/i386/i386.h (PIC_OFFSET_TABLE_REGNUM): Look at pic_offset_table_rtx after reload. (REAL_PIC_OFFSET_TABLE_REGNUM): New. * config/i386/i386.md (set_got): Make insn, not expander. (set_got_nopic, set_got_deep, set_got_nodeep): Remove. From-SVN: r54021
This commit is contained in:
parent
002ff5bc3e
commit
bd09bdeb98
@ -1,3 +1,22 @@
|
||||
2002-05-29 Richard Henderson <rth@redhat.com>
|
||||
|
||||
* config/i386/i386.c (ix86_output_function_epilogue): New.
|
||||
(TARGET_ASM_FUNCTION_EPILOGUE): New.
|
||||
(pic_label_name): Remove.
|
||||
(pic_labels_used): New.
|
||||
(ix86_asm_file_end): Emit one pc load stub for each register used.
|
||||
(output_set_got): Generate deep pc load to any register.
|
||||
(ix86_select_alt_pic_regnum): New.
|
||||
(ix86_save_reg): Don't save pic register if we can find a valid
|
||||
call-clobbered replacement.
|
||||
(ix86_expand_prologue): If we found a valid replacement, renumber
|
||||
pic_offset_table_rtx.
|
||||
* config/i386/i386.h (PIC_OFFSET_TABLE_REGNUM): Look at
|
||||
pic_offset_table_rtx after reload.
|
||||
(REAL_PIC_OFFSET_TABLE_REGNUM): New.
|
||||
* config/i386/i386.md (set_got): Make insn, not expander.
|
||||
(set_got_nopic, set_got_deep, set_got_nodeep): Remove.
|
||||
|
||||
2002-05-29 Richard Henderson <rth@redhat.com>
|
||||
|
||||
* config/i386/i386.c (ix86_compute_frame_layout): Do add bottom
|
||||
|
@ -687,6 +687,7 @@ static int ix86_nsaved_regs PARAMS ((void));
|
||||
static void ix86_emit_save_regs PARAMS ((void));
|
||||
static void ix86_emit_save_regs_using_mov PARAMS ((rtx, HOST_WIDE_INT));
|
||||
static void ix86_emit_restore_regs_using_mov PARAMS ((rtx, int, int));
|
||||
static void ix86_output_function_epilogue PARAMS ((FILE *, HOST_WIDE_INT));
|
||||
static void ix86_set_move_mem_attrs_1 PARAMS ((rtx, rtx, rtx, rtx, rtx));
|
||||
static void ix86_sched_reorder_ppro PARAMS ((rtx *, rtx *));
|
||||
static HOST_WIDE_INT ix86_GOT_alias_set PARAMS ((void));
|
||||
@ -737,6 +738,7 @@ static int ix86_fp_comparison_arithmetics_cost PARAMS ((enum rtx_code code));
|
||||
static int ix86_fp_comparison_fcomi_cost PARAMS ((enum rtx_code code));
|
||||
static int ix86_fp_comparison_sahf_cost PARAMS ((enum rtx_code code));
|
||||
static int ix86_fp_comparison_cost PARAMS ((enum rtx_code code));
|
||||
static unsigned int ix86_select_alt_pic_regnum PARAMS ((void));
|
||||
static int ix86_save_reg PARAMS ((unsigned int, int));
|
||||
static void ix86_compute_frame_layout PARAMS ((struct ix86_frame *));
|
||||
static int ix86_comp_type_attributes PARAMS ((tree, tree));
|
||||
@ -806,6 +808,8 @@ static enum x86_64_reg_class merge_classes PARAMS ((enum x86_64_reg_class,
|
||||
# undef TARGET_ASM_FUNCTION_PROLOGUE
|
||||
# define TARGET_ASM_FUNCTION_PROLOGUE ix86_osf_output_function_prologue
|
||||
#endif
|
||||
#undef TARGET_ASM_FUNCTION_EPILOGUE
|
||||
#define TARGET_ASM_FUNCTION_EPILOGUE ix86_output_function_epilogue
|
||||
|
||||
#undef TARGET_ASM_OPEN_PAREN
|
||||
#define TARGET_ASM_OPEN_PAREN ""
|
||||
@ -3894,7 +3898,7 @@ ix86_setup_frame_addresses ()
|
||||
cfun->machine->accesses_prev_frame = 1;
|
||||
}
|
||||
|
||||
static char pic_label_name[32];
|
||||
static int pic_labels_used;
|
||||
|
||||
/* This function generates code for -fpic that loads %ebx with
|
||||
the return address of the caller and then returns. */
|
||||
@ -3904,48 +3908,28 @@ ix86_asm_file_end (file)
|
||||
FILE *file;
|
||||
{
|
||||
rtx xops[2];
|
||||
int regno;
|
||||
|
||||
if (pic_label_name[0] == 0)
|
||||
return;
|
||||
|
||||
/* ??? Binutils 2.10 and earlier has a linkonce elimination bug related
|
||||
to updating relocations to a section being discarded such that this
|
||||
doesn't work. Ought to detect this at configure time. */
|
||||
#if 0
|
||||
/* The trick here is to create a linkonce section containing the
|
||||
pic label thunk, but to refer to it with an internal label.
|
||||
Because the label is internal, we don't have inter-dso name
|
||||
binding issues on hosts that don't support ".hidden".
|
||||
|
||||
In order to use these macros, however, we must create a fake
|
||||
function decl. */
|
||||
if (targetm.have_named_sections)
|
||||
for (regno = 0; regno < 8; ++regno)
|
||||
{
|
||||
tree decl = build_decl (FUNCTION_DECL,
|
||||
get_identifier ("i686.get_pc_thunk"),
|
||||
error_mark_node);
|
||||
DECL_ONE_ONLY (decl) = 1;
|
||||
(*targetm.asm_out.unique_section) (decl, 0);
|
||||
named_section (decl, NULL);
|
||||
if (! ((pic_labels_used >> regno) & 1))
|
||||
continue;
|
||||
|
||||
text_section ();
|
||||
|
||||
/* This used to call ASM_DECLARE_FUNCTION_NAME() but since it's an
|
||||
internal (non-global) label that's being emitted, it didn't make
|
||||
sense to have .type information for local labels. This caused
|
||||
the SCO OpenServer 5.0.4 ELF assembler grief (why are you giving
|
||||
me debug info for a label that you're declaring non-global?) this
|
||||
was changed to call ASM_OUTPUT_LABEL() instead. */
|
||||
ASM_OUTPUT_INTERNAL_LABEL (file, "LPR", regno);
|
||||
|
||||
xops[0] = gen_rtx_REG (SImode, regno);
|
||||
xops[1] = gen_rtx_MEM (SImode, stack_pointer_rtx);
|
||||
output_asm_insn ("mov{l}\t{%1, %0|%0, %1}", xops);
|
||||
output_asm_insn ("ret", xops);
|
||||
}
|
||||
else
|
||||
#else
|
||||
text_section ();
|
||||
#endif
|
||||
|
||||
/* This used to call ASM_DECLARE_FUNCTION_NAME() but since it's an
|
||||
internal (non-global) label that's being emitted, it didn't make
|
||||
sense to have .type information for local labels. This caused
|
||||
the SCO OpenServer 5.0.4 ELF assembler grief (why are you giving
|
||||
me debug info for a label that you're declaring non-global?) this
|
||||
was changed to call ASM_OUTPUT_LABEL() instead. */
|
||||
|
||||
ASM_OUTPUT_LABEL (file, pic_label_name);
|
||||
|
||||
xops[0] = pic_offset_table_rtx;
|
||||
xops[1] = gen_rtx_MEM (SImode, stack_pointer_rtx);
|
||||
output_asm_insn ("mov{l}\t{%1, %0|%0, %1}", xops);
|
||||
output_asm_insn ("ret", xops);
|
||||
}
|
||||
|
||||
/* Emit code for the SET_GOT patterns. */
|
||||
@ -3976,10 +3960,11 @@ output_set_got (dest)
|
||||
}
|
||||
else
|
||||
{
|
||||
if (! pic_label_name[0])
|
||||
ASM_GENERATE_INTERNAL_LABEL (pic_label_name, "LPR", 0);
|
||||
char pic_label_name[32];
|
||||
ASM_GENERATE_INTERNAL_LABEL (pic_label_name, "LPR", REGNO (dest));
|
||||
pic_labels_used |= 1 << REGNO (dest);
|
||||
|
||||
xops[2] = gen_rtx_SYMBOL_REF (Pmode, pic_label_name);
|
||||
xops[2] = gen_rtx_SYMBOL_REF (Pmode, ggc_strdup (pic_label_name));
|
||||
xops[2] = gen_rtx_MEM (QImode, xops[2]);
|
||||
output_asm_insn ("call\t%X2", xops);
|
||||
}
|
||||
@ -4005,17 +3990,39 @@ gen_push (arg)
|
||||
arg);
|
||||
}
|
||||
|
||||
/* Return >= 0 if there is an unused call-clobbered register available
|
||||
for the entire function. */
|
||||
|
||||
static unsigned int
|
||||
ix86_select_alt_pic_regnum ()
|
||||
{
|
||||
if (current_function_is_leaf && !current_function_profile)
|
||||
{
|
||||
int i;
|
||||
for (i = 2; i >= 0; --i)
|
||||
if (!regs_ever_live[i])
|
||||
return i;
|
||||
}
|
||||
|
||||
return INVALID_REGNUM;
|
||||
}
|
||||
|
||||
/* Return 1 if we need to save REGNO. */
|
||||
static int
|
||||
ix86_save_reg (regno, maybe_eh_return)
|
||||
unsigned int regno;
|
||||
int maybe_eh_return;
|
||||
{
|
||||
if (regno == PIC_OFFSET_TABLE_REGNUM
|
||||
&& (regs_ever_live[regno]
|
||||
if (pic_offset_table_rtx
|
||||
&& regno == REAL_PIC_OFFSET_TABLE_REGNUM
|
||||
&& (regs_ever_live[REAL_PIC_OFFSET_TABLE_REGNUM]
|
||||
|| current_function_profile
|
||||
|| current_function_calls_eh_return))
|
||||
return 1;
|
||||
{
|
||||
if (ix86_select_alt_pic_regnum () != INVALID_REGNUM)
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (current_function_calls_eh_return && maybe_eh_return)
|
||||
{
|
||||
@ -4236,9 +4243,7 @@ void
|
||||
ix86_expand_prologue ()
|
||||
{
|
||||
rtx insn;
|
||||
int pic_reg_used = (PIC_OFFSET_TABLE_REGNUM != INVALID_REGNUM
|
||||
&& (regs_ever_live[PIC_OFFSET_TABLE_REGNUM]
|
||||
|| current_function_profile));
|
||||
bool pic_reg_used;
|
||||
struct ix86_frame frame;
|
||||
int use_mov = 0;
|
||||
HOST_WIDE_INT allocate;
|
||||
@ -4317,6 +4322,19 @@ ix86_expand_prologue ()
|
||||
SUBTARGET_PROLOGUE;
|
||||
#endif
|
||||
|
||||
pic_reg_used = false;
|
||||
if (pic_offset_table_rtx
|
||||
&& (regs_ever_live[REAL_PIC_OFFSET_TABLE_REGNUM]
|
||||
|| current_function_profile))
|
||||
{
|
||||
unsigned int alt_pic_reg_used = ix86_select_alt_pic_regnum ();
|
||||
|
||||
if (alt_pic_reg_used != INVALID_REGNUM)
|
||||
REGNO (pic_offset_table_rtx) = alt_pic_reg_used;
|
||||
|
||||
pic_reg_used = true;
|
||||
}
|
||||
|
||||
if (pic_reg_used)
|
||||
{
|
||||
insn = emit_insn (gen_set_got (pic_offset_table_rtx));
|
||||
@ -4522,6 +4540,17 @@ ix86_expand_epilogue (style)
|
||||
else
|
||||
emit_jump_insn (gen_return_internal ());
|
||||
}
|
||||
|
||||
/* Reset from the function's potential modifications. */
|
||||
|
||||
static void
|
||||
ix86_output_function_epilogue (file, size)
|
||||
FILE *file ATTRIBUTE_UNUSED;
|
||||
HOST_WIDE_INT size ATTRIBUTE_UNUSED;
|
||||
{
|
||||
if (pic_offset_table_rtx)
|
||||
REGNO (pic_offset_table_rtx) = REAL_PIC_OFFSET_TABLE_REGNUM;
|
||||
}
|
||||
|
||||
/* Extract the parts of an RTL expression that is a valid memory address
|
||||
for an instruction. Return 0 if the structure of the address is
|
||||
|
@ -1086,9 +1086,18 @@ do { \
|
||||
/* Register to hold the addressing base for position independent
|
||||
code access to data items. We don't use PIC pointer for 64bit
|
||||
mode. Define the regnum to dummy value to prevent gcc from
|
||||
pessimizing code dealing with EBX. */
|
||||
#define PIC_OFFSET_TABLE_REGNUM \
|
||||
(TARGET_64BIT || !flag_pic ? INVALID_REGNUM : 3)
|
||||
pessimizing code dealing with EBX.
|
||||
|
||||
To avoid clobbering a call-saved register unnecessarily, we renumber
|
||||
the pic register when possible. The change is visible after the
|
||||
prologue has been emitted. */
|
||||
|
||||
#define REAL_PIC_OFFSET_TABLE_REGNUM 3
|
||||
|
||||
#define PIC_OFFSET_TABLE_REGNUM \
|
||||
(TARGET_64BIT || !flag_pic ? INVALID_REGNUM \
|
||||
: reload_completed ? REGNO (pic_offset_table_rtx) \
|
||||
: REAL_PIC_OFFSET_TABLE_REGNUM)
|
||||
|
||||
/* Register in which address to store a structure value
|
||||
arrives in the function. On the 386, the prologue
|
||||
|
@ -13137,32 +13137,7 @@
|
||||
""
|
||||
"ix86_expand_prologue (); DONE;")
|
||||
|
||||
(define_expand "set_got"
|
||||
[(parallel [(set (match_operand:SI 0 "register_operand" "")
|
||||
(unspec:SI [(const_int 0)] UNSPEC_SET_GOT))
|
||||
(clobber (reg:CC 17))])]
|
||||
"!TARGET_64BIT"
|
||||
"")
|
||||
|
||||
(define_insn "*set_got_nopic"
|
||||
[(set (match_operand:SI 0 "register_operand" "=r")
|
||||
(unspec:SI [(const_int 0)] UNSPEC_SET_GOT))
|
||||
(clobber (reg:CC 17))]
|
||||
"!TARGET_64BIT && !flag_pic"
|
||||
{ return output_set_got (operands[0]); }
|
||||
[(set_attr "type" "multi")
|
||||
(set_attr "length" "11")])
|
||||
|
||||
(define_insn "*set_got_deep"
|
||||
[(set (match_operand:SI 0 "register_operand" "=b")
|
||||
(unspec:SI [(const_int 0)] UNSPEC_SET_GOT))
|
||||
(clobber (reg:CC 17))]
|
||||
"!TARGET_64BIT && TARGET_DEEP_BRANCH_PREDICTION"
|
||||
{ return output_set_got (operands[0]); }
|
||||
[(set_attr "type" "multi")
|
||||
(set_attr "length" "11")])
|
||||
|
||||
(define_insn "*set_got_nodeep"
|
||||
(define_insn "set_got"
|
||||
[(set (match_operand:SI 0 "register_operand" "=r")
|
||||
(unspec:SI [(const_int 0)] UNSPEC_SET_GOT))
|
||||
(clobber (reg:CC 17))]
|
||||
|
Loading…
Reference in New Issue
Block a user