LLVM 24.0.0git
SPIRVUtils.cpp
Go to the documentation of this file.
1//===--- SPIRVUtils.cpp ---- SPIR-V Utility Functions -----------*- C++ -*-===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8//
9// This file contains miscellaneous utility functions.
10//
11//===----------------------------------------------------------------------===//
12
13#include "SPIRVUtils.h"
15#include "SPIRV.h"
16#include "SPIRVBuiltins.h"
17#include "SPIRVGlobalRegistry.h"
18#include "SPIRVInstrInfo.h"
19#include "SPIRVSubtarget.h"
20#include "llvm/ADT/STLExtras.h"
21#include "llvm/ADT/StringRef.h"
28#include "llvm/IR/IntrinsicsSPIRV.h"
31#include <queue>
32#include <vector>
33
34namespace llvm {
35namespace SPIRV {
37 auto It = find_if(NMD->operands(), [Name](MDNode *N) {
38 if (auto *MDS = dyn_cast_or_null<MDString>(N->getOperand(0)))
39 return MDS->getString() == Name;
40 return false;
41 });
42 return It == NMD->op_end() ? nullptr : *It;
43}
44
45// This code restores function args/retvalue types for composite cases
46// because the final types should still be aggregate whereas they're i32
47// during the translation to cope with aggregate flattening etc.
48// TODO: should these just return nullptr when there's no metadata?
50 FunctionType *FTy,
51 StringRef Name) {
52 if (!NMD)
53 return FTy;
54
55 MDNode *Match = findNamedMDOperand(NMD, Name);
56 if (!Match)
57 return FTy;
58
59 Type *RetTy = FTy->getReturnType();
60 SmallVector<Type *, 4> PTys(FTy->params());
61
62 for (unsigned I = 1; I != Match->getNumOperands(); ++I) {
63 MDNode *MD = dyn_cast<MDNode>(Match->getOperand(I));
64 assert(MD && "MDNode operand is expected");
65
66 if (auto *Const = getMDOperandAsConstInt(MD, 0)) {
67 auto *CMeta = dyn_cast<ConstantAsMetadata>(MD->getOperand(1));
68 assert(CMeta && "ConstantAsMetadata operand is expected");
69 int64_t Idx = Const->getSExtValue();
70 // Currently -1 indicates return value, greater values mean
71 // argument numbers.
72 if (Idx == -1) {
73 RetTy = CMeta->getType();
74 continue;
75 }
76 if (Idx >= 0 && static_cast<uint64_t>(Idx) < PTys.size()) {
77 PTys[Idx] = CMeta->getType();
78 continue;
79 }
80 report_fatal_error("invalid argument index in function type metadata");
81 }
82 }
83
84 return FunctionType::get(RetTy, PTys, FTy->isVarArg());
85}
86
88 StringRef Constraints,
89 StringRef Name) {
90 if (!NMD)
91 return Constraints;
92
93 MDNode *Match = findNamedMDOperand(NMD, Name);
94 if (!Match)
95 return Constraints;
96
97 // By convention, the constraints string is stored in the final MD operand.
98 MDNode *MD = dyn_cast<MDNode>(Match->getOperand(Match->getNumOperands() - 1));
99 assert(MD && "MDNode operand is expected");
100
101 if (auto *MDS = dyn_cast<MDString>(MD->getOperand(0)))
102 Constraints = MDS->getString();
103
104 return Constraints;
105}
106
109 F.getParent()->getNamedMetadata("spv.cloned_funcs"), F.getFunctionType(),
110 F.getName());
111}
112
113// Keyed via instruction metadata, not a name.
114static std::optional<StringRef> getMutatedCallsiteKey(const CallBase &CB) {
115 if (MDNode *MD = CB.getMetadata("spv.mutated_callsite"))
116 if (MD->getNumOperands() > 0)
117 if (auto *MDS = dyn_cast<MDString>(MD->getOperand(0)))
118 return MDS->getString();
119 return std::nullopt;
120}
121
123 std::optional<StringRef> Key = getMutatedCallsiteKey(CB);
124 if (!Key)
125 return CB.getFunctionType();
127 CB.getModule()->getNamedMetadata("spv.mutated_callsites"),
128 CB.getFunctionType(), *Key);
129}
130
132 StringRef Constraints =
133 cast<InlineAsm>(CB.getCalledOperand())->getConstraintString();
134 std::optional<StringRef> Key = getMutatedCallsiteKey(CB);
135 if (!Key)
136 return Constraints;
138 CB.getModule()->getNamedMetadata("spv.mutated_callsites"), Constraints,
139 *Key);
140}
141} // Namespace SPIRV
142
143// The following functions are used to add these string literals as a series of
144// 32-bit integer operands with the correct format, and unpack them if necessary
145// when making string comparisons in compiler passes.
146// SPIR-V requires null-terminated UTF-8 strings padded to 32-bit alignment.
147static uint32_t convertCharsToWord(StringRef Str, unsigned i) {
148 uint32_t Word = 0u; // Build up this 32-bit word from 4 8-bit chars.
149 for (unsigned WordIndex = 0; WordIndex < 4; ++WordIndex) {
150 unsigned StrIndex = i + WordIndex;
151 uint8_t CharToAdd = 0; // Initilize char as padding/null.
152 if (StrIndex < Str.size()) { // If it's within the string, get a real char.
153 CharToAdd = Str[StrIndex];
154 }
155 Word |= (CharToAdd << (WordIndex * 8));
156 }
157 return Word;
158}
159
160// Get length including padding and null terminator.
161static size_t getPaddedLen(StringRef Str) { return alignTo(Str.size() + 1, 4); }
162
163void addStringImm(StringRef Str, MCInst &Inst) {
164 const size_t PaddedLen = getPaddedLen(Str);
165 for (unsigned i = 0; i < PaddedLen; i += 4) {
166 // Add an operand for the 32-bits of chars or padding.
168 }
169}
170
172 const size_t PaddedLen = getPaddedLen(Str);
173 for (unsigned i = 0; i < PaddedLen; i += 4) {
174 // Add an operand for the 32-bits of chars or padding.
175 MIB.addImm(convertCharsToWord(Str, i));
176 }
177}
178
179std::string getStringImm(const MachineInstr &MI, unsigned StartIndex) {
180 return getSPIRVStringOperand(MI, StartIndex);
181}
182
184 MachineInstr *Def = getVRegDef(MRI, Reg);
185 assert(Def && Def->getOpcode() == TargetOpcode::G_GLOBAL_VALUE &&
186 "Expected G_GLOBAL_VALUE");
187 const GlobalValue *GV = Def->getOperand(1).getGlobal();
188 Value *V = GV->getOperand(0);
190 return CDA->getAsCString().str();
191}
192
193void addNumImm(const APInt &Imm, MachineInstrBuilder &MIB) {
194 const auto Bitwidth = Imm.getBitWidth();
195 if (Bitwidth == 1)
196 return; // Already handled
197 else if (Bitwidth <= 32) {
198 MIB.addImm(Imm.getZExtValue());
199 // Asm Printer needs this info to print floating-type correctly
200 if (Bitwidth == 16)
202 return;
203 } else if (Bitwidth <= 64) {
204 uint64_t FullImm = Imm.getZExtValue();
205 MIB.addImm(Lo_32(FullImm)).addImm(Hi_32(FullImm));
206 // Asm Printer needs this info to print 64-bit operands correctly
208 return;
209 } else {
210 // Emit ceil(Bitwidth / 32) words to conform SPIR-V spec.
211 unsigned NumWords = divideCeil(Bitwidth, 32);
212 for (unsigned I = 0; I < NumWords; ++I) {
213 unsigned LimbIdx = I / 2;
214 unsigned LimbShift = (I % 2) * 32;
215 uint32_t Word = (Imm.getRawData()[LimbIdx] >> LimbShift) & 0xffffffff;
216 MIB.addImm(Word);
217 }
218 return;
219 }
220}
221
223 MachineIRBuilder &MIRBuilder) {
224 if (!Name.empty()) {
225 auto MIB = MIRBuilder.buildInstr(SPIRV::OpName).addUse(Target);
226 addStringImm(Name, MIB);
227 }
228}
229
231 const SPIRVInstrInfo &TII) {
232 if (!Name.empty()) {
233 auto MIB =
234 BuildMI(*I.getParent(), I, I.getDebugLoc(), TII.get(SPIRV::OpName))
235 .addUse(Target);
236 addStringImm(Name, MIB);
237 }
238}
239
241 ArrayRef<uint32_t> DecArgs,
242 StringRef StrImm) {
243 if (!StrImm.empty())
244 addStringImm(StrImm, MIB);
245 for (const auto &DecArg : DecArgs)
246 MIB.addImm(DecArg);
247}
248
250 SPIRV::Decoration::Decoration Dec,
251 ArrayRef<uint32_t> DecArgs, StringRef StrImm) {
252 auto MIB = MIRBuilder.buildInstr(SPIRV::OpDecorate)
253 .addUse(Reg)
254 .addImm(static_cast<uint32_t>(Dec));
255 finishBuildOpDecorate(MIB, DecArgs, StrImm);
256}
257
259 SPIRV::Decoration::Decoration Dec,
260 ArrayRef<uint32_t> DecArgs, StringRef StrImm) {
261 MachineBasicBlock &MBB = *I.getParent();
262 auto MIB = BuildMI(MBB, I, I.getDebugLoc(), TII.get(SPIRV::OpDecorate))
263 .addUse(Reg)
264 .addImm(static_cast<uint32_t>(Dec));
265 finishBuildOpDecorate(MIB, DecArgs, StrImm);
266}
267
269 SPIRV::Decoration::Decoration Dec, uint32_t Member,
270 ArrayRef<uint32_t> DecArgs, StringRef StrImm) {
271 auto MIB = MIRBuilder.buildInstr(SPIRV::OpMemberDecorate)
272 .addUse(Reg)
273 .addImm(Member)
274 .addImm(static_cast<uint32_t>(Dec));
275 finishBuildOpDecorate(MIB, DecArgs, StrImm);
276}
277
279 const MDNode *GVarMD, const SPIRVSubtarget &ST) {
280 for (unsigned I = 0, E = GVarMD->getNumOperands(); I != E; ++I) {
281 auto *OpMD = dyn_cast<MDNode>(GVarMD->getOperand(I));
282 if (!OpMD)
283 report_fatal_error("Invalid decoration");
284 if (OpMD->getNumOperands() == 0)
285 report_fatal_error("Expect operand(s) of the decoration");
286 ConstantInt *DecorationId =
287 mdconst::dyn_extract<ConstantInt>(OpMD->getOperand(0));
288 if (!DecorationId)
289 report_fatal_error("Expect SPIR-V <Decoration> operand to be the first "
290 "element of the decoration");
291
292 // The goal of `spirv.Decorations` metadata is to provide a way to
293 // represent SPIR-V entities that do not map to LLVM in an obvious way.
294 // FP flags do have obvious matches between LLVM IR and SPIR-V.
295 // Additionally, we have no guarantee at this point that the flags passed
296 // through the decoration are not violated already in the optimizer passes.
297 // Therefore, we simply ignore FP flags, including NoContraction, and
298 // FPFastMathMode.
299 if (DecorationId->getZExtValue() ==
300 static_cast<uint32_t>(SPIRV::Decoration::NoContraction) ||
301 DecorationId->getZExtValue() ==
302 static_cast<uint32_t>(SPIRV::Decoration::FPFastMathMode)) {
303 continue; // Ignored.
304 }
305 uint32_t Dec = static_cast<uint32_t>(DecorationId->getZExtValue());
306 if (Dec == static_cast<uint32_t>(SPIRV::Decoration::UniformId)) {
307 ConstantInt *ScopeV =
308 OpMD->getNumOperands() == 2
309 ? mdconst::dyn_extract<ConstantInt>(OpMD->getOperand(1))
310 : nullptr;
311 assert(ScopeV && isUInt<32>(ScopeV->getZExtValue()) &&
312 "Expect Scope <id> operand of the UniformId decoration");
313 SPIRVGlobalRegistry *GR = ST.getSPIRVGlobalRegistry();
314 SPIRVTypeInst SpvTypeInt32 =
315 GR->getOrCreateSPIRVIntegerType(32, MIRBuilder);
316 Register ScopeReg = GR->buildConstantInt(
317 ScopeV->getZExtValue(), MIRBuilder, SpvTypeInt32, /*EmitIR=*/false);
318 MIRBuilder.buildInstr(SPIRV::OpDecorateId)
319 .addUse(Reg)
320 .addImm(Dec)
321 .addUse(ScopeReg);
322 continue;
323 }
324 auto MIB = MIRBuilder.buildInstr(SPIRV::OpDecorate).addUse(Reg).addImm(Dec);
325 for (unsigned OpI = 1, OpE = OpMD->getNumOperands(); OpI != OpE; ++OpI) {
326 if (ConstantInt *OpV =
327 mdconst::dyn_extract<ConstantInt>(OpMD->getOperand(OpI)))
328 MIB.addImm(static_cast<uint32_t>(OpV->getZExtValue()));
329 else if (MDString *OpV = dyn_cast<MDString>(OpMD->getOperand(OpI)))
330 addStringImm(OpV->getString(), MIB);
331 else
332 report_fatal_error("Unexpected operand of the decoration");
333 }
334 }
335}
336
339 // Find the position to insert the OpVariable instruction.
340 // We will insert it after the last OpFunctionParameter, if any, or
341 // after OpFunction otherwise.
342 auto IsPreamble = [](const MachineInstr &MI) {
343 switch (MI.getOpcode()) {
344 case SPIRV::OpFunction:
345 case SPIRV::OpFunctionParameter:
346 case SPIRV::OpLabel:
347 case SPIRV::ASSIGN_TYPE:
348 return true;
349 default:
350 return false;
351 }
352 };
353 MachineBasicBlock::iterator VarPos = MBB.SkipPHIsAndLabels(MBB.begin());
354 while (VarPos != MBB.end() && VarPos->getOpcode() != SPIRV::OpFunction)
355 ++VarPos;
356 // Advance past the preamble.
357 while (VarPos != MBB.end() && IsPreamble(*VarPos))
358 ++VarPos;
359 return VarPos;
360}
361
364 if (I == MBB->begin())
365 return I;
366 --I;
367 while (I->isTerminator() || I->isDebugValue()) {
368 if (I == MBB->begin())
369 break;
370 --I;
371 }
372 return I;
373}
374
375SPIRV::StorageClass::StorageClass
376addressSpaceToStorageClass(unsigned AddrSpace, const SPIRVSubtarget &STI) {
377 switch (AddrSpace) {
378 case 0:
379 return SPIRV::StorageClass::Function;
380 case 1:
381 return SPIRV::StorageClass::CrossWorkgroup;
382 case 2:
383 return SPIRV::StorageClass::UniformConstant;
384 case 3:
385 return SPIRV::StorageClass::Workgroup;
386 case 4:
387 return SPIRV::StorageClass::Generic;
388 case 5:
389 return STI.canUseExtension(SPIRV::Extension::SPV_INTEL_usm_storage_classes)
390 ? SPIRV::StorageClass::DeviceOnlyINTEL
391 : SPIRV::StorageClass::CrossWorkgroup;
392 case 6:
393 return STI.canUseExtension(SPIRV::Extension::SPV_INTEL_usm_storage_classes)
394 ? SPIRV::StorageClass::HostOnlyINTEL
395 : SPIRV::StorageClass::CrossWorkgroup;
396 case 7:
397 return SPIRV::StorageClass::Input;
398 case 8:
399 return SPIRV::StorageClass::Output;
400 case 9:
401 return SPIRV::StorageClass::CodeSectionINTEL;
402 case 10:
403 return SPIRV::StorageClass::Private;
404 case 11:
405 return SPIRV::StorageClass::StorageBuffer;
406 case 12:
407 return SPIRV::StorageClass::Uniform;
408 case 13:
409 return SPIRV::StorageClass::PushConstant;
410 default:
411 report_fatal_error("Unknown address space");
412 }
413}
414
415SPIRV::MemorySemantics::MemorySemantics
416getMemSemanticsForStorageClass(SPIRV::StorageClass::StorageClass SC) {
417 switch (SC) {
418 case SPIRV::StorageClass::StorageBuffer:
419 case SPIRV::StorageClass::Uniform:
420 return SPIRV::MemorySemantics::UniformMemory;
421 case SPIRV::StorageClass::Workgroup:
422 return SPIRV::MemorySemantics::WorkgroupMemory;
423 case SPIRV::StorageClass::CrossWorkgroup:
424 return SPIRV::MemorySemantics::CrossWorkgroupMemory;
425 case SPIRV::StorageClass::AtomicCounter:
426 return SPIRV::MemorySemantics::AtomicCounterMemory;
427 case SPIRV::StorageClass::Image:
428 return SPIRV::MemorySemantics::ImageMemory;
429 default:
430 return SPIRV::MemorySemantics::None;
431 }
432}
433
434SPIRV::MemorySemantics::MemorySemantics getMemSemantics(AtomicOrdering Ord) {
435 switch (Ord) {
437 return SPIRV::MemorySemantics::Acquire;
439 return SPIRV::MemorySemantics::Release;
441 return SPIRV::MemorySemantics::AcquireRelease;
443 return SPIRV::MemorySemantics::SequentiallyConsistent;
447 return SPIRV::MemorySemantics::None;
448 }
449 llvm_unreachable(nullptr);
450}
451
452SPIRV::Scope::Scope getMemScope(const Triple &TT, LLVMContext &Ctx,
453 SyncScope::ID Id) {
454 // Named by
455 // https://registry.khronos.org/SPIR-V/specs/unified1/SPIRV.html#_scope_id.
456 // We don't need aliases for Invocation and CrossDevice, as we already have
457 // them covered by "singlethread" and "" strings respectively (see
458 // implementation of LLVMContext::LLVMContext()).
459 auto ScopeID = [&](AtomicScope Scope) {
460 return Ctx.getOrInsertSyncScopeID(*getAtomicScopeIRString(TT, Scope));
461 };
462 static const llvm::SyncScope::ID SubGroup = ScopeID(AtomicScope::Wavefront);
463 static const llvm::SyncScope::ID WorkGroup = ScopeID(AtomicScope::Workgroup);
464 static const llvm::SyncScope::ID Device = ScopeID(AtomicScope::Device);
465
467 return SPIRV::Scope::Invocation;
468 else if (Id == llvm::SyncScope::System)
469 return SPIRV::Scope::CrossDevice;
470 else if (Id == SubGroup)
471 return SPIRV::Scope::Subgroup;
472 else if (Id == WorkGroup)
473 return SPIRV::Scope::Workgroup;
474 else if (Id == Device)
475 return SPIRV::Scope::Device;
476 return SPIRV::Scope::CrossDevice;
477}
478
480 const MachineRegisterInfo *MRI) {
481 MachineInstr *MI = MRI->getVRegDef(ConstReg);
482 MachineInstr *ConstInstr =
483 MI->getOpcode() == SPIRV::G_TRUNC || MI->getOpcode() == SPIRV::G_ZEXT
484 ? MRI->getVRegDef(MI->getOperand(1).getReg())
485 : MI;
486 if (auto *GI = dyn_cast<GIntrinsic>(ConstInstr)) {
487 if (GI->is(Intrinsic::spv_track_constant)) {
488 ConstReg = ConstInstr->getOperand(2).getReg();
489 return MRI->getVRegDef(ConstReg);
490 }
491 } else if (ConstInstr->getOpcode() == SPIRV::ASSIGN_TYPE) {
492 ConstReg = ConstInstr->getOperand(1).getReg();
493 return MRI->getVRegDef(ConstReg);
494 } else if (ConstInstr->getOpcode() == TargetOpcode::G_CONSTANT ||
495 ConstInstr->getOpcode() == TargetOpcode::G_FCONSTANT) {
496 ConstReg = ConstInstr->getOperand(0).getReg();
497 return ConstInstr;
498 }
499 return MRI->getVRegDef(ConstReg);
500}
501
503 const MachineInstr *MI = getDefInstrMaybeConstant(ConstReg, MRI);
504 assert(MI && MI->getOpcode() == TargetOpcode::G_CONSTANT);
505 return MI->getOperand(1).getCImm()->getValue().getZExtValue();
506}
507
508int64_t getIConstValSext(Register ConstReg, const MachineRegisterInfo *MRI) {
509 const MachineInstr *MI = getDefInstrMaybeConstant(ConstReg, MRI);
510 assert(MI && MI->getOpcode() == TargetOpcode::G_CONSTANT);
511 return MI->getOperand(1).getCImm()->getSExtValue();
512}
513
514bool isSpvIntrinsic(const MachineInstr &MI, Intrinsic::ID IntrinsicID) {
515 if (const auto *GI = dyn_cast<GIntrinsic>(&MI))
516 return GI->is(IntrinsicID);
517 return false;
518}
519
520Type *getMDOperandAsType(const MDNode *N, unsigned I) {
521 Type *ElementTy = cast<ValueAsMetadata>(N->getOperand(I))->getType();
522 return toTypedPointer(ElementTy);
523}
524
526 if (N->getNumOperands() <= I)
527 return nullptr;
528 if (auto *CMeta = dyn_cast<ConstantAsMetadata>(N->getOperand(I)))
529 return dyn_cast<ConstantInt>(CMeta->getValue());
530 return nullptr;
531}
532
533static bool isEnqueueKernelBI(StringRef MangledName) {
534 return MangledName == "__enqueue_kernel_basic" ||
535 MangledName == "__enqueue_kernel_basic_events" ||
536 MangledName == "__enqueue_kernel_varargs" ||
537 MangledName == "__enqueue_kernel_events_varargs";
538}
539
540static bool isKernelQueryBI(StringRef MangledName) {
541 return MangledName == "__get_kernel_work_group_size_impl" ||
542 MangledName == "__get_kernel_sub_group_count_for_ndrange_impl" ||
543 MangledName == "__get_kernel_max_sub_group_size_for_ndrange_impl" ||
544 MangledName == "__get_kernel_preferred_work_group_size_multiple_impl";
545}
546
548 if (!Name.starts_with("__"))
549 return false;
550
551 return isEnqueueKernelBI(Name) || isKernelQueryBI(Name) ||
553 Name == "__translate_sampler_initializer";
554}
555
557 bool IsNonMangledOCL = isNonMangledOCLBuiltin(Name);
558 bool IsNonMangledSPIRV = Name.starts_with("__spirv_");
559 bool IsNonMangledHLSL = Name.starts_with("__hlsl_");
560 bool IsMangled = Name.starts_with("_Z");
561
562 // Otherwise use simple demangling to return the function name.
563 if (IsNonMangledOCL || IsNonMangledSPIRV || IsNonMangledHLSL || !IsMangled)
564 return Name.str();
565
566 // Try to use the itanium demangler.
567 if (char *DemangledName = itaniumDemangle(Name.data())) {
568 std::string Result = DemangledName;
569 free(DemangledName);
570 return Result;
571 }
572
573 // Autocheck C++, maybe need to do explicit check of the source language.
574 // OpenCL C++ built-ins are declared in cl namespace.
575 // TODO: consider using 'St' abbriviation for cl namespace mangling.
576 // Similar to ::std:: in C++.
577 size_t Start, Len = 0;
578 size_t DemangledNameLenStart = 2;
579 if (Name.starts_with("_ZN")) {
580 // Skip CV and ref qualifiers.
581 size_t NameSpaceStart = Name.find_first_not_of("rVKRO", 3);
582 // All built-ins are in the ::cl:: namespace.
583 if (Name.substr(NameSpaceStart, 11) != "2cl7__spirv")
584 return std::string();
585 DemangledNameLenStart = NameSpaceStart + 11;
586 }
587 Start = Name.find_first_not_of("0123456789", DemangledNameLenStart);
588 bool Error = Name.substr(DemangledNameLenStart, Start - DemangledNameLenStart)
589 .getAsInteger(10, Len);
590 if (Error)
591 return std::string();
592 return Name.substr(Start, Len).str();
593}
594
596 if (Name.starts_with("opencl.") || Name.starts_with("ocl_") ||
597 Name.starts_with("spirv."))
598 return true;
599 return false;
600}
601
602bool isSpecialOpaqueType(const Type *Ty) {
603 if (const TargetExtType *ExtTy = dyn_cast<TargetExtType>(Ty))
604 return isTypedPointerWrapper(ExtTy)
605 ? false
606 : hasBuiltinTypePrefix(ExtTy->getName());
607
608 return false;
609}
610
611bool isEntryPoint(const Function &F) {
612 // OpenCL handling: any function with the SPIR_KERNEL
613 // calling convention will be a potential entry point.
614 if (F.getCallingConv() == CallingConv::SPIR_KERNEL)
615 return true;
616
617 // HLSL handling: special attribute are emitted from the
618 // front-end.
619 if (F.getFnAttribute("hlsl.shader").isValid())
620 return true;
621
622 return false;
623}
624
626 TypeName.consume_front("atomic_");
627 if (TypeName.consume_front("void"))
628 return Type::getVoidTy(Ctx);
629 else if (TypeName.consume_front("bool") || TypeName.consume_front("_Bool"))
630 return Type::getIntNTy(Ctx, 1);
631 else if (TypeName.consume_front("char") ||
632 TypeName.consume_front("signed char") ||
633 TypeName.consume_front("unsigned char") ||
634 TypeName.consume_front("uchar"))
635 return Type::getInt8Ty(Ctx);
636 else if (TypeName.consume_front("short") ||
637 TypeName.consume_front("signed short") ||
638 TypeName.consume_front("unsigned short") ||
639 TypeName.consume_front("ushort"))
640 return Type::getInt16Ty(Ctx);
641 else if (TypeName.consume_front("int") ||
642 TypeName.consume_front("signed int") ||
643 TypeName.consume_front("unsigned int") ||
644 TypeName.consume_front("uint"))
645 return Type::getInt32Ty(Ctx);
646 else if (TypeName.consume_front("long") ||
647 TypeName.consume_front("signed long") ||
648 TypeName.consume_front("unsigned long") ||
649 TypeName.consume_front("ulong"))
650 return Type::getInt64Ty(Ctx);
651 else if (TypeName.consume_front("half") ||
652 TypeName.consume_front("_Float16") ||
653 TypeName.consume_front("__fp16"))
654 return Type::getHalfTy(Ctx);
655 else if (TypeName.consume_front("float"))
656 return Type::getFloatTy(Ctx);
657 else if (TypeName.consume_front("double"))
658 return Type::getDoubleTy(Ctx);
659
660 // Unable to recognize SPIRV type name
661 return nullptr;
662}
663
664SmallPtrSet<BasicBlock *, 0>
665PartialOrderingVisitor::getReachableFrom(BasicBlock *Start) {
666 std::queue<BasicBlock *> ToVisit;
667 ToVisit.push(Start);
668
669 SmallPtrSet<BasicBlock *, 0> Output;
670 while (ToVisit.size() != 0) {
671 BasicBlock *BB = ToVisit.front();
672 ToVisit.pop();
673
674 if (Output.count(BB) != 0)
675 continue;
676 Output.insert(BB);
677
678 for (BasicBlock *Successor : successors(BB)) {
679 if (DT.dominates(Successor, BB))
680 continue;
681 ToVisit.push(Successor);
682 }
683 }
684
685 return Output;
686}
687
688bool PartialOrderingVisitor::CanBeVisited(BasicBlock *BB) const {
689 for (BasicBlock *P : predecessors(BB)) {
690 // Ignore back-edges.
691 if (DT.dominates(BB, P))
692 continue;
693
694 // One of the predecessor hasn't been visited. Not ready yet.
695 if (BlockToOrder.count(P) == 0)
696 return false;
697
698 // If the block is a loop exit, the loop must be finished before
699 // we can continue.
700 Loop *L = LI.getLoopFor(P);
701 if (L == nullptr || L->contains(BB))
702 continue;
703
704 // SPIR-V requires a single back-edge. And the backend first
705 // step transforms loops into the simplified format. If we have
706 // more than 1 back-edge, something is wrong.
707 assert(L->getNumBackEdges() <= 1);
708
709 // If the loop has no latch, loop's rank won't matter, so we can
710 // proceed.
711 BasicBlock *Latch = L->getLoopLatch();
712 assert(Latch);
713 if (Latch == nullptr)
714 continue;
715
716 // The latch is not ready yet, let's wait.
717 if (BlockToOrder.count(Latch) == 0)
718 return false;
719 }
720
721 return true;
722}
723
725 auto It = BlockToOrder.find(BB);
726 if (It != BlockToOrder.end())
727 return It->second.Rank;
728
729 size_t result = 0;
730 for (BasicBlock *P : predecessors(BB)) {
731 // Ignore back-edges.
732 if (DT.dominates(BB, P))
733 continue;
734
735 auto Iterator = BlockToOrder.end();
736 Loop *L = LI.getLoopFor(P);
737 BasicBlock *Latch = L ? L->getLoopLatch() : nullptr;
738
739 // If the predecessor is either outside a loop, or part of
740 // the same loop, simply take its rank + 1.
741 if (L == nullptr || L->contains(BB) || Latch == nullptr) {
742 Iterator = BlockToOrder.find(P);
743 } else {
744 // Otherwise, take the loop's rank (highest rank in the loop) as base.
745 // Since loops have a single latch, highest rank is easy to find.
746 // If the loop has no latch, then it doesn't matter.
747 Iterator = BlockToOrder.find(Latch);
748 }
749
750 assert(Iterator != BlockToOrder.end());
751 result = std::max(result, Iterator->second.Rank + 1);
752 }
753
754 return result;
755}
756
757size_t PartialOrderingVisitor::visit(BasicBlock *BB, size_t Unused) {
758 ToVisit.push(BB);
759 Queued.insert(BB);
760
761 size_t QueueIndex = 0;
762 while (ToVisit.size() != 0) {
763 BasicBlock *BB = ToVisit.front();
764 ToVisit.pop();
765
766 if (!CanBeVisited(BB)) {
767 ToVisit.push(BB);
768 if (QueueIndex >= ToVisit.size())
770 "No valid candidate in the queue. Is the graph reducible?");
771 QueueIndex++;
772 continue;
773 }
774
775 QueueIndex = 0;
776 size_t Rank = GetNodeRank(BB);
777 OrderInfo Info = {Rank, BlockToOrder.size()};
778 BlockToOrder.try_emplace(BB, Info);
779
780 for (BasicBlock *S : successors(BB)) {
781 if (Queued.count(S) != 0)
782 continue;
783 ToVisit.push(S);
784 Queued.insert(S);
785 }
786 }
787
788 return 0;
789}
790
792 DT.recalculate(F);
793 LI = LoopInfo(DT);
794
795 visit(&*F.begin(), 0);
796
797 Order.reserve(F.size());
798 for (auto &[BB, Info] : BlockToOrder)
799 Order.emplace_back(BB);
800
801 llvm::sort(Order, [&](const auto &LHS, const auto &RHS) {
802 return compare(LHS, RHS);
803 });
804}
805
807 const BasicBlock *RHS) const {
808 const OrderInfo &InfoLHS = BlockToOrder.at(const_cast<BasicBlock *>(LHS));
809 const OrderInfo &InfoRHS = BlockToOrder.at(const_cast<BasicBlock *>(RHS));
810 if (InfoLHS.Rank != InfoRHS.Rank)
811 return InfoLHS.Rank < InfoRHS.Rank;
812 return InfoLHS.TraversalIndex < InfoRHS.TraversalIndex;
813}
814
816 BasicBlock &Start, std::function<bool(BasicBlock *)> Op) {
817 SmallPtrSet<BasicBlock *, 0> Reachable = getReachableFrom(&Start);
818 assert(BlockToOrder.count(&Start) != 0);
819
820 // Skipping blocks with a rank inferior to |Start|'s rank.
821 auto It = Order.begin();
822 while (It != Order.end() && *It != &Start)
823 ++It;
824
825 // This is unexpected. Worst case |Start| is the last block,
826 // so It should point to the last block, not past-end.
827 assert(It != Order.end());
828
829 // By default, there is no rank limit. Setting it to the maximum value.
830 std::optional<size_t> EndRank = std::nullopt;
831 for (; It != Order.end(); ++It) {
832 if (EndRank.has_value() && BlockToOrder[*It].Rank > *EndRank)
833 break;
834
835 if (Reachable.count(*It) == 0) {
836 continue;
837 }
838
839 if (!Op(*It)) {
840 EndRank = BlockToOrder[*It].Rank;
841 }
842 }
843}
844
846 if (F.size() == 0)
847 return false;
848
849 bool Modified = false;
850 std::vector<BasicBlock *> Order;
851 Order.reserve(F.size());
852
854 llvm::append_range(Order, RPOT);
855
856 assert(&*F.begin() == Order[0]);
857 BasicBlock *LastBlock = &*F.begin();
858 for (BasicBlock *BB : Order) {
859 if (BB != LastBlock && &*LastBlock->getNextNode() != BB) {
860 Modified = true;
861 BB->moveAfter(LastBlock);
862 }
863 LastBlock = BB;
864 }
865
866 return Modified;
867}
868
870 const DataLayout &DL = F.getDataLayout();
871 return new AllocaInst(Type, DL.getAllocaAddrSpace(), nullptr, "reg",
872 F.begin()->getFirstInsertionPt());
873}
874
875Value *
877 const DenseMap<BasicBlock *, ConstantInt *> &TargetToValue) {
878 auto *T = BB->getTerminator();
879 if (isa<ReturnInst>(T))
880 return nullptr;
881 if (auto *BI = dyn_cast<UncondBrInst>(T))
882 return TargetToValue.lookup(BI->getSuccessor());
883
884 IRBuilder<> Builder(BB);
885 Builder.SetInsertPoint(T);
886
887 if (auto *BI = dyn_cast<CondBrInst>(T)) {
888 Value *LHS = TargetToValue.lookup(BI->getSuccessor(0));
889 Value *RHS = TargetToValue.lookup(BI->getSuccessor(1));
890
891 if (LHS == nullptr || RHS == nullptr)
892 return LHS == nullptr ? RHS : LHS;
893 return Builder.CreateSelect(BI->getCondition(), LHS, RHS);
894 }
895
896 if (auto *SI = dyn_cast<SwitchInst>(T)) {
897 Value *Condition = SI->getCondition();
898 // The default destination acts as the fallback value of the select chain.
899 Value *Result = TargetToValue.lookup(SI->getDefaultDest());
900 for (const auto &Case : SI->cases()) {
901 Value *CaseValue = TargetToValue.lookup(Case.getCaseSuccessor());
902 // Successors that are internal to the region have no exit value.
903 if (CaseValue == nullptr)
904 continue;
905 // The first known exit value becomes the base of the select chain.
906 if (Result == nullptr) {
907 Result = CaseValue;
908 continue;
909 }
910 Value *Cmp = Builder.CreateICmpEQ(Condition, Case.getCaseValue());
911 Result = Builder.CreateSelect(Cmp, CaseValue, Result);
912 }
913 return Result;
914 }
915
916 llvm_unreachable("Unhandled terminator type.");
917}
918
920 MachineInstr *MaybeDef = MRI.getVRegDef(Reg);
921 if (MaybeDef && MaybeDef->getOpcode() == SPIRV::ASSIGN_TYPE)
922 MaybeDef = MRI.getVRegDef(MaybeDef->getOperand(1).getReg());
923 return MaybeDef;
924}
925
926static bool getVacantFunctionName(Module &M, std::string &Name) {
927 // It's a bit of paranoia, but still we don't want to have even a chance that
928 // the loop will work for too long.
929 constexpr unsigned MaxIters = 1024;
930 for (unsigned I = 0; I < MaxIters; ++I) {
931 std::string OrdName = Name + Twine(I).str();
932 if (!M.getFunction(OrdName)) {
933 Name = std::move(OrdName);
934 return true;
935 }
936 }
937 return false;
938}
939
940// Assign SPIR-V type to the register. If the register has no valid assigned
941// class, set register LLT type and class according to the SPIR-V type.
944 const MachineFunction &MF, bool Force) {
945 GR->assignSPIRVTypeToVReg(SpvType, Reg, MF);
946 if (!MRI->getRegClassOrNull(Reg) || Force) {
947 MRI->setRegClass(Reg, GR->getRegClass(SpvType));
948 LLT RegType = GR->getRegType(SpvType);
949 if (Force || !MRI->getType(Reg).isValid())
950 MRI->setType(Reg, RegType);
951 }
952}
953
954// Create a SPIR-V type, assign SPIR-V type to the register. If the register has
955// no valid assigned class, set register LLT type and class according to the
956// SPIR-V type.
958 MachineIRBuilder &MIRBuilder,
959 SPIRV::AccessQualifier::AccessQualifier AccessQual,
960 bool EmitIR, bool Force) {
962 GR->getOrCreateSPIRVType(Ty, MIRBuilder, AccessQual, EmitIR),
963 GR, MIRBuilder.getMRI(), MIRBuilder.getMF(), Force);
964}
965
966// Create a virtual register and assign SPIR-V type to the register. Set
967// register LLT type and class according to the SPIR-V type.
970 const MachineFunction &MF) {
971 Register Reg = MRI->createVirtualRegister(GR->getRegClass(SpvType));
972 MRI->setType(Reg, GR->getRegType(SpvType));
973 GR->assignSPIRVTypeToVReg(SpvType, Reg, MF);
974 return Reg;
975}
976
977// Create a virtual register and assign SPIR-V type to the register. Set
978// register LLT type and class according to the SPIR-V type.
980 MachineIRBuilder &MIRBuilder) {
981 return createVirtualRegister(SpvType, GR, MIRBuilder.getMRI(),
982 MIRBuilder.getMF());
983}
984
985// Create a SPIR-V type, virtual register and assign SPIR-V type to the
986// register. Set register LLT type and class according to the SPIR-V type.
988 const Type *Ty, SPIRVGlobalRegistry *GR, MachineIRBuilder &MIRBuilder,
989 SPIRV::AccessQualifier::AccessQualifier AccessQual, bool EmitIR) {
991 GR->getOrCreateSPIRVType(Ty, MIRBuilder, AccessQual, EmitIR), GR,
992 MIRBuilder);
993}
994
996 Value *Arg, Value *Arg2, ArrayRef<Constant *> Imms,
997 IRBuilder<> &B) {
999 Args.push_back(Arg2);
1000 Args.push_back(buildMD(Arg));
1001 llvm::append_range(Args, Imms);
1002 return B.CreateIntrinsicWithoutFolding(IntrID, {Types}, Args);
1003}
1004
1005// Return true if there is an opaque pointer type nested in the argument.
1006bool isNestedPointer(const Type *Ty) {
1007 if (Ty->isPtrOrPtrVectorTy())
1008 return true;
1009 if (const FunctionType *RefTy = dyn_cast<FunctionType>(Ty)) {
1010 if (isNestedPointer(RefTy->getReturnType()))
1011 return true;
1012 for (const Type *ArgTy : RefTy->params())
1013 if (isNestedPointer(ArgTy))
1014 return true;
1015 return false;
1016 }
1017 if (const ArrayType *RefTy = dyn_cast<ArrayType>(Ty))
1018 return isNestedPointer(RefTy->getElementType());
1019 return false;
1020}
1021
1022bool isSpvIntrinsic(const Value *Arg) {
1023 if (const auto *II = dyn_cast<IntrinsicInst>(Arg))
1024 if (Function *F = II->getCalledFunction())
1025 if (F->getName().starts_with("llvm.spv."))
1026 return true;
1027 return false;
1028}
1029
1030// Function to create continued instructions for SPV_INTEL_long_composites
1031// extension
1032SmallVector<MachineInstr *, 4>
1034 unsigned MinWC, unsigned ContinuedOpcode,
1035 ArrayRef<Register> Args, Register ReturnRegister,
1036 Register TypeID) {
1037
1038 SmallVector<MachineInstr *, 4> Instructions;
1039 constexpr unsigned MaxWordCount = UINT16_MAX;
1040 const size_t NumElements = Args.size();
1041 size_t MaxNumElements = MaxWordCount - MinWC;
1042 size_t SPIRVStructNumElements = NumElements;
1043
1044 if (NumElements > MaxNumElements) {
1045 // Do adjustments for continued instructions which always had only one
1046 // minumum word count.
1047 SPIRVStructNumElements = MaxNumElements;
1048 MaxNumElements = MaxWordCount - 1;
1049 }
1050
1051 auto MIB =
1052 MIRBuilder.buildInstr(Opcode).addDef(ReturnRegister).addUse(TypeID);
1053
1054 for (size_t I = 0; I < SPIRVStructNumElements; ++I)
1055 MIB.addUse(Args[I]);
1056
1057 Instructions.push_back(MIB.getInstr());
1058
1059 for (size_t I = SPIRVStructNumElements; I < NumElements;
1060 I += MaxNumElements) {
1061 auto MIB = MIRBuilder.buildInstr(ContinuedOpcode);
1062 for (size_t J = I; J < std::min(I + MaxNumElements, NumElements); ++J)
1063 MIB.addUse(Args[J]);
1064 Instructions.push_back(MIB.getInstr());
1065 }
1066 return Instructions;
1067}
1068
1069SmallVector<unsigned, 1>
1071 unsigned LC = SPIRV::LoopControl::None;
1072 // Currently used only to store PartialCount value. Later when other
1073 // LoopControls are added - this map should be sorted before making
1074 // them loop_merge operands to satisfy 3.23. Loop Control requirements.
1075 std::vector<std::pair<unsigned, unsigned>> MaskToValueMap;
1076 if (findOptionMDForLoopID(LoopMD, "llvm.loop.unroll.disable")) {
1077 LC |= SPIRV::LoopControl::DontUnroll;
1078 } else {
1079 if (findOptionMDForLoopID(LoopMD, "llvm.loop.unroll.enable") ||
1080 findOptionMDForLoopID(LoopMD, "llvm.loop.unroll.full")) {
1081 LC |= SPIRV::LoopControl::Unroll;
1082 }
1083 if (MDNode *CountMD =
1084 findOptionMDForLoopID(LoopMD, "llvm.loop.unroll.count")) {
1085 if (auto *CI =
1086 mdconst::extract_or_null<ConstantInt>(CountMD->getOperand(1))) {
1087 unsigned Count = CI->getZExtValue();
1088 if (Count != 1) {
1089 LC |= SPIRV::LoopControl::PartialCount;
1090 MaskToValueMap.emplace_back(
1091 std::make_pair(SPIRV::LoopControl::PartialCount, Count));
1092 }
1093 }
1094 }
1095 }
1096 SmallVector<unsigned, 1> Result = {LC};
1097 for (auto &[Mask, Val] : MaskToValueMap)
1098 Result.push_back(Val);
1099 return Result;
1100}
1101
1105
1106const std::set<unsigned> &getTypeFoldingSupportedOpcodes() {
1107 // clang-format off
1108 static const std::set<unsigned> TypeFoldingSupportingOpcs = {
1109 TargetOpcode::G_ADD,
1110 TargetOpcode::G_FADD,
1111 TargetOpcode::G_STRICT_FADD,
1112 TargetOpcode::G_SUB,
1113 TargetOpcode::G_FSUB,
1114 TargetOpcode::G_STRICT_FSUB,
1115 TargetOpcode::G_MUL,
1116 TargetOpcode::G_FMUL,
1117 TargetOpcode::G_STRICT_FMUL,
1118 TargetOpcode::G_SDIV,
1119 TargetOpcode::G_UDIV,
1120 TargetOpcode::G_FDIV,
1121 TargetOpcode::G_STRICT_FDIV,
1122 TargetOpcode::G_SREM,
1123 TargetOpcode::G_UREM,
1124 TargetOpcode::G_FREM,
1125 TargetOpcode::G_STRICT_FREM,
1126 TargetOpcode::G_FNEG,
1127 TargetOpcode::G_CONSTANT,
1128 TargetOpcode::G_FCONSTANT,
1129 TargetOpcode::G_AND,
1130 TargetOpcode::G_OR,
1131 TargetOpcode::G_XOR,
1132 TargetOpcode::G_SHL,
1133 TargetOpcode::G_ASHR,
1134 TargetOpcode::G_LSHR,
1135 TargetOpcode::G_SELECT,
1136 TargetOpcode::G_EXTRACT_VECTOR_ELT,
1137 };
1138 // clang-format on
1139 return TypeFoldingSupportingOpcs;
1140}
1141
1142bool isTypeFoldingSupported(unsigned Opcode) {
1143 return getTypeFoldingSupportedOpcodes().count(Opcode) > 0;
1144}
1145
1146// Traversing [g]MIR accounting for pseudo-instructions.
1148 return (Def->getOpcode() == SPIRV::ASSIGN_TYPE ||
1149 Def->getOpcode() == TargetOpcode::COPY)
1150 ? MRI->getVRegDef(Def->getOperand(1).getReg())
1151 : Def;
1152}
1153
1155 if (MachineInstr *Def = MRI->getVRegDef(MO.getReg()))
1156 return passCopy(Def, MRI);
1157 return nullptr;
1158}
1159
1161 if (MachineInstr *Def = getDef(MO, MRI)) {
1162 if (Def->getOpcode() == TargetOpcode::G_CONSTANT ||
1163 Def->getOpcode() == SPIRV::OpConstantI)
1164 return Def;
1165 }
1166 return nullptr;
1167}
1168
1169int64_t foldImm(const MachineOperand &MO, const MachineRegisterInfo *MRI) {
1170 if (MachineInstr *Def = getImm(MO, MRI)) {
1171 if (Def->getOpcode() == SPIRV::OpConstantI)
1172 return Def->getOperand(2).getImm();
1173 if (Def->getOpcode() == TargetOpcode::G_CONSTANT)
1174 return Def->getOperand(1).getCImm()->getZExtValue();
1175 }
1176 llvm_unreachable("Unexpected integer constant pattern");
1177}
1178
1180 const MachineInstr *ResType) {
1181 return foldImm(ResType->getOperand(2), MRI);
1182}
1183
1184bool matchPeeledArrayPattern(const StructType *Ty, Type *&OriginalElementType,
1185 uint64_t &TotalSize) {
1186 // An array of N padded structs is represented as {[N-1 x <{T, pad}>], T}.
1187 if (Ty->getStructNumElements() != 2)
1188 return false;
1189
1190 Type *FirstElement = Ty->getStructElementType(0);
1191 Type *SecondElement = Ty->getStructElementType(1);
1192
1193 if (!FirstElement->isArrayTy())
1194 return false;
1195
1196 Type *ArrayElementType = FirstElement->getArrayElementType();
1197 if (!ArrayElementType->isStructTy() ||
1198 ArrayElementType->getStructNumElements() != 2)
1199 return false;
1200
1201 Type *T_in_struct = ArrayElementType->getStructElementType(0);
1202 if (T_in_struct != SecondElement)
1203 return false;
1204
1205 auto *Padding_in_struct =
1206 dyn_cast<TargetExtType>(ArrayElementType->getStructElementType(1));
1207 if (!Padding_in_struct || Padding_in_struct->getName() != "spirv.Padding")
1208 return false;
1209
1210 const uint64_t ArraySize = FirstElement->getArrayNumElements();
1211 TotalSize = ArraySize + 1;
1212 OriginalElementType = ArrayElementType;
1213 return true;
1214}
1215
1217 if (!Ty->isStructTy())
1218 return Ty;
1219
1220 auto *STy = cast<StructType>(Ty);
1221 Type *OriginalElementType = nullptr;
1222 uint64_t TotalSize = 0;
1223 if (matchPeeledArrayPattern(STy, OriginalElementType, TotalSize)) {
1224 Type *ResultTy = ArrayType::get(
1225 reconstitutePeeledArrayType(OriginalElementType), TotalSize);
1226 return ResultTy;
1227 }
1228
1229 SmallVector<Type *, 4> NewElementTypes;
1230 bool Changed = false;
1231 for (Type *ElementTy : STy->elements()) {
1232 Type *NewElementTy = reconstitutePeeledArrayType(ElementTy);
1233 if (NewElementTy != ElementTy)
1234 Changed = true;
1235 NewElementTypes.push_back(NewElementTy);
1236 }
1237
1238 if (!Changed)
1239 return Ty;
1240
1241 Type *ResultTy;
1242 if (STy->isLiteral())
1243 ResultTy =
1244 StructType::get(STy->getContext(), NewElementTypes, STy->isPacked());
1245 else {
1246 auto *NewTy = StructType::create(STy->getContext(), STy->getName());
1247 NewTy->setBody(NewElementTypes, STy->isPacked());
1248 ResultTy = NewTy;
1249 }
1250 return ResultTy;
1251}
1252
1253std::optional<SPIRV::LinkageType::LinkageType>
1255 if (GV.hasLocalLinkage())
1256 return std::nullopt;
1257
1258 if (GV.isDeclarationForLinker()) {
1259 if (const auto *GVar = dyn_cast<GlobalVariable>(&GV)) {
1260 auto SC = addressSpaceToStorageClass(GVar->getAddressSpace(), ST);
1261 // Interface variables must not get Import linkage.
1262 if (SC == SPIRV::StorageClass::Input ||
1263 SC == SPIRV::StorageClass::Output ||
1264 SC == SPIRV::StorageClass::PushConstant)
1265 return std::nullopt;
1266 // Shaders have no linker, so module-internal storage
1267 // (e.g. HLSL groupshared) can't be imported
1268 if (ST.isShader() && (SC == SPIRV::StorageClass::Workgroup ||
1269 SC == SPIRV::StorageClass::Private))
1270 return std::nullopt;
1271 }
1272 return SPIRV::LinkageType::Import;
1273 }
1274
1275 if (GV.hasHiddenVisibility())
1276 return std::nullopt;
1277
1278 if (GV.hasLinkOnceODRLinkage() &&
1279 ST.canUseExtension(SPIRV::Extension::SPV_KHR_linkonce_odr))
1280 return SPIRV::LinkageType::LinkOnceODR;
1281
1282 if (GV.hasWeakLinkage() &&
1283 ST.canUseExtension(SPIRV::Extension::SPV_AMD_weak_linkage))
1284 return SPIRV::LinkageType::WeakAMD;
1285
1286 return SPIRV::LinkageType::Export;
1287}
1288
1290 std::string ServiceFunName = SPIRV_BACKEND_SERVICE_FUN_NAME;
1291 if (!getVacantFunctionName(M, ServiceFunName))
1293 "cannot allocate a name for the internal service function");
1294 if (Function *SF = M.getFunction(ServiceFunName)) {
1295 if (SF->getInstructionCount() > 0)
1297 "Unexpected combination of global variables and function pointers");
1298 return SF;
1299 }
1301 FunctionType::get(Type::getVoidTy(M.getContext()), {}, false),
1302 GlobalValue::PrivateLinkage, ServiceFunName, M);
1304 return SF;
1305}
1306
1307} // namespace llvm
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
MachineBasicBlock & MBB
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
Declares convenience wrapper classes for interpreting MachineInstr instances as specific generic oper...
const HexagonInstrInfo * TII
IRTranslator LLVM IR MI
#define F(x, y, z)
Definition MD5.cpp:54
#define I(x, y, z)
Definition MD5.cpp:57
This file declares the MachineIRBuilder class.
Register Reg
Type::TypeID TypeID
#define T
uint64_t IntrinsicInst * II
#define P(N)
#define SPIRV_BACKEND_SERVICE_FUN_NAME
Definition SPIRVUtils.h:543
This file contains some templates that are useful if you are working with the STL at all.
Value * RHS
Value * LHS
Class for arbitrary precision integers.
Definition APInt.h:78
an instruction to allocate memory on the stack
Represent a constant reference to an array (0 or more elements consecutively in memory),...
Definition ArrayRef.h:40
Class to represent array types.
static LLVM_ABI ArrayType * get(Type *ElementType, uint64_t NumElements)
This static method is the primary way to construct an ArrayType.
LLVM Basic Block Representation.
Definition BasicBlock.h:62
LLVM_ABI void moveAfter(BasicBlock *MovePos)
Unlink this basic block from its current function and insert it right after MovePos in the function M...
const Instruction & front() const
Definition BasicBlock.h:469
const Instruction * getTerminator() const LLVM_READONLY
Returns the terminator instruction; assumes that the block is well-formed.
Definition BasicBlock.h:237
Base class for all callable instructions (InvokeInst and CallInst) Holds everything related to callin...
Value * getCalledOperand() const
FunctionType * getFunctionType() const
This class represents a function call, abstracting a target machine's calling convention.
An array constant whose element type is a simple 1/2/4/8-byte integer, bytes or float/double,...
Definition Constants.h:865
StringRef getAsCString() const
If this array is isCString(), then this method returns the array (without the trailing null byte) as ...
Definition Constants.h:838
This is the shared class of boolean and integer constants.
Definition Constants.h:87
uint64_t getZExtValue() const
Return the constant as a 64-bit unsigned integer value after it has been zero extended as appropriate...
Definition Constants.h:168
A parsed version of the target data layout string in and methods for querying it.
Definition DataLayout.h:64
ValueT lookup(const_arg_type_t< KeyT > Val) const
Return the entry for the specified key, or a default constructed value if no such entry exists.
Definition DenseMap.h:250
unsigned size() const
Definition DenseMap.h:172
bool dominates(const DomTreeNodeBase< NodeT > *A, const DomTreeNodeBase< NodeT > *B) const
dominates - Returns true iff A dominates B.
Lightweight error class with error context and mandatory checking.
Definition Error.h:159
Class to represent function types.
ArrayRef< Type * > params() const
bool isVarArg() const
Type * getReturnType() const
static LLVM_ABI FunctionType * get(Type *Result, ArrayRef< Type * > Params, bool isVarArg)
This static method is the primary way of constructing a FunctionType.
void addFnAttr(Attribute::AttrKind Kind)
Add function attributes to this function.
Definition Function.cpp:637
static Function * Create(FunctionType *Ty, LinkageTypes Linkage, unsigned AddrSpace, const Twine &N="", Module *M=nullptr)
Definition Function.h:168
const Function & getFunction() const
Definition Function.h:166
bool hasLocalLinkage() const
bool hasHiddenVisibility() const
bool isDeclarationForLinker() const
bool hasWeakLinkage() const
bool hasLinkOnceODRLinkage() const
@ PrivateLinkage
Like Internal, but omit from symbol table.
Definition GlobalValue.h:61
This provides a uniform API for creating instructions and inserting them into a basic block: either a...
Definition IRBuilder.h:2893
LLVM_ABI const Module * getModule() const
Return the module owning the function this instruction belongs to or nullptr it the function does not...
MDNode * getMetadata(unsigned KindID) const
Get the metadata of given kind attached to this Instruction.
constexpr bool isValid() const
This is an important class for using LLVM in a threaded context.
Definition LLVMContext.h:68
Represents a single loop in the control flow graph.
Definition LoopInfo.h:40
Instances of this class represent a single low-level machine instruction.
Definition MCInst.h:188
void addOperand(const MCOperand Op)
Definition MCInst.h:215
static MCOperand createImm(int64_t Val)
Definition MCInst.h:145
Metadata node.
Definition Metadata.h:1069
const MDOperand & getOperand(unsigned I) const
Definition Metadata.h:1426
unsigned getNumOperands() const
Return number of MDNode operands.
Definition Metadata.h:1432
A single uniqued string.
Definition Metadata.h:722
MachineInstrBundleIterator< MachineInstr > iterator
const MachineBasicBlock & front() const
Helper class to build MachineInstr.
MachineInstrBuilder buildInstr(unsigned Opcode)
Build and insert <empty> = Opcode <empty>.
MachineFunction & getMF()
Getter for the function we currently build.
MachineRegisterInfo * getMRI()
Getter for MRI.
const MachineInstrBuilder & addUse(Register RegNo, RegState Flags={}, unsigned SubReg=0) const
Add a virtual register use operand.
const MachineInstrBuilder & addImm(int64_t Val) const
Add a new immediate operand.
const MachineInstrBuilder & addDef(Register RegNo, RegState Flags={}, unsigned SubReg=0) const
Add a virtual register definition 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(AsmPrinterFlagTy Flag)
Set a flag for the AsmPrinter.
const MachineOperand & getOperand(unsigned i) const
MachineOperand class - Representation of each machine instruction operand.
Register getReg() const
getReg - Returns the register number.
MachineRegisterInfo - Keep track of information for virtual and physical registers,...
LLVM_ABI MachineInstr * getVRegDef(Register Reg) const
getVRegDef - Return the machine instr that defines the specified virtual register or null if none is ...
LLVM_ABI Register createVirtualRegister(const TargetRegisterClass *RegClass, StringRef Name="")
createVirtualRegister - Create and return a new virtual register in the function with the specified r...
LLT getType(Register Reg) const
Get the low-level type of Reg or LLT{} if Reg is not a generic (target independent) virtual register.
LLVM_ABI void setType(Register VReg, LLT Ty)
Set the low-level type of VReg to Ty.
LLVM_ABI void setRegClass(Register Reg, const TargetRegisterClass *RC)
setRegClass - Set the register class of the specified virtual register.
const TargetRegisterClass * getRegClassOrNull(Register Reg) const
Return the register class of Reg, or null if Reg has not been assigned a register class yet.
A Module instance is used to store all the information related to an LLVM module.
Definition Module.h:67
NamedMDNode * getNamedMetadata(StringRef Name) const
Return the first NamedMDNode in the module with the specified name.
Definition Module.cpp:301
A tuple of MDNodes.
Definition Metadata.h:1755
op_iterator op_end()
Definition Metadata.h:1844
iterator_range< op_iterator > operands()
Definition Metadata.h:1851
size_t GetNodeRank(BasicBlock *BB) const
void partialOrderVisit(BasicBlock &Start, std::function< bool(BasicBlock *)> Op)
bool compare(const BasicBlock *LHS, const BasicBlock *RHS) const
Wrapper class representing virtual and physical registers.
Definition Register.h:20
void assignSPIRVTypeToVReg(SPIRVTypeInst Type, Register VReg, const MachineFunction &MF)
const TargetRegisterClass * getRegClass(SPIRVTypeInst SpvType) const
SPIRVTypeInst getOrCreateSPIRVIntegerType(unsigned BitWidth, MachineIRBuilder &MIRBuilder)
LLT getRegType(SPIRVTypeInst SpvType) const
SPIRVTypeInst getOrCreateSPIRVType(const Type *Type, MachineInstr &I, SPIRV::AccessQualifier::AccessQualifier AQ, bool EmitIR)
Register buildConstantInt(uint64_t Val, MachineIRBuilder &MIRBuilder, SPIRVTypeInst SpvType, bool EmitIR, bool ZeroAsNull=true)
bool canUseExtension(SPIRV::Extension::Extension E) const
std::pair< iterator, bool > insert(PtrType Ptr)
Inserts Ptr if and only if there is no element in the container equal to Ptr.
SmallPtrSet - This class implements a set which is optimized for holding SmallSize or less elements.
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
Represent a constant reference to a string, i.e.
Definition StringRef.h:56
std::string str() const
Get the contents as an std::string.
Definition StringRef.h:222
constexpr bool empty() const
Check if the string is empty.
Definition StringRef.h:141
Class to represent struct types.
static LLVM_ABI StructType * get(LLVMContext &Context, ArrayRef< Type * > Elements, bool isPacked=false)
This static method is the primary way to create a literal StructType.
Definition Type.cpp:477
static LLVM_ABI StructType * create(LLVMContext &Context, StringRef Name)
This creates an identified struct.
Definition Type.cpp:683
Class to represent target extensions types, which are generally unintrospectable from target-independ...
Target - Wrapper for Target specific information.
Triple - Helper class for working with autoconf configuration names.
Definition Triple.h:48
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
Definition Twine.h:82
LLVM_ABI std::string str() const
Return the twine contents as a std::string.
Definition Twine.cpp:17
The instances of the Type class are immutable: once they are created, they are never changed.
Definition Type.h:46
static LLVM_ABI IntegerType * getInt64Ty(LLVMContext &C)
Definition Type.cpp:310
LLVM_ABI Type * getStructElementType(unsigned N) const
bool isArrayTy() const
True if this is an instance of ArrayType.
Definition Type.h:279
static LLVM_ABI IntegerType * getInt32Ty(LLVMContext &C)
Definition Type.cpp:309
Type * getArrayElementType() const
Definition Type.h:425
LLVM_ABI unsigned getStructNumElements() const
LLVM_ABI uint64_t getArrayNumElements() const
static LLVM_ABI Type * getVoidTy(LLVMContext &C)
Definition Type.cpp:282
static LLVM_ABI IntegerType * getInt8Ty(LLVMContext &C)
Definition Type.cpp:307
bool isStructTy() const
True if this is an instance of StructType.
Definition Type.h:276
static LLVM_ABI IntegerType * getInt16Ty(LLVMContext &C)
Definition Type.cpp:308
static LLVM_ABI IntegerType * getIntNTy(LLVMContext &C, unsigned N)
Definition Type.cpp:313
static LLVM_ABI Type * getDoubleTy(LLVMContext &C)
Definition Type.cpp:287
static LLVM_ABI Type * getFloatTy(LLVMContext &C)
Definition Type.cpp:286
static LLVM_ABI Type * getHalfTy(LLVMContext &C)
Definition Type.cpp:284
Value * getOperand(unsigned i) const
Definition User.h:207
unsigned getNumOperands() const
Definition User.h:229
LLVM Value Representation.
Definition Value.h:75
NodeTy * getNextNode()
Get the next node, or nullptr for the list tail.
Definition ilist_node.h:348
Changed
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
@ SPIR_KERNEL
Used for SPIR kernel functions.
@ BasicBlock
Various leaf nodes.
Definition ISDOpcodes.h:81
static StringRef extractAsmConstraintsFromMetadata(NamedMDNode *NMD, StringRef Constraints, StringRef Name)
bool isPipeOrAddressSpaceCastBuiltin(StringRef Name)
Returns true if Name is a pipe or address-space-cast OpenCL builtin.
static MDNode * findNamedMDOperand(NamedMDNode *NMD, StringRef Name)
FunctionType * getOriginalFunctionType(const Function &F)
static std::optional< StringRef > getMutatedCallsiteKey(const CallBase &CB)
static FunctionType * extractFunctionTypeFromMetadata(NamedMDNode *NMD, FunctionType *FTy, StringRef Name)
StringRef getOriginalAsmConstraints(const CallBase &CB)
@ SingleThread
Synchronized with respect to signal handlers executing in the same thread.
Definition LLVMContext.h:55
@ System
Synchronized with respect to all concurrently executing threads.
Definition LLVMContext.h:58
std::enable_if_t< detail::IsValidPointer< X, Y >::value, X * > extract_or_null(Y &&MD)
Extract a Value from Metadata, allowing null.
Definition Metadata.h:683
std::enable_if_t< detail::IsValidPointer< X, Y >::value, X * > dyn_extract(Y &&MD)
Extract a Value from Metadata, if any.
Definition Metadata.h:696
This is an optimization pass for GlobalISel generic memory operations.
std::string getStringImm(const MachineInstr &MI, unsigned StartIndex)
void addStringImm(StringRef Str, MCInst &Inst)
MachineBasicBlock::iterator getOpVariableMBBIt(MachineFunction &MF)
int64_t getIConstValSext(Register ConstReg, const MachineRegisterInfo *MRI)
bool isTypedPointerWrapper(const TargetExtType *ExtTy)
Definition SPIRVUtils.h:421
MachineInstrBuilder BuildMI(MachineFunction &MF, const MIMetadata &MIMD, const MCInstrDesc &MCID)
Builder interface. Specify how to create the initial instruction itself.
AtomicScope
Target-neutral memory synchronization scopes.
Definition AtomicScope.h:23
bool isTypeFoldingSupported(unsigned Opcode)
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
Definition Casting.h:643
MachineInstr * getDef(const MachineOperand &MO, const MachineRegisterInfo *MRI)
void addNumImm(const APInt &Imm, MachineInstrBuilder &MIB)
auto successors(const MachineBasicBlock *BB)
CallInst * buildIntrWithMD(Intrinsic::ID IntrID, ArrayRef< Type * > Types, Value *Arg, Value *Arg2, ArrayRef< Constant * > Imms, IRBuilder<> &B)
bool matchPeeledArrayPattern(const StructType *Ty, Type *&OriginalElementType, uint64_t &TotalSize)
Register createVirtualRegister(SPIRVTypeInst SpvType, SPIRVGlobalRegistry *GR, MachineRegisterInfo *MRI, const MachineFunction &MF)
void append_range(Container &C, Range &&R)
Wrapper function to append range R to container C.
Definition STLExtras.h:2208
unsigned getArrayComponentCount(const MachineRegisterInfo *MRI, const MachineInstr *ResType)
bool sortBlocks(Function &F)
AllocaInst * createVariable(Function &F, Type *Type)
static bool getVacantFunctionName(Module &M, std::string &Name)
void buildOpDecorate(Register Reg, MachineIRBuilder &MIRBuilder, SPIRV::Decoration::Decoration Dec, ArrayRef< uint32_t > DecArgs, StringRef StrImm)
SPIRV::Scope::Scope getMemScope(const Triple &TT, LLVMContext &Ctx, SyncScope::ID Id)
uint64_t getIConstVal(Register ConstReg, const MachineRegisterInfo *MRI)
SmallVector< MachineInstr *, 4 > createContinuedInstructions(MachineIRBuilder &MIRBuilder, unsigned Opcode, unsigned MinWC, unsigned ContinuedOpcode, ArrayRef< Register > Args, Register ReturnRegister, Register TypeID)
SPIRV::MemorySemantics::MemorySemantics getMemSemanticsForStorageClass(SPIRV::StorageClass::StorageClass SC)
bool isNestedPointer(const Type *Ty)
Function * getOrCreateBackendServiceFunction(Module &M)
MetadataAsValue * buildMD(Value *Arg)
Definition SPIRVUtils.h:531
std::string getOclOrSpirvBuiltinDemangledName(StringRef Name)
void buildOpName(Register Target, StringRef Name, MachineIRBuilder &MIRBuilder)
static void finishBuildOpDecorate(MachineInstrBuilder &MIB, ArrayRef< uint32_t > DecArgs, StringRef StrImm)
SmallVector< unsigned, 1 > getSpirvLoopControlOperandsFromLoopMetadata(MDNode *LoopMD)
MachineInstr * getImm(const MachineOperand &MO, const MachineRegisterInfo *MRI)
static uint32_t convertCharsToWord(StringRef Str, unsigned i)
void sort(IteratorTy Start, IteratorTy End)
Definition STLExtras.h:1636
std::string getSPIRVStringOperand(const InstType &MI, unsigned StartIndex)
Type * toTypedPointer(Type *Ty)
Definition SPIRVUtils.h:476
ConstantInt * getMDOperandAsConstInt(const MDNode *N, unsigned I)
DEMANGLE_ABI 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,...
constexpr uint32_t Hi_32(uint64_t Value)
Return the high 32 bits of a 64 bit value.
Definition MathExtras.h:151
bool isSpecialOpaqueType(const Type *Ty)
LLVM_ABI void report_fatal_error(Error Err, bool gen_crash_diag=true)
Definition Error.cpp:163
constexpr uint64_t alignTo(uint64_t Size, Align A)
Returns a multiple of A needed to store Size bytes.
Definition Alignment.h:144
void setRegClassType(Register Reg, SPIRVTypeInst SpvType, SPIRVGlobalRegistry *GR, MachineRegisterInfo *MRI, const MachineFunction &MF, bool Force)
MachineBasicBlock::iterator getInsertPtValidEnd(MachineBasicBlock *MBB)
constexpr bool isUInt(uint64_t x)
Checks if an unsigned integer fits into the given bit width.
Definition MathExtras.h:190
static bool isNonMangledOCLBuiltin(StringRef Name)
constexpr uint32_t Lo_32(uint64_t Value)
Return the low 32 bits of a 64 bit value.
Definition MathExtras.h:156
MachineInstr * passCopy(MachineInstr *Def, const MachineRegisterInfo *MRI)
bool isa(const From &Val)
isa<X> - Return true if the parameter to the template is an instance of one of the template type argu...
Definition Casting.h:547
std::optional< SPIRV::LinkageType::LinkageType > getSpirvLinkageTypeFor(const SPIRVSubtarget &ST, const GlobalValue &GV)
bool isEntryPoint(const Function &F)
LLVM_ATTRIBUTE_VISIBILITY_DEFAULT AnalysisKey InnerAnalysisManagerProxy< AnalysisManagerT, IRUnitT, ExtraArgTs... >::Key
const std::set< unsigned > & getTypeFoldingSupportedOpcodes()
SPIRV::StorageClass::StorageClass addressSpaceToStorageClass(unsigned AddrSpace, const SPIRVSubtarget &STI)
AtomicOrdering
Atomic ordering for LLVM's memory model.
constexpr T divideCeil(U Numerator, V Denominator)
Returns the integer ceil(Numerator / Denominator).
Definition MathExtras.h:395
static bool isEnqueueKernelBI(StringRef MangledName)
static bool isKernelQueryBI(StringRef MangledName)
void buildOpSpirvDecorations(Register Reg, MachineIRBuilder &MIRBuilder, const MDNode *GVarMD, const SPIRVSubtarget &ST)
std::string getStringValueFromReg(Register Reg, MachineRegisterInfo &MRI)
RelativeUniformCounterPtr ValuesPtrExpr VTableAddr Count
Definition InstrProf.h:145
int64_t foldImm(const MachineOperand &MO, const MachineRegisterInfo *MRI)
Type * parseBasicTypeName(StringRef &TypeName, LLVMContext &Ctx)
DWARFExpression::Operation Op
MachineInstr * getDefInstrMaybeConstant(Register &ConstReg, const MachineRegisterInfo *MRI)
Value * createExitVariable(BasicBlock *BB, const DenseMap< BasicBlock *, ConstantInt * > &TargetToValue)
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.
Definition Casting.h:559
bool hasBuiltinTypePrefix(StringRef Name)
Type * getMDOperandAsType(const MDNode *N, unsigned I)
void buildOpMemberDecorate(Register Reg, MachineIRBuilder &MIRBuilder, SPIRV::Decoration::Decoration Dec, uint32_t Member, ArrayRef< uint32_t > DecArgs, StringRef StrImm)
auto find_if(R &&Range, UnaryPredicate P)
Provide wrappers to std::find_if which take ranges instead of having to pass begin/end explicitly.
Definition STLExtras.h:1772
std::optional< StringRef > getAtomicScopeIRString(const Triple &T, AtomicScope S, bool IsSingleAddressSpace=false)
Returns the LLVM IR syncscope string that T uses to spell S.
Definition AtomicScope.h:34
auto predecessors(const MachineBasicBlock *BB)
static size_t getPaddedLen(StringRef Str)
bool isSpvIntrinsic(const MachineInstr &MI, Intrinsic::ID IntrinsicID)
MachineInstr * getVRegDef(MachineRegisterInfo &MRI, Register Reg)
Type * reconstitutePeeledArrayType(Type *Ty)
SPIRV::MemorySemantics::MemorySemantics getMemSemantics(AtomicOrdering Ord)
LLVM_ABI MDNode * findOptionMDForLoopID(MDNode *LoopID, StringRef Name)
Find and return the loop attribute node for the attribute Name in LoopID.
#define N