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