Changes to ARM tail calls, mostly cosmetic.
authorDale Johannesen <dalej@apple.com>
Thu, 8 Jul 2010 01:18:23 +0000 (01:18 +0000)
committerDale Johannesen <dalej@apple.com>
Thu, 8 Jul 2010 01:18:23 +0000 (01:18 +0000)
Add explicit testcases for tail calls within the same module.
Duplicate some code to humor those who think .w doesn't apply on ARM.
Leave this disabled on Thumb1, and add some comments explaining why it's hard
and won't gain much.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@107851 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Target/ARM/ARMBaseRegisterInfo.cpp
lib/Target/ARM/ARMISelLowering.cpp
lib/Target/ARM/ARMInstrInfo.td
test/CodeGen/ARM/call-tc.ll
test/CodeGen/Thumb2/thumb2-call-tc.ll
utils/TableGen/ARMDecoderEmitter.cpp

index 3cd28b486b43e8241bf3736ef11ba4cf64647d84..8f22d177c2aa0e0113ba27bae7b75bec00e27ac7 100644 (file)
@@ -1663,7 +1663,8 @@ emitEpilogue(MachineFunction &MF, MachineBasicBlock &MBB) const {
 
     // Jump to label or value in register.
     if (RetOpcode == ARM::TCRETURNdi) {
-      BuildMI(MBB, MBBI, dl, TII.get(ARM::TAILJMPd)).
+      BuildMI(MBB, MBBI, dl, 
+            TII.get(STI.isThumb() ? ARM::TAILJMPdt : ARM::TAILJMPd)).
         addGlobalAddress(JumpTarget.getGlobal(), JumpTarget.getOffset(),
                          JumpTarget.getTargetFlags());
     } else if (RetOpcode == ARM::TCRETURNdiND) {
index 8f82c7498a22dbb999aa9af126de9288459dce27..8670d37c83681a3eeffc7ebcfaf4b5c6565f56ff 100644 (file)
@@ -1338,13 +1338,7 @@ bool MatchingStackOffset(SDValue Arg, unsigned Offset, ISD::ArgFlagsTy Flags,
       if (!TII->isLoadFromStackSlot(Def, FI))
         return false;
     } else {
-//      unsigned Opcode = Def->getOpcode();
-//      if ((Opcode == X86::LEA32r || Opcode == X86::LEA64r) &&
-//          Def->getOperand(1).isFI()) {
-//        FI = Def->getOperand(1).getIndex();
-//        Bytes = Flags.getByValSize();
-//      } else
-        return false;
+      return false;
     }
   } else if (LoadSDNode *Ld = dyn_cast<LoadSDNode>(Arg)) {
     if (Flags.isByVal())
@@ -1400,6 +1394,12 @@ ARMTargetLowering::IsEligibleForTailCallOptimization(SDValue Callee,
 
   // FIXME: Completely disable sibcall for Thumb1 since Thumb1RegisterInfo::
   // emitEpilogue is not ready for them.
+  // Doing this is tricky, since the LDM/POP instruction on Thumb doesn't take
+  // LR.  This means if we need to reload LR, it takes an extra instructions,
+  // which outweighs the value of the tail call; but here we don't know yet
+  // whether LR is going to be used.  Probably the right approach is to
+  // generate the tail call here and turn it back into CALL/RET in 
+  // emitEpilogue if LR is used.
   if (Subtarget->isThumb1Only())
     return false;
 
@@ -1409,6 +1409,13 @@ ARMTargetLowering::IsEligibleForTailCallOptimization(SDValue Callee,
   // (We could do this by loading the address of the callee into a register;
   // that is an extra instruction over the direct call and burns a register
   // as well, so is not likely to be a win.)
+
+  // It might be safe to remove this restriction on non-Darwin.
+
+  // Thumb1 PIC calls to external symbols use BX, so they can be tail calls,
+  // but we need to make sure there are enough registers; the only valid
+  // registers are the 4 used for parameters.  We don't currently do this
+  // case.
   if (isa<ExternalSymbolSDNode>(Callee))
       return false;
 
index 16d94093b044ea1ea3dd895b9ef87cd522b3cbb5..c73e204a26b3f62e11c19c1c84e89c33084b786d 100644 (file)
@@ -1049,6 +1049,10 @@ let isCall = 1, isTerminator = 1, isReturn = 1, isBarrier = 1 in {
                        "@TC_RETURN","\t$dst", []>, Requires<[IsDarwin]>;
 
     def TAILJMPd : ABXI<0b1010, (outs), (ins brtarget:$dst, variable_ops),
+                   IIC_Br, "b\t$dst  @ TAILCALL",
+                   []>, Requires<[IsDarwin]>;
+
+    def TAILJMPdt: ABXI<0b1010, (outs), (ins brtarget:$dst, variable_ops),
                    IIC_Br, "b.w\t$dst  @ TAILCALL",
                    []>, Requires<[IsDarwin]>;
 
index 2bbdb91c90bc714492229a522bfa484bde3a4e3c..f1269d5bd2be660871b5836537ade2486fb418a4 100644 (file)
@@ -1,5 +1,5 @@
-; RUN: llc < %s -march=arm | FileCheck %s -check-prefix=CHECKV4
-; RUN: llc < %s -march=arm -mattr=+v5t | FileCheck %s -check-prefix=CHECKV5
+; RUN: llc < %s -mtriple=arm-apple-darwin -march=arm | FileCheck %s -check-prefix=CHECKV4
+; RUN: llc < %s -march=arm -mtriple=arm-apple-darwin -mattr=+v5t | FileCheck %s -check-prefix=CHECKV5
 ; RUN: llc < %s -march=arm -mtriple=arm-linux-gnueabi\
 ; RUN:   -relocation-model=pic | FileCheck %s -check-prefix=CHECKELF
 
@@ -37,3 +37,12 @@ BB0:
   %10 = call i32* %9(i32 %0, i32* null, i32 %1, i32* %2, i32* %3, i32* %4) ; <i32*> [#uses=1]
   ret i32* %10
 }
+
+define void @t4() {
+; CHECKV4: t4:
+; CHECKV4: b _t2  @ TAILCALL
+; CHECKV5: t4:
+; CHECKV5: b _t2  @ TAILCALL
+        tail call void @t2( )            ; <i32> [#uses=0]
+        ret void
+}
index fe47e348ab24fe6a413b59d2f86b13a1af9fcde1..24502b0338c25d9127dd54d9a1a4830853c9e7e3 100644 (file)
@@ -25,3 +25,13 @@ define void @h() {
         %tmp.upgrd.2 = tail call i32 %tmp( )            ; <i32> [#uses=0]
         ret void
 }
+
+define void @j() {
+; DARWIN: j:
+; DARWIN: b.w _f  @ TAILCALL
+
+; LINUX: j:
+; LINUX: b.w f  @ TAILCALL
+        tail call void @f()
+        ret void
+}
index d03e0b96cc6f9d34932e75ec615e6d9cac7705e9..50256919bbe6ad60c2140c22b664ff370231d2b9 100644 (file)
@@ -1578,8 +1578,8 @@ bool ARMDecoderEmitter::ARMDEBackend::populateInstruction(
     // Tail calls are other patterns that generate existing instructions.
     if (Name == "TCRETURNdi" || Name == "TCRETURNdiND" ||
         Name == "TCRETURNri" || Name == "TCRETURNriND" ||
-        Name == "TAILJMPd"  || Name == "TAILJMPdND" ||
-        Name == "TAILJMPdNDt" ||
+        Name == "TAILJMPd"  || Name == "TAILJMPdt" ||
+        Name == "TAILJMPdND" || Name == "TAILJMPdNDt" ||
         Name == "TAILJMPr"  || Name == "TAILJMPrND" ||
         Name == "MOVr_TC")
       return false;