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
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::Generic:
426 return SPIRV::MemorySemantics::MemorySemantics(
427 SPIRV::MemorySemantics::WorkgroupMemory |
428 SPIRV::MemorySemantics::CrossWorkgroupMemory);
429 case SPIRV::StorageClass::AtomicCounter:
430 return SPIRV::MemorySemantics::AtomicCounterMemory;
431 case SPIRV::StorageClass::Image:
432 return SPIRV::MemorySemantics::ImageMemory;
433 default:
434 return SPIRV::MemorySemantics::None;
435 }
436}
437
438SPIRV::MemorySemantics::MemorySemantics getMemSemantics(AtomicOrdering Ord) {
439 switch (Ord) {
441 return SPIRV::MemorySemantics::Acquire;
443 return SPIRV::MemorySemantics::Release;
445 return SPIRV::MemorySemantics::AcquireRelease;
447 return SPIRV::MemorySemantics::SequentiallyConsistent;
451 return SPIRV::MemorySemantics::None;
452 }
453 llvm_unreachable(nullptr);
454}
455
457 uint32_t StorageClassSem) {
458 bool DropStorageClass =
459 TT.isVulkanOS() &&
460 OrderSem == static_cast<uint32_t>(SPIRV::MemorySemantics::None);
461 return OrderSem | (DropStorageClass ? 0 : StorageClassSem);
462}
463
464SPIRV::Scope::Scope getMemScope(const Triple &TT, LLVMContext &Ctx,
465 SyncScope::ID Id) {
466 // Named by
467 // https://registry.khronos.org/SPIR-V/specs/unified1/SPIRV.html#_scope_id.
468 // We don't need aliases for Invocation and CrossDevice, as we already have
469 // them covered by "singlethread" and "" strings respectively (see
470 // implementation of LLVMContext::LLVMContext()).
471 auto ScopeID = [&](AtomicScope Scope) {
472 return Ctx.getOrInsertSyncScopeID(*getAtomicScopeIRString(TT, Scope));
473 };
474 static const llvm::SyncScope::ID SubGroup = ScopeID(AtomicScope::Wavefront);
475 static const llvm::SyncScope::ID WorkGroup = ScopeID(AtomicScope::Workgroup);
476 static const llvm::SyncScope::ID Device = ScopeID(AtomicScope::Device);
477
479 return SPIRV::Scope::Invocation;
480 else if (Id == llvm::SyncScope::System)
481 return SPIRV::Scope::CrossDevice;
482 else if (Id == SubGroup)
483 return SPIRV::Scope::Subgroup;
484 else if (Id == WorkGroup)
485 return SPIRV::Scope::Workgroup;
486 else if (Id == Device)
487 return SPIRV::Scope::Device;
488 return SPIRV::Scope::CrossDevice;
489}
490
492 const MachineRegisterInfo *MRI) {
493 MachineInstr *MI = MRI->getVRegDef(ConstReg);
494 MachineInstr *ConstInstr =
495 MI->getOpcode() == SPIRV::G_TRUNC || MI->getOpcode() == SPIRV::G_ZEXT
496 ? MRI->getVRegDef(MI->getOperand(1).getReg())
497 : MI;
498 if (auto *GI = dyn_cast<GIntrinsic>(ConstInstr)) {
499 if (GI->is(Intrinsic::spv_track_constant)) {
500 ConstReg = ConstInstr->getOperand(2).getReg();
501 return MRI->getVRegDef(ConstReg);
502 }
503 } else if (ConstInstr->getOpcode() == SPIRV::ASSIGN_TYPE) {
504 ConstReg = ConstInstr->getOperand(1).getReg();
505 return MRI->getVRegDef(ConstReg);
506 } else if (ConstInstr->getOpcode() == TargetOpcode::G_CONSTANT ||
507 ConstInstr->getOpcode() == TargetOpcode::G_FCONSTANT) {
508 ConstReg = ConstInstr->getOperand(0).getReg();
509 return ConstInstr;
510 }
511 return MRI->getVRegDef(ConstReg);
512}
513
515 const MachineInstr *MI = getDefInstrMaybeConstant(ConstReg, MRI);
516 assert(MI && MI->getOpcode() == TargetOpcode::G_CONSTANT);
517 return MI->getOperand(1).getCImm()->getValue().getZExtValue();
518}
519
520int64_t getIConstValSext(Register ConstReg, const MachineRegisterInfo *MRI) {
521 const MachineInstr *MI = getDefInstrMaybeConstant(ConstReg, MRI);
522 assert(MI && MI->getOpcode() == TargetOpcode::G_CONSTANT);
523 return MI->getOperand(1).getCImm()->getSExtValue();
524}
525
526bool isSpvIntrinsic(const MachineInstr &MI, Intrinsic::ID IntrinsicID) {
527 if (const auto *GI = dyn_cast<GIntrinsic>(&MI))
528 return GI->is(IntrinsicID);
529 return false;
530}
531
532Type *getMDOperandAsType(const MDNode *N, unsigned I) {
533 Type *ElementTy = cast<ValueAsMetadata>(N->getOperand(I))->getType();
534 return toTypedPointer(ElementTy);
535}
536
538 if (N->getNumOperands() <= I)
539 return nullptr;
540 if (auto *CMeta = dyn_cast<ConstantAsMetadata>(N->getOperand(I)))
541 return dyn_cast<ConstantInt>(CMeta->getValue());
542 return nullptr;
543}
544
545static bool isEnqueueKernelBI(StringRef MangledName) {
546 return MangledName == "__enqueue_kernel_basic" ||
547 MangledName == "__enqueue_kernel_basic_events" ||
548 MangledName == "__enqueue_kernel_varargs" ||
549 MangledName == "__enqueue_kernel_events_varargs";
550}
551
552static bool isKernelQueryBI(StringRef MangledName) {
553 return MangledName == "__get_kernel_work_group_size_impl" ||
554 MangledName == "__get_kernel_sub_group_count_for_ndrange_impl" ||
555 MangledName == "__get_kernel_max_sub_group_size_for_ndrange_impl" ||
556 MangledName == "__get_kernel_preferred_work_group_size_multiple_impl";
557}
558
560 if (!Name.starts_with("__"))
561 return false;
562
563 return isEnqueueKernelBI(Name) || isKernelQueryBI(Name) ||
565 Name == "__translate_sampler_initializer";
566}
567
569 bool IsNonMangledOCL = isNonMangledOCLBuiltin(Name);
570 bool IsNonMangledSPIRV = Name.starts_with("__spirv_");
571 bool IsNonMangledHLSL = Name.starts_with("__hlsl_");
572 bool IsMangled = Name.starts_with("_Z");
573
574 // Otherwise use simple demangling to return the function name.
575 if (IsNonMangledOCL || IsNonMangledSPIRV || IsNonMangledHLSL || !IsMangled)
576 return Name.str();
577
578 // Try to use the itanium demangler.
579 if (char *DemangledName = itaniumDemangle(Name.data())) {
580 std::string Result = DemangledName;
581 free(DemangledName);
582 return Result;
583 }
584
585 // Autocheck C++, maybe need to do explicit check of the source language.
586 // OpenCL C++ built-ins are declared in cl namespace.
587 // TODO: consider using 'St' abbriviation for cl namespace mangling.
588 // Similar to ::std:: in C++.
589 size_t Start, Len = 0;
590 size_t DemangledNameLenStart = 2;
591 if (Name.starts_with("_ZN")) {
592 // Skip CV and ref qualifiers.
593 size_t NameSpaceStart = Name.find_first_not_of("rVKRO", 3);
594 // All built-ins are in the ::cl:: namespace.
595 if (Name.substr(NameSpaceStart, 11) != "2cl7__spirv")
596 return std::string();
597 DemangledNameLenStart = NameSpaceStart + 11;
598 }
599 Start = Name.find_first_not_of("0123456789", DemangledNameLenStart);
600 bool Error = Name.substr(DemangledNameLenStart, Start - DemangledNameLenStart)
601 .getAsInteger(10, Len);
602 if (Error)
603 return std::string();
604 return Name.substr(Start, Len).str();
605}
606
608 if (Name.starts_with("opencl.") || Name.starts_with("ocl_") ||
609 Name.starts_with("spirv."))
610 return true;
611 return false;
612}
613
614bool isSpecialOpaqueType(const Type *Ty) {
615 if (const TargetExtType *ExtTy = dyn_cast<TargetExtType>(Ty))
616 return isTypedPointerWrapper(ExtTy)
617 ? false
618 : hasBuiltinTypePrefix(ExtTy->getName());
619
620 return false;
621}
622
623bool isEntryPoint(const Function &F) {
624 // OpenCL handling: any function with the SPIR_KERNEL
625 // calling convention will be a potential entry point.
626 if (F.getCallingConv() == CallingConv::SPIR_KERNEL)
627 return true;
628
629 // HLSL handling: special attribute are emitted from the
630 // front-end.
631 if (F.getFnAttribute("hlsl.shader").isValid())
632 return true;
633
634 return false;
635}
636
638 TypeName.consume_front("atomic_");
639 if (TypeName.consume_front("void"))
640 return Type::getVoidTy(Ctx);
641 else if (TypeName.consume_front("bool") || TypeName.consume_front("_Bool"))
642 return Type::getIntNTy(Ctx, 1);
643 else if (TypeName.consume_front("char") ||
644 TypeName.consume_front("signed char") ||
645 TypeName.consume_front("unsigned char") ||
646 TypeName.consume_front("uchar"))
647 return Type::getInt8Ty(Ctx);
648 else if (TypeName.consume_front("short") ||
649 TypeName.consume_front("signed short") ||
650 TypeName.consume_front("unsigned short") ||
651 TypeName.consume_front("ushort"))
652 return Type::getInt16Ty(Ctx);
653 else if (TypeName.consume_front("int") ||
654 TypeName.consume_front("signed int") ||
655 TypeName.consume_front("unsigned int") ||
656 TypeName.consume_front("uint"))
657 return Type::getInt32Ty(Ctx);
658 else if (TypeName.consume_front("long") ||
659 TypeName.consume_front("signed long") ||
660 TypeName.consume_front("unsigned long") ||
661 TypeName.consume_front("ulong"))
662 return Type::getInt64Ty(Ctx);
663 else if (TypeName.consume_front("half") ||
664 TypeName.consume_front("_Float16") ||
665 TypeName.consume_front("__fp16"))
666 return Type::getHalfTy(Ctx);
667 else if (TypeName.consume_front("float"))
668 return Type::getFloatTy(Ctx);
669 else if (TypeName.consume_front("double"))
670 return Type::getDoubleTy(Ctx);
671
672 // Unable to recognize SPIRV type name
673 return nullptr;
674}
675
676SmallPtrSet<BasicBlock *, 0>
677PartialOrderingVisitor::getReachableFrom(BasicBlock *Start) {
678 std::queue<BasicBlock *> ToVisit;
679 ToVisit.push(Start);
680
681 SmallPtrSet<BasicBlock *, 0> Output;
682 while (ToVisit.size() != 0) {
683 BasicBlock *BB = ToVisit.front();
684 ToVisit.pop();
685
686 if (Output.count(BB) != 0)
687 continue;
688 Output.insert(BB);
689
690 for (BasicBlock *Successor : successors(BB)) {
691 if (DT.dominates(Successor, BB))
692 continue;
693 ToVisit.push(Successor);
694 }
695 }
696
697 return Output;
698}
699
700bool PartialOrderingVisitor::CanBeVisited(BasicBlock *BB) const {
701 for (BasicBlock *P : predecessors(BB)) {
702 // Ignore back-edges.
703 if (DT.dominates(BB, P))
704 continue;
705
706 // One of the predecessor hasn't been visited. Not ready yet.
707 if (BlockToOrder.count(P) == 0)
708 return false;
709
710 // If the block is a loop exit, the loop must be finished before
711 // we can continue.
712 Loop *L = LI.getLoopFor(P);
713 if (L == nullptr || L->contains(BB))
714 continue;
715
716 // SPIR-V requires a single back-edge. And the backend first
717 // step transforms loops into the simplified format. If we have
718 // more than 1 back-edge, something is wrong.
719 assert(L->getNumBackEdges() <= 1);
720
721 // If the loop has no latch, loop's rank won't matter, so we can
722 // proceed.
723 BasicBlock *Latch = L->getLoopLatch();
724 assert(Latch);
725 if (Latch == nullptr)
726 continue;
727
728 // The latch is not ready yet, let's wait.
729 if (BlockToOrder.count(Latch) == 0)
730 return false;
731 }
732
733 return true;
734}
735
737 auto It = BlockToOrder.find(BB);
738 if (It != BlockToOrder.end())
739 return It->second.Rank;
740
741 size_t result = 0;
742 for (BasicBlock *P : predecessors(BB)) {
743 // Ignore back-edges.
744 if (DT.dominates(BB, P))
745 continue;
746
747 auto Iterator = BlockToOrder.end();
748 Loop *L = LI.getLoopFor(P);
749 BasicBlock *Latch = L ? L->getLoopLatch() : nullptr;
750
751 // If the predecessor is either outside a loop, or part of
752 // the same loop, simply take its rank + 1.
753 if (L == nullptr || L->contains(BB) || Latch == nullptr) {
754 Iterator = BlockToOrder.find(P);
755 } else {
756 // Otherwise, take the loop's rank (highest rank in the loop) as base.
757 // Since loops have a single latch, highest rank is easy to find.
758 // If the loop has no latch, then it doesn't matter.
759 Iterator = BlockToOrder.find(Latch);
760 }
761
762 assert(Iterator != BlockToOrder.end());
763 result = std::max(result, Iterator->second.Rank + 1);
764 }
765
766 return result;
767}
768
769size_t PartialOrderingVisitor::visit(BasicBlock *BB, size_t Unused) {
770 ToVisit.push(BB);
771 Queued.insert(BB);
772
773 size_t QueueIndex = 0;
774 while (ToVisit.size() != 0) {
775 BasicBlock *BB = ToVisit.front();
776 ToVisit.pop();
777
778 if (!CanBeVisited(BB)) {
779 ToVisit.push(BB);
780 if (QueueIndex >= ToVisit.size())
782 "No valid candidate in the queue. Is the graph reducible?");
783 QueueIndex++;
784 continue;
785 }
786
787 QueueIndex = 0;
788 size_t Rank = GetNodeRank(BB);
789 OrderInfo Info = {Rank, BlockToOrder.size()};
790 BlockToOrder.try_emplace(BB, Info);
791
792 for (BasicBlock *S : successors(BB)) {
793 if (Queued.count(S) != 0)
794 continue;
795 ToVisit.push(S);
796 Queued.insert(S);
797 }
798 }
799
800 return 0;
801}
802
804 DT.recalculate(F);
805 LI = LoopInfo(DT);
806
807 visit(&*F.begin(), 0);
808
809 Order.reserve(F.size());
810 for (auto &[BB, Info] : BlockToOrder)
811 Order.emplace_back(BB);
812
813 llvm::sort(Order, [&](const auto &LHS, const auto &RHS) {
814 return compare(LHS, RHS);
815 });
816}
817
819 const BasicBlock *RHS) const {
820 const OrderInfo &InfoLHS = BlockToOrder.at(const_cast<BasicBlock *>(LHS));
821 const OrderInfo &InfoRHS = BlockToOrder.at(const_cast<BasicBlock *>(RHS));
822 if (InfoLHS.Rank != InfoRHS.Rank)
823 return InfoLHS.Rank < InfoRHS.Rank;
824 return InfoLHS.TraversalIndex < InfoRHS.TraversalIndex;
825}
826
828 BasicBlock &Start, std::function<bool(BasicBlock *)> Op) {
829 SmallPtrSet<BasicBlock *, 0> Reachable = getReachableFrom(&Start);
830 assert(BlockToOrder.count(&Start) != 0);
831
832 // Skipping blocks with a rank inferior to |Start|'s rank.
833 auto It = Order.begin();
834 while (It != Order.end() && *It != &Start)
835 ++It;
836
837 // This is unexpected. Worst case |Start| is the last block,
838 // so It should point to the last block, not past-end.
839 assert(It != Order.end());
840
841 // By default, there is no rank limit. Setting it to the maximum value.
842 std::optional<size_t> EndRank = std::nullopt;
843 for (; It != Order.end(); ++It) {
844 if (EndRank.has_value() && BlockToOrder[*It].Rank > *EndRank)
845 break;
846
847 if (Reachable.count(*It) == 0) {
848 continue;
849 }
850
851 if (!Op(*It)) {
852 EndRank = BlockToOrder[*It].Rank;
853 }
854 }
855}
856
858 if (F.size() == 0)
859 return false;
860
861 bool Modified = false;
862 std::vector<BasicBlock *> Order;
863 Order.reserve(F.size());
864
866 llvm::append_range(Order, RPOT);
867
868 assert(&*F.begin() == Order[0]);
869 BasicBlock *LastBlock = &*F.begin();
870 for (BasicBlock *BB : Order) {
871 if (BB != LastBlock && &*LastBlock->getNextNode() != BB) {
872 Modified = true;
873 BB->moveAfter(LastBlock);
874 }
875 LastBlock = BB;
876 }
877
878 return Modified;
879}
880
882 const DataLayout &DL = F.getDataLayout();
883 return new AllocaInst(Type, DL.getAllocaAddrSpace(), nullptr, "reg",
884 F.begin()->getFirstInsertionPt());
885}
886
887Value *
889 const DenseMap<BasicBlock *, ConstantInt *> &TargetToValue) {
890 auto *T = BB->getTerminator();
891 if (isa<ReturnInst>(T))
892 return nullptr;
893 if (auto *BI = dyn_cast<UncondBrInst>(T))
894 return TargetToValue.lookup(BI->getSuccessor());
895
896 IRBuilder<> Builder(BB);
897 Builder.SetInsertPoint(T);
898
899 if (auto *BI = dyn_cast<CondBrInst>(T)) {
900 Value *LHS = TargetToValue.lookup(BI->getSuccessor(0));
901 Value *RHS = TargetToValue.lookup(BI->getSuccessor(1));
902
903 if (LHS == nullptr || RHS == nullptr)
904 return LHS == nullptr ? RHS : LHS;
905 return Builder.CreateSelect(BI->getCondition(), LHS, RHS);
906 }
907
908 if (auto *SI = dyn_cast<SwitchInst>(T)) {
909 Value *Condition = SI->getCondition();
910 // The default destination acts as the fallback value of the select chain.
911 Value *Result = TargetToValue.lookup(SI->getDefaultDest());
912 for (const auto &Case : SI->cases()) {
913 Value *CaseValue = TargetToValue.lookup(Case.getCaseSuccessor());
914 // Successors that are internal to the region have no exit value.
915 if (CaseValue == nullptr)
916 continue;
917 // The first known exit value becomes the base of the select chain.
918 if (Result == nullptr) {
919 Result = CaseValue;
920 continue;
921 }
922 Value *Cmp = Builder.CreateICmpEQ(Condition, Case.getCaseValue());
923 Result = Builder.CreateSelect(Cmp, CaseValue, Result);
924 }
925 return Result;
926 }
927
928 llvm_unreachable("Unhandled terminator type.");
929}
930
932 MachineInstr *MaybeDef = MRI.getVRegDef(Reg);
933 if (MaybeDef && MaybeDef->getOpcode() == SPIRV::ASSIGN_TYPE)
934 MaybeDef = MRI.getVRegDef(MaybeDef->getOperand(1).getReg());
935 return MaybeDef;
936}
937
938static bool getVacantFunctionName(Module &M, std::string &Name) {
939 // It's a bit of paranoia, but still we don't want to have even a chance that
940 // the loop will work for too long.
941 constexpr unsigned MaxIters = 1024;
942 for (unsigned I = 0; I < MaxIters; ++I) {
943 std::string OrdName = Name + Twine(I).str();
944 if (!M.getFunction(OrdName)) {
945 Name = std::move(OrdName);
946 return true;
947 }
948 }
949 return false;
950}
951
952// Assign SPIR-V type to the register. If the register has no valid assigned
953// class, set register LLT type and class according to the SPIR-V type.
956 const MachineFunction &MF, bool Force) {
957 GR->assignSPIRVTypeToVReg(SpvType, Reg, MF);
958 if (!MRI->getRegClassOrNull(Reg) || Force) {
959 MRI->setRegClass(Reg, GR->getRegClass(SpvType));
960 LLT RegType = GR->getRegType(SpvType);
961 if (Force || !MRI->getType(Reg).isValid())
962 MRI->setType(Reg, RegType);
963 }
964}
965
966// Create a SPIR-V type, assign SPIR-V type to the register. If the register has
967// no valid assigned class, set register LLT type and class according to the
968// SPIR-V type.
970 MachineIRBuilder &MIRBuilder,
971 SPIRV::AccessQualifier::AccessQualifier AccessQual,
972 bool EmitIR, bool Force) {
974 GR->getOrCreateSPIRVType(Ty, MIRBuilder, AccessQual, EmitIR),
975 GR, MIRBuilder.getMRI(), MIRBuilder.getMF(), Force);
976}
977
978// Create a virtual register and assign SPIR-V type to the register. Set
979// register LLT type and class according to the SPIR-V type.
982 const MachineFunction &MF) {
983 Register Reg = MRI->createVirtualRegister(GR->getRegClass(SpvType));
984 MRI->setType(Reg, GR->getRegType(SpvType));
985 GR->assignSPIRVTypeToVReg(SpvType, Reg, MF);
986 return Reg;
987}
988
989// Create a virtual register and assign SPIR-V type to the register. Set
990// register LLT type and class according to the SPIR-V type.
992 MachineIRBuilder &MIRBuilder) {
993 return createVirtualRegister(SpvType, GR, MIRBuilder.getMRI(),
994 MIRBuilder.getMF());
995}
996
997// Create a SPIR-V type, virtual register and assign SPIR-V type to the
998// register. Set register LLT type and class according to the SPIR-V type.
1000 const Type *Ty, SPIRVGlobalRegistry *GR, MachineIRBuilder &MIRBuilder,
1001 SPIRV::AccessQualifier::AccessQualifier AccessQual, bool EmitIR) {
1002 return createVirtualRegister(
1003 GR->getOrCreateSPIRVType(Ty, MIRBuilder, AccessQual, EmitIR), GR,
1004 MIRBuilder);
1005}
1006
1008 return SPVTy->getOpcode() == SPIRV::OpTypeVector ||
1009 SPVTy->getOpcode() == SPIRV::OpTypeVectorIdEXT;
1010}
1011
1013 Value *Arg, Value *Arg2, ArrayRef<Constant *> Imms,
1014 IRBuilder<> &B) {
1016 Args.push_back(Arg2);
1017 Args.push_back(buildMD(Arg));
1018 llvm::append_range(Args, Imms);
1019 return B.CreateIntrinsicWithoutFolding(IntrID, {Types}, Args);
1020}
1021
1022// Return true if there is an opaque pointer type nested in the argument.
1023bool isNestedPointer(const Type *Ty) {
1024 if (Ty->isPtrOrPtrVectorTy())
1025 return true;
1026 if (const FunctionType *RefTy = dyn_cast<FunctionType>(Ty)) {
1027 if (isNestedPointer(RefTy->getReturnType()))
1028 return true;
1029 for (const Type *ArgTy : RefTy->params())
1030 if (isNestedPointer(ArgTy))
1031 return true;
1032 return false;
1033 }
1034 if (const ArrayType *RefTy = dyn_cast<ArrayType>(Ty))
1035 return isNestedPointer(RefTy->getElementType());
1036 return false;
1037}
1038
1039bool isSpvIntrinsic(const Value *Arg) {
1040 if (const auto *II = dyn_cast<IntrinsicInst>(Arg))
1041 if (Function *F = II->getCalledFunction())
1042 if (F->getName().starts_with("llvm.spv."))
1043 return true;
1044 return false;
1045}
1046
1047// Function to create continued instructions for SPV_INTEL_long_composites
1048// extension
1049SmallVector<MachineInstr *, 4>
1051 unsigned MinWC, unsigned ContinuedOpcode,
1052 ArrayRef<Register> Args, Register ReturnRegister,
1053 Register TypeID) {
1054
1055 SmallVector<MachineInstr *, 4> Instructions;
1056 constexpr unsigned MaxWordCount = UINT16_MAX;
1057 const size_t NumElements = Args.size();
1058 size_t MaxNumElements = MaxWordCount - MinWC;
1059 size_t SPIRVStructNumElements = NumElements;
1060
1061 if (NumElements > MaxNumElements) {
1062 // Do adjustments for continued instructions which always had only one
1063 // minumum word count.
1064 SPIRVStructNumElements = MaxNumElements;
1065 MaxNumElements = MaxWordCount - 1;
1066 }
1067
1068 auto MIB =
1069 MIRBuilder.buildInstr(Opcode).addDef(ReturnRegister).addUse(TypeID);
1070
1071 for (size_t I = 0; I < SPIRVStructNumElements; ++I)
1072 MIB.addUse(Args[I]);
1073
1074 Instructions.push_back(MIB.getInstr());
1075
1076 for (size_t I = SPIRVStructNumElements; I < NumElements;
1077 I += MaxNumElements) {
1078 auto MIB = MIRBuilder.buildInstr(ContinuedOpcode);
1079 for (size_t J = I; J < std::min(I + MaxNumElements, NumElements); ++J)
1080 MIB.addUse(Args[J]);
1081 Instructions.push_back(MIB.getInstr());
1082 }
1083 return Instructions;
1084}
1085
1086SmallVector<unsigned, 1>
1088 unsigned LC = SPIRV::LoopControl::None;
1089 // Currently used only to store PartialCount value. Later when other
1090 // LoopControls are added - this map should be sorted before making
1091 // them loop_merge operands to satisfy 3.23. Loop Control requirements.
1092 std::vector<std::pair<unsigned, unsigned>> MaskToValueMap;
1093 if (findOptionMDForLoopID(LoopMD, "llvm.loop.unroll.disable")) {
1094 LC |= SPIRV::LoopControl::DontUnroll;
1095 } else {
1096 if (findOptionMDForLoopID(LoopMD, "llvm.loop.unroll.enable") ||
1097 findOptionMDForLoopID(LoopMD, "llvm.loop.unroll.full")) {
1098 LC |= SPIRV::LoopControl::Unroll;
1099 }
1100 if (MDNode *CountMD =
1101 findOptionMDForLoopID(LoopMD, "llvm.loop.unroll.count")) {
1102 if (auto *CI =
1103 mdconst::extract_or_null<ConstantInt>(CountMD->getOperand(1))) {
1104 unsigned Count = CI->getZExtValue();
1105 if (Count != 1) {
1106 LC |= SPIRV::LoopControl::PartialCount;
1107 MaskToValueMap.emplace_back(
1108 std::make_pair(SPIRV::LoopControl::PartialCount, Count));
1109 }
1110 }
1111 }
1112 }
1113 SmallVector<unsigned, 1> Result = {LC};
1114 for (auto &[Mask, Val] : MaskToValueMap)
1115 Result.push_back(Val);
1116 return Result;
1117}
1118
1122
1123const std::set<unsigned> &getTypeFoldingSupportedOpcodes() {
1124 // clang-format off
1125 static const std::set<unsigned> TypeFoldingSupportingOpcs = {
1126 TargetOpcode::G_ADD,
1127 TargetOpcode::G_FADD,
1128 TargetOpcode::G_STRICT_FADD,
1129 TargetOpcode::G_SUB,
1130 TargetOpcode::G_FSUB,
1131 TargetOpcode::G_STRICT_FSUB,
1132 TargetOpcode::G_MUL,
1133 TargetOpcode::G_FMUL,
1134 TargetOpcode::G_STRICT_FMUL,
1135 TargetOpcode::G_SDIV,
1136 TargetOpcode::G_UDIV,
1137 TargetOpcode::G_FDIV,
1138 TargetOpcode::G_STRICT_FDIV,
1139 TargetOpcode::G_SREM,
1140 TargetOpcode::G_UREM,
1141 TargetOpcode::G_FREM,
1142 TargetOpcode::G_STRICT_FREM,
1143 TargetOpcode::G_FNEG,
1144 TargetOpcode::G_CONSTANT,
1145 TargetOpcode::G_FCONSTANT,
1146 TargetOpcode::G_AND,
1147 TargetOpcode::G_OR,
1148 TargetOpcode::G_XOR,
1149 TargetOpcode::G_SHL,
1150 TargetOpcode::G_ASHR,
1151 TargetOpcode::G_LSHR,
1152 TargetOpcode::G_SELECT,
1153 TargetOpcode::G_EXTRACT_VECTOR_ELT,
1154 };
1155 // clang-format on
1156 return TypeFoldingSupportingOpcs;
1157}
1158
1159bool isTypeFoldingSupported(unsigned Opcode) {
1160 return getTypeFoldingSupportedOpcodes().count(Opcode) > 0;
1161}
1162
1163// Traversing [g]MIR accounting for pseudo-instructions.
1165 return (Def->getOpcode() == SPIRV::ASSIGN_TYPE ||
1166 Def->getOpcode() == TargetOpcode::COPY)
1167 ? MRI->getVRegDef(Def->getOperand(1).getReg())
1168 : Def;
1169}
1170
1172 if (MachineInstr *Def = MRI->getVRegDef(MO.getReg()))
1173 return passCopy(Def, MRI);
1174 return nullptr;
1175}
1176
1178 if (MachineInstr *Def = getDef(MO, MRI)) {
1179 if (Def->getOpcode() == TargetOpcode::G_CONSTANT ||
1180 Def->getOpcode() == SPIRV::OpConstantI)
1181 return Def;
1182 }
1183 return nullptr;
1184}
1185
1186int64_t foldImm(const MachineOperand &MO, const MachineRegisterInfo *MRI) {
1187 if (MachineInstr *Def = getImm(MO, MRI)) {
1188 if (Def->getOpcode() == SPIRV::OpConstantI)
1189 return Def->getOperand(2).getImm();
1190 if (Def->getOpcode() == TargetOpcode::G_CONSTANT)
1191 return Def->getOperand(1).getCImm()->getZExtValue();
1192 }
1193 llvm_unreachable("Unexpected integer constant pattern");
1194}
1195
1197 const MachineInstr *ResType) {
1198 return foldImm(ResType->getOperand(2), MRI);
1199}
1200
1201bool matchPeeledArrayPattern(const StructType *Ty, Type *&OriginalElementType,
1202 uint64_t &TotalSize) {
1203 // An array of N padded structs is represented as {[N-1 x <{T, pad}>], T}.
1204 if (Ty->getStructNumElements() != 2)
1205 return false;
1206
1207 Type *FirstElement = Ty->getStructElementType(0);
1208 Type *SecondElement = Ty->getStructElementType(1);
1209
1210 if (!FirstElement->isArrayTy())
1211 return false;
1212
1213 Type *ArrayElementType = FirstElement->getArrayElementType();
1214 if (!ArrayElementType->isStructTy() ||
1215 ArrayElementType->getStructNumElements() != 2)
1216 return false;
1217
1218 Type *T_in_struct = ArrayElementType->getStructElementType(0);
1219 if (T_in_struct != SecondElement)
1220 return false;
1221
1222 auto *Padding_in_struct =
1223 dyn_cast<TargetExtType>(ArrayElementType->getStructElementType(1));
1224 if (!Padding_in_struct || Padding_in_struct->getName() != "spirv.Padding")
1225 return false;
1226
1227 const uint64_t ArraySize = FirstElement->getArrayNumElements();
1228 TotalSize = ArraySize + 1;
1229 OriginalElementType = ArrayElementType;
1230 return true;
1231}
1232
1234 if (!Ty->isStructTy())
1235 return Ty;
1236
1237 auto *STy = cast<StructType>(Ty);
1238 Type *OriginalElementType = nullptr;
1239 uint64_t TotalSize = 0;
1240 if (matchPeeledArrayPattern(STy, OriginalElementType, TotalSize)) {
1241 Type *ResultTy = ArrayType::get(
1242 reconstitutePeeledArrayType(OriginalElementType), TotalSize);
1243 return ResultTy;
1244 }
1245
1246 SmallVector<Type *, 4> NewElementTypes;
1247 bool Changed = false;
1248 for (Type *ElementTy : STy->elements()) {
1249 Type *NewElementTy = reconstitutePeeledArrayType(ElementTy);
1250 if (NewElementTy != ElementTy)
1251 Changed = true;
1252 NewElementTypes.push_back(NewElementTy);
1253 }
1254
1255 if (!Changed)
1256 return Ty;
1257
1258 Type *ResultTy;
1259 if (STy->isLiteral()) {
1260 ResultTy =
1261 StructType::get(STy->getContext(), NewElementTypes, STy->isPacked());
1262 } else {
1263 ResultTy = StructType::create(STy->getContext(), NewElementTypes,
1264 STy->getName(), STy->isPacked());
1265 }
1266 return ResultTy;
1267}
1268
1269std::optional<SPIRV::LinkageType::LinkageType>
1271 if (GV.hasLocalLinkage())
1272 return std::nullopt;
1273
1274 if (GV.isDeclarationForLinker()) {
1275 if (const auto *GVar = dyn_cast<GlobalVariable>(&GV)) {
1276 auto SC = addressSpaceToStorageClass(GVar->getAddressSpace(), ST);
1277 // Interface variables must not get Import linkage.
1278 if (SC == SPIRV::StorageClass::Input ||
1279 SC == SPIRV::StorageClass::Output ||
1280 SC == SPIRV::StorageClass::PushConstant)
1281 return std::nullopt;
1282 // Shaders have no linker, so module-internal storage
1283 // (e.g. HLSL groupshared) can't be imported
1284 if (ST.isShader() && (SC == SPIRV::StorageClass::Workgroup ||
1285 SC == SPIRV::StorageClass::Private))
1286 return std::nullopt;
1287 }
1288 return SPIRV::LinkageType::Import;
1289 }
1290
1291 if (GV.hasHiddenVisibility())
1292 return std::nullopt;
1293
1294 if (GV.hasLinkOnceODRLinkage() &&
1295 ST.canUseExtension(SPIRV::Extension::SPV_KHR_linkonce_odr))
1296 return SPIRV::LinkageType::LinkOnceODR;
1297
1298 if (GV.hasWeakLinkage() &&
1299 ST.canUseExtension(SPIRV::Extension::SPV_AMD_weak_linkage))
1300 return SPIRV::LinkageType::WeakAMD;
1301
1302 return SPIRV::LinkageType::Export;
1303}
1304
1306 std::string ServiceFunName = SPIRV_BACKEND_SERVICE_FUN_NAME;
1307 if (!getVacantFunctionName(M, ServiceFunName))
1309 "cannot allocate a name for the internal service function");
1310 if (Function *SF = M.getFunction(ServiceFunName)) {
1311 if (SF->getInstructionCount() > 0)
1313 "Unexpected combination of global variables and function pointers");
1314 return SF;
1315 }
1317 FunctionType::get(Type::getVoidTy(M.getContext()), {}, false),
1318 GlobalValue::PrivateLinkage, ServiceFunName, M);
1320 return SF;
1321}
1322
1323} // namespace llvm
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
unsigned Imm
unsigned uint64_t
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:567
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:285
unsigned size() const
Definition DenseMap.h:207
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:640
static Function * Create(FunctionType *Ty, LinkageTypes Linkage, unsigned AddrSpace, const Twine &N="", Module *M=nullptr)
Definition Function.h:169
const Function & getFunction() const
Definition Function.h:167
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:2908
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:1081
const MDOperand & getOperand(unsigned I) const
Definition Metadata.h:1437
unsigned getNumOperands() const
Return number of MDNode operands.
Definition Metadata.h:1443
A single uniqued string.
Definition Metadata.h:733
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 LLVM_READONLY 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:68
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:1766
op_iterator op_end()
Definition Metadata.h:1855
iterator_range< op_iterator > operands()
Definition Metadata.h:1862
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:467
static LLVM_ABI StructType * create(LLVMContext &Context, StringRef Name)
This creates an identified struct.
Definition Type.cpp:662
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:300
LLVM_ABI Type * getStructElementType(unsigned N) const
bool isArrayTy() const
True if this is an instance of ArrayType.
Definition Type.h:274
static LLVM_ABI IntegerType * getInt32Ty(LLVMContext &C)
Definition Type.cpp:299
Type * getArrayElementType() const
Definition Type.h:420
LLVM_ABI unsigned getStructNumElements() const
LLVM_ABI uint64_t getArrayNumElements() const
static LLVM_ABI Type * getVoidTy(LLVMContext &C)
Definition Type.cpp:272
static LLVM_ABI IntegerType * getInt8Ty(LLVMContext &C)
Definition Type.cpp:297
bool isStructTy() const
True if this is an instance of StructType.
Definition Type.h:271
static LLVM_ABI IntegerType * getInt16Ty(LLVMContext &C)
Definition Type.cpp:298
static LLVM_ABI IntegerType * getIntNTy(LLVMContext &C, unsigned N)
Definition Type.cpp:303
static LLVM_ABI Type * getDoubleTy(LLVMContext &C)
Definition Type.cpp:277
static LLVM_ABI Type * getFloatTy(LLVMContext &C)
Definition Type.cpp:276
static LLVM_ABI Type * getHalfTy(LLVMContext &C)
Definition Type.cpp:274
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:694
std::enable_if_t< detail::IsValidPointer< X, Y >::value, X * > dyn_extract(Y &&MD)
Extract a Value from Metadata, if any.
Definition Metadata.h:707
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:424
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)
uint32_t getMemSemanticsWithStorageClass(const Triple &TT, uint32_t OrderSem, uint32_t StorageClassSem)
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:2224
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 isVectorType(SPIRVTypeInst SPVTy)
bool isNestedPointer(const Type *Ty)
Function * getOrCreateBackendServiceFunction(Module &M)
MetadataAsValue * buildMD(Value *Arg)
Definition SPIRVUtils.h:555
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:1652
std::string getSPIRVStringOperand(const InstType &MI, unsigned StartIndex)
Type * toTypedPointer(Type *Ty)
Definition SPIRVUtils.h:479
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:389
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:1788
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