Apply patch from Phillip Blundel to use single STR/LDR when...

Apply patch from Phillip Blundel to use single STR/LDR when only loading
storing a single register in a function prologue/epilogue.

From-SVN: r31296
This commit is contained in:
Philip Blundell 2000-01-09 19:42:57 +00:00 committed by Nick Clifton
parent 9a29c058e7
commit 3a5a428223
3 changed files with 60 additions and 25 deletions

View File

@ -1,3 +1,10 @@
2000-01-09 Philip Blundell <philb@gnu.org>
* config/arm/arm.c (output_return_instruction): Use `ldr' rather
than `ldm' with only one register.
* config/arm/arm.md (push_multi): Use `str' rather than `stm' with
only one register.
Sun Jan 9 17:50:23 2000 Hans-Peter Nilsson <hp@axis.com>
* config/ns32k/ns32k.md (load or push effective address): Operand 1

View File

@ -1,5 +1,5 @@
/* Output routines for GCC for ARM.
Copyright (C) 1991, 93-98, 1999 Free Software Foundation, Inc.
Copyright (C) 1991, 93-99, 2000 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).
@ -5477,18 +5477,20 @@ output_return_instruction (operand, really_return, reverse)
if (TARGET_ABORT_NORETURN && volatile_func)
{
rtx ops[2];
/* If this function was declared non-returning, and we have found a tail
call, then we have to trust that the called function won't return. */
if (! really_return)
return "";
/* Otherwise, trap an attempted return by aborting. */
ops[0] = operand;
ops[1] = gen_rtx_SYMBOL_REF (Pmode, NEED_PLT_RELOC ? "abort(PLT)"
: "abort");
assemble_external_libcall (ops[1]);
output_asm_insn (reverse ? "bl%D0\t%a1" : "bl%d0\t%a1", ops);
call, then we have to trust that the called function won't return. */
if (really_return)
{
rtx ops[2];
/* Otherwise, trap an attempted return by aborting. */
ops[0] = operand;
ops[1] = gen_rtx_SYMBOL_REF (Pmode, NEED_PLT_RELOC ? "abort(PLT)"
: "abort");
assemble_external_libcall (ops[1]);
output_asm_insn (reverse ? "bl%D0\t%a1" : "bl%d0\t%a1", ops);
}
return "";
}
@ -5509,7 +5511,19 @@ output_return_instruction (operand, really_return, reverse)
if (frame_pointer_needed)
live_regs += 4;
if (live_regs)
/* On some ARM architectures it is faster to use LDR rather than LDM to
load a single register. On other architectures, the cost is the same. */
if (live_regs == 1
&& regs_ever_live[LR_REGNUM]
&& ! lr_save_eliminated
/* FIXME: We ought to handle the case TARGET_APCS_32 is true,
really_return is true, and only the PC needs restoring. */
&& ! really_return)
{
output_asm_insn (reverse ? "ldr%?%D0\t%|lr, [%|sp], #4"
: "ldr%?%d0\t%|lr, [%|sp], #4", &operand);
}
else if (live_regs)
{
if (lr_save_eliminated || ! regs_ever_live[LR_REGNUM])
live_regs++;

View File

@ -6534,25 +6534,39 @@
""
"*
{
char pattern[100];
int i;
extern int lr_save_eliminated;
if (lr_save_eliminated)
int num_saves = XVECLEN (operands[2], 0);
if (lr_save_eliminated)
{
if (XVECLEN (operands[2], 0) > 1)
if (num_saves > 1)
abort ();
return \"\";
}
strcpy (pattern, \"stmfd\\t%m0!, {%1\");
for (i = 1; i < XVECLEN (operands[2], 0); i++)
/* For the StrongARM at least it is faster to
use STR to store only a single register. */
else if (num_saves == 1)
output_asm_insn (\"str\\t%1, [%m0, #-4]!\", operands);
else
{
strcat (pattern, \", %|\");
strcat (pattern, reg_names[REGNO (XEXP (XVECEXP (operands[2], 0, i),
int i;
char pattern[100];
if (lr_save_eliminated)
abort ();
strcpy (pattern, \"stmfd\\t%m0!, {%1\");
for (i = 1; i < num_saves; i++)
{
strcat (pattern, \", %|\");
strcat (pattern, reg_names[REGNO (XEXP (XVECEXP (operands[2], 0, i),
0))]);
}
strcat (pattern, \"}\");
output_asm_insn (pattern, operands);
}
strcat (pattern, \"}\");
output_asm_insn (pattern, operands);
return \"\";
}"
[(set_attr "type" "store4")])