mirror of
git://gcc.gnu.org/git/gcc.git
synced 2025-02-26 01:45:46 +08:00
re PR target/592 ([ARM/Thumb] Poor choice of PIC register)
PR target/592 PR middle-end/11135 * arm.h (struct machine_function): Add pic_reg. * arm.c (arm_pic_register): Make unsigned. (arm_override_options): Only set arm_pic_register if TARGET_SINGLE_PIC_BASE. (use_return_insn): Only test for a pic register if it is fixed. (arm_compute_save_reg0_reg12_mask): Likewise. (thumb_compute_save_reg_mask): Likewise. (legitimate_pic_operand): Factor out some known invariants. (legitimize_pic_address): If we don't have a fixed pic register, then set up a pseudo in the function entry sequence. Handle the pic base being in a pseudo. (arm_load_pic_register): Handle the pic register being in a pseudo. (arm_expand_prologue): Only set up the pic register if it is fixed. (thumb_expand_prologue): Likewise. * arm.md (pic_load_addr_based): Handle the pic base being a pseudo. (pic_load_addr_based_insn): Likewise. (builtin_setjmp_receiver): Don't restore the pic base if it isn't fixed. From-SVN: r109839
This commit is contained in:
parent
a5a9792182
commit
020a403534
@ -1,3 +1,26 @@
|
||||
2006-01-17 Richard Earnshaw <rearnsha@arm.com>
|
||||
|
||||
PR target/592
|
||||
PR middle-end/11135
|
||||
* arm.h (struct machine_function): Add pic_reg.
|
||||
* arm.c (arm_pic_register): Make unsigned.
|
||||
(arm_override_options): Only set arm_pic_register if
|
||||
TARGET_SINGLE_PIC_BASE.
|
||||
(use_return_insn): Only test for a pic register if it is fixed.
|
||||
(arm_compute_save_reg0_reg12_mask): Likewise.
|
||||
(thumb_compute_save_reg_mask): Likewise.
|
||||
(legitimate_pic_operand): Factor out some known invariants.
|
||||
(legitimize_pic_address): If we don't have a fixed pic register,
|
||||
then set up a pseudo in the function entry sequence. Handle the
|
||||
pic base being in a pseudo.
|
||||
(arm_load_pic_register): Handle the pic register being in a pseudo.
|
||||
(arm_expand_prologue): Only set up the pic register if it is fixed.
|
||||
(thumb_expand_prologue): Likewise.
|
||||
* arm.md (pic_load_addr_based): Handle the pic base being a pseudo.
|
||||
(pic_load_addr_based_insn): Likewise.
|
||||
(builtin_setjmp_receiver): Don't restore the pic base if it isn't
|
||||
fixed.
|
||||
|
||||
2006-01-18 Ben Elliston <bje@au.ibm.com>
|
||||
|
||||
* config/rs6000/rs6000.c (rs6000_hard_regno_mode_ok): Reject
|
||||
|
@ -1,6 +1,6 @@
|
||||
/* Output routines for GCC for ARM.
|
||||
Copyright (C) 1991, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001,
|
||||
2002, 2003, 2004, 2005 Free Software Foundation, Inc.
|
||||
2002, 2003, 2004, 2005, 2006 Free Software Foundation, Inc.
|
||||
Contributed by Pieter `Tiggr' Schoenmakers (rcpieter@win.tue.nl)
|
||||
and Martin Simmons (@harleqn.co.uk).
|
||||
More major hacks by Richard Earnshaw (rearnsha@arm.com).
|
||||
@ -524,7 +524,7 @@ int arm_cpp_interwork = 0;
|
||||
enum machine_mode output_memory_reference_mode;
|
||||
|
||||
/* The register number to be used for the PIC offset register. */
|
||||
int arm_pic_register = INVALID_REGNUM;
|
||||
unsigned arm_pic_register = INVALID_REGNUM;
|
||||
|
||||
/* Set to 1 when a return insn is output, this means that the epilogue
|
||||
is not needed. */
|
||||
@ -1096,7 +1096,7 @@ arm_override_options (void)
|
||||
|
||||
/* If stack checking is disabled, we can use r10 as the PIC register,
|
||||
which keeps r9 available. */
|
||||
if (flag_pic)
|
||||
if (flag_pic && TARGET_SINGLE_PIC_BASE)
|
||||
arm_pic_register = TARGET_APCS_STACK ? 9 : 10;
|
||||
|
||||
if (TARGET_APCS_FLOAT)
|
||||
@ -1547,7 +1547,9 @@ use_return_insn (int iscond, rtx sibling)
|
||||
if (saved_int_regs != 0 && saved_int_regs != (1 << LR_REGNUM))
|
||||
return 0;
|
||||
|
||||
if (flag_pic && regs_ever_live[PIC_OFFSET_TABLE_REGNUM])
|
||||
if (flag_pic
|
||||
&& arm_pic_register != INVALID_REGNUM
|
||||
&& regs_ever_live[PIC_OFFSET_TABLE_REGNUM])
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -3171,16 +3173,14 @@ arm_function_ok_for_sibcall (tree decl, tree exp ATTRIBUTE_UNUSED)
|
||||
/* Addressing mode support functions. */
|
||||
|
||||
/* Return nonzero if X is a legitimate immediate operand when compiling
|
||||
for PIC. */
|
||||
for PIC. We know that X satisfies CONSTANT_P and flag_pic is true. */
|
||||
int
|
||||
legitimate_pic_operand_p (rtx x)
|
||||
{
|
||||
if (CONSTANT_P (x)
|
||||
&& flag_pic
|
||||
&& (GET_CODE (x) == SYMBOL_REF
|
||||
|| (GET_CODE (x) == CONST
|
||||
&& GET_CODE (XEXP (x, 0)) == PLUS
|
||||
&& GET_CODE (XEXP (XEXP (x, 0), 0)) == SYMBOL_REF)))
|
||||
if (GET_CODE (x) == SYMBOL_REF
|
||||
|| (GET_CODE (x) == CONST
|
||||
&& GET_CODE (XEXP (x, 0)) == PLUS
|
||||
&& GET_CODE (XEXP (XEXP (x, 0), 0)) == SYMBOL_REF))
|
||||
return 0;
|
||||
|
||||
return 1;
|
||||
@ -3198,6 +3198,49 @@ legitimize_pic_address (rtx orig, enum machine_mode mode, rtx reg)
|
||||
rtx insn;
|
||||
int subregs = 0;
|
||||
|
||||
/* If this function doesn't have a pic register, create one now.
|
||||
A lot of the logic here is made obscure by the fact that this
|
||||
routine gets called as part of the rtx cost estimation
|
||||
process. We don't want those calls to affect any assumptions
|
||||
about the real function; and further, we can't call
|
||||
entry_of_function() until we start the real expansion
|
||||
process. */
|
||||
if (!current_function_uses_pic_offset_table)
|
||||
{
|
||||
gcc_assert (!no_new_pseudos);
|
||||
if (arm_pic_register != INVALID_REGNUM)
|
||||
{
|
||||
cfun->machine->pic_reg = gen_rtx_REG (Pmode, arm_pic_register);
|
||||
|
||||
/* Play games to avoid marking the function as needing pic
|
||||
if we are being called as part of the cost-estimation
|
||||
process. */
|
||||
if (!ir_type())
|
||||
current_function_uses_pic_offset_table = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
rtx seq;
|
||||
|
||||
cfun->machine->pic_reg = gen_reg_rtx (Pmode);
|
||||
|
||||
/* Play games to avoid marking the function as needing pic
|
||||
if we are being called as part of the cost-estimation
|
||||
process. */
|
||||
if (!ir_type())
|
||||
{
|
||||
current_function_uses_pic_offset_table = 1;
|
||||
start_sequence ();
|
||||
|
||||
arm_load_pic_register (0UL);
|
||||
|
||||
seq = get_insns ();
|
||||
end_sequence ();
|
||||
emit_insn_after (seq, entry_of_function ());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (reg == 0)
|
||||
{
|
||||
gcc_assert (!no_new_pseudos);
|
||||
@ -3225,17 +3268,16 @@ legitimize_pic_address (rtx orig, enum machine_mode mode, rtx reg)
|
||||
|| (GET_CODE (orig) == SYMBOL_REF &&
|
||||
SYMBOL_REF_LOCAL_P (orig)))
|
||||
&& NEED_GOT_RELOC)
|
||||
pic_ref = gen_rtx_PLUS (Pmode, pic_offset_table_rtx, address);
|
||||
pic_ref = gen_rtx_PLUS (Pmode, cfun->machine->pic_reg, address);
|
||||
else
|
||||
{
|
||||
pic_ref = gen_const_mem (Pmode,
|
||||
gen_rtx_PLUS (Pmode, pic_offset_table_rtx,
|
||||
gen_rtx_PLUS (Pmode, cfun->machine->pic_reg,
|
||||
address));
|
||||
}
|
||||
|
||||
insn = emit_move_insn (reg, pic_ref);
|
||||
#endif
|
||||
current_function_uses_pic_offset_table = 1;
|
||||
/* Put a REG_EQUAL note on this insn, so that it can be optimized
|
||||
by loop. */
|
||||
REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_EQUAL, orig,
|
||||
@ -3247,7 +3289,7 @@ legitimize_pic_address (rtx orig, enum machine_mode mode, rtx reg)
|
||||
rtx base, offset;
|
||||
|
||||
if (GET_CODE (XEXP (orig, 0)) == PLUS
|
||||
&& XEXP (XEXP (orig, 0), 0) == pic_offset_table_rtx)
|
||||
&& XEXP (XEXP (orig, 0), 0) == cfun->machine->pic_reg)
|
||||
return orig;
|
||||
|
||||
if (GET_CODE (XEXP (orig, 0)) == UNSPEC
|
||||
@ -3387,13 +3429,14 @@ arm_load_pic_register (unsigned long saved_regs ATTRIBUTE_UNUSED)
|
||||
|
||||
if (TARGET_ARM)
|
||||
{
|
||||
emit_insn (gen_pic_load_addr_arm (pic_offset_table_rtx, pic_rtx));
|
||||
emit_insn (gen_pic_add_dot_plus_eight (pic_offset_table_rtx,
|
||||
pic_offset_table_rtx, labelno));
|
||||
emit_insn (gen_pic_load_addr_arm (cfun->machine->pic_reg, pic_rtx));
|
||||
emit_insn (gen_pic_add_dot_plus_eight (cfun->machine->pic_reg,
|
||||
cfun->machine->pic_reg, labelno));
|
||||
}
|
||||
else
|
||||
{
|
||||
if (REGNO (pic_offset_table_rtx) > LAST_LO_REGNUM)
|
||||
if (arm_pic_register != INVALID_REGNUM
|
||||
&& REGNO (cfun->machine->pic_reg) > LAST_LO_REGNUM)
|
||||
{
|
||||
/* We will have pushed the pic register, so we should always be
|
||||
able to find a work register. */
|
||||
@ -3403,14 +3446,14 @@ arm_load_pic_register (unsigned long saved_regs ATTRIBUTE_UNUSED)
|
||||
emit_insn (gen_movsi (pic_offset_table_rtx, pic_tmp));
|
||||
}
|
||||
else
|
||||
emit_insn (gen_pic_load_addr_thumb (pic_offset_table_rtx, pic_rtx));
|
||||
emit_insn (gen_pic_add_dot_plus_four (pic_offset_table_rtx,
|
||||
pic_offset_table_rtx, labelno));
|
||||
emit_insn (gen_pic_load_addr_thumb (cfun->machine->pic_reg, pic_rtx));
|
||||
emit_insn (gen_pic_add_dot_plus_four (cfun->machine->pic_reg,
|
||||
cfun->machine->pic_reg, labelno));
|
||||
}
|
||||
|
||||
/* Need to emit this whether or not we obey regdecls,
|
||||
since setjmp/longjmp can cause life info to screw up. */
|
||||
emit_insn (gen_rtx_USE (VOIDmode, pic_offset_table_rtx));
|
||||
emit_insn (gen_rtx_USE (VOIDmode, cfun->machine->pic_reg));
|
||||
#endif /* AOF_ASSEMBLER */
|
||||
}
|
||||
|
||||
@ -3690,7 +3733,7 @@ thumb_legitimate_address_p (enum machine_mode mode, rtx x, int strict_p)
|
||||
/* This is PC relative data before arm_reorg runs. */
|
||||
else if (GET_MODE_SIZE (mode) >= 4 && CONSTANT_P (x)
|
||||
&& GET_CODE (x) == SYMBOL_REF
|
||||
&& CONSTANT_POOL_ADDRESS_P (x) && ! flag_pic)
|
||||
&& CONSTANT_POOL_ADDRESS_P (x) && !flag_pic)
|
||||
return 1;
|
||||
|
||||
/* This is PC relative data after arm_reorg runs. */
|
||||
@ -9173,6 +9216,7 @@ arm_compute_save_reg0_reg12_mask (void)
|
||||
/* Also save the pic base register if necessary. */
|
||||
if (flag_pic
|
||||
&& !TARGET_SINGLE_PIC_BASE
|
||||
&& arm_pic_register != INVALID_REGNUM
|
||||
&& current_function_uses_pic_offset_table)
|
||||
save_reg_mask |= 1 << PIC_OFFSET_TABLE_REGNUM;
|
||||
}
|
||||
@ -9195,6 +9239,7 @@ arm_compute_save_reg0_reg12_mask (void)
|
||||
don't stack it even though it may be live. */
|
||||
if (flag_pic
|
||||
&& !TARGET_SINGLE_PIC_BASE
|
||||
&& arm_pic_register != INVALID_REGNUM
|
||||
&& (regs_ever_live[PIC_OFFSET_TABLE_REGNUM]
|
||||
|| current_function_uses_pic_offset_table))
|
||||
save_reg_mask |= 1 << PIC_OFFSET_TABLE_REGNUM;
|
||||
@ -9312,6 +9357,7 @@ thumb_compute_save_reg_mask (void)
|
||||
|
||||
if (flag_pic
|
||||
&& !TARGET_SINGLE_PIC_BASE
|
||||
&& arm_pic_register != INVALID_REGNUM
|
||||
&& current_function_uses_pic_offset_table)
|
||||
mask |= 1 << PIC_OFFSET_TABLE_REGNUM;
|
||||
|
||||
@ -10822,7 +10868,7 @@ arm_expand_prologue (void)
|
||||
}
|
||||
|
||||
|
||||
if (flag_pic)
|
||||
if (flag_pic && arm_pic_register != INVALID_REGNUM)
|
||||
arm_load_pic_register (0UL);
|
||||
|
||||
/* If we are profiling, make sure no instructions are scheduled before
|
||||
@ -13584,7 +13630,7 @@ thumb_expand_prologue (void)
|
||||
live_regs_mask = thumb_compute_save_reg_mask ();
|
||||
/* Load the pic register before setting the frame pointer,
|
||||
so we can use r7 as a temporary work register. */
|
||||
if (flag_pic)
|
||||
if (flag_pic && arm_pic_register != INVALID_REGNUM)
|
||||
arm_load_pic_register (live_regs_mask);
|
||||
|
||||
if (!frame_pointer_needed && CALLER_INTERWORKING_SLOT_SIZE > 0)
|
||||
|
@ -1,6 +1,6 @@
|
||||
/* Definitions of target machine for GNU compiler, for ARM.
|
||||
Copyright (C) 1991, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000,
|
||||
2001, 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
|
||||
2001, 2002, 2003, 2004, 2005, 2006 Free Software Foundation, Inc.
|
||||
Contributed by Pieter `Tiggr' Schoenmakers (rcpieter@win.tue.nl)
|
||||
and Martin Simmons (@harleqn.co.uk).
|
||||
More major hacks by Richard Earnshaw (rearnsha@arm.com)
|
||||
@ -1519,6 +1519,8 @@ typedef struct machine_function GTY(())
|
||||
/* Records if sibcalls are blocked because an argument
|
||||
register is needed to preserve stack alignment. */
|
||||
int sibcall_blocked;
|
||||
/* The PIC register for this function. This might be a pseudo. */
|
||||
rtx pic_reg;
|
||||
/* Labels for per-function Thumb call-via stubs. One per potential calling
|
||||
register. We can never call via LR or PC. We can call via SP if a
|
||||
trampoline happens to be on the top of the stack. */
|
||||
@ -2206,7 +2208,7 @@ do { \
|
||||
/* We decide which register to use based on the compilation options and
|
||||
the assembler in use; this is more general than the APCS restriction of
|
||||
using sb (r9) all the time. */
|
||||
extern int arm_pic_register;
|
||||
extern unsigned arm_pic_register;
|
||||
|
||||
/* The register number of the register used to address a table of static
|
||||
data addresses in memory. */
|
||||
|
@ -1,6 +1,6 @@
|
||||
;;- Machine description for ARM for GNU compiler
|
||||
;; Copyright 1991, 1993, 1994, 1995, 1996, 1996, 1997, 1998, 1999, 2000,
|
||||
;; 2001, 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
|
||||
;; 2001, 2002, 2003, 2004, 2005, 2006 Free Software Foundation, Inc.
|
||||
;; Contributed by Pieter `Tiggr' Schoenmakers (rcpieter@win.tue.nl)
|
||||
;; and Martin Simmons (@harleqn.co.uk).
|
||||
;; More major hacks by Richard Earnshaw (rearnsha@arm.com).
|
||||
@ -4448,7 +4448,7 @@
|
||||
[(set (match_operand:SI 0 "s_register_operand" "")
|
||||
(unspec:SI [(match_operand 1 "" "") (match_dup 2)] UNSPEC_PIC_SYM))]
|
||||
"TARGET_ARM && flag_pic"
|
||||
"operands[2] = pic_offset_table_rtx;"
|
||||
"operands[2] = cfun->machine->pic_reg;"
|
||||
)
|
||||
|
||||
(define_insn "*pic_load_addr_based_insn"
|
||||
@ -4456,7 +4456,7 @@
|
||||
(unspec:SI [(match_operand 1 "" "")
|
||||
(match_operand 2 "s_register_operand" "r")]
|
||||
UNSPEC_PIC_SYM))]
|
||||
"TARGET_EITHER && flag_pic && operands[2] == pic_offset_table_rtx"
|
||||
"TARGET_EITHER && flag_pic && operands[2] == cfun->machine->pic_reg"
|
||||
"*
|
||||
#ifdef AOF_ASSEMBLER
|
||||
operands[1] = aof_pic_entry (operands[1]);
|
||||
@ -4547,7 +4547,8 @@
|
||||
{
|
||||
/* r3 is clobbered by set/longjmp, so we can use it as a scratch
|
||||
register. */
|
||||
arm_load_pic_register (3);
|
||||
if (arm_pic_register != INVALID_REGNUM)
|
||||
arm_load_pic_register (1UL << 3);
|
||||
DONE;
|
||||
}")
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user