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