This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
Re: [PATCH, arm] Stack the PIC register for Thumb if PIC is enabled
- From: Nick Clifton <nickc at redhat dot com>
- To: Adam Nemet <anemet at Lnxw dot COM>
- Cc: Richard dot Earnshaw at arm dot com, gcc-patches at gcc dot gnu dot org
- Date: 01 Aug 2002 15:48:27 +0100
- Subject: Re: [PATCH, arm] Stack the PIC register for Thumb if PIC is enabled
- References: <200207311232.NAA07048@cam-mail2.cambridge.arm.com><hcvg6v5ald.fsf@anemet1.lynx.com>
Hi Adam,
> In the merged ARM-Thumb backend
> call_used_regs[PIC_OFFSET_TABLE_REGNUM] == 1. When producing the
> prologue/epilogue the ARM part special-cases the PIC register so
> that it gets stacked properly. Here is the patch for the Thumb
> part.
>
> The patch is the first of a series of patches (mostly binutils) where
> I will attempt to make Thumb shared libs work.
>
> 2002-07-09 Adam Nemet <anemet@lnxw.com>
>
> * config/arm/arm.c (thumb_unexpanded_epilogue): Stack the PIC
> register.
> (thumb_expand_prologue): Likewise.
> (thumb_output_function_prologue): Likewise.
> * config/arm/arm.h (THUMB_INITIAL_ELIMINATION_OFFSET): Account for
> the additional push of the PIC register.
I think that this patch would be better if you moved the entire test
for a thumb register being pushed into a macro and then just used the
macro throughtout arm.[ch]. See the attached reworked patch for an
example.
Using a macro has several advantages:
* It will be easier to update the test in the future.
* It eliminates discrepancies in different functions which need to
decide if a register will be stacked. For example the current
implementation of THUMB_INITIAL_ELIMINATION_OFFSET does not take
into account "!(TARGET_SINGLE_PIC_BASE && ((reg) == arm_pic_register))"
* It reduces source code size and makes the code easier to read.
What do you think ?
Cheers
Nick
Index: gcc/config/arm/arm.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/arm/arm.h,v
retrieving revision 1.154
diff -c -3 -p -w -r1.154 arm.h
*** gcc/config/arm/arm.h 17 Jul 2002 09:54:11 -0000 1.154
--- gcc/config/arm/arm.h 1 Aug 2002 14:38:59 -0000
*************** typedef struct
*** 1622,1627 ****
--- 1622,1633 ----
((TO) == THUMB_HARD_FRAME_POINTER_REGNUM && TARGET_ARM) ? 0 : \
1)
+ #define THUMB_REG_PUSHED_P(reg) \
+ (regs_ever_live [reg] \
+ && (! call_used_regs [reg] \
+ || (flag_pic && (reg) == PIC_OFFSET_TABLE_REGNUM)) \
+ && !(TARGET_SINGLE_PIC_BASE && ((reg) == arm_pic_register)))
+
/* Define the offset between two registers, one to be eliminated, and the
other its replacement, at the start of a routine. */
#define ARM_INITIAL_ELIMINATION_OFFSET(FROM, TO, OFFSET) \
*************** typedef struct
*** 1640,1652 ****
int count_regs = 0; \
int regno; \
for (regno = 8; regno < 13; regno ++) \
! if (regs_ever_live[regno] && ! call_used_regs[regno]) \
count_regs ++; \
if (count_regs) \
(OFFSET) += 4 * count_regs; \
count_regs = 0; \
for (regno = 0; regno <= LAST_LO_REGNUM; regno ++) \
! if (regs_ever_live[regno] && ! call_used_regs[regno]) \
count_regs ++; \
if (count_regs || ! leaf_function_p () || thumb_far_jump_used_p (0))\
(OFFSET) += 4 * (count_regs + 1); \
--- 1646,1658 ----
int count_regs = 0; \
int regno; \
for (regno = 8; regno < 13; regno ++) \
! if (THUMB_REG_PUSHED_P (regno)) \
count_regs ++; \
if (count_regs) \
(OFFSET) += 4 * count_regs; \
count_regs = 0; \
for (regno = 0; regno <= LAST_LO_REGNUM; regno ++) \
! if (THUMB_REG_PUSHED_P (regno)) \
count_regs ++; \
if (count_regs || ! leaf_function_p () || thumb_far_jump_used_p (0))\
(OFFSET) += 4 * (count_regs + 1); \
Index: gcc/config/arm/arm.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/arm/arm.c,v
retrieving revision 1.218
diff -c -3 -p -w -r1.218 arm.c
*** gcc/config/arm/arm.c 23 Jul 2002 06:22:02 -0000 1.218
--- gcc/config/arm/arm.c 1 Aug 2002 14:39:01 -0000
*************** thumb_unexpanded_epilogue ()
*** 9912,9927 ****
return "";
for (regno = 0; regno <= LAST_LO_REGNUM; regno++)
! if (regs_ever_live[regno] && !call_used_regs[regno]
! && !(TARGET_SINGLE_PIC_BASE && (regno == arm_pic_register)))
live_regs_mask |= 1 << regno;
for (regno = 8; regno < 13; regno++)
! {
! if (regs_ever_live[regno] && !call_used_regs[regno]
! && !(TARGET_SINGLE_PIC_BASE && (regno == arm_pic_register)))
high_regs_pushed++;
- }
/* The prolog may have pushed some high registers to use as
work registers. eg the testuite file:
--- 9912,9923 ----
return "";
for (regno = 0; regno <= LAST_LO_REGNUM; regno++)
! if (THUMB_REG_PUSHED_P (regno))
live_regs_mask |= 1 << regno;
for (regno = 8; regno < 13; regno++)
! if (THUMB_REG_PUSHED_P (regno))
high_regs_pushed++;
/* The prolog may have pushed some high registers to use as
work registers. eg the testuite file:
*************** thumb_unexpanded_epilogue ()
*** 9966,9973 ****
("no low registers available for popping high registers");
for (next_hi_reg = 8; next_hi_reg < 13; next_hi_reg++)
! if (regs_ever_live[next_hi_reg] && !call_used_regs[next_hi_reg]
! && !(TARGET_SINGLE_PIC_BASE && (next_hi_reg == arm_pic_register)))
break;
while (high_regs_pushed)
--- 9962,9968 ----
("no low registers available for popping high registers");
for (next_hi_reg = 8; next_hi_reg < 13; next_hi_reg++)
! if (THUMB_REG_PUSHED_P (next_hi_reg))
break;
while (high_regs_pushed)
*************** thumb_unexpanded_epilogue ()
*** 9996,10005 ****
regno);
for (next_hi_reg++; next_hi_reg < 13; next_hi_reg++)
! if (regs_ever_live[next_hi_reg]
! && !call_used_regs[next_hi_reg]
! && !(TARGET_SINGLE_PIC_BASE
! && (next_hi_reg == arm_pic_register)))
break;
}
}
--- 9991,9997 ----
regno);
for (next_hi_reg++; next_hi_reg < 13; next_hi_reg++)
! if (THUMB_REG_PUSHED_P (next_hi_reg))
break;
}
}
*************** thumb_expand_prologue ()
*** 10166,10179 ****
been pushed at the start of the prologue and so we can corrupt
it now. */
for (regno = LAST_ARG_REGNUM + 1; regno <= LAST_LO_REGNUM; regno++)
! if (regs_ever_live[regno]
! && !call_used_regs[regno] /* Paranoia */
! && !(TARGET_SINGLE_PIC_BASE && (regno == arm_pic_register))
&& !(frame_pointer_needed
&& (regno == THUMB_HARD_FRAME_POINTER_REGNUM)))
break;
! if (regno > LAST_LO_REGNUM) /* Very unlikely */
{
rtx spare = gen_rtx (REG, SImode, IP_REGNUM);
--- 10158,10169 ----
been pushed at the start of the prologue and so we can corrupt
it now. */
for (regno = LAST_ARG_REGNUM + 1; regno <= LAST_LO_REGNUM; regno++)
! if (THUMB_REG_PUSHED_P (regno)
&& !(frame_pointer_needed
&& (regno == THUMB_HARD_FRAME_POINTER_REGNUM)))
break;
! if (regno > LAST_LO_REGNUM) /* Very unlikely. */
{
rtx spare = gen_rtx (REG, SImode, IP_REGNUM);
*************** thumb_output_function_prologue (f, size)
*** 10323,10330 ****
}
for (regno = 0; regno <= LAST_LO_REGNUM; regno++)
! if (regs_ever_live[regno] && !call_used_regs[regno]
! && !(TARGET_SINGLE_PIC_BASE && (regno == arm_pic_register)))
live_regs_mask |= 1 << regno;
if (live_regs_mask || !leaf_function_p () || thumb_far_jump_used_p (1))
--- 10313,10319 ----
}
for (regno = 0; regno <= LAST_LO_REGNUM; regno++)
! if (THUMB_REG_PUSHED_P (regno))
live_regs_mask |= 1 << regno;
if (live_regs_mask || !leaf_function_p () || thumb_far_jump_used_p (1))
*************** thumb_output_function_prologue (f, size)
*** 10426,10433 ****
for (regno = 8; regno < 13; regno++)
{
! if (regs_ever_live[regno] && !call_used_regs[regno]
! && !(TARGET_SINGLE_PIC_BASE && (regno == arm_pic_register)))
high_regs_pushed++;
}
--- 10415,10421 ----
for (regno = 8; regno < 13; regno++)
{
! if (THUMB_REG_PUSHED_P (regno))
high_regs_pushed++;
}
*************** thumb_output_function_prologue (f, size)
*** 10439,10447 ****
for (next_hi_reg = 12; next_hi_reg > LAST_LO_REGNUM; next_hi_reg--)
{
! if (regs_ever_live[next_hi_reg] && !call_used_regs[next_hi_reg]
! && !(TARGET_SINGLE_PIC_BASE
! && (next_hi_reg == arm_pic_register)))
break;
}
--- 10427,10433 ----
for (next_hi_reg = 12; next_hi_reg > LAST_LO_REGNUM; next_hi_reg--)
{
! if (THUMB_REG_PUSHED_P (next_hi_reg))
break;
}
*************** thumb_output_function_prologue (f, size)
*** 10450,10457 ****
if (pushable_regs == 0)
{
/* Desperation time -- this probably will never happen. */
! if (regs_ever_live[LAST_ARG_REGNUM]
! || !call_used_regs[LAST_ARG_REGNUM])
asm_fprintf (f, "\tmov\t%r, %r\n", IP_REGNUM, LAST_ARG_REGNUM);
mask = 1 << LAST_ARG_REGNUM;
}
--- 10436,10442 ----
if (pushable_regs == 0)
{
/* Desperation time -- this probably will never happen. */
! if (THUMB_REG_PUSHED_P (LAST_ARG_REGNUM))
asm_fprintf (f, "\tmov\t%r, %r\n", IP_REGNUM, LAST_ARG_REGNUM);
mask = 1 << LAST_ARG_REGNUM;
}
*************** thumb_output_function_prologue (f, size)
*** 10467,10479 ****
high_regs_pushed--;
if (high_regs_pushed)
for (next_hi_reg--; next_hi_reg > LAST_LO_REGNUM;
next_hi_reg--)
! {
! if (regs_ever_live[next_hi_reg]
! && !call_used_regs[next_hi_reg]
! && !(TARGET_SINGLE_PIC_BASE
! && (next_hi_reg == arm_pic_register)))
break;
}
else
--- 10452,10461 ----
high_regs_pushed--;
if (high_regs_pushed)
+ {
for (next_hi_reg--; next_hi_reg > LAST_LO_REGNUM;
next_hi_reg--)
! if (THUMB_REG_PUSHED_P (next_hi_reg))
break;
}
else
*************** thumb_output_function_prologue (f, size)
*** 10488,10495 ****
}
if (pushable_regs == 0
! && (regs_ever_live[LAST_ARG_REGNUM]
! || !call_used_regs[LAST_ARG_REGNUM]))
asm_fprintf (f, "\tmov\t%r, %r\n", LAST_ARG_REGNUM, IP_REGNUM);
}
}
--- 10470,10476 ----
}
if (pushable_regs == 0
! && (THUMB_REG_PUSHED_P (LAST_ARG_REGNUM)))
asm_fprintf (f, "\tmov\t%r, %r\n", LAST_ARG_REGNUM, IP_REGNUM);
}
}