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()  | 

