summaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorRichard Earnshaw <rearnsha@arm.com>2002-11-01 14:41:57 +0000
committerRichard Earnshaw <rearnsha@gcc.gnu.org>2002-11-01 14:41:57 +0000
commitd5db54a12c1fec54208876b4137ab09851fe6565 (patch)
tree7fe50bc1681bc3ac3462d5638af232702f27e312 /gcc
parent9dcb1ec8139c2ebd15357e6efe37d19f4ff80267 (diff)
downloadgcc-d5db54a12c1fec54208876b4137ab09851fe6565.tar.gz
re PR target/7856 ([arm] invalid offset in constant pool reference)
PR target/7856 * arm.c (use_return_insn): Don't use a return insn if there are saved integer regs, but LR is not one of them. From-SVN: r58716
Diffstat (limited to 'gcc')
-rw-r--r--gcc/ChangeLog6
-rw-r--r--gcc/config/arm/arm.c29
2 files changed, 25 insertions, 10 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 85f6174594a..d904fc4eacc 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,9 @@
+2002-11-01 Richard Earnshaw (rearnsha@arm.com)
+
+ PR target/7856
+ * arm.c (use_return_insn): Don't use a return insn if there are
+ saved integer regs, but LR is not one of them.
+
Fri Nov 1 10:33:15 CET 2002 Jan Hubicka <jh@suse.cz>
* expr.c (emit_move_insn): Use SCALAR_FLOAT_MODE_P
diff --git a/gcc/config/arm/arm.c b/gcc/config/arm/arm.c
index b06cb9bb337..5c0eea7cd9d 100644
--- a/gcc/config/arm/arm.c
+++ b/gcc/config/arm/arm.c
@@ -909,6 +909,7 @@ use_return_insn (iscond)
{
int regno;
unsigned int func_type;
+ unsigned long saved_int_regs;
/* Never use a return instruction before reload has run. */
if (!reload_completed)
@@ -931,23 +932,31 @@ use_return_insn (iscond)
&& !frame_pointer_needed))
return 0;
+ saved_int_regs = arm_compute_save_reg_mask ();
+
/* Can't be done if interworking with Thumb, and any registers have been
- stacked. Similarly, on StrongARM, conditional returns are expensive
- if they aren't taken and registers have been stacked. */
- if (iscond && arm_is_strong && frame_pointer_needed)
+ stacked. */
+ if (TARGET_INTERWORK && saved_int_regs != 0)
return 0;
-
- if ((iscond && arm_is_strong)
- || TARGET_INTERWORK)
+
+ /* On StrongARM, conditional returns are expensive if they aren't
+ taken and multiple registers have been stacked. */
+ if (iscond && arm_is_strong)
{
- for (regno = 0; regno <= LAST_ARM_REGNUM; regno++)
- if (regs_ever_live[regno] && !call_used_regs[regno])
- return 0;
+ /* Conditional return when just the LR is stored is a simple
+ conditional-load instruction, that's not expensive. */
+ if (saved_int_regs != 0 && saved_int_regs != (1 << LR_REGNUM))
+ return 0;
if (flag_pic && regs_ever_live[PIC_OFFSET_TABLE_REGNUM])
return 0;
}
-
+
+ /* If there are saved registers but the LR isn't saved, then we need
+ two instructions for the return. */
+ if (saved_int_regs && !(saved_int_regs & (1 << LR_REGNUM)))
+ return 0;
+
/* Can't be done if any of the FPU regs are pushed,
since this also requires an insn. */
if (TARGET_HARD_FLOAT)