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:
Richard Henderson 2002-05-29 13:54:00 -07:00 committed by Richard Henderson
parent 002ff5bc3e
commit bd09bdeb98
4 changed files with 110 additions and 78 deletions

View File

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

View File

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

View File

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

View File

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