Index: llvm/include/llvm/IR/CallingConv.h =================================================================== --- llvm/include/llvm/IR/CallingConv.h +++ llvm/include/llvm/IR/CallingConv.h @@ -237,6 +237,9 @@ /// Preserve X2-X15, X19-X29, SP, Z0-Z31, P0-P15. AArch64_SME_ABI_Support_Routines_PreserveMost_From_X2 = 103, + /// Used for M68k rtd-based CC (similar to X86's stdcall). + M68k_RTD = 104, + /// The highest possible ID. Must be some 2^k - 1. MaxID = 1023 }; Index: llvm/lib/Target/M68k/M68kExpandPseudo.cpp =================================================================== --- llvm/lib/Target/M68k/M68kExpandPseudo.cpp +++ llvm/lib/Target/M68k/M68kExpandPseudo.cpp @@ -259,32 +259,25 @@ if (StackAdj == 0) { MIB = BuildMI(MBB, MBBI, DL, TII->get(M68k::RTS)); - } else if (isUInt<16>(StackAdj)) { + } else { + // Default situation for 68000 or adjustment larger than 16 bits + // as RTD can only take a 16-bit displacement. - if (STI->atLeastM68020()) { - llvm_unreachable("RTD is not implemented"); - } else { - // Copy PC from stack to a free address(A0 or A1) register - // TODO check if pseudo expand uses free address register - BuildMI(MBB, MBBI, DL, TII->get(M68k::MOV32aj), M68k::A1) - .addReg(M68k::SP); + // Copy return address from stack to a free address(A0 or A1) register + // TODO check if pseudo expand uses free address register + BuildMI(MBB, MBBI, DL, TII->get(M68k::MOV32aj), M68k::A1) + .addReg(M68k::SP); - // Adjust SP - FL->emitSPUpdate(MBB, MBBI, StackAdj, /*InEpilogue=*/true); + // Adjust SP + FL->emitSPUpdate(MBB, MBBI, StackAdj, /*InEpilogue=*/true); - // Put the return address on stack - BuildMI(MBB, MBBI, DL, TII->get(M68k::MOV32ja)) - .addReg(M68k::SP) - .addReg(M68k::A1); + // Put the return address on stack + BuildMI(MBB, MBBI, DL, TII->get(M68k::MOV32ja)) + .addReg(M68k::SP) + .addReg(M68k::A1); - // RTS - BuildMI(MBB, MBBI, DL, TII->get(M68k::RTS)); - } - } else { - // TODO: RTD can only handle immediates as big as 2**16-1. - // If we need to pop off bytes before the return address, we - // must do it manually. - llvm_unreachable("Stack adjustment size not supported"); + // RTS + BuildMI(MBB, MBBI, DL, TII->get(M68k::RTS)); } // FIXME: Can rest of the operands be ignored, if there is any? Index: llvm/lib/Target/M68k/M68kISelLowering.cpp =================================================================== --- llvm/lib/Target/M68k/M68kISelLowering.cpp +++ llvm/lib/Target/M68k/M68kISelLowering.cpp @@ -2950,9 +2950,8 @@ /// Determines whether the callee is required to pop its own arguments. /// Callee pop is necessary to support tail calls. -bool M68k::isCalleePop(CallingConv::ID CallingConv, bool IsVarArg, - bool GuaranteeTCO) { - return false; +bool M68k::isCalleePop(CallingConv::ID CC, bool IsVarArg, bool GuaranteeTCO) { + return CC == CallingConv::M68k_RTD; } // Return true if it is OK for this CMOV pseudo-opcode to be cascaded Index: llvm/test/CodeGen/M68k/CConv/rtd-call.ll =================================================================== --- /dev/null +++ llvm/test/CodeGen/M68k/CConv/rtd-call.ll @@ -0,0 +1,20 @@ +; RUN: llc -mtriple=m68k %s -stop-after=finalize-isel -o - | FileCheck %s + +; We want to make sure caller doesn't pop the stack for callees using +; the M68k_RTD CC. However, we've implemented some frame optimization +; techniques to eliminate as many as frame setup/destroy instructions. +; Therefore, to make test case small and concise, we check the MIR generated +; after ISel instead. + +declare dso_local cc104 void @callee(i32 noundef) + +; CHECK-LABEL: caller +define dso_local i32 @caller(ptr noundef %y) { +entry: + %0 = load i32, ptr %y, align 4 +; CHECK: ADJCALLSTACKDOWN + call cc104 void @callee(i32 noundef %0) +; CHECK: ADJCALLSTACKUP 4, 4 + ret i32 %0 +} + Index: llvm/test/CodeGen/M68k/CConv/rtd-ret.ll =================================================================== --- /dev/null +++ llvm/test/CodeGen/M68k/CConv/rtd-ret.ll @@ -0,0 +1,20 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 2 +; RUN: llc -mtriple=m68k < %s | FileCheck %s + +define dso_local cc104 i32 @ret(i32 noundef %a, i32 noundef %b, i32 noundef %c) { +; CHECK-LABEL: ret: +; CHECK: .cfi_startproc +; CHECK-NEXT: ; %bb.0: ; %entry +; CHECK-NEXT: move.l (8,%sp), %d0 +; CHECK-NEXT: add.l (4,%sp), %d0 +; CHECK-NEXT: add.l (12,%sp), %d0 +; CHECK-NEXT: move.l (%sp), %a1 +; CHECK-NEXT: adda.l #12, %sp +; CHECK-NEXT: move.l %a1, (%sp) +; CHECK-NEXT: rts +entry: + %add = add nsw i32 %b, %a + %add1 = add nsw i32 %add, %c + ret i32 %add1 +} +