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);
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",
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). */
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)
{
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;
}
}
}
}
/* 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)
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\
- (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