Index: lib/Target/ARM/Thumb1FrameLowering.cpp =================================================================== --- lib/Target/ARM/Thumb1FrameLowering.cpp +++ lib/Target/ARM/Thumb1FrameLowering.cpp @@ -866,6 +866,16 @@ // 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()) Index: test/CodeGen/ARM/v8m-tail-call.ll =================================================================== --- /dev/null +++ test/CodeGen/ARM/v8m-tail-call.ll @@ -0,0 +1,37 @@ +; RUN: llc %s -o - -mtriple=thumbv8m.base | FileCheck %s + +define i32 @test(i32 %Enum_Val_Par, i32* nocapture %Enum_Ref_Par) { +entry: + %call = tail call i32 @Func_3(i32 %Enum_Val_Par) + %tobool = icmp ne i32 %call, 0 + %cond = select i1 %tobool, i32 3, i32 %Enum_Val_Par + store i32 %cond, i32* %Enum_Ref_Par, align 4 +; CHECK: cbnz +; CHECK-NOT: cmp +; CHECK-NOT: bne + + %tail = tail call i32 @Proc_7(i32 10, i32 %Enum_Val_Par, i32* %Enum_Ref_Par) + ret i32 undef +; CHECK: bl Proc_7 +; CHECK-NOT: b Proc_7 +} + +define i32 @test2(i32 %Enum_Val_Par, i32* nocapture %Enum_Ref_Par) { +entry: + %tobool = icmp ne i32 %Enum_Val_Par, 0 + %cond = select i1 %tobool, i32 3, i32 %Enum_Val_Par + store i32 %cond, i32* %Enum_Ref_Par, align 4 +; CHECK: cbnz +; CHECK-NOT: cmp +; CHECK-NOT: bne + + %tail = tail call i32 @Proc_7(i32 10, i32 %Enum_Val_Par, i32* %Enum_Ref_Par) + ret i32 undef +; CHECK: b Proc_7 +; CHECK-NOT: bl +} + +declare i32 @Proc_7(i32, i32, i32*) + +declare i32 @Func_3(i32) +