Index: llvm/trunk/lib/Target/Mips/MipsCallLowering.h =================================================================== --- llvm/trunk/lib/Target/Mips/MipsCallLowering.h +++ llvm/trunk/lib/Target/Mips/MipsCallLowering.h @@ -48,6 +48,10 @@ bool lowerFormalArguments(MachineIRBuilder &MIRBuilder, const Function &F, ArrayRef VRegs) const override; + bool lowerCall(MachineIRBuilder &MIRBuilder, CallingConv::ID CallConv, + const MachineOperand &Callee, const ArgInfo &OrigRet, + ArrayRef OrigArgs) const override; + private: using FunTy = std::function OrigArgs) const { + + if (CallConv != CallingConv::C) + return false; + + for (auto &Arg : OrigArgs) { + if (!isSupportedType(Arg.Ty)) + return false; + if (Arg.Flags.isByVal() || Arg.Flags.isSRet()) + return false; + } + if (OrigRet.Reg && !isSupportedType(OrigRet.Ty)) + return false; + + MachineFunction &MF = MIRBuilder.getMF(); + const Function &F = MF.getFunction(); + const MipsTargetLowering &TLI = *getTLI(); + const MipsTargetMachine &TM = + static_cast(MF.getTarget()); + const MipsABIInfo &ABI = TM.getABI(); + + MachineInstrBuilder CallSeqStart = + MIRBuilder.buildInstr(Mips::ADJCALLSTACKDOWN); + + // FIXME: Add support for pic calling sequences, long call sequences for O32, + // N32 and N64. First handle the case when Callee.isReg(). + if (Callee.isReg()) + return false; + + MachineInstrBuilder MIB = MIRBuilder.buildInstrNoInsert(Mips::JAL); + MIB.addDef(Mips::SP, RegState::Implicit); + MIB.add(Callee); + const TargetRegisterInfo *TRI = MF.getSubtarget().getRegisterInfo(); + MIB.addRegMask(TRI->getCallPreservedMask(MF, F.getCallingConv())); + + TargetLowering::ArgListTy FuncOrigArgs; + FuncOrigArgs.reserve(OrigArgs.size()); + + SmallVector ArgInfos; + SmallVector OrigArgIndices; + unsigned i = 0; + for (auto &Arg : OrigArgs) { + + TargetLowering::ArgListEntry Entry; + Entry.Ty = Arg.Ty; + FuncOrigArgs.push_back(Entry); + + splitToValueTypes(Arg, i, ArgInfos, OrigArgIndices); + ++i; + } + + SmallVector Outs; + subTargetRegTypeForCallingConv( + MIRBuilder, ArgInfos, OrigArgIndices, + [&](ISD::ArgFlagsTy flags, EVT vt, EVT argvt, bool used, unsigned origIdx, + unsigned partOffs) { + Outs.emplace_back(flags, vt, argvt, used, origIdx, partOffs); + }); + + SmallVector ArgLocs; + MipsCCState CCInfo(F.getCallingConv(), F.isVarArg(), MF, ArgLocs, + F.getContext()); + + const char *Call = Callee.isSymbol() ? Callee.getSymbolName() : nullptr; + CCInfo.AnalyzeCallOperands(Outs, TLI.CCAssignFnForCall(), FuncOrigArgs, Call); + + OutgoingValueHandler RetHandler(MIRBuilder, MF.getRegInfo(), MIB); + if (!RetHandler.handle(ArgLocs, ArgInfos)) { + return false; + } + + // TODO: Calculate stack offset. + CallSeqStart.addImm(ABI.GetCalleeAllocdArgSizeInBytes(CallConv)).addImm(0); + MIRBuilder.insertInstr(MIB); + + if (OrigRet.Reg) { + + ArgInfos.clear(); + SmallVector OrigRetIndices; + + splitToValueTypes(OrigRet, 0, ArgInfos, OrigRetIndices); + + SmallVector Ins; + subTargetRegTypeForCallingConv( + MIRBuilder, ArgInfos, OrigRetIndices, + [&](ISD::ArgFlagsTy flags, EVT vt, EVT argvt, bool used, + unsigned origIdx, unsigned partOffs) { + Ins.emplace_back(flags, vt, argvt, used, origIdx, partOffs); + }); + + SmallVector ArgLocs; + MipsCCState CCInfo(F.getCallingConv(), F.isVarArg(), MF, ArgLocs, + F.getContext()); + + CCInfo.AnalyzeCallResult(Ins, TLI.CCAssignFnForReturn(), OrigRet.Ty, Call); + + CallReturnHandler Handler(MIRBuilder, MF.getRegInfo(), MIB); + if (!Handler.handle(ArgLocs, ArgInfos)) + return false; + } + + MIRBuilder.buildInstr(Mips::ADJCALLSTACKUP) + .addImm(ABI.GetCalleeAllocdArgSizeInBytes(CallConv)) + .addImm(0); + + return true; +} + void MipsCallLowering::subTargetRegTypeForCallingConv( MachineIRBuilder &MIRBuilder, ArrayRef Args, ArrayRef OrigArgIndices, const FunTy &PushBack) const { Index: llvm/trunk/test/CodeGen/Mips/GlobalISel/irtranslator/call.ll =================================================================== --- llvm/trunk/test/CodeGen/Mips/GlobalISel/irtranslator/call.ll +++ llvm/trunk/test/CodeGen/Mips/GlobalISel/irtranslator/call.ll @@ -0,0 +1,27 @@ +; NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py +; RUN: llc -O0 -mtriple=mipsel-linux-gnu -global-isel -stop-after=irtranslator -verify-machineinstrs %s -o - | FileCheck %s -check-prefixes=MIPS32 + +declare i32 @f(i32 %a, i32 %b); + +define i32 @g(i32 %a0, i32 %a1, i32 %x, i32 %y) { + ; MIPS32-LABEL: name: g + ; MIPS32: bb.1.entry: + ; MIPS32: liveins: $a0, $a1, $a2, $a3 + ; MIPS32: [[COPY:%[0-9]+]]:_(s32) = COPY $a0 + ; MIPS32: [[COPY1:%[0-9]+]]:_(s32) = COPY $a1 + ; MIPS32: [[COPY2:%[0-9]+]]:_(s32) = COPY $a2 + ; MIPS32: [[COPY3:%[0-9]+]]:_(s32) = COPY $a3 + ; MIPS32: ADJCALLSTACKDOWN 16, 0, implicit-def $sp, implicit $sp + ; MIPS32: $a0 = COPY [[COPY2]](s32) + ; MIPS32: $a1 = COPY [[COPY3]](s32) + ; MIPS32: JAL @f, csr_o32, implicit-def $ra, implicit-def $sp, implicit $a0, implicit $a1, implicit-def $v0 + ; MIPS32: [[COPY4:%[0-9]+]]:_(s32) = COPY $v0 + ; MIPS32: ADJCALLSTACKUP 16, 0, implicit-def $sp, implicit $sp + ; MIPS32: [[ADD:%[0-9]+]]:_(s32) = G_ADD [[COPY4]], [[COPY4]] + ; MIPS32: $v0 = COPY [[ADD]](s32) + ; MIPS32: RetRA implicit $v0 +entry: + %z = call i32 @f(i32 %x, i32 %y) + %doublez = add i32 %z, %z + ret i32 %doublez +} Index: llvm/trunk/test/CodeGen/Mips/GlobalISel/llvm-ir/call.ll =================================================================== --- llvm/trunk/test/CodeGen/Mips/GlobalISel/llvm-ir/call.ll +++ llvm/trunk/test/CodeGen/Mips/GlobalISel/llvm-ir/call.ll @@ -0,0 +1,26 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py +; RUN: llc -O0 -mtriple=mipsel-linux-gnu -global-isel -verify-machineinstrs %s -o -| FileCheck %s -check-prefixes=MIPS32 + +declare i32 @f(i32 %a, i32 %b); + +define i32 @g(i32 %a0, i32 %a1, i32 %x, i32 %y) { +; MIPS32-LABEL: g: +; MIPS32: # %bb.0: # %entry +; MIPS32-NEXT: addiu $sp, $sp, -24 +; MIPS32-NEXT: .cfi_def_cfa_offset 24 +; MIPS32-NEXT: sw $ra, 20($sp) # 4-byte Folded Spill +; MIPS32-NEXT: .cfi_offset 31, -4 +; MIPS32-NEXT: move $4, $6 +; MIPS32-NEXT: move $5, $7 +; MIPS32-NEXT: jal f +; MIPS32-NEXT: nop +; MIPS32-NEXT: addu $2, $2, $2 +; MIPS32-NEXT: lw $ra, 20($sp) # 4-byte Folded Reload +; MIPS32-NEXT: addiu $sp, $sp, 24 +; MIPS32-NEXT: jr $ra +; MIPS32-NEXT: nop +entry: + %z = call i32 @f(i32 %x, i32 %y) + %doublez = add i32 %z, %z + ret i32 %doublez +}