re PR target/42601 (Simplify code to address function static variables with option -fpic)
PR target/42601 * config/arm/arm.c (arm_pic_static_addr): New function. (legitimize_pic_address): Call arm_pic_static_addr when it detects a static symbol. (arm_output_addr_const_extra): Output expression for new pattern. * config/arm/arm.md (UNSPEC_SYMBOL_OFFSET): New unspec symbol. From-SVN: r158189
This commit is contained in:
parent
52c1d580dd
commit
85c9bcd418
|
@ -1,3 +1,12 @@
|
|||
2010-04-10 Wei Guozhi <carrot@google.com>
|
||||
|
||||
PR target/42601
|
||||
* config/arm/arm.c (arm_pic_static_addr): New function.
|
||||
(legitimize_pic_address): Call arm_pic_static_addr when it detects
|
||||
a static symbol.
|
||||
(arm_output_addr_const_extra): Output expression for new pattern.
|
||||
* config/arm/arm.md (UNSPEC_SYMBOL_OFFSET): New unspec symbol.
|
||||
|
||||
2010-04-10 Bernd Schmidt <bernd.schmidt@codesourcery.com>
|
||||
|
||||
* ira-costs.c (record_reg_classes): Ignore alternatives that are
|
||||
|
|
|
@ -224,6 +224,7 @@ static bool arm_can_eliminate (const int, const int);
|
|||
static void arm_asm_trampoline_template (FILE *);
|
||||
static void arm_trampoline_init (rtx, tree, rtx);
|
||||
static rtx arm_trampoline_adjust_address (rtx);
|
||||
static rtx arm_pic_static_addr (rtx orig, rtx reg);
|
||||
|
||||
|
||||
/* Table of machine attributes. */
|
||||
|
@ -4905,29 +4906,16 @@ legitimize_pic_address (rtx orig, enum machine_mode mode, rtx reg)
|
|||
{
|
||||
rtx pic_ref, address;
|
||||
rtx insn;
|
||||
int subregs = 0;
|
||||
|
||||
/* If this function doesn't have a pic register, create one now. */
|
||||
require_pic_register ();
|
||||
|
||||
if (reg == 0)
|
||||
{
|
||||
gcc_assert (can_create_pseudo_p ());
|
||||
reg = gen_reg_rtx (Pmode);
|
||||
|
||||
subregs = 1;
|
||||
address = gen_reg_rtx (Pmode);
|
||||
}
|
||||
|
||||
if (subregs)
|
||||
address = gen_reg_rtx (Pmode);
|
||||
else
|
||||
address = reg;
|
||||
|
||||
if (TARGET_32BIT)
|
||||
emit_insn (gen_pic_load_addr_32bit (address, orig));
|
||||
else /* TARGET_THUMB1 */
|
||||
emit_insn (gen_pic_load_addr_thumb1 (address, orig));
|
||||
|
||||
/* VxWorks does not impose a fixed gap between segments; the run-time
|
||||
gap can be different from the object-file gap. We therefore can't
|
||||
use GOTOFF unless we are absolutely sure that the symbol is in the
|
||||
|
@ -4939,16 +4927,23 @@ legitimize_pic_address (rtx orig, enum machine_mode mode, rtx reg)
|
|||
SYMBOL_REF_LOCAL_P (orig)))
|
||||
&& NEED_GOT_RELOC
|
||||
&& !TARGET_VXWORKS_RTP)
|
||||
pic_ref = gen_rtx_PLUS (Pmode, cfun->machine->pic_reg, address);
|
||||
insn = arm_pic_static_addr (orig, reg);
|
||||
else
|
||||
{
|
||||
/* If this function doesn't have a pic register, create one now. */
|
||||
require_pic_register ();
|
||||
|
||||
if (TARGET_32BIT)
|
||||
emit_insn (gen_pic_load_addr_32bit (address, orig));
|
||||
else /* TARGET_THUMB1 */
|
||||
emit_insn (gen_pic_load_addr_thumb1 (address, orig));
|
||||
|
||||
pic_ref = gen_const_mem (Pmode,
|
||||
gen_rtx_PLUS (Pmode, cfun->machine->pic_reg,
|
||||
address));
|
||||
insn = emit_move_insn (reg, pic_ref);
|
||||
}
|
||||
|
||||
insn = emit_move_insn (reg, pic_ref);
|
||||
|
||||
/* Put a REG_EQUAL note on this insn, so that it can be optimized
|
||||
by loop. */
|
||||
set_unique_reg_note (insn, REG_EQUAL, orig);
|
||||
|
@ -5155,6 +5150,43 @@ arm_load_pic_register (unsigned long saved_regs ATTRIBUTE_UNUSED)
|
|||
emit_use (pic_reg);
|
||||
}
|
||||
|
||||
/* Generate code to load the address of a static var when flag_pic is set. */
|
||||
static rtx
|
||||
arm_pic_static_addr (rtx orig, rtx reg)
|
||||
{
|
||||
rtx l1, labelno, offset_rtx, insn;
|
||||
|
||||
gcc_assert (flag_pic);
|
||||
|
||||
/* We use an UNSPEC rather than a LABEL_REF because this label
|
||||
never appears in the code stream. */
|
||||
labelno = GEN_INT (pic_labelno++);
|
||||
l1 = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, labelno), UNSPEC_PIC_LABEL);
|
||||
l1 = gen_rtx_CONST (VOIDmode, l1);
|
||||
|
||||
/* On the ARM the PC register contains 'dot + 8' at the time of the
|
||||
addition, on the Thumb it is 'dot + 4'. */
|
||||
offset_rtx = plus_constant (l1, TARGET_ARM ? 8 : 4);
|
||||
offset_rtx = gen_rtx_UNSPEC (Pmode, gen_rtvec (2, orig, offset_rtx),
|
||||
UNSPEC_SYMBOL_OFFSET);
|
||||
offset_rtx = gen_rtx_CONST (Pmode, offset_rtx);
|
||||
|
||||
if (TARGET_32BIT)
|
||||
{
|
||||
emit_insn (gen_pic_load_addr_32bit (reg, offset_rtx));
|
||||
if (TARGET_ARM)
|
||||
insn = emit_insn (gen_pic_add_dot_plus_eight (reg, reg, labelno));
|
||||
else
|
||||
insn = emit_insn (gen_pic_add_dot_plus_four (reg, reg, labelno));
|
||||
}
|
||||
else /* TARGET_THUMB1 */
|
||||
{
|
||||
emit_insn (gen_pic_load_addr_thumb1 (reg, offset_rtx));
|
||||
insn = emit_insn (gen_pic_add_dot_plus_four (reg, reg, labelno));
|
||||
}
|
||||
|
||||
return insn;
|
||||
}
|
||||
|
||||
/* Return nonzero if X is valid as an ARM state addressing register. */
|
||||
static int
|
||||
|
@ -21325,6 +21357,16 @@ arm_output_addr_const_extra (FILE *fp, rtx x)
|
|||
fputc (')', fp);
|
||||
return TRUE;
|
||||
}
|
||||
else if (GET_CODE (x) == UNSPEC && XINT (x, 1) == UNSPEC_SYMBOL_OFFSET)
|
||||
{
|
||||
output_addr_const (fp, XVECEXP (x, 0, 0));
|
||||
if (GOT_PCREL)
|
||||
fputs ("+.", fp);
|
||||
fputs ("-(", fp);
|
||||
output_addr_const (fp, XVECEXP (x, 0, 1));
|
||||
fputc (')', fp);
|
||||
return TRUE;
|
||||
}
|
||||
else if (GET_CODE (x) == CONST_VECTOR)
|
||||
return arm_emit_vector_const (fp, x);
|
||||
|
||||
|
|
|
@ -101,6 +101,8 @@
|
|||
; a given symbolic address.
|
||||
(UNSPEC_THUMB1_CASESI 25) ; A Thumb1 compressed dispatch-table call.
|
||||
(UNSPEC_RBIT 26) ; rbit operation.
|
||||
(UNSPEC_SYMBOL_OFFSET 27) ; The offset of the start of the symbol from
|
||||
; another symbolic address.
|
||||
]
|
||||
)
|
||||
|
||||
|
|
Loading…
Reference in New Issue