[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