[llvm-branch-commits] [llvm-branch] r106316 - in /llvm/branches/Apple/Troughton: lib/CodeGen/ lib/Target/ARM/ lib/Target/X86/ test/CodeGen/ARM/ test/CodeGen/Thumb2/ utils/TableGen/

Dale Johannesen dalej at apple.com
Fri Jun 18 14:29:26 PDT 2010


Author: johannes
Date: Fri Jun 18 16:29:25 2010
New Revision: 106316

URL: http://llvm.org/viewvc/llvm-project?rev=106316&view=rev
Log:
Move ARM tail call stuff into Troughton.
Branch folding is working differently in ARM/ifcvt6-tc.ll than
in mainline; I don't understand why, but it isn't connected
with tail calls.

--- Merging r105413 into '.':
U    utils/TableGen/ARMDecoderEmitter.cpp
U    lib/Target/ARM/ARMISelLowering.h
U    lib/Target/ARM/ARMInstrInfo.td
U    lib/Target/ARM/ARMISelLowering.cpp
U    lib/Target/ARM/ARMISelDAGToDAG.cpp
U    lib/Target/ARM/ARMBaseRegisterInfo.cpp
--- Merging r105419 into '.':
U    test/CodeGen/Thumb2/thumb2-ldm.ll
--- Merging r105422 into '.':
U    test/CodeGen/Thumb2/thumb2-call.ll
--- Merging r105438 into '.':
U    test/CodeGen/Thumb2/thumb2-ifcvt1.ll
--- Merging r105449 into '.':
U    test/CodeGen/ARM/call.ll
--- Merging r105450 into '.':
U    test/CodeGen/ARM/insn-sched1.ll
U    test/CodeGen/ARM/ldm.ll
--- Merging r105472 into '.':
G    lib/Target/ARM/ARMISelLowering.cpp
--- Merging r105485 into '.':
U    test/CodeGen/ARM/ifcvt6.ll
U    test/CodeGen/Thumb2/thumb2-ifcvt2.ll
--- Merging r105509 into '.':
U    lib/CodeGen/LiveVariables.cpp
U    lib/Target/X86/X86ISelLowering.cpp
--- Merging r105515 into '.':
G    lib/Target/ARM/ARMISelLowering.cpp
--- Merging r106053 into '.':
G    utils/TableGen/ARMDecoderEmitter.cpp
U    utils/TableGen/EDEmitter.cpp
G    lib/Target/ARM/ARMISelLowering.cpp
G    lib/Target/ARM/ARMBaseRegisterInfo.cpp
U    lib/Target/ARM/ARMBaseInstrInfo.cpp
U    lib/Target/ARM/ARMRegisterInfo.td
U    lib/Target/ARM/Thumb1InstrInfo.cpp
U    lib/Target/ARM/Thumb2InstrInfo.cpp
--- Merging r106058 into '.':
G    lib/Target/ARM/ARMInstrInfo.td
--- Merging r106295 into '.':
G    lib/Target/ARM/ARMInstrInfo.td
G    lib/Target/ARM/ARMISelLowering.cpp
--- Merging r106299 into '.':
A    test/CodeGen/ARM/insn-sched1-tc.ll
A    test/CodeGen/ARM/ldm-tc.ll
A    test/CodeGen/ARM/call-tc.ll
A    test/CodeGen/ARM/ifcvt6-tc.ll
A    test/CodeGen/Thumb2/thumb2-call-tc.ll
A    test/CodeGen/Thumb2/thumb2-ifcvt1-tc.ll
G    lib/Target/ARM/ARMISelLowering.cpp


Added:
    llvm/branches/Apple/Troughton/test/CodeGen/ARM/call-tc.ll
      - copied unchanged from r106299, llvm/trunk/test/CodeGen/ARM/call-tc.ll
    llvm/branches/Apple/Troughton/test/CodeGen/ARM/ifcvt6-tc.ll
      - copied, changed from r106299, llvm/trunk/test/CodeGen/ARM/ifcvt6-tc.ll
    llvm/branches/Apple/Troughton/test/CodeGen/ARM/insn-sched1-tc.ll
      - copied unchanged from r106299, llvm/trunk/test/CodeGen/ARM/insn-sched1-tc.ll
    llvm/branches/Apple/Troughton/test/CodeGen/ARM/ldm-tc.ll
      - copied unchanged from r106299, llvm/trunk/test/CodeGen/ARM/ldm-tc.ll
    llvm/branches/Apple/Troughton/test/CodeGen/Thumb2/thumb2-call-tc.ll
      - copied unchanged from r106299, llvm/trunk/test/CodeGen/Thumb2/thumb2-call-tc.ll
    llvm/branches/Apple/Troughton/test/CodeGen/Thumb2/thumb2-ifcvt1-tc.ll
      - copied unchanged from r106299, llvm/trunk/test/CodeGen/Thumb2/thumb2-ifcvt1-tc.ll
Modified:
    llvm/branches/Apple/Troughton/lib/CodeGen/LiveVariables.cpp
    llvm/branches/Apple/Troughton/lib/Target/ARM/ARMBaseInstrInfo.cpp
    llvm/branches/Apple/Troughton/lib/Target/ARM/ARMBaseRegisterInfo.cpp
    llvm/branches/Apple/Troughton/lib/Target/ARM/ARMISelDAGToDAG.cpp
    llvm/branches/Apple/Troughton/lib/Target/ARM/ARMISelLowering.cpp
    llvm/branches/Apple/Troughton/lib/Target/ARM/ARMISelLowering.h
    llvm/branches/Apple/Troughton/lib/Target/ARM/ARMInstrInfo.td
    llvm/branches/Apple/Troughton/lib/Target/ARM/ARMRegisterInfo.td
    llvm/branches/Apple/Troughton/lib/Target/ARM/Thumb1InstrInfo.cpp
    llvm/branches/Apple/Troughton/lib/Target/ARM/Thumb2InstrInfo.cpp
    llvm/branches/Apple/Troughton/lib/Target/X86/X86ISelLowering.cpp
    llvm/branches/Apple/Troughton/test/CodeGen/ARM/call.ll
    llvm/branches/Apple/Troughton/test/CodeGen/ARM/ifcvt6.ll
    llvm/branches/Apple/Troughton/test/CodeGen/ARM/insn-sched1.ll
    llvm/branches/Apple/Troughton/test/CodeGen/ARM/ldm.ll
    llvm/branches/Apple/Troughton/test/CodeGen/Thumb2/thumb2-call.ll
    llvm/branches/Apple/Troughton/test/CodeGen/Thumb2/thumb2-ifcvt1.ll
    llvm/branches/Apple/Troughton/test/CodeGen/Thumb2/thumb2-ifcvt2.ll
    llvm/branches/Apple/Troughton/test/CodeGen/Thumb2/thumb2-ldm.ll
    llvm/branches/Apple/Troughton/utils/TableGen/ARMDecoderEmitter.cpp
    llvm/branches/Apple/Troughton/utils/TableGen/EDEmitter.cpp

Modified: llvm/branches/Apple/Troughton/lib/CodeGen/LiveVariables.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/branches/Apple/Troughton/lib/CodeGen/LiveVariables.cpp?rev=106316&r1=106315&r2=106316&view=diff
==============================================================================
--- llvm/branches/Apple/Troughton/lib/CodeGen/LiveVariables.cpp (original)
+++ llvm/branches/Apple/Troughton/lib/CodeGen/LiveVariables.cpp Fri Jun 18 16:29:25 2010
@@ -609,7 +609,12 @@
 
     // Finally, if the last instruction in the block is a return, make sure to
     // mark it as using all of the live-out values in the function.
-    if (!MBB->empty() && MBB->back().getDesc().isReturn()) {
+    // Things marked both call and return are tail calls; do not do this for
+    // them.  The tail callee need not take the same registers as input
+    // that it produces as output, and there are dependencies for its input
+    // registers elsewhere.
+    if (!MBB->empty() && MBB->back().getDesc().isReturn()
+        && !MBB->back().getDesc().isCall()) {
       MachineInstr *Ret = &MBB->back();
 
       for (MachineRegisterInfo::liveout_iterator

Modified: llvm/branches/Apple/Troughton/lib/Target/ARM/ARMBaseInstrInfo.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/branches/Apple/Troughton/lib/Target/ARM/ARMBaseInstrInfo.cpp?rev=106316&r1=106315&r2=106316&view=diff
==============================================================================
--- llvm/branches/Apple/Troughton/lib/Target/ARM/ARMBaseInstrInfo.cpp (original)
+++ llvm/branches/Apple/Troughton/lib/Target/ARM/ARMBaseInstrInfo.cpp Fri Jun 18 16:29:25 2010
@@ -596,6 +596,7 @@
     return true;
   }
   case ARM::MOVr:
+  case ARM::MOVr_TC:
   case ARM::tMOVr:
   case ARM::tMOVgpr2tgpr:
   case ARM::tMOVtgpr2gpr:
@@ -701,11 +702,11 @@
                                const TargetRegisterClass *DestRC,
                                const TargetRegisterClass *SrcRC,
                                DebugLoc DL) const {
-  // tGPR is used sometimes in ARM instructions that need to avoid using
-  // certain registers.  Just treat it as GPR here.
-  if (DestRC == ARM::tGPRRegisterClass)
+  // tGPR or tcGPR is used sometimes in ARM instructions that need to avoid
+  // using certain registers.  Just treat them as GPR here.
+  if (DestRC == ARM::tGPRRegisterClass || DestRC == ARM::tcGPRRegisterClass)
     DestRC = ARM::GPRRegisterClass;
-  if (SrcRC == ARM::tGPRRegisterClass)
+  if (SrcRC == ARM::tGPRRegisterClass || SrcRC == ARM::tcGPRRegisterClass)
     SrcRC = ARM::GPRRegisterClass;
 
   // Allow DPR / DPR_VFP2 / DPR_8 cross-class copies.
@@ -799,7 +800,7 @@
 
   // tGPR is used sometimes in ARM instructions that need to avoid using
   // certain registers.  Just treat it as GPR here.
-  if (RC == ARM::tGPRRegisterClass)
+  if (RC == ARM::tGPRRegisterClass || RC == ARM::tcGPRRegisterClass)
     RC = ARM::GPRRegisterClass;
 
   if (RC == ARM::GPRRegisterClass) {
@@ -890,7 +891,7 @@
 
   // tGPR is used sometimes in ARM instructions that need to avoid using
   // certain registers.  Just treat it as GPR here.
-  if (RC == ARM::tGPRRegisterClass)
+  if (RC == ARM::tGPRRegisterClass || RC == ARM::tcGPRRegisterClass)
     RC = ARM::GPRRegisterClass;
 
   if (RC == ARM::GPRRegisterClass) {

Modified: llvm/branches/Apple/Troughton/lib/Target/ARM/ARMBaseRegisterInfo.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/branches/Apple/Troughton/lib/Target/ARM/ARMBaseRegisterInfo.cpp?rev=106316&r1=106315&r2=106316&view=diff
==============================================================================
--- llvm/branches/Apple/Troughton/lib/Target/ARM/ARMBaseRegisterInfo.cpp (original)
+++ llvm/branches/Apple/Troughton/lib/Target/ARM/ARMBaseRegisterInfo.cpp Fri Jun 18 16:29:25 2010
@@ -1580,6 +1580,7 @@
   MachineBasicBlock::iterator MBBI = prior(MBB.end());
   assert(MBBI->getDesc().isReturn() &&
          "Can only insert epilog into returning blocks");
+  unsigned RetOpcode = MBBI->getOpcode();
   DebugLoc dl = MBBI->getDebugLoc();
   MachineFrameInfo *MFI = MF.getFrameInfo();
   ARMFunctionInfo *AFI = MF.getInfo<ARMFunctionInfo>();
@@ -1654,6 +1655,37 @@
     emitSPUpdate(isARM, MBB, MBBI, dl, TII, AFI->getGPRCalleeSavedArea1Size());
   }
 
+  if (RetOpcode == ARM::TCRETURNdi || RetOpcode == ARM::TCRETURNdiND ||
+      RetOpcode == ARM::TCRETURNri || RetOpcode == ARM::TCRETURNriND) {
+    // Tail call return: adjust the stack pointer and jump to callee.
+    MBBI = prior(MBB.end());
+    MachineOperand &JumpTarget = MBBI->getOperand(0);
+
+    // Jump to label or value in register.
+    if (RetOpcode == ARM::TCRETURNdi) {
+      BuildMI(MBB, MBBI, dl, TII.get(ARM::TAILJMPd)).
+        addGlobalAddress(JumpTarget.getGlobal(), JumpTarget.getOffset(),
+                         JumpTarget.getTargetFlags());
+    } else if (RetOpcode == ARM::TCRETURNdiND) {
+      BuildMI(MBB, MBBI, dl, TII.get(ARM::TAILJMPdND)).
+        addGlobalAddress(JumpTarget.getGlobal(), JumpTarget.getOffset(),
+                         JumpTarget.getTargetFlags());
+    } else if (RetOpcode == ARM::TCRETURNri) {
+      BuildMI(MBB, MBBI, dl, TII.get(ARM::TAILJMPr)).
+        addReg(JumpTarget.getReg(), RegState::Kill);
+    } else if (RetOpcode == ARM::TCRETURNriND) {
+      BuildMI(MBB, MBBI, dl, TII.get(ARM::TAILJMPrND)).
+        addReg(JumpTarget.getReg(), RegState::Kill);
+    } 
+
+    MachineInstr *NewMI = prior(MBBI);
+    for (unsigned i = 1, e = MBBI->getNumOperands(); i != e; ++i)
+      NewMI->addOperand(MBBI->getOperand(i));
+
+    // Delete the pseudo instruction TCRETURN.
+    MBB.erase(MBBI);
+  }
+
   if (VARegSaveSize)
     emitSPUpdate(isARM, MBB, MBBI, dl, TII, VARegSaveSize);
 }

Modified: llvm/branches/Apple/Troughton/lib/Target/ARM/ARMISelDAGToDAG.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/branches/Apple/Troughton/lib/Target/ARM/ARMISelDAGToDAG.cpp?rev=106316&r1=106315&r2=106316&view=diff
==============================================================================
--- llvm/branches/Apple/Troughton/lib/Target/ARM/ARMISelDAGToDAG.cpp (original)
+++ llvm/branches/Apple/Troughton/lib/Target/ARM/ARMISelDAGToDAG.cpp Fri Jun 18 16:29:25 2010
@@ -11,6 +11,7 @@
 //
 //===----------------------------------------------------------------------===//
 
+#define DEBUG_TYPE "arm-isel"
 #include "ARM.h"
 #include "ARMAddressingModes.h"
 #include "ARMTargetMachine.h"

Modified: llvm/branches/Apple/Troughton/lib/Target/ARM/ARMISelLowering.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/branches/Apple/Troughton/lib/Target/ARM/ARMISelLowering.cpp?rev=106316&r1=106315&r2=106316&view=diff
==============================================================================
--- llvm/branches/Apple/Troughton/lib/Target/ARM/ARMISelLowering.cpp (original)
+++ llvm/branches/Apple/Troughton/lib/Target/ARM/ARMISelLowering.cpp Fri Jun 18 16:29:25 2010
@@ -12,6 +12,7 @@
 //
 //===----------------------------------------------------------------------===//
 
+#define DEBUG_TYPE "arm-isel"
 #include "ARM.h"
 #include "ARMAddressingModes.h"
 #include "ARMConstantPoolValue.h"
@@ -40,6 +41,7 @@
 #include "llvm/MC/MCSectionMachO.h"
 #include "llvm/Target/TargetOptions.h"
 #include "llvm/ADT/VectorExtras.h"
+#include "llvm/ADT/Statistic.h"
 #include "llvm/Support/CommandLine.h"
 #include "llvm/Support/ErrorHandling.h"
 #include "llvm/Support/MathExtras.h"
@@ -47,6 +49,14 @@
 #include <sstream>
 using namespace llvm;
 
+STATISTIC(NumTailCalls, "Number of tail calls");
+
+// This option should go away when tail calls fully work.
+static cl::opt<bool>
+EnableARMTailCalls("arm-tail-calls", cl::Hidden,
+  cl::desc("Generate tail calls (TEMPORARY OPTION)."),
+  cl::init(true));
+
 static cl::opt<bool>
 EnableARMLongCalls("arm-long-calls", cl::Hidden,
   cl::desc("Generate calls via indirect call instructions."),
@@ -537,6 +547,8 @@
   case ARMISD::EH_SJLJ_SETJMP: return "ARMISD::EH_SJLJ_SETJMP";
   case ARMISD::EH_SJLJ_LONGJMP:return "ARMISD::EH_SJLJ_LONGJMP";
 
+  case ARMISD::TC_RETURN:     return "ARMISD::TC_RETURN";
+  
   case ARMISD::THREAD_POINTER:return "ARMISD::THREAD_POINTER";
 
   case ARMISD::DYN_ALLOC:     return "ARMISD::DYN_ALLOC";
@@ -986,8 +998,24 @@
                              const SmallVectorImpl<ISD::InputArg> &Ins,
                              DebugLoc dl, SelectionDAG &DAG,
                              SmallVectorImpl<SDValue> &InVals) const {
-  // ARM target does not yet support tail call optimization.
-  isTailCall = false;
+  MachineFunction &MF = DAG.getMachineFunction();
+  bool IsStructRet    = (Outs.empty()) ? false : Outs[0].Flags.isSRet();
+  bool IsSibCall = false;
+  // Temporarily disable tail calls so things don't break.
+  if (!EnableARMTailCalls)
+    isTailCall = false;
+  if (isTailCall) {
+    // Check if it's really possible to do a tail call.
+    isTailCall = IsEligibleForTailCallOptimization(Callee, CallConv,
+                    isVarArg, IsStructRet, MF.getFunction()->hasStructRetAttr(),
+                                                   Outs, Ins, DAG);
+    // We don't support GuaranteedTailCallOpt for ARM, only automatically
+    // detected sibcalls.
+    if (isTailCall) {
+      ++NumTailCalls;
+      IsSibCall = true;
+    }
+  }
 
   // Analyze operands of the call, assigning locations to each operand.
   SmallVector<CCValAssign, 16> ArgLocs;
@@ -1000,9 +1028,14 @@
   // Get a count of how many bytes are to be pushed on the stack.
   unsigned NumBytes = CCInfo.getNextStackOffset();
 
+  // For tail calls, memory operands are available in our caller's stack.
+  if (IsSibCall)
+    NumBytes = 0;
+
   // Adjust the stack pointer for the new arguments...
   // These operations are automatically eliminated by the prolog/epilog pass
-  Chain = DAG.getCALLSEQ_START(Chain, DAG.getIntPtrConstant(NumBytes, true));
+  if (!IsSibCall)
+    Chain = DAG.getCALLSEQ_START(Chain, DAG.getIntPtrConstant(NumBytes, true));
 
   SDValue StackPtr = DAG.getCopyFromReg(Chain, dl, ARM::SP, getPointerTy());
 
@@ -1063,7 +1096,7 @@
       }
     } else if (VA.isRegLoc()) {
       RegsToPass.push_back(std::make_pair(VA.getLocReg(), Arg));
-    } else {
+    } else if (!IsSibCall) {
       assert(VA.isMemLoc());
 
       MemOpChains.push_back(LowerMemOpCallTo(Chain, StackPtr, Arg,
@@ -1078,10 +1111,32 @@
   // Build a sequence of copy-to-reg nodes chained together with token chain
   // and flag operands which copy the outgoing args into the appropriate regs.
   SDValue InFlag;
-  for (unsigned i = 0, e = RegsToPass.size(); i != e; ++i) {
-    Chain = DAG.getCopyToReg(Chain, dl, RegsToPass[i].first,
-                             RegsToPass[i].second, InFlag);
-    InFlag = Chain.getValue(1);
+  // Tail call byval lowering might overwrite argument registers so in case of
+  // tail call optimization the copies to registers are lowered later.
+  if (!isTailCall)
+    for (unsigned i = 0, e = RegsToPass.size(); i != e; ++i) {
+      Chain = DAG.getCopyToReg(Chain, dl, RegsToPass[i].first,
+                               RegsToPass[i].second, InFlag);
+      InFlag = Chain.getValue(1);
+    }
+
+  // For tail calls lower the arguments to the 'real' stack slot.
+  if (isTailCall) {
+    // Force all the incoming stack arguments to be loaded from the stack
+    // before any new outgoing arguments are stored to the stack, because the
+    // outgoing stack slots may alias the incoming argument stack slots, and
+    // the alias isn't otherwise explicit. This is slightly more conservative
+    // than necessary, because it means that each store effectively depends
+    // on every argument instead of just those arguments it would clobber.
+
+    // Do not flag preceeding copytoreg stuff together with the following stuff.
+    InFlag = SDValue();
+    for (unsigned i = 0, e = RegsToPass.size(); i != e; ++i) {
+      Chain = DAG.getCopyToReg(Chain, dl, RegsToPass[i].first,
+                               RegsToPass[i].second, InFlag);
+      InFlag = Chain.getValue(1);
+    }
+    InFlag =SDValue();
   }
 
   // If the callee is a GlobalAddress/ExternalSymbol node (quite common, every
@@ -1090,7 +1145,6 @@
   bool isDirect = false;
   bool isARMFunc = false;
   bool isLocalARMFunc = false;
-  MachineFunction &MF = DAG.getMachineFunction();
   ARMFunctionInfo *AFI = MF.getInfo<ARMFunctionInfo>();
 
   if (EnableARMLongCalls) {
@@ -1208,9 +1262,13 @@
 
   if (InFlag.getNode())
     Ops.push_back(InFlag);
+
+  SDVTList NodeTys = DAG.getVTList(MVT::Other, MVT::Flag);
+  if (isTailCall)
+    return DAG.getNode(ARMISD::TC_RETURN, dl, NodeTys, &Ops[0], Ops.size());
+
   // Returns a chain and a flag for retval copy to use.
-  Chain = DAG.getNode(CallOpc, dl, DAG.getVTList(MVT::Other, MVT::Flag),
-                      &Ops[0], Ops.size());
+  Chain = DAG.getNode(CallOpc, dl, NodeTys, &Ops[0], Ops.size());
   InFlag = Chain.getValue(1);
 
   Chain = DAG.getCALLSEQ_END(Chain, DAG.getIntPtrConstant(NumBytes, true),
@@ -1224,6 +1282,184 @@
                          dl, DAG, InVals);
 }
 
+/// MatchingStackOffset - Return true if the given stack call argument is
+/// already available in the same position (relatively) of the caller's
+/// incoming argument stack.
+static
+bool MatchingStackOffset(SDValue Arg, unsigned Offset, ISD::ArgFlagsTy Flags,
+                         MachineFrameInfo *MFI, const MachineRegisterInfo *MRI,
+                         const ARMInstrInfo *TII) {
+  unsigned Bytes = Arg.getValueType().getSizeInBits() / 8;
+  int FI = INT_MAX;
+  if (Arg.getOpcode() == ISD::CopyFromReg) {
+    unsigned VR = cast<RegisterSDNode>(Arg.getOperand(1))->getReg();
+    if (!VR || TargetRegisterInfo::isPhysicalRegister(VR))
+      return false;
+    MachineInstr *Def = MRI->getVRegDef(VR);
+    if (!Def)
+      return false;
+    if (!Flags.isByVal()) {
+      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;
+    }
+  } else if (LoadSDNode *Ld = dyn_cast<LoadSDNode>(Arg)) {
+    if (Flags.isByVal())
+      // ByVal argument is passed in as a pointer but it's now being
+      // dereferenced. e.g.
+      // define @foo(%struct.X* %A) {
+      //   tail call @bar(%struct.X* byval %A)
+      // }
+      return false;
+    SDValue Ptr = Ld->getBasePtr();
+    FrameIndexSDNode *FINode = dyn_cast<FrameIndexSDNode>(Ptr);
+    if (!FINode)
+      return false;
+    FI = FINode->getIndex();
+  } else
+    return false;
+
+  assert(FI != INT_MAX);
+  if (!MFI->isFixedObjectIndex(FI))
+    return false;
+  return Offset == MFI->getObjectOffset(FI) && Bytes == MFI->getObjectSize(FI);
+}
+
+/// IsEligibleForTailCallOptimization - Check whether the call is eligible
+/// for tail call optimization. Targets which want to do tail call
+/// optimization should implement this function.
+bool
+ARMTargetLowering::IsEligibleForTailCallOptimization(SDValue Callee,
+                                                     CallingConv::ID CalleeCC,
+                                                     bool isVarArg,
+                                                     bool isCalleeStructRet,
+                                                     bool isCallerStructRet,
+                                    const SmallVectorImpl<ISD::OutputArg> &Outs,
+                                    const SmallVectorImpl<ISD::InputArg> &Ins,
+                                                     SelectionDAG& DAG) const {
+
+  const Function *CallerF = DAG.getMachineFunction().getFunction();
+  CallingConv::ID CallerCC = CallerF->getCallingConv();
+  bool CCMatch = CallerCC == CalleeCC;
+
+  // Look for obvious safe cases to perform tail call optimization that do not
+  // require ABI changes. This is what gcc calls sibcall.
+
+  // Do not sibcall optimize vararg calls unless the call site is not passing any
+  // arguments.
+  if (isVarArg && !Outs.empty())
+    return false;
+
+  // Also avoid sibcall optimization if either caller or callee uses struct
+  // return semantics.
+  if (isCalleeStructRet || isCallerStructRet)
+    return false;
+
+  // On Thumb, for the moment, we can only do this to functions defined in this
+  // compilation, or to indirect calls.  A Thumb B to an ARM function is not
+  // easily fixed up in the linker, unlike BL.
+  if (Subtarget->isThumb()) {
+    if (GlobalAddressSDNode *G = dyn_cast<GlobalAddressSDNode>(Callee)) {
+      const GlobalValue *GV = G->getGlobal();
+      if (GV->isDeclaration() || GV->isWeakForLinker())
+        return false;
+    } else if (isa<ExternalSymbolSDNode>(Callee)) {
+      return false;
+    }
+  }
+
+  // If the calling conventions do not match, then we'd better make sure the
+  // results are returned in the same way as what the caller expects.
+  if (!CCMatch) {
+    SmallVector<CCValAssign, 16> RVLocs1;
+    CCState CCInfo1(CalleeCC, false, getTargetMachine(),
+                    RVLocs1, *DAG.getContext());
+    CCInfo1.AnalyzeCallResult(Ins, CCAssignFnForNode(CalleeCC, true, isVarArg));
+
+    SmallVector<CCValAssign, 16> RVLocs2;
+    CCState CCInfo2(CallerCC, false, getTargetMachine(),
+                    RVLocs2, *DAG.getContext());
+    CCInfo2.AnalyzeCallResult(Ins, CCAssignFnForNode(CallerCC, true, isVarArg));
+
+    if (RVLocs1.size() != RVLocs2.size())
+      return false;
+    for (unsigned i = 0, e = RVLocs1.size(); i != e; ++i) {
+      if (RVLocs1[i].isRegLoc() != RVLocs2[i].isRegLoc())
+        return false;
+      if (RVLocs1[i].getLocInfo() != RVLocs2[i].getLocInfo())
+        return false;
+      if (RVLocs1[i].isRegLoc()) {
+        if (RVLocs1[i].getLocReg() != RVLocs2[i].getLocReg())
+          return false;
+      } else {
+        if (RVLocs1[i].getLocMemOffset() != RVLocs2[i].getLocMemOffset())
+          return false;
+      }
+    }
+  }
+
+  // If the callee takes no arguments then go on to check the results of the
+  // call.
+  if (!Outs.empty()) {
+    // Check if stack adjustment is needed. For now, do not do this if any
+    // argument is passed on the stack.
+    SmallVector<CCValAssign, 16> ArgLocs;
+    CCState CCInfo(CalleeCC, isVarArg, getTargetMachine(),
+                   ArgLocs, *DAG.getContext());
+    CCInfo.AnalyzeCallOperands(Outs,
+                               CCAssignFnForNode(CalleeCC, false, isVarArg));
+    if (CCInfo.getNextStackOffset()) {
+      MachineFunction &MF = DAG.getMachineFunction();
+
+      // Check if the arguments are already laid out in the right way as
+      // the caller's fixed stack objects.
+      MachineFrameInfo *MFI = MF.getFrameInfo();
+      const MachineRegisterInfo *MRI = &MF.getRegInfo();
+      const ARMInstrInfo *TII =
+        ((ARMTargetMachine&)getTargetMachine()).getInstrInfo();
+      for (unsigned i = 0, realArgIdx = 0, e = ArgLocs.size();
+           i != e;
+           ++i, ++realArgIdx) {
+        CCValAssign &VA = ArgLocs[i];
+        EVT RegVT = VA.getLocVT();
+        SDValue Arg = Outs[realArgIdx].Val;
+        ISD::ArgFlagsTy Flags = Outs[realArgIdx].Flags;
+        if (VA.getLocInfo() == CCValAssign::Indirect)
+          return false;
+        if (VA.needsCustom()) {
+          // f64 and vector types are split into multiple registers or
+          // register/stack-slot combinations.  The types will not match
+          // the registers; give up on memory f64 refs until we figure
+          // out what to do about this.
+          if (!VA.isRegLoc())
+            return false;
+          if (!ArgLocs[++i].isRegLoc())
+            return false; 
+          if (RegVT == MVT::v2f64) {
+            if (!ArgLocs[++i].isRegLoc())
+              return false;
+            if (!ArgLocs[++i].isRegLoc())
+              return false;
+          }
+        } else if (!VA.isRegLoc()) {
+          if (!MatchingStackOffset(Arg, VA.getLocMemOffset(), Flags,
+                                   MFI, MRI, TII))
+            return false;
+        }
+      }
+    }
+  }
+
+  return true;
+}
+
 SDValue
 ARMTargetLowering::LowerReturn(SDValue Chain,
                                CallingConv::ID CallConv, bool isVarArg,

Modified: llvm/branches/Apple/Troughton/lib/Target/ARM/ARMISelLowering.h
URL: http://llvm.org/viewvc/llvm-project/llvm/branches/Apple/Troughton/lib/Target/ARM/ARMISelLowering.h?rev=106316&r1=106315&r2=106316&view=diff
==============================================================================
--- llvm/branches/Apple/Troughton/lib/Target/ARM/ARMISelLowering.h (original)
+++ llvm/branches/Apple/Troughton/lib/Target/ARM/ARMISelLowering.h Fri Jun 18 16:29:25 2010
@@ -70,6 +70,8 @@
       EH_SJLJ_SETJMP,    // SjLj exception handling setjmp.
       EH_SJLJ_LONGJMP,   // SjLj exception handling longjmp.
 
+      TC_RETURN,    // Tail call return pseudo.
+
       THREAD_POINTER,
 
       DYN_ALLOC,    // Dynamic allocation on the stack.
@@ -340,6 +342,17 @@
                 DebugLoc dl, SelectionDAG &DAG,
                 SmallVectorImpl<SDValue> &InVals) const;
 
+    /// IsEligibleForTailCallOptimization - Check whether the call is eligible
+    /// for tail call optimization. Targets which want to do tail call
+    /// optimization should implement this function.
+    bool IsEligibleForTailCallOptimization(SDValue Callee,
+                                           CallingConv::ID CalleeCC,
+                                           bool isVarArg,
+                                           bool isCalleeStructRet,
+                                           bool isCallerStructRet,
+                                    const SmallVectorImpl<ISD::OutputArg> &Outs,
+                                    const SmallVectorImpl<ISD::InputArg> &Ins,
+                                           SelectionDAG& DAG) const;
     virtual SDValue
       LowerReturn(SDValue Chain,
                   CallingConv::ID CallConv, bool isVarArg,

Modified: llvm/branches/Apple/Troughton/lib/Target/ARM/ARMInstrInfo.td
URL: http://llvm.org/viewvc/llvm-project/llvm/branches/Apple/Troughton/lib/Target/ARM/ARMInstrInfo.td?rev=106316&r1=106315&r2=106316&view=diff
==============================================================================
--- llvm/branches/Apple/Troughton/lib/Target/ARM/ARMInstrInfo.td (original)
+++ llvm/branches/Apple/Troughton/lib/Target/ARM/ARMInstrInfo.td Fri Jun 18 16:29:25 2010
@@ -53,6 +53,8 @@
 def SDT_ARMMEMBARRIERV6  : SDTypeProfile<0, 1, [SDTCisInt<0>]>;
 def SDT_ARMSYNCBARRIERV6 : SDTypeProfile<0, 1, [SDTCisInt<0>]>;
 
+def SDT_ARMTCRET : SDTypeProfile<0, 1, [SDTCisPtrTy<0>]>;
+
 // Node definitions.
 def ARMWrapper       : SDNode<"ARMISD::Wrapper",     SDTIntUnaryOp>;
 def ARMWrapperJT     : SDNode<"ARMISD::WrapperJT",   SDTIntBinOp>;
@@ -117,6 +119,9 @@
 
 def ARMrbit          : SDNode<"ARMISD::RBIT", SDTIntUnaryOp>;
 
+def ARMtcret         : SDNode<"ARMISD::TC_RETURN", SDT_ARMTCRET, 
+                        [SDNPHasChain,  SDNPOptInFlag, SDNPVariadic]>;
+
 //===----------------------------------------------------------------------===//
 // ARM Instruction Predicate Definitions.
 //
@@ -1026,6 +1031,80 @@
   }
 }
 
+// Tail calls.
+
+let isCall = 1, isTerminator = 1, isReturn = 1, isBarrier = 1 in {
+  // Darwin versions.
+  let Defs = [R0, R1, R2, R3, R9, R12,
+              D0, D1, D2, D3, D4, D5, D6, D7,
+              D16, D17, D18, D19, D20, D21, D22, D23, D24, D25, D26,
+              D27, D28, D29, D30, D31, PC],
+      Uses = [SP] in {
+  def TCRETURNdi : AInoP<(outs), (ins i32imm:$dst, variable_ops),
+                     Pseudo, IIC_Br,
+                     "@TC_RETURN","\t$dst", []>, Requires<[IsDarwin]>;
+
+  def TCRETURNri : AInoP<(outs), (ins tcGPR:$dst, variable_ops),
+                     Pseudo, IIC_Br,
+                     "@TC_RETURN","\t$dst", []>, Requires<[IsDarwin]>;
+
+  def TAILJMPd : ABXI<0b1010, (outs), (ins brtarget:$dst, variable_ops),
+                 IIC_Br, "b.w\t$dst  @ TAILCALL",
+                 []>, Requires<[IsDarwin]>;
+
+  def TAILJMPr : AXI<(outs), (ins tcGPR:$dst, variable_ops),
+                   BrMiscFrm, IIC_Br, "bx\t$dst  @ TAILCALL",
+                 []>, Requires<[IsDarwin]> {
+                 let Inst{7-4}   = 0b0001;
+                 let Inst{19-8}  = 0b111111111111;
+                 let Inst{27-20} = 0b00010010;
+                 let Inst{31-28} = 0b1110;
+  }
+
+  // FIXME: This is a hack so that MCInst lowering can preserve the TAILCALL
+  // marker on instructions, while still being able to relax.
+//  let isCodeGenOnly = 1 in {
+//    def TAILJMP_1 : Ii8PCRel<0xEB, RawFrm, (outs), (ins brtarget8:$dst),
+//                         "jmp\t$dst  @ TAILCALL", []>,
+//                         Requires<[IsARM, IsDarwin]>;
+  }
+
+  // Non-Darwin versions (the difference is R9).
+  let Defs = [R0, R1, R2, R3, R12,
+              D0, D1, D2, D3, D4, D5, D6, D7,
+              D16, D17, D18, D19, D20, D21, D22, D23, D24, D25, D26,
+              D27, D28, D29, D30, D31, PC],
+      Uses = [SP] in {
+  def TCRETURNdiND : AInoP<(outs), (ins i32imm:$dst, variable_ops),
+                     Pseudo, IIC_Br,
+                     "@TC_RETURN","\t$dst", []>, Requires<[IsNotDarwin]>;
+
+  def TCRETURNriND : AInoP<(outs), (ins tGPR:$dst, variable_ops),
+                     Pseudo, IIC_Br,
+                     "@TC_RETURN","\t$dst", []>, Requires<[IsNotDarwin]>;
+
+  def TAILJMPdND : ABXI<0b1010, (outs), (ins brtarget:$dst, variable_ops),
+                 IIC_Br, "b.w\t$dst  @ TAILCALL",
+                 []>, Requires<[IsNotDarwin]>;
+
+  def TAILJMPrND : AXI<(outs), (ins tGPR:$dst, variable_ops),
+                   BrMiscFrm, IIC_Br, "bx\t$dst  @ TAILCALL",
+                 []>, Requires<[IsNotDarwin]> {
+                 let Inst{7-4}   = 0b0001;
+                 let Inst{19-8}  = 0b111111111111;
+                 let Inst{27-20} = 0b00010010;
+                 let Inst{31-28} = 0b1110;
+  }
+
+  // FIXME: This is a hack so that MCInst lowering can preserve the TAILCALL
+  // marker on instructions, while still being able to relax.
+//  let isCodeGenOnly = 1 in {
+//    def TAILJMP_1ND : Ii8PCRel<0xEB, RawFrm, (outs), (ins brtarget8:$dst),
+//                         "jmp\t$dst  @ TAILCALL", []>,
+//                         Requires<[IsARM, IsNotDarwin]>;
+  }
+}
+
 let isBranch = 1, isTerminator = 1 in {
   // B is "predicable" since it can be xformed into a Bcc.
   let isBarrier = 1 in {
@@ -1397,6 +1476,14 @@
   let Inst{25} = 0;
 }
 
+// A version for the smaller set of tail call registers.
+let neverHasSideEffects = 1 in
+def MOVr_TC : AsI1<0b1101, (outs tcGPR:$dst), (ins tcGPR:$src), DPFrm, 
+                IIC_iMOVr, "mov", "\t$dst, $src", []>, UnaryDP {
+  let Inst{11-4} = 0b00000000;
+  let Inst{25} = 0;
+}
+
 def MOVs : AsI1<0b1101, (outs GPR:$dst), (ins so_reg:$src),
                 DPSoRegFrm, IIC_iMOVsr,
                 "mov", "\t$dst, $src", [(set GPR:$dst, so_reg:$src)]>, UnaryDP {
@@ -2620,6 +2707,24 @@
 
 // TODO: add,sub,and, 3-instr forms?
 
+// Tail calls
+def : ARMPat<(ARMtcret tcGPR:$dst),
+          (TCRETURNri tcGPR:$dst)>, Requires<[IsDarwin]>;
+
+def : ARMPat<(ARMtcret (i32 tglobaladdr:$dst)),
+          (TCRETURNdi texternalsym:$dst)>, Requires<[IsDarwin]>;
+
+def : ARMPat<(ARMtcret (i32 texternalsym:$dst)),
+          (TCRETURNdi texternalsym:$dst)>, Requires<[IsDarwin]>;
+
+def : ARMPat<(ARMtcret tcGPR:$dst),
+          (TCRETURNriND tcGPR:$dst)>, Requires<[IsNotDarwin]>;
+
+def : ARMPat<(ARMtcret (i32 tglobaladdr:$dst)),
+          (TCRETURNdiND texternalsym:$dst)>, Requires<[IsNotDarwin]>;
+
+def : ARMPat<(ARMtcret (i32 texternalsym:$dst)),
+          (TCRETURNdiND texternalsym:$dst)>, Requires<[IsNotDarwin]>;
 
 // Direct calls
 def : ARMPat<(ARMcall texternalsym:$func), (BL texternalsym:$func)>,

Modified: llvm/branches/Apple/Troughton/lib/Target/ARM/ARMRegisterInfo.td
URL: http://llvm.org/viewvc/llvm-project/llvm/branches/Apple/Troughton/lib/Target/ARM/ARMRegisterInfo.td?rev=106316&r1=106315&r2=106316&view=diff
==============================================================================
--- llvm/branches/Apple/Troughton/lib/Target/ARM/ARMRegisterInfo.td (original)
+++ llvm/branches/Apple/Troughton/lib/Target/ARM/ARMRegisterInfo.td Fri Jun 18 16:29:25 2010
@@ -349,6 +349,83 @@
   }];
 }
 
+// For tail calls, we can't use callee-saved registers, as they are restored
+// to the saved value before the tail call, which would clobber a call address.
+// Note, getMinimalPhysRegClass(R0) returns tGPR because of the names of
+// this class and the preceding one(!)  This is what we want.
+def tcGPR : RegisterClass<"ARM", [i32], 32, [R0, R1, R2, R3, R9, R12]> {
+  let MethodProtos = [{
+    iterator allocation_order_begin(const MachineFunction &MF) const;
+    iterator allocation_order_end(const MachineFunction &MF) const;
+  }];
+  let MethodBodies = [{
+    // R9 is available.
+    static const unsigned ARM_GPR_R9_TC[] = {
+      ARM::R0, ARM::R1, ARM::R2, ARM::R3,
+      ARM::R9, ARM::R12 };
+    // R9 is not available.
+    static const unsigned ARM_GPR_NOR9_TC[] = {
+      ARM::R0, ARM::R1, ARM::R2, ARM::R3,
+      ARM::R12 };
+
+    // For Thumb1 mode, we don't want to allocate hi regs at all, as we
+    // don't know how to spill them. If we make our prologue/epilogue code
+    // smarter at some point, we can go back to using the above allocation
+    // orders for the Thumb1 instructions that know how to use hi regs.
+    static const unsigned THUMB_GPR_AO_TC[] = {
+      ARM::R0, ARM::R1, ARM::R2, ARM::R3 };
+
+    tcGPRClass::iterator
+    tcGPRClass::allocation_order_begin(const MachineFunction &MF) const {
+      const TargetMachine &TM = MF.getTarget();
+      const ARMSubtarget &Subtarget = TM.getSubtarget<ARMSubtarget>();
+      if (Subtarget.isThumb1Only())
+        return THUMB_GPR_AO_TC;
+      if (Subtarget.isTargetDarwin()) {
+        if (Subtarget.isR9Reserved())
+          return ARM_GPR_NOR9_TC;
+        else
+          return ARM_GPR_R9_TC;
+      } else {
+        if (Subtarget.isR9Reserved())
+          return ARM_GPR_NOR9_TC;
+        else if (Subtarget.isThumb())
+          return ARM_GPR_R9_TC;
+        else
+          return ARM_GPR_R9_TC;
+      }
+    }
+
+    tcGPRClass::iterator
+    tcGPRClass::allocation_order_end(const MachineFunction &MF) const {
+      const TargetMachine &TM = MF.getTarget();
+      const ARMSubtarget &Subtarget = TM.getSubtarget<ARMSubtarget>();
+      GPRClass::iterator I;
+
+      if (Subtarget.isThumb1Only()) {
+        I = THUMB_GPR_AO_TC + (sizeof(THUMB_GPR_AO_TC)/sizeof(unsigned));
+        return I;
+      }
+
+      if (Subtarget.isTargetDarwin()) {
+        if (Subtarget.isR9Reserved())
+          I = ARM_GPR_NOR9_TC + (sizeof(ARM_GPR_NOR9_TC)/sizeof(unsigned));
+        else
+          I = ARM_GPR_R9_TC + (sizeof(ARM_GPR_R9_TC)/sizeof(unsigned));
+      } else {
+        if (Subtarget.isR9Reserved())
+          I = ARM_GPR_NOR9_TC + (sizeof(ARM_GPR_NOR9_TC)/sizeof(unsigned));
+        else if (Subtarget.isThumb())
+          I = ARM_GPR_R9_TC + (sizeof(ARM_GPR_R9_TC)/sizeof(unsigned));
+        else
+          I = ARM_GPR_R9_TC + (sizeof(ARM_GPR_R9_TC)/sizeof(unsigned));
+      }
+      return I;
+    }
+  }];
+}
+
+
 // Scalar single precision floating point register class..
 def SPR : RegisterClass<"ARM", [f32], 32, [S0, S1, S2, S3, S4, S5, S6, S7, S8,
   S9, S10, S11, S12, S13, S14, S15, S16, S17, S18, S19, S20, S21, S22,

Modified: llvm/branches/Apple/Troughton/lib/Target/ARM/Thumb1InstrInfo.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/branches/Apple/Troughton/lib/Target/ARM/Thumb1InstrInfo.cpp?rev=106316&r1=106315&r2=106316&view=diff
==============================================================================
--- llvm/branches/Apple/Troughton/lib/Target/ARM/Thumb1InstrInfo.cpp (original)
+++ llvm/branches/Apple/Troughton/lib/Target/ARM/Thumb1InstrInfo.cpp Fri Jun 18 16:29:25 2010
@@ -39,8 +39,8 @@
                                    const TargetRegisterClass *DestRC,
                                    const TargetRegisterClass *SrcRC,
                                    DebugLoc DL) const {
-  if (DestRC == ARM::GPRRegisterClass) {
-    if (SrcRC == ARM::GPRRegisterClass) {
+  if (DestRC == ARM::GPRRegisterClass || DestRC == ARM::tcGPRRegisterClass) {
+    if (SrcRC == ARM::GPRRegisterClass || SrcRC == ARM::tcGPRRegisterClass) {
       BuildMI(MBB, I, DL, get(ARM::tMOVgpr2gpr), DestReg).addReg(SrcReg);
       return true;
     } else if (SrcRC == ARM::tGPRRegisterClass) {
@@ -48,7 +48,7 @@
       return true;
     }
   } else if (DestRC == ARM::tGPRRegisterClass) {
-    if (SrcRC == ARM::GPRRegisterClass) {
+    if (SrcRC == ARM::GPRRegisterClass || SrcRC == ARM::tcGPRRegisterClass) {
       BuildMI(MBB, I, DL, get(ARM::tMOVgpr2tgpr), DestReg).addReg(SrcReg);
       return true;
     } else if (SrcRC == ARM::tGPRRegisterClass) {

Modified: llvm/branches/Apple/Troughton/lib/Target/ARM/Thumb2InstrInfo.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/branches/Apple/Troughton/lib/Target/ARM/Thumb2InstrInfo.cpp?rev=106316&r1=106315&r2=106316&view=diff
==============================================================================
--- llvm/branches/Apple/Troughton/lib/Target/ARM/Thumb2InstrInfo.cpp (original)
+++ llvm/branches/Apple/Troughton/lib/Target/ARM/Thumb2InstrInfo.cpp Fri Jun 18 16:29:25 2010
@@ -42,8 +42,8 @@
                               const TargetRegisterClass *DestRC,
                               const TargetRegisterClass *SrcRC,
                               DebugLoc DL) const {
-  if (DestRC == ARM::GPRRegisterClass) {
-    if (SrcRC == ARM::GPRRegisterClass) {
+  if (DestRC == ARM::GPRRegisterClass || DestRC == ARM::tcGPRRegisterClass) {
+    if (SrcRC == ARM::GPRRegisterClass || SrcRC == ARM::tcGPRRegisterClass) {
       BuildMI(MBB, I, DL, get(ARM::tMOVgpr2gpr), DestReg).addReg(SrcReg);
       return true;
     } else if (SrcRC == ARM::tGPRRegisterClass) {
@@ -51,7 +51,7 @@
       return true;
     }
   } else if (DestRC == ARM::tGPRRegisterClass) {
-    if (SrcRC == ARM::GPRRegisterClass) {
+    if (SrcRC == ARM::GPRRegisterClass || SrcRC == ARM::tcGPRRegisterClass) {
       BuildMI(MBB, I, DL, get(ARM::tMOVgpr2tgpr), DestReg).addReg(SrcReg);
       return true;
     } else if (SrcRC == ARM::tGPRRegisterClass) {
@@ -70,7 +70,8 @@
                     unsigned SrcReg, bool isKill, int FI,
                     const TargetRegisterClass *RC,
                     const TargetRegisterInfo *TRI) const {
-  if (RC == ARM::GPRRegisterClass || RC == ARM::tGPRRegisterClass) {
+  if (RC == ARM::GPRRegisterClass || RC == ARM::tGPRRegisterClass ||
+      RC == ARM::tcGPRRegisterClass) {
     DebugLoc DL;
     if (I != MBB.end()) DL = I->getDebugLoc();
 
@@ -95,7 +96,8 @@
                      unsigned DestReg, int FI,
                      const TargetRegisterClass *RC,
                      const TargetRegisterInfo *TRI) const {
-  if (RC == ARM::GPRRegisterClass || RC == ARM::tGPRRegisterClass) {
+  if (RC == ARM::GPRRegisterClass || RC == ARM::tGPRRegisterClass ||
+      RC == ARM::tcGPRRegisterClass) {
     DebugLoc DL;
     if (I != MBB.end()) DL = I->getDebugLoc();
 

Modified: llvm/branches/Apple/Troughton/lib/Target/X86/X86ISelLowering.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/branches/Apple/Troughton/lib/Target/X86/X86ISelLowering.cpp?rev=106316&r1=106315&r2=106316&view=diff
==============================================================================
--- llvm/branches/Apple/Troughton/lib/Target/X86/X86ISelLowering.cpp (original)
+++ llvm/branches/Apple/Troughton/lib/Target/X86/X86ISelLowering.cpp Fri Jun 18 16:29:25 2010
@@ -2150,17 +2150,12 @@
     Ops.push_back(InFlag);
 
   if (isTailCall) {
-    // If this is the first return lowered for this function, add the regs
-    // to the liveout set for the function.
-    if (MF.getRegInfo().liveout_empty()) {
-      SmallVector<CCValAssign, 16> RVLocs;
-      CCState CCInfo(CallConv, isVarArg, getTargetMachine(), RVLocs,
-                     *DAG.getContext());
-      CCInfo.AnalyzeCallResult(Ins, RetCC_X86);
-      for (unsigned i = 0; i != RVLocs.size(); ++i)
-        if (RVLocs[i].isRegLoc())
-          MF.getRegInfo().addLiveOut(RVLocs[i].getLocReg());
-    }
+    // We used to do:
+    //// If this is the first return lowered for this function, add the regs
+    //// to the liveout set for the function.
+    // This isn't right, although it's probably harmless on x86; liveouts
+    // should be computed from returns not tail calls.  Consider a void
+    // function making a tail call to a function returning int.
     return DAG.getNode(X86ISD::TC_RETURN, dl,
                        NodeTys, &Ops[0], Ops.size());
   }

Modified: llvm/branches/Apple/Troughton/test/CodeGen/ARM/call.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/branches/Apple/Troughton/test/CodeGen/ARM/call.ll?rev=106316&r1=106315&r2=106316&view=diff
==============================================================================
--- llvm/branches/Apple/Troughton/test/CodeGen/ARM/call.ll (original)
+++ llvm/branches/Apple/Troughton/test/CodeGen/ARM/call.ll Fri Jun 18 16:29:25 2010
@@ -8,16 +8,16 @@
 declare void @g(i32, i32, i32, i32)
 
 define void @f() {
-; CHECKV4: mov lr, pc
-; CHECKV5: blx
 ; CHECKELF: PLT
         call void @g( i32 1, i32 2, i32 3, i32 4 )
         ret void
 }
 
 define void @g.upgrd.1() {
+; CHECKV4: mov lr, pc
+; CHECKV5: blx
         %tmp = load i32 ()** @t         ; <i32 ()*> [#uses=1]
-        %tmp.upgrd.2 = tail call i32 %tmp( )            ; <i32> [#uses=0]
+        %tmp.upgrd.2 = call i32 %tmp( )            ; <i32> [#uses=0]
         ret void
 }
 

Copied: llvm/branches/Apple/Troughton/test/CodeGen/ARM/ifcvt6-tc.ll (from r106299, llvm/trunk/test/CodeGen/ARM/ifcvt6-tc.ll)
URL: http://llvm.org/viewvc/llvm-project/llvm/branches/Apple/Troughton/test/CodeGen/ARM/ifcvt6-tc.ll?p2=llvm/branches/Apple/Troughton/test/CodeGen/ARM/ifcvt6-tc.ll&p1=llvm/trunk/test/CodeGen/ARM/ifcvt6-tc.ll&r1=106299&r2=106316&rev=106316&view=diff
==============================================================================
--- llvm/trunk/test/CodeGen/ARM/ifcvt6-tc.ll (original)
+++ llvm/branches/Apple/Troughton/test/CodeGen/ARM/ifcvt6-tc.ll Fri Jun 18 16:29:25 2010
@@ -1,7 +1,7 @@
 ; RUN: llc < %s -march=arm -mtriple=arm-apple-darwin | \
 ; RUN:   grep cmpne | count 1
 ; RUN: llc < %s -march=arm -mtriple=arm-apple-darwin | \
-; RUN:   grep bhi | count 1
+; RUN:   grep bls | count 1
 ; Here, tail call wins over eliminating branches.  It is 1 fewer instruction
 ; and removes all stack accesses, so seems like a win.
 

Modified: llvm/branches/Apple/Troughton/test/CodeGen/ARM/ifcvt6.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/branches/Apple/Troughton/test/CodeGen/ARM/ifcvt6.ll?rev=106316&r1=106315&r2=106316&view=diff
==============================================================================
--- llvm/branches/Apple/Troughton/test/CodeGen/ARM/ifcvt6.ll (original)
+++ llvm/branches/Apple/Troughton/test/CodeGen/ARM/ifcvt6.ll Fri Jun 18 16:29:25 2010
@@ -11,7 +11,7 @@
 	br i1 %tmp7, label %cond_true, label %UnifiedReturnBlock
 
 cond_true:		; preds = %entry
-	%tmp10 = tail call i32 (...)* @bar( )		; <i32> [#uses=0]
+	%tmp10 = call i32 (...)* @bar( )		; <i32> [#uses=0]
 	ret void
 
 UnifiedReturnBlock:		; preds = %entry

Modified: llvm/branches/Apple/Troughton/test/CodeGen/ARM/insn-sched1.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/branches/Apple/Troughton/test/CodeGen/ARM/insn-sched1.ll?rev=106316&r1=106315&r2=106316&view=diff
==============================================================================
--- llvm/branches/Apple/Troughton/test/CodeGen/ARM/insn-sched1.ll (original)
+++ llvm/branches/Apple/Troughton/test/CodeGen/ARM/insn-sched1.ll Fri Jun 18 16:29:25 2010
@@ -4,7 +4,7 @@
 
 define i32 @test(i32 %x) {
         %tmp = trunc i32 %x to i16              ; <i16> [#uses=1]
-        %tmp2 = tail call i32 @f( i32 1, i16 %tmp )             ; <i32> [#uses=1]
+        %tmp2 = call i32 @f( i32 1, i16 %tmp )             ; <i32> [#uses=1]
         ret i32 %tmp2
 }
 

Modified: llvm/branches/Apple/Troughton/test/CodeGen/ARM/ldm.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/branches/Apple/Troughton/test/CodeGen/ARM/ldm.ll?rev=106316&r1=106315&r2=106316&view=diff
==============================================================================
--- llvm/branches/Apple/Troughton/test/CodeGen/ARM/ldm.ll (original)
+++ llvm/branches/Apple/Troughton/test/CodeGen/ARM/ldm.ll Fri Jun 18 16:29:25 2010
@@ -28,7 +28,7 @@
         %tmp = load i32* getelementptr ([0 x i32]* @X, i32 0, i32 1)            ; <i32> [#uses=1]
         %tmp3 = load i32* getelementptr ([0 x i32]* @X, i32 0, i32 2)           ; <i32> [#uses=1]
         %tmp5 = load i32* getelementptr ([0 x i32]* @X, i32 0, i32 3)           ; <i32> [#uses=1]
-        %tmp6 = tail call i32 @f2( i32 %tmp, i32 %tmp3, i32 %tmp5 )             ; <i32> [#uses=1]
+        %tmp6 = call i32 @f2( i32 %tmp, i32 %tmp3, i32 %tmp5 )             ; <i32> [#uses=1]
         ret i32 %tmp6
 }
 

Modified: llvm/branches/Apple/Troughton/test/CodeGen/Thumb2/thumb2-call.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/branches/Apple/Troughton/test/CodeGen/Thumb2/thumb2-call.ll?rev=106316&r1=106315&r2=106316&view=diff
==============================================================================
--- llvm/branches/Apple/Troughton/test/CodeGen/Thumb2/thumb2-call.ll (original)
+++ llvm/branches/Apple/Troughton/test/CodeGen/Thumb2/thumb2-call.ll Fri Jun 18 16:29:25 2010
@@ -22,6 +22,6 @@
 ; LINUX: h:
 ; LINUX: blx r0
         %tmp = load i32 ()** @t         ; <i32 ()*> [#uses=1]
-        %tmp.upgrd.2 = tail call i32 %tmp( )            ; <i32> [#uses=0]
+        %tmp.upgrd.2 = call i32 %tmp( )            ; <i32> [#uses=0]
         ret void
 }

Modified: llvm/branches/Apple/Troughton/test/CodeGen/Thumb2/thumb2-ifcvt1.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/branches/Apple/Troughton/test/CodeGen/Thumb2/thumb2-ifcvt1.ll?rev=106316&r1=106315&r2=106316&view=diff
==============================================================================
--- llvm/branches/Apple/Troughton/test/CodeGen/Thumb2/thumb2-ifcvt1.ll (original)
+++ llvm/branches/Apple/Troughton/test/CodeGen/Thumb2/thumb2-ifcvt1.ll Fri Jun 18 16:29:25 2010
@@ -76,7 +76,7 @@
 	br i1 %tmp1, label %cond_true, label %UnifiedReturnBlock
 
 cond_true:		; preds = %entry
-	tail call void @foo( i32 %b )
+	call void @foo( i32 %b )
 	ret void
 
 UnifiedReturnBlock:		; preds = %entry

Modified: llvm/branches/Apple/Troughton/test/CodeGen/Thumb2/thumb2-ifcvt2.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/branches/Apple/Troughton/test/CodeGen/Thumb2/thumb2-ifcvt2.ll?rev=106316&r1=106315&r2=106316&view=diff
==============================================================================
--- llvm/branches/Apple/Troughton/test/CodeGen/Thumb2/thumb2-ifcvt2.ll (original)
+++ llvm/branches/Apple/Troughton/test/CodeGen/Thumb2/thumb2-ifcvt2.ll Fri Jun 18 16:29:25 2010
@@ -13,7 +13,7 @@
 	br i1 %tmp7, label %cond_true, label %UnifiedReturnBlock
 
 cond_true:		; preds = %entry
-	%tmp10 = tail call i32 (...)* @bar( )		; <i32> [#uses=0]
+	%tmp10 = call i32 (...)* @bar( )		; <i32> [#uses=0]
 	ret void
 
 UnifiedReturnBlock:		; preds = %entry

Modified: llvm/branches/Apple/Troughton/test/CodeGen/Thumb2/thumb2-ldm.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/branches/Apple/Troughton/test/CodeGen/Thumb2/thumb2-ldm.ll?rev=106316&r1=106315&r2=106316&view=diff
==============================================================================
--- llvm/branches/Apple/Troughton/test/CodeGen/Thumb2/thumb2-ldm.ll (original)
+++ llvm/branches/Apple/Troughton/test/CodeGen/Thumb2/thumb2-ldm.ll Fri Jun 18 16:29:25 2010
@@ -8,7 +8,7 @@
 ; CHECK: pop {r7, pc}
         %tmp = load i32* getelementptr ([0 x i32]* @X, i32 0, i32 0)            ; <i32> [#uses=1]
         %tmp3 = load i32* getelementptr ([0 x i32]* @X, i32 0, i32 1)           ; <i32> [#uses=1]
-        %tmp4 = tail call i32 @f1( i32 %tmp, i32 %tmp3 )                ; <i32> [#uses=1]
+        %tmp4 = call i32 @f1( i32 %tmp, i32 %tmp3 )                ; <i32> [#uses=1]
         ret i32 %tmp4
 }
 
@@ -20,7 +20,7 @@
         %tmp = load i32* getelementptr ([0 x i32]* @X, i32 0, i32 2)            ; <i32> [#uses=1]
         %tmp3 = load i32* getelementptr ([0 x i32]* @X, i32 0, i32 3)           ; <i32> [#uses=1]
         %tmp5 = load i32* getelementptr ([0 x i32]* @X, i32 0, i32 4)           ; <i32> [#uses=1]
-        %tmp6 = tail call i32 @f2( i32 %tmp, i32 %tmp3, i32 %tmp5 )             ; <i32> [#uses=1]
+        %tmp6 = call i32 @f2( i32 %tmp, i32 %tmp3, i32 %tmp5 )             ; <i32> [#uses=1]
         ret i32 %tmp6
 }
 
@@ -31,7 +31,7 @@
         %tmp = load i32* getelementptr ([0 x i32]* @X, i32 0, i32 1)            ; <i32> [#uses=1]
         %tmp3 = load i32* getelementptr ([0 x i32]* @X, i32 0, i32 2)           ; <i32> [#uses=1]
         %tmp5 = load i32* getelementptr ([0 x i32]* @X, i32 0, i32 3)           ; <i32> [#uses=1]
-        %tmp6 = tail call i32 @f2( i32 %tmp, i32 %tmp3, i32 %tmp5 )             ; <i32> [#uses=1]
+        %tmp6 = call i32 @f2( i32 %tmp, i32 %tmp3, i32 %tmp5 )             ; <i32> [#uses=1]
         ret i32 %tmp6
 }
 

Modified: llvm/branches/Apple/Troughton/utils/TableGen/ARMDecoderEmitter.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/branches/Apple/Troughton/utils/TableGen/ARMDecoderEmitter.cpp?rev=106316&r1=106315&r2=106316&view=diff
==============================================================================
--- llvm/branches/Apple/Troughton/utils/TableGen/ARMDecoderEmitter.cpp (original)
+++ llvm/branches/Apple/Troughton/utils/TableGen/ARMDecoderEmitter.cpp Fri Jun 18 16:29:25 2010
@@ -1575,6 +1575,14 @@
     if (Name == "BXr9" || Name == "BMOVPCRX" || Name == "BMOVPCRXr9")
       return false;
 
+    // Tail calls are other patterns that generate existing instructions.
+    if (Name == "TCRETURNdi" || Name == "TCRETURNdiND" ||
+        Name == "TCRETURNri" || Name == "TCRETURNriND" ||
+        Name == "TAILJMPd"  || Name == "TAILJMPdND" ||
+        Name == "TAILJMPr"  || Name == "TAILJMPrND" ||
+        Name == "MOVr_TC")
+      return false;
+
     // VLDMQ/VSTMQ can be hanlded with the more generic VLDMD/VSTMD.
     if (Name == "VLDMQ" || Name == "VLDMQ_UPD" ||
         Name == "VSTMQ" || Name == "VSTMQ_UPD")

Modified: llvm/branches/Apple/Troughton/utils/TableGen/EDEmitter.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/branches/Apple/Troughton/utils/TableGen/EDEmitter.cpp?rev=106316&r1=106315&r2=106316&view=diff
==============================================================================
--- llvm/branches/Apple/Troughton/utils/TableGen/EDEmitter.cpp (original)
+++ llvm/branches/Apple/Troughton/utils/TableGen/EDEmitter.cpp Fri Jun 18 16:29:25 2010
@@ -570,6 +570,7 @@
 static int ARMFlagFromOpName(LiteralConstantEmitter *type,
                              const std::string &name) {
   REG("GPR");
+  REG("tcGPR");
   REG("cc_out");
   REG("s_cc_out");
   REG("tGPR");





More information about the llvm-branch-commits mailing list