Hi,This fixes PR target/57340 a fallout from my PR target/19599 patch. Unfortunately this didn't show up in the testing I did and I'm sorry about the breakage.
The problem here is that we choose r3 as a padding register with indirect tailcalls that could use r3 for this purpose. Ofcourse this decision is made when the frame offsets is calculated and r3 isn't in the fusage of the function. The simplest way to fix this was to check if the tailcall in this case is also an indirect tailcall. If so, we don't allow the use of r3 as a padding register. Additionally, in the prologue code we choose an alternate callee save register that is free if r3 is not available so we are free to use this instead of another callee save register.
Tested by bootstrapping armv5te and observing it pass well into stage2. Tested by bootstrapping and reg testing Thumb2 configurations with A9 where this problem was also observed on a version prior to breakages from PR57351.
Applied. regards Ramana 2013-05-22 Ramana Radhakrishnan <ramana.radhakrish...@arm.com> PR target/19599 PR target/57340 * config/arm/arm.c (any_sibcall_uses_r3): Rename to .. (any_sibcall_could_use_r3): this and handle indirect calls. (arm_get_frame_offsets): Rename use of any_sibcall_uses_r3.
Index: gcc/config/arm/arm.c =================================================================== --- gcc/config/arm/arm.c (revision 199202) +++ gcc/config/arm/arm.c (working copy) @@ -17568,11 +17568,27 @@ thumb_force_lr_save (void) || df_regs_ever_live_p (LR_REGNUM)); } +/* We do not know if r3 will be available because + we do have an indirect tailcall happening in this + particular case. */ +static bool +is_indirect_tailcall_p (rtx call) +{ + rtx pat = PATTERN (call); + + /* Indirect tail call. */ + pat = XVECEXP (pat, 0, 0); + if (GET_CODE (pat) == SET) + pat = SET_SRC (pat); + + pat = XEXP (XEXP (pat, 0), 0); + return REG_P (pat); +} /* Return true if r3 is used by any of the tail call insns in the current function. */ static bool -any_sibcall_uses_r3 (void) +any_sibcall_could_use_r3 (void) { edge_iterator ei; edge e; @@ -17586,7 +17602,8 @@ any_sibcall_uses_r3 (void) if (!CALL_P (call)) call = prev_nonnote_nondebug_insn (call); gcc_assert (CALL_P (call) && SIBLING_CALL_P (call)); - if (find_regno_fusage (call, USE, 3)) + if (find_regno_fusage (call, USE, 3) + || is_indirect_tailcall_p (call)) return true; } return false; @@ -17753,7 +17770,7 @@ arm_get_frame_offsets (void) /* If it is safe to use r3, then do so. This sometimes generates better code on Thumb-2 by avoiding the need to use 32-bit push/pop instructions. */ - if (! any_sibcall_uses_r3 () + if (! any_sibcall_could_use_r3 () && arm_size_return_regs () <= 12 && (offsets->saved_regs_mask & (1 << 3)) == 0 && (TARGET_THUMB2 || !current_tune->prefer_ldrd_strd))