24#include "llvm/IR/IntrinsicsSPIRV.h"
34 for (
unsigned WordIndex = 0; WordIndex < 4; ++WordIndex) {
35 unsigned StrIndex = i + WordIndex;
36 uint8_t CharToAdd = 0;
37 if (StrIndex < Str.size()) {
38 CharToAdd = Str[StrIndex];
40 Word |= (CharToAdd << (WordIndex * 8));
47 const size_t Len = Str.size() + 1;
48 return (Len % 4 == 0) ? Len : Len + (4 - (Len % 4));
53 for (
unsigned i = 0; i < PaddedLen; i += 4) {
61 for (
unsigned i = 0; i < PaddedLen; i += 4) {
68 std::vector<Value *> &Args) {
70 for (
unsigned i = 0; i < PaddedLen; i += 4) {
81 const auto Bitwidth = Imm.getBitWidth();
84 else if (Bitwidth <= 32) {
85 MIB.
addImm(Imm.getZExtValue());
90 }
else if (Bitwidth <= 64) {
91 uint64_t FullImm = Imm.getZExtValue();
92 uint32_t LowBits = FullImm & 0xffffffff;
93 uint32_t HighBits = (FullImm >> 32) & 0xffffffff;
109 const std::vector<uint32_t> &DecArgs,
113 for (
const auto &DecArg : DecArgs)
118 SPIRV::Decoration::Decoration Dec,
119 const std::vector<uint32_t> &DecArgs,
StringRef StrImm) {
120 auto MIB = MIRBuilder.
buildInstr(SPIRV::OpDecorate)
127 SPIRV::Decoration::Decoration Dec,
128 const std::vector<uint32_t> &DecArgs,
StringRef StrImm) {
130 auto MIB =
BuildMI(
MBB,
I,
I.getDebugLoc(),
TII.get(SPIRV::OpDecorate))
139 auto *OpMD = dyn_cast<MDNode>(GVarMD->
getOperand(
I));
142 if (OpMD->getNumOperands() == 0)
145 mdconst::dyn_extract<ConstantInt>(OpMD->getOperand(0));
148 "element of the decoration");
149 auto MIB = MIRBuilder.
buildInstr(SPIRV::OpDecorate)
152 for (
unsigned OpI = 1, OpE = OpMD->getNumOperands(); OpI != OpE; ++OpI) {
154 mdconst::dyn_extract<ConstantInt>(OpMD->getOperand(OpI)))
156 else if (
MDString *OpV = dyn_cast<MDString>(OpMD->getOperand(OpI)))
168 case SPIRV::StorageClass::Function:
170 case SPIRV::StorageClass::CrossWorkgroup:
172 case SPIRV::StorageClass::UniformConstant:
174 case SPIRV::StorageClass::Workgroup:
176 case SPIRV::StorageClass::Generic:
178 case SPIRV::StorageClass::DeviceOnlyINTEL:
180 case SPIRV::StorageClass::HostOnlyINTEL:
182 case SPIRV::StorageClass::Input:
189SPIRV::StorageClass::StorageClass
193 return SPIRV::StorageClass::Function;
195 return SPIRV::StorageClass::CrossWorkgroup;
197 return SPIRV::StorageClass::UniformConstant;
199 return SPIRV::StorageClass::Workgroup;
201 return SPIRV::StorageClass::Generic;
203 return STI.
canUseExtension(SPIRV::Extension::SPV_INTEL_usm_storage_classes)
204 ? SPIRV::StorageClass::DeviceOnlyINTEL
205 : SPIRV::StorageClass::CrossWorkgroup;
207 return STI.
canUseExtension(SPIRV::Extension::SPV_INTEL_usm_storage_classes)
208 ? SPIRV::StorageClass::HostOnlyINTEL
209 : SPIRV::StorageClass::CrossWorkgroup;
211 return SPIRV::StorageClass::Input;
217SPIRV::MemorySemantics::MemorySemantics
220 case SPIRV::StorageClass::StorageBuffer:
221 case SPIRV::StorageClass::Uniform:
222 return SPIRV::MemorySemantics::UniformMemory;
223 case SPIRV::StorageClass::Workgroup:
224 return SPIRV::MemorySemantics::WorkgroupMemory;
225 case SPIRV::StorageClass::CrossWorkgroup:
226 return SPIRV::MemorySemantics::CrossWorkgroupMemory;
227 case SPIRV::StorageClass::AtomicCounter:
228 return SPIRV::MemorySemantics::AtomicCounterMemory;
229 case SPIRV::StorageClass::Image:
230 return SPIRV::MemorySemantics::ImageMemory;
232 return SPIRV::MemorySemantics::None;
239 return SPIRV::MemorySemantics::Acquire;
241 return SPIRV::MemorySemantics::Release;
243 return SPIRV::MemorySemantics::AcquireRelease;
245 return SPIRV::MemorySemantics::SequentiallyConsistent;
249 return SPIRV::MemorySemantics::None;
258 MI->getOpcode() == SPIRV::G_TRUNC ||
MI->getOpcode() == SPIRV::G_ZEXT
259 ?
MRI->getVRegDef(
MI->getOperand(1).getReg())
261 if (
auto *GI = dyn_cast<GIntrinsic>(ConstInstr)) {
262 if (GI->is(Intrinsic::spv_track_constant)) {
264 return MRI->getVRegDef(ConstReg);
266 }
else if (ConstInstr->
getOpcode() == SPIRV::ASSIGN_TYPE) {
268 return MRI->getVRegDef(ConstReg);
270 return MRI->getVRegDef(ConstReg);
275 assert(
MI &&
MI->getOpcode() == TargetOpcode::G_CONSTANT);
276 return MI->getOperand(1).getCImm()->getValue().getZExtValue();
280 if (
const auto *GI = dyn_cast<GIntrinsic>(&
MI))
281 return GI->is(IntrinsicID);
286 Type *ElementTy = cast<ValueAsMetadata>(
N->getOperand(
I))->getType();
293 return MangledName ==
"write_pipe_2" || MangledName ==
"read_pipe_2" ||
294 MangledName ==
"write_pipe_2_bl" || MangledName ==
"read_pipe_2_bl" ||
295 MangledName ==
"write_pipe_4" || MangledName ==
"read_pipe_4" ||
296 MangledName ==
"reserve_write_pipe" ||
297 MangledName ==
"reserve_read_pipe" ||
298 MangledName ==
"commit_write_pipe" ||
299 MangledName ==
"commit_read_pipe" ||
300 MangledName ==
"work_group_reserve_write_pipe" ||
301 MangledName ==
"work_group_reserve_read_pipe" ||
302 MangledName ==
"work_group_commit_write_pipe" ||
303 MangledName ==
"work_group_commit_read_pipe" ||
304 MangledName ==
"get_pipe_num_packets_ro" ||
305 MangledName ==
"get_pipe_max_packets_ro" ||
306 MangledName ==
"get_pipe_num_packets_wo" ||
307 MangledName ==
"get_pipe_max_packets_wo" ||
308 MangledName ==
"sub_group_reserve_write_pipe" ||
309 MangledName ==
"sub_group_reserve_read_pipe" ||
310 MangledName ==
"sub_group_commit_write_pipe" ||
311 MangledName ==
"sub_group_commit_read_pipe" ||
312 MangledName ==
"to_global" || MangledName ==
"to_local" ||
313 MangledName ==
"to_private";
317 return MangledName ==
"__enqueue_kernel_basic" ||
318 MangledName ==
"__enqueue_kernel_basic_events" ||
319 MangledName ==
"__enqueue_kernel_varargs" ||
320 MangledName ==
"__enqueue_kernel_events_varargs";
324 return MangledName ==
"__get_kernel_work_group_size_impl" ||
325 MangledName ==
"__get_kernel_sub_group_count_for_ndrange_impl" ||
326 MangledName ==
"__get_kernel_max_sub_group_size_for_ndrange_impl" ||
327 MangledName ==
"__get_kernel_preferred_work_group_size_multiple_impl";
331 if (!
Name.starts_with(
"__"))
336 Name ==
"__translate_sampler_initializer";
341 bool IsNonMangledSPIRV =
Name.starts_with(
"__spirv_");
342 bool IsNonMangledHLSL =
Name.starts_with(
"__hlsl_");
343 bool IsMangled =
Name.starts_with(
"_Z");
346 if (IsNonMangledOCL || IsNonMangledSPIRV || IsNonMangledHLSL || !IsMangled)
351 std::string Result = DemangledName;
360 size_t Start, Len = 0;
361 size_t DemangledNameLenStart = 2;
362 if (
Name.starts_with(
"_ZN")) {
364 size_t NameSpaceStart =
Name.find_first_not_of(
"rVKRO", 3);
366 if (
Name.substr(NameSpaceStart, 11) !=
"2cl7__spirv")
367 return std::string();
368 DemangledNameLenStart = NameSpaceStart + 11;
370 Start =
Name.find_first_not_of(
"0123456789", DemangledNameLenStart);
371 Name.substr(DemangledNameLenStart, Start - DemangledNameLenStart)
372 .getAsInteger(10, Len);
373 return Name.substr(Start, Len).str();
377 if (
Name.starts_with(
"opencl.") ||
Name.starts_with(
"ocl_") ||
378 Name.starts_with(
"spirv."))
384 if (
const TargetExtType *EType = dyn_cast<TargetExtType>(Ty))
398 if (
F.getFnAttribute(
"hlsl.shader").isValid())
405 TypeName.consume_front(
"atomic_");
406 if (TypeName.consume_front(
"void"))
408 else if (TypeName.consume_front(
"bool"))
410 else if (TypeName.consume_front(
"char") ||
411 TypeName.consume_front(
"unsigned char") ||
412 TypeName.consume_front(
"uchar"))
414 else if (TypeName.consume_front(
"short") ||
415 TypeName.consume_front(
"unsigned short") ||
416 TypeName.consume_front(
"ushort"))
418 else if (TypeName.consume_front(
"int") ||
419 TypeName.consume_front(
"unsigned int") ||
420 TypeName.consume_front(
"uint"))
422 else if (TypeName.consume_front(
"long") ||
423 TypeName.consume_front(
"unsigned long") ||
424 TypeName.consume_front(
"ulong"))
426 else if (TypeName.consume_front(
"half"))
428 else if (TypeName.consume_front(
"float"))
430 else if (TypeName.consume_front(
"double"))
unsigned const MachineRegisterInfo * MRI
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
Declares convenience wrapper classes for interpreting MachineInstr instances as specific generic oper...
const HexagonInstrInfo * TII
This file declares the MachineIRBuilder class.
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
Class for arbitrary precision integers.
This is the shared class of boolean and integer constants.
uint64_t getZExtValue() const
Return the constant as a 64-bit unsigned integer value after it has been zero extended as appropriate...
This provides a uniform API for creating instructions and inserting them into a basic block: either a...
This is an important class for using LLVM in a threaded context.
Instances of this class represent a single low-level machine instruction.
void addOperand(const MCOperand Op)
static MCOperand createImm(int64_t Val)
const MDOperand & getOperand(unsigned I) const
unsigned getNumOperands() const
Return number of MDNode operands.
Helper class to build MachineInstr.
MachineInstrBuilder buildInstr(unsigned Opcode)
Build and insert <empty> = Opcode <empty>.
const MachineInstrBuilder & addImm(int64_t Val) const
Add a new immediate operand.
const MachineInstrBuilder & addUse(Register RegNo, unsigned Flags=0, unsigned SubReg=0) const
Add a virtual register use operand.
MachineInstr * getInstr() const
If conversion operators fail, use this method to get the MachineInstr explicitly.
Representation of each machine instruction.
unsigned getOpcode() const
Returns the opcode of this MachineInstr.
void setAsmPrinterFlag(uint8_t Flag)
Set a flag for the AsmPrinter.
const MachineOperand & getOperand(unsigned i) const
Register getReg() const
getReg - Returns the register number.
MachineRegisterInfo - Keep track of information for virtual and physical registers,...
Wrapper class representing virtual and physical registers.
bool canUseExtension(SPIRV::Extension::Extension E) const
StringRef - Represent a constant reference to a string, i.e.
constexpr bool empty() const
empty - Check if the string is empty.
Class to represent target extensions types, which are generally unintrospectable from target-independ...
Target - Wrapper for Target specific information.
The instances of the Type class are immutable: once they are created, they are never changed.
static Type * getHalfTy(LLVMContext &C)
static Type * getDoubleTy(LLVMContext &C)
static IntegerType * getIntNTy(LLVMContext &C, unsigned N)
static Type * getVoidTy(LLVMContext &C)
static IntegerType * getInt16Ty(LLVMContext &C)
static IntegerType * getInt8Ty(LLVMContext &C)
static IntegerType * getInt32Ty(LLVMContext &C)
static IntegerType * getInt64Ty(LLVMContext &C)
static Type * getFloatTy(LLVMContext &C)
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
@ SPIR_KERNEL
Used for SPIR kernel functions.
This is an optimization pass for GlobalISel generic memory operations.
void buildOpName(Register Target, const StringRef &Name, MachineIRBuilder &MIRBuilder)
unsigned storageClassToAddressSpace(SPIRV::StorageClass::StorageClass SC)
std::string getStringImm(const MachineInstr &MI, unsigned StartIndex)
MachineInstrBuilder BuildMI(MachineFunction &MF, const MIMetadata &MIMD, const MCInstrDesc &MCID)
Builder interface. Specify how to create the initial instruction itself.
static void finishBuildOpDecorate(MachineInstrBuilder &MIB, const std::vector< uint32_t > &DecArgs, StringRef StrImm)
static uint32_t convertCharsToWord(const StringRef &Str, unsigned i)
void addNumImm(const APInt &Imm, MachineInstrBuilder &MIB)
uint64_t getIConstVal(Register ConstReg, const MachineRegisterInfo *MRI)
SPIRV::MemorySemantics::MemorySemantics getMemSemanticsForStorageClass(SPIRV::StorageClass::StorageClass SC)
std::string getOclOrSpirvBuiltinDemangledName(StringRef Name)
void buildOpDecorate(Register Reg, MachineIRBuilder &MIRBuilder, SPIRV::Decoration::Decoration Dec, const std::vector< uint32_t > &DecArgs, StringRef StrImm)
std::string getSPIRVStringOperand(const InstType &MI, unsigned StartIndex)
Type * toTypedPointer(Type *Ty)
char * itaniumDemangle(std::string_view mangled_name, bool ParseParams=true)
Returns a non-NULL pointer to a NUL-terminated C style string that should be explicitly freed,...
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.
static bool isNonMangledOCLBuiltin(StringRef Name)
bool isEntryPoint(const Function &F)
SPIRV::StorageClass::StorageClass addressSpaceToStorageClass(unsigned AddrSpace, const SPIRVSubtarget &STI)
AtomicOrdering
Atomic ordering for LLVM's memory model.
static bool isPipeOrAddressSpaceCastBI(const StringRef MangledName)
Type * parseBasicTypeName(StringRef &TypeName, LLVMContext &Ctx)
MachineInstr * getDefInstrMaybeConstant(Register &ConstReg, const MachineRegisterInfo *MRI)
bool hasBuiltinTypePrefix(StringRef Name)
Type * getMDOperandAsType(const MDNode *N, unsigned I)
static size_t getPaddedLen(const StringRef &Str)
bool isSpvIntrinsic(const MachineInstr &MI, Intrinsic::ID IntrinsicID)
void addStringImm(const StringRef &Str, MCInst &Inst)
static bool isKernelQueryBI(const StringRef MangledName)
void buildOpSpirvDecorations(Register Reg, MachineIRBuilder &MIRBuilder, const MDNode *GVarMD)
static bool isEnqueueKernelBI(const StringRef MangledName)
SPIRV::MemorySemantics::MemorySemantics getMemSemantics(AtomicOrdering Ord)