[ARM] Fix PR57340

Message ID 519CE4EE.9040408@arm.com
State New
Headers show

Commit Message

Ramana Radhakrishnan May 22, 2013, 3:31 p.m.

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 

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.



2013-05-22  Ramana Radhakrishnan  <ramana.radhakrishnan@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))