From 6c260d3bc059b29aa62b91378be4afa2d98d8067 Mon Sep 17 00:00:00 2001 From: Matt Arsenault Date: Sun, 28 Feb 2021 11:12:08 -0500 Subject: [PATCH] GlobalISel: Move splitToValueTypes to generic code I copied the nearly identical function from AArch64 into AMDGPU, so fix this duplication. Mips and X86 have their own more exotic versions which should be removed. However replacing those is better left for a separate patch since it requires other changes to avoid regressions. --- .../llvm/CodeGen/GlobalISel/CallLowering.h | 7 +++ llvm/lib/CodeGen/GlobalISel/CallLowering.cpp | 37 ++++++++++++ .../AArch64/GISel/AArch64CallLowering.cpp | 45 ++------------- .../AArch64/GISel/AArch64CallLowering.h | 5 -- llvm/lib/Target/AMDGPU/AMDGPUCallLowering.cpp | 49 ++-------------- llvm/lib/Target/AMDGPU/AMDGPUCallLowering.h | 4 -- llvm/lib/Target/ARM/ARMCallLowering.cpp | 57 ++----------------- llvm/lib/Target/ARM/ARMCallLowering.h | 6 -- llvm/lib/Target/Mips/MipsCallLowering.cpp | 1 + llvm/lib/Target/X86/X86CallLowering.cpp | 1 + 10 files changed, 60 insertions(+), 152 deletions(-) diff --git a/llvm/include/llvm/CodeGen/GlobalISel/CallLowering.h b/llvm/include/llvm/CodeGen/GlobalISel/CallLowering.h index 1141bddbc1a8..5e5530508a4a 100644 --- a/llvm/include/llvm/CodeGen/GlobalISel/CallLowering.h +++ b/llvm/include/llvm/CodeGen/GlobalISel/CallLowering.h @@ -244,6 +244,13 @@ protected: void setArgFlags(ArgInfo &Arg, unsigned OpIdx, const DataLayout &DL, const FuncInfoTy &FuncInfo) const; + /// Break \p OrigArgInfo into one or more pieces the calling convention can + /// process, returned in \p SplitArgs. For example, this should break structs + /// down into individual fields. + void splitToValueTypes(const ArgInfo &OrigArgInfo, + SmallVectorImpl &SplitArgs, + const DataLayout &DL, CallingConv::ID CallConv) const; + /// Generate instructions for packing \p SrcRegs into one big register /// corresponding to the aggregate type \p PackedTy. /// diff --git a/llvm/lib/CodeGen/GlobalISel/CallLowering.cpp b/llvm/lib/CodeGen/GlobalISel/CallLowering.cpp index c6bfa2451936..d0e8188cf555 100644 --- a/llvm/lib/CodeGen/GlobalISel/CallLowering.cpp +++ b/llvm/lib/CodeGen/GlobalISel/CallLowering.cpp @@ -187,6 +187,43 @@ CallLowering::setArgFlags(CallLowering::ArgInfo &Arg, unsigned OpIdx, const DataLayout &DL, const CallBase &FuncInfo) const; +void CallLowering::splitToValueTypes(const ArgInfo &OrigArg, + SmallVectorImpl &SplitArgs, + const DataLayout &DL, + CallingConv::ID CallConv) const { + LLVMContext &Ctx = OrigArg.Ty->getContext(); + + SmallVector SplitVTs; + SmallVector Offsets; + ComputeValueVTs(*TLI, DL, OrigArg.Ty, SplitVTs, &Offsets, 0); + + if (SplitVTs.size() == 0) + return; + + if (SplitVTs.size() == 1) { + // No splitting to do, but we want to replace the original type (e.g. [1 x + // double] -> double). + SplitArgs.emplace_back(OrigArg.Regs[0], SplitVTs[0].getTypeForEVT(Ctx), + OrigArg.Flags[0], OrigArg.IsFixed); + return; + } + + // Create one ArgInfo for each virtual register in the original ArgInfo. + assert(OrigArg.Regs.size() == SplitVTs.size() && "Regs / types mismatch"); + + bool NeedsRegBlock = TLI->functionArgumentNeedsConsecutiveRegisters( + OrigArg.Ty, CallConv, false); + for (unsigned i = 0, e = SplitVTs.size(); i < e; ++i) { + Type *SplitTy = SplitVTs[i].getTypeForEVT(Ctx); + SplitArgs.emplace_back(OrigArg.Regs[i], SplitTy, OrigArg.Flags[0], + OrigArg.IsFixed); + if (NeedsRegBlock) + SplitArgs.back().Flags[0].setInConsecutiveRegs(); + } + + SplitArgs.back().Flags[0].setInConsecutiveRegsLast(); +} + Register CallLowering::packRegs(ArrayRef SrcRegs, Type *PackedTy, MachineIRBuilder &MIRBuilder) const { assert(SrcRegs.size() > 1 && "Nothing to pack"); diff --git a/llvm/lib/Target/AArch64/GISel/AArch64CallLowering.cpp b/llvm/lib/Target/AArch64/GISel/AArch64CallLowering.cpp index ed6b231e5add..c128e50236ed 100644 --- a/llvm/lib/Target/AArch64/GISel/AArch64CallLowering.cpp +++ b/llvm/lib/Target/AArch64/GISel/AArch64CallLowering.cpp @@ -285,43 +285,6 @@ static bool doesCalleeRestoreStack(CallingConv::ID CallConv, bool TailCallOpt) { return CallConv == CallingConv::Fast && TailCallOpt; } -void AArch64CallLowering::splitToValueTypes( - const ArgInfo &OrigArg, SmallVectorImpl &SplitArgs, - const DataLayout &DL, MachineRegisterInfo &MRI, CallingConv::ID CallConv) const { - const AArch64TargetLowering &TLI = *getTLI(); - LLVMContext &Ctx = OrigArg.Ty->getContext(); - - SmallVector SplitVTs; - SmallVector Offsets; - ComputeValueVTs(TLI, DL, OrigArg.Ty, SplitVTs, &Offsets, 0); - - if (SplitVTs.size() == 0) - return; - - if (SplitVTs.size() == 1) { - // No splitting to do, but we want to replace the original type (e.g. [1 x - // double] -> double). - SplitArgs.emplace_back(OrigArg.Regs[0], SplitVTs[0].getTypeForEVT(Ctx), - OrigArg.Flags[0], OrigArg.IsFixed); - return; - } - - // Create one ArgInfo for each virtual register in the original ArgInfo. - assert(OrigArg.Regs.size() == SplitVTs.size() && "Regs / types mismatch"); - - bool NeedsRegBlock = TLI.functionArgumentNeedsConsecutiveRegisters( - OrigArg.Ty, CallConv, false); - for (unsigned i = 0, e = SplitVTs.size(); i < e; ++i) { - Type *SplitTy = SplitVTs[i].getTypeForEVT(Ctx); - SplitArgs.emplace_back(OrigArg.Regs[i], SplitTy, OrigArg.Flags[0], - OrigArg.IsFixed); - if (NeedsRegBlock) - SplitArgs.back().Flags[0].setInConsecutiveRegs(); - } - - SplitArgs.back().Flags[0].setInConsecutiveRegsLast(); -} - bool AArch64CallLowering::lowerReturn(MachineIRBuilder &MIRBuilder, const Value *Val, ArrayRef VRegs, @@ -423,7 +386,7 @@ bool AArch64CallLowering::lowerReturn(MachineIRBuilder &MIRBuilder, // Reset the arg flags after modifying CurVReg. setArgFlags(CurArgInfo, AttributeList::ReturnIndex, DL, F); } - splitToValueTypes(CurArgInfo, SplitArgs, DL, MRI, CC); + splitToValueTypes(CurArgInfo, SplitArgs, DL, CC); } OutgoingArgHandler Handler(MIRBuilder, MRI, MIB, AssignFn, AssignFn); @@ -508,7 +471,7 @@ bool AArch64CallLowering::lowerFormalArguments( ArgInfo OrigArg{VRegs[i], Arg.getType()}; setArgFlags(OrigArg, i + AttributeList::FirstArgIndex, DL, F); - splitToValueTypes(OrigArg, SplitArgs, DL, MRI, F.getCallingConv()); + splitToValueTypes(OrigArg, SplitArgs, DL, F.getCallingConv()); ++i; } @@ -986,7 +949,7 @@ bool AArch64CallLowering::lowerCall(MachineIRBuilder &MIRBuilder, SmallVector OutArgs; for (auto &OrigArg : Info.OrigArgs) { - splitToValueTypes(OrigArg, OutArgs, DL, MRI, Info.CallConv); + splitToValueTypes(OrigArg, OutArgs, DL, Info.CallConv); // AAPCS requires that we zero-extend i1 to 8 bits by the caller. if (OrigArg.Ty->isIntegerTy(1)) OutArgs.back().Flags[0].setZExt(); @@ -994,7 +957,7 @@ bool AArch64CallLowering::lowerCall(MachineIRBuilder &MIRBuilder, SmallVector InArgs; if (!Info.OrigRet.Ty->isVoidTy()) - splitToValueTypes(Info.OrigRet, InArgs, DL, MRI, Info.CallConv); + splitToValueTypes(Info.OrigRet, InArgs, DL, Info.CallConv); // If we can lower as a tail call, do that instead. bool CanTailCallOpt = diff --git a/llvm/lib/Target/AArch64/GISel/AArch64CallLowering.h b/llvm/lib/Target/AArch64/GISel/AArch64CallLowering.h index 786dfc88e29c..1b9de9f93a33 100644 --- a/llvm/lib/Target/AArch64/GISel/AArch64CallLowering.h +++ b/llvm/lib/Target/AArch64/GISel/AArch64CallLowering.h @@ -64,11 +64,6 @@ private: using MemHandler = std::function; - void splitToValueTypes(const ArgInfo &OrigArgInfo, - SmallVectorImpl &SplitArgs, - const DataLayout &DL, MachineRegisterInfo &MRI, - CallingConv::ID CallConv) const; - bool lowerTailCall(MachineIRBuilder &MIRBuilder, CallLoweringInfo &Info, SmallVectorImpl &OutArgs) const; diff --git a/llvm/lib/Target/AMDGPU/AMDGPUCallLowering.cpp b/llvm/lib/Target/AMDGPU/AMDGPUCallLowering.cpp index 6d0df5ce53c2..7ad62fe6da65 100644 --- a/llvm/lib/Target/AMDGPU/AMDGPUCallLowering.cpp +++ b/llvm/lib/Target/AMDGPU/AMDGPUCallLowering.cpp @@ -278,47 +278,6 @@ static ISD::NodeType extOpcodeToISDExtOpcode(unsigned MIOpc) { } } -// FIXME: This should move to generic code. -void AMDGPUCallLowering::splitToValueTypes(MachineIRBuilder &B, - const ArgInfo &OrigArg, - SmallVectorImpl &SplitArgs, - const DataLayout &DL, - CallingConv::ID CallConv) const { - const SITargetLowering &TLI = *getTLI(); - LLVMContext &Ctx = OrigArg.Ty->getContext(); - - SmallVector SplitVTs; - ComputeValueVTs(TLI, DL, OrigArg.Ty, SplitVTs); - - assert(OrigArg.Regs.size() == SplitVTs.size()); - - if (SplitVTs.size() == 0) - return; - - if (SplitVTs.size() == 1) { - // No splitting to do, but we want to replace the original type (e.g. [1 x - // double] -> double). - SplitArgs.emplace_back(OrigArg.Regs[0], SplitVTs[0].getTypeForEVT(Ctx), - OrigArg.Flags[0], OrigArg.IsFixed); - return; - } - - // Create one ArgInfo for each virtual register in the original ArgInfo. - assert(OrigArg.Regs.size() == SplitVTs.size() && "Regs / types mismatch"); - - bool NeedsRegBlock = TLI.functionArgumentNeedsConsecutiveRegisters( - OrigArg.Ty, CallConv, false); - for (unsigned i = 0, e = SplitVTs.size(); i < e; ++i) { - Type *SplitTy = SplitVTs[i].getTypeForEVT(Ctx); - SplitArgs.emplace_back(OrigArg.Regs[i], SplitTy, OrigArg.Flags[0], - OrigArg.IsFixed); - if (NeedsRegBlock) - SplitArgs.back().Flags[0].setInConsecutiveRegs(); - } - - SplitArgs.back().Flags[0].setInConsecutiveRegsLast(); -} - void AMDGPUCallLowering::processSplitArgs( MachineIRBuilder &B, const ArgInfo &OrigArg, const SmallVectorImpl &SplitArg, @@ -498,7 +457,7 @@ bool AMDGPUCallLowering::lowerReturnVal(MachineIRBuilder &B, setArgFlags(RetInfo, AttributeList::ReturnIndex, DL, F); } - splitToValueTypes(B, RetInfo, PreSplitRetInfos, DL, CC); + splitToValueTypes(RetInfo, PreSplitRetInfos, DL, CC); // FIXME: This splitting should mostly be done by handleAssignments processSplitArgs(B, RetInfo, @@ -824,7 +783,7 @@ bool AMDGPUCallLowering::lowerFormalArguments( const unsigned OrigArgIdx = Idx + AttributeList::FirstArgIndex; setArgFlags(OrigArg, OrigArgIdx, DL, F); - splitToValueTypes(B, OrigArg, SplitArgs, DL, CC); + splitToValueTypes(OrigArg, SplitArgs, DL, CC); ++Idx; } @@ -1117,7 +1076,7 @@ bool AMDGPUCallLowering::lowerCall(MachineIRBuilder &MIRBuilder, SmallVector SplitArg; for (auto &OrigArg : Info.OrigArgs) { - splitToValueTypes(MIRBuilder, OrigArg, SplitArg, DL, Info.CallConv); + splitToValueTypes(OrigArg, SplitArg, DL, Info.CallConv); processSplitArgs( MIRBuilder, OrigArg, SplitArg, OutArgs, DL, Info.CallConv, true, @@ -1232,7 +1191,7 @@ bool AMDGPUCallLowering::lowerCall(MachineIRBuilder &MIRBuilder, insertSRetLoads(MIRBuilder, Info.OrigRet.Ty, Info.OrigRet.Regs, Info.DemoteRegister, Info.DemoteStackIndex); } else if (!Info.OrigRet.Ty->isVoidTy()) { - splitToValueTypes(MIRBuilder, Info.OrigRet, InArgs, DL, Info.CallConv); + splitToValueTypes(Info.OrigRet, InArgs, DL, Info.CallConv); } // Make sure the raw argument copies are inserted before the marshalling to diff --git a/llvm/lib/Target/AMDGPU/AMDGPUCallLowering.h b/llvm/lib/Target/AMDGPU/AMDGPUCallLowering.h index 1312388e4a38..8a3280cfcc4a 100644 --- a/llvm/lib/Target/AMDGPU/AMDGPUCallLowering.h +++ b/llvm/lib/Target/AMDGPU/AMDGPUCallLowering.h @@ -31,10 +31,6 @@ class AMDGPUCallLowering final : public CallLowering { /// A function of this type is used to perform value split action. using SplitArgTy = std::function, Register, LLT, LLT, int)>; - void splitToValueTypes(MachineIRBuilder &B, const ArgInfo &OrigArgInfo, - SmallVectorImpl &SplitArgs, - const DataLayout &DL, CallingConv::ID CallConv) const; - void processSplitArgs(MachineIRBuilder &B, const ArgInfo &OrigArgInfo, const SmallVectorImpl &SplitArg, SmallVectorImpl &SplitArgs, diff --git a/llvm/lib/Target/ARM/ARMCallLowering.cpp b/llvm/lib/Target/ARM/ARMCallLowering.cpp index ea789e2e33ca..d4b920a43e89 100644 --- a/llvm/lib/Target/ARM/ARMCallLowering.cpp +++ b/llvm/lib/Target/ARM/ARMCallLowering.cpp @@ -186,51 +186,6 @@ struct ARMOutgoingValueHandler : public CallLowering::OutgoingValueHandler { } // end anonymous namespace -void ARMCallLowering::splitToValueTypes(const ArgInfo &OrigArg, - SmallVectorImpl &SplitArgs, - MachineFunction &MF) const { - const ARMTargetLowering &TLI = *getTLI(); - LLVMContext &Ctx = OrigArg.Ty->getContext(); - const DataLayout &DL = MF.getDataLayout(); - const Function &F = MF.getFunction(); - - SmallVector SplitVTs; - ComputeValueVTs(TLI, DL, OrigArg.Ty, SplitVTs, nullptr, nullptr, 0); - assert(OrigArg.Regs.size() == SplitVTs.size() && "Regs / types mismatch"); - - if (SplitVTs.size() == 1) { - // Even if there is no splitting to do, we still want to replace the - // original type (e.g. pointer type -> integer). - auto Flags = OrigArg.Flags[0]; - Flags.setOrigAlign(DL.getABITypeAlign(OrigArg.Ty)); - SplitArgs.emplace_back(OrigArg.Regs[0], SplitVTs[0].getTypeForEVT(Ctx), - Flags, OrigArg.IsFixed); - return; - } - - // Create one ArgInfo for each virtual register. - for (unsigned i = 0, e = SplitVTs.size(); i != e; ++i) { - EVT SplitVT = SplitVTs[i]; - Type *SplitTy = SplitVT.getTypeForEVT(Ctx); - auto Flags = OrigArg.Flags[0]; - - Flags.setOrigAlign(DL.getABITypeAlign(SplitTy)); - - bool NeedsConsecutiveRegisters = - TLI.functionArgumentNeedsConsecutiveRegisters( - SplitTy, F.getCallingConv(), F.isVarArg()); - if (NeedsConsecutiveRegisters) { - Flags.setInConsecutiveRegs(); - if (i == e - 1) - Flags.setInConsecutiveRegsLast(); - } - - // FIXME: We also want to split SplitTy further. - Register PartReg = OrigArg.Regs[i]; - SplitArgs.emplace_back(PartReg, SplitTy, Flags, OrigArg.IsFixed); - } -} - /// Lower the return value for the already existing \p Ret. This assumes that /// \p MIRBuilder's insertion point is correct. bool ARMCallLowering::lowerReturnVal(MachineIRBuilder &MIRBuilder, @@ -243,7 +198,7 @@ bool ARMCallLowering::lowerReturnVal(MachineIRBuilder &MIRBuilder, auto &MF = MIRBuilder.getMF(); const auto &F = MF.getFunction(); - auto DL = MF.getDataLayout(); + const auto &DL = MF.getDataLayout(); auto &TLI = *getTLI(); if (!isSupportedType(DL, TLI, Val->getType())) return false; @@ -252,7 +207,7 @@ bool ARMCallLowering::lowerReturnVal(MachineIRBuilder &MIRBuilder, setArgFlags(OrigRetInfo, AttributeList::ReturnIndex, DL, F); SmallVector SplitRetInfos; - splitToValueTypes(OrigRetInfo, SplitRetInfos, MF); + splitToValueTypes(OrigRetInfo, SplitRetInfos, DL, F.getCallingConv()); CCAssignFn *AssignFn = TLI.CCAssignFnForReturn(F.getCallingConv(), F.isVarArg()); @@ -430,7 +385,7 @@ bool ARMCallLowering::lowerFormalArguments(MachineIRBuilder &MIRBuilder, auto &MF = MIRBuilder.getMF(); auto &MBB = MIRBuilder.getMBB(); - auto DL = MF.getDataLayout(); + const auto &DL = MF.getDataLayout(); for (auto &Arg : F.args()) { if (!isSupportedType(DL, TLI, Arg.getType())) @@ -451,7 +406,7 @@ bool ARMCallLowering::lowerFormalArguments(MachineIRBuilder &MIRBuilder, ArgInfo OrigArgInfo(VRegs[Idx], Arg.getType()); setArgFlags(OrigArgInfo, Idx + AttributeList::FirstArgIndex, DL, F); - splitToValueTypes(OrigArgInfo, SplitArgInfos, MF); + splitToValueTypes(OrigArgInfo, SplitArgInfos, DL, F.getCallingConv()); Idx++; } @@ -548,7 +503,7 @@ bool ARMCallLowering::lowerCall(MachineIRBuilder &MIRBuilder, CallLoweringInfo & if (Arg.Flags[0].isByVal()) return false; - splitToValueTypes(Arg, ArgInfos, MF); + splitToValueTypes(Arg, ArgInfos, DL, Info.CallConv); } auto ArgAssignFn = TLI.CCAssignFnForCall(Info.CallConv, Info.IsVarArg); @@ -565,7 +520,7 @@ bool ARMCallLowering::lowerCall(MachineIRBuilder &MIRBuilder, CallLoweringInfo & return false; ArgInfos.clear(); - splitToValueTypes(Info.OrigRet, ArgInfos, MF); + splitToValueTypes(Info.OrigRet, ArgInfos, DL, Info.CallConv); auto RetAssignFn = TLI.CCAssignFnForReturn(Info.CallConv, Info.IsVarArg); CallReturnHandler RetHandler(MIRBuilder, MRI, MIB, RetAssignFn); if (!handleAssignments(MIRBuilder, ArgInfos, RetHandler, Info.CallConv, diff --git a/llvm/lib/Target/ARM/ARMCallLowering.h b/llvm/lib/Target/ARM/ARMCallLowering.h index 3be73d497d0b..87b18f811747 100644 --- a/llvm/lib/Target/ARM/ARMCallLowering.h +++ b/llvm/lib/Target/ARM/ARMCallLowering.h @@ -47,12 +47,6 @@ private: bool lowerReturnVal(MachineIRBuilder &MIRBuilder, const Value *Val, ArrayRef VRegs, MachineInstrBuilder &Ret) const; - - /// Split an argument into one or more arguments that the CC lowering can cope - /// with. - void splitToValueTypes(const ArgInfo &OrigArg, - SmallVectorImpl &SplitArgs, - MachineFunction &MF) const; }; } // end namespace llvm diff --git a/llvm/lib/Target/Mips/MipsCallLowering.cpp b/llvm/lib/Target/Mips/MipsCallLowering.cpp index 377aa4825b43..d5251ce10bd2 100644 --- a/llvm/lib/Target/Mips/MipsCallLowering.cpp +++ b/llvm/lib/Target/Mips/MipsCallLowering.cpp @@ -664,6 +664,7 @@ void MipsCallLowering::subTargetRegTypeForCallingConv( } } +// FIXME: This should be removed and the generic version used void MipsCallLowering::splitToValueTypes( const DataLayout &DL, const ArgInfo &OrigArg, unsigned OriginalIndex, SmallVectorImpl &SplitArgs, diff --git a/llvm/lib/Target/X86/X86CallLowering.cpp b/llvm/lib/Target/X86/X86CallLowering.cpp index 8c6a44671c75..28bba84c7448 100644 --- a/llvm/lib/Target/X86/X86CallLowering.cpp +++ b/llvm/lib/Target/X86/X86CallLowering.cpp @@ -50,6 +50,7 @@ using namespace llvm; X86CallLowering::X86CallLowering(const X86TargetLowering &TLI) : CallLowering(&TLI) {} +// FIXME: This should be removed and the generic version used bool X86CallLowering::splitToValueTypes(const ArgInfo &OrigArg, SmallVectorImpl &SplitArgs, const DataLayout &DL,