1
0
mirror of https://github.com/RPCS3/llvm-mirror.git synced 2024-10-18 10:32:48 +02:00

[GlobalISel] Base implementation for sret demotion.

If the return values can't be lowered to registers
SelectionDAG performs the sret demotion. This patch
contains the basic implementation for the same in
the GlobalISel pipeline.

Furthermore, targets should bring relevant changes
during lowerFormalArguments, lowerReturn and
lowerCall to make use of this feature.

Reviewed By: arsenm

Differential Revision: https://reviews.llvm.org/D92953
This commit is contained in:
Christudasan Devadasan 2020-12-23 12:22:36 +05:30
parent a3c9c60e8f
commit f0d6cc1d99
18 changed files with 330 additions and 62 deletions

View File

@ -19,6 +19,7 @@
#include "llvm/CodeGen/CallingConvLower.h" #include "llvm/CodeGen/CallingConvLower.h"
#include "llvm/CodeGen/MachineOperand.h" #include "llvm/CodeGen/MachineOperand.h"
#include "llvm/CodeGen/TargetCallingConv.h" #include "llvm/CodeGen/TargetCallingConv.h"
#include "llvm/IR/Attributes.h"
#include "llvm/IR/CallingConv.h" #include "llvm/IR/CallingConv.h"
#include "llvm/IR/Type.h" #include "llvm/IR/Type.h"
#include "llvm/Support/ErrorHandling.h" #include "llvm/Support/ErrorHandling.h"
@ -31,6 +32,7 @@ namespace llvm {
class CallBase; class CallBase;
class DataLayout; class DataLayout;
class Function; class Function;
class FunctionLoweringInfo;
class MachineIRBuilder; class MachineIRBuilder;
struct MachinePointerInfo; struct MachinePointerInfo;
class MachineRegisterInfo; class MachineRegisterInfo;
@ -42,21 +44,30 @@ class CallLowering {
virtual void anchor(); virtual void anchor();
public: public:
struct ArgInfo { struct BaseArgInfo {
Type *Ty;
SmallVector<ISD::ArgFlagsTy, 4> Flags;
bool IsFixed;
BaseArgInfo(Type *Ty,
ArrayRef<ISD::ArgFlagsTy> Flags = ArrayRef<ISD::ArgFlagsTy>(),
bool IsFixed = true)
: Ty(Ty), Flags(Flags.begin(), Flags.end()), IsFixed(IsFixed) {}
BaseArgInfo() : Ty(nullptr), IsFixed(false) {}
};
struct ArgInfo : public BaseArgInfo {
SmallVector<Register, 4> Regs; SmallVector<Register, 4> Regs;
// If the argument had to be split into multiple parts according to the // If the argument had to be split into multiple parts according to the
// target calling convention, then this contains the original vregs // target calling convention, then this contains the original vregs
// if the argument was an incoming arg. // if the argument was an incoming arg.
SmallVector<Register, 2> OrigRegs; SmallVector<Register, 2> OrigRegs;
Type *Ty;
SmallVector<ISD::ArgFlagsTy, 4> Flags;
bool IsFixed;
ArgInfo(ArrayRef<Register> Regs, Type *Ty, ArgInfo(ArrayRef<Register> Regs, Type *Ty,
ArrayRef<ISD::ArgFlagsTy> Flags = ArrayRef<ISD::ArgFlagsTy>(), ArrayRef<ISD::ArgFlagsTy> Flags = ArrayRef<ISD::ArgFlagsTy>(),
bool IsFixed = true) bool IsFixed = true)
: Regs(Regs.begin(), Regs.end()), Ty(Ty), : BaseArgInfo(Ty, Flags, IsFixed), Regs(Regs.begin(), Regs.end()) {
Flags(Flags.begin(), Flags.end()), IsFixed(IsFixed) {
if (!Regs.empty() && Flags.empty()) if (!Regs.empty() && Flags.empty())
this->Flags.push_back(ISD::ArgFlagsTy()); this->Flags.push_back(ISD::ArgFlagsTy());
// FIXME: We should have just one way of saying "no register". // FIXME: We should have just one way of saying "no register".
@ -65,7 +76,7 @@ public:
"only void types should have no register"); "only void types should have no register");
} }
ArgInfo() : Ty(nullptr), IsFixed(false) {} ArgInfo() : BaseArgInfo() {}
}; };
struct CallLoweringInfo { struct CallLoweringInfo {
@ -101,6 +112,15 @@ public:
/// True if the call is to a vararg function. /// True if the call is to a vararg function.
bool IsVarArg = false; bool IsVarArg = false;
/// True if the function's return value can be lowered to registers.
bool CanLowerReturn = true;
/// VReg to hold the hidden sret parameter.
Register DemoteRegister;
/// The stack index for sret demotion.
int DemoteStackIndex;
}; };
/// Argument handling is mostly uniform between the four places that /// Argument handling is mostly uniform between the four places that
@ -292,20 +312,73 @@ public:
return false; return false;
} }
/// Load the returned value from the stack into virtual registers in \p VRegs.
/// It uses the frame index \p FI and the start offset from \p DemoteReg.
/// The loaded data size will be determined from \p RetTy.
void insertSRetLoads(MachineIRBuilder &MIRBuilder, Type *RetTy,
ArrayRef<Register> VRegs, Register DemoteReg,
int FI) const;
/// Store the return value given by \p VRegs into stack starting at the offset
/// specified in \p DemoteReg.
void insertSRetStores(MachineIRBuilder &MIRBuilder, Type *RetTy,
ArrayRef<Register> VRegs, Register DemoteReg) const;
/// Insert the hidden sret ArgInfo to the beginning of \p SplitArgs.
/// This function should be called from the target specific
/// lowerFormalArguments when \p F requires the sret demotion.
void insertSRetIncomingArgument(const Function &F,
SmallVectorImpl<ArgInfo> &SplitArgs,
Register &DemoteReg, MachineRegisterInfo &MRI,
const DataLayout &DL) const;
/// For the call-base described by \p CB, insert the hidden sret ArgInfo to
/// the OrigArgs field of \p Info.
void insertSRetOutgoingArgument(MachineIRBuilder &MIRBuilder,
const CallBase &CB,
CallLoweringInfo &Info) const;
/// \return True if the return type described by \p Outs can be returned
/// without performing sret demotion.
bool checkReturn(CCState &CCInfo, SmallVectorImpl<BaseArgInfo> &Outs,
CCAssignFn *Fn) const;
/// Get the type and the ArgFlags for the split components of \p RetTy as
/// returned by \c ComputeValueVTs.
void getReturnInfo(CallingConv::ID CallConv, Type *RetTy, AttributeList Attrs,
SmallVectorImpl<BaseArgInfo> &Outs,
const DataLayout &DL) const;
/// Toplevel function to check the return type based on the target calling
/// convention. \return True if the return value of \p MF can be returned
/// without performing sret demotion.
bool checkReturnTypeForCallConv(MachineFunction &MF) const;
/// This hook must be implemented to check whether the return values
/// described by \p Outs can fit into the return registers. If false
/// is returned, an sret-demotion is performed.
virtual bool canLowerReturn(MachineFunction &MF, CallingConv::ID CallConv,
SmallVectorImpl<BaseArgInfo> &Outs, bool IsVarArg,
LLVMContext &Context) const {
return true;
}
/// This hook must be implemented to lower outgoing return values, described /// This hook must be implemented to lower outgoing return values, described
/// by \p Val, into the specified virtual registers \p VRegs. /// by \p Val, into the specified virtual registers \p VRegs.
/// This hook is used by GlobalISel. /// This hook is used by GlobalISel.
/// ///
/// \p FLI is required for sret demotion.
///
/// \p SwiftErrorVReg is non-zero if the function has a swifterror parameter /// \p SwiftErrorVReg is non-zero if the function has a swifterror parameter
/// that needs to be implicitly returned. /// that needs to be implicitly returned.
/// ///
/// \return True if the lowering succeeds, false otherwise. /// \return True if the lowering succeeds, false otherwise.
virtual bool lowerReturn(MachineIRBuilder &MIRBuilder, const Value *Val, virtual bool lowerReturn(MachineIRBuilder &MIRBuilder, const Value *Val,
ArrayRef<Register> VRegs, ArrayRef<Register> VRegs, FunctionLoweringInfo &FLI,
Register SwiftErrorVReg) const { Register SwiftErrorVReg) const {
if (!supportSwiftError()) { if (!supportSwiftError()) {
assert(SwiftErrorVReg == 0 && "attempt to use unsupported swifterror"); assert(SwiftErrorVReg == 0 && "attempt to use unsupported swifterror");
return lowerReturn(MIRBuilder, Val, VRegs); return lowerReturn(MIRBuilder, Val, VRegs, FLI);
} }
return false; return false;
} }
@ -313,7 +386,8 @@ public:
/// This hook behaves as the extended lowerReturn function, but for targets /// This hook behaves as the extended lowerReturn function, but for targets
/// that do not support swifterror value promotion. /// that do not support swifterror value promotion.
virtual bool lowerReturn(MachineIRBuilder &MIRBuilder, const Value *Val, virtual bool lowerReturn(MachineIRBuilder &MIRBuilder, const Value *Val,
ArrayRef<Register> VRegs) const { ArrayRef<Register> VRegs,
FunctionLoweringInfo &FLI) const {
return false; return false;
} }
@ -326,12 +400,13 @@ public:
/// the second in \c VRegs[1], and so on. For each argument, there will be one /// the second in \c VRegs[1], and so on. For each argument, there will be one
/// register for each non-aggregate type, as returned by \c computeValueLLTs. /// register for each non-aggregate type, as returned by \c computeValueLLTs.
/// \p MIRBuilder is set to the proper insertion for the argument /// \p MIRBuilder is set to the proper insertion for the argument
/// lowering. /// lowering. \p FLI is required for sret demotion.
/// ///
/// \return True if the lowering succeeded, false otherwise. /// \return True if the lowering succeeded, false otherwise.
virtual bool lowerFormalArguments(MachineIRBuilder &MIRBuilder, virtual bool lowerFormalArguments(MachineIRBuilder &MIRBuilder,
const Function &F, const Function &F,
ArrayRef<ArrayRef<Register>> VRegs) const { ArrayRef<ArrayRef<Register>> VRegs,
FunctionLoweringInfo &FLI) const {
return false; return false;
} }

View File

@ -89,6 +89,24 @@ bool CallLowering::lowerCall(MachineIRBuilder &MIRBuilder, const CallBase &CB,
.getFnAttribute("disable-tail-calls") .getFnAttribute("disable-tail-calls")
.getValueAsString() != "true"); .getValueAsString() != "true");
CallingConv::ID CallConv = CB.getCallingConv();
Type *RetTy = CB.getType();
bool IsVarArg = CB.getFunctionType()->isVarArg();
SmallVector<BaseArgInfo, 4> SplitArgs;
getReturnInfo(CallConv, RetTy, CB.getAttributes(), SplitArgs, DL);
Info.CanLowerReturn =
canLowerReturn(MF, CallConv, SplitArgs, IsVarArg, RetTy->getContext());
if (!Info.CanLowerReturn) {
// Callee requires sret demotion.
insertSRetOutgoingArgument(MIRBuilder, CB, Info);
// The sret demotion isn't compatible with tail-calls, since the sret
// argument points into the caller's stack frame.
CanBeTailCalled = false;
}
// First step is to marshall all the function's parameters into the correct // First step is to marshall all the function's parameters into the correct
// physregs and memory locations. Gather the sequence of argument types that // physregs and memory locations. Gather the sequence of argument types that
// we'll pass to the assigner function. // we'll pass to the assigner function.
@ -116,16 +134,16 @@ bool CallLowering::lowerCall(MachineIRBuilder &MIRBuilder, const CallBase &CB,
else else
Info.Callee = MachineOperand::CreateReg(GetCalleeReg(), false); Info.Callee = MachineOperand::CreateReg(GetCalleeReg(), false);
Info.OrigRet = ArgInfo{ResRegs, CB.getType(), ISD::ArgFlagsTy{}}; Info.OrigRet = ArgInfo{ResRegs, RetTy, ISD::ArgFlagsTy{}};
if (!Info.OrigRet.Ty->isVoidTy()) if (!Info.OrigRet.Ty->isVoidTy())
setArgFlags(Info.OrigRet, AttributeList::ReturnIndex, DL, CB); setArgFlags(Info.OrigRet, AttributeList::ReturnIndex, DL, CB);
Info.KnownCallees = CB.getMetadata(LLVMContext::MD_callees); Info.KnownCallees = CB.getMetadata(LLVMContext::MD_callees);
Info.CallConv = CB.getCallingConv(); Info.CallConv = CallConv;
Info.SwiftErrorVReg = SwiftErrorVReg; Info.SwiftErrorVReg = SwiftErrorVReg;
Info.IsMustTailCall = CB.isMustTailCall(); Info.IsMustTailCall = CB.isMustTailCall();
Info.IsTailCall = CanBeTailCalled; Info.IsTailCall = CanBeTailCalled;
Info.IsVarArg = CB.getFunctionType()->isVarArg(); Info.IsVarArg = IsVarArg;
return lowerCall(MIRBuilder, Info); return lowerCall(MIRBuilder, Info);
} }
@ -429,6 +447,155 @@ bool CallLowering::handleAssignments(CCState &CCInfo,
return true; return true;
} }
void CallLowering::insertSRetLoads(MachineIRBuilder &MIRBuilder, Type *RetTy,
ArrayRef<Register> VRegs, Register DemoteReg,
int FI) const {
MachineFunction &MF = MIRBuilder.getMF();
MachineRegisterInfo &MRI = MF.getRegInfo();
const DataLayout &DL = MF.getDataLayout();
SmallVector<EVT, 4> SplitVTs;
SmallVector<uint64_t, 4> Offsets;
ComputeValueVTs(*TLI, DL, RetTy, SplitVTs, &Offsets, 0);
assert(VRegs.size() == SplitVTs.size());
unsigned NumValues = SplitVTs.size();
Align BaseAlign = DL.getPrefTypeAlign(RetTy);
Type *RetPtrTy = RetTy->getPointerTo(DL.getAllocaAddrSpace());
LLT OffsetLLTy = getLLTForType(*DL.getIntPtrType(RetPtrTy), DL);
MachinePointerInfo PtrInfo = MachinePointerInfo::getFixedStack(MF, FI);
for (unsigned I = 0; I < NumValues; ++I) {
Register Addr;
MIRBuilder.materializePtrAdd(Addr, DemoteReg, OffsetLLTy, Offsets[I]);
auto *MMO = MF.getMachineMemOperand(PtrInfo, MachineMemOperand::MOLoad,
MRI.getType(VRegs[I]).getSizeInBytes(),
commonAlignment(BaseAlign, Offsets[I]));
MIRBuilder.buildLoad(VRegs[I], Addr, *MMO);
}
}
void CallLowering::insertSRetStores(MachineIRBuilder &MIRBuilder, Type *RetTy,
ArrayRef<Register> VRegs,
Register DemoteReg) const {
MachineFunction &MF = MIRBuilder.getMF();
MachineRegisterInfo &MRI = MF.getRegInfo();
const DataLayout &DL = MF.getDataLayout();
SmallVector<EVT, 4> SplitVTs;
SmallVector<uint64_t, 4> Offsets;
ComputeValueVTs(*TLI, DL, RetTy, SplitVTs, &Offsets, 0);
assert(VRegs.size() == SplitVTs.size());
unsigned NumValues = SplitVTs.size();
Align BaseAlign = DL.getPrefTypeAlign(RetTy);
unsigned AS = DL.getAllocaAddrSpace();
LLT OffsetLLTy =
getLLTForType(*DL.getIntPtrType(RetTy->getPointerTo(AS)), DL);
MachinePointerInfo PtrInfo(AS);
for (unsigned I = 0; I < NumValues; ++I) {
Register Addr;
MIRBuilder.materializePtrAdd(Addr, DemoteReg, OffsetLLTy, Offsets[I]);
auto *MMO = MF.getMachineMemOperand(PtrInfo, MachineMemOperand::MOStore,
MRI.getType(VRegs[I]).getSizeInBytes(),
commonAlignment(BaseAlign, Offsets[I]));
MIRBuilder.buildStore(VRegs[I], Addr, *MMO);
}
}
void CallLowering::insertSRetIncomingArgument(
const Function &F, SmallVectorImpl<ArgInfo> &SplitArgs, Register &DemoteReg,
MachineRegisterInfo &MRI, const DataLayout &DL) const {
unsigned AS = DL.getAllocaAddrSpace();
DemoteReg = MRI.createGenericVirtualRegister(
LLT::pointer(AS, DL.getPointerSizeInBits(AS)));
Type *PtrTy = PointerType::get(F.getReturnType(), AS);
SmallVector<EVT, 1> ValueVTs;
ComputeValueVTs(*TLI, DL, PtrTy, ValueVTs);
// NOTE: Assume that a pointer won't get split into more than one VT.
assert(ValueVTs.size() == 1);
ArgInfo DemoteArg(DemoteReg, ValueVTs[0].getTypeForEVT(PtrTy->getContext()));
setArgFlags(DemoteArg, AttributeList::ReturnIndex, DL, F);
DemoteArg.Flags[0].setSRet();
SplitArgs.insert(SplitArgs.begin(), DemoteArg);
}
void CallLowering::insertSRetOutgoingArgument(MachineIRBuilder &MIRBuilder,
const CallBase &CB,
CallLoweringInfo &Info) const {
const DataLayout &DL = MIRBuilder.getDataLayout();
Type *RetTy = CB.getType();
unsigned AS = DL.getAllocaAddrSpace();
LLT FramePtrTy = LLT::pointer(AS, DL.getPointerSizeInBits(AS));
int FI = MIRBuilder.getMF().getFrameInfo().CreateStackObject(
DL.getTypeAllocSize(RetTy), DL.getPrefTypeAlign(RetTy), false);
Register DemoteReg = MIRBuilder.buildFrameIndex(FramePtrTy, FI).getReg(0);
ArgInfo DemoteArg(DemoteReg, PointerType::get(RetTy, AS));
setArgFlags(DemoteArg, AttributeList::ReturnIndex, DL, CB);
DemoteArg.Flags[0].setSRet();
Info.OrigArgs.insert(Info.OrigArgs.begin(), DemoteArg);
Info.DemoteStackIndex = FI;
Info.DemoteRegister = DemoteReg;
}
bool CallLowering::checkReturn(CCState &CCInfo,
SmallVectorImpl<BaseArgInfo> &Outs,
CCAssignFn *Fn) const {
for (unsigned I = 0, E = Outs.size(); I < E; ++I) {
MVT VT = MVT::getVT(Outs[I].Ty);
if (Fn(I, VT, VT, CCValAssign::Full, Outs[I].Flags[0], CCInfo))
return false;
}
return true;
}
void CallLowering::getReturnInfo(CallingConv::ID CallConv, Type *RetTy,
AttributeList Attrs,
SmallVectorImpl<BaseArgInfo> &Outs,
const DataLayout &DL) const {
LLVMContext &Context = RetTy->getContext();
ISD::ArgFlagsTy Flags = ISD::ArgFlagsTy();
SmallVector<EVT, 4> SplitVTs;
ComputeValueVTs(*TLI, DL, RetTy, SplitVTs);
addArgFlagsFromAttributes(Flags, Attrs, AttributeList::ReturnIndex);
for (EVT VT : SplitVTs) {
unsigned NumParts =
TLI->getNumRegistersForCallingConv(Context, CallConv, VT);
MVT RegVT = TLI->getRegisterTypeForCallingConv(Context, CallConv, VT);
Type *PartTy = EVT(RegVT).getTypeForEVT(Context);
for (unsigned I = 0; I < NumParts; ++I) {
Outs.emplace_back(PartTy, Flags);
}
}
}
bool CallLowering::checkReturnTypeForCallConv(MachineFunction &MF) const {
const auto &F = MF.getFunction();
Type *ReturnType = F.getReturnType();
CallingConv::ID CallConv = F.getCallingConv();
SmallVector<BaseArgInfo, 4> SplitArgs;
getReturnInfo(CallConv, ReturnType, F.getAttributes(), SplitArgs,
MF.getDataLayout());
return canLowerReturn(MF, CallConv, SplitArgs, F.isVarArg(),
ReturnType->getContext());
}
bool CallLowering::analyzeArgInfo(CCState &CCState, bool CallLowering::analyzeArgInfo(CCState &CCState,
SmallVectorImpl<ArgInfo> &Args, SmallVectorImpl<ArgInfo> &Args,
CCAssignFn &AssignFnFixed, CCAssignFn &AssignFnFixed,

View File

@ -368,7 +368,7 @@ bool IRTranslator::translateRet(const User &U, MachineIRBuilder &MIRBuilder) {
// The target may mess up with the insertion point, but // The target may mess up with the insertion point, but
// this is not important as a return is the last instruction // this is not important as a return is the last instruction
// of the block anyway. // of the block anyway.
return CLI->lowerReturn(MIRBuilder, Ret, VRegs, SwiftErrorVReg); return CLI->lowerReturn(MIRBuilder, Ret, VRegs, FuncInfo, SwiftErrorVReg);
} }
void IRTranslator::emitBranchForMergedCondition( void IRTranslator::emitBranchForMergedCondition(
@ -3067,6 +3067,8 @@ bool IRTranslator::runOnMachineFunction(MachineFunction &CurMF) {
else else
FuncInfo.BPI = nullptr; FuncInfo.BPI = nullptr;
FuncInfo.CanLowerReturn = CLI->checkReturnTypeForCallConv(*MF);
const auto &TLI = *MF->getSubtarget().getTargetLowering(); const auto &TLI = *MF->getSubtarget().getTargetLowering();
SL = std::make_unique<GISelSwitchLowering>(this, FuncInfo); SL = std::make_unique<GISelSwitchLowering>(this, FuncInfo);
@ -3140,7 +3142,7 @@ bool IRTranslator::runOnMachineFunction(MachineFunction &CurMF) {
} }
} }
if (!CLI->lowerFormalArguments(*EntryBuilder.get(), F, VRegArgs)) { if (!CLI->lowerFormalArguments(*EntryBuilder.get(), F, VRegArgs, FuncInfo)) {
OptimizationRemarkMissed R("gisel-irtranslator", "GISelFailure", OptimizationRemarkMissed R("gisel-irtranslator", "GISelFailure",
F.getSubprogram(), &F.getEntryBlock()); F.getSubprogram(), &F.getEntryBlock());
R << "unable to lower arguments: " << ore::NV("Prototype", F.getType()); R << "unable to lower arguments: " << ore::NV("Prototype", F.getType());

View File

@ -274,6 +274,7 @@ void AArch64CallLowering::splitToValueTypes(
bool AArch64CallLowering::lowerReturn(MachineIRBuilder &MIRBuilder, bool AArch64CallLowering::lowerReturn(MachineIRBuilder &MIRBuilder,
const Value *Val, const Value *Val,
ArrayRef<Register> VRegs, ArrayRef<Register> VRegs,
FunctionLoweringInfo &FLI,
Register SwiftErrorVReg) const { Register SwiftErrorVReg) const {
auto MIB = MIRBuilder.buildInstrNoInsert(AArch64::RET_ReallyLR); auto MIB = MIRBuilder.buildInstrNoInsert(AArch64::RET_ReallyLR);
assert(((Val && !VRegs.empty()) || (!Val && VRegs.empty())) && assert(((Val && !VRegs.empty()) || (!Val && VRegs.empty())) &&
@ -440,7 +441,7 @@ bool AArch64CallLowering::fallBackToDAGISel(const Function &F) const {
bool AArch64CallLowering::lowerFormalArguments( bool AArch64CallLowering::lowerFormalArguments(
MachineIRBuilder &MIRBuilder, const Function &F, MachineIRBuilder &MIRBuilder, const Function &F,
ArrayRef<ArrayRef<Register>> VRegs) const { ArrayRef<ArrayRef<Register>> VRegs, FunctionLoweringInfo &FLI) const {
MachineFunction &MF = MIRBuilder.getMF(); MachineFunction &MF = MIRBuilder.getMF();
MachineBasicBlock &MBB = MIRBuilder.getMBB(); MachineBasicBlock &MBB = MIRBuilder.getMBB();
MachineRegisterInfo &MRI = MF.getRegInfo(); MachineRegisterInfo &MRI = MF.getRegInfo();

View File

@ -34,13 +34,14 @@ public:
AArch64CallLowering(const AArch64TargetLowering &TLI); AArch64CallLowering(const AArch64TargetLowering &TLI);
bool lowerReturn(MachineIRBuilder &MIRBuilder, const Value *Val, bool lowerReturn(MachineIRBuilder &MIRBuilder, const Value *Val,
ArrayRef<Register> VRegs, ArrayRef<Register> VRegs, FunctionLoweringInfo &FLI,
Register SwiftErrorVReg) const override; Register SwiftErrorVReg) const override;
bool fallBackToDAGISel(const Function &F) const override; bool fallBackToDAGISel(const Function &F) const override;
bool lowerFormalArguments(MachineIRBuilder &MIRBuilder, const Function &F, bool lowerFormalArguments(MachineIRBuilder &MIRBuilder, const Function &F,
ArrayRef<ArrayRef<Register>> VRegs) const override; ArrayRef<ArrayRef<Register>> VRegs,
FunctionLoweringInfo &FLI) const override;
bool lowerCall(MachineIRBuilder &MIRBuilder, bool lowerCall(MachineIRBuilder &MIRBuilder,
CallLoweringInfo &Info) const override; CallLoweringInfo &Info) const override;

View File

@ -447,9 +447,9 @@ bool AMDGPUCallLowering::lowerReturnVal(MachineIRBuilder &B,
return handleAssignments(B, SplitRetInfos, RetHandler); return handleAssignments(B, SplitRetInfos, RetHandler);
} }
bool AMDGPUCallLowering::lowerReturn(MachineIRBuilder &B, bool AMDGPUCallLowering::lowerReturn(MachineIRBuilder &B, const Value *Val,
const Value *Val, ArrayRef<Register> VRegs,
ArrayRef<Register> VRegs) const { FunctionLoweringInfo &FLI) const {
MachineFunction &MF = B.getMF(); MachineFunction &MF = B.getMF();
MachineRegisterInfo &MRI = MF.getRegInfo(); MachineRegisterInfo &MRI = MF.getRegInfo();
@ -775,8 +775,8 @@ static void packSplitRegsToOrigType(MachineIRBuilder &B,
} }
bool AMDGPUCallLowering::lowerFormalArguments( bool AMDGPUCallLowering::lowerFormalArguments(
MachineIRBuilder &B, const Function &F, MachineIRBuilder &B, const Function &F, ArrayRef<ArrayRef<Register>> VRegs,
ArrayRef<ArrayRef<Register>> VRegs) const { FunctionLoweringInfo &FLI) const {
CallingConv::ID CC = F.getCallingConv(); CallingConv::ID CC = F.getCallingConv();
// The infrastructure for normal calling convention lowering is essentially // The infrastructure for normal calling convention lowering is essentially

View File

@ -47,13 +47,15 @@ public:
AMDGPUCallLowering(const AMDGPUTargetLowering &TLI); AMDGPUCallLowering(const AMDGPUTargetLowering &TLI);
bool lowerReturn(MachineIRBuilder &B, const Value *Val, bool lowerReturn(MachineIRBuilder &B, const Value *Val,
ArrayRef<Register> VRegs) const override; ArrayRef<Register> VRegs,
FunctionLoweringInfo &FLI) const override;
bool lowerFormalArgumentsKernel(MachineIRBuilder &B, const Function &F, bool lowerFormalArgumentsKernel(MachineIRBuilder &B, const Function &F,
ArrayRef<ArrayRef<Register>> VRegs) const; ArrayRef<ArrayRef<Register>> VRegs) const;
bool lowerFormalArguments(MachineIRBuilder &B, const Function &F, bool lowerFormalArguments(MachineIRBuilder &B, const Function &F,
ArrayRef<ArrayRef<Register>> VRegs) const override; ArrayRef<ArrayRef<Register>> VRegs,
FunctionLoweringInfo &FLI) const override;
bool passSpecialInputs(MachineIRBuilder &MIRBuilder, bool passSpecialInputs(MachineIRBuilder &MIRBuilder,
CCState &CCInfo, CCState &CCInfo,

View File

@ -263,8 +263,8 @@ bool ARMCallLowering::lowerReturnVal(MachineIRBuilder &MIRBuilder,
} }
bool ARMCallLowering::lowerReturn(MachineIRBuilder &MIRBuilder, bool ARMCallLowering::lowerReturn(MachineIRBuilder &MIRBuilder,
const Value *Val, const Value *Val, ArrayRef<Register> VRegs,
ArrayRef<Register> VRegs) const { FunctionLoweringInfo &FLI) const {
assert(!Val == VRegs.empty() && "Return value without a vreg"); assert(!Val == VRegs.empty() && "Return value without a vreg");
auto const &ST = MIRBuilder.getMF().getSubtarget<ARMSubtarget>(); auto const &ST = MIRBuilder.getMF().getSubtarget<ARMSubtarget>();
@ -410,9 +410,10 @@ struct FormalArgHandler : public ARMIncomingValueHandler {
} // end anonymous namespace } // end anonymous namespace
bool ARMCallLowering::lowerFormalArguments( bool ARMCallLowering::lowerFormalArguments(MachineIRBuilder &MIRBuilder,
MachineIRBuilder &MIRBuilder, const Function &F, const Function &F,
ArrayRef<ArrayRef<Register>> VRegs) const { ArrayRef<ArrayRef<Register>> VRegs,
FunctionLoweringInfo &FLI) const {
auto &TLI = *getTLI<ARMTargetLowering>(); auto &TLI = *getTLI<ARMTargetLowering>();
auto Subtarget = TLI.getSubtarget(); auto Subtarget = TLI.getSubtarget();

View File

@ -33,10 +33,12 @@ public:
ARMCallLowering(const ARMTargetLowering &TLI); ARMCallLowering(const ARMTargetLowering &TLI);
bool lowerReturn(MachineIRBuilder &MIRBuilder, const Value *Val, bool lowerReturn(MachineIRBuilder &MIRBuilder, const Value *Val,
ArrayRef<Register> VRegs) const override; ArrayRef<Register> VRegs,
FunctionLoweringInfo &FLI) const override;
bool lowerFormalArguments(MachineIRBuilder &MIRBuilder, const Function &F, bool lowerFormalArguments(MachineIRBuilder &MIRBuilder, const Function &F,
ArrayRef<ArrayRef<Register>> VRegs) const override; ArrayRef<ArrayRef<Register>> VRegs,
FunctionLoweringInfo &FLI) const override;
bool lowerCall(MachineIRBuilder &MIRBuilder, bool lowerCall(MachineIRBuilder &MIRBuilder,
CallLoweringInfo &Info) const override; CallLoweringInfo &Info) const override;

View File

@ -374,8 +374,8 @@ static void setLocInfo(SmallVectorImpl<CCValAssign> &ArgLocs,
} }
bool MipsCallLowering::lowerReturn(MachineIRBuilder &MIRBuilder, bool MipsCallLowering::lowerReturn(MachineIRBuilder &MIRBuilder,
const Value *Val, const Value *Val, ArrayRef<Register> VRegs,
ArrayRef<Register> VRegs) const { FunctionLoweringInfo &FLI) const {
MachineInstrBuilder Ret = MIRBuilder.buildInstrNoInsert(Mips::RetRA); MachineInstrBuilder Ret = MIRBuilder.buildInstrNoInsert(Mips::RetRA);
@ -413,9 +413,10 @@ bool MipsCallLowering::lowerReturn(MachineIRBuilder &MIRBuilder,
return true; return true;
} }
bool MipsCallLowering::lowerFormalArguments( bool MipsCallLowering::lowerFormalArguments(MachineIRBuilder &MIRBuilder,
MachineIRBuilder &MIRBuilder, const Function &F, const Function &F,
ArrayRef<ArrayRef<Register>> VRegs) const { ArrayRef<ArrayRef<Register>> VRegs,
FunctionLoweringInfo &FLI) const {
// Quick exit if there aren't any args. // Quick exit if there aren't any args.
if (F.arg_empty()) if (F.arg_empty())

View File

@ -64,10 +64,12 @@ public:
MipsCallLowering(const MipsTargetLowering &TLI); MipsCallLowering(const MipsTargetLowering &TLI);
bool lowerReturn(MachineIRBuilder &MIRBuilder, const Value *Val, bool lowerReturn(MachineIRBuilder &MIRBuilder, const Value *Val,
ArrayRef<Register> VRegs) const override; ArrayRef<Register> VRegs,
FunctionLoweringInfo &FLI) const override;
bool lowerFormalArguments(MachineIRBuilder &MIRBuilder, const Function &F, bool lowerFormalArguments(MachineIRBuilder &MIRBuilder, const Function &F,
ArrayRef<ArrayRef<Register>> VRegs) const override; ArrayRef<ArrayRef<Register>> VRegs,
FunctionLoweringInfo &FLI) const override;
bool lowerCall(MachineIRBuilder &MIRBuilder, bool lowerCall(MachineIRBuilder &MIRBuilder,
CallLoweringInfo &Info) const override; CallLoweringInfo &Info) const override;

View File

@ -25,6 +25,7 @@ PPCCallLowering::PPCCallLowering(const PPCTargetLowering &TLI)
bool PPCCallLowering::lowerReturn(MachineIRBuilder &MIRBuilder, bool PPCCallLowering::lowerReturn(MachineIRBuilder &MIRBuilder,
const Value *Val, ArrayRef<Register> VRegs, const Value *Val, ArrayRef<Register> VRegs,
FunctionLoweringInfo &FLI,
Register SwiftErrorVReg) const { Register SwiftErrorVReg) const {
assert(((Val && !VRegs.empty()) || (!Val && VRegs.empty())) && assert(((Val && !VRegs.empty()) || (!Val && VRegs.empty())) &&
"Return value without a vreg"); "Return value without a vreg");
@ -35,9 +36,10 @@ bool PPCCallLowering::lowerReturn(MachineIRBuilder &MIRBuilder,
return true; return true;
} }
bool PPCCallLowering::lowerFormalArguments( bool PPCCallLowering::lowerFormalArguments(MachineIRBuilder &MIRBuilder,
MachineIRBuilder &MIRBuilder, const Function &F, const Function &F,
ArrayRef<ArrayRef<Register>> VRegs) const { ArrayRef<ArrayRef<Register>> VRegs,
FunctionLoweringInfo &FLI) const {
// If VRegs is empty, then there are no formal arguments to lower and thus can // If VRegs is empty, then there are no formal arguments to lower and thus can
// always return true. If there are formal arguments, we currently do not // always return true. If there are formal arguments, we currently do not

View File

@ -27,10 +27,11 @@ public:
PPCCallLowering(const PPCTargetLowering &TLI); PPCCallLowering(const PPCTargetLowering &TLI);
bool lowerReturn(MachineIRBuilder &MIRBuilder, const Value *Val, bool lowerReturn(MachineIRBuilder &MIRBuilder, const Value *Val,
ArrayRef<Register> VRegs, ArrayRef<Register> VRegs, FunctionLoweringInfo &FLI,
Register SwiftErrorVReg) const override; Register SwiftErrorVReg) const override;
bool lowerFormalArguments(MachineIRBuilder &MIRBuilder, const Function &F, bool lowerFormalArguments(MachineIRBuilder &MIRBuilder, const Function &F,
ArrayRef<ArrayRef<Register>> VRegs) const override; ArrayRef<ArrayRef<Register>> VRegs,
FunctionLoweringInfo &FLI) const override;
bool lowerCall(MachineIRBuilder &MIRBuilder, bool lowerCall(MachineIRBuilder &MIRBuilder,
CallLoweringInfo &Info) const override; CallLoweringInfo &Info) const override;
}; };

View File

@ -22,8 +22,8 @@ RISCVCallLowering::RISCVCallLowering(const RISCVTargetLowering &TLI)
: CallLowering(&TLI) {} : CallLowering(&TLI) {}
bool RISCVCallLowering::lowerReturn(MachineIRBuilder &MIRBuilder, bool RISCVCallLowering::lowerReturn(MachineIRBuilder &MIRBuilder,
const Value *Val, const Value *Val, ArrayRef<Register> VRegs,
ArrayRef<Register> VRegs) const { FunctionLoweringInfo &FLI) const {
MachineInstrBuilder Ret = MIRBuilder.buildInstrNoInsert(RISCV::PseudoRET); MachineInstrBuilder Ret = MIRBuilder.buildInstrNoInsert(RISCV::PseudoRET);
@ -34,9 +34,10 @@ bool RISCVCallLowering::lowerReturn(MachineIRBuilder &MIRBuilder,
return true; return true;
} }
bool RISCVCallLowering::lowerFormalArguments( bool RISCVCallLowering::lowerFormalArguments(MachineIRBuilder &MIRBuilder,
MachineIRBuilder &MIRBuilder, const Function &F, const Function &F,
ArrayRef<ArrayRef<Register>> VRegs) const { ArrayRef<ArrayRef<Register>> VRegs,
FunctionLoweringInfo &FLI) const {
if (F.arg_empty()) if (F.arg_empty())
return true; return true;

View File

@ -28,10 +28,12 @@ public:
RISCVCallLowering(const RISCVTargetLowering &TLI); RISCVCallLowering(const RISCVTargetLowering &TLI);
bool lowerReturn(MachineIRBuilder &MIRBuiler, const Value *Val, bool lowerReturn(MachineIRBuilder &MIRBuiler, const Value *Val,
ArrayRef<Register> VRegs) const override; ArrayRef<Register> VRegs,
FunctionLoweringInfo &FLI) const override;
bool lowerFormalArguments(MachineIRBuilder &MIRBuilder, const Function &F, bool lowerFormalArguments(MachineIRBuilder &MIRBuilder, const Function &F,
ArrayRef<ArrayRef<Register>> VRegs) const override; ArrayRef<ArrayRef<Register>> VRegs,
FunctionLoweringInfo &FLI) const override;
bool lowerCall(MachineIRBuilder &MIRBuilder, bool lowerCall(MachineIRBuilder &MIRBuilder,
CallLoweringInfo &Info) const override; CallLoweringInfo &Info) const override;

View File

@ -184,9 +184,9 @@ protected:
} // end anonymous namespace } // end anonymous namespace
bool X86CallLowering::lowerReturn( bool X86CallLowering::lowerReturn(MachineIRBuilder &MIRBuilder,
MachineIRBuilder &MIRBuilder, const Value *Val, const Value *Val, ArrayRef<Register> VRegs,
ArrayRef<Register> VRegs) const { FunctionLoweringInfo &FLI) const {
assert(((Val && !VRegs.empty()) || (!Val && VRegs.empty())) && assert(((Val && !VRegs.empty()) || (!Val && VRegs.empty())) &&
"Return value without a vreg"); "Return value without a vreg");
auto MIB = MIRBuilder.buildInstrNoInsert(X86::RET).addImm(0); auto MIB = MIRBuilder.buildInstrNoInsert(X86::RET).addImm(0);
@ -322,9 +322,10 @@ protected:
} // end anonymous namespace } // end anonymous namespace
bool X86CallLowering::lowerFormalArguments( bool X86CallLowering::lowerFormalArguments(MachineIRBuilder &MIRBuilder,
MachineIRBuilder &MIRBuilder, const Function &F, const Function &F,
ArrayRef<ArrayRef<Register>> VRegs) const { ArrayRef<ArrayRef<Register>> VRegs,
FunctionLoweringInfo &FLI) const {
if (F.arg_empty()) if (F.arg_empty())
return true; return true;

View File

@ -29,10 +29,12 @@ public:
X86CallLowering(const X86TargetLowering &TLI); X86CallLowering(const X86TargetLowering &TLI);
bool lowerReturn(MachineIRBuilder &MIRBuilder, const Value *Val, bool lowerReturn(MachineIRBuilder &MIRBuilder, const Value *Val,
ArrayRef<Register> VRegs) const override; ArrayRef<Register> VRegs,
FunctionLoweringInfo &FLI) const override;
bool lowerFormalArguments(MachineIRBuilder &MIRBuilder, const Function &F, bool lowerFormalArguments(MachineIRBuilder &MIRBuilder, const Function &F,
ArrayRef<ArrayRef<Register>> VRegs) const override; ArrayRef<ArrayRef<Register>> VRegs,
FunctionLoweringInfo &FLI) const override;
bool lowerCall(MachineIRBuilder &MIRBuilder, bool lowerCall(MachineIRBuilder &MIRBuilder,
CallLoweringInfo &Info) const override; CallLoweringInfo &Info) const override;

View File

@ -11,6 +11,7 @@
#include "SnippetRepetitor.h" #include "SnippetRepetitor.h"
#include "Target.h" #include "Target.h"
#include "llvm/Analysis/TargetLibraryInfo.h" #include "llvm/Analysis/TargetLibraryInfo.h"
#include "llvm/CodeGen/FunctionLoweringInfo.h"
#include "llvm/CodeGen/GlobalISel/CallLowering.h" #include "llvm/CodeGen/GlobalISel/CallLowering.h"
#include "llvm/CodeGen/GlobalISel/MachineIRBuilder.h" #include "llvm/CodeGen/GlobalISel/MachineIRBuilder.h"
#include "llvm/CodeGen/MachineInstrBuilder.h" #include "llvm/CodeGen/MachineInstrBuilder.h"
@ -128,7 +129,11 @@ void BasicBlockFiller::addReturn(const DebugLoc &DL) {
} else { } else {
MachineIRBuilder MIB(MF); MachineIRBuilder MIB(MF);
MIB.setMBB(*MBB); MIB.setMBB(*MBB);
MF.getSubtarget().getCallLowering()->lowerReturn(MIB, nullptr, {});
FunctionLoweringInfo FuncInfo;
FuncInfo.CanLowerReturn = true;
MF.getSubtarget().getCallLowering()->lowerReturn(MIB, nullptr, {},
FuncInfo);
} }
} }