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 MachineInstr *MaybeDef = MRI.getVRegDef(Reg);
888 if (MaybeDef && MaybeDef->getOpcode() == SPIRV::ASSIGN_TYPE)
889 MaybeDef = MRI.getVRegDef(MaybeDef->getOperand(1).getReg());
890 return MaybeDef;
891}
892
893bool getVacantFunctionName(Module &M, std::string &Name) {
894 // It's a bit of paranoia, but still we don't want to have even a chance that
895 // the loop will work for too long.
896 constexpr unsigned MaxIters = 1024;
897 for (unsigned I = 0; I < MaxIters; ++I) {
898 std::string OrdName = Name + Twine(I).str();
899 if (!M.getFunction(OrdName)) {
900 Name = std::move(OrdName);
901 return true;
902 }
903 }
904 return false;
905}
906
907// Assign SPIR-V type to the register. If the register has no valid assigned
908// class, set register LLT type and class according to the SPIR-V type.
911 const MachineFunction &MF, bool Force) {
912 GR->assignSPIRVTypeToVReg(SpvType, Reg, MF);
913 if (!MRI->getRegClassOrNull(Reg) || Force) {
914 MRI->setRegClass(Reg, GR->getRegClass(SpvType));
915 LLT RegType = GR->getRegType(SpvType);
916 if (Force || !MRI->getType(Reg).isValid())
917 MRI->setType(Reg, RegType);
918 }
919}
920
921// Create a SPIR-V type, assign SPIR-V type to the register. If the register has
922// no valid assigned class, set register LLT type and class according to the
923// SPIR-V type.
925 MachineIRBuilder &MIRBuilder,
926 SPIRV::AccessQualifier::AccessQualifier AccessQual,
927 bool EmitIR, bool Force) {
929 GR->getOrCreateSPIRVType(Ty, MIRBuilder, AccessQual, EmitIR),
930 GR, MIRBuilder.getMRI(), MIRBuilder.getMF(), Force);
931}
932
933// Create a virtual register and assign SPIR-V type to the register. Set
934// register LLT type and class according to the SPIR-V type.
937 const MachineFunction &MF) {
938 Register Reg = MRI->createVirtualRegister(GR->getRegClass(SpvType));
939 MRI->setType(Reg, GR->getRegType(SpvType));
940 GR->assignSPIRVTypeToVReg(SpvType, Reg, MF);
941 return Reg;
942}
943
944// Create a virtual register and assign SPIR-V type to the register. Set
945// register LLT type and class according to the SPIR-V type.
947 MachineIRBuilder &MIRBuilder) {
948 return createVirtualRegister(SpvType, GR, MIRBuilder.getMRI(),
949 MIRBuilder.getMF());
950}
951
952// Create a SPIR-V type, virtual register and assign SPIR-V type to the
953// register. Set register LLT type and class according to the SPIR-V type.
955 const Type *Ty, SPIRVGlobalRegistry *GR, MachineIRBuilder &MIRBuilder,
956 SPIRV::AccessQualifier::AccessQualifier AccessQual, bool EmitIR) {
958 GR->getOrCreateSPIRVType(Ty, MIRBuilder, AccessQual, EmitIR), GR,
959 MIRBuilder);
960}
961
963 Value *Arg, Value *Arg2, ArrayRef<Constant *> Imms,
964 IRBuilder<> &B) {
966 Args.push_back(Arg2);
967 Args.push_back(buildMD(Arg));
968 llvm::append_range(Args, Imms);
969 return B.CreateIntrinsic(IntrID, {Types}, Args);
970}
971
972// Return true if there is an opaque pointer type nested in the argument.
973bool isNestedPointer(const Type *Ty) {
974 if (Ty->isPtrOrPtrVectorTy())
975 return true;
976 if (const FunctionType *RefTy = dyn_cast<FunctionType>(Ty)) {
977 if (isNestedPointer(RefTy->getReturnType()))
978 return true;
979 for (const Type *ArgTy : RefTy->params())
980 if (isNestedPointer(ArgTy))
981 return true;
982 return false;
983 }
984 if (const ArrayType *RefTy = dyn_cast<ArrayType>(Ty))
985 return isNestedPointer(RefTy->getElementType());
986 return false;
987}
988
989bool isSpvIntrinsic(const Value *Arg) {
990 if (const auto *II = dyn_cast<IntrinsicInst>(Arg))
991 if (Function *F = II->getCalledFunction())
992 if (F->getName().starts_with("llvm.spv."))
993 return true;
994 return false;
995}
996
997// Function to create continued instructions for SPV_INTEL_long_composites
998// extension
999SmallVector<MachineInstr *, 4>
1001 unsigned MinWC, unsigned ContinuedOpcode,
1002 ArrayRef<Register> Args, Register ReturnRegister,
1003 Register TypeID) {
1004
1005 SmallVector<MachineInstr *, 4> Instructions;
1006 constexpr unsigned MaxWordCount = UINT16_MAX;
1007 const size_t NumElements = Args.size();
1008 size_t MaxNumElements = MaxWordCount - MinWC;
1009 size_t SPIRVStructNumElements = NumElements;
1010
1011 if (NumElements > MaxNumElements) {
1012 // Do adjustments for continued instructions which always had only one
1013 // minumum word count.
1014 SPIRVStructNumElements = MaxNumElements;
1015 MaxNumElements = MaxWordCount - 1;
1016 }
1017
1018 auto MIB =
1019 MIRBuilder.buildInstr(Opcode).addDef(ReturnRegister).addUse(TypeID);
1020
1021 for (size_t I = 0; I < SPIRVStructNumElements; ++I)
1022 MIB.addUse(Args[I]);
1023
1024 Instructions.push_back(MIB.getInstr());
1025
1026 for (size_t I = SPIRVStructNumElements; I < NumElements;
1027 I += MaxNumElements) {
1028 auto MIB = MIRBuilder.buildInstr(ContinuedOpcode);
1029 for (size_t J = I; J < std::min(I + MaxNumElements, NumElements); ++J)
1030 MIB.addUse(Args[J]);
1031 Instructions.push_back(MIB.getInstr());
1032 }
1033 return Instructions;
1034}
1035
1036SmallVector<unsigned, 1>
1038 unsigned LC = SPIRV::LoopControl::None;
1039 // Currently used only to store PartialCount value. Later when other
1040 // LoopControls are added - this map should be sorted before making
1041 // them loop_merge operands to satisfy 3.23. Loop Control requirements.
1042 std::vector<std::pair<unsigned, unsigned>> MaskToValueMap;
1043 if (findOptionMDForLoopID(LoopMD, "llvm.loop.unroll.disable")) {
1044 LC |= SPIRV::LoopControl::DontUnroll;
1045 } else {
1046 if (findOptionMDForLoopID(LoopMD, "llvm.loop.unroll.enable") ||
1047 findOptionMDForLoopID(LoopMD, "llvm.loop.unroll.full")) {
1048 LC |= SPIRV::LoopControl::Unroll;
1049 }
1050 if (MDNode *CountMD =
1051 findOptionMDForLoopID(LoopMD, "llvm.loop.unroll.count")) {
1052 if (auto *CI =
1053 mdconst::extract_or_null<ConstantInt>(CountMD->getOperand(1))) {
1054 unsigned Count = CI->getZExtValue();
1055 if (Count != 1) {
1056 LC |= SPIRV::LoopControl::PartialCount;
1057 MaskToValueMap.emplace_back(
1058 std::make_pair(SPIRV::LoopControl::PartialCount, Count));
1059 }
1060 }
1061 }
1062 }
1063 SmallVector<unsigned, 1> Result = {LC};
1064 for (auto &[Mask, Val] : MaskToValueMap)
1065 Result.push_back(Val);
1066 return Result;
1067}
1068
1072
1073const std::set<unsigned> &getTypeFoldingSupportedOpcodes() {
1074 // clang-format off
1075 static const std::set<unsigned> TypeFoldingSupportingOpcs = {
1076 TargetOpcode::G_ADD,
1077 TargetOpcode::G_FADD,
1078 TargetOpcode::G_STRICT_FADD,
1079 TargetOpcode::G_SUB,
1080 TargetOpcode::G_FSUB,
1081 TargetOpcode::G_STRICT_FSUB,
1082 TargetOpcode::G_MUL,
1083 TargetOpcode::G_FMUL,
1084 TargetOpcode::G_STRICT_FMUL,
1085 TargetOpcode::G_SDIV,
1086 TargetOpcode::G_UDIV,
1087 TargetOpcode::G_FDIV,
1088 TargetOpcode::G_STRICT_FDIV,
1089 TargetOpcode::G_SREM,
1090 TargetOpcode::G_UREM,
1091 TargetOpcode::G_FREM,
1092 TargetOpcode::G_STRICT_FREM,
1093 TargetOpcode::G_FNEG,
1094 TargetOpcode::G_CONSTANT,
1095 TargetOpcode::G_FCONSTANT,
1096 TargetOpcode::G_AND,
1097 TargetOpcode::G_OR,
1098 TargetOpcode::G_XOR,
1099 TargetOpcode::G_SHL,
1100 TargetOpcode::G_ASHR,
1101 TargetOpcode::G_LSHR,
1102 TargetOpcode::G_SELECT,
1103 TargetOpcode::G_EXTRACT_VECTOR_ELT,
1104 };
1105 // clang-format on
1106 return TypeFoldingSupportingOpcs;
1107}
1108
1109bool isTypeFoldingSupported(unsigned Opcode) {
1110 return getTypeFoldingSupportedOpcodes().count(Opcode) > 0;
1111}
1112
1113// Traversing [g]MIR accounting for pseudo-instructions.
1115 return (Def->getOpcode() == SPIRV::ASSIGN_TYPE ||
1116 Def->getOpcode() == TargetOpcode::COPY)
1117 ? MRI->getVRegDef(Def->getOperand(1).getReg())
1118 : Def;
1119}
1120
1122 if (MachineInstr *Def = MRI->getVRegDef(MO.getReg()))
1123 return passCopy(Def, MRI);
1124 return nullptr;
1125}
1126
1128 if (MachineInstr *Def = getDef(MO, MRI)) {
1129 if (Def->getOpcode() == TargetOpcode::G_CONSTANT ||
1130 Def->getOpcode() == SPIRV::OpConstantI)
1131 return Def;
1132 }
1133 return nullptr;
1134}
1135
1136int64_t foldImm(const MachineOperand &MO, const MachineRegisterInfo *MRI) {
1137 if (MachineInstr *Def = getImm(MO, MRI)) {
1138 if (Def->getOpcode() == SPIRV::OpConstantI)
1139 return Def->getOperand(2).getImm();
1140 if (Def->getOpcode() == TargetOpcode::G_CONSTANT)
1141 return Def->getOperand(1).getCImm()->getZExtValue();
1142 }
1143 llvm_unreachable("Unexpected integer constant pattern");
1144}
1145
1147 const MachineInstr *ResType) {
1148 return foldImm(ResType->getOperand(2), MRI);
1149}
1150
1151bool matchPeeledArrayPattern(const StructType *Ty, Type *&OriginalElementType,
1152 uint64_t &TotalSize) {
1153 // An array of N padded structs is represented as {[N-1 x <{T, pad}>], T}.
1154 if (Ty->getStructNumElements() != 2)
1155 return false;
1156
1157 Type *FirstElement = Ty->getStructElementType(0);
1158 Type *SecondElement = Ty->getStructElementType(1);
1159
1160 if (!FirstElement->isArrayTy())
1161 return false;
1162
1163 Type *ArrayElementType = FirstElement->getArrayElementType();
1164 if (!ArrayElementType->isStructTy() ||
1165 ArrayElementType->getStructNumElements() != 2)
1166 return false;
1167
1168 Type *T_in_struct = ArrayElementType->getStructElementType(0);
1169 if (T_in_struct != SecondElement)
1170 return false;
1171
1172 auto *Padding_in_struct =
1173 dyn_cast<TargetExtType>(ArrayElementType->getStructElementType(1));
1174 if (!Padding_in_struct || Padding_in_struct->getName() != "spirv.Padding")
1175 return false;
1176
1177 const uint64_t ArraySize = FirstElement->getArrayNumElements();
1178 TotalSize = ArraySize + 1;
1179 OriginalElementType = ArrayElementType;
1180 return true;
1181}
1182
1184 if (!Ty->isStructTy())
1185 return Ty;
1186
1187 auto *STy = cast<StructType>(Ty);
1188 Type *OriginalElementType = nullptr;
1189 uint64_t TotalSize = 0;
1190 if (matchPeeledArrayPattern(STy, OriginalElementType, TotalSize)) {
1191 Type *ResultTy = ArrayType::get(
1192 reconstitutePeeledArrayType(OriginalElementType), TotalSize);
1193 return ResultTy;
1194 }
1195
1196 SmallVector<Type *, 4> NewElementTypes;
1197 bool Changed = false;
1198 for (Type *ElementTy : STy->elements()) {
1199 Type *NewElementTy = reconstitutePeeledArrayType(ElementTy);
1200 if (NewElementTy != ElementTy)
1201 Changed = true;
1202 NewElementTypes.push_back(NewElementTy);
1203 }
1204
1205 if (!Changed)
1206 return Ty;
1207
1208 Type *ResultTy;
1209 if (STy->isLiteral())
1210 ResultTy =
1211 StructType::get(STy->getContext(), NewElementTypes, STy->isPacked());
1212 else {
1213 auto *NewTy = StructType::create(STy->getContext(), STy->getName());
1214 NewTy->setBody(NewElementTypes, STy->isPacked());
1215 ResultTy = NewTy;
1216 }
1217 return ResultTy;
1218}
1219
1220std::optional<SPIRV::LinkageType::LinkageType>
1222 if (GV.hasLocalLinkage())
1223 return std::nullopt;
1224
1225 if (GV.isDeclarationForLinker()) {
1226 // Interface variables must not get Import linkage.
1227 if (const auto *GVar = dyn_cast<GlobalVariable>(&GV)) {
1228 auto SC = addressSpaceToStorageClass(GVar->getAddressSpace(), ST);
1229 if (SC == SPIRV::StorageClass::Input ||
1230 SC == SPIRV::StorageClass::Output ||
1231 SC == SPIRV::StorageClass::PushConstant)
1232 return std::nullopt;
1233 }
1234 return SPIRV::LinkageType::Import;
1235 }
1236
1237 if (GV.hasHiddenVisibility())
1238 return std::nullopt;
1239
1240 if (GV.hasLinkOnceODRLinkage() &&
1241 ST.canUseExtension(SPIRV::Extension::SPV_KHR_linkonce_odr))
1242 return SPIRV::LinkageType::LinkOnceODR;
1243
1244 if (GV.hasWeakLinkage() &&
1245 ST.canUseExtension(SPIRV::Extension::SPV_AMD_weak_linkage))
1246 return SPIRV::LinkageType::WeakAMD;
1247
1248 return SPIRV::LinkageType::Export;
1249}
1250
1252 std::string ServiceFunName = SPIRV_BACKEND_SERVICE_FUN_NAME;
1253 if (!getVacantFunctionName(M, ServiceFunName))
1255 "cannot allocate a name for the internal service function");
1256 if (Function *SF = M.getFunction(ServiceFunName)) {
1257 if (SF->getInstructionCount() > 0)
1259 "Unexpected combination of global variables and function pointers");
1260 return SF;
1261 }
1263 FunctionType::get(Type::getVoidTy(M.getContext()), {}, false),
1264 GlobalValue::PrivateLinkage, ServiceFunName, M);
1266 return SF;
1267}
1268
1269} // namespace llvm
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
MachineBasicBlock & MBB
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
uint64_t IntrinsicInst * II
#define P(N)
static ConstantInt * getConstInt(MDNode *MD, unsigned NumOp)
#define SPIRV_BACKEND_SERVICE_FUN_NAME
Definition SPIRVUtils.h:528
Value * RHS
Value * LHS
Class for arbitrary precision integers.
Definition APInt.h:78
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
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
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:638
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:1075
const MDOperand & getOperand(unsigned I) const
Definition Metadata.h:1439
unsigned getNumOperands() const
Return number of MDNode operands.
Definition Metadata.h:1445
A single uniqued string.
Definition Metadata.h:722
MachineInstrBundleIterator< MachineInstr > iterator
const MachineBasicBlock & front() const
Helper class to build MachineInstr.
MachineInstrBuilder buildInstr(unsigned Opcode)
Build and insert <empty> = Opcode <empty>.
MachineFunction & getMF()
Getter for the function we currently build.
MachineRegisterInfo * getMRI()
Getter for MRI.
const MachineInstrBuilder & addUse(Register RegNo, RegState Flags={}, unsigned SubReg=0) const
Add a virtual register use operand.
const MachineInstrBuilder & addImm(int64_t Val) const
Add a new immediate operand.
const MachineInstrBuilder & addDef(Register RegNo, RegState Flags={}, unsigned SubReg=0) const
Add a virtual register definition operand.
MachineInstr * getInstr() const
If conversion operators fail, use this method to get the MachineInstr explicitly.
Representation of each machine instruction.
unsigned getOpcode() const
Returns the opcode of this MachineInstr.
void setAsmPrinterFlag(AsmPrinterFlagTy Flag)
Set a flag for the AsmPrinter.
const MachineOperand & getOperand(unsigned i) const
MachineOperand class - Representation of each machine instruction operand.
Register getReg() const
getReg - Returns the register number.
MachineRegisterInfo - Keep track of information for virtual and physical registers,...
LLVM_ABI MachineInstr * getVRegDef(Register Reg) const
getVRegDef - Return the machine instr that defines the specified virtual register or null if none is ...
LLVM_ABI Register createVirtualRegister(const TargetRegisterClass *RegClass, StringRef Name="")
createVirtualRegister - Create and return a new virtual register in the function with the specified r...
LLT getType(Register Reg) const
Get the low-level type of Reg or LLT{} if Reg is not a generic (target independent) virtual register.
LLVM_ABI void setType(Register VReg, LLT Ty)
Set the low-level type of VReg to Ty.
LLVM_ABI void setRegClass(Register Reg, const TargetRegisterClass *RC)
setRegClass - Set the register class of the specified virtual register.
const TargetRegisterClass * getRegClassOrNull(Register Reg) const
Return the register class of Reg, or null if Reg has not been assigned a register class yet.
A Module instance is used to store all the information related to an LLVM module.
Definition Module.h:67
NamedMDNode * getNamedMetadata(StringRef Name) const
Return the first NamedMDNode in the module with the specified name.
Definition Module.cpp:301
A tuple of MDNodes.
Definition Metadata.h:1755
op_iterator op_end()
Definition Metadata.h:1844
iterator_range< op_iterator > operands()
Definition Metadata.h:1851
size_t GetNodeRank(BasicBlock *BB) const
void partialOrderVisit(BasicBlock &Start, std::function< bool(BasicBlock *)> Op)
bool compare(const BasicBlock *LHS, const BasicBlock *RHS) const
Wrapper class representing virtual and physical registers.
Definition Register.h:20
void assignSPIRVTypeToVReg(SPIRVTypeInst Type, Register VReg, const MachineFunction &MF)
const TargetRegisterClass * getRegClass(SPIRVTypeInst SpvType) const
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:318
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:406
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)
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:516
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:461
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)
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)
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