+2002-05-28 Richard Henderson <rth@redhat.com>
+
+ * config/i386/i386.c (ix86_save_reg): Examine regs_ever_live,
+ not current_function_uses_pic_offset_table and
+ current_function_uses_const_pool; examine current_function_profile.
+ (ix86_expand_prologue): Likewise. Add pic_offset_table_rtx as
+ input to blockage if needed.
+ (ix86_expand_call): Do not set current_function_uses_pic_offset_table.
+ (legitimize_pic_address): Likewise. Set regs_ever_live for
+ pic_offset_table_rtx when invoked during reload.
+ * config/i386/i386.h (FINALIZE_PIC): Remove.
+ * config/i386/i386.md (tablejump): Reformat. Do not set
+ current_function_uses_pic_offset_table.
+ (tls_global_dynamic, tls_local_dynamic_base): Likewise.
+ (blockage): Accept anything as operand 0.
+
2002-05-28 Jason Thorpe <thorpej@wasabisystems.com>
* config/netbsd-aout.h (NETBSD_OS_CPP_BUILTINS_AOUT): Define
int maybe_eh_return;
{
if (regno == PIC_OFFSET_TABLE_REGNUM
- && (current_function_uses_pic_offset_table
- || current_function_uses_const_pool
+ && (regs_ever_live[regno]
+ || current_function_profile
|| current_function_calls_eh_return))
return 1;
ix86_expand_prologue ()
{
rtx insn;
- int pic_reg_used = (flag_pic && (current_function_uses_pic_offset_table
- || current_function_uses_const_pool)
- && !TARGET_64BIT);
+ int pic_reg_used = (PIC_OFFSET_TABLE_REGNUM != INVALID_REGNUM
+ && (regs_ever_live[PIC_OFFSET_TABLE_REGNUM]
+ || current_function_profile));
struct ix86_frame frame;
int use_mov = 0;
HOST_WIDE_INT allocate;
{
insn = emit_insn (gen_set_got (pic_offset_table_rtx));
- /* ??? The current_function_uses_pic_offset_table flag is woefully
- inaccurate, as it isn't updated as code gets deleted. Allow the
- thing to be removed. A better solution would be to actually get
- proper liveness for ebx, as then we won't save/restore it too. */
+ /* Even with accurate pre-reload life analysis, we can wind up
+ deleting all references to the pic register after reload.
+ Consider if cross-jumping unifies two sides of a branch
+ controled by a comparison vs the only read from a global.
+ In which case, allow the set_got to be deleted, though we're
+ too late to do anything about the ebx save in the prologue. */
REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_MAYBE_DEAD, const0_rtx, NULL);
}
- /* If we are profiling, make sure no instructions are scheduled before
- the call to mcount. However, if -fpic, the above call will have
- done that. */
- if (current_function_profile && ! pic_reg_used)
- emit_insn (gen_blockage ());
+ /* Prevent function calls from be scheduled before the call to mcount.
+ In the pic_reg_used case, make sure that the got load isn't deleted. */
+ if (current_function_profile)
+ emit_insn (gen_blockage (pic_reg_used ? pic_offset_table_rtx : const0_rtx));
}
/* Emit code to restore saved registers using MOV insns. First register
/* This symbol may be referenced via a displacement from the PIC
base address (@GOTOFF). */
- current_function_uses_pic_offset_table = 1;
+ if (reload_in_progress)
+ regs_ever_live[PIC_OFFSET_TABLE_REGNUM] = 1;
new = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, addr), UNSPEC_GOTOFF);
new = gen_rtx_CONST (Pmode, new);
new = gen_rtx_PLUS (Pmode, pic_offset_table_rtx, new);
{
if (TARGET_64BIT)
{
- current_function_uses_pic_offset_table = 1;
new = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, addr), UNSPEC_GOTPCREL);
new = gen_rtx_CONST (Pmode, new);
new = gen_rtx_MEM (Pmode, new);
/* This symbol must be referenced via a load from the
Global Offset Table (@GOT). */
- current_function_uses_pic_offset_table = 1;
+ if (reload_in_progress)
+ regs_ever_live[PIC_OFFSET_TABLE_REGNUM] = 1;
new = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, addr), UNSPEC_GOT);
new = gen_rtx_CONST (Pmode, new);
new = gen_rtx_PLUS (Pmode, pic_offset_table_rtx, new);
{
if (!TARGET_64BIT)
{
- current_function_uses_pic_offset_table = 1;
+ if (reload_in_progress)
+ regs_ever_live[PIC_OFFSET_TABLE_REGNUM] = 1;
new = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, op0),
UNSPEC_GOTOFF);
new = gen_rtx_PLUS (Pmode, new, op1);
case TLS_MODEL_INITIAL_EXEC:
if (flag_pic)
{
- current_function_uses_pic_offset_table = 1;
+ if (reload_in_progress)
+ regs_ever_live[PIC_OFFSET_TABLE_REGNUM] = 1;
pic = pic_offset_table_rtx;
}
else
if (! TARGET_64BIT && flag_pic
&& GET_CODE (XEXP (fnaddr, 0)) == SYMBOL_REF
&& ! SYMBOL_REF_FLAG (XEXP (fnaddr, 0)))
- {
- current_function_uses_pic_offset_table = 1;
- use_reg (&use, pic_offset_table_rtx);
- }
+ use_reg (&use, pic_offset_table_rtx);
if (TARGET_64BIT && INTVAL (callarg2) >= 0)
{
(use (label_ref (match_operand 1 "" "")))])]
""
{
- /* In PIC mode, the table entries are stored GOT-relative. Convert
- the relative address to an absolute address. */
+ /* In PIC mode, the table entries are stored GOT (32-bit) or PC (64-bit)
+ relative. Convert the relative address to an absolute address. */
if (flag_pic)
{
+ rtx op0, op1;
+ enum rtx_code code;
+
if (TARGET_64BIT)
- operands[0] = expand_simple_binop (Pmode, PLUS, operands[0],
- gen_rtx_LABEL_REF (Pmode, operands[1]),
- NULL_RTX, 0,
- OPTAB_DIRECT);
+ {
+ code = PLUS;
+ op0 = operands[0];
+ op1 = gen_rtx_LABEL_REF (Pmode, operands[1]);
+ }
else if (HAVE_AS_GOTOFF_IN_DATA)
{
- operands[0] = expand_simple_binop (Pmode, PLUS, operands[0],
- pic_offset_table_rtx, NULL_RTX,
- 1, OPTAB_DIRECT);
- current_function_uses_pic_offset_table = 1;
+ code = PLUS;
+ op0 = operands[0];
+ op1 = pic_offset_table_rtx;
}
else
{
- operands[0] = expand_simple_binop (Pmode, MINUS, pic_offset_table_rtx,
- operands[0], NULL_RTX, 1,
- OPTAB_DIRECT);
- current_function_uses_pic_offset_table = 1;
+ code = MINUS;
+ op0 = pic_offset_table_rtx;
+ op1 = operands[0];
}
+
+ operands[0] = expand_simple_binop (Pmode, code, op0, op1, NULL_RTX, 1,
+ OPTAB_DIRECT);
}
})
registers we stored in the result block. We avoid problems by
claiming that all hard registers are used and clobbered at this
point. */
- emit_insn (gen_blockage ());
+ emit_insn (gen_blockage (const0_rtx));
DONE;
})
;; all of memory. This blocks insns from being moved across this point.
(define_insn "blockage"
- [(unspec_volatile [(const_int 0)] UNSPECV_BLOCKAGE)]
+ [(unspec_volatile [(match_operand 0 "" "")] UNSPECV_BLOCKAGE)]
""
""
[(set_attr "length" "0")])
{
if (!flag_pic)
abort ();
- current_function_uses_pic_offset_table = 1;
operands[2] = pic_offset_table_rtx;
operands[3] = ix86_tls_get_addr ();
})
{
if (!flag_pic)
abort ();
- current_function_uses_pic_offset_table = 1;
operands[1] = pic_offset_table_rtx;
operands[2] = ix86_tls_get_addr ();
})