diff options
-rw-r--r-- | llvm/lib/Target/ARM/ARMSubtarget.cpp | 12 | ||||
-rw-r--r-- | llvm/lib/Target/ARM/Thumb1FrameLowering.cpp | 10 | ||||
-rw-r--r-- | llvm/test/CodeGen/ARM/v8m-tail-call.ll | 23 |
3 files changed, 39 insertions, 6 deletions
diff --git a/llvm/lib/Target/ARM/ARMSubtarget.cpp b/llvm/lib/Target/ARM/ARMSubtarget.cpp index 5596478a3b2..73c63099374 100644 --- a/llvm/lib/Target/ARM/ARMSubtarget.cpp +++ b/llvm/lib/Target/ARM/ARMSubtarget.cpp @@ -202,12 +202,12 @@ void ARMSubtarget::initSubtargetFeatures(StringRef CPU, StringRef FS) { // support in the assembler and linker to be used. This would need to be // fixed to fully support tail calls in Thumb1. // - // 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. + // For ARMv8-M, we /do/ implement tail calls. Doing this is tricky for v8-M + // baseline, since the LDM/POP instruction on Thumb doesn't take LR. This + // means if we need to reload LR, it takes extra instructions, which outweighs + // the value of the tail call; but here we don't know yet whether LR is going + // to be used. We generate the tail call here and turn it back into CALL/RET + // in emitEpilogue if LR is used. // 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 diff --git a/llvm/lib/Target/ARM/Thumb1FrameLowering.cpp b/llvm/lib/Target/ARM/Thumb1FrameLowering.cpp index a2e60299c88..fc083b98395 100644 --- a/llvm/lib/Target/ARM/Thumb1FrameLowering.cpp +++ b/llvm/lib/Target/ARM/Thumb1FrameLowering.cpp @@ -888,6 +888,16 @@ restoreCalleeSavedRegisters(MachineBasicBlock &MBB, // ARMv4T requires BX, see emitEpilogue if (!STI.hasV5TOps()) continue; + // Tailcall optimization failed; change TCRETURN to a tBL + if (MI->getOpcode() == ARM::TCRETURNdi || + MI->getOpcode() == ARM::TCRETURNri) { + unsigned Opcode = MI->getOpcode() == ARM::TCRETURNdi + ? ARM::tBL : ARM::tBLXr; + MachineInstrBuilder BL = BuildMI(MF, DL, TII.get(Opcode)); + BL.add(predOps(ARMCC::AL)); + BL.add(MI->getOperand(0)); + MBB.insert(MI, &*BL); + } Reg = ARM::PC; (*MIB).setDesc(TII.get(ARM::tPOP_RET)); if (MI != MBB.end()) diff --git a/llvm/test/CodeGen/ARM/v8m-tail-call.ll b/llvm/test/CodeGen/ARM/v8m-tail-call.ll new file mode 100644 index 00000000000..2c2c795838f --- /dev/null +++ b/llvm/test/CodeGen/ARM/v8m-tail-call.ll @@ -0,0 +1,23 @@ +; RUN: llc %s -o - -mtriple=thumbv8m.base | FileCheck %s + +define void @test() { +; CHECK-LABEL: test: +entry: + %call = tail call i32 @foo() + %tail = tail call i32 @foo() + ret void +; CHECK: bl foo +; CHECK: bl foo +; CHECK-NOT: b foo +} + +define void @test2() { +; CHECK-LABEL: test2: +entry: + %tail = tail call i32 @foo() + ret void +; CHECK: b foo +; CHECK-NOT: bl foo +} + +declare i32 @foo() |