Major calling convention code refactoring.
Instead of awkwardly encoding calling-convention information with ISD::CALL,
ISD::FORMAL_ARGUMENTS, ISD::RET, and ISD::ARG_FLAGS nodes, TargetLowering
provides three virtual functions for targets to override:
LowerFormalArguments, LowerCall, and LowerRet, which replace the custom
lowering done on the special nodes. They provide the same information, but
in a more immediately usable format.
This also reworks much of the target-independent tail call logic. The
decision of whether or not to perform a tail call is now cleanly split
between target-independent portions, and the target dependent portion
in IsEligibleForTailCallOptimization.
This also synchronizes all in-tree targets, to help enable future
refactoring and feature work.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@78142 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/CodeGen/SelectionDAG/CallingConvLower.cpp b/lib/CodeGen/SelectionDAG/CallingConvLower.cpp
index e43af82..d6137a5 100644
--- a/lib/CodeGen/SelectionDAG/CallingConvLower.cpp
+++ b/lib/CodeGen/SelectionDAG/CallingConvLower.cpp
@@ -57,15 +57,16 @@
UsedRegs[Reg/32] |= 1 << (Reg&31);
}
-/// AnalyzeFormalArguments - Analyze an ISD::FORMAL_ARGUMENTS node,
+/// AnalyzeFormalArguments - Analyze an array of argument values,
/// incorporating info about the formals into this state.
-void CCState::AnalyzeFormalArguments(SDNode *TheArgs, CCAssignFn Fn) {
- unsigned NumArgs = TheArgs->getNumValues()-1;
-
+void
+CCState::AnalyzeFormalArguments(const SmallVectorImpl<ISD::InputArg> &Ins,
+ CCAssignFn Fn) {
+ unsigned NumArgs = Ins.size();
+
for (unsigned i = 0; i != NumArgs; ++i) {
- MVT ArgVT = TheArgs->getValueType(i);
- ISD::ArgFlagsTy ArgFlags =
- cast<ARG_FLAGSSDNode>(TheArgs->getOperand(3+i))->getArgFlags();
+ MVT ArgVT = Ins[i].VT;
+ ISD::ArgFlagsTy ArgFlags = Ins[i].Flags;
if (Fn(i, ArgVT, ArgVT, CCValAssign::Full, ArgFlags, *this)) {
#ifndef NDEBUG
cerr << "Formal argument #" << i << " has unhandled type "
@@ -76,14 +77,14 @@
}
}
-/// AnalyzeReturn - Analyze the returned values of an ISD::RET node,
+/// AnalyzeReturn - Analyze the returned values of a return,
/// incorporating info about the result values into this state.
-void CCState::AnalyzeReturn(SDNode *TheRet, CCAssignFn Fn) {
+void CCState::AnalyzeReturn(const SmallVectorImpl<ISD::OutputArg> &Outs,
+ CCAssignFn Fn) {
// Determine which register each value should be copied into.
- for (unsigned i = 0, e = TheRet->getNumOperands() / 2; i != e; ++i) {
- MVT VT = TheRet->getOperand(i*2+1).getValueType();
- ISD::ArgFlagsTy ArgFlags =
- cast<ARG_FLAGSSDNode>(TheRet->getOperand(i*2+2))->getArgFlags();
+ for (unsigned i = 0, e = Outs.size(); i != e; ++i) {
+ MVT VT = Outs[i].Val.getValueType();
+ ISD::ArgFlagsTy ArgFlags = Outs[i].Flags;
if (Fn(i, VT, VT, CCValAssign::Full, ArgFlags, *this)) {
#ifndef NDEBUG
cerr << "Return operand #" << i << " has unhandled type "
@@ -95,13 +96,14 @@
}
-/// AnalyzeCallOperands - Analyze an ISD::CALL node, incorporating info
-/// about the passed values into this state.
-void CCState::AnalyzeCallOperands(CallSDNode *TheCall, CCAssignFn Fn) {
- unsigned NumOps = TheCall->getNumArgs();
+/// AnalyzeCallOperands - Analyze the outgoing arguments to a call,
+/// incorporating info about the passed values into this state.
+void CCState::AnalyzeCallOperands(const SmallVectorImpl<ISD::OutputArg> &Outs,
+ CCAssignFn Fn) {
+ unsigned NumOps = Outs.size();
for (unsigned i = 0; i != NumOps; ++i) {
- MVT ArgVT = TheCall->getArg(i).getValueType();
- ISD::ArgFlagsTy ArgFlags = TheCall->getArgFlags(i);
+ MVT ArgVT = Outs[i].Val.getValueType();
+ ISD::ArgFlagsTy ArgFlags = Outs[i].Flags;
if (Fn(i, ArgVT, ArgVT, CCValAssign::Full, ArgFlags, *this)) {
#ifndef NDEBUG
cerr << "Call operand #" << i << " has unhandled type "
@@ -131,14 +133,13 @@
}
}
-/// AnalyzeCallResult - Analyze the return values of an ISD::CALL node,
+/// AnalyzeCallResult - Analyze the return values of a call,
/// incorporating info about the passed values into this state.
-void CCState::AnalyzeCallResult(CallSDNode *TheCall, CCAssignFn Fn) {
- for (unsigned i = 0, e = TheCall->getNumRetVals(); i != e; ++i) {
- MVT VT = TheCall->getRetValType(i);
- ISD::ArgFlagsTy Flags = ISD::ArgFlagsTy();
- if (TheCall->isInreg())
- Flags.setInReg();
+void CCState::AnalyzeCallResult(const SmallVectorImpl<ISD::InputArg> &Ins,
+ CCAssignFn Fn) {
+ for (unsigned i = 0, e = Ins.size(); i != e; ++i) {
+ MVT VT = Ins[i].VT;
+ ISD::ArgFlagsTy Flags = Ins[i].Flags;
if (Fn(i, VT, VT, CCValAssign::Full, Flags, *this)) {
#ifndef NDEBUG
cerr << "Call result #" << i << " has unhandled type "
diff --git a/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp b/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp
index 189d255..4be5b3d 100644
--- a/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp
+++ b/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp
@@ -823,11 +823,6 @@
// special case should be done as part of making LegalizeDAG non-recursive.
SimpleFinishLegalizing = false;
break;
- case ISD::CALL:
- // FIXME: Legalization for calls requires custom-lowering the call before
- // legalizing the operands! (I haven't looked into precisely why.)
- SimpleFinishLegalizing = false;
- break;
case ISD::EXTRACT_ELEMENT:
case ISD::FLT_ROUNDS_:
case ISD::SADDO:
@@ -849,7 +844,6 @@
case ISD::TRAMPOLINE:
case ISD::FRAMEADDR:
case ISD::RETURNADDR:
- case ISD::FORMAL_ARGUMENTS:
// These operations lie about being legal: when they claim to be legal,
// they should actually be custom-lowered.
Action = TLI.getOperationAction(Node->getOpcode(), Node->getValueType(0));
@@ -887,7 +881,6 @@
case ISD::BR_JT:
case ISD::BR_CC:
case ISD::BRCOND:
- case ISD::RET:
// Branches tweak the chain to include LastCALLSEQ_END
Ops[0] = DAG.getNode(ISD::TokenFactor, dl, MVT::Other, Ops[0],
LastCALLSEQ_END);
@@ -951,37 +944,7 @@
cerr << "NODE: "; Node->dump(&DAG); cerr << "\n";
#endif
llvm_unreachable("Do not know how to legalize this operator!");
- case ISD::CALL:
- // The only option for this is to custom lower it.
- Tmp3 = TLI.LowerOperation(Result.getValue(0), DAG);
- assert(Tmp3.getNode() && "Target didn't custom lower this node!");
- // A call within a calling sequence must be legalized to something
- // other than the normal CALLSEQ_END. Violating this gets Legalize
- // into an infinite loop.
- assert ((!IsLegalizingCall ||
- Node->getOpcode() != ISD::CALL ||
- Tmp3.getNode()->getOpcode() != ISD::CALLSEQ_END) &&
- "Nested CALLSEQ_START..CALLSEQ_END not supported.");
- // The number of incoming and outgoing values should match; unless the final
- // outgoing value is a flag.
- assert((Tmp3.getNode()->getNumValues() == Result.getNode()->getNumValues() ||
- (Tmp3.getNode()->getNumValues() == Result.getNode()->getNumValues() + 1 &&
- Tmp3.getNode()->getValueType(Tmp3.getNode()->getNumValues() - 1) ==
- MVT::Flag)) &&
- "Lowering call/formal_arguments produced unexpected # results!");
-
- // Since CALL/FORMAL_ARGUMENTS nodes produce multiple values, make sure to
- // remember that we legalized all of them, so it doesn't get relegalized.
- for (unsigned i = 0, e = Tmp3.getNode()->getNumValues(); i != e; ++i) {
- if (Tmp3.getNode()->getValueType(i) == MVT::Flag)
- continue;
- Tmp1 = LegalizeOp(Tmp3.getValue(i));
- if (Op.getResNo() == i)
- Tmp2 = Tmp1;
- AddLegalizedOperand(SDValue(Node, i), Tmp1);
- }
- return Tmp2;
case ISD::BUILD_VECTOR:
switch (TLI.getOperationAction(ISD::BUILD_VECTOR, Node->getValueType(0))) {
default: llvm_unreachable("This action is not supported yet!");
@@ -1905,7 +1868,9 @@
const Type *RetTy = Node->getValueType(0).getTypeForMVT();
std::pair<SDValue, SDValue> CallInfo =
TLI.LowerCallTo(InChain, RetTy, isSigned, !isSigned, false, false,
- 0, CallingConv::C, false, Callee, Args, DAG,
+ 0, CallingConv::C, false,
+ /*isReturnValueUsed=*/true,
+ Callee, Args, DAG,
Node->getDebugLoc());
// Legalize the call sequence, starting with the chain. This will advance
@@ -2311,6 +2276,7 @@
std::pair<SDValue, SDValue> CallResult =
TLI.LowerCallTo(Node->getOperand(0), Type::VoidTy,
false, false, false, false, 0, CallingConv::C, false,
+ /*isReturnValueUsed=*/true,
DAG.getExternalSymbol("abort", TLI.getPointerTy()),
Args, DAG, dl);
Results.push_back(CallResult.second);
diff --git a/lib/CodeGen/SelectionDAG/LegalizeTypes.cpp b/lib/CodeGen/SelectionDAG/LegalizeTypes.cpp
index 82d98a7..4e4c69a 100644
--- a/lib/CodeGen/SelectionDAG/LegalizeTypes.cpp
+++ b/lib/CodeGen/SelectionDAG/LegalizeTypes.cpp
@@ -1019,7 +1019,9 @@
const Type *RetTy = RetVT.getTypeForMVT();
std::pair<SDValue,SDValue> CallInfo =
TLI.LowerCallTo(DAG.getEntryNode(), RetTy, isSigned, !isSigned, false,
- false, 0, CallingConv::C, false, Callee, Args, DAG, dl);
+ false, 0, CallingConv::C, false,
+ /*isReturnValueUsed=*/true,
+ Callee, Args, DAG, dl);
return CallInfo.first;
}
diff --git a/lib/CodeGen/SelectionDAG/LegalizeVectorOps.cpp b/lib/CodeGen/SelectionDAG/LegalizeVectorOps.cpp
index 335c73c..58a0927 100644
--- a/lib/CodeGen/SelectionDAG/LegalizeVectorOps.cpp
+++ b/lib/CodeGen/SelectionDAG/LegalizeVectorOps.cpp
@@ -20,8 +20,8 @@
// type i8 which must be promoted.
//
// This does not legalize vector manipulations like ISD::BUILD_VECTOR,
-// or operations that happen to take a vector which are custom-lowered like
-// ISD::CALL; the legalization for such operations never produces nodes
+// or operations that happen to take a vector which are custom-lowered;
+// the legalization for such operations never produces nodes
// with illegal types, so it's okay to put off legalizing them until
// SelectionDAG::Legalize runs.
//
diff --git a/lib/CodeGen/SelectionDAG/SelectionDAG.cpp b/lib/CodeGen/SelectionDAG/SelectionDAG.cpp
index a0e6054..87a0b1f 100644
--- a/lib/CodeGen/SelectionDAG/SelectionDAG.cpp
+++ b/lib/CodeGen/SelectionDAG/SelectionDAG.cpp
@@ -366,9 +366,6 @@
case ISD::ExternalSymbol:
llvm_unreachable("Should only be used on nodes with operands");
default: break; // Normal nodes don't need extra info.
- case ISD::ARG_FLAGS:
- ID.AddInteger(cast<ARG_FLAGSSDNode>(N)->getArgFlags().getRawBits());
- break;
case ISD::TargetConstant:
case ISD::Constant:
ID.AddPointer(cast<ConstantSDNode>(N)->getConstantIntValue());
@@ -430,12 +427,6 @@
ID.AddInteger(CP->getTargetFlags());
break;
}
- case ISD::CALL: {
- const CallSDNode *Call = cast<CallSDNode>(N);
- ID.AddInteger(Call->getCallingConv());
- ID.AddInteger(Call->isVarArg());
- break;
- }
case ISD::LOAD: {
const LoadSDNode *LD = cast<LoadSDNode>(N);
ID.AddInteger(LD->getMemoryVT().getRawBits());
@@ -1103,20 +1094,6 @@
return SDValue(N, 0);
}
-SDValue SelectionDAG::getArgFlags(ISD::ArgFlagsTy Flags) {
- FoldingSetNodeID ID;
- AddNodeIDNode(ID, ISD::ARG_FLAGS, getVTList(MVT::Other), 0, 0);
- ID.AddInteger(Flags.getRawBits());
- void *IP = 0;
- if (SDNode *E = CSEMap.FindNodeOrInsertPos(ID, IP))
- return SDValue(E, 0);
- SDNode *N = NodeAllocator.Allocate<ARG_FLAGSSDNode>();
- new (N) ARG_FLAGSSDNode(Flags);
- CSEMap.InsertNode(N, IP);
- AllNodes.push_back(N);
- return SDValue(N, 0);
-}
-
SDValue SelectionDAG::getValueType(MVT VT) {
if (VT.isSimple() && (unsigned)VT.getSimpleVT() >= ValueTypeNodes.size())
ValueTypeNodes.resize(VT.getSimpleVT()+1);
@@ -2995,6 +2972,29 @@
return getNode(Opcode, DL, VT, Ops, 5);
}
+/// getStackArgumentTokenFactor - Compute a TokenFactor to force all
+/// the incoming stack arguments to be loaded from the stack.
+SDValue SelectionDAG::getStackArgumentTokenFactor(SDValue Chain) {
+ SmallVector<SDValue, 8> ArgChains;
+
+ // Include the original chain at the beginning of the list. When this is
+ // used by target LowerCall hooks, this helps legalize find the
+ // CALLSEQ_BEGIN node.
+ ArgChains.push_back(Chain);
+
+ // Add a chain value for each stack argument.
+ for (SDNode::use_iterator U = getEntryNode().getNode()->use_begin(),
+ UE = getEntryNode().getNode()->use_end(); U != UE; ++U)
+ if (LoadSDNode *L = dyn_cast<LoadSDNode>(*U))
+ if (FrameIndexSDNode *FI = dyn_cast<FrameIndexSDNode>(L->getBasePtr()))
+ if (FI->getIndex() < 0)
+ ArgChains.push_back(SDValue(L, 1));
+
+ // Build a tokenfactor for all the chains.
+ return getNode(ISD::TokenFactor, Chain.getDebugLoc(), MVT::Other,
+ &ArgChains[0], ArgChains.size());
+}
+
/// getMemsetValue - Vectorized representation of the memset value
/// operand.
static SDValue getMemsetValue(SDValue Value, MVT VT, SelectionDAG &DAG,
@@ -3386,6 +3386,7 @@
std::pair<SDValue,SDValue> CallResult =
TLI.LowerCallTo(Chain, Type::VoidTy,
false, false, false, false, 0, CallingConv::C, false,
+ /*isReturnValueUsed=*/false,
getExternalSymbol(TLI.getLibcallName(RTLIB::MEMCPY),
TLI.getPointerTy()),
Args, *this, dl);
@@ -3433,6 +3434,7 @@
std::pair<SDValue,SDValue> CallResult =
TLI.LowerCallTo(Chain, Type::VoidTy,
false, false, false, false, 0, CallingConv::C, false,
+ /*isReturnValueUsed=*/false,
getExternalSymbol(TLI.getLibcallName(RTLIB::MEMMOVE),
TLI.getPointerTy()),
Args, *this, dl);
@@ -3486,6 +3488,7 @@
std::pair<SDValue,SDValue> CallResult =
TLI.LowerCallTo(Chain, Type::VoidTy,
false, false, false, false, 0, CallingConv::C, false,
+ /*isReturnValueUsed=*/false,
getExternalSymbol(TLI.getLibcallName(RTLIB::MEMSET),
TLI.getPointerTy()),
Args, *this, dl);
@@ -3616,32 +3619,6 @@
}
SDValue
-SelectionDAG::getCall(unsigned CallingConv, DebugLoc dl, bool IsVarArgs,
- bool IsTailCall, bool IsInreg, SDVTList VTs,
- const SDValue *Operands, unsigned NumOperands,
- unsigned NumFixedArgs) {
- // Do not include isTailCall in the folding set profile.
- FoldingSetNodeID ID;
- AddNodeIDNode(ID, ISD::CALL, VTs, Operands, NumOperands);
- ID.AddInteger(CallingConv);
- ID.AddInteger(IsVarArgs);
- void *IP = 0;
- if (SDNode *E = CSEMap.FindNodeOrInsertPos(ID, IP)) {
- // Instead of including isTailCall in the folding set, we just
- // set the flag of the existing node.
- if (!IsTailCall)
- cast<CallSDNode>(E)->setNotTailCall();
- return SDValue(E, 0);
- }
- SDNode *N = NodeAllocator.Allocate<CallSDNode>();
- new (N) CallSDNode(CallingConv, dl, IsVarArgs, IsTailCall, IsInreg,
- VTs, Operands, NumOperands, NumFixedArgs);
- CSEMap.InsertNode(N, IP);
- AllNodes.push_back(N);
- return SDValue(N, 0);
-}
-
-SDValue
SelectionDAG::getLoad(ISD::MemIndexedMode AM, DebugLoc dl,
ISD::LoadExtType ExtType, MVT VT, SDValue Chain,
SDValue Ptr, SDValue Offset,
@@ -5206,7 +5183,6 @@
case ISD::AssertZext: return "AssertZext";
case ISD::BasicBlock: return "BasicBlock";
- case ISD::ARG_FLAGS: return "ArgFlags";
case ISD::VALUETYPE: return "ValueType";
case ISD::Register: return "Register";
@@ -5254,8 +5230,6 @@
case ISD::EH_LABEL: return "eh_label";
case ISD::DECLARE: return "declare";
case ISD::HANDLENODE: return "handlenode";
- case ISD::FORMAL_ARGUMENTS: return "formal_arguments";
- case ISD::CALL: return "call";
// Unary operators
case ISD::FABS: return "fabs";
@@ -5364,7 +5338,6 @@
case ISD::BR_JT: return "br_jt";
case ISD::BRCOND: return "brcond";
case ISD::BR_CC: return "br_cc";
- case ISD::RET: return "ret";
case ISD::CALLSEQ_START: return "callseq_start";
case ISD::CALLSEQ_END: return "callseq_end";
@@ -5566,8 +5539,6 @@
OS << "<" << M->MO.getValue() << ":" << M->MO.getOffset() << ">";
else
OS << "<null:" << M->MO.getOffset() << ">";
- } else if (const ARG_FLAGSSDNode *N = dyn_cast<ARG_FLAGSSDNode>(this)) {
- OS << N->getArgFlags().getArgFlagsString();
} else if (const VTSDNode *N = dyn_cast<VTSDNode>(this)) {
OS << ":" << N->getVT().getMVTString();
}
diff --git a/lib/CodeGen/SelectionDAG/SelectionDAGBuild.cpp b/lib/CodeGen/SelectionDAG/SelectionDAGBuild.cpp
index 0c410fb..1eb87e8 100644
--- a/lib/CodeGen/SelectionDAG/SelectionDAGBuild.cpp
+++ b/lib/CodeGen/SelectionDAG/SelectionDAGBuild.cpp
@@ -17,6 +17,7 @@
#include "llvm/ADT/SmallSet.h"
#include "llvm/Analysis/AliasAnalysis.h"
#include "llvm/Constants.h"
+#include "llvm/Constants.h"
#include "llvm/CallingConv.h"
#include "llvm/DerivedTypes.h"
#include "llvm/Function.h"
@@ -753,6 +754,7 @@
PendingExports.clear();
DAG.clear();
CurDebugLoc = DebugLoc::getUnknownLoc();
+ HasTailCall = false;
}
/// getRoot - Return the current virtual root of the Selection DAG,
@@ -934,14 +936,8 @@
void SelectionDAGLowering::visitRet(ReturnInst &I) {
- if (I.getNumOperands() == 0) {
- DAG.setRoot(DAG.getNode(ISD::RET, getCurDebugLoc(),
- MVT::Other, getControlRoot()));
- return;
- }
-
- SmallVector<SDValue, 8> NewValues;
- NewValues.push_back(getControlRoot());
+ SDValue Chain = getControlRoot();
+ SmallVector<ISD::OutputArg, 8> Outs;
for (unsigned i = 0, e = I.getNumOperands(); i != e; ++i) {
SmallVector<MVT, 4> ValueVTs;
ComputeValueVTs(TLI, I.getOperand(i)->getType(), ValueVTs);
@@ -988,14 +984,16 @@
else if (F->paramHasAttr(0, Attribute::ZExt))
Flags.setZExt();
- for (unsigned i = 0; i < NumParts; ++i) {
- NewValues.push_back(Parts[i]);
- NewValues.push_back(DAG.getArgFlags(Flags));
- }
+ for (unsigned i = 0; i < NumParts; ++i)
+ Outs.push_back(ISD::OutputArg(Flags, Parts[i], /*isfixed=*/true));
}
}
- DAG.setRoot(DAG.getNode(ISD::RET, getCurDebugLoc(), MVT::Other,
- &NewValues[0], NewValues.size()));
+
+ bool isVarArg = DAG.getMachineFunction().getFunction()->isVarArg();
+ unsigned CallConv = DAG.getMachineFunction().getFunction()->getCallingConv();
+ Chain = TLI.LowerReturn(Chain, CallConv, isVarArg,
+ Outs, getCurDebugLoc(), DAG);
+ DAG.setRoot(Chain);
}
/// CopyToExportRegsIfNeeded - If the given value has virtual registers
@@ -4346,9 +4344,76 @@
}
}
+/// Test if the given instruction is in a position to be optimized
+/// with a tail-call. This roughly means that it's in a block with
+/// a return and there's nothing that needs to be scheduled
+/// between it and the return.
+///
+/// This function only tests target-independent requirements.
+/// For target-dependent requirements, a target should override
+/// TargetLowering::IsEligibleForTailCallOptimization.
+///
+static bool
+isInTailCallPosition(const Instruction *I, Attributes RetAttr,
+ const TargetLowering &TLI) {
+ const BasicBlock *ExitBB = I->getParent();
+ const TerminatorInst *Term = ExitBB->getTerminator();
+ const ReturnInst *Ret = dyn_cast<ReturnInst>(Term);
+ const Function *F = ExitBB->getParent();
+
+ // The block must end in a return statement or an unreachable.
+ if (!Ret && !isa<UnreachableInst>(Term)) return false;
+
+ // If I will have a chain, make sure no other instruction that will have a
+ // chain interposes between I and the return.
+ if (I->mayHaveSideEffects() || I->mayReadFromMemory() ||
+ !I->isSafeToSpeculativelyExecute())
+ for (BasicBlock::const_iterator BBI = prior(prior(ExitBB->end())); ;
+ --BBI) {
+ if (&*BBI == I)
+ break;
+ if (BBI->mayHaveSideEffects() || BBI->mayReadFromMemory() ||
+ !BBI->isSafeToSpeculativelyExecute())
+ return false;
+ }
+
+ // If the block ends with a void return or unreachable, it doesn't matter
+ // what the call's return type is.
+ if (!Ret || Ret->getNumOperands() == 0) return true;
+
+ // Conservatively require the attributes of the call to match those of
+ // the return.
+ if (F->getAttributes().getRetAttributes() != RetAttr)
+ return false;
+
+ // Otherwise, make sure the unmodified return value of I is the return value.
+ for (const Instruction *U = dyn_cast<Instruction>(Ret->getOperand(0)); ;
+ U = dyn_cast<Instruction>(U->getOperand(0))) {
+ if (!U)
+ return false;
+ if (!U->hasOneUse())
+ return false;
+ if (U == I)
+ break;
+ // Check for a truly no-op truncate.
+ if (isa<TruncInst>(U) &&
+ TLI.isTruncateFree(U->getOperand(0)->getType(), U->getType()))
+ continue;
+ // Check for a truly no-op bitcast.
+ if (isa<BitCastInst>(U) &&
+ (U->getOperand(0)->getType() == U->getType() ||
+ (isa<PointerType>(U->getOperand(0)->getType()) &&
+ isa<PointerType>(U->getType()))))
+ continue;
+ // Otherwise it's not a true no-op.
+ return false;
+ }
+
+ return true;
+}
void SelectionDAGLowering::LowerCallTo(CallSite CS, SDValue Callee,
- bool IsTailCall,
+ bool isTailCall,
MachineBasicBlock *LandingPad) {
const PointerType *PT = cast<PointerType>(CS.getCalledValue()->getType());
const FunctionType *FTy = cast<FunctionType>(PT->getElementType());
@@ -4358,8 +4423,9 @@
TargetLowering::ArgListTy Args;
TargetLowering::ArgListEntry Entry;
Args.reserve(CS.arg_size());
+ unsigned j = 1;
for (CallSite::arg_iterator i = CS.arg_begin(), e = CS.arg_end();
- i != e; ++i) {
+ i != e; ++i, ++j) {
SDValue ArgNode = getValue(*i);
Entry.Node = ArgNode; Entry.Ty = (*i)->getType();
@@ -4385,17 +4451,38 @@
getControlRoot(), BeginLabel));
}
+ // Check if target-independent constraints permit a tail call here.
+ // Target-dependent constraints are checked within TLI.LowerCallTo.
+ if (isTailCall &&
+ !isInTailCallPosition(CS.getInstruction(),
+ CS.getAttributes().getRetAttributes(),
+ TLI))
+ isTailCall = false;
+
std::pair<SDValue,SDValue> Result =
TLI.LowerCallTo(getRoot(), CS.getType(),
CS.paramHasAttr(0, Attribute::SExt),
CS.paramHasAttr(0, Attribute::ZExt), FTy->isVarArg(),
CS.paramHasAttr(0, Attribute::InReg), FTy->getNumParams(),
CS.getCallingConv(),
- IsTailCall && PerformTailCallOpt,
+ isTailCall,
+ !CS.getInstruction()->use_empty(),
Callee, Args, DAG, getCurDebugLoc());
- if (CS.getType() != Type::VoidTy)
+ assert((isTailCall || CS.getType() == Type::VoidTy ||
+ Result.first.getNode()) &&
+ "Non-null value expected with non-void non-tail call!");
+ assert((isTailCall || Result.second.getNode()) &&
+ "Non-null chain expected with non-tail call!");
+ assert((Result.second.getNode() || !Result.first.getNode()) &&
+ "Null value expected with tail call!");
+ if (Result.first.getNode())
setValue(CS.getInstruction(), Result.first);
- DAG.setRoot(Result.second);
+ // As a special case, a null chain means that a tail call has
+ // been emitted and the DAG root is already updated.
+ if (Result.second.getNode())
+ DAG.setRoot(Result.second);
+ else
+ HasTailCall = true;
if (LandingPad && MMI) {
// Insert a label at the end of the invoke call to mark the try range. This
@@ -4484,7 +4571,12 @@
else
Callee = DAG.getExternalSymbol(RenameFn, TLI.getPointerTy());
- LowerCallTo(&I, Callee, I.isTailCall());
+ // Check if we can potentially perform a tail call. More detailed
+ // checking is be done within LowerCallTo, after more information
+ // about the call is known.
+ bool isTailCall = PerformTailCallOpt && I.isTailCall();
+
+ LowerCallTo(&I, Callee, isTailCall);
}
@@ -5431,13 +5523,18 @@
Entry.Ty = TLI.getTargetData()->getIntPtrType();
Args.push_back(Entry);
+ bool isTailCall = PerformTailCallOpt &&
+ isInTailCallPosition(&I, Attribute::None, TLI);
std::pair<SDValue,SDValue> Result =
TLI.LowerCallTo(getRoot(), I.getType(), false, false, false, false,
- 0, CallingConv::C, PerformTailCallOpt,
+ 0, CallingConv::C, isTailCall,
+ /*isReturnValueUsed=*/true,
DAG.getExternalSymbol("malloc", IntPtr),
Args, DAG, getCurDebugLoc());
- setValue(&I, Result.first); // Pointers always fit in registers
- DAG.setRoot(Result.second);
+ if (Result.first.getNode())
+ setValue(&I, Result.first); // Pointers always fit in registers
+ if (Result.second.getNode())
+ DAG.setRoot(Result.second);
}
void SelectionDAGLowering::visitFree(FreeInst &I) {
@@ -5447,12 +5544,16 @@
Entry.Ty = TLI.getTargetData()->getIntPtrType();
Args.push_back(Entry);
MVT IntPtr = TLI.getPointerTy();
+ bool isTailCall = PerformTailCallOpt &&
+ isInTailCallPosition(&I, Attribute::None, TLI);
std::pair<SDValue,SDValue> Result =
TLI.LowerCallTo(getRoot(), Type::VoidTy, false, false, false, false,
- 0, CallingConv::C, PerformTailCallOpt,
+ 0, CallingConv::C, isTailCall,
+ /*isReturnValueUsed=*/true,
DAG.getExternalSymbol("free", IntPtr), Args, DAG,
getCurDebugLoc());
- DAG.setRoot(Result.second);
+ if (Result.second.getNode())
+ DAG.setRoot(Result.second);
}
void SelectionDAGLowering::visitVAStart(CallInst &I) {
@@ -5486,154 +5587,24 @@
DAG.getSrcValue(I.getOperand(2))));
}
-/// TargetLowering::LowerArguments - This is the default LowerArguments
-/// implementation, which just inserts a FORMAL_ARGUMENTS node. FIXME: When all
-/// targets are migrated to using FORMAL_ARGUMENTS, this hook should be
-/// integrated into SDISel.
-void TargetLowering::LowerArguments(Function &F, SelectionDAG &DAG,
- SmallVectorImpl<SDValue> &ArgValues,
- DebugLoc dl) {
- // Add CC# and isVararg as operands to the FORMAL_ARGUMENTS node.
- SmallVector<SDValue, 3+16> Ops;
- Ops.push_back(DAG.getRoot());
- Ops.push_back(DAG.getConstant(F.getCallingConv(), getPointerTy()));
- Ops.push_back(DAG.getConstant(F.isVarArg(), getPointerTy()));
-
- // Add one result value for each formal argument.
- SmallVector<MVT, 16> RetVals;
- unsigned j = 1;
- for (Function::arg_iterator I = F.arg_begin(), E = F.arg_end();
- I != E; ++I, ++j) {
- SmallVector<MVT, 4> ValueVTs;
- ComputeValueVTs(*this, I->getType(), ValueVTs);
- for (unsigned Value = 0, NumValues = ValueVTs.size();
- Value != NumValues; ++Value) {
- MVT VT = ValueVTs[Value];
- const Type *ArgTy = VT.getTypeForMVT();
- ISD::ArgFlagsTy Flags;
- unsigned OriginalAlignment =
- getTargetData()->getABITypeAlignment(ArgTy);
-
- if (F.paramHasAttr(j, Attribute::ZExt))
- Flags.setZExt();
- if (F.paramHasAttr(j, Attribute::SExt))
- Flags.setSExt();
- if (F.paramHasAttr(j, Attribute::InReg))
- Flags.setInReg();
- if (F.paramHasAttr(j, Attribute::StructRet))
- Flags.setSRet();
- if (F.paramHasAttr(j, Attribute::ByVal)) {
- Flags.setByVal();
- const PointerType *Ty = cast<PointerType>(I->getType());
- const Type *ElementTy = Ty->getElementType();
- unsigned FrameAlign = getByValTypeAlignment(ElementTy);
- unsigned FrameSize = getTargetData()->getTypeAllocSize(ElementTy);
- // For ByVal, alignment should be passed from FE. BE will guess if
- // this info is not there but there are cases it cannot get right.
- if (F.getParamAlignment(j))
- FrameAlign = F.getParamAlignment(j);
- Flags.setByValAlign(FrameAlign);
- Flags.setByValSize(FrameSize);
- }
- if (F.paramHasAttr(j, Attribute::Nest))
- Flags.setNest();
- Flags.setOrigAlign(OriginalAlignment);
-
- MVT RegisterVT = getRegisterType(VT);
- unsigned NumRegs = getNumRegisters(VT);
- for (unsigned i = 0; i != NumRegs; ++i) {
- RetVals.push_back(RegisterVT);
- ISD::ArgFlagsTy MyFlags = Flags;
- if (NumRegs > 1 && i == 0)
- MyFlags.setSplit();
- // if it isn't first piece, alignment must be 1
- else if (i > 0)
- MyFlags.setOrigAlign(1);
- Ops.push_back(DAG.getArgFlags(MyFlags));
- }
- }
- }
-
- RetVals.push_back(MVT::Other);
-
- // Create the node.
- SDNode *Result = DAG.getNode(ISD::FORMAL_ARGUMENTS, dl,
- DAG.getVTList(&RetVals[0], RetVals.size()),
- &Ops[0], Ops.size()).getNode();
-
- // Prelower FORMAL_ARGUMENTS. This isn't required for functionality, but
- // allows exposing the loads that may be part of the argument access to the
- // first DAGCombiner pass.
- SDValue TmpRes = LowerOperation(SDValue(Result, 0), DAG);
-
- // The number of results should match up, except that the lowered one may have
- // an extra flag result.
- assert((Result->getNumValues() == TmpRes.getNode()->getNumValues() ||
- (Result->getNumValues()+1 == TmpRes.getNode()->getNumValues() &&
- TmpRes.getValue(Result->getNumValues()).getValueType() == MVT::Flag))
- && "Lowering produced unexpected number of results!");
-
- // The FORMAL_ARGUMENTS node itself is likely no longer needed.
- if (Result != TmpRes.getNode() && Result->use_empty()) {
- HandleSDNode Dummy(DAG.getRoot());
- DAG.RemoveDeadNode(Result);
- }
-
- Result = TmpRes.getNode();
-
- unsigned NumArgRegs = Result->getNumValues() - 1;
- DAG.setRoot(SDValue(Result, NumArgRegs));
-
- // Set up the return result vector.
- unsigned i = 0;
- unsigned Idx = 1;
- for (Function::arg_iterator I = F.arg_begin(), E = F.arg_end(); I != E;
- ++I, ++Idx) {
- SmallVector<MVT, 4> ValueVTs;
- ComputeValueVTs(*this, I->getType(), ValueVTs);
- for (unsigned Value = 0, NumValues = ValueVTs.size();
- Value != NumValues; ++Value) {
- MVT VT = ValueVTs[Value];
- MVT PartVT = getRegisterType(VT);
-
- unsigned NumParts = getNumRegisters(VT);
- SmallVector<SDValue, 4> Parts(NumParts);
- for (unsigned j = 0; j != NumParts; ++j)
- Parts[j] = SDValue(Result, i++);
-
- ISD::NodeType AssertOp = ISD::DELETED_NODE;
- if (F.paramHasAttr(Idx, Attribute::SExt))
- AssertOp = ISD::AssertSext;
- else if (F.paramHasAttr(Idx, Attribute::ZExt))
- AssertOp = ISD::AssertZext;
-
- ArgValues.push_back(getCopyFromParts(DAG, dl, &Parts[0], NumParts,
- PartVT, VT, AssertOp));
- }
- }
- assert(i == NumArgRegs && "Argument register count mismatch!");
-}
-
-
/// TargetLowering::LowerCallTo - This is the default LowerCallTo
-/// implementation, which just inserts an ISD::CALL node, which is later custom
-/// lowered by the target to something concrete. FIXME: When all targets are
-/// migrated to using ISD::CALL, this hook should be integrated into SDISel.
+/// implementation, which just calls LowerCall.
+/// FIXME: When all targets are
+/// migrated to using LowerCall, this hook should be integrated into SDISel.
std::pair<SDValue, SDValue>
TargetLowering::LowerCallTo(SDValue Chain, const Type *RetTy,
bool RetSExt, bool RetZExt, bool isVarArg,
bool isInreg, unsigned NumFixedArgs,
- unsigned CallingConv, bool isTailCall,
+ unsigned CallConv, bool isTailCall,
+ bool isReturnValueUsed,
SDValue Callee,
ArgListTy &Args, SelectionDAG &DAG, DebugLoc dl) {
+
assert((!isTailCall || PerformTailCallOpt) &&
"isTailCall set when tail-call optimizations are disabled!");
- SmallVector<SDValue, 32> Ops;
- Ops.push_back(Chain); // Op#0 - Chain
- Ops.push_back(Callee);
-
// Handle all of the outgoing arguments.
+ SmallVector<ISD::OutputArg, 32> Outs;
for (unsigned i = 0, e = Args.size(); i != e; ++i) {
SmallVector<MVT, 4> ValueVTs;
ComputeValueVTs(*this, Args[i].Ty, ValueVTs);
@@ -5684,75 +5655,92 @@
getCopyToParts(DAG, dl, Op, &Parts[0], NumParts, PartVT, ExtendKind);
- for (unsigned i = 0; i != NumParts; ++i) {
+ for (unsigned j = 0; j != NumParts; ++j) {
// if it isn't first piece, alignment must be 1
- ISD::ArgFlagsTy MyFlags = Flags;
- if (NumParts > 1 && i == 0)
- MyFlags.setSplit();
- else if (i != 0)
- MyFlags.setOrigAlign(1);
+ ISD::OutputArg MyFlags(Flags, Parts[j], i < NumFixedArgs);
+ if (NumParts > 1 && j == 0)
+ MyFlags.Flags.setSplit();
+ else if (j != 0)
+ MyFlags.Flags.setOrigAlign(1);
- Ops.push_back(Parts[i]);
- Ops.push_back(DAG.getArgFlags(MyFlags));
+ Outs.push_back(MyFlags);
}
}
}
- // Figure out the result value types. We start by making a list of
- // the potentially illegal return value types.
- SmallVector<MVT, 4> LoweredRetTys;
+ // Handle the incoming return values from the call.
+ SmallVector<ISD::InputArg, 32> Ins;
SmallVector<MVT, 4> RetTys;
ComputeValueVTs(*this, RetTy, RetTys);
-
- // Then we translate that to a list of legal types.
for (unsigned I = 0, E = RetTys.size(); I != E; ++I) {
MVT VT = RetTys[I];
MVT RegisterVT = getRegisterType(VT);
unsigned NumRegs = getNumRegisters(VT);
- for (unsigned i = 0; i != NumRegs; ++i)
- LoweredRetTys.push_back(RegisterVT);
- }
-
- LoweredRetTys.push_back(MVT::Other); // Always has a chain.
-
- // Create the CALL node.
- SDValue Res = DAG.getCall(CallingConv, dl,
- isVarArg, isTailCall, isInreg,
- DAG.getVTList(&LoweredRetTys[0],
- LoweredRetTys.size()),
- &Ops[0], Ops.size(), NumFixedArgs
- );
- Chain = Res.getValue(LoweredRetTys.size() - 1);
-
- // Gather up the call result into a single value.
- if (RetTy != Type::VoidTy && !RetTys.empty()) {
- ISD::NodeType AssertOp = ISD::DELETED_NODE;
-
- if (RetSExt)
- AssertOp = ISD::AssertSext;
- else if (RetZExt)
- AssertOp = ISD::AssertZext;
-
- SmallVector<SDValue, 4> ReturnValues;
- unsigned RegNo = 0;
- for (unsigned I = 0, E = RetTys.size(); I != E; ++I) {
- MVT VT = RetTys[I];
- MVT RegisterVT = getRegisterType(VT);
- unsigned NumRegs = getNumRegisters(VT);
- unsigned RegNoEnd = NumRegs + RegNo;
- SmallVector<SDValue, 4> Results;
- for (; RegNo != RegNoEnd; ++RegNo)
- Results.push_back(Res.getValue(RegNo));
- SDValue ReturnValue =
- getCopyFromParts(DAG, dl, &Results[0], NumRegs, RegisterVT, VT,
- AssertOp);
- ReturnValues.push_back(ReturnValue);
+ for (unsigned i = 0; i != NumRegs; ++i) {
+ ISD::InputArg MyFlags;
+ MyFlags.VT = RegisterVT;
+ MyFlags.Used = isReturnValueUsed;
+ if (RetSExt)
+ MyFlags.Flags.setSExt();
+ if (RetZExt)
+ MyFlags.Flags.setZExt();
+ if (isInreg)
+ MyFlags.Flags.setInReg();
+ Ins.push_back(MyFlags);
}
- Res = DAG.getNode(ISD::MERGE_VALUES, dl,
- DAG.getVTList(&RetTys[0], RetTys.size()),
- &ReturnValues[0], ReturnValues.size());
}
+ // Check if target-dependent constraints permit a tail call here.
+ // Target-independent constraints should be checked by the caller.
+ if (isTailCall &&
+ !IsEligibleForTailCallOptimization(Callee, CallConv, isVarArg, Ins, DAG))
+ isTailCall = false;
+
+ SmallVector<SDValue, 4> InVals;
+ Chain = LowerCall(Chain, Callee, CallConv, isVarArg, isTailCall,
+ Outs, Ins, dl, DAG, InVals);
+ assert((!isTailCall || InVals.empty()) && "Tail call had return SDValues!");
+
+ // For a tail call, the return value is merely live-out and there aren't
+ // any nodes in the DAG representing it. Return a special value to
+ // indicate that a tail call has been emitted and no more Instructions
+ // should be processed in the current block.
+ if (isTailCall) {
+ DAG.setRoot(Chain);
+ return std::make_pair(SDValue(), SDValue());
+ }
+
+ // Collect the legal value parts into potentially illegal values
+ // that correspond to the original function's return values.
+ ISD::NodeType AssertOp = ISD::DELETED_NODE;
+ if (RetSExt)
+ AssertOp = ISD::AssertSext;
+ else if (RetZExt)
+ AssertOp = ISD::AssertZext;
+ SmallVector<SDValue, 4> ReturnValues;
+ unsigned CurReg = 0;
+ for (unsigned I = 0, E = RetTys.size(); I != E; ++I) {
+ MVT VT = RetTys[I];
+ MVT RegisterVT = getRegisterType(VT);
+ unsigned NumRegs = getNumRegisters(VT);
+
+ SDValue ReturnValue =
+ getCopyFromParts(DAG, dl, &InVals[CurReg], NumRegs, RegisterVT, VT,
+ AssertOp);
+ ReturnValues.push_back(ReturnValue);
+ CurReg += NumRegs;
+ }
+
+ // For a function returning void, there is no return value. We can't create
+ // such a node, so we just return a null return value in that case. In
+ // that case, nothing will actualy look at the value.
+ if (ReturnValues.empty())
+ return std::make_pair(SDValue(), Chain);
+
+ SDValue Res = DAG.getNode(ISD::MERGE_VALUES, dl,
+ DAG.getVTList(&RetTys[0], RetTys.size()),
+ &ReturnValues[0], ReturnValues.size());
+
return std::make_pair(Res, Chain);
}
@@ -5789,25 +5777,108 @@
LowerArguments(BasicBlock *LLVMBB) {
// If this is the entry block, emit arguments.
Function &F = *LLVMBB->getParent();
- SDValue OldRoot = SDL->DAG.getRoot();
- SmallVector<SDValue, 16> Args;
- TLI.LowerArguments(F, SDL->DAG, Args, SDL->getCurDebugLoc());
+ SelectionDAG &DAG = SDL->DAG;
+ SDValue OldRoot = DAG.getRoot();
+ DebugLoc dl = SDL->getCurDebugLoc();
+ const TargetData *TD = TLI.getTargetData();
- unsigned a = 0;
- for (Function::arg_iterator AI = F.arg_begin(), E = F.arg_end();
- AI != E; ++AI) {
+ // Set up the incoming argument description vector.
+ SmallVector<ISD::InputArg, 16> Ins;
+ unsigned Idx = 1;
+ for (Function::arg_iterator I = F.arg_begin(), E = F.arg_end();
+ I != E; ++I, ++Idx) {
SmallVector<MVT, 4> ValueVTs;
- ComputeValueVTs(TLI, AI->getType(), ValueVTs);
+ ComputeValueVTs(TLI, I->getType(), ValueVTs);
+ bool isArgValueUsed = !I->use_empty();
+ for (unsigned Value = 0, NumValues = ValueVTs.size();
+ Value != NumValues; ++Value) {
+ MVT VT = ValueVTs[Value];
+ const Type *ArgTy = VT.getTypeForMVT();
+ ISD::ArgFlagsTy Flags;
+ unsigned OriginalAlignment =
+ TD->getABITypeAlignment(ArgTy);
+
+ if (F.paramHasAttr(Idx, Attribute::ZExt))
+ Flags.setZExt();
+ if (F.paramHasAttr(Idx, Attribute::SExt))
+ Flags.setSExt();
+ if (F.paramHasAttr(Idx, Attribute::InReg))
+ Flags.setInReg();
+ if (F.paramHasAttr(Idx, Attribute::StructRet))
+ Flags.setSRet();
+ if (F.paramHasAttr(Idx, Attribute::ByVal)) {
+ Flags.setByVal();
+ const PointerType *Ty = cast<PointerType>(I->getType());
+ const Type *ElementTy = Ty->getElementType();
+ unsigned FrameAlign = TLI.getByValTypeAlignment(ElementTy);
+ unsigned FrameSize = TD->getTypeAllocSize(ElementTy);
+ // For ByVal, alignment should be passed from FE. BE will guess if
+ // this info is not there but there are cases it cannot get right.
+ if (F.getParamAlignment(Idx))
+ FrameAlign = F.getParamAlignment(Idx);
+ Flags.setByValAlign(FrameAlign);
+ Flags.setByValSize(FrameSize);
+ }
+ if (F.paramHasAttr(Idx, Attribute::Nest))
+ Flags.setNest();
+ Flags.setOrigAlign(OriginalAlignment);
+
+ MVT RegisterVT = TLI.getRegisterType(VT);
+ unsigned NumRegs = TLI.getNumRegisters(VT);
+ for (unsigned i = 0; i != NumRegs; ++i) {
+ ISD::InputArg MyFlags(Flags, RegisterVT, isArgValueUsed);
+ if (NumRegs > 1 && i == 0)
+ MyFlags.Flags.setSplit();
+ // if it isn't first piece, alignment must be 1
+ else if (i > 0)
+ MyFlags.Flags.setOrigAlign(1);
+ Ins.push_back(MyFlags);
+ }
+ }
+ }
+
+ // Call the target to set up the argument values.
+ SmallVector<SDValue, 8> InVals;
+ SDValue NewRoot = TLI.LowerFormalArguments(DAG.getRoot(), F.getCallingConv(),
+ F.isVarArg(), Ins,
+ dl, DAG, InVals);
+ DAG.setRoot(NewRoot);
+
+ // Set up the argument values.
+ unsigned i = 0;
+ Idx = 1;
+ for (Function::arg_iterator I = F.arg_begin(), E = F.arg_end(); I != E;
+ ++I, ++Idx) {
+ SmallVector<SDValue, 4> ArgValues;
+ SmallVector<MVT, 4> ValueVTs;
+ ComputeValueVTs(TLI, I->getType(), ValueVTs);
unsigned NumValues = ValueVTs.size();
- if (!AI->use_empty()) {
- SDL->setValue(AI, SDL->DAG.getMergeValues(&Args[a], NumValues,
- SDL->getCurDebugLoc()));
+ for (unsigned Value = 0; Value != NumValues; ++Value) {
+ MVT VT = ValueVTs[Value];
+ MVT PartVT = TLI.getRegisterType(VT);
+ unsigned NumParts = TLI.getNumRegisters(VT);
+
+ if (!I->use_empty()) {
+ ISD::NodeType AssertOp = ISD::DELETED_NODE;
+ if (F.paramHasAttr(Idx, Attribute::SExt))
+ AssertOp = ISD::AssertSext;
+ else if (F.paramHasAttr(Idx, Attribute::ZExt))
+ AssertOp = ISD::AssertZext;
+
+ ArgValues.push_back(getCopyFromParts(DAG, dl, &InVals[i], NumParts,
+ PartVT, VT, AssertOp));
+ }
+ i += NumParts;
+ }
+ if (!I->use_empty()) {
+ SDL->setValue(I, DAG.getMergeValues(&ArgValues[0], NumValues,
+ SDL->getCurDebugLoc()));
// If this argument is live outside of the entry block, insert a copy from
// whereever we got it to the vreg that other BB's will reference it as.
- SDL->CopyToExportRegsIfNeeded(AI);
+ SDL->CopyToExportRegsIfNeeded(I);
}
- a += NumValues;
}
+ assert(i == InVals.size() && "Argument register count mismatch!");
// Finally, if the target has anything special to do, allow it to do so.
// FIXME: this should insert code into the DAG!
diff --git a/lib/CodeGen/SelectionDAG/SelectionDAGBuild.h b/lib/CodeGen/SelectionDAG/SelectionDAGBuild.h
index bebe5ca..379ced9 100644
--- a/lib/CodeGen/SelectionDAG/SelectionDAGBuild.h
+++ b/lib/CodeGen/SelectionDAG/SelectionDAGBuild.h
@@ -363,13 +363,20 @@
/// GFI - Garbage collection metadata for the function.
GCFunctionInfo *GFI;
+ /// HasTailCall - This is set to true if a call in the current
+ /// block has been translated as a tail call. In this case,
+ /// no subsequent DAG nodes should be created.
+ ///
+ bool HasTailCall;
+
LLVMContext *Context;
SelectionDAGLowering(SelectionDAG &dag, TargetLowering &tli,
FunctionLoweringInfo &funcinfo,
CodeGenOpt::Level ol)
: CurDebugLoc(DebugLoc::getUnknownLoc()),
- TLI(tli), DAG(dag), FuncInfo(funcinfo), OptLevel(ol),
+ TLI(tli), DAG(dag), FuncInfo(funcinfo), OptLevel(ol),
+ HasTailCall(false),
Context(dag.getContext()) {
}
diff --git a/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp b/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp
index 622aa7c..b02fbea 100644
--- a/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp
+++ b/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp
@@ -366,140 +366,36 @@
}
}
-/// IsFixedFrameObjectWithPosOffset - Check if object is a fixed frame object and
-/// whether object offset >= 0.
-static bool
-IsFixedFrameObjectWithPosOffset(MachineFrameInfo *MFI, SDValue Op) {
- if (!isa<FrameIndexSDNode>(Op)) return false;
-
- FrameIndexSDNode * FrameIdxNode = dyn_cast<FrameIndexSDNode>(Op);
- int FrameIdx = FrameIdxNode->getIndex();
- return MFI->isFixedObjectIndex(FrameIdx) &&
- MFI->getObjectOffset(FrameIdx) >= 0;
-}
-
-/// IsPossiblyOverwrittenArgumentOfTailCall - Check if the operand could
-/// possibly be overwritten when lowering the outgoing arguments in a tail
-/// call. Currently the implementation of this call is very conservative and
-/// assumes all arguments sourcing from FORMAL_ARGUMENTS or a CopyFromReg with
-/// virtual registers would be overwritten by direct lowering.
-static bool IsPossiblyOverwrittenArgumentOfTailCall(SDValue Op,
- MachineFrameInfo *MFI) {
- RegisterSDNode * OpReg = NULL;
- if (Op.getOpcode() == ISD::FORMAL_ARGUMENTS ||
- (Op.getOpcode()== ISD::CopyFromReg &&
- (OpReg = dyn_cast<RegisterSDNode>(Op.getOperand(1))) &&
- (OpReg->getReg() >= TargetRegisterInfo::FirstVirtualRegister)) ||
- (Op.getOpcode() == ISD::LOAD &&
- IsFixedFrameObjectWithPosOffset(MFI, Op.getOperand(1))) ||
- (Op.getOpcode() == ISD::MERGE_VALUES &&
- Op.getOperand(Op.getResNo()).getOpcode() == ISD::LOAD &&
- IsFixedFrameObjectWithPosOffset(MFI, Op.getOperand(Op.getResNo()).
- getOperand(1))))
- return true;
- return false;
-}
-
-/// CheckDAGForTailCallsAndFixThem - This Function looks for CALL nodes in the
-/// DAG and fixes their tailcall attribute operand.
-static void CheckDAGForTailCallsAndFixThem(SelectionDAG &DAG,
- const TargetLowering& TLI) {
- SDNode * Ret = NULL;
- SDValue Terminator = DAG.getRoot();
-
- // Find RET node.
- if (Terminator.getOpcode() == ISD::RET) {
- Ret = Terminator.getNode();
- }
-
- // Fix tail call attribute of CALL nodes.
- for (SelectionDAG::allnodes_iterator BE = DAG.allnodes_begin(),
- BI = DAG.allnodes_end(); BI != BE; ) {
- --BI;
- if (CallSDNode *TheCall = dyn_cast<CallSDNode>(BI)) {
- SDValue OpRet(Ret, 0);
- SDValue OpCall(BI, 0);
- bool isMarkedTailCall = TheCall->isTailCall();
- // If CALL node has tail call attribute set to true and the call is not
- // eligible (no RET or the target rejects) the attribute is fixed to
- // false. The TargetLowering::IsEligibleForTailCallOptimization function
- // must correctly identify tail call optimizable calls.
- if (!isMarkedTailCall) continue;
- if (Ret==NULL ||
- !TLI.IsEligibleForTailCallOptimization(TheCall, OpRet, DAG)) {
- // Not eligible. Mark CALL node as non tail call. Note that we
- // can modify the call node in place since calls are not CSE'd.
- TheCall->setNotTailCall();
- } else {
- // Look for tail call clobbered arguments. Emit a series of
- // copyto/copyfrom virtual register nodes to protect them.
- SmallVector<SDValue, 32> Ops;
- SDValue Chain = TheCall->getChain(), InFlag;
- Ops.push_back(Chain);
- Ops.push_back(TheCall->getCallee());
- for (unsigned i = 0, e = TheCall->getNumArgs(); i != e; ++i) {
- SDValue Arg = TheCall->getArg(i);
- bool isByVal = TheCall->getArgFlags(i).isByVal();
- MachineFunction &MF = DAG.getMachineFunction();
- MachineFrameInfo *MFI = MF.getFrameInfo();
- if (!isByVal &&
- IsPossiblyOverwrittenArgumentOfTailCall(Arg, MFI)) {
- MVT VT = Arg.getValueType();
- unsigned VReg = MF.getRegInfo().
- createVirtualRegister(TLI.getRegClassFor(VT));
- Chain = DAG.getCopyToReg(Chain, Arg.getDebugLoc(),
- VReg, Arg, InFlag);
- InFlag = Chain.getValue(1);
- Arg = DAG.getCopyFromReg(Chain, Arg.getDebugLoc(),
- VReg, VT, InFlag);
- Chain = Arg.getValue(1);
- InFlag = Arg.getValue(2);
- }
- Ops.push_back(Arg);
- Ops.push_back(TheCall->getArgFlagsVal(i));
- }
- // Link in chain of CopyTo/CopyFromReg.
- Ops[0] = Chain;
- DAG.UpdateNodeOperands(OpCall, Ops.begin(), Ops.size());
- }
- }
- }
-}
-
void SelectionDAGISel::SelectBasicBlock(BasicBlock *LLVMBB,
BasicBlock::iterator Begin,
BasicBlock::iterator End) {
SDL->setCurrentBasicBlock(BB);
- // Lower all of the non-terminator instructions.
- for (BasicBlock::iterator I = Begin; I != End; ++I)
+ // Lower all of the non-terminator instructions. If a call is emitted
+ // as a tail call, cease emitting nodes for this block.
+ for (BasicBlock::iterator I = Begin; I != End && !SDL->HasTailCall; ++I)
if (!isa<TerminatorInst>(I))
SDL->visit(*I);
- // Ensure that all instructions which are used outside of their defining
- // blocks are available as virtual registers. Invoke is handled elsewhere.
- for (BasicBlock::iterator I = Begin; I != End; ++I)
- if (!isa<PHINode>(I) && !isa<InvokeInst>(I))
- SDL->CopyToExportRegsIfNeeded(I);
+ if (!SDL->HasTailCall) {
+ // Ensure that all instructions which are used outside of their defining
+ // blocks are available as virtual registers. Invoke is handled elsewhere.
+ for (BasicBlock::iterator I = Begin; I != End; ++I)
+ if (!isa<PHINode>(I) && !isa<InvokeInst>(I))
+ SDL->CopyToExportRegsIfNeeded(I);
- // Handle PHI nodes in successor blocks.
- if (End == LLVMBB->end()) {
- HandlePHINodesInSuccessorBlocks(LLVMBB);
+ // Handle PHI nodes in successor blocks.
+ if (End == LLVMBB->end()) {
+ HandlePHINodesInSuccessorBlocks(LLVMBB);
- // Lower the terminator after the copies are emitted.
- SDL->visit(*LLVMBB->getTerminator());
+ // Lower the terminator after the copies are emitted.
+ SDL->visit(*LLVMBB->getTerminator());
+ }
}
// Make sure the root of the DAG is up-to-date.
CurDAG->setRoot(SDL->getControlRoot());
- // Check whether calls in this block are real tail calls. Fix up CALL nodes
- // with correct tailcall attribute so that the target can rely on the tailcall
- // attribute indicating whether the call is really eligible for tail call
- // optimization.
- if (PerformTailCallOpt)
- CheckDAGForTailCallsAndFixThem(*CurDAG, TLI);
-
// Final step, emit the lowered DAG as machine code.
CodeGenAndEmitDAG();
SDL->clear();
diff --git a/lib/CodeGen/SelectionDAG/TargetLowering.cpp b/lib/CodeGen/SelectionDAG/TargetLowering.cpp
index 21b8cce..3c5305d 100644
--- a/lib/CodeGen/SelectionDAG/TargetLowering.cpp
+++ b/lib/CodeGen/SelectionDAG/TargetLowering.cpp
@@ -2584,45 +2584,3 @@
DAG.getConstant(magics.s-1, getShiftAmountTy()));
}
}
-
-/// IgnoreHarmlessInstructions - Ignore instructions between a CALL and RET
-/// node that don't prevent tail call optimization.
-static SDValue IgnoreHarmlessInstructions(SDValue node) {
- // Found call return.
- if (node.getOpcode() == ISD::CALL) return node;
- // Ignore MERGE_VALUES. Will have at least one operand.
- if (node.getOpcode() == ISD::MERGE_VALUES)
- return IgnoreHarmlessInstructions(node.getOperand(0));
- // Ignore ANY_EXTEND node.
- if (node.getOpcode() == ISD::ANY_EXTEND)
- return IgnoreHarmlessInstructions(node.getOperand(0));
- if (node.getOpcode() == ISD::TRUNCATE)
- return IgnoreHarmlessInstructions(node.getOperand(0));
- // Any other node type.
- return node;
-}
-
-bool TargetLowering::CheckTailCallReturnConstraints(CallSDNode *TheCall,
- SDValue Ret) {
- unsigned NumOps = Ret.getNumOperands();
- // ISD::CALL results:(value0, ..., valuen, chain)
- // ISD::RET operands:(chain, value0, flag0, ..., valuen, flagn)
- // Value return:
- // Check that operand of the RET node sources from the CALL node. The RET node
- // has at least two operands. Operand 0 holds the chain. Operand 1 holds the
- // value.
- // Also we need to check that there is no code in between the call and the
- // return. Hence we also check that the incomming chain to the return sources
- // from the outgoing chain of the call.
- if (NumOps > 1 &&
- IgnoreHarmlessInstructions(Ret.getOperand(1)) == SDValue(TheCall,0) &&
- Ret.getOperand(0) == SDValue(TheCall, TheCall->getNumValues()-1))
- return true;
- // void return: The RET node has the chain result value of the CALL node as
- // input.
- if (NumOps == 1 &&
- Ret.getOperand(0) == SDValue(TheCall, TheCall->getNumValues()-1))
- return true;
-
- return false;
-}