diff options
author | Richard Earnshaw <rearnsha@arm.com> | 2002-11-01 14:41:57 +0000 |
---|---|---|
committer | Richard Earnshaw <rearnsha@gcc.gnu.org> | 2002-11-01 14:41:57 +0000 |
commit | d5db54a12c1fec54208876b4137ab09851fe6565 (patch) | |
tree | 7fe50bc1681bc3ac3462d5638af232702f27e312 /gcc | |
parent | 9dcb1ec8139c2ebd15357e6efe37d19f4ff80267 (diff) | |
download | gcc-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/ChangeLog | 6 | ||||
-rw-r--r-- | gcc/config/arm/arm.c | 29 |
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) |