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 <cstring>
31#include <queue>
32#include <vector>
33
34namespace llvm {
35namespace SPIRV {
36// This code restores function args/retvalue types for composite cases
37// because the final types should still be aggregate whereas they're i32
38// during the translation to cope with aggregate flattening etc.
39// TODO: should these just return nullptr when there's no metadata?
41 FunctionType *FTy,
42 StringRef Name) {
43 if (!NMD)
44 return FTy;
45
46 auto It = find_if(NMD->operands(), [Name](MDNode *N) {
47 if (auto *MDS = dyn_cast_or_null<MDString>(N->getOperand(0)))
48 return MDS->getString() == Name;
49 return false;
50 });
51
52 if (It == NMD->op_end())
53 return FTy;
54
55 Type *RetTy = FTy->getReturnType();
56 SmallVector<Type *, 4> PTys(FTy->params());
57
58 for (unsigned I = 1; I != (*It)->getNumOperands(); ++I) {
59 MDNode *MD = dyn_cast<MDNode>((*It)->getOperand(I));
60 assert(MD && "MDNode operand is expected");
61
62 if (auto *Const = getMDOperandAsConstInt(MD, 0)) {
63 auto *CMeta = dyn_cast<ConstantAsMetadata>(MD->getOperand(1));
64 assert(CMeta && "ConstantAsMetadata operand is expected");
65 int64_t Idx = Const->getSExtValue();
66 // Currently -1 indicates return value, greater values mean
67 // argument numbers.
68 if (Idx == -1) {
69 RetTy = CMeta->getType();
70 continue;
71 }
72 if (Idx >= 0 && static_cast<uint64_t>(Idx) < PTys.size()) {
73 PTys[Idx] = CMeta->getType();
74 continue;
75 }
76 report_fatal_error("invalid argument index in function type metadata");
77 }
78 }
79
80 return FunctionType::get(RetTy, PTys, FTy->isVarArg());
81}
82
84 StringRef Constraints,
85 StringRef Name) {
86 // TODO: unify the extractors.
87 if (!NMD)
88 return Constraints;
89
90 auto It = find_if(NMD->operands(), [Name](MDNode *N) {
91 if (auto *MDS = dyn_cast_or_null<MDString>(N->getOperand(0)))
92 return MDS->getString() == Name;
93 return false;
94 });
95
96 if (It == NMD->op_end())
97 return Constraints;
98
99 // By convention, the constraints string is stored in the final MD operand.
100 MDNode *MD = dyn_cast<MDNode>((*It)->getOperand((*It)->getNumOperands() - 1));
101 assert(MD && "MDNode operand is expected");
102
103 if (auto *MDS = dyn_cast<MDString>(MD->getOperand(0)))
104 Constraints = MDS->getString();
105
106 return Constraints;
107}
108
111 F.getParent()->getNamedMetadata("spv.cloned_funcs"), F.getFunctionType(),
112 F.getName());
113}
114
115// Keyed via instruction metadata, not a name.
116static std::optional<StringRef> getMutatedCallsiteKey(const CallBase &CB) {
117 if (MDNode *MD = CB.getMetadata("spv.mutated_callsite"))
118 if (MD->getNumOperands() > 0)
119 if (auto *MDS = dyn_cast<MDString>(MD->getOperand(0)))
120 return MDS->getString();
121 return std::nullopt;
122}
123
125 std::optional<StringRef> Key = getMutatedCallsiteKey(CB);
126 if (!Key)
127 return CB.getFunctionType();
129 CB.getModule()->getNamedMetadata("spv.mutated_callsites"),
130 CB.getFunctionType(), *Key);
131}
132
134 StringRef Constraints =
135 cast<InlineAsm>(CB.getCalledOperand())->getConstraintString();
136 std::optional<StringRef> Key = getMutatedCallsiteKey(CB);
137 if (!Key)
138 return Constraints;
140 CB.getModule()->getNamedMetadata("spv.mutated_callsites"), Constraints,
141 *Key);
142}
143} // Namespace SPIRV
144
145// The following functions are used to add these string literals as a series of
146// 32-bit integer operands with the correct format, and unpack them if necessary
147// when making string comparisons in compiler passes.
148// SPIR-V requires null-terminated UTF-8 strings padded to 32-bit alignment.
149static uint32_t convertCharsToWord(StringRef Str, unsigned i) {
150 uint32_t Word = 0u; // Padding/null bytes are zero-initialized.
151 unsigned Count = std::min(static_cast<size_t>(4), Str.size() - i);
152 std::memcpy(&Word, Str.data() + i, Count);
153 return Word;
154}
155
156// Get length including padding and null terminator.
157static size_t getPaddedLen(StringRef Str) { return alignTo(Str.size() + 1, 4); }
158
159void addStringImm(StringRef Str, MCInst &Inst) {
160 const size_t PaddedLen = getPaddedLen(Str);
161 for (unsigned i = 0; i < PaddedLen; i += 4) {
162 // Add an operand for the 32-bits of chars or padding.
164 }
165}
166
168 const size_t PaddedLen = getPaddedLen(Str);
169 for (unsigned i = 0; i < PaddedLen; i += 4) {
170 // Add an operand for the 32-bits of chars or padding.
171 MIB.addImm(convertCharsToWord(Str, i));
172 }
173}
174
175std::string getStringImm(const MachineInstr &MI, unsigned StartIndex) {
176 return getSPIRVStringOperand(MI, StartIndex);
177}
178
180 MachineInstr *Def = getVRegDef(MRI, Reg);
181 assert(Def && Def->getOpcode() == TargetOpcode::G_GLOBAL_VALUE &&
182 "Expected G_GLOBAL_VALUE");
183 const GlobalValue *GV = Def->getOperand(1).getGlobal();
184 Value *V = GV->getOperand(0);
186 return CDA->getAsCString().str();
187}
188
189void addNumImm(const APInt &Imm, MachineInstrBuilder &MIB) {
190 const auto Bitwidth = Imm.getBitWidth();
191 if (Bitwidth == 1)
192 return; // Already handled
193 else if (Bitwidth <= 32) {
194 MIB.addImm(Imm.getZExtValue());
195 // Asm Printer needs this info to print floating-type correctly
196 if (Bitwidth == 16)
198 return;
199 } else if (Bitwidth <= 64) {
200 uint64_t FullImm = Imm.getZExtValue();
201 MIB.addImm(Lo_32(FullImm)).addImm(Hi_32(FullImm));
202 // Asm Printer needs this info to print 64-bit operands correctly
204 return;
205 } else {
206 // Emit ceil(Bitwidth / 32) words to conform SPIR-V spec.
207 unsigned NumWords = divideCeil(Bitwidth, 32);
208 for (unsigned I = 0; I < NumWords; ++I) {
209 unsigned LimbIdx = I / 2;
210 unsigned LimbShift = (I % 2) * 32;
211 uint32_t Word = (Imm.getRawData()[LimbIdx] >> LimbShift) & 0xffffffff;
212 MIB.addImm(Word);
213 }
214 return;
215 }
216}
217
219 MachineIRBuilder &MIRBuilder) {
220 if (!Name.empty()) {
221 auto MIB = MIRBuilder.buildInstr(SPIRV::OpName).addUse(Target);
222 addStringImm(Name, MIB);
223 }
224}
225
227 const SPIRVInstrInfo &TII) {
228 if (!Name.empty()) {
229 auto MIB =
230 BuildMI(*I.getParent(), I, I.getDebugLoc(), TII.get(SPIRV::OpName))
231 .addUse(Target);
232 addStringImm(Name, MIB);
233 }
234}
235
237 ArrayRef<uint32_t> DecArgs,
238 StringRef StrImm) {
239 if (!StrImm.empty())
240 addStringImm(StrImm, MIB);
241 for (const auto &DecArg : DecArgs)
242 MIB.addImm(DecArg);
243}
244
246 SPIRV::Decoration::Decoration Dec,
247 ArrayRef<uint32_t> DecArgs, StringRef StrImm) {
248 auto MIB = MIRBuilder.buildInstr(SPIRV::OpDecorate)
249 .addUse(Reg)
250 .addImm(static_cast<uint32_t>(Dec));
251 finishBuildOpDecorate(MIB, DecArgs, StrImm);
252}
253
255 SPIRV::Decoration::Decoration Dec,
256 ArrayRef<uint32_t> DecArgs, StringRef StrImm) {
257 MachineBasicBlock &MBB = *I.getParent();
258 auto MIB = BuildMI(MBB, I, I.getDebugLoc(), TII.get(SPIRV::OpDecorate))
259 .addUse(Reg)
260 .addImm(static_cast<uint32_t>(Dec));
261 finishBuildOpDecorate(MIB, DecArgs, StrImm);
262}
263
265 SPIRV::Decoration::Decoration Dec, uint32_t Member,
266 ArrayRef<uint32_t> DecArgs, StringRef StrImm) {
267 auto MIB = MIRBuilder.buildInstr(SPIRV::OpMemberDecorate)
268 .addUse(Reg)
269 .addImm(Member)
270 .addImm(static_cast<uint32_t>(Dec));
271 finishBuildOpDecorate(MIB, DecArgs, StrImm);
272}
273
275 const MDNode *GVarMD, const SPIRVSubtarget &ST) {
276 for (unsigned I = 0, E = GVarMD->getNumOperands(); I != E; ++I) {
277 auto *OpMD = dyn_cast<MDNode>(GVarMD->getOperand(I));
278 if (!OpMD)
279 report_fatal_error("Invalid decoration");
280 if (OpMD->getNumOperands() == 0)
281 report_fatal_error("Expect operand(s) of the decoration");
282 ConstantInt *DecorationId =
283 mdconst::dyn_extract<ConstantInt>(OpMD->getOperand(0));
284 if (!DecorationId)
285 report_fatal_error("Expect SPIR-V <Decoration> operand to be the first "
286 "element of the decoration");
287
288 // The goal of `spirv.Decorations` metadata is to provide a way to
289 // represent SPIR-V entities that do not map to LLVM in an obvious way.
290 // FP flags do have obvious matches between LLVM IR and SPIR-V.
291 // Additionally, we have no guarantee at this point that the flags passed
292 // through the decoration are not violated already in the optimizer passes.
293 // Therefore, we simply ignore FP flags, including NoContraction, and
294 // FPFastMathMode.
295 if (DecorationId->getZExtValue() ==
296 static_cast<uint32_t>(SPIRV::Decoration::NoContraction) ||
297 DecorationId->getZExtValue() ==
298 static_cast<uint32_t>(SPIRV::Decoration::FPFastMathMode)) {
299 continue; // Ignored.
300 }
301 auto MIB = MIRBuilder.buildInstr(SPIRV::OpDecorate)
302 .addUse(Reg)
303 .addImm(static_cast<uint32_t>(DecorationId->getZExtValue()));
304 for (unsigned OpI = 1, OpE = OpMD->getNumOperands(); OpI != OpE; ++OpI) {
305 if (ConstantInt *OpV =
306 mdconst::dyn_extract<ConstantInt>(OpMD->getOperand(OpI)))
307 MIB.addImm(static_cast<uint32_t>(OpV->getZExtValue()));
308 else if (MDString *OpV = dyn_cast<MDString>(OpMD->getOperand(OpI)))
309 addStringImm(OpV->getString(), MIB);
310 else
311 report_fatal_error("Unexpected operand of the decoration");
312 }
313 }
314}
315
318 // Find the position to insert the OpVariable instruction.
319 // We will insert it after the last OpFunctionParameter, if any, or
320 // after OpFunction otherwise.
321 auto IsPreamble = [](const MachineInstr &MI) {
322 switch (MI.getOpcode()) {
323 case SPIRV::OpFunction:
324 case SPIRV::OpFunctionParameter:
325 case SPIRV::OpLabel:
326 case SPIRV::ASSIGN_TYPE:
327 return true;
328 default:
329 return false;
330 }
331 };
332 MachineBasicBlock::iterator VarPos = MBB.SkipPHIsAndLabels(MBB.begin());
333 while (VarPos != MBB.end() && VarPos->getOpcode() != SPIRV::OpFunction)
334 ++VarPos;
335 // Advance past the preamble.
336 while (VarPos != MBB.end() && IsPreamble(*VarPos))
337 ++VarPos;
338 return VarPos;
339}
340
343 if (I == MBB->begin())
344 return I;
345 --I;
346 while (I->isTerminator() || I->isDebugValue()) {
347 if (I == MBB->begin())
348 break;
349 --I;
350 }
351 return I;
352}
353
354SPIRV::StorageClass::StorageClass
355addressSpaceToStorageClass(unsigned AddrSpace, const SPIRVSubtarget &STI) {
356 switch (AddrSpace) {
357 case 0:
358 return SPIRV::StorageClass::Function;
359 case 1:
360 return SPIRV::StorageClass::CrossWorkgroup;
361 case 2:
362 return SPIRV::StorageClass::UniformConstant;
363 case 3:
364 return SPIRV::StorageClass::Workgroup;
365 case 4:
366 return SPIRV::StorageClass::Generic;
367 case 5:
368 return STI.canUseExtension(SPIRV::Extension::SPV_INTEL_usm_storage_classes)
369 ? SPIRV::StorageClass::DeviceOnlyINTEL
370 : SPIRV::StorageClass::CrossWorkgroup;
371 case 6:
372 return STI.canUseExtension(SPIRV::Extension::SPV_INTEL_usm_storage_classes)
373 ? SPIRV::StorageClass::HostOnlyINTEL
374 : SPIRV::StorageClass::CrossWorkgroup;
375 case 7:
376 return SPIRV::StorageClass::Input;
377 case 8:
378 return SPIRV::StorageClass::Output;
379 case 9:
380 return SPIRV::StorageClass::CodeSectionINTEL;
381 case 10:
382 return SPIRV::StorageClass::Private;
383 case 11:
384 return SPIRV::StorageClass::StorageBuffer;
385 case 12:
386 return SPIRV::StorageClass::Uniform;
387 case 13:
388 return SPIRV::StorageClass::PushConstant;
389 default:
390 report_fatal_error("Unknown address space");
391 }
392}
393
394SPIRV::MemorySemantics::MemorySemantics
395getMemSemanticsForStorageClass(SPIRV::StorageClass::StorageClass SC) {
396 switch (SC) {
397 case SPIRV::StorageClass::StorageBuffer:
398 case SPIRV::StorageClass::Uniform:
399 return SPIRV::MemorySemantics::UniformMemory;
400 case SPIRV::StorageClass::Workgroup:
401 return SPIRV::MemorySemantics::WorkgroupMemory;
402 case SPIRV::StorageClass::CrossWorkgroup:
403 return SPIRV::MemorySemantics::CrossWorkgroupMemory;
404 case SPIRV::StorageClass::AtomicCounter:
405 return SPIRV::MemorySemantics::AtomicCounterMemory;
406 case SPIRV::StorageClass::Image:
407 return SPIRV::MemorySemantics::ImageMemory;
408 default:
409 return SPIRV::MemorySemantics::None;
410 }
411}
412
413SPIRV::MemorySemantics::MemorySemantics getMemSemantics(AtomicOrdering Ord) {
414 switch (Ord) {
416 return SPIRV::MemorySemantics::Acquire;
418 return SPIRV::MemorySemantics::Release;
420 return SPIRV::MemorySemantics::AcquireRelease;
422 return SPIRV::MemorySemantics::SequentiallyConsistent;
426 return SPIRV::MemorySemantics::None;
427 }
428 llvm_unreachable(nullptr);
429}
430
431SPIRV::Scope::Scope getMemScope(LLVMContext &Ctx, SyncScope::ID Id) {
432 // Named by
433 // https://registry.khronos.org/SPIR-V/specs/unified1/SPIRV.html#_scope_id.
434 // We don't need aliases for Invocation and CrossDevice, as we already have
435 // them covered by "singlethread" and "" strings respectively (see
436 // implementation of LLVMContext::LLVMContext()).
437 static const llvm::SyncScope::ID SubGroup =
438 Ctx.getOrInsertSyncScopeID("subgroup");
439 static const llvm::SyncScope::ID WorkGroup =
440 Ctx.getOrInsertSyncScopeID("workgroup");
441 static const llvm::SyncScope::ID Device =
442 Ctx.getOrInsertSyncScopeID("device");
443
445 return SPIRV::Scope::Invocation;
446 else if (Id == llvm::SyncScope::System)
447 return SPIRV::Scope::CrossDevice;
448 else if (Id == SubGroup)
449 return SPIRV::Scope::Subgroup;
450 else if (Id == WorkGroup)
451 return SPIRV::Scope::Workgroup;
452 else if (Id == Device)
453 return SPIRV::Scope::Device;
454 return SPIRV::Scope::CrossDevice;
455}
456
458 const MachineRegisterInfo *MRI) {
459 MachineInstr *MI = MRI->getVRegDef(ConstReg);
460 MachineInstr *ConstInstr =
461 MI->getOpcode() == SPIRV::G_TRUNC || MI->getOpcode() == SPIRV::G_ZEXT
462 ? MRI->getVRegDef(MI->getOperand(1).getReg())
463 : MI;
464 if (auto *GI = dyn_cast<GIntrinsic>(ConstInstr)) {
465 if (GI->is(Intrinsic::spv_track_constant)) {
466 ConstReg = ConstInstr->getOperand(2).getReg();
467 return MRI->getVRegDef(ConstReg);
468 }
469 } else if (ConstInstr->getOpcode() == SPIRV::ASSIGN_TYPE) {
470 ConstReg = ConstInstr->getOperand(1).getReg();
471 return MRI->getVRegDef(ConstReg);
472 } else if (ConstInstr->getOpcode() == TargetOpcode::G_CONSTANT ||
473 ConstInstr->getOpcode() == TargetOpcode::G_FCONSTANT) {
474 ConstReg = ConstInstr->getOperand(0).getReg();
475 return ConstInstr;
476 }
477 return MRI->getVRegDef(ConstReg);
478}
479
481 const MachineInstr *MI = getDefInstrMaybeConstant(ConstReg, MRI);
482 assert(MI && MI->getOpcode() == TargetOpcode::G_CONSTANT);
483 return MI->getOperand(1).getCImm()->getValue().getZExtValue();
484}
485
486int64_t getIConstValSext(Register ConstReg, const MachineRegisterInfo *MRI) {
487 const MachineInstr *MI = getDefInstrMaybeConstant(ConstReg, MRI);
488 assert(MI && MI->getOpcode() == TargetOpcode::G_CONSTANT);
489 return MI->getOperand(1).getCImm()->getSExtValue();
490}
491
492bool isSpvIntrinsic(const MachineInstr &MI, Intrinsic::ID IntrinsicID) {
493 if (const auto *GI = dyn_cast<GIntrinsic>(&MI))
494 return GI->is(IntrinsicID);
495 return false;
496}
497
498Type *getMDOperandAsType(const MDNode *N, unsigned I) {
499 Type *ElementTy = cast<ValueAsMetadata>(N->getOperand(I))->getType();
500 return toTypedPointer(ElementTy);
501}
502
504 if (N->getNumOperands() <= I)
505 return nullptr;
506 if (auto *CMeta = dyn_cast<ConstantAsMetadata>(N->getOperand(I)))
507 return dyn_cast<ConstantInt>(CMeta->getValue());
508 return nullptr;
509}
510
511static bool isEnqueueKernelBI(StringRef MangledName) {
512 return MangledName == "__enqueue_kernel_basic" ||
513 MangledName == "__enqueue_kernel_basic_events" ||
514 MangledName == "__enqueue_kernel_varargs" ||
515 MangledName == "__enqueue_kernel_events_varargs";
516}
517
518static bool isKernelQueryBI(StringRef MangledName) {
519 return MangledName == "__get_kernel_work_group_size_impl" ||
520 MangledName == "__get_kernel_sub_group_count_for_ndrange_impl" ||
521 MangledName == "__get_kernel_max_sub_group_size_for_ndrange_impl" ||
522 MangledName == "__get_kernel_preferred_work_group_size_multiple_impl";
523}
524
526 if (!Name.starts_with("__"))
527 return false;
528
529 return isEnqueueKernelBI(Name) || isKernelQueryBI(Name) ||
531 Name == "__translate_sampler_initializer";
532}
533
535 bool IsNonMangledOCL = isNonMangledOCLBuiltin(Name);
536 bool IsNonMangledSPIRV = Name.starts_with("__spirv_");
537 bool IsNonMangledHLSL = Name.starts_with("__hlsl_");
538 bool IsMangled = Name.starts_with("_Z");
539
540 // Otherwise use simple demangling to return the function name.
541 if (IsNonMangledOCL || IsNonMangledSPIRV || IsNonMangledHLSL || !IsMangled)
542 return Name.str();
543
544 // Try to use the itanium demangler.
545 if (char *DemangledName = itaniumDemangle(Name.data())) {
546 std::string Result = DemangledName;
547 free(DemangledName);
548 return Result;
549 }
550
551 // Autocheck C++, maybe need to do explicit check of the source language.
552 // OpenCL C++ built-ins are declared in cl namespace.
553 // TODO: consider using 'St' abbriviation for cl namespace mangling.
554 // Similar to ::std:: in C++.
555 size_t Start, Len = 0;
556 size_t DemangledNameLenStart = 2;
557 if (Name.starts_with("_ZN")) {
558 // Skip CV and ref qualifiers.
559 size_t NameSpaceStart = Name.find_first_not_of("rVKRO", 3);
560 // All built-ins are in the ::cl:: namespace.
561 if (Name.substr(NameSpaceStart, 11) != "2cl7__spirv")
562 return std::string();
563 DemangledNameLenStart = NameSpaceStart + 11;
564 }
565 Start = Name.find_first_not_of("0123456789", DemangledNameLenStart);
566 bool Error = Name.substr(DemangledNameLenStart, Start - DemangledNameLenStart)
567 .getAsInteger(10, Len);
568 if (Error)
569 return std::string();
570 return Name.substr(Start, Len).str();
571}
572
574 if (Name.starts_with("opencl.") || Name.starts_with("ocl_") ||
575 Name.starts_with("spirv."))
576 return true;
577 return false;
578}
579
580bool isSpecialOpaqueType(const Type *Ty) {
581 if (const TargetExtType *ExtTy = dyn_cast<TargetExtType>(Ty))
582 return isTypedPointerWrapper(ExtTy)
583 ? false
584 : hasBuiltinTypePrefix(ExtTy->getName());
585
586 return false;
587}
588
589bool isEntryPoint(const Function &F) {
590 // OpenCL handling: any function with the SPIR_KERNEL
591 // calling convention will be a potential entry point.
592 if (F.getCallingConv() == CallingConv::SPIR_KERNEL)
593 return true;
594
595 // HLSL handling: special attribute are emitted from the
596 // front-end.
597 if (F.getFnAttribute("hlsl.shader").isValid())
598 return true;
599
600 return false;
601}
602
604 TypeName.consume_front("atomic_");
605 if (TypeName.consume_front("void"))
606 return Type::getVoidTy(Ctx);
607 else if (TypeName.consume_front("bool") || TypeName.consume_front("_Bool"))
608 return Type::getIntNTy(Ctx, 1);
609 else if (TypeName.consume_front("char") ||
610 TypeName.consume_front("signed char") ||
611 TypeName.consume_front("unsigned char") ||
612 TypeName.consume_front("uchar"))
613 return Type::getInt8Ty(Ctx);
614 else if (TypeName.consume_front("short") ||
615 TypeName.consume_front("signed short") ||
616 TypeName.consume_front("unsigned short") ||
617 TypeName.consume_front("ushort"))
618 return Type::getInt16Ty(Ctx);
619 else if (TypeName.consume_front("int") ||
620 TypeName.consume_front("signed int") ||
621 TypeName.consume_front("unsigned int") ||
622 TypeName.consume_front("uint"))
623 return Type::getInt32Ty(Ctx);
624 else if (TypeName.consume_front("long") ||
625 TypeName.consume_front("signed long") ||
626 TypeName.consume_front("unsigned long") ||
627 TypeName.consume_front("ulong"))
628 return Type::getInt64Ty(Ctx);
629 else if (TypeName.consume_front("half") ||
630 TypeName.consume_front("_Float16") ||
631 TypeName.consume_front("__fp16"))
632 return Type::getHalfTy(Ctx);
633 else if (TypeName.consume_front("float"))
634 return Type::getFloatTy(Ctx);
635 else if (TypeName.consume_front("double"))
636 return Type::getDoubleTy(Ctx);
637
638 // Unable to recognize SPIRV type name
639 return nullptr;
640}
641
642SmallPtrSet<BasicBlock *, 0>
643PartialOrderingVisitor::getReachableFrom(BasicBlock *Start) {
644 std::queue<BasicBlock *> ToVisit;
645 ToVisit.push(Start);
646
647 SmallPtrSet<BasicBlock *, 0> Output;
648 while (ToVisit.size() != 0) {
649 BasicBlock *BB = ToVisit.front();
650 ToVisit.pop();
651
652 if (Output.count(BB) != 0)
653 continue;
654 Output.insert(BB);
655
656 for (BasicBlock *Successor : successors(BB)) {
657 if (DT.dominates(Successor, BB))
658 continue;
659 ToVisit.push(Successor);
660 }
661 }
662
663 return Output;
664}
665
666bool PartialOrderingVisitor::CanBeVisited(BasicBlock *BB) const {
667 for (BasicBlock *P : predecessors(BB)) {
668 // Ignore back-edges.
669 if (DT.dominates(BB, P))
670 continue;
671
672 // One of the predecessor hasn't been visited. Not ready yet.
673 if (BlockToOrder.count(P) == 0)
674 return false;
675
676 // If the block is a loop exit, the loop must be finished before
677 // we can continue.
678 Loop *L = LI.getLoopFor(P);
679 if (L == nullptr || L->contains(BB))
680 continue;
681
682 // SPIR-V requires a single back-edge. And the backend first
683 // step transforms loops into the simplified format. If we have
684 // more than 1 back-edge, something is wrong.
685 assert(L->getNumBackEdges() <= 1);
686
687 // If the loop has no latch, loop's rank won't matter, so we can
688 // proceed.
689 BasicBlock *Latch = L->getLoopLatch();
690 assert(Latch);
691 if (Latch == nullptr)
692 continue;
693
694 // The latch is not ready yet, let's wait.
695 if (BlockToOrder.count(Latch) == 0)
696 return false;
697 }
698
699 return true;
700}
701
703 auto It = BlockToOrder.find(BB);
704 if (It != BlockToOrder.end())
705 return It->second.Rank;
706
707 size_t result = 0;
708 for (BasicBlock *P : predecessors(BB)) {
709 // Ignore back-edges.
710 if (DT.dominates(BB, P))
711 continue;
712
713 auto Iterator = BlockToOrder.end();
714 Loop *L = LI.getLoopFor(P);
715 BasicBlock *Latch = L ? L->getLoopLatch() : nullptr;
716
717 // If the predecessor is either outside a loop, or part of
718 // the same loop, simply take its rank + 1.
719 if (L == nullptr || L->contains(BB) || Latch == nullptr) {
720 Iterator = BlockToOrder.find(P);
721 } else {
722 // Otherwise, take the loop's rank (highest rank in the loop) as base.
723 // Since loops have a single latch, highest rank is easy to find.
724 // If the loop has no latch, then it doesn't matter.
725 Iterator = BlockToOrder.find(Latch);
726 }
727
728 assert(Iterator != BlockToOrder.end());
729 result = std::max(result, Iterator->second.Rank + 1);
730 }
731
732 return result;
733}
734
735size_t PartialOrderingVisitor::visit(BasicBlock *BB, size_t Unused) {
736 ToVisit.push(BB);
737 Queued.insert(BB);
738
739 size_t QueueIndex = 0;
740 while (ToVisit.size() != 0) {
741 BasicBlock *BB = ToVisit.front();
742 ToVisit.pop();
743
744 if (!CanBeVisited(BB)) {
745 ToVisit.push(BB);
746 if (QueueIndex >= ToVisit.size())
748 "No valid candidate in the queue. Is the graph reducible?");
749 QueueIndex++;
750 continue;
751 }
752
753 QueueIndex = 0;
754 size_t Rank = GetNodeRank(BB);
755 OrderInfo Info = {Rank, BlockToOrder.size()};
756 BlockToOrder.try_emplace(BB, Info);
757
758 for (BasicBlock *S : successors(BB)) {
759 if (Queued.count(S) != 0)
760 continue;
761 ToVisit.push(S);
762 Queued.insert(S);
763 }
764 }
765
766 return 0;
767}
768
770 DT.recalculate(F);
771 LI = LoopInfo(DT);
772
773 visit(&*F.begin(), 0);
774
775 Order.reserve(F.size());
776 for (auto &[BB, Info] : BlockToOrder)
777 Order.emplace_back(BB);
778
779 llvm::sort(Order, [&](const auto &LHS, const auto &RHS) {
780 return compare(LHS, RHS);
781 });
782}
783
785 const BasicBlock *RHS) const {
786 const OrderInfo &InfoLHS = BlockToOrder.at(const_cast<BasicBlock *>(LHS));
787 const OrderInfo &InfoRHS = BlockToOrder.at(const_cast<BasicBlock *>(RHS));
788 if (InfoLHS.Rank != InfoRHS.Rank)
789 return InfoLHS.Rank < InfoRHS.Rank;
790 return InfoLHS.TraversalIndex < InfoRHS.TraversalIndex;
791}
792
794 BasicBlock &Start, std::function<bool(BasicBlock *)> Op) {
795 SmallPtrSet<BasicBlock *, 0> Reachable = getReachableFrom(&Start);
796 assert(BlockToOrder.count(&Start) != 0);
797
798 // Skipping blocks with a rank inferior to |Start|'s rank.
799 auto It = Order.begin();
800 while (It != Order.end() && *It != &Start)
801 ++It;
802
803 // This is unexpected. Worst case |Start| is the last block,
804 // so It should point to the last block, not past-end.
805 assert(It != Order.end());
806
807 // By default, there is no rank limit. Setting it to the maximum value.
808 std::optional<size_t> EndRank = std::nullopt;
809 for (; It != Order.end(); ++It) {
810 if (EndRank.has_value() && BlockToOrder[*It].Rank > *EndRank)
811 break;
812
813 if (Reachable.count(*It) == 0) {
814 continue;
815 }
816
817 if (!Op(*It)) {
818 EndRank = BlockToOrder[*It].Rank;
819 }
820 }
821}
822
824 if (F.size() == 0)
825 return false;
826
827 bool Modified = false;
828 std::vector<BasicBlock *> Order;
829 Order.reserve(F.size());
830
832 llvm::append_range(Order, RPOT);
833
834 assert(&*F.begin() == Order[0]);
835 BasicBlock *LastBlock = &*F.begin();
836 for (BasicBlock *BB : Order) {
837 if (BB != LastBlock && &*LastBlock->getNextNode() != BB) {
838 Modified = true;
839 BB->moveAfter(LastBlock);
840 }
841 LastBlock = BB;
842 }
843
844 return Modified;
845}
846
848 const DataLayout &DL = F.getDataLayout();
849 return new AllocaInst(Type, DL.getAllocaAddrSpace(), nullptr, "reg",
850 F.begin()->getFirstInsertionPt());
851}
852
853Value *
855 const DenseMap<BasicBlock *, ConstantInt *> &TargetToValue) {
856 auto *T = BB->getTerminator();
857 if (isa<ReturnInst>(T))
858 return nullptr;
859 if (auto *BI = dyn_cast<UncondBrInst>(T))
860 return TargetToValue.lookup(BI->getSuccessor());
861
862 IRBuilder<> Builder(BB);
863 Builder.SetInsertPoint(T);
864
865 if (auto *BI = dyn_cast<CondBrInst>(T)) {
866 Value *LHS = TargetToValue.lookup(BI->getSuccessor(0));
867 Value *RHS = TargetToValue.lookup(BI->getSuccessor(1));
868
869 if (LHS == nullptr || RHS == nullptr)
870 return LHS == nullptr ? RHS : LHS;
871 return Builder.CreateSelect(BI->getCondition(), LHS, RHS);
872 }
873
874 // TODO: add support for switch cases.
875 llvm_unreachable("Unhandled terminator type.");
876}
877
879 MachineInstr *MaybeDef = MRI.getVRegDef(Reg);
880 if (MaybeDef && MaybeDef->getOpcode() == SPIRV::ASSIGN_TYPE)
881 MaybeDef = MRI.getVRegDef(MaybeDef->getOperand(1).getReg());
882 return MaybeDef;
883}
884
885static bool getVacantFunctionName(Module &M, std::string &Name) {
886 // It's a bit of paranoia, but still we don't want to have even a chance that
887 // the loop will work for too long.
888 constexpr unsigned MaxIters = 1024;
889 for (unsigned I = 0; I < MaxIters; ++I) {
890 std::string OrdName = Name + Twine(I).str();
891 if (!M.getFunction(OrdName)) {
892 Name = std::move(OrdName);
893 return true;
894 }
895 }
896 return false;
897}
898
899// Assign SPIR-V type to the register. If the register has no valid assigned
900// class, set register LLT type and class according to the SPIR-V type.
903 const MachineFunction &MF, bool Force) {
904 GR->assignSPIRVTypeToVReg(SpvType, Reg, MF);
905 if (!MRI->getRegClassOrNull(Reg) || Force) {
906 MRI->setRegClass(Reg, GR->getRegClass(SpvType));
907 LLT RegType = GR->getRegType(SpvType);
908 if (Force || !MRI->getType(Reg).isValid())
909 MRI->setType(Reg, RegType);
910 }
911}
912
913// Create a SPIR-V type, assign SPIR-V type to the register. If the register has
914// no valid assigned class, set register LLT type and class according to the
915// SPIR-V type.
917 MachineIRBuilder &MIRBuilder,
918 SPIRV::AccessQualifier::AccessQualifier AccessQual,
919 bool EmitIR, bool Force) {
921 GR->getOrCreateSPIRVType(Ty, MIRBuilder, AccessQual, EmitIR),
922 GR, MIRBuilder.getMRI(), MIRBuilder.getMF(), Force);
923}
924
925// Create a virtual register and assign SPIR-V type to the register. Set
926// register LLT type and class according to the SPIR-V type.
929 const MachineFunction &MF) {
930 Register Reg = MRI->createVirtualRegister(GR->getRegClass(SpvType));
931 MRI->setType(Reg, GR->getRegType(SpvType));
932 GR->assignSPIRVTypeToVReg(SpvType, Reg, MF);
933 return Reg;
934}
935
936// Create a virtual register and assign SPIR-V type to the register. Set
937// register LLT type and class according to the SPIR-V type.
939 MachineIRBuilder &MIRBuilder) {
940 return createVirtualRegister(SpvType, GR, MIRBuilder.getMRI(),
941 MIRBuilder.getMF());
942}
943
944// Create a SPIR-V type, virtual register and assign SPIR-V type to the
945// register. Set register LLT type and class according to the SPIR-V type.
947 const Type *Ty, SPIRVGlobalRegistry *GR, MachineIRBuilder &MIRBuilder,
948 SPIRV::AccessQualifier::AccessQualifier AccessQual, bool EmitIR) {
950 GR->getOrCreateSPIRVType(Ty, MIRBuilder, AccessQual, EmitIR), GR,
951 MIRBuilder);
952}
953
955 Value *Arg, Value *Arg2, ArrayRef<Constant *> Imms,
956 IRBuilder<> &B) {
958 Args.push_back(Arg2);
959 Args.push_back(buildMD(Arg));
960 llvm::append_range(Args, Imms);
961 return B.CreateIntrinsicWithoutFolding(IntrID, {Types}, Args);
962}
963
964// Return true if there is an opaque pointer type nested in the argument.
965bool isNestedPointer(const Type *Ty) {
966 if (Ty->isPtrOrPtrVectorTy())
967 return true;
968 if (const FunctionType *RefTy = dyn_cast<FunctionType>(Ty)) {
969 if (isNestedPointer(RefTy->getReturnType()))
970 return true;
971 for (const Type *ArgTy : RefTy->params())
972 if (isNestedPointer(ArgTy))
973 return true;
974 return false;
975 }
976 if (const ArrayType *RefTy = dyn_cast<ArrayType>(Ty))
977 return isNestedPointer(RefTy->getElementType());
978 return false;
979}
980
981bool isSpvIntrinsic(const Value *Arg) {
982 if (const auto *II = dyn_cast<IntrinsicInst>(Arg))
983 if (Function *F = II->getCalledFunction())
984 if (F->getName().starts_with("llvm.spv."))
985 return true;
986 return false;
987}
988
989// Function to create continued instructions for SPV_INTEL_long_composites
990// extension
991SmallVector<MachineInstr *, 4>
993 unsigned MinWC, unsigned ContinuedOpcode,
994 ArrayRef<Register> Args, Register ReturnRegister,
996
998 constexpr unsigned MaxWordCount = UINT16_MAX;
999 const size_t NumElements = Args.size();
1000 size_t MaxNumElements = MaxWordCount - MinWC;
1001 size_t SPIRVStructNumElements = NumElements;
1002
1003 if (NumElements > MaxNumElements) {
1004 // Do adjustments for continued instructions which always had only one
1005 // minumum word count.
1006 SPIRVStructNumElements = MaxNumElements;
1007 MaxNumElements = MaxWordCount - 1;
1008 }
1009
1010 auto MIB =
1011 MIRBuilder.buildInstr(Opcode).addDef(ReturnRegister).addUse(TypeID);
1012
1013 for (size_t I = 0; I < SPIRVStructNumElements; ++I)
1014 MIB.addUse(Args[I]);
1015
1016 Instructions.push_back(MIB.getInstr());
1017
1018 for (size_t I = SPIRVStructNumElements; I < NumElements;
1019 I += MaxNumElements) {
1020 auto MIB = MIRBuilder.buildInstr(ContinuedOpcode);
1021 for (size_t J = I; J < std::min(I + MaxNumElements, NumElements); ++J)
1022 MIB.addUse(Args[J]);
1023 Instructions.push_back(MIB.getInstr());
1024 }
1025 return Instructions;
1026}
1027
1028SmallVector<unsigned, 1>
1030 unsigned LC = SPIRV::LoopControl::None;
1031 // Currently used only to store PartialCount value. Later when other
1032 // LoopControls are added - this map should be sorted before making
1033 // them loop_merge operands to satisfy 3.23. Loop Control requirements.
1034 std::vector<std::pair<unsigned, unsigned>> MaskToValueMap;
1035 if (findOptionMDForLoopID(LoopMD, "llvm.loop.unroll.disable")) {
1036 LC |= SPIRV::LoopControl::DontUnroll;
1037 } else {
1038 if (findOptionMDForLoopID(LoopMD, "llvm.loop.unroll.enable") ||
1039 findOptionMDForLoopID(LoopMD, "llvm.loop.unroll.full")) {
1040 LC |= SPIRV::LoopControl::Unroll;
1041 }
1042 if (MDNode *CountMD =
1043 findOptionMDForLoopID(LoopMD, "llvm.loop.unroll.count")) {
1044 if (auto *CI =
1045 mdconst::extract_or_null<ConstantInt>(CountMD->getOperand(1))) {
1046 unsigned Count = CI->getZExtValue();
1047 if (Count != 1) {
1048 LC |= SPIRV::LoopControl::PartialCount;
1049 MaskToValueMap.emplace_back(
1050 std::make_pair(SPIRV::LoopControl::PartialCount, Count));
1051 }
1052 }
1053 }
1054 }
1055 SmallVector<unsigned, 1> Result = {LC};
1056 for (auto &[Mask, Val] : MaskToValueMap)
1057 Result.push_back(Val);
1058 return Result;
1059}
1060
1064
1065const std::set<unsigned> &getTypeFoldingSupportedOpcodes() {
1066 // clang-format off
1067 static const std::set<unsigned> TypeFoldingSupportingOpcs = {
1068 TargetOpcode::G_ADD,
1069 TargetOpcode::G_FADD,
1070 TargetOpcode::G_STRICT_FADD,
1071 TargetOpcode::G_SUB,
1072 TargetOpcode::G_FSUB,
1073 TargetOpcode::G_STRICT_FSUB,
1074 TargetOpcode::G_MUL,
1075 TargetOpcode::G_FMUL,
1076 TargetOpcode::G_STRICT_FMUL,
1077 TargetOpcode::G_SDIV,
1078 TargetOpcode::G_UDIV,
1079 TargetOpcode::G_FDIV,
1080 TargetOpcode::G_STRICT_FDIV,
1081 TargetOpcode::G_SREM,
1082 TargetOpcode::G_UREM,
1083 TargetOpcode::G_FREM,
1084 TargetOpcode::G_STRICT_FREM,
1085 TargetOpcode::G_FNEG,
1086 TargetOpcode::G_CONSTANT,
1087 TargetOpcode::G_FCONSTANT,
1088 TargetOpcode::G_AND,
1089 TargetOpcode::G_OR,
1090 TargetOpcode::G_XOR,
1091 TargetOpcode::G_SHL,
1092 TargetOpcode::G_ASHR,
1093 TargetOpcode::G_LSHR,
1094 TargetOpcode::G_SELECT,
1095 TargetOpcode::G_EXTRACT_VECTOR_ELT,
1096 };
1097 // clang-format on
1098 return TypeFoldingSupportingOpcs;
1099}
1100
1101bool isTypeFoldingSupported(unsigned Opcode) {
1102 return getTypeFoldingSupportedOpcodes().count(Opcode) > 0;
1103}
1104
1105// Traversing [g]MIR accounting for pseudo-instructions.
1107 return (Def->getOpcode() == SPIRV::ASSIGN_TYPE ||
1108 Def->getOpcode() == TargetOpcode::COPY)
1109 ? MRI->getVRegDef(Def->getOperand(1).getReg())
1110 : Def;
1111}
1112
1114 if (MachineInstr *Def = MRI->getVRegDef(MO.getReg()))
1115 return passCopy(Def, MRI);
1116 return nullptr;
1117}
1118
1120 if (MachineInstr *Def = getDef(MO, MRI)) {
1121 if (Def->getOpcode() == TargetOpcode::G_CONSTANT ||
1122 Def->getOpcode() == SPIRV::OpConstantI)
1123 return Def;
1124 }
1125 return nullptr;
1126}
1127
1128int64_t foldImm(const MachineOperand &MO, const MachineRegisterInfo *MRI) {
1129 if (MachineInstr *Def = getImm(MO, MRI)) {
1130 if (Def->getOpcode() == SPIRV::OpConstantI)
1131 return Def->getOperand(2).getImm();
1132 if (Def->getOpcode() == TargetOpcode::G_CONSTANT)
1133 return Def->getOperand(1).getCImm()->getZExtValue();
1134 }
1135 llvm_unreachable("Unexpected integer constant pattern");
1136}
1137
1139 const MachineInstr *ResType) {
1140 return foldImm(ResType->getOperand(2), MRI);
1141}
1142
1143bool matchPeeledArrayPattern(const StructType *Ty, Type *&OriginalElementType,
1144 uint64_t &TotalSize) {
1145 // An array of N padded structs is represented as {[N-1 x <{T, pad}>], T}.
1146 if (Ty->getStructNumElements() != 2)
1147 return false;
1148
1149 Type *FirstElement = Ty->getStructElementType(0);
1150 Type *SecondElement = Ty->getStructElementType(1);
1151
1152 if (!FirstElement->isArrayTy())
1153 return false;
1154
1155 Type *ArrayElementType = FirstElement->getArrayElementType();
1156 if (!ArrayElementType->isStructTy() ||
1157 ArrayElementType->getStructNumElements() != 2)
1158 return false;
1159
1160 Type *T_in_struct = ArrayElementType->getStructElementType(0);
1161 if (T_in_struct != SecondElement)
1162 return false;
1163
1164 auto *Padding_in_struct =
1165 dyn_cast<TargetExtType>(ArrayElementType->getStructElementType(1));
1166 if (!Padding_in_struct || Padding_in_struct->getName() != "spirv.Padding")
1167 return false;
1168
1169 const uint64_t ArraySize = FirstElement->getArrayNumElements();
1170 TotalSize = ArraySize + 1;
1171 OriginalElementType = ArrayElementType;
1172 return true;
1173}
1174
1176 if (!Ty->isStructTy())
1177 return Ty;
1178
1179 auto *STy = cast<StructType>(Ty);
1180 Type *OriginalElementType = nullptr;
1181 uint64_t TotalSize = 0;
1182 if (matchPeeledArrayPattern(STy, OriginalElementType, TotalSize)) {
1183 Type *ResultTy = ArrayType::get(
1184 reconstitutePeeledArrayType(OriginalElementType), TotalSize);
1185 return ResultTy;
1186 }
1187
1188 SmallVector<Type *, 4> NewElementTypes;
1189 bool Changed = false;
1190 for (Type *ElementTy : STy->elements()) {
1191 Type *NewElementTy = reconstitutePeeledArrayType(ElementTy);
1192 if (NewElementTy != ElementTy)
1193 Changed = true;
1194 NewElementTypes.push_back(NewElementTy);
1195 }
1196
1197 if (!Changed)
1198 return Ty;
1199
1200 Type *ResultTy;
1201 if (STy->isLiteral())
1202 ResultTy =
1203 StructType::get(STy->getContext(), NewElementTypes, STy->isPacked());
1204 else {
1205 auto *NewTy = StructType::create(STy->getContext(), STy->getName());
1206 NewTy->setBody(NewElementTypes, STy->isPacked());
1207 ResultTy = NewTy;
1208 }
1209 return ResultTy;
1210}
1211
1212std::optional<SPIRV::LinkageType::LinkageType>
1214 if (GV.hasLocalLinkage())
1215 return std::nullopt;
1216
1217 if (GV.isDeclarationForLinker()) {
1218 // Interface variables must not get Import linkage.
1219 if (const auto *GVar = dyn_cast<GlobalVariable>(&GV)) {
1220 auto SC = addressSpaceToStorageClass(GVar->getAddressSpace(), ST);
1221 if (SC == SPIRV::StorageClass::Input ||
1222 SC == SPIRV::StorageClass::Output ||
1223 SC == SPIRV::StorageClass::PushConstant)
1224 return std::nullopt;
1225 }
1226 return SPIRV::LinkageType::Import;
1227 }
1228
1229 if (GV.hasHiddenVisibility())
1230 return std::nullopt;
1231
1232 if (GV.hasLinkOnceODRLinkage() &&
1233 ST.canUseExtension(SPIRV::Extension::SPV_KHR_linkonce_odr))
1234 return SPIRV::LinkageType::LinkOnceODR;
1235
1236 if (GV.hasWeakLinkage() &&
1237 ST.canUseExtension(SPIRV::Extension::SPV_AMD_weak_linkage))
1238 return SPIRV::LinkageType::WeakAMD;
1239
1240 return SPIRV::LinkageType::Export;
1241}
1242
1244 std::string ServiceFunName = SPIRV_BACKEND_SERVICE_FUN_NAME;
1245 if (!getVacantFunctionName(M, ServiceFunName))
1247 "cannot allocate a name for the internal service function");
1248 if (Function *SF = M.getFunction(ServiceFunName)) {
1249 if (SF->getInstructionCount() > 0)
1251 "Unexpected combination of global variables and function pointers");
1252 return SF;
1253 }
1255 FunctionType::get(Type::getVoidTy(M.getContext()), {}, false),
1256 GlobalValue::PrivateLinkage, ServiceFunName, M);
1258 return SF;
1259}
1260
1261} // 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