42 return MIRBuilder.
buildInstr(SPIRV::OpReturnValue)
45 *STI.getRegBankInfo());
57 if (
F.hasFnAttribute(Attribute::AttrKind::NoInline))
58 FuncControl |=
static_cast<uint32_t>(SPIRV::FunctionControl::DontInline);
59 else if (
F.hasFnAttribute(Attribute::AttrKind::AlwaysInline))
60 FuncControl |=
static_cast<uint32_t>(SPIRV::FunctionControl::Inline);
63 FuncControl |=
static_cast<uint32_t>(SPIRV::FunctionControl::Pure);
65 FuncControl |=
static_cast<uint32_t>(SPIRV::FunctionControl::Const);
72 auto *CMeta = dyn_cast<ConstantAsMetadata>(MD->
getOperand(NumOp));
74 return dyn_cast<ConstantInt>(CMeta->getValue());
83 auto *NamedMD =
F.getParent()->getNamedMetadata(
"spv.cloned_funcs");
84 if (NamedMD ==
nullptr)
85 return F.getFunctionType();
87 Type *
RetTy =
F.getFunctionType()->getReturnType();
89 for (
auto &Arg :
F.args())
93 std::find_if(NamedMD->op_begin(), NamedMD->op_end(), [&
F](
MDNode *
N) {
94 return isa<MDString>(N->getOperand(0)) &&
95 cast<MDString>(N->getOperand(0))->getString() == F.getName();
99 if (ThisFuncMDIt != NamedMD->op_end()) {
100 auto *ThisFuncMD = *ThisFuncMDIt;
101 MDNode *MD = dyn_cast<MDNode>(ThisFuncMD->getOperand(1));
102 assert(MD &&
"MDNode operand is expected");
105 auto *CMeta = dyn_cast<ConstantAsMetadata>(MD->
getOperand(1));
106 assert(CMeta &&
"ConstantAsMetadata operand is expected");
107 assert(Const->getSExtValue() >= -1);
110 if (Const->getSExtValue() == -1)
111 RetTy = CMeta->getType();
113 ArgTypes[Const->getSExtValue()] = CMeta->getType();
124 "Kernel attributes are attached/belong only to kernel functions");
128 if (
Node && ArgIdx < Node->getNumOperands())
129 return cast<MDString>(
Node->getOperand(ArgIdx));
140 unsigned MDArgIdx = ArgIdx + 1;
150 bool FoundLoweredKernelFunction =
false;
153 if (MaybeValue && dyn_cast<Function>(MaybeValue->
getValue())->getName() ==
155 FoundLoweredKernelFunction =
true;
158 if (MaybeValue && FoundLoweredKernelFunction)
161 MDNode *MaybeNode = dyn_cast<MDNode>(Operand);
162 if (FoundLoweredKernelFunction && MaybeNode &&
163 cast<MDString>(MaybeNode->
getOperand(0))->getString() ==
165 MDArgIdx < MaybeNode->getNumOperands())
166 return cast<MDString>(MaybeNode->
getOperand(MDArgIdx));
171static SPIRV::AccessQualifier::AccessQualifier
174 return SPIRV::AccessQualifier::ReadWrite;
179 return SPIRV::AccessQualifier::ReadWrite;
182 return SPIRV::AccessQualifier::ReadOnly;
184 return SPIRV::AccessQualifier::WriteOnly;
185 return SPIRV::AccessQualifier::ReadWrite;
188static std::vector<SPIRV::Decoration::Decoration>
193 return {SPIRV::Decoration::Volatile};
201 SPIRV::AccessQualifier::AccessQualifier ArgAccessQual =
220 MDKernelArgType->
getString(), MIRBuilder,
225 "opencl." + MDKernelArgType->
getString().
str(), MIRBuilder,
226 SPIRV::StorageClass::Function, ArgAccessQual);
239 if (
F.getFnAttribute(
"hlsl.shader").isValid())
245static SPIRV::ExecutionModel::ExecutionModel
248 return SPIRV::ExecutionModel::Kernel;
250 auto attribute =
F.getFnAttribute(
"hlsl.shader");
251 if (!attribute.isValid()) {
253 "This entry point lacks mandatory hlsl.shader attribute.");
256 const auto value = attribute.getValueAsString();
257 if (
value ==
"compute")
258 return SPIRV::ExecutionModel::GLCompute;
267 assert(GR &&
"Must initialize the SPIRV type registry before lowering args.");
273 if (VRegs.size() > 0) {
275 for (
const auto &Arg :
F.args()) {
278 if (VRegs[i].
size() > 1)
285 buildOpName(VRegs[i][0], Arg.getName(), MIRBuilder);
286 if (Arg.getType()->isPointerTy()) {
287 auto DerefBytes =
static_cast<unsigned>(Arg.getDereferenceableBytes());
290 SPIRV::Decoration::MaxByteOffset, {DerefBytes});
292 if (Arg.hasAttribute(Attribute::Alignment)) {
293 auto Alignment =
static_cast<unsigned>(
294 Arg.getAttribute(Attribute::Alignment).getValueAsInt());
298 if (Arg.hasAttribute(Attribute::ReadOnly)) {
300 static_cast<unsigned>(SPIRV::FunctionParameterAttribute::NoWrite);
302 SPIRV::Decoration::FuncParamAttr, {Attr});
304 if (Arg.hasAttribute(Attribute::ZExt)) {
306 static_cast<unsigned>(SPIRV::FunctionParameterAttribute::Zext);
308 SPIRV::Decoration::FuncParamAttr, {Attr});
310 if (Arg.hasAttribute(Attribute::NoAlias)) {
312 static_cast<unsigned>(SPIRV::FunctionParameterAttribute::NoAlias);
314 SPIRV::Decoration::FuncParamAttr, {Attr});
318 std::vector<SPIRV::Decoration::Decoration> ArgTypeQualDecs =
320 for (SPIRV::Decoration::Decoration Decoration : ArgTypeQualDecs)
324 MDNode *Node =
F.getMetadata(
"spirv.ParameterDecorations");
325 if (Node && i < Node->getNumOperands() &&
326 isa<MDNode>(Node->getOperand(i))) {
327 MDNode *MD = cast<MDNode>(Node->getOperand(i));
329 MDNode *MD2 = dyn_cast<MDNode>(MDOp);
330 assert(MD2 &&
"Metadata operand is expected");
332 assert(Const &&
"MDOperand should be ConstantInt");
334 static_cast<SPIRV::Decoration::Decoration
>(Const->getZExtValue());
335 std::vector<uint32_t> DecVec;
338 assert(Const &&
"MDOperand should be ConstantInt");
339 DecVec.push_back(
static_cast<uint32_t>(Const->getZExtValue()));
351 MRI->setRegClass(FuncVReg, &SPIRV::IDRegClass);
352 if (
F.isDeclaration())
353 GR->
add(&
F, &MIRBuilder.
getMF(), FuncVReg);
356 FTy,
RetTy, ArgTypeVRegs, MIRBuilder);
369 for (
const auto &Arg :
F.args()) {
370 assert(VRegs[i].
size() == 1 &&
"Formal arg has multiple vregs");
371 MRI->setRegClass(VRegs[i][0], &SPIRV::IDRegClass);
372 MIRBuilder.
buildInstr(SPIRV::OpFunctionParameter)
375 if (
F.isDeclaration())
376 GR->
add(&Arg, &MIRBuilder.
getMF(), VRegs[i][0]);
387 auto MIB = MIRBuilder.
buildInstr(SPIRV::OpEntryPoint)
393 auto LnkTy =
F.isDeclaration() ? SPIRV::LinkageType::Import
394 : SPIRV::LinkageType::Export;
395 buildOpDecorate(FuncVReg, MIRBuilder, SPIRV::Decoration::LinkageAttributes,
396 {
static_cast<uint32_t>(LnkTy)},
F.getGlobalIdentifier());
406 if (
Info.OrigRet.Regs.size() > 1)
416 if (
Info.Callee.isGlobal()) {
417 CF = dyn_cast_or_null<const Function>(
Info.Callee.getGlobal());
427 std::string FuncName =
Info.Callee.getGlobal()->getName().str();
432 ST->canUseExtInstSet(SPIRV::InstructionSet::OpenCL_std)) {
433 const Type *OrigRetTy =
Info.OrigRet.Ty;
437 for (
auto Arg :
Info.OrigArgs) {
438 assert(Arg.Regs.size() == 1 &&
"Call arg has multiple VRegs");
444 DemangledName, SPIRV::InstructionSet::OpenCL_std, MIRBuilder,
445 ResVReg, OrigRetTy, ArgVRegs, GR))
453 FirstBlockBuilder.
setMF(MF);
462 MRI->setRegClass(Reg, &SPIRV::IDRegClass);
478 auto MIB = MIRBuilder.
buildInstr(SPIRV::OpFunctionCall)
483 for (
const auto &Arg :
Info.OrigArgs) {
485 if (Arg.Regs.size() > 1)
490 *ST->getRegBankInfo());
unsigned const MachineRegisterInfo * MRI
Analysis containing CSE Info
Given that RA is a live value
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
static ConstantInt * getConstInt(MDNode *MD, unsigned NumOp)
static std::vector< SPIRV::Decoration::Decoration > getKernelArgTypeQual(const Function &KernelFunction, unsigned ArgIdx)
static uint32_t getFunctionControl(const Function &F)
static SPIRV::ExecutionModel::ExecutionModel getExecutionModel(const SPIRVSubtarget &STI, const Function &F)
static FunctionType * getOriginalFunctionType(const Function &F)
static SPIRV::AccessQualifier::AccessQualifier getArgAccessQual(const Function &F, unsigned ArgIdx)
static SPIRVType * getArgSPIRVType(const Function &F, unsigned ArgIdx, SPIRVGlobalRegistry *GR, MachineIRBuilder &MIRBuilder)
static bool isEntryPoint(const Function &F)
static MDString * getKernelArgAttribute(const Function &KernelFunction, unsigned ArgIdx, const StringRef AttributeName)
This class represents an incoming formal argument to a Function.
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...
size_t size() const
size - Get the array size.
This is the shared class of boolean and integer constants.
TypeSize getTypeStoreSize(Type *Ty) const
Returns the maximum number of bytes that may be overwritten by storing the specified type.
FunctionLoweringInfo - This contains information that is global to a function that is used when lower...
Class to represent function types.
Type * getParamType(unsigned i) const
Parameter type accessors.
Type * getReturnType() const
static FunctionType * get(Type *Result, ArrayRef< Type * > Params, bool isVarArg)
This static method is the primary way of constructing a FunctionType.
iterator_range< arg_iterator > args()
CallingConv::ID getCallingConv() const
getCallingConv()/setCallingConv(CC) - These method get and set the calling convention of this functio...
MDNode * getMetadata(unsigned KindID) const
Get the current metadata attachments for the given kind, if any.
bool isDeclaration() const
Return true if the primary definition of this global value is outside of the current translation unit...
Module * getParent()
Get the module that this global value is contained inside of...
@ ExternalLinkage
Externally visible function.
@ LinkOnceODRLinkage
Same, but only replaced by something equivalent.
static constexpr LLT scalar(unsigned SizeInBits)
Get a low-level scalar or aggregate "bag of bits".
const MDOperand & getOperand(unsigned I) const
ArrayRef< MDOperand > operands() const
unsigned getNumOperands() const
Return number of MDNode operands.
Tracking metadata reference owned by Metadata.
StringRef getString() const
const TargetSubtargetInfo & getSubtarget() const
getSubtarget - Return the subtarget for which this machine code is being compiled.
MachineBasicBlock * getBlockNumbered(unsigned N) const
getBlockNumbered - MachineBasicBlocks are automatically numbered when they are inserted into the mach...
Helper class to build MachineInstr.
const TargetInstrInfo & getTII()
MachineInstrBuilder buildInstr(unsigned Opcode)
Build and insert <empty> = Opcode <empty>.
MachineFunction & getMF()
Getter for the function we currently build.
void setMBB(MachineBasicBlock &MBB)
Set the insertion point to the end of MBB.
MachineRegisterInfo * getMRI()
Getter for MRI.
const DataLayout & getDataLayout() const
void setMF(MachineFunction &MF)
const MachineInstrBuilder & addImm(int64_t Val) const
Add a new immediate operand.
const MachineInstrBuilder & add(const MachineOperand &MO) const
bool constrainAllUses(const TargetInstrInfo &TII, const TargetRegisterInfo &TRI, const RegisterBankInfo &RBI) const
const MachineInstrBuilder & addUse(Register RegNo, unsigned Flags=0, unsigned SubReg=0) const
Add a virtual register use operand.
const MachineInstrBuilder & addDef(Register RegNo, unsigned Flags=0, unsigned SubReg=0) const
Add a virtual register definition operand.
Representation of each machine instruction.
MachineRegisterInfo - Keep track of information for virtual and physical registers,...
Register createVirtualRegister(const TargetRegisterClass *RegClass, StringRef Name="")
createVirtualRegister - Create and return a new virtual register in the function with the specified r...
bool doesNotAccessMemory() const
Whether this function accesses no memory.
bool onlyReadsMemory() const
Whether this function only (at most) reads memory.
NamedMDNode * getNamedMetadata(const Twine &Name) const
Return the first NamedMDNode in the module with the specified name.
MDNode * getOperand(unsigned i) const
unsigned getNumOperands() const
Wrapper class representing virtual and physical registers.
constexpr bool isValid() const
bool lowerCall(MachineIRBuilder &MIRBuilder, CallLoweringInfo &Info) const override
This hook must be implemented to lower the given call instruction, including argument and return valu...
bool lowerReturn(MachineIRBuilder &MIRBuiler, const Value *Val, ArrayRef< Register > VRegs, FunctionLoweringInfo &FLI, Register SwiftErrorVReg) const override
This hook must be implemented to lower outgoing return values, described by Val, into the specified v...
SPIRVCallLowering(const SPIRVTargetLowering &TLI, SPIRVGlobalRegistry *GR)
bool lowerFormalArguments(MachineIRBuilder &MIRBuilder, const Function &F, ArrayRef< ArrayRef< Register > > VRegs, FunctionLoweringInfo &FLI) const override
This hook must be implemented to lower the incoming (formal) arguments, described by VRegs,...
void setCurrentFunc(MachineFunction &MF)
void add(const Constant *C, MachineFunction *MF, Register R)
Register find(const Constant *C, MachineFunction *MF)
Register getSPIRVTypeID(const SPIRVType *SpirvType) const
SPIRVType * getOrCreateSPIRVType(const Type *Type, MachineIRBuilder &MIRBuilder, SPIRV::AccessQualifier::AccessQualifier AQ=SPIRV::AccessQualifier::ReadWrite, bool EmitIR=true)
void assignSPIRVTypeToVReg(SPIRVType *Type, Register VReg, MachineFunction &MF)
SPIRVType * getOrCreateSPIRVTypeByName(StringRef TypeStr, MachineIRBuilder &MIRBuilder, SPIRV::StorageClass::StorageClass SC=SPIRV::StorageClass::Function, SPIRV::AccessQualifier::AccessQualifier AQ=SPIRV::AccessQualifier::ReadWrite)
SPIRVType * assignTypeToVReg(const Type *Type, Register VReg, MachineIRBuilder &MIRBuilder, SPIRV::AccessQualifier::AccessQualifier AQ=SPIRV::AccessQualifier::ReadWrite, bool EmitIR=true)
SPIRVType * getOrCreateOpTypeFunctionWithArgs(const Type *Ty, SPIRVType *RetType, const SmallVectorImpl< SPIRVType * > &ArgTypes, MachineIRBuilder &MIRBuilder)
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
StringRef - Represent a constant reference to a string, i.e.
std::string str() const
str - Get the contents as an std::string.
bool ends_with(StringRef Suffix) const
Check if this string ends with the given Suffix.
int compare(StringRef RHS) const
compare - Compare two strings; the result is negative, zero, or positive if this string is lexicograp...
The instances of the Type class are immutable: once they are created, they are never changed.
unsigned getPointerAddressSpace() const
Get the address space of this pointer or pointer vector type.
LLVM Value Representation.
StringRef getName() const
Return a constant reference to the value's name.
constexpr bool isZero() const
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
@ SPIR_KERNEL
Used for SPIR kernel functions.
std::optional< bool > lowerBuiltin(const StringRef DemangledCall, SPIRV::InstructionSet::InstructionSet Set, MachineIRBuilder &MIRBuilder, const Register OrigRet, const Type *OrigRetTy, const SmallVectorImpl< Register > &Args, SPIRVGlobalRegistry *GR)
This is an optimization pass for GlobalISel generic memory operations.
void buildOpName(Register Target, const StringRef &Name, MachineIRBuilder &MIRBuilder)
auto size(R &&Range, std::enable_if_t< std::is_base_of< std::random_access_iterator_tag, typename std::iterator_traits< decltype(Range.begin())>::iterator_category >::value, void > *=nullptr)
Get the size of a range.
std::string getOclOrSpirvBuiltinDemangledName(StringRef Name)
void buildOpDecorate(Register Reg, MachineIRBuilder &MIRBuilder, SPIRV::Decoration::Decoration Dec, const std::vector< uint32_t > &DecArgs, StringRef StrImm)
SPIRV::StorageClass::StorageClass addressSpaceToStorageClass(unsigned AddrSpace)
bool isSpecialOpaqueType(const Type *Ty)
void report_fatal_error(Error Err, bool gen_crash_diag=true)
Report a serious error, calling any installed error handler.
void addStringImm(const StringRef &Str, MCInst &Inst)