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