aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJeff Law <law@gcc.gnu.org>1993-01-14 16:45:40 -0700
committerJeff Law <law@gcc.gnu.org>1993-01-14 16:45:40 -0700
commit4971c587de52d0d0c9eaa6d0f27ea862727f9d48 (patch)
treed9cff41e995d11623d1136507376b85c7efef270
parent6627e974145343383c5cfcd3787d0b396059f87c (diff)
downloadgcc-4971c587de52d0d0c9eaa6d0f27ea862727f9d48.zip
gcc-4971c587de52d0d0c9eaa6d0f27ea862727f9d48.tar.gz
gcc-4971c587de52d0d0c9eaa6d0f27ea862727f9d48.tar.bz2
pa.c (output_function_prologue): Combine stack adjustment and first GR save when reasonable to do so.
* pa.c (output_function_prologue): Combine stack adjustment and first GR save when reasonable to do so. (output_function_epilogue): Combine stack adjustment and first GR restore when reasonable to do so. Avoid load/use stall for RP restore in common cases. From-SVN: r3246
-rw-r--r--gcc/config/pa/pa.c89
1 files changed, 79 insertions, 10 deletions
diff --git a/gcc/config/pa/pa.c b/gcc/config/pa/pa.c
index 800a2e0..4c36032 100644
--- a/gcc/config/pa/pa.c
+++ b/gcc/config/pa/pa.c
@@ -1499,6 +1499,7 @@ output_function_prologue (file, size)
extern int frame_pointer_needed;
extern int current_function_returns_struct;
int i, offset;
+ int merge_sp_adjust_with_store = 0;
save_fregs = 0;
local_fsize = size + (size || frame_pointer_needed ? 8 : 0);
@@ -1536,7 +1537,13 @@ output_function_prologue (file, size)
else
/* Used to be abort (); */
{
- if (VAL_14_BITS_P (actual_fsize))
+ if (VAL_14_BITS_P (-actual_fsize)
+ && local_fsize == 0
+ && ! frame_pointer_needed
+ && ! flag_pic
+ && ! profile_flag)
+ merge_sp_adjust_with_store = 1;
+ else if (VAL_14_BITS_P (actual_fsize))
fprintf (file, "\tldo %d(30),30\n", actual_fsize);
else
fprintf (file, "\taddil L'%d,30\n\tldo R'%d(1),30\n",
@@ -1613,12 +1620,32 @@ output_function_prologue (file, size)
for (i = 18, offset = local_fsize - actual_fsize; i >= 5; i--)
if (regs_ever_live[i] && ! call_used_regs[i])
{
- print_stw (file, i, offset, 30); offset += 4;
+ /* If merge_sp_adjust_with_store is nonzero, then we can
+ optimize the first GR save. */
+ if (merge_sp_adjust_with_store == 1)
+ {
+ merge_sp_adjust_with_store = 0;
+ fprintf (file, "\tstwm %d,%d(0,%d)\n", i, -offset, 30);
+ }
+ else
+ print_stw (file, i, offset, 30); offset += 4;
}
if (regs_ever_live[3] && ! call_used_regs[3])
{
- print_stw (file, 3, offset, 30); offset += 4;
+ /* If merge_sp_adjust_with_store is nonzero, then we can
+ optimize the first GR save. */
+ if (merge_sp_adjust_with_store == 1)
+ {
+ merge_sp_adjust_with_store = 0;
+ fprintf (file, "\tstwm %d,%d(0,%d)\n", 3, -offset, 30);
+ }
+ else
+ print_stw (file, 3, offset, 30); offset += 4;
}
+ /* If we wanted to merge the SP adjustment with a GR save, but we never
+ did any GR saves, then just output the adjustment here. */
+ if (merge_sp_adjust_with_store == 1)
+ fprintf (file, "\tldo %d(30),30\n", actual_fsize);
}
/* Align pointer properly (doubleword boundary). */
@@ -1670,6 +1697,17 @@ output_function_epilogue (file, size)
extern char call_used_regs[];
extern int frame_pointer_needed;
int i, offset;
+ int merge_sp_adjust_with_load = 0;
+
+ /* In the common cases restore RP early to avoid load/use interlock when
+ RP gets used in the bv instruction. */
+ if (frame_pointer_needed
+ && (regs_ever_live [2] || profile_flag))
+ fprintf (file, "\tldw -20(%%r4),%%r2\n");
+ else if (actual_fsize
+ && VAL_14_BITS_P (actual_fsize + 20)
+ && (regs_ever_live [2] || profile_flag))
+ fprintf(file,"\tldw %d(30),2\n", - (actual_fsize + 20));
if (frame_pointer_needed)
{
@@ -1688,11 +1726,29 @@ output_function_epilogue (file, size)
for (i = 18, offset = local_fsize - actual_fsize; i >= 5; i--)
if (regs_ever_live[i] && ! call_used_regs[i])
{
- print_ldw (file, i, offset, 30); offset += 4;
+ /* Only for first load. And not if profiling.
+ merge_sp_adjust_with_load holds the register load with
+ which we will merge the sp adjustment with.*/
+ if (VAL_14_BITS_P (actual_fsize + 20)
+ && local_fsize == 0
+ && ! profile_flag
+ && ! merge_sp_adjust_with_load)
+ merge_sp_adjust_with_load = i;
+ else
+ print_ldw (file, i, offset, 30); offset += 4;
}
if (regs_ever_live[3] && ! call_used_regs[3])
{
- print_ldw (file, 3, offset, 30); offset += 4;
+ /* Only for first load. And not if profiling.
+ merge_sp_adjust_with_load holds the register load with
+ which we will merge the sp adjustment with.*/
+ if (VAL_14_BITS_P (actual_fsize + 20)
+ && local_fsize == 0
+ && ! profile_flag
+ && ! merge_sp_adjust_with_load)
+ merge_sp_adjust_with_load = 3;
+ else
+ print_ldw (file, 3, offset, 30); offset += 4;
}
}
@@ -1736,12 +1792,12 @@ output_function_epilogue (file, size)
}
}
/* Reset stack pointer (and possibly frame pointer). The stack */
- /* pointer is initially set to fp + 64 to avoid a race condition. */
+ /* pointer is initially set to fp + 64 to avoid a race condition.
+ ??? What race condition?!? */
if (frame_pointer_needed)
{
+ /* RP has already been restored in this case. */
fprintf (file, "\tldo 64(%%r4),%%r30\n");
- if (regs_ever_live[2] || profile_flag)
- fprintf (file, "\tldw -84(%%r30),%%r2\n");
fprintf (file, "\tbv 0(%%r2)\n\tldwm -64(%%r30),4\n");
}
else if (actual_fsize)
@@ -1749,9 +1805,18 @@ output_function_epilogue (file, size)
if (regs_ever_live[2] || profile_flag)
{
+ /* In this case RP has already been restored! */
if (VAL_14_BITS_P (actual_fsize + 20))
- fprintf (file, "\tldw %d(30),2\n\tbv 0(2)\n\tldo %d(30),30\n",
- -(actual_fsize + 20), -actual_fsize);
+ {
+ /* Optimize load and sp adjustment. */
+ if (merge_sp_adjust_with_load)
+ fprintf (file, "\tbv 0(2)\n\tldwm %d(30),%d\n",
+ -actual_fsize, merge_sp_adjust_with_load);
+ else
+ fprintf (file, "\tbv 0(2)\n\tldo %d(30),30\n", -actual_fsize);
+ }
+ /* Large frame. Uncommon and not worth extra hair to avoid
+ load/use delay for RP. */
else
fprintf (file,
"\taddil L'%d,30\n\tldw %d(1),2\n\tbv 0(2)\n\
@@ -1760,6 +1825,10 @@ output_function_epilogue (file, size)
- (actual_fsize + 20 + ((-actual_fsize) & ~0x7ff)),
- actual_fsize);
}
+ /* Merge load with SP adjustment. */
+ else if (merge_sp_adjust_with_load)
+ fprintf (file, "\tbv 0(2)\n\tldwm %d(0,30),%d\n",
+ - actual_fsize, merge_sp_adjust_with_load);
else if (VAL_14_BITS_P (actual_fsize))
fprintf (file, "\tbv 0(2)\n\tldo %d(30),30\n", - actual_fsize);
else