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.
This commit is contained in:
Matt Arsenault 2021-02-28 11:12:08 -05:00
parent b4bfe29415
commit 6c260d3bc0
10 changed files with 60 additions and 152 deletions

View File

@ -244,6 +244,13 @@ protected:
void setArgFlags(ArgInfo &Arg, unsigned OpIdx, const DataLayout &DL, void setArgFlags(ArgInfo &Arg, unsigned OpIdx, const DataLayout &DL,
const FuncInfoTy &FuncInfo) const; 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<ArgInfo> &SplitArgs,
const DataLayout &DL, CallingConv::ID CallConv) const;
/// Generate instructions for packing \p SrcRegs into one big register /// Generate instructions for packing \p SrcRegs into one big register
/// corresponding to the aggregate type \p PackedTy. /// corresponding to the aggregate type \p PackedTy.
/// ///

View File

@ -187,6 +187,43 @@ CallLowering::setArgFlags<CallBase>(CallLowering::ArgInfo &Arg, unsigned OpIdx,
const DataLayout &DL, const DataLayout &DL,
const CallBase &FuncInfo) const; const CallBase &FuncInfo) const;
void CallLowering::splitToValueTypes(const ArgInfo &OrigArg,
SmallVectorImpl<ArgInfo> &SplitArgs,
const DataLayout &DL,
CallingConv::ID CallConv) const {
LLVMContext &Ctx = OrigArg.Ty->getContext();
SmallVector<EVT, 4> SplitVTs;
SmallVector<uint64_t, 4> 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<Register> SrcRegs, Type *PackedTy, Register CallLowering::packRegs(ArrayRef<Register> SrcRegs, Type *PackedTy,
MachineIRBuilder &MIRBuilder) const { MachineIRBuilder &MIRBuilder) const {
assert(SrcRegs.size() > 1 && "Nothing to pack"); assert(SrcRegs.size() > 1 && "Nothing to pack");

View File

@ -285,43 +285,6 @@ static bool doesCalleeRestoreStack(CallingConv::ID CallConv, bool TailCallOpt) {
return CallConv == CallingConv::Fast && TailCallOpt; return CallConv == CallingConv::Fast && TailCallOpt;
} }
void AArch64CallLowering::splitToValueTypes(
const ArgInfo &OrigArg, SmallVectorImpl<ArgInfo> &SplitArgs,
const DataLayout &DL, MachineRegisterInfo &MRI, CallingConv::ID CallConv) const {
const AArch64TargetLowering &TLI = *getTLI<AArch64TargetLowering>();
LLVMContext &Ctx = OrigArg.Ty->getContext();
SmallVector<EVT, 4> SplitVTs;
SmallVector<uint64_t, 4> 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, bool AArch64CallLowering::lowerReturn(MachineIRBuilder &MIRBuilder,
const Value *Val, const Value *Val,
ArrayRef<Register> VRegs, ArrayRef<Register> VRegs,
@ -423,7 +386,7 @@ bool AArch64CallLowering::lowerReturn(MachineIRBuilder &MIRBuilder,
// Reset the arg flags after modifying CurVReg. // Reset the arg flags after modifying CurVReg.
setArgFlags(CurArgInfo, AttributeList::ReturnIndex, DL, F); setArgFlags(CurArgInfo, AttributeList::ReturnIndex, DL, F);
} }
splitToValueTypes(CurArgInfo, SplitArgs, DL, MRI, CC); splitToValueTypes(CurArgInfo, SplitArgs, DL, CC);
} }
OutgoingArgHandler Handler(MIRBuilder, MRI, MIB, AssignFn, AssignFn); OutgoingArgHandler Handler(MIRBuilder, MRI, MIB, AssignFn, AssignFn);
@ -508,7 +471,7 @@ bool AArch64CallLowering::lowerFormalArguments(
ArgInfo OrigArg{VRegs[i], Arg.getType()}; ArgInfo OrigArg{VRegs[i], Arg.getType()};
setArgFlags(OrigArg, i + AttributeList::FirstArgIndex, DL, F); setArgFlags(OrigArg, i + AttributeList::FirstArgIndex, DL, F);
splitToValueTypes(OrigArg, SplitArgs, DL, MRI, F.getCallingConv()); splitToValueTypes(OrigArg, SplitArgs, DL, F.getCallingConv());
++i; ++i;
} }
@ -986,7 +949,7 @@ bool AArch64CallLowering::lowerCall(MachineIRBuilder &MIRBuilder,
SmallVector<ArgInfo, 8> OutArgs; SmallVector<ArgInfo, 8> OutArgs;
for (auto &OrigArg : Info.OrigArgs) { 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. // AAPCS requires that we zero-extend i1 to 8 bits by the caller.
if (OrigArg.Ty->isIntegerTy(1)) if (OrigArg.Ty->isIntegerTy(1))
OutArgs.back().Flags[0].setZExt(); OutArgs.back().Flags[0].setZExt();
@ -994,7 +957,7 @@ bool AArch64CallLowering::lowerCall(MachineIRBuilder &MIRBuilder,
SmallVector<ArgInfo, 8> InArgs; SmallVector<ArgInfo, 8> InArgs;
if (!Info.OrigRet.Ty->isVoidTy()) 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. // If we can lower as a tail call, do that instead.
bool CanTailCallOpt = bool CanTailCallOpt =

View File

@ -64,11 +64,6 @@ private:
using MemHandler = using MemHandler =
std::function<void(MachineIRBuilder &, int, CCValAssign &)>; std::function<void(MachineIRBuilder &, int, CCValAssign &)>;
void splitToValueTypes(const ArgInfo &OrigArgInfo,
SmallVectorImpl<ArgInfo> &SplitArgs,
const DataLayout &DL, MachineRegisterInfo &MRI,
CallingConv::ID CallConv) const;
bool lowerTailCall(MachineIRBuilder &MIRBuilder, CallLoweringInfo &Info, bool lowerTailCall(MachineIRBuilder &MIRBuilder, CallLoweringInfo &Info,
SmallVectorImpl<ArgInfo> &OutArgs) const; SmallVectorImpl<ArgInfo> &OutArgs) const;

View File

@ -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<ArgInfo> &SplitArgs,
const DataLayout &DL,
CallingConv::ID CallConv) const {
const SITargetLowering &TLI = *getTLI<SITargetLowering>();
LLVMContext &Ctx = OrigArg.Ty->getContext();
SmallVector<EVT, 4> 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( void AMDGPUCallLowering::processSplitArgs(
MachineIRBuilder &B, const ArgInfo &OrigArg, MachineIRBuilder &B, const ArgInfo &OrigArg,
const SmallVectorImpl<ArgInfo> &SplitArg, const SmallVectorImpl<ArgInfo> &SplitArg,
@ -498,7 +457,7 @@ bool AMDGPUCallLowering::lowerReturnVal(MachineIRBuilder &B,
setArgFlags(RetInfo, AttributeList::ReturnIndex, DL, F); 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 // FIXME: This splitting should mostly be done by handleAssignments
processSplitArgs(B, RetInfo, processSplitArgs(B, RetInfo,
@ -824,7 +783,7 @@ bool AMDGPUCallLowering::lowerFormalArguments(
const unsigned OrigArgIdx = Idx + AttributeList::FirstArgIndex; const unsigned OrigArgIdx = Idx + AttributeList::FirstArgIndex;
setArgFlags(OrigArg, OrigArgIdx, DL, F); setArgFlags(OrigArg, OrigArgIdx, DL, F);
splitToValueTypes(B, OrigArg, SplitArgs, DL, CC); splitToValueTypes(OrigArg, SplitArgs, DL, CC);
++Idx; ++Idx;
} }
@ -1117,7 +1076,7 @@ bool AMDGPUCallLowering::lowerCall(MachineIRBuilder &MIRBuilder,
SmallVector<ArgInfo, 8> SplitArg; SmallVector<ArgInfo, 8> SplitArg;
for (auto &OrigArg : Info.OrigArgs) { for (auto &OrigArg : Info.OrigArgs) {
splitToValueTypes(MIRBuilder, OrigArg, SplitArg, DL, Info.CallConv); splitToValueTypes(OrigArg, SplitArg, DL, Info.CallConv);
processSplitArgs( processSplitArgs(
MIRBuilder, OrigArg, SplitArg, OutArgs, DL, Info.CallConv, true, 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, insertSRetLoads(MIRBuilder, Info.OrigRet.Ty, Info.OrigRet.Regs,
Info.DemoteRegister, Info.DemoteStackIndex); Info.DemoteRegister, Info.DemoteStackIndex);
} else if (!Info.OrigRet.Ty->isVoidTy()) { } 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 // Make sure the raw argument copies are inserted before the marshalling to

View File

@ -31,10 +31,6 @@ class AMDGPUCallLowering final : public CallLowering {
/// A function of this type is used to perform value split action. /// A function of this type is used to perform value split action.
using SplitArgTy = std::function<void(ArrayRef<Register>, Register, LLT, LLT, int)>; using SplitArgTy = std::function<void(ArrayRef<Register>, Register, LLT, LLT, int)>;
void splitToValueTypes(MachineIRBuilder &B, const ArgInfo &OrigArgInfo,
SmallVectorImpl<ArgInfo> &SplitArgs,
const DataLayout &DL, CallingConv::ID CallConv) const;
void processSplitArgs(MachineIRBuilder &B, const ArgInfo &OrigArgInfo, void processSplitArgs(MachineIRBuilder &B, const ArgInfo &OrigArgInfo,
const SmallVectorImpl<ArgInfo> &SplitArg, const SmallVectorImpl<ArgInfo> &SplitArg,
SmallVectorImpl<ArgInfo> &SplitArgs, SmallVectorImpl<ArgInfo> &SplitArgs,

View File

@ -186,51 +186,6 @@ struct ARMOutgoingValueHandler : public CallLowering::OutgoingValueHandler {
} // end anonymous namespace } // end anonymous namespace
void ARMCallLowering::splitToValueTypes(const ArgInfo &OrigArg,
SmallVectorImpl<ArgInfo> &SplitArgs,
MachineFunction &MF) const {
const ARMTargetLowering &TLI = *getTLI<ARMTargetLowering>();
LLVMContext &Ctx = OrigArg.Ty->getContext();
const DataLayout &DL = MF.getDataLayout();
const Function &F = MF.getFunction();
SmallVector<EVT, 4> 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 /// Lower the return value for the already existing \p Ret. This assumes that
/// \p MIRBuilder's insertion point is correct. /// \p MIRBuilder's insertion point is correct.
bool ARMCallLowering::lowerReturnVal(MachineIRBuilder &MIRBuilder, bool ARMCallLowering::lowerReturnVal(MachineIRBuilder &MIRBuilder,
@ -243,7 +198,7 @@ bool ARMCallLowering::lowerReturnVal(MachineIRBuilder &MIRBuilder,
auto &MF = MIRBuilder.getMF(); auto &MF = MIRBuilder.getMF();
const auto &F = MF.getFunction(); const auto &F = MF.getFunction();
auto DL = MF.getDataLayout(); const auto &DL = MF.getDataLayout();
auto &TLI = *getTLI<ARMTargetLowering>(); auto &TLI = *getTLI<ARMTargetLowering>();
if (!isSupportedType(DL, TLI, Val->getType())) if (!isSupportedType(DL, TLI, Val->getType()))
return false; return false;
@ -252,7 +207,7 @@ bool ARMCallLowering::lowerReturnVal(MachineIRBuilder &MIRBuilder,
setArgFlags(OrigRetInfo, AttributeList::ReturnIndex, DL, F); setArgFlags(OrigRetInfo, AttributeList::ReturnIndex, DL, F);
SmallVector<ArgInfo, 4> SplitRetInfos; SmallVector<ArgInfo, 4> SplitRetInfos;
splitToValueTypes(OrigRetInfo, SplitRetInfos, MF); splitToValueTypes(OrigRetInfo, SplitRetInfos, DL, F.getCallingConv());
CCAssignFn *AssignFn = CCAssignFn *AssignFn =
TLI.CCAssignFnForReturn(F.getCallingConv(), F.isVarArg()); TLI.CCAssignFnForReturn(F.getCallingConv(), F.isVarArg());
@ -430,7 +385,7 @@ bool ARMCallLowering::lowerFormalArguments(MachineIRBuilder &MIRBuilder,
auto &MF = MIRBuilder.getMF(); auto &MF = MIRBuilder.getMF();
auto &MBB = MIRBuilder.getMBB(); auto &MBB = MIRBuilder.getMBB();
auto DL = MF.getDataLayout(); const auto &DL = MF.getDataLayout();
for (auto &Arg : F.args()) { for (auto &Arg : F.args()) {
if (!isSupportedType(DL, TLI, Arg.getType())) if (!isSupportedType(DL, TLI, Arg.getType()))
@ -451,7 +406,7 @@ bool ARMCallLowering::lowerFormalArguments(MachineIRBuilder &MIRBuilder,
ArgInfo OrigArgInfo(VRegs[Idx], Arg.getType()); ArgInfo OrigArgInfo(VRegs[Idx], Arg.getType());
setArgFlags(OrigArgInfo, Idx + AttributeList::FirstArgIndex, DL, F); setArgFlags(OrigArgInfo, Idx + AttributeList::FirstArgIndex, DL, F);
splitToValueTypes(OrigArgInfo, SplitArgInfos, MF); splitToValueTypes(OrigArgInfo, SplitArgInfos, DL, F.getCallingConv());
Idx++; Idx++;
} }
@ -548,7 +503,7 @@ bool ARMCallLowering::lowerCall(MachineIRBuilder &MIRBuilder, CallLoweringInfo &
if (Arg.Flags[0].isByVal()) if (Arg.Flags[0].isByVal())
return false; return false;
splitToValueTypes(Arg, ArgInfos, MF); splitToValueTypes(Arg, ArgInfos, DL, Info.CallConv);
} }
auto ArgAssignFn = TLI.CCAssignFnForCall(Info.CallConv, Info.IsVarArg); auto ArgAssignFn = TLI.CCAssignFnForCall(Info.CallConv, Info.IsVarArg);
@ -565,7 +520,7 @@ bool ARMCallLowering::lowerCall(MachineIRBuilder &MIRBuilder, CallLoweringInfo &
return false; return false;
ArgInfos.clear(); ArgInfos.clear();
splitToValueTypes(Info.OrigRet, ArgInfos, MF); splitToValueTypes(Info.OrigRet, ArgInfos, DL, Info.CallConv);
auto RetAssignFn = TLI.CCAssignFnForReturn(Info.CallConv, Info.IsVarArg); auto RetAssignFn = TLI.CCAssignFnForReturn(Info.CallConv, Info.IsVarArg);
CallReturnHandler RetHandler(MIRBuilder, MRI, MIB, RetAssignFn); CallReturnHandler RetHandler(MIRBuilder, MRI, MIB, RetAssignFn);
if (!handleAssignments(MIRBuilder, ArgInfos, RetHandler, Info.CallConv, if (!handleAssignments(MIRBuilder, ArgInfos, RetHandler, Info.CallConv,

View File

@ -47,12 +47,6 @@ private:
bool lowerReturnVal(MachineIRBuilder &MIRBuilder, const Value *Val, bool lowerReturnVal(MachineIRBuilder &MIRBuilder, const Value *Val,
ArrayRef<Register> VRegs, ArrayRef<Register> VRegs,
MachineInstrBuilder &Ret) const; MachineInstrBuilder &Ret) const;
/// Split an argument into one or more arguments that the CC lowering can cope
/// with.
void splitToValueTypes(const ArgInfo &OrigArg,
SmallVectorImpl<ArgInfo> &SplitArgs,
MachineFunction &MF) const;
}; };
} // end namespace llvm } // end namespace llvm

View File

@ -664,6 +664,7 @@ void MipsCallLowering::subTargetRegTypeForCallingConv(
} }
} }
// FIXME: This should be removed and the generic version used
void MipsCallLowering::splitToValueTypes( void MipsCallLowering::splitToValueTypes(
const DataLayout &DL, const ArgInfo &OrigArg, unsigned OriginalIndex, const DataLayout &DL, const ArgInfo &OrigArg, unsigned OriginalIndex,
SmallVectorImpl<ArgInfo> &SplitArgs, SmallVectorImpl<ArgInfo> &SplitArgs,

View File

@ -50,6 +50,7 @@ using namespace llvm;
X86CallLowering::X86CallLowering(const X86TargetLowering &TLI) X86CallLowering::X86CallLowering(const X86TargetLowering &TLI)
: CallLowering(&TLI) {} : CallLowering(&TLI) {}
// FIXME: This should be removed and the generic version used
bool X86CallLowering::splitToValueTypes(const ArgInfo &OrigArg, bool X86CallLowering::splitToValueTypes(const ArgInfo &OrigArg,
SmallVectorImpl<ArgInfo> &SplitArgs, SmallVectorImpl<ArgInfo> &SplitArgs,
const DataLayout &DL, const DataLayout &DL,