From 226e6117ae8b360ec4398510335c3c84469e06b4 Mon Sep 17 00:00:00 2001 From: Petar Jovanovic Date: Tue, 3 Jul 2018 09:31:48 +0000 Subject: [PATCH] [MIPS GlobalISel] Lower arguments using stack Lower more than 4 arguments using stack. This patch targets MIPS32. It supports only functions with arguments of type i32. Patch by Petar Avramovic. Differential Revision: https://reviews.llvm.org/D47934 llvm-svn: 336185 --- llvm/lib/Target/Mips/MipsCallLowering.cpp | 94 ++++++++++++++++++++-- llvm/lib/Target/Mips/MipsCallLowering.h | 12 ++- .../Mips/GlobalISel/irtranslator/stack_args.ll | 33 ++++++++ 3 files changed, 129 insertions(+), 10 deletions(-) create mode 100644 llvm/test/CodeGen/Mips/GlobalISel/irtranslator/stack_args.ll diff --git a/llvm/lib/Target/Mips/MipsCallLowering.cpp b/llvm/lib/Target/Mips/MipsCallLowering.cpp index cd751e5..cb3c5ef 100644 --- a/llvm/lib/Target/Mips/MipsCallLowering.cpp +++ b/llvm/lib/Target/Mips/MipsCallLowering.cpp @@ -27,6 +27,12 @@ bool MipsCallLowering::MipsHandler::assign(const CCValAssign &VA, unsigned vreg) { if (VA.isRegLoc()) { assignValueToReg(vreg, VA.getLocReg()); + } else if (VA.isMemLoc()) { + unsigned Size = alignTo(VA.getValVT().getSizeInBits(), 8) / 8; + unsigned Offset = VA.getLocMemOffset(); + MachinePointerInfo MPO; + unsigned StackAddr = getStackAddress(Size, Offset, MPO); + assignValueToAddress(vreg, StackAddr, Size, MPO); } else { return false; } @@ -43,11 +49,24 @@ public: ArrayRef Args); private: - virtual void assignValueToReg(unsigned ValVReg, unsigned PhysReg) override; + void assignValueToReg(unsigned ValVReg, unsigned PhysReg) override; + + unsigned getStackAddress(uint64_t Size, int64_t Offset, + MachinePointerInfo &MPO) override; + + void assignValueToAddress(unsigned ValVReg, unsigned Addr, uint64_t Size, + MachinePointerInfo &MPO) override; virtual void markPhysRegUsed(unsigned PhysReg) { MIRBuilder.getMBB().addLiveIn(PhysReg); } + + void buildLoad(unsigned Val, unsigned Addr, uint64_t Size, unsigned Alignment, + MachinePointerInfo &MPO) { + MachineMemOperand *MMO = MIRBuilder.getMF().getMachineMemOperand( + MPO, MachineMemOperand::MOLoad, Size, Alignment); + MIRBuilder.buildLoad(Val, Addr, *MMO); + } }; class CallReturnHandler : public IncomingValueHandler { @@ -57,7 +76,7 @@ public: : IncomingValueHandler(MIRBuilder, MRI), MIB(MIB) {} private: - virtual void markPhysRegUsed(unsigned PhysReg) override { + void markPhysRegUsed(unsigned PhysReg) override { MIB.addDef(PhysReg, RegState::Implicit); } @@ -72,6 +91,26 @@ void IncomingValueHandler::assignValueToReg(unsigned ValVReg, markPhysRegUsed(PhysReg); } +unsigned IncomingValueHandler::getStackAddress(uint64_t Size, int64_t Offset, + MachinePointerInfo &MPO) { + MachineFrameInfo &MFI = MIRBuilder.getMF().getFrameInfo(); + + int FI = MFI.CreateFixedObject(Size, Offset, true); + MPO = MachinePointerInfo::getFixedStack(MIRBuilder.getMF(), FI); + + unsigned AddrReg = MRI.createGenericVirtualRegister(LLT::pointer(0, 32)); + MIRBuilder.buildFrameIndex(AddrReg, FI); + + return AddrReg; +} + +void IncomingValueHandler::assignValueToAddress(unsigned ValVReg, unsigned Addr, + uint64_t Size, + MachinePointerInfo &MPO) { + // If the value is not extended, a simple load will suffice. + buildLoad(ValVReg, Addr, Size, /* Alignment */ 0, MPO); +} + bool IncomingValueHandler::handle(ArrayRef ArgLocs, ArrayRef Args) { for (unsigned i = 0, ArgsSize = Args.size(); i < ArgsSize; ++i) { @@ -92,7 +131,13 @@ public: ArrayRef Args); private: - virtual void assignValueToReg(unsigned ValVReg, unsigned PhysReg) override; + void assignValueToReg(unsigned ValVReg, unsigned PhysReg) override; + + unsigned getStackAddress(uint64_t Size, int64_t Offset, + MachinePointerInfo &MPO) override; + + void assignValueToAddress(unsigned ValVReg, unsigned Addr, uint64_t Size, + MachinePointerInfo &MPO) override; MachineInstrBuilder &MIB; }; @@ -104,6 +149,31 @@ void OutgoingValueHandler::assignValueToReg(unsigned ValVReg, MIB.addUse(PhysReg, RegState::Implicit); } +unsigned OutgoingValueHandler::getStackAddress(uint64_t Size, int64_t Offset, + MachinePointerInfo &MPO) { + LLT p0 = LLT::pointer(0, 32); + LLT s32 = LLT::scalar(32); + unsigned SPReg = MRI.createGenericVirtualRegister(p0); + MIRBuilder.buildCopy(SPReg, Mips::SP); + + unsigned OffsetReg = MRI.createGenericVirtualRegister(s32); + MIRBuilder.buildConstant(OffsetReg, Offset); + + unsigned AddrReg = MRI.createGenericVirtualRegister(p0); + MIRBuilder.buildGEP(AddrReg, SPReg, OffsetReg); + + MPO = MachinePointerInfo::getStack(MIRBuilder.getMF(), Offset); + return AddrReg; +} + +void OutgoingValueHandler::assignValueToAddress(unsigned ValVReg, unsigned Addr, + uint64_t Size, + MachinePointerInfo &MPO) { + MachineMemOperand *MMO = MIRBuilder.getMF().getMachineMemOperand( + MPO, MachineMemOperand::MOStore, Size, /* Alignment */ 0); + MIRBuilder.buildStore(ValVReg, Addr, *MMO); +} + bool OutgoingValueHandler::handle(ArrayRef ArgLocs, ArrayRef Args) { for (unsigned i = 0; i < Args.size(); ++i) { @@ -205,6 +275,11 @@ bool MipsCallLowering::lowerFormalArguments(MachineIRBuilder &MIRBuilder, MipsCCState CCInfo(F.getCallingConv(), F.isVarArg(), MF, ArgLocs, F.getContext()); + const MipsTargetMachine &TM = + static_cast(MF.getTarget()); + const MipsABIInfo &ABI = TM.getABI(); + CCInfo.AllocateStack(ABI.GetCalleeAllocdArgSizeInBytes(F.getCallingConv()), + 1); CCInfo.AnalyzeFormalArguments(Ins, TLI.CCAssignFnForCall()); IncomingValueHandler Handler(MIRBuilder, MF.getRegInfo()); @@ -281,6 +356,7 @@ bool MipsCallLowering::lowerCall(MachineIRBuilder &MIRBuilder, MipsCCState CCInfo(F.getCallingConv(), F.isVarArg(), MF, ArgLocs, F.getContext()); + CCInfo.AllocateStack(ABI.GetCalleeAllocdArgSizeInBytes(CallConv), 1); const char *Call = Callee.isSymbol() ? Callee.getSymbolName() : nullptr; CCInfo.AnalyzeCallOperands(Outs, TLI.CCAssignFnForCall(), FuncOrigArgs, Call); @@ -289,8 +365,12 @@ bool MipsCallLowering::lowerCall(MachineIRBuilder &MIRBuilder, return false; } - // TODO: Calculate stack offset. - CallSeqStart.addImm(ABI.GetCalleeAllocdArgSizeInBytes(CallConv)).addImm(0); + unsigned NextStackOffset = CCInfo.getNextStackOffset(); + const TargetFrameLowering *TFL = MF.getSubtarget().getFrameLowering(); + unsigned StackAlignment = TFL->getStackAlignment(); + NextStackOffset = alignTo(NextStackOffset, StackAlignment); + CallSeqStart.addImm(NextStackOffset).addImm(0); + MIRBuilder.insertInstr(MIB); if (OrigRet.Reg) { @@ -319,9 +399,7 @@ bool MipsCallLowering::lowerCall(MachineIRBuilder &MIRBuilder, return false; } - MIRBuilder.buildInstr(Mips::ADJCALLSTACKUP) - .addImm(ABI.GetCalleeAllocdArgSizeInBytes(CallConv)) - .addImm(0); + MIRBuilder.buildInstr(Mips::ADJCALLSTACKUP).addImm(NextStackOffset).addImm(0); return true; } diff --git a/llvm/lib/Target/Mips/MipsCallLowering.h b/llvm/lib/Target/Mips/MipsCallLowering.h index cdff19a..e23c10c 100644 --- a/llvm/lib/Target/Mips/MipsCallLowering.h +++ b/llvm/lib/Target/Mips/MipsCallLowering.h @@ -32,12 +32,20 @@ public: virtual ~MipsHandler() = default; protected: - virtual void assignValueToReg(unsigned ValVReg, unsigned PhysReg) = 0; - bool assign(const CCValAssign &VA, unsigned vreg); MachineIRBuilder &MIRBuilder; MachineRegisterInfo &MRI; + + private: + virtual unsigned getStackAddress(uint64_t Size, int64_t Offset, + MachinePointerInfo &MPO) = 0; + + virtual void assignValueToReg(unsigned ValVReg, unsigned PhysReg) = 0; + + virtual void assignValueToAddress(unsigned ValVReg, unsigned Addr, + uint64_t Size, + MachinePointerInfo &MPO) = 0; }; MipsCallLowering(const MipsTargetLowering &TLI); diff --git a/llvm/test/CodeGen/Mips/GlobalISel/irtranslator/stack_args.ll b/llvm/test/CodeGen/Mips/GlobalISel/irtranslator/stack_args.ll new file mode 100644 index 0000000..ae89af4 --- /dev/null +++ b/llvm/test/CodeGen/Mips/GlobalISel/irtranslator/stack_args.ll @@ -0,0 +1,33 @@ +; 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, i32, i32, i32, i32) + +define i32 @g(i32 %x1, i32 %x2, i32 %x3, i32 %x4, i32 %x5){ + ; 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: [[FRAME_INDEX:%[0-9]+]]:_(p0) = G_FRAME_INDEX %fixed-stack.0 + ; MIPS32: [[LOAD:%[0-9]+]]:_(s32) = G_LOAD [[FRAME_INDEX]](p0) :: (load 4 from %fixed-stack.0, align 0) + ; MIPS32: ADJCALLSTACKDOWN 24, 0, implicit-def $sp, implicit $sp + ; MIPS32: $a0 = COPY [[COPY]](s32) + ; MIPS32: $a1 = COPY [[COPY1]](s32) + ; MIPS32: $a2 = COPY [[COPY2]](s32) + ; MIPS32: $a3 = COPY [[COPY3]](s32) + ; MIPS32: [[COPY4:%[0-9]+]]:_(p0) = COPY $sp + ; MIPS32: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 16 + ; MIPS32: [[GEP:%[0-9]+]]:_(p0) = G_GEP [[COPY4]], [[C]](s32) + ; MIPS32: G_STORE [[LOAD]](s32), [[GEP]](p0) :: (store 4 into stack + 16, align 0) + ; MIPS32: JAL @f, csr_o32, implicit-def $ra, implicit-def $sp, implicit $a0, implicit $a1, implicit $a2, implicit $a3, implicit-def $v0 + ; MIPS32: [[COPY5:%[0-9]+]]:_(s32) = COPY $v0 + ; MIPS32: ADJCALLSTACKUP 24, 0, implicit-def $sp, implicit $sp + ; MIPS32: $v0 = COPY [[COPY5]](s32) + ; MIPS32: RetRA implicit $v0 +entry: + %call = call i32 @f(i32 %x1, i32 %x2, i32 %x3, i32 %x4, i32 %x5) + ret i32 %call +} -- 2.7.4