diff options
Diffstat (limited to 'lib/Target/Mips/MipsCallLowering.cpp')
| -rw-r--r-- | lib/Target/Mips/MipsCallLowering.cpp | 335 |
1 files changed, 236 insertions, 99 deletions
diff --git a/lib/Target/Mips/MipsCallLowering.cpp b/lib/Target/Mips/MipsCallLowering.cpp index a705ebb6b193..c550fadf6632 100644 --- a/lib/Target/Mips/MipsCallLowering.cpp +++ b/lib/Target/Mips/MipsCallLowering.cpp @@ -16,6 +16,7 @@ #include "MipsCallLowering.h" #include "MipsCCState.h" #include "MipsTargetMachine.h" +#include "llvm/CodeGen/Analysis.h" #include "llvm/CodeGen/GlobalISel/MachineIRBuilder.h" using namespace llvm; @@ -23,48 +24,89 @@ using namespace llvm; MipsCallLowering::MipsCallLowering(const MipsTargetLowering &TLI) : CallLowering(&TLI) {} -bool MipsCallLowering::MipsHandler::assign(const CCValAssign &VA, - unsigned vreg) { +bool MipsCallLowering::MipsHandler::assign(unsigned VReg, + const CCValAssign &VA) { if (VA.isRegLoc()) { - assignValueToReg(vreg, VA.getLocReg()); + assignValueToReg(VReg, VA); } 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); + assignValueToAddress(VReg, VA); } else { return false; } return true; } +bool MipsCallLowering::MipsHandler::assignVRegs(ArrayRef<unsigned> VRegs, + ArrayRef<CCValAssign> ArgLocs, + unsigned ArgLocsStartIndex) { + for (unsigned i = 0; i < VRegs.size(); ++i) + if (!assign(VRegs[i], ArgLocs[ArgLocsStartIndex + i])) + return false; + return true; +} + +void MipsCallLowering::MipsHandler::setLeastSignificantFirst( + SmallVectorImpl<unsigned> &VRegs) { + if (!MIRBuilder.getMF().getDataLayout().isLittleEndian()) + std::reverse(VRegs.begin(), VRegs.end()); +} + +bool MipsCallLowering::MipsHandler::handle( + ArrayRef<CCValAssign> ArgLocs, ArrayRef<CallLowering::ArgInfo> Args) { + SmallVector<unsigned, 4> VRegs; + unsigned SplitLength; + const Function &F = MIRBuilder.getMF().getFunction(); + const DataLayout &DL = F.getParent()->getDataLayout(); + const MipsTargetLowering &TLI = *static_cast<const MipsTargetLowering *>( + MIRBuilder.getMF().getSubtarget().getTargetLowering()); + + for (unsigned ArgsIndex = 0, ArgLocsIndex = 0; ArgsIndex < Args.size(); + ++ArgsIndex, ArgLocsIndex += SplitLength) { + EVT VT = TLI.getValueType(DL, Args[ArgsIndex].Ty); + SplitLength = TLI.getNumRegistersForCallingConv(F.getContext(), + F.getCallingConv(), VT); + if (SplitLength > 1) { + VRegs.clear(); + MVT RegisterVT = TLI.getRegisterTypeForCallingConv( + F.getContext(), F.getCallingConv(), VT); + for (unsigned i = 0; i < SplitLength; ++i) + VRegs.push_back(MRI.createGenericVirtualRegister(LLT{RegisterVT})); + + if (!handleSplit(VRegs, ArgLocs, ArgLocsIndex, Args[ArgsIndex].Reg)) + return false; + } else { + if (!assign(Args[ArgsIndex].Reg, ArgLocs[ArgLocsIndex])) + return false; + } + } + return true; +} + namespace { class IncomingValueHandler : public MipsCallLowering::MipsHandler { public: IncomingValueHandler(MachineIRBuilder &MIRBuilder, MachineRegisterInfo &MRI) : MipsHandler(MIRBuilder, MRI) {} - bool handle(ArrayRef<CCValAssign> ArgLocs, - ArrayRef<CallLowering::ArgInfo> Args); - private: - void assignValueToReg(unsigned ValVReg, unsigned PhysReg) override; + void assignValueToReg(unsigned ValVReg, const CCValAssign &VA) override; - unsigned getStackAddress(uint64_t Size, int64_t Offset, - MachinePointerInfo &MPO) override; + unsigned getStackAddress(const CCValAssign &VA, + MachineMemOperand *&MMO) override; - void assignValueToAddress(unsigned ValVReg, unsigned Addr, uint64_t Size, - MachinePointerInfo &MPO) override; + void assignValueToAddress(unsigned ValVReg, const CCValAssign &VA) override; + + bool handleSplit(SmallVectorImpl<unsigned> &VRegs, + ArrayRef<CCValAssign> ArgLocs, unsigned ArgLocsStartIndex, + unsigned ArgsReg) 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); + void buildLoad(unsigned Val, const CCValAssign &VA) { + MachineMemOperand *MMO; + unsigned Addr = getStackAddress(VA, MMO); MIRBuilder.buildLoad(Val, Addr, *MMO); } }; @@ -86,17 +128,34 @@ private: } // end anonymous namespace void IncomingValueHandler::assignValueToReg(unsigned ValVReg, - unsigned PhysReg) { - MIRBuilder.buildCopy(ValVReg, PhysReg); + const CCValAssign &VA) { + unsigned PhysReg = VA.getLocReg(); + switch (VA.getLocInfo()) { + case CCValAssign::LocInfo::SExt: + case CCValAssign::LocInfo::ZExt: + case CCValAssign::LocInfo::AExt: { + auto Copy = MIRBuilder.buildCopy(LLT{VA.getLocVT()}, PhysReg); + MIRBuilder.buildTrunc(ValVReg, Copy); + break; + } + default: + MIRBuilder.buildCopy(ValVReg, PhysReg); + break; + } markPhysRegUsed(PhysReg); } -unsigned IncomingValueHandler::getStackAddress(uint64_t Size, int64_t Offset, - MachinePointerInfo &MPO) { +unsigned IncomingValueHandler::getStackAddress(const CCValAssign &VA, + MachineMemOperand *&MMO) { + unsigned Size = alignTo(VA.getValVT().getSizeInBits(), 8) / 8; + unsigned Offset = VA.getLocMemOffset(); MachineFrameInfo &MFI = MIRBuilder.getMF().getFrameInfo(); int FI = MFI.CreateFixedObject(Size, Offset, true); - MPO = MachinePointerInfo::getFixedStack(MIRBuilder.getMF(), FI); + MachinePointerInfo MPO = + MachinePointerInfo::getFixedStack(MIRBuilder.getMF(), FI); + MMO = MIRBuilder.getMF().getMachineMemOperand(MPO, MachineMemOperand::MOLoad, + Size, /* Alignment */ 0); unsigned AddrReg = MRI.createGenericVirtualRegister(LLT::pointer(0, 32)); MIRBuilder.buildFrameIndex(AddrReg, FI); @@ -104,19 +163,26 @@ unsigned IncomingValueHandler::getStackAddress(uint64_t Size, int64_t Offset, 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); +void IncomingValueHandler::assignValueToAddress(unsigned ValVReg, + const CCValAssign &VA) { + if (VA.getLocInfo() == CCValAssign::SExt || + VA.getLocInfo() == CCValAssign::ZExt || + VA.getLocInfo() == CCValAssign::AExt) { + unsigned LoadReg = MRI.createGenericVirtualRegister(LLT::scalar(32)); + buildLoad(LoadReg, VA); + MIRBuilder.buildTrunc(ValVReg, LoadReg); + } else + buildLoad(ValVReg, VA); } -bool IncomingValueHandler::handle(ArrayRef<CCValAssign> ArgLocs, - ArrayRef<CallLowering::ArgInfo> Args) { - for (unsigned i = 0, ArgsSize = Args.size(); i < ArgsSize; ++i) { - if (!assign(ArgLocs[i], Args[i].Reg)) - return false; - } +bool IncomingValueHandler::handleSplit(SmallVectorImpl<unsigned> &VRegs, + ArrayRef<CCValAssign> ArgLocs, + unsigned ArgLocsStartIndex, + unsigned ArgsReg) { + if (!assignVRegs(VRegs, ArgLocs, ArgLocsStartIndex)) + return false; + setLeastSignificantFirst(VRegs); + MIRBuilder.buildMerge(ArgsReg, VRegs); return true; } @@ -127,103 +193,179 @@ public: MachineInstrBuilder &MIB) : MipsHandler(MIRBuilder, MRI), MIB(MIB) {} - bool handle(ArrayRef<CCValAssign> ArgLocs, - ArrayRef<CallLowering::ArgInfo> Args); - private: - void assignValueToReg(unsigned ValVReg, unsigned PhysReg) override; + void assignValueToReg(unsigned ValVReg, const CCValAssign &VA) override; + + unsigned getStackAddress(const CCValAssign &VA, + MachineMemOperand *&MMO) override; - unsigned getStackAddress(uint64_t Size, int64_t Offset, - MachinePointerInfo &MPO) override; + void assignValueToAddress(unsigned ValVReg, const CCValAssign &VA) override; - void assignValueToAddress(unsigned ValVReg, unsigned Addr, uint64_t Size, - MachinePointerInfo &MPO) override; + bool handleSplit(SmallVectorImpl<unsigned> &VRegs, + ArrayRef<CCValAssign> ArgLocs, unsigned ArgLocsStartIndex, + unsigned ArgsReg) override; + + unsigned extendRegister(unsigned ValReg, const CCValAssign &VA); MachineInstrBuilder &MIB; }; } // end anonymous namespace void OutgoingValueHandler::assignValueToReg(unsigned ValVReg, - unsigned PhysReg) { - MIRBuilder.buildCopy(PhysReg, ValVReg); + const CCValAssign &VA) { + unsigned PhysReg = VA.getLocReg(); + unsigned ExtReg = extendRegister(ValVReg, VA); + MIRBuilder.buildCopy(PhysReg, ExtReg); MIB.addUse(PhysReg, RegState::Implicit); } -unsigned OutgoingValueHandler::getStackAddress(uint64_t Size, int64_t Offset, - MachinePointerInfo &MPO) { +unsigned OutgoingValueHandler::getStackAddress(const CCValAssign &VA, + MachineMemOperand *&MMO) { 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); + unsigned Offset = VA.getLocMemOffset(); MIRBuilder.buildConstant(OffsetReg, Offset); unsigned AddrReg = MRI.createGenericVirtualRegister(p0); MIRBuilder.buildGEP(AddrReg, SPReg, OffsetReg); - MPO = MachinePointerInfo::getStack(MIRBuilder.getMF(), Offset); + MachinePointerInfo MPO = + MachinePointerInfo::getStack(MIRBuilder.getMF(), Offset); + unsigned Size = alignTo(VA.getValVT().getSizeInBits(), 8) / 8; + MMO = MIRBuilder.getMF().getMachineMemOperand(MPO, MachineMemOperand::MOStore, + Size, /* Alignment */ 0); + 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); +void OutgoingValueHandler::assignValueToAddress(unsigned ValVReg, + const CCValAssign &VA) { + MachineMemOperand *MMO; + unsigned Addr = getStackAddress(VA, MMO); + unsigned ExtReg = extendRegister(ValVReg, VA); + MIRBuilder.buildStore(ExtReg, Addr, *MMO); } -bool OutgoingValueHandler::handle(ArrayRef<CCValAssign> ArgLocs, - ArrayRef<CallLowering::ArgInfo> Args) { - for (unsigned i = 0; i < Args.size(); ++i) { - if (!assign(ArgLocs[i], Args[i].Reg)) - return false; +unsigned OutgoingValueHandler::extendRegister(unsigned ValReg, + const CCValAssign &VA) { + LLT LocTy{VA.getLocVT()}; + switch (VA.getLocInfo()) { + case CCValAssign::SExt: { + unsigned ExtReg = MRI.createGenericVirtualRegister(LocTy); + MIRBuilder.buildSExt(ExtReg, ValReg); + return ExtReg; + } + case CCValAssign::ZExt: { + unsigned ExtReg = MRI.createGenericVirtualRegister(LocTy); + MIRBuilder.buildZExt(ExtReg, ValReg); + return ExtReg; + } + case CCValAssign::AExt: { + unsigned ExtReg = MRI.createGenericVirtualRegister(LocTy); + MIRBuilder.buildAnyExt(ExtReg, ValReg); + return ExtReg; + } + // TODO : handle upper extends + case CCValAssign::Full: + return ValReg; + default: + break; } + llvm_unreachable("unable to extend register"); +} + +bool OutgoingValueHandler::handleSplit(SmallVectorImpl<unsigned> &VRegs, + ArrayRef<CCValAssign> ArgLocs, + unsigned ArgLocsStartIndex, + unsigned ArgsReg) { + MIRBuilder.buildUnmerge(VRegs, ArgsReg); + setLeastSignificantFirst(VRegs); + if (!assignVRegs(VRegs, ArgLocs, ArgLocsStartIndex)) + return false; + return true; } static bool isSupportedType(Type *T) { - if (T->isIntegerTy() && T->getScalarSizeInBits() == 32) + if (T->isIntegerTy()) return true; if (T->isPointerTy()) return true; return false; } +static CCValAssign::LocInfo determineLocInfo(const MVT RegisterVT, const EVT VT, + const ISD::ArgFlagsTy &Flags) { + // > does not mean loss of information as type RegisterVT can't hold type VT, + // it means that type VT is split into multiple registers of type RegisterVT + if (VT.getSizeInBits() >= RegisterVT.getSizeInBits()) + return CCValAssign::LocInfo::Full; + if (Flags.isSExt()) + return CCValAssign::LocInfo::SExt; + if (Flags.isZExt()) + return CCValAssign::LocInfo::ZExt; + return CCValAssign::LocInfo::AExt; +} + +template <typename T> +static void setLocInfo(SmallVectorImpl<CCValAssign> &ArgLocs, + const SmallVectorImpl<T> &Arguments) { + for (unsigned i = 0; i < ArgLocs.size(); ++i) { + const CCValAssign &VA = ArgLocs[i]; + CCValAssign::LocInfo LocInfo = determineLocInfo( + Arguments[i].VT, Arguments[i].ArgVT, Arguments[i].Flags); + if (VA.isMemLoc()) + ArgLocs[i] = + CCValAssign::getMem(VA.getValNo(), VA.getValVT(), + VA.getLocMemOffset(), VA.getLocVT(), LocInfo); + else + ArgLocs[i] = CCValAssign::getReg(VA.getValNo(), VA.getValVT(), + VA.getLocReg(), VA.getLocVT(), LocInfo); + } +} + bool MipsCallLowering::lowerReturn(MachineIRBuilder &MIRBuilder, - const Value *Val, unsigned VReg) const { + const Value *Val, + ArrayRef<unsigned> VRegs) const { MachineInstrBuilder Ret = MIRBuilder.buildInstrNoInsert(Mips::RetRA); - if (Val != nullptr) { - if (!isSupportedType(Val->getType())) - return false; + if (Val != nullptr && !isSupportedType(Val->getType())) + return false; + if (!VRegs.empty()) { MachineFunction &MF = MIRBuilder.getMF(); const Function &F = MF.getFunction(); const DataLayout &DL = MF.getDataLayout(); const MipsTargetLowering &TLI = *getTLI<MipsTargetLowering>(); + LLVMContext &Ctx = Val->getType()->getContext(); + + SmallVector<EVT, 4> SplitEVTs; + ComputeValueVTs(TLI, DL, Val->getType(), SplitEVTs); + assert(VRegs.size() == SplitEVTs.size() && + "For each split Type there should be exactly one VReg."); SmallVector<ArgInfo, 8> RetInfos; SmallVector<unsigned, 8> OrigArgIndices; - ArgInfo ArgRetInfo(VReg, Val->getType()); - setArgFlags(ArgRetInfo, AttributeList::ReturnIndex, DL, F); - splitToValueTypes(ArgRetInfo, 0, RetInfos, OrigArgIndices); + for (unsigned i = 0; i < SplitEVTs.size(); ++i) { + ArgInfo CurArgInfo = ArgInfo{VRegs[i], SplitEVTs[i].getTypeForEVT(Ctx)}; + setArgFlags(CurArgInfo, AttributeList::ReturnIndex, DL, F); + splitToValueTypes(CurArgInfo, 0, RetInfos, OrigArgIndices); + } SmallVector<ISD::OutputArg, 8> Outs; - subTargetRegTypeForCallingConv( - MIRBuilder, RetInfos, OrigArgIndices, - [&](ISD::ArgFlagsTy flags, EVT vt, EVT argvt, bool used, - unsigned origIdx, unsigned partOffs) { - Outs.emplace_back(flags, vt, argvt, used, origIdx, partOffs); - }); + subTargetRegTypeForCallingConv(F, RetInfos, OrigArgIndices, Outs); SmallVector<CCValAssign, 16> ArgLocs; MipsCCState CCInfo(F.getCallingConv(), F.isVarArg(), MF, ArgLocs, F.getContext()); CCInfo.AnalyzeReturn(Outs, TLI.CCAssignFnForReturn()); + setLocInfo(ArgLocs, Outs); OutgoingValueHandler RetHandler(MIRBuilder, MF.getRegInfo(), Ret); if (!RetHandler.handle(ArgLocs, RetInfos)) { @@ -266,12 +408,7 @@ bool MipsCallLowering::lowerFormalArguments(MachineIRBuilder &MIRBuilder, } SmallVector<ISD::InputArg, 8> Ins; - subTargetRegTypeForCallingConv( - MIRBuilder, ArgInfos, OrigArgIndices, - [&](ISD::ArgFlagsTy flags, EVT vt, EVT argvt, bool used, unsigned origIdx, - unsigned partOffs) { - Ins.emplace_back(flags, vt, argvt, used, origIdx, partOffs); - }); + subTargetRegTypeForCallingConv(F, ArgInfos, OrigArgIndices, Ins); SmallVector<CCValAssign, 16> ArgLocs; MipsCCState CCInfo(F.getCallingConv(), F.isVarArg(), MF, ArgLocs, @@ -283,6 +420,7 @@ bool MipsCallLowering::lowerFormalArguments(MachineIRBuilder &MIRBuilder, CCInfo.AllocateStack(ABI.GetCalleeAllocdArgSizeInBytes(F.getCallingConv()), 1); CCInfo.AnalyzeFormalArguments(Ins, TLI.CCAssignFnForCall()); + setLocInfo(ArgLocs, Ins); IncomingValueHandler Handler(MIRBuilder, MF.getRegInfo()); if (!Handler.handle(ArgLocs, ArgInfos)) @@ -347,12 +485,7 @@ bool MipsCallLowering::lowerCall(MachineIRBuilder &MIRBuilder, } SmallVector<ISD::OutputArg, 8> 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); - }); + subTargetRegTypeForCallingConv(F, ArgInfos, OrigArgIndices, Outs); SmallVector<CCValAssign, 8> ArgLocs; MipsCCState CCInfo(F.getCallingConv(), F.isVarArg(), MF, ArgLocs, @@ -361,6 +494,7 @@ bool MipsCallLowering::lowerCall(MachineIRBuilder &MIRBuilder, CCInfo.AllocateStack(ABI.GetCalleeAllocdArgSizeInBytes(CallConv), 1); const char *Call = Callee.isSymbol() ? Callee.getSymbolName() : nullptr; CCInfo.AnalyzeCallOperands(Outs, TLI.CCAssignFnForCall(), FuncOrigArgs, Call); + setLocInfo(ArgLocs, Outs); OutgoingValueHandler RetHandler(MIRBuilder, MF.getRegInfo(), MIB); if (!RetHandler.handle(ArgLocs, ArgInfos)) { @@ -383,18 +517,14 @@ bool MipsCallLowering::lowerCall(MachineIRBuilder &MIRBuilder, splitToValueTypes(OrigRet, 0, ArgInfos, OrigRetIndices); SmallVector<ISD::InputArg, 8> 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); - }); + subTargetRegTypeForCallingConv(F, ArgInfos, OrigRetIndices, Ins); SmallVector<CCValAssign, 8> ArgLocs; MipsCCState CCInfo(F.getCallingConv(), F.isVarArg(), MF, ArgLocs, F.getContext()); CCInfo.AnalyzeCallResult(Ins, TLI.CCAssignFnForReturn(), OrigRet.Ty, Call); + setLocInfo(ArgLocs, Ins); CallReturnHandler Handler(MIRBuilder, MF.getRegInfo(), MIB); if (!Handler.handle(ArgLocs, ArgInfos)) @@ -406,11 +536,10 @@ bool MipsCallLowering::lowerCall(MachineIRBuilder &MIRBuilder, return true; } +template <typename T> void MipsCallLowering::subTargetRegTypeForCallingConv( - MachineIRBuilder &MIRBuilder, ArrayRef<ArgInfo> Args, - ArrayRef<unsigned> OrigArgIndices, const FunTy &PushBack) const { - MachineFunction &MF = MIRBuilder.getMF(); - const Function &F = MF.getFunction(); + const Function &F, ArrayRef<ArgInfo> Args, + ArrayRef<unsigned> OrigArgIndices, SmallVectorImpl<T> &ISDArgs) const { const DataLayout &DL = F.getParent()->getDataLayout(); const MipsTargetLowering &TLI = *getTLI<MipsTargetLowering>(); @@ -420,12 +549,20 @@ void MipsCallLowering::subTargetRegTypeForCallingConv( EVT VT = TLI.getValueType(DL, Arg.Ty); MVT RegisterVT = TLI.getRegisterTypeForCallingConv(F.getContext(), F.getCallingConv(), VT); + unsigned NumRegs = TLI.getNumRegistersForCallingConv( + F.getContext(), F.getCallingConv(), VT); - ISD::ArgFlagsTy Flags = Arg.Flags; - Flags.setOrigAlign(TLI.getABIAlignmentForCallingConv(Arg.Ty, DL)); + for (unsigned i = 0; i < NumRegs; ++i) { + ISD::ArgFlagsTy Flags = Arg.Flags; - PushBack(Flags, RegisterVT, VT, true, OrigArgIndices[ArgNo], 0); + if (i == 0) + Flags.setOrigAlign(TLI.getABIAlignmentForCallingConv(Arg.Ty, DL)); + else + Flags.setOrigAlign(1); + ISDArgs.emplace_back(Flags, RegisterVT, VT, true, OrigArgIndices[ArgNo], + 0); + } ++ArgNo; } } |
