diff --git a/lib/Target/ARM/ARMISelLowering.cpp b/lib/Target/ARM/ARMISelLowering.cpp index 5ec995f771c..50258c6f85e 100644 --- a/lib/Target/ARM/ARMISelLowering.cpp +++ b/lib/Target/ARM/ARMISelLowering.cpp @@ -1101,7 +1101,7 @@ ARMTargetLowering::LowerCall(SDValue Chain, SDValue Callee, } } 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, @@ -1357,12 +1357,6 @@ ARMTargetLowering::IsEligibleForTailCallOptimization(SDValue Callee, // Look for obvious safe cases to perform tail call optimization that do not // require ABI changes. This is what gcc calls sibcall. - // Can't do sibcall if stack needs to be dynamically re-aligned. PEI needs to - // emit a special epilogue. - // Not sure yet if this is true on ARM. -//?? if (RegInfo->needsStackRealignment(MF)) -//?? return false; - // Do not sibcall optimize vararg calls unless the call site is not passing // any arguments. if (isVarArg && !Outs.empty()) @@ -1373,6 +1367,19 @@ ARMTargetLowering::IsEligibleForTailCallOptimization(SDValue Callee, 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(Callee)) { + const GlobalValue *GV = G->getGlobal(); + if (GV->isDeclaration() || GV->isWeakForLinker()) + return false; + } else if (isa(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) { diff --git a/lib/Target/ARM/ARMInstrInfo.td b/lib/Target/ARM/ARMInstrInfo.td index 052104d0533..d95137ae900 100644 --- a/lib/Target/ARM/ARMInstrInfo.td +++ b/lib/Target/ARM/ARMInstrInfo.td @@ -1049,7 +1049,7 @@ let isCall = 1, isTerminator = 1, isReturn = 1, isBarrier = 1 in { "@TC_RETURN","\t$dst", []>, Requires<[IsDarwin]>; def TAILJMPd : ABXI<0b1010, (outs), (ins brtarget:$dst, variable_ops), - IIC_Br, "b\t$dst @ TAILCALL", + IIC_Br, "b.w\t$dst @ TAILCALL", []>, Requires<[IsDarwin]>; def TAILJMPr : AXI<(outs), (ins tcGPR:$dst, variable_ops), @@ -1084,7 +1084,7 @@ let isCall = 1, isTerminator = 1, isReturn = 1, isBarrier = 1 in { "@TC_RETURN","\t$dst", []>, Requires<[IsNotDarwin]>; def TAILJMPdND : ABXI<0b1010, (outs), (ins brtarget:$dst, variable_ops), - IIC_Br, "b\t$dst @ TAILCALL", + IIC_Br, "b.w\t$dst @ TAILCALL", []>, Requires<[IsNotDarwin]>; def TAILJMPrND : AXI<(outs), (ins tGPR:$dst, variable_ops),