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:
Richard Earnshaw 2006-01-17 20:22:19 +00:00 committed by Richard Earnshaw
parent a5a9792182
commit 020a403534
4 changed files with 104 additions and 32 deletions

View File

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

View File

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

View File

@ -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. */

View File

@ -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;
}")