LLVM 23.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 "SPIRVGlobalRegistry.h"
17#include "SPIRVInstrInfo.h"
18#include "SPIRVSubtarget.h"
19#include "llvm/ADT/StringRef.h"
26#include "llvm/IR/IntrinsicsSPIRV.h"
27#include <queue>
28#include <vector>
29
30namespace llvm {
31namespace SPIRV {
32// This code restores function args/retvalue types for composite cases
33// because the final types should still be aggregate whereas they're i32
34// during the translation to cope with aggregate flattening etc.
35// TODO: should these just return nullptr when there's no metadata?
37 FunctionType *FTy,
38 StringRef Name) {
39 if (!NMD)
40 return FTy;
41
42 constexpr auto getConstInt = [](MDNode *MD, unsigned OpId) -> ConstantInt * {
43 if (MD->getNumOperands() <= OpId)
44 return nullptr;
45 if (auto *CMeta = dyn_cast<ConstantAsMetadata>(MD->getOperand(OpId)))
46 return dyn_cast<ConstantInt>(CMeta->getValue());
47 return nullptr;
48 };
49
50 auto It = find_if(NMD->operands(), [Name](MDNode *N) {
51 if (auto *MDS = dyn_cast_or_null<MDString>(N->getOperand(0)))
52 return MDS->getString() == Name;
53 return false;
54 });
55
56 if (It == NMD->op_end())
57 return FTy;
58
59 Type *RetTy = FTy->getReturnType();
60 SmallVector<Type *, 4> PTys(FTy->params());
61
62 for (unsigned I = 1; I != (*It)->getNumOperands(); ++I) {
63 MDNode *MD = dyn_cast<MDNode>((*It)->getOperand(I));
64 assert(MD && "MDNode operand is expected");
65
66 if (auto *Const = getConstInt(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 // TODO: unify the extractors.
91 if (!NMD)
92 return Constraints;
93
94 auto It = find_if(NMD->operands(), [Name](MDNode *N) {
95 if (auto *MDS = dyn_cast_or_null<MDString>(N->getOperand(0)))
96 return MDS->getString() == Name;
97 return false;
98 });
99
100 if (It == NMD->op_end())
101 return Constraints;
102
103 // By convention, the constraints string is stored in the final MD operand.
104 MDNode *MD = dyn_cast<MDNode>((*It)->getOperand((*It)->getNumOperands() - 1));
105 assert(MD && "MDNode operand is expected");
106
107 if (auto *MDS = dyn_cast<MDString>(MD->getOperand(0)))
108 Constraints = MDS->getString();
109
110 return Constraints;
111}
112
115 F.getParent()->getNamedMetadata("spv.cloned_funcs"), F.getFunctionType(),
116 F.getName());
117}
118
121 CB.getModule()->getNamedMetadata("spv.mutated_callsites"),
122 CB.getFunctionType(), CB.getName());
123}
124
127 CB.getModule()->getNamedMetadata("spv.mutated_callsites"),
128 cast<InlineAsm>(CB.getCalledOperand())->getConstraintString(),
129 CB.getName());
130}
131} // Namespace SPIRV
132
133// The following functions are used to add these string literals as a series of
134// 32-bit integer operands with the correct format, and unpack them if necessary
135// when making string comparisons in compiler passes.
136// SPIR-V requires null-terminated UTF-8 strings padded to 32-bit alignment.
137static uint32_t convertCharsToWord(const StringRef &Str, unsigned i) {
138 uint32_t Word = 0u; // Build up this 32-bit word from 4 8-bit chars.
139 for (unsigned WordIndex = 0; WordIndex < 4; ++WordIndex) {
140 unsigned StrIndex = i + WordIndex;
141 uint8_t CharToAdd = 0; // Initilize char as padding/null.
142 if (StrIndex < Str.size()) { // If it's within the string, get a real char.
143 CharToAdd = Str[StrIndex];
144 }
145 Word |= (CharToAdd << (WordIndex * 8));
146 }
147 return Word;
148}
149
150// Get length including padding and null terminator.
151static size_t getPaddedLen(const StringRef &Str) {
152 return (Str.size() + 4) & ~3;
153}
154
155void addStringImm(const StringRef &Str, MCInst &Inst) {
156 const size_t PaddedLen = getPaddedLen(Str);
157 for (unsigned i = 0; i < PaddedLen; i += 4) {
158 // Add an operand for the 32-bits of chars or padding.
160 }
161}
162
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.
167 MIB.addImm(convertCharsToWord(Str, i));
168 }
169}
170
172 std::vector<Value *> &Args) {
173 const size_t PaddedLen = getPaddedLen(Str);
174 for (unsigned i = 0; i < PaddedLen; i += 4) {
175 // Add a vector element for the 32-bits of chars or padding.
176 Args.push_back(B.getInt32(convertCharsToWord(Str, i)));
177 }
178}
179
180std::string getStringImm(const MachineInstr &MI, unsigned StartIndex) {
181 return getSPIRVStringOperand(MI, StartIndex);
182}
183
185 MachineInstr *Def = getVRegDef(MRI, Reg);
186 assert(Def && Def->getOpcode() == TargetOpcode::G_GLOBAL_VALUE &&
187 "Expected G_GLOBAL_VALUE");
188 const GlobalValue *GV = Def->getOperand(1).getGlobal();
189 Value *V = GV->getOperand(0);
191 return CDA->getAsCString().str();
192}
193
194void addNumImm(const APInt &Imm, MachineInstrBuilder &MIB) {
195 const auto Bitwidth = Imm.getBitWidth();
196 if (Bitwidth == 1)
197 return; // Already handled
198 else if (Bitwidth <= 32) {
199 MIB.addImm(Imm.getZExtValue());
200 // Asm Printer needs this info to print floating-type correctly
201 if (Bitwidth == 16)
203 return;
204 } else if (Bitwidth <= 64) {
205 uint64_t FullImm = Imm.getZExtValue();
206 uint32_t LowBits = FullImm & 0xffffffff;
207 uint32_t HighBits = (FullImm >> 32) & 0xffffffff;
208 MIB.addImm(LowBits).addImm(HighBits);
209 // Asm Printer needs this info to print 64-bit operands correctly
211 return;
212 } else {
213 // Emit ceil(Bitwidth / 32) words to conform SPIR-V spec.
214 unsigned NumWords = (Bitwidth + 31) / 32;
215 for (unsigned I = 0; I < NumWords; ++I) {
216 unsigned LimbIdx = I / 2;
217 unsigned LimbShift = (I % 2) * 32;
218 uint32_t Word = (Imm.getRawData()[LimbIdx] >> LimbShift) & 0xffffffff;
219 MIB.addImm(Word);
220 }
221 return;
222 }
223}
224
226 MachineIRBuilder &MIRBuilder) {
227 if (!Name.empty()) {
228 auto MIB = MIRBuilder.buildInstr(SPIRV::OpName).addUse(Target);
229 addStringImm(Name, MIB);
230 }
231}
232
234 const SPIRVInstrInfo &TII) {
235 if (!Name.empty()) {
236 auto MIB =
237 BuildMI(*I.getParent(), I, I.getDebugLoc(), TII.get(SPIRV::OpName))
238 .addUse(Target);
239 addStringImm(Name, MIB);
240 }
241}
242
244 const std::vector<uint32_t> &DecArgs,
245 StringRef StrImm) {
246 if (!StrImm.empty())
247 addStringImm(StrImm, MIB);
248 for (const auto &DecArg : DecArgs)
249 MIB.addImm(DecArg);
250}
251
253 SPIRV::Decoration::Decoration Dec,
254 const std::vector<uint32_t> &DecArgs, StringRef StrImm) {
255 auto MIB = MIRBuilder.buildInstr(SPIRV::OpDecorate)
256 .addUse(Reg)
257 .addImm(static_cast<uint32_t>(Dec));
258 finishBuildOpDecorate(MIB, DecArgs, StrImm);
259}
260
262 SPIRV::Decoration::Decoration Dec,
263 const std::vector<uint32_t> &DecArgs, StringRef StrImm) {
264 MachineBasicBlock &MBB = *I.getParent();
265 auto MIB = BuildMI(MBB, I, I.getDebugLoc(), TII.get(SPIRV::OpDecorate))
266 .addUse(Reg)
267 .addImm(static_cast<uint32_t>(Dec));
268 finishBuildOpDecorate(MIB, DecArgs, StrImm);
269}
270
272 SPIRV::Decoration::Decoration Dec, uint32_t Member,
273 const std::vector<uint32_t> &DecArgs,
274 StringRef StrImm) {
275 auto MIB = MIRBuilder.buildInstr(SPIRV::OpMemberDecorate)
276 .addUse(Reg)
277 .addImm(Member)
278 .addImm(static_cast<uint32_t>(Dec));
279 finishBuildOpDecorate(MIB, DecArgs, StrImm);
280}
281
283 const SPIRVInstrInfo &TII,
284 SPIRV::Decoration::Decoration Dec, uint32_t Member,
285 const std::vector<uint32_t> &DecArgs,
286 StringRef StrImm) {
287 MachineBasicBlock &MBB = *I.getParent();
288 auto MIB = BuildMI(MBB, I, I.getDebugLoc(), TII.get(SPIRV::OpMemberDecorate))
289 .addUse(Reg)
290 .addImm(Member)
291 .addImm(static_cast<uint32_t>(Dec));
292 finishBuildOpDecorate(MIB, DecArgs, StrImm);
293}
294
296 const MDNode *GVarMD, const SPIRVSubtarget &ST) {
297 for (unsigned I = 0, E = GVarMD->getNumOperands(); I != E; ++I) {
298 auto *OpMD = dyn_cast<MDNode>(GVarMD->getOperand(I));
299 if (!OpMD)
300 report_fatal_error("Invalid decoration");
301 if (OpMD->getNumOperands() == 0)
302 report_fatal_error("Expect operand(s) of the decoration");
303 ConstantInt *DecorationId =
304 mdconst::dyn_extract<ConstantInt>(OpMD->getOperand(0));
305 if (!DecorationId)
306 report_fatal_error("Expect SPIR-V <Decoration> operand to be the first "
307 "element of the decoration");
308
309 // The goal of `spirv.Decorations` metadata is to provide a way to
310 // represent SPIR-V entities that do not map to LLVM in an obvious way.
311 // FP flags do have obvious matches between LLVM IR and SPIR-V.
312 // Additionally, we have no guarantee at this point that the flags passed
313 // through the decoration are not violated already in the optimizer passes.
314 // Therefore, we simply ignore FP flags, including NoContraction, and
315 // FPFastMathMode.
316 if (DecorationId->getZExtValue() ==
317 static_cast<uint32_t>(SPIRV::Decoration::NoContraction) ||
318 DecorationId->getZExtValue() ==
319 static_cast<uint32_t>(SPIRV::Decoration::FPFastMathMode)) {
320 continue; // Ignored.
321 }
322 auto MIB = MIRBuilder.buildInstr(SPIRV::OpDecorate)
323 .addUse(Reg)
324 .addImm(static_cast<uint32_t>(DecorationId->getZExtValue()));
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(LLVMContext &Ctx, SyncScope::ID Id) {
453 // Named by
454 // https://registry.khronos.org/SPIR-V/specs/unified1/SPIRV.html#_scope_id.
455 // We don't need aliases for Invocation and CrossDevice, as we already have
456 // them covered by "singlethread" and "" strings respectively (see
457 // implementation of LLVMContext::LLVMContext()).
458 static const llvm::SyncScope::ID SubGroup =
459 Ctx.getOrInsertSyncScopeID("subgroup");
460 static const llvm::SyncScope::ID WorkGroup =
461 Ctx.getOrInsertSyncScopeID("workgroup");
462 static const llvm::SyncScope::ID Device =
463 Ctx.getOrInsertSyncScopeID("device");
464
466 return SPIRV::Scope::Invocation;
467 else if (Id == llvm::SyncScope::System)
468 return SPIRV::Scope::CrossDevice;
469 else if (Id == SubGroup)
470 return SPIRV::Scope::Subgroup;
471 else if (Id == WorkGroup)
472 return SPIRV::Scope::Workgroup;
473 else if (Id == Device)
474 return SPIRV::Scope::Device;
475 return SPIRV::Scope::CrossDevice;
476}
477
479 const MachineRegisterInfo *MRI) {
480 MachineInstr *MI = MRI->getVRegDef(ConstReg);
481 MachineInstr *ConstInstr =
482 MI->getOpcode() == SPIRV::G_TRUNC || MI->getOpcode() == SPIRV::G_ZEXT
483 ? MRI->getVRegDef(MI->getOperand(1).getReg())
484 : MI;
485 if (auto *GI = dyn_cast<GIntrinsic>(ConstInstr)) {
486 if (GI->is(Intrinsic::spv_track_constant)) {
487 ConstReg = ConstInstr->getOperand(2).getReg();
488 return MRI->getVRegDef(ConstReg);
489 }
490 } else if (ConstInstr->getOpcode() == SPIRV::ASSIGN_TYPE) {
491 ConstReg = ConstInstr->getOperand(1).getReg();
492 return MRI->getVRegDef(ConstReg);
493 } else if (ConstInstr->getOpcode() == TargetOpcode::G_CONSTANT ||
494 ConstInstr->getOpcode() == TargetOpcode::G_FCONSTANT) {
495 ConstReg = ConstInstr->getOperand(0).getReg();
496 return ConstInstr;
497 }
498 return MRI->getVRegDef(ConstReg);
499}
500
502 const MachineInstr *MI = getDefInstrMaybeConstant(ConstReg, MRI);
503 assert(MI && MI->getOpcode() == TargetOpcode::G_CONSTANT);
504 return MI->getOperand(1).getCImm()->getValue().getZExtValue();
505}
506
507int64_t getIConstValSext(Register ConstReg, const MachineRegisterInfo *MRI) {
508 const MachineInstr *MI = getDefInstrMaybeConstant(ConstReg, MRI);
509 assert(MI && MI->getOpcode() == TargetOpcode::G_CONSTANT);
510 return MI->getOperand(1).getCImm()->getSExtValue();
511}
512
513bool isSpvIntrinsic(const MachineInstr &MI, Intrinsic::ID IntrinsicID) {
514 if (const auto *GI = dyn_cast<GIntrinsic>(&MI))
515 return GI->is(IntrinsicID);
516 return false;
517}
518
519Type *getMDOperandAsType(const MDNode *N, unsigned I) {
520 Type *ElementTy = cast<ValueAsMetadata>(N->getOperand(I))->getType();
521 return toTypedPointer(ElementTy);
522}
523
524// The set of names is borrowed from the SPIR-V translator.
525// TODO: may be implemented in SPIRVBuiltins.td.
526static bool isPipeOrAddressSpaceCastBI(const StringRef MangledName) {
527 return MangledName == "write_pipe_2" || MangledName == "read_pipe_2" ||
528 MangledName == "write_pipe_2_bl" || MangledName == "read_pipe_2_bl" ||
529 MangledName == "write_pipe_4" || MangledName == "read_pipe_4" ||
530 MangledName == "reserve_write_pipe" ||
531 MangledName == "reserve_read_pipe" ||
532 MangledName == "commit_write_pipe" ||
533 MangledName == "commit_read_pipe" ||
534 MangledName == "work_group_reserve_write_pipe" ||
535 MangledName == "work_group_reserve_read_pipe" ||
536 MangledName == "work_group_commit_write_pipe" ||
537 MangledName == "work_group_commit_read_pipe" ||
538 MangledName == "get_pipe_num_packets_ro" ||
539 MangledName == "get_pipe_max_packets_ro" ||
540 MangledName == "get_pipe_num_packets_wo" ||
541 MangledName == "get_pipe_max_packets_wo" ||
542 MangledName == "sub_group_reserve_write_pipe" ||
543 MangledName == "sub_group_reserve_read_pipe" ||
544 MangledName == "sub_group_commit_write_pipe" ||
545 MangledName == "sub_group_commit_read_pipe" ||
546 MangledName == "to_global" || MangledName == "to_local" ||
547 MangledName == "to_private";
548}
549
550static bool isEnqueueKernelBI(const StringRef MangledName) {
551 return MangledName == "__enqueue_kernel_basic" ||
552 MangledName == "__enqueue_kernel_basic_events" ||
553 MangledName == "__enqueue_kernel_varargs" ||
554 MangledName == "__enqueue_kernel_events_varargs";
555}
556
557static bool isKernelQueryBI(const StringRef MangledName) {
558 return MangledName == "__get_kernel_work_group_size_impl" ||
559 MangledName == "__get_kernel_sub_group_count_for_ndrange_impl" ||
560 MangledName == "__get_kernel_max_sub_group_size_for_ndrange_impl" ||
561 MangledName == "__get_kernel_preferred_work_group_size_multiple_impl";
562}
563
565 if (!Name.starts_with("__"))
566 return false;
567
568 return isEnqueueKernelBI(Name) || isKernelQueryBI(Name) ||
569 isPipeOrAddressSpaceCastBI(Name.drop_front(2)) ||
570 Name == "__translate_sampler_initializer";
571}
572
574 bool IsNonMangledOCL = isNonMangledOCLBuiltin(Name);
575 bool IsNonMangledSPIRV = Name.starts_with("__spirv_");
576 bool IsNonMangledHLSL = Name.starts_with("__hlsl_");
577 bool IsMangled = Name.starts_with("_Z");
578
579 // Otherwise use simple demangling to return the function name.
580 if (IsNonMangledOCL || IsNonMangledSPIRV || IsNonMangledHLSL || !IsMangled)
581 return Name.str();
582
583 // Try to use the itanium demangler.
584 if (char *DemangledName = itaniumDemangle(Name.data())) {
585 std::string Result = DemangledName;
586 free(DemangledName);
587 return Result;
588 }
589
590 // Autocheck C++, maybe need to do explicit check of the source language.
591 // OpenCL C++ built-ins are declared in cl namespace.
592 // TODO: consider using 'St' abbriviation for cl namespace mangling.
593 // Similar to ::std:: in C++.
594 size_t Start, Len = 0;
595 size_t DemangledNameLenStart = 2;
596 if (Name.starts_with("_ZN")) {
597 // Skip CV and ref qualifiers.
598 size_t NameSpaceStart = Name.find_first_not_of("rVKRO", 3);
599 // All built-ins are in the ::cl:: namespace.
600 if (Name.substr(NameSpaceStart, 11) != "2cl7__spirv")
601 return std::string();
602 DemangledNameLenStart = NameSpaceStart + 11;
603 }
604 Start = Name.find_first_not_of("0123456789", DemangledNameLenStart);
605 [[maybe_unused]] bool Error =
606 Name.substr(DemangledNameLenStart, Start - DemangledNameLenStart)
607 .getAsInteger(10, Len);
608 assert(!Error && "Failed to parse demangled name length");
609 return Name.substr(Start, Len).str();
610}
611
613 if (Name.starts_with("opencl.") || Name.starts_with("ocl_") ||
614 Name.starts_with("spirv."))
615 return true;
616 return false;
617}
618
619bool isSpecialOpaqueType(const Type *Ty) {
620 if (const TargetExtType *ExtTy = dyn_cast<TargetExtType>(Ty))
621 return isTypedPointerWrapper(ExtTy)
622 ? false
623 : hasBuiltinTypePrefix(ExtTy->getName());
624
625 return false;
626}
627
628bool isEntryPoint(const Function &F) {
629 // OpenCL handling: any function with the SPIR_KERNEL
630 // calling convention will be a potential entry point.
631 if (F.getCallingConv() == CallingConv::SPIR_KERNEL)
632 return true;
633
634 // HLSL handling: special attribute are emitted from the
635 // front-end.
636 if (F.getFnAttribute("hlsl.shader").isValid())
637 return true;
638
639 return false;
640}
641
643 TypeName.consume_front("atomic_");
644 if (TypeName.consume_front("void"))
645 return Type::getVoidTy(Ctx);
646 else if (TypeName.consume_front("bool") || TypeName.consume_front("_Bool"))
647 return Type::getIntNTy(Ctx, 1);
648 else if (TypeName.consume_front("char") ||
649 TypeName.consume_front("signed char") ||
650 TypeName.consume_front("unsigned char") ||
651 TypeName.consume_front("uchar"))
652 return Type::getInt8Ty(Ctx);
653 else if (TypeName.consume_front("short") ||
654 TypeName.consume_front("signed short") ||
655 TypeName.consume_front("unsigned short") ||
656 TypeName.consume_front("ushort"))
657 return Type::getInt16Ty(Ctx);
658 else if (TypeName.consume_front("int") ||
659 TypeName.consume_front("signed int") ||
660 TypeName.consume_front("unsigned int") ||
661 TypeName.consume_front("uint"))
662 return Type::getInt32Ty(Ctx);
663 else if (TypeName.consume_front("long") ||
664 TypeName.consume_front("signed long") ||
665 TypeName.consume_front("unsigned long") ||
666 TypeName.consume_front("ulong"))
667 return Type::getInt64Ty(Ctx);
668 else if (TypeName.consume_front("half") ||
669 TypeName.consume_front("_Float16") ||
670 TypeName.consume_front("__fp16"))
671 return Type::getHalfTy(Ctx);
672 else if (TypeName.consume_front("float"))
673 return Type::getFloatTy(Ctx);
674 else if (TypeName.consume_front("double"))
675 return Type::getDoubleTy(Ctx);
676
677 // Unable to recognize SPIRV type name
678 return nullptr;
679}
680
681std::unordered_set<BasicBlock *>
682PartialOrderingVisitor::getReachableFrom(BasicBlock *Start) {
683 std::queue<BasicBlock *> ToVisit;
684 ToVisit.push(Start);
685
686 std::unordered_set<BasicBlock *> Output;
687 while (ToVisit.size() != 0) {
688 BasicBlock *BB = ToVisit.front();
689 ToVisit.pop();
690
691 if (Output.count(BB) != 0)
692 continue;
693 Output.insert(BB);
694
695 for (BasicBlock *Successor : successors(BB)) {
696 if (DT.dominates(Successor, BB))
697 continue;
698 ToVisit.push(Successor);
699 }
700 }
701
702 return Output;
703}
704
705bool PartialOrderingVisitor::CanBeVisited(BasicBlock *BB) const {
706 for (BasicBlock *P : predecessors(BB)) {
707 // Ignore back-edges.
708 if (DT.dominates(BB, P))
709 continue;
710
711 // One of the predecessor hasn't been visited. Not ready yet.
712 if (BlockToOrder.count(P) == 0)
713 return false;
714
715 // If the block is a loop exit, the loop must be finished before
716 // we can continue.
717 Loop *L = LI.getLoopFor(P);
718 if (L == nullptr || L->contains(BB))
719 continue;
720
721 // SPIR-V requires a single back-edge. And the backend first
722 // step transforms loops into the simplified format. If we have
723 // more than 1 back-edge, something is wrong.
724 assert(L->getNumBackEdges() <= 1);
725
726 // If the loop has no latch, loop's rank won't matter, so we can
727 // proceed.
728 BasicBlock *Latch = L->getLoopLatch();
729 assert(Latch);
730 if (Latch == nullptr)
731 continue;
732
733 // The latch is not ready yet, let's wait.
734 if (BlockToOrder.count(Latch) == 0)
735 return false;
736 }
737
738 return true;
739}
740
742 auto It = BlockToOrder.find(BB);
743 if (It != BlockToOrder.end())
744 return It->second.Rank;
745
746 size_t result = 0;
747 for (BasicBlock *P : predecessors(BB)) {
748 // Ignore back-edges.
749 if (DT.dominates(BB, P))
750 continue;
751
752 auto Iterator = BlockToOrder.end();
753 Loop *L = LI.getLoopFor(P);
754 BasicBlock *Latch = L ? L->getLoopLatch() : nullptr;
755
756 // If the predecessor is either outside a loop, or part of
757 // the same loop, simply take its rank + 1.
758 if (L == nullptr || L->contains(BB) || Latch == nullptr) {
759 Iterator = BlockToOrder.find(P);
760 } else {
761 // Otherwise, take the loop's rank (highest rank in the loop) as base.
762 // Since loops have a single latch, highest rank is easy to find.
763 // If the loop has no latch, then it doesn't matter.
764 Iterator = BlockToOrder.find(Latch);
765 }
766
767 assert(Iterator != BlockToOrder.end());
768 result = std::max(result, Iterator->second.Rank + 1);
769 }
770
771 return result;
772}
773
774size_t PartialOrderingVisitor::visit(BasicBlock *BB, size_t Unused) {
775 ToVisit.push(BB);
776 Queued.insert(BB);
777
778 size_t QueueIndex = 0;
779 while (ToVisit.size() != 0) {
780 BasicBlock *BB = ToVisit.front();
781 ToVisit.pop();
782
783 if (!CanBeVisited(BB)) {
784 ToVisit.push(BB);
785 if (QueueIndex >= ToVisit.size())
787 "No valid candidate in the queue. Is the graph reducible?");
788 QueueIndex++;
789 continue;
790 }
791
792 QueueIndex = 0;
793 size_t Rank = GetNodeRank(BB);
794 OrderInfo Info = {Rank, BlockToOrder.size()};
795 BlockToOrder.emplace(BB, Info);
796
797 for (BasicBlock *S : successors(BB)) {
798 if (Queued.count(S) != 0)
799 continue;
800 ToVisit.push(S);
801 Queued.insert(S);
802 }
803 }
804
805 return 0;
806}
807
809 DT.recalculate(F);
810 LI = LoopInfo(DT);
811
812 visit(&*F.begin(), 0);
813
814 Order.reserve(F.size());
815 for (auto &[BB, Info] : BlockToOrder)
816 Order.emplace_back(BB);
817
818 std::sort(Order.begin(), Order.end(), [&](const auto &LHS, const auto &RHS) {
819 return compare(LHS, RHS);
820 });
821}
822
824 const BasicBlock *RHS) const {
825 const OrderInfo &InfoLHS = BlockToOrder.at(const_cast<BasicBlock *>(LHS));
826 const OrderInfo &InfoRHS = BlockToOrder.at(const_cast<BasicBlock *>(RHS));
827 if (InfoLHS.Rank != InfoRHS.Rank)
828 return InfoLHS.Rank < InfoRHS.Rank;
829 return InfoLHS.TraversalIndex < InfoRHS.TraversalIndex;
830}
831
833 BasicBlock &Start, std::function<bool(BasicBlock *)> Op) {
834 std::unordered_set<BasicBlock *> Reachable = getReachableFrom(&Start);
835 assert(BlockToOrder.count(&Start) != 0);
836
837 // Skipping blocks with a rank inferior to |Start|'s rank.
838 auto It = Order.begin();
839 while (It != Order.end() && *It != &Start)
840 ++It;
841
842 // This is unexpected. Worst case |Start| is the last block,
843 // so It should point to the last block, not past-end.
844 assert(It != Order.end());
845
846 // By default, there is no rank limit. Setting it to the maximum value.
847 std::optional<size_t> EndRank = std::nullopt;
848 for (; It != Order.end(); ++It) {
849 if (EndRank.has_value() && BlockToOrder[*It].Rank > *EndRank)
850 break;
851
852 if (Reachable.count(*It) == 0) {
853 continue;
854 }
855
856 if (!Op(*It)) {
857 EndRank = BlockToOrder[*It].Rank;
858 }
859 }
860}
861
863 if (F.size() == 0)
864 return false;
865
866 bool Modified = false;
867 std::vector<BasicBlock *> Order;
868 Order.reserve(F.size());
869
871 llvm::append_range(Order, RPOT);
872
873 assert(&*F.begin() == Order[0]);
874 BasicBlock *LastBlock = &*F.begin();
875 for (BasicBlock *BB : Order) {
876 if (BB != LastBlock && &*LastBlock->getNextNode() != BB) {
877 Modified = true;
878 BB->moveAfter(LastBlock);
879 }
880 LastBlock = BB;
881 }
882
883 return Modified;
884}
885
887 const DataLayout &DL = F.getDataLayout();
888 return new AllocaInst(Type, DL.getAllocaAddrSpace(), nullptr, "reg",
889 F.begin()->getFirstInsertionPt());
890}
891
892Value *
894 const DenseMap<BasicBlock *, ConstantInt *> &TargetToValue) {
895 auto *T = BB->getTerminator();
896 if (isa<ReturnInst>(T))
897 return nullptr;
898 if (auto *BI = dyn_cast<UncondBrInst>(T))
899 return TargetToValue.lookup(BI->getSuccessor());
900
901 IRBuilder<> Builder(BB);
902 Builder.SetInsertPoint(T);
903
904 if (auto *BI = dyn_cast<CondBrInst>(T)) {
905 Value *LHS = TargetToValue.lookup(BI->getSuccessor(0));
906 Value *RHS = TargetToValue.lookup(BI->getSuccessor(1));
907
908 if (LHS == nullptr || RHS == nullptr)
909 return LHS == nullptr ? RHS : LHS;
910 return Builder.CreateSelect(BI->getCondition(), LHS, RHS);
911 }
912
913 // TODO: add support for switch cases.
914 llvm_unreachable("Unhandled terminator type.");
915}
916
918 MachineInstr *MaybeDef = MRI.getVRegDef(Reg);
919 if (MaybeDef && MaybeDef->getOpcode() == SPIRV::ASSIGN_TYPE)
920 MaybeDef = MRI.getVRegDef(MaybeDef->getOperand(1).getReg());
921 return MaybeDef;
922}
923
924bool getVacantFunctionName(Module &M, std::string &Name) {
925 // It's a bit of paranoia, but still we don't want to have even a chance that
926 // the loop will work for too long.
927 constexpr unsigned MaxIters = 1024;
928 for (unsigned I = 0; I < MaxIters; ++I) {
929 std::string OrdName = Name + Twine(I).str();
930 if (!M.getFunction(OrdName)) {
931 Name = std::move(OrdName);
932 return true;
933 }
934 }
935 return false;
936}
937
938// Assign SPIR-V type to the register. If the register has no valid assigned
939// class, set register LLT type and class according to the SPIR-V type.
942 const MachineFunction &MF, bool Force) {
943 GR->assignSPIRVTypeToVReg(SpvType, Reg, MF);
944 if (!MRI->getRegClassOrNull(Reg) || Force) {
945 MRI->setRegClass(Reg, GR->getRegClass(SpvType));
946 LLT RegType = GR->getRegType(SpvType);
947 if (Force || !MRI->getType(Reg).isValid())
948 MRI->setType(Reg, RegType);
949 }
950}
951
952// Create a SPIR-V type, assign SPIR-V type to the register. If the register has
953// no valid assigned class, set register LLT type and class according to the
954// SPIR-V type.
956 MachineIRBuilder &MIRBuilder,
957 SPIRV::AccessQualifier::AccessQualifier AccessQual,
958 bool EmitIR, bool Force) {
960 GR->getOrCreateSPIRVType(Ty, MIRBuilder, AccessQual, EmitIR),
961 GR, MIRBuilder.getMRI(), MIRBuilder.getMF(), Force);
962}
963
964// Create a virtual register and assign SPIR-V type to the register. Set
965// register LLT type and class according to the SPIR-V type.
968 const MachineFunction &MF) {
969 Register Reg = MRI->createVirtualRegister(GR->getRegClass(SpvType));
970 MRI->setType(Reg, GR->getRegType(SpvType));
971 GR->assignSPIRVTypeToVReg(SpvType, Reg, MF);
972 return Reg;
973}
974
975// Create a virtual register and assign SPIR-V type to the register. Set
976// register LLT type and class according to the SPIR-V type.
978 MachineIRBuilder &MIRBuilder) {
979 return createVirtualRegister(SpvType, GR, MIRBuilder.getMRI(),
980 MIRBuilder.getMF());
981}
982
983// Create a SPIR-V type, virtual register and assign SPIR-V type to the
984// register. Set register LLT type and class according to the SPIR-V type.
986 const Type *Ty, SPIRVGlobalRegistry *GR, MachineIRBuilder &MIRBuilder,
987 SPIRV::AccessQualifier::AccessQualifier AccessQual, bool EmitIR) {
989 GR->getOrCreateSPIRVType(Ty, MIRBuilder, AccessQual, EmitIR), GR,
990 MIRBuilder);
991}
992
994 Value *Arg, Value *Arg2, ArrayRef<Constant *> Imms,
995 IRBuilder<> &B) {
997 Args.push_back(Arg2);
998 Args.push_back(buildMD(Arg));
999 llvm::append_range(Args, Imms);
1000 return B.CreateIntrinsic(IntrID, {Types}, Args);
1001}
1002
1003// Return true if there is an opaque pointer type nested in the argument.
1004bool isNestedPointer(const Type *Ty) {
1005 if (Ty->isPtrOrPtrVectorTy())
1006 return true;
1007 if (const FunctionType *RefTy = dyn_cast<FunctionType>(Ty)) {
1008 if (isNestedPointer(RefTy->getReturnType()))
1009 return true;
1010 for (const Type *ArgTy : RefTy->params())
1011 if (isNestedPointer(ArgTy))
1012 return true;
1013 return false;
1014 }
1015 if (const ArrayType *RefTy = dyn_cast<ArrayType>(Ty))
1016 return isNestedPointer(RefTy->getElementType());
1017 return false;
1018}
1019
1020bool isSpvIntrinsic(const Value *Arg) {
1021 if (const auto *II = dyn_cast<IntrinsicInst>(Arg))
1022 if (Function *F = II->getCalledFunction())
1023 if (F->getName().starts_with("llvm.spv."))
1024 return true;
1025 return false;
1026}
1027
1028// Function to create continued instructions for SPV_INTEL_long_composites
1029// extension
1030SmallVector<MachineInstr *, 4>
1032 unsigned MinWC, unsigned ContinuedOpcode,
1033 ArrayRef<Register> Args, Register ReturnRegister,
1034 Register TypeID) {
1035
1036 SmallVector<MachineInstr *, 4> Instructions;
1037 constexpr unsigned MaxWordCount = UINT16_MAX;
1038 const size_t NumElements = Args.size();
1039 size_t MaxNumElements = MaxWordCount - MinWC;
1040 size_t SPIRVStructNumElements = NumElements;
1041
1042 if (NumElements > MaxNumElements) {
1043 // Do adjustments for continued instructions which always had only one
1044 // minumum word count.
1045 SPIRVStructNumElements = MaxNumElements;
1046 MaxNumElements = MaxWordCount - 1;
1047 }
1048
1049 auto MIB =
1050 MIRBuilder.buildInstr(Opcode).addDef(ReturnRegister).addUse(TypeID);
1051
1052 for (size_t I = 0; I < SPIRVStructNumElements; ++I)
1053 MIB.addUse(Args[I]);
1054
1055 Instructions.push_back(MIB.getInstr());
1056
1057 for (size_t I = SPIRVStructNumElements; I < NumElements;
1058 I += MaxNumElements) {
1059 auto MIB = MIRBuilder.buildInstr(ContinuedOpcode);
1060 for (size_t J = I; J < std::min(I + MaxNumElements, NumElements); ++J)
1061 MIB.addUse(Args[J]);
1062 Instructions.push_back(MIB.getInstr());
1063 }
1064 return Instructions;
1065}
1066
1067SmallVector<unsigned, 1>
1069 unsigned LC = SPIRV::LoopControl::None;
1070 // Currently used only to store PartialCount value. Later when other
1071 // LoopControls are added - this map should be sorted before making
1072 // them loop_merge operands to satisfy 3.23. Loop Control requirements.
1073 std::vector<std::pair<unsigned, unsigned>> MaskToValueMap;
1074 if (findOptionMDForLoopID(LoopMD, "llvm.loop.unroll.disable")) {
1075 LC |= SPIRV::LoopControl::DontUnroll;
1076 } else {
1077 if (findOptionMDForLoopID(LoopMD, "llvm.loop.unroll.enable") ||
1078 findOptionMDForLoopID(LoopMD, "llvm.loop.unroll.full")) {
1079 LC |= SPIRV::LoopControl::Unroll;
1080 }
1081 if (MDNode *CountMD =
1082 findOptionMDForLoopID(LoopMD, "llvm.loop.unroll.count")) {
1083 if (auto *CI =
1084 mdconst::extract_or_null<ConstantInt>(CountMD->getOperand(1))) {
1085 unsigned Count = CI->getZExtValue();
1086 if (Count != 1) {
1087 LC |= SPIRV::LoopControl::PartialCount;
1088 MaskToValueMap.emplace_back(
1089 std::make_pair(SPIRV::LoopControl::PartialCount, Count));
1090 }
1091 }
1092 }
1093 }
1094 SmallVector<unsigned, 1> Result = {LC};
1095 for (auto &[Mask, Val] : MaskToValueMap)
1096 Result.push_back(Val);
1097 return Result;
1098}
1099
1103
1104const std::set<unsigned> &getTypeFoldingSupportedOpcodes() {
1105 // clang-format off
1106 static const std::set<unsigned> TypeFoldingSupportingOpcs = {
1107 TargetOpcode::G_ADD,
1108 TargetOpcode::G_FADD,
1109 TargetOpcode::G_STRICT_FADD,
1110 TargetOpcode::G_SUB,
1111 TargetOpcode::G_FSUB,
1112 TargetOpcode::G_STRICT_FSUB,
1113 TargetOpcode::G_MUL,
1114 TargetOpcode::G_FMUL,
1115 TargetOpcode::G_STRICT_FMUL,
1116 TargetOpcode::G_SDIV,
1117 TargetOpcode::G_UDIV,
1118 TargetOpcode::G_FDIV,
1119 TargetOpcode::G_STRICT_FDIV,
1120 TargetOpcode::G_SREM,
1121 TargetOpcode::G_UREM,
1122 TargetOpcode::G_FREM,
1123 TargetOpcode::G_STRICT_FREM,
1124 TargetOpcode::G_FNEG,
1125 TargetOpcode::G_CONSTANT,
1126 TargetOpcode::G_FCONSTANT,
1127 TargetOpcode::G_AND,
1128 TargetOpcode::G_OR,
1129 TargetOpcode::G_XOR,
1130 TargetOpcode::G_SHL,
1131 TargetOpcode::G_ASHR,
1132 TargetOpcode::G_LSHR,
1133 TargetOpcode::G_SELECT,
1134 TargetOpcode::G_EXTRACT_VECTOR_ELT,
1135 };
1136 // clang-format on
1137 return TypeFoldingSupportingOpcs;
1138}
1139
1140bool isTypeFoldingSupported(unsigned Opcode) {
1141 return getTypeFoldingSupportedOpcodes().count(Opcode) > 0;
1142}
1143
1144// Traversing [g]MIR accounting for pseudo-instructions.
1146 return (Def->getOpcode() == SPIRV::ASSIGN_TYPE ||
1147 Def->getOpcode() == TargetOpcode::COPY)
1148 ? MRI->getVRegDef(Def->getOperand(1).getReg())
1149 : Def;
1150}
1151
1153 if (MachineInstr *Def = MRI->getVRegDef(MO.getReg()))
1154 return passCopy(Def, MRI);
1155 return nullptr;
1156}
1157
1159 if (MachineInstr *Def = getDef(MO, MRI)) {
1160 if (Def->getOpcode() == TargetOpcode::G_CONSTANT ||
1161 Def->getOpcode() == SPIRV::OpConstantI)
1162 return Def;
1163 }
1164 return nullptr;
1165}
1166
1167int64_t foldImm(const MachineOperand &MO, const MachineRegisterInfo *MRI) {
1168 if (MachineInstr *Def = getImm(MO, MRI)) {
1169 if (Def->getOpcode() == SPIRV::OpConstantI)
1170 return Def->getOperand(2).getImm();
1171 if (Def->getOpcode() == TargetOpcode::G_CONSTANT)
1172 return Def->getOperand(1).getCImm()->getZExtValue();
1173 }
1174 llvm_unreachable("Unexpected integer constant pattern");
1175}
1176
1178 const MachineInstr *ResType) {
1179 return foldImm(ResType->getOperand(2), MRI);
1180}
1181
1182bool matchPeeledArrayPattern(const StructType *Ty, Type *&OriginalElementType,
1183 uint64_t &TotalSize) {
1184 // An array of N padded structs is represented as {[N-1 x <{T, pad}>], T}.
1185 if (Ty->getStructNumElements() != 2)
1186 return false;
1187
1188 Type *FirstElement = Ty->getStructElementType(0);
1189 Type *SecondElement = Ty->getStructElementType(1);
1190
1191 if (!FirstElement->isArrayTy())
1192 return false;
1193
1194 Type *ArrayElementType = FirstElement->getArrayElementType();
1195 if (!ArrayElementType->isStructTy() ||
1196 ArrayElementType->getStructNumElements() != 2)
1197 return false;
1198
1199 Type *T_in_struct = ArrayElementType->getStructElementType(0);
1200 if (T_in_struct != SecondElement)
1201 return false;
1202
1203 auto *Padding_in_struct =
1204 dyn_cast<TargetExtType>(ArrayElementType->getStructElementType(1));
1205 if (!Padding_in_struct || Padding_in_struct->getName() != "spirv.Padding")
1206 return false;
1207
1208 const uint64_t ArraySize = FirstElement->getArrayNumElements();
1209 TotalSize = ArraySize + 1;
1210 OriginalElementType = ArrayElementType;
1211 return true;
1212}
1213
1215 if (!Ty->isStructTy())
1216 return Ty;
1217
1218 auto *STy = cast<StructType>(Ty);
1219 Type *OriginalElementType = nullptr;
1220 uint64_t TotalSize = 0;
1221 if (matchPeeledArrayPattern(STy, OriginalElementType, TotalSize)) {
1222 Type *ResultTy = ArrayType::get(
1223 reconstitutePeeledArrayType(OriginalElementType), TotalSize);
1224 return ResultTy;
1225 }
1226
1227 SmallVector<Type *, 4> NewElementTypes;
1228 bool Changed = false;
1229 for (Type *ElementTy : STy->elements()) {
1230 Type *NewElementTy = reconstitutePeeledArrayType(ElementTy);
1231 if (NewElementTy != ElementTy)
1232 Changed = true;
1233 NewElementTypes.push_back(NewElementTy);
1234 }
1235
1236 if (!Changed)
1237 return Ty;
1238
1239 Type *ResultTy;
1240 if (STy->isLiteral())
1241 ResultTy =
1242 StructType::get(STy->getContext(), NewElementTypes, STy->isPacked());
1243 else {
1244 auto *NewTy = StructType::create(STy->getContext(), STy->getName());
1245 NewTy->setBody(NewElementTypes, STy->isPacked());
1246 ResultTy = NewTy;
1247 }
1248 return ResultTy;
1249}
1250
1251std::optional<SPIRV::LinkageType::LinkageType>
1253 if (GV.hasLocalLinkage())
1254 return std::nullopt;
1255
1256 if (GV.isDeclarationForLinker()) {
1257 // Interface variables must not get Import linkage.
1258 if (const auto *GVar = dyn_cast<GlobalVariable>(&GV)) {
1259 auto SC = addressSpaceToStorageClass(GVar->getAddressSpace(), ST);
1260 if (SC == SPIRV::StorageClass::Input ||
1261 SC == SPIRV::StorageClass::Output ||
1262 SC == SPIRV::StorageClass::PushConstant)
1263 return std::nullopt;
1264 }
1265 return SPIRV::LinkageType::Import;
1266 }
1267
1268 if (GV.hasHiddenVisibility())
1269 return std::nullopt;
1270
1271 if (GV.hasLinkOnceODRLinkage() &&
1272 ST.canUseExtension(SPIRV::Extension::SPV_KHR_linkonce_odr))
1273 return SPIRV::LinkageType::LinkOnceODR;
1274
1275 if (GV.hasWeakLinkage() &&
1276 ST.canUseExtension(SPIRV::Extension::SPV_AMD_weak_linkage))
1277 return SPIRV::LinkageType::WeakAMD;
1278
1279 return SPIRV::LinkageType::Export;
1280}
1281
1283 std::string ServiceFunName = SPIRV_BACKEND_SERVICE_FUN_NAME;
1284 if (!getVacantFunctionName(M, ServiceFunName))
1286 "cannot allocate a name for the internal service function");
1287 if (Function *SF = M.getFunction(ServiceFunName)) {
1288 if (SF->getInstructionCount() > 0)
1290 "Unexpected combination of global variables and function pointers");
1291 return SF;
1292 }
1294 FunctionType::get(Type::getVoidTy(M.getContext()), {}, false),
1295 GlobalValue::PrivateLinkage, ServiceFunName, M);
1297 return SF;
1298}
1299
1300} // 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)
static ConstantInt * getConstInt(MDNode *MD, unsigned NumOp)
#define SPIRV_BACKEND_SERVICE_FUN_NAME
Definition SPIRVUtils.h:543
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:484
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:859
StringRef getAsCString() const
If this array is isCString(), then this method returns the array (without the trailing null byte) as ...
Definition Constants.h:832
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:252
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:634
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:2868
LLVM_ABI const Module * getModule() const
Return the module owning the function this instruction belongs to or nullptr it the function does not...
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:1433
unsigned getNumOperands() const
Return number of MDNode operands.
Definition Metadata.h:1439
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:1749
op_iterator op_end()
Definition Metadata.h:1838
iterator_range< op_iterator > operands()
Definition Metadata.h:1845
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
LLT getRegType(SPIRVTypeInst SpvType) const
SPIRVTypeInst getOrCreateSPIRVType(const Type *Type, MachineInstr &I, SPIRV::AccessQualifier::AccessQualifier AQ, bool EmitIR)
bool canUseExtension(SPIRV::Extension::Extension E) const
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:479
static LLVM_ABI StructType * create(LLVMContext &Context, StringRef Name)
This creates an identified struct.
Definition Type.cpp:685
Class to represent target extensions types, which are generally unintrospectable from target-independ...
Target - Wrapper for Target specific information.
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
LLVM Value Representation.
Definition Value.h:75
LLVM_ABI StringRef getName() const
Return a constant reference to the value's name.
Definition Value.cpp:319
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)
FunctionType * getOriginalFunctionType(const Function &F)
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.
void buildOpName(Register Target, const StringRef &Name, MachineIRBuilder &MIRBuilder)
bool getVacantFunctionName(Module &M, std::string &Name)
std::string getStringImm(const MachineInstr &MI, unsigned StartIndex)
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.
static void finishBuildOpDecorate(MachineInstrBuilder &MIB, const std::vector< uint32_t > &DecArgs, StringRef StrImm)
bool isTypeFoldingSupported(unsigned Opcode)
static uint32_t convertCharsToWord(const StringRef &Str, unsigned i)
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:2207
unsigned getArrayComponentCount(const MachineRegisterInfo *MRI, const MachineInstr *ResType)
bool sortBlocks(Function &F)
AllocaInst * createVariable(Function &F, Type *Type)
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)
SmallVector< unsigned, 1 > getSpirvLoopControlOperandsFromLoopMetadata(MDNode *LoopMD)
void buildOpDecorate(Register Reg, MachineIRBuilder &MIRBuilder, SPIRV::Decoration::Decoration Dec, const std::vector< uint32_t > &DecArgs, StringRef StrImm)
MachineInstr * getImm(const MachineOperand &MO, const MachineRegisterInfo *MRI)
std::string getSPIRVStringOperand(const InstType &MI, unsigned StartIndex)
void buildOpMemberDecorate(Register Reg, MachineIRBuilder &MIRBuilder, SPIRV::Decoration::Decoration Dec, uint32_t Member, const std::vector< uint32_t > &DecArgs, StringRef StrImm)
Type * toTypedPointer(Type *Ty)
Definition SPIRVUtils.h:476
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,...
bool isSpecialOpaqueType(const Type *Ty)
LLVM_ABI void report_fatal_error(Error Err, bool gen_crash_diag=true)
Definition Error.cpp:163
void setRegClassType(Register Reg, SPIRVTypeInst SpvType, SPIRVGlobalRegistry *GR, MachineRegisterInfo *MRI, const MachineFunction &MF, bool Force)
MachineBasicBlock::iterator getInsertPtValidEnd(MachineBasicBlock *MBB)
FunctionAddr VTableAddr Count
Definition InstrProf.h:139
static bool isNonMangledOCLBuiltin(StringRef Name)
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)
const std::set< unsigned > & getTypeFoldingSupportedOpcodes()
SPIRV::StorageClass::StorageClass addressSpaceToStorageClass(unsigned AddrSpace, const SPIRVSubtarget &STI)
AtomicOrdering
Atomic ordering for LLVM's memory model.
SPIRV::Scope::Scope getMemScope(LLVMContext &Ctx, SyncScope::ID Id)
static bool isPipeOrAddressSpaceCastBI(const StringRef MangledName)
void buildOpSpirvDecorations(Register Reg, MachineIRBuilder &MIRBuilder, const MDNode *GVarMD, const SPIRVSubtarget &ST)
std::string getStringValueFromReg(Register Reg, MachineRegisterInfo &MRI)
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)
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:1771
auto predecessors(const MachineBasicBlock *BB)
static size_t getPaddedLen(const StringRef &Str)
bool isSpvIntrinsic(const MachineInstr &MI, Intrinsic::ID IntrinsicID)
void addStringImm(const StringRef &Str, MCInst &Inst)
static bool isKernelQueryBI(const StringRef MangledName)
MachineInstr * getVRegDef(MachineRegisterInfo &MRI, Register Reg)
static bool isEnqueueKernelBI(const StringRef MangledName)
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