LLVM: lib/Target/SPIRV/SPIRVUtils.cpp Source File (original) (raw)
1
2
3
4
5
6
7
8
9
10
11
12
26#include "llvm/IR/IntrinsicsSPIRV.h"
27#include
28#include
29
30namespace llvm {
32
33
34
35
39 if (!NMD)
40 return FTy;
41
44 return nullptr;
47 return nullptr;
48 };
49
51 if (auto *MDS = dyn_cast_or_null(N->getOperand(0)))
52 return MDS->getString() == Name;
53 return false;
54 });
55
56 if (It == NMD->op_end())
57 return FTy;
58
61
62 for (unsigned I = 1; I != (*It)->getNumOperands(); ++I) {
64 assert(MD && "MDNode operand is expected");
65
68 assert(CMeta && "ConstantAsMetadata operand is expected");
69 assert(Const->getSExtValue() >= -1);
70
71
72 if (Const->getSExtValue() == -1)
73 RetTy = CMeta->getType();
74 else
75 PTys[Const->getSExtValue()] = CMeta->getType();
76 }
77 }
78
80}
81
84 F.getParent()->getNamedMetadata("spv.cloned_funcs"), F.getFunctionType(),
85 F.getName());
86}
87
93}
94
95
96
97
98
100 uint32_t Word = 0u;
101 for (unsigned WordIndex = 0; WordIndex < 4; ++WordIndex) {
102 unsigned StrIndex = i + WordIndex;
103 uint8_t CharToAdd = 0;
104 if (StrIndex < Str.size()) {
105 CharToAdd = Str[StrIndex];
106 }
107 Word |= (CharToAdd << (WordIndex * 8));
108 }
109 return Word;
110}
111
112
114 return (Str.size() + 4) & ~3;
115}
116
119 for (unsigned i = 0; i < PaddedLen; i += 4) {
120
122 }
123}
124
127 for (unsigned i = 0; i < PaddedLen; i += 4) {
128
130 }
131}
132
134 std::vector<Value *> &Args) {
136 for (unsigned i = 0; i < PaddedLen; i += 4) {
137
139 }
140}
141
145
148 assert(Def && Def->getOpcode() == TargetOpcode::G_GLOBAL_VALUE &&
149 "Expected G_GLOBAL_VALUE");
150 const GlobalValue *GV = Def->getOperand(1).getGlobal();
154}
155
157 const auto Bitwidth = Imm.getBitWidth();
158 if (Bitwidth == 1)
159 return;
160 else if (Bitwidth <= 32) {
161 MIB.addImm(Imm.getZExtValue());
162
163 if (Bitwidth == 16)
165 return;
166 } else if (Bitwidth <= 64) {
167 uint64_t FullImm = Imm.getZExtValue();
168 uint32_t LowBits = FullImm & 0xffffffff;
169 uint32_t HighBits = (FullImm >> 32) & 0xffffffff;
171
173 return;
174 } else if (Bitwidth <= 128) {
175 uint32_t LowBits = Imm.getRawData()[0] & 0xffffffff;
176 uint32_t MidBits0 = (Imm.getRawData()[0] >> 32) & 0xffffffff;
177 uint32_t MidBits1 = Imm.getRawData()[1] & 0xffffffff;
178 uint32_t HighBits = (Imm.getRawData()[1] >> 32) & 0xffffffff;
180 return;
181 }
183}
184
187 if (!Name.empty()) {
190 }
191}
192
195 if (!Name.empty()) {
196 auto MIB =
197 BuildMI(*I.getParent(), I, I.getDebugLoc(), TII.get(SPIRV::OpName))
200 }
201}
202
204 const std::vector<uint32_t> &DecArgs,
206 if (!StrImm.empty())
208 for (const auto &DecArg : DecArgs)
210}
211
213 SPIRV::Decoration::Decoration Dec,
214 const std::vector<uint32_t> &DecArgs, StringRef StrImm) {
215 auto MIB = MIRBuilder.buildInstr(SPIRV::OpDecorate)
219}
220
222 SPIRV::Decoration::Decoration Dec,
223 const std::vector<uint32_t> &DecArgs, StringRef StrImm) {
225 auto MIB = BuildMI(MBB, I, I.getDebugLoc(), TII.get(SPIRV::OpDecorate))
229}
230
232 SPIRV::Decoration::Decoration Dec, uint32_t Member,
233 const std::vector<uint32_t> &DecArgs,
235 auto MIB = MIRBuilder.buildInstr(SPIRV::OpMemberDecorate)
240}
241
244 SPIRV::Decoration::Decoration Dec, uint32_t Member,
245 const std::vector<uint32_t> &DecArgs,
248 auto MIB = BuildMI(MBB, I, I.getDebugLoc(), TII.get(SPIRV::OpMemberDecorate))
253}
254
259 if (!OpMD)
261 if (OpMD->getNumOperands() == 0)
265 if (!DecorationId)
266 report_fatal_error("Expect SPIR-V operand to be the first "
267 "element of the decoration");
268
269
270
271
272
273
274
275
277 static_cast<uint32_t>(SPIRV::Decoration::NoContraction) ||
279 static_cast<uint32_t>(SPIRV::Decoration::FPFastMathMode)) {
280 continue;
281 }
282 auto MIB = MIRBuilder.buildInstr(SPIRV::OpDecorate)
285 for (unsigned OpI = 1, OpE = OpMD->getNumOperands(); OpI != OpE; ++OpI) {
288 MIB.addImm(static_cast<uint32_t>(OpV->getZExtValue()));
291 else
293 }
294 }
295}
296
302 bool IsHeader = false;
303 unsigned Opcode;
304 for (; It != E && It != I; ++It) {
305 Opcode = It->getOpcode();
306 if (Opcode == SPIRV::OpFunction || Opcode == SPIRV::OpFunctionParameter) {
307 IsHeader = true;
308 } else if (IsHeader &&
309 !(Opcode == SPIRV::ASSIGN_TYPE || Opcode == SPIRV::OpLabel)) {
310 ++It;
311 break;
312 }
313 }
314 return It;
315}
316
320 return I;
321 --I;
322 while (I->isTerminator() || I->isDebugValue()) {
324 break;
325 --I;
326 }
327 return I;
328}
329
330SPIRV::StorageClass::StorageClass
332 switch (AddrSpace) {
333 case 0:
334 return SPIRV::StorageClass::Function;
335 case 1:
336 return SPIRV::StorageClass::CrossWorkgroup;
337 case 2:
338 return SPIRV::StorageClass::UniformConstant;
339 case 3:
340 return SPIRV::StorageClass::Workgroup;
341 case 4:
342 return SPIRV::StorageClass::Generic;
343 case 5:
344 return STI.canUseExtension(SPIRV::Extension::SPV_INTEL_usm_storage_classes)
345 ? SPIRV::StorageClass::DeviceOnlyINTEL
346 : SPIRV::StorageClass::CrossWorkgroup;
347 case 6:
348 return STI.canUseExtension(SPIRV::Extension::SPV_INTEL_usm_storage_classes)
349 ? SPIRV::StorageClass::HostOnlyINTEL
350 : SPIRV::StorageClass::CrossWorkgroup;
351 case 7:
352 return SPIRV::StorageClass::Input;
353 case 8:
354 return SPIRV::StorageClass::Output;
355 case 9:
356 return SPIRV::StorageClass::CodeSectionINTEL;
357 case 10:
358 return SPIRV::StorageClass::Private;
359 case 11:
360 return SPIRV::StorageClass::StorageBuffer;
361 case 12:
362 return SPIRV::StorageClass::Uniform;
363 default:
365 }
366}
367
368SPIRV::MemorySemantics::MemorySemantics
370 switch (SC) {
371 case SPIRV::StorageClass::StorageBuffer:
372 case SPIRV::StorageClass::Uniform:
373 return SPIRV::MemorySemantics::UniformMemory;
374 case SPIRV::StorageClass::Workgroup:
375 return SPIRV::MemorySemantics::WorkgroupMemory;
376 case SPIRV::StorageClass::CrossWorkgroup:
377 return SPIRV::MemorySemantics::CrossWorkgroupMemory;
378 case SPIRV::StorageClass::AtomicCounter:
379 return SPIRV::MemorySemantics::AtomicCounterMemory;
380 case SPIRV::StorageClass::Image:
381 return SPIRV::MemorySemantics::ImageMemory;
382 default:
383 return SPIRV::MemorySemantics::None;
384 }
385}
386
388 switch (Ord) {
390 return SPIRV::MemorySemantics::Acquire;
392 return SPIRV::MemorySemantics::Release;
394 return SPIRV::MemorySemantics::AcquireRelease;
396 return SPIRV::MemorySemantics::SequentiallyConsistent;
400 return SPIRV::MemorySemantics::None;
401 }
403}
404
406
407
408
409
410
412 Ctx.getOrInsertSyncScopeID("subgroup");
414 Ctx.getOrInsertSyncScopeID("workgroup");
416 Ctx.getOrInsertSyncScopeID("device");
417
419 return SPIRV::Scope::Invocation;
421 return SPIRV::Scope::CrossDevice;
422 else if (Id == SubGroup)
423 return SPIRV::Scope::Subgroup;
424 else if (Id == WorkGroup)
425 return SPIRV::Scope::Workgroup;
426 else if (Id == Device)
427 return SPIRV::Scope::Device;
428 return SPIRV::Scope::CrossDevice;
429}
430
435 MI->getOpcode() == SPIRV::G_TRUNC || MI->getOpcode() == SPIRV::G_ZEXT
436 ? MRI->getVRegDef(MI->getOperand(1).getReg())
437 : MI;
439 if (GI->is(Intrinsic::spv_track_constant)) {
441 return MRI->getVRegDef(ConstReg);
442 }
443 } else if (ConstInstr->getOpcode() == SPIRV::ASSIGN_TYPE) {
445 return MRI->getVRegDef(ConstReg);
446 } else if (ConstInstr->getOpcode() == TargetOpcode::G_CONSTANT ||
447 ConstInstr->getOpcode() == TargetOpcode::G_FCONSTANT) {
449 return ConstInstr;
450 }
451 return MRI->getVRegDef(ConstReg);
452}
453
456 assert(MI && MI->getOpcode() == TargetOpcode::G_CONSTANT);
457 return MI->getOperand(1).getCImm()->getValue().getZExtValue();
458}
459
462 assert(MI && MI->getOpcode() == TargetOpcode::G_CONSTANT);
463 return MI->getOperand(1).getCImm()->getSExtValue();
464}
465
468 return GI->is(IntrinsicID);
469 return false;
470}
471
476
477
478
480 return MangledName == "write_pipe_2" || MangledName == "read_pipe_2" ||
481 MangledName == "write_pipe_2_bl" || MangledName == "read_pipe_2_bl" ||
482 MangledName == "write_pipe_4" || MangledName == "read_pipe_4" ||
483 MangledName == "reserve_write_pipe" ||
484 MangledName == "reserve_read_pipe" ||
485 MangledName == "commit_write_pipe" ||
486 MangledName == "commit_read_pipe" ||
487 MangledName == "work_group_reserve_write_pipe" ||
488 MangledName == "work_group_reserve_read_pipe" ||
489 MangledName == "work_group_commit_write_pipe" ||
490 MangledName == "work_group_commit_read_pipe" ||
491 MangledName == "get_pipe_num_packets_ro" ||
492 MangledName == "get_pipe_max_packets_ro" ||
493 MangledName == "get_pipe_num_packets_wo" ||
494 MangledName == "get_pipe_max_packets_wo" ||
495 MangledName == "sub_group_reserve_write_pipe" ||
496 MangledName == "sub_group_reserve_read_pipe" ||
497 MangledName == "sub_group_commit_write_pipe" ||
498 MangledName == "sub_group_commit_read_pipe" ||
499 MangledName == "to_global" || MangledName == "to_local" ||
500 MangledName == "to_private";
501}
502
504 return MangledName == "__enqueue_kernel_basic" ||
505 MangledName == "__enqueue_kernel_basic_events" ||
506 MangledName == "__enqueue_kernel_varargs" ||
507 MangledName == "__enqueue_kernel_events_varargs";
508}
509
511 return MangledName == "__get_kernel_work_group_size_impl" ||
512 MangledName == "__get_kernel_sub_group_count_for_ndrange_impl" ||
513 MangledName == "__get_kernel_max_sub_group_size_for_ndrange_impl" ||
514 MangledName == "__get_kernel_preferred_work_group_size_multiple_impl";
515}
516
518 if (!Name.starts_with("__"))
519 return false;
520
523 Name == "__translate_sampler_initializer";
524}
525
528 bool IsNonMangledSPIRV = Name.starts_with("__spirv_");
529 bool IsNonMangledHLSL = Name.starts_with("__hlsl_");
530 bool IsMangled = Name.starts_with("_Z");
531
532
533 if (IsNonMangledOCL || IsNonMangledSPIRV || IsNonMangledHLSL || !IsMangled)
534 return Name.str();
535
536
537 if (char *DemangledName = itaniumDemangle(Name.data())) {
538 std::string Result = DemangledName;
539 free(DemangledName);
540 return Result;
541 }
542
543
544
545
546
547 size_t Start, Len = 0;
548 size_t DemangledNameLenStart = 2;
549 if (Name.starts_with("_ZN")) {
550
551 size_t NameSpaceStart = Name.find_first_not_of("rVKRO", 3);
552
553 if (Name.substr(NameSpaceStart, 11) != "2cl7__spirv")
554 return std::string();
555 DemangledNameLenStart = NameSpaceStart + 11;
556 }
557 Start = Name.find_first_not_of("0123456789", DemangledNameLenStart);
558 [[maybe_unused]] bool Error =
559 Name.substr(DemangledNameLenStart, Start - DemangledNameLenStart)
560 .getAsInteger(10, Len);
561 assert( && "Failed to parse demangled name length");
562 return Name.substr(Start, Len).str();
563}
564
566 if (Name.starts_with("opencl.") || Name.starts_with("ocl_") ||
567 Name.starts_with("spirv."))
568 return true;
569 return false;
570}
571
577
578 return false;
579}
580
582
583
585 return true;
586
587
588
589 if (F.getFnAttribute("hlsl.shader").isValid())
590 return true;
591
592 return false;
593}
594
596 TypeName.consume_front("atomic_");
597 if (TypeName.consume_front("void"))
599 else if (TypeName.consume_front("bool") || TypeName.consume_front("_Bool"))
601 else if (TypeName.consume_front("char") ||
602 TypeName.consume_front("signed char") ||
603 TypeName.consume_front("unsigned char") ||
604 TypeName.consume_front("uchar"))
606 else if (TypeName.consume_front("short") ||
607 TypeName.consume_front("signed short") ||
608 TypeName.consume_front("unsigned short") ||
609 TypeName.consume_front("ushort"))
611 else if (TypeName.consume_front("int") ||
612 TypeName.consume_front("signed int") ||
613 TypeName.consume_front("unsigned int") ||
614 TypeName.consume_front("uint"))
616 else if (TypeName.consume_front("long") ||
617 TypeName.consume_front("signed long") ||
618 TypeName.consume_front("unsigned long") ||
619 TypeName.consume_front("ulong"))
621 else if (TypeName.consume_front("half") ||
622 TypeName.consume_front("_Float16") ||
623 TypeName.consume_front("__fp16"))
625 else if (TypeName.consume_front("float"))
627 else if (TypeName.consume_front("double"))
629
630
631 return nullptr;
632}
633
634std::unordered_set<BasicBlock *>
635PartialOrderingVisitor::getReachableFrom(BasicBlock *Start) {
636 std::queue<BasicBlock *> ToVisit;
637 ToVisit.push(Start);
638
639 std::unordered_set<BasicBlock *> Output;
640 while (ToVisit.size() != 0) {
641 BasicBlock *BB = ToVisit.front();
642 ToVisit.pop();
643
644 if (Output.count(BB) != 0)
645 continue;
646 Output.insert(BB);
647
650 continue;
652 }
653 }
654
655 return Output;
656}
657
658bool PartialOrderingVisitor::CanBeVisited(BasicBlock *BB) const {
660
661 if (DT.dominates(BB, P))
662 continue;
663
664
665 if (BlockToOrder.count(P) == 0)
666 return false;
667
668
669
670 Loop *L = LI.getLoopFor(P);
671 if (L == nullptr || L->contains(BB))
672 continue;
673
674
675
676
677 assert(L->getNumBackEdges() <= 1);
678
679
680
683 if (Latch == nullptr)
684 continue;
685
686
687 if (BlockToOrder.count(Latch) == 0)
688 return false;
689 }
690
691 return true;
692}
693
695 auto It = BlockToOrder.find(BB);
696 if (It != BlockToOrder.end())
697 return It->second.Rank;
698
699 size_t result = 0;
701
702 if (DT.dominates(BB, P))
703 continue;
704
705 auto Iterator = BlockToOrder.end();
706 Loop *L = LI.getLoopFor(P);
707 BasicBlock *Latch = L ? L->getLoopLatch() : nullptr;
708
709
710
711 if (L == nullptr || L->contains(BB) || Latch == nullptr) {
712 Iterator = BlockToOrder.find(P);
713 } else {
714
715
716
717 Iterator = BlockToOrder.find(Latch);
718 }
719
720 assert(Iterator != BlockToOrder.end());
721 result = std::max(result, Iterator->second.Rank + 1);
722 }
723
724 return result;
725}
726
727size_t PartialOrderingVisitor::visit(BasicBlock *BB, size_t Unused) {
728 ToVisit.push(BB);
729 Queued.insert(BB);
730
731 size_t QueueIndex = 0;
732 while (ToVisit.size() != 0) {
734 ToVisit.pop();
735
736 if (!CanBeVisited(BB)) {
737 ToVisit.push(BB);
738 if (QueueIndex >= ToVisit.size())
740 "No valid candidate in the queue. Is the graph reducible?");
741 QueueIndex++;
742 continue;
743 }
744
745 QueueIndex = 0;
747 OrderInfo Info = {Rank, BlockToOrder.size()};
748 BlockToOrder.emplace(BB, Info);
749
750 for (BasicBlock *S : successors(BB)) {
751 if (Queued.count(S) != 0)
752 continue;
753 ToVisit.push(S);
754 Queued.insert(S);
755 }
756 }
757
758 return 0;
759}
760
762 DT.recalculate(F);
764
765 visit(&*F.begin(), 0);
766
767 Order.reserve(F.size());
768 for (auto &[BB, Info] : BlockToOrder)
769 Order.emplace_back(BB);
770
771 std::sort(Order.begin(), Order.end(), [&](const auto &LHS, const auto &RHS) {
772 return compare(LHS, RHS);
773 });
774}
775
778 const OrderInfo &InfoLHS = BlockToOrder.at(const_cast<BasicBlock *>(LHS));
779 const OrderInfo &InfoRHS = BlockToOrder.at(const_cast<BasicBlock *>(RHS));
780 if (InfoLHS.Rank != InfoRHS.Rank)
781 return InfoLHS.Rank < InfoRHS.Rank;
782 return InfoLHS.TraversalIndex < InfoRHS.TraversalIndex;
783}
784
787 std::unordered_set<BasicBlock *> Reachable = getReachableFrom(&Start);
788 assert(BlockToOrder.count(&Start) != 0);
789
790
791 auto It = Order.begin();
792 while (It != Order.end() && *It != &Start)
793 ++It;
794
795
796
797 assert(It != Order.end());
798
799
800 std::optional<size_t> EndRank = std::nullopt;
801 for (; It != Order.end(); ++It) {
802 if (EndRank.has_value() && BlockToOrder[*It].Rank > *EndRank)
803 break;
804
805 if (Reachable.count(*It) == 0) {
806 continue;
807 }
808
809 if ((*It)) {
810 EndRank = BlockToOrder[*It].Rank;
811 }
812 }
813}
814
816 if (F.size() == 0)
817 return false;
818
820 std::vector<BasicBlock *> Order;
821 Order.reserve(F.size());
822
825
826 assert(&*F.begin() == Order[0]);
829 if (BB != LastBlock && &*LastBlock->getNextNode() != BB) {
832 }
833 LastBlock = BB;
834 }
835
837}
838
841 if (MaybeDef && MaybeDef->getOpcode() == SPIRV::ASSIGN_TYPE)
843 return MaybeDef;
844}
845
847
848
849 constexpr unsigned MaxIters = 1024;
850 for (unsigned I = 0; I < MaxIters; ++I) {
851 std::string OrdName = Name + Twine(I).str();
852 if (!M.getFunction(OrdName)) {
853 Name = std::move(OrdName);
854 return true;
855 }
856 }
857 return false;
858}
859
860
861
864 bool Force) {
866 if (->getRegClassOrNull(Reg) || Force) {
869 }
870}
871
872
873
874
877 SPIRV::AccessQualifier::AccessQualifier AccessQual,
878 bool EmitIR, bool Force) {
881 GR, MIRBuilder.getMRI(), MIRBuilder.getMF(), Force);
882}
883
884
885
894
895
896
900 MIRBuilder.getMF());
901}
902
903
904
907 SPIRV::AccessQualifier::AccessQualifier AccessQual, bool EmitIR) {
910 MIRBuilder);
911}
912
917 Args.push_back(Arg2);
918 Args.push_back(buildMD(Arg));
920 return B.CreateIntrinsic(IntrID, {Types}, Args);
921}
922
923
925 if (Ty->isPtrOrPtrVectorTy())
926 return true;
929 return true;
930 for (const Type *ArgTy : RefTy->params())
932 return true;
933 return false;
934 }
937 return false;
938}
939
942 if (Function *F = II->getCalledFunction())
943 if (F->getName().starts_with("llvm.spv."))
944 return true;
945 return false;
946}
947
948
949
950SmallVector<MachineInstr *, 4>
952 unsigned MinWC, unsigned ContinuedOpcode,
955
957 constexpr unsigned MaxWordCount = UINT16_MAX;
958 const size_t NumElements = Args.size();
959 size_t MaxNumElements = MaxWordCount - MinWC;
960 size_t SPIRVStructNumElements = NumElements;
961
962 if (NumElements > MaxNumElements) {
963
964
965 SPIRVStructNumElements = MaxNumElements;
966 MaxNumElements = MaxWordCount - 1;
967 }
968
969 auto MIB =
971
972 for (size_t I = 0; I < SPIRVStructNumElements; ++I)
974
975 Instructions.push_back(MIB.getInstr());
976
977 for (size_t I = SPIRVStructNumElements; I < NumElements;
978 I += MaxNumElements) {
979 auto MIB = MIRBuilder.buildInstr(ContinuedOpcode);
980 for (size_t J = I; J < std::min(I + MaxNumElements, NumElements); ++J)
982 Instructions.push_back(MIB.getInstr());
983 }
984 return Instructions;
985}
986
988 unsigned LC = SPIRV::LoopControl::None;
989
990
991
992 std::vector<std::pair<unsigned, unsigned>> MaskToValueMap;
994 LC |= SPIRV::LoopControl::DontUnroll;
995 } else {
998 LC |= SPIRV::LoopControl::Unroll;
999 }
1000 std::optional Count =
1003 LC |= SPIRV::LoopControl::PartialCount;
1004 MaskToValueMap.emplace_back(
1005 std::make_pair(SPIRV::LoopControl::PartialCount, *Count));
1006 }
1007 }
1009 for (auto &[Mask, Val] : MaskToValueMap)
1010 Result.push_back(Val);
1011 return Result;
1012}
1013
1015
1016 static const std::set TypeFoldingSupportingOpcs = {
1017 TargetOpcode::G_ADD,
1018 TargetOpcode::G_FADD,
1019 TargetOpcode::G_STRICT_FADD,
1020 TargetOpcode::G_SUB,
1021 TargetOpcode::G_FSUB,
1022 TargetOpcode::G_STRICT_FSUB,
1023 TargetOpcode::G_MUL,
1024 TargetOpcode::G_FMUL,
1025 TargetOpcode::G_STRICT_FMUL,
1026 TargetOpcode::G_SDIV,
1027 TargetOpcode::G_UDIV,
1028 TargetOpcode::G_FDIV,
1029 TargetOpcode::G_STRICT_FDIV,
1030 TargetOpcode::G_SREM,
1031 TargetOpcode::G_UREM,
1032 TargetOpcode::G_FREM,
1033 TargetOpcode::G_STRICT_FREM,
1034 TargetOpcode::G_FNEG,
1035 TargetOpcode::G_CONSTANT,
1036 TargetOpcode::G_FCONSTANT,
1037 TargetOpcode::G_AND,
1038 TargetOpcode::G_OR,
1039 TargetOpcode::G_XOR,
1040 TargetOpcode::G_SHL,
1041 TargetOpcode::G_ASHR,
1042 TargetOpcode::G_LSHR,
1043 TargetOpcode::G_SELECT,
1044 TargetOpcode::G_EXTRACT_VECTOR_ELT,
1045 };
1046
1047 return TypeFoldingSupportingOpcs;
1048}
1049
1053
1054
1056 return (Def->getOpcode() == SPIRV::ASSIGN_TYPE ||
1057 Def->getOpcode() == TargetOpcode::COPY)
1058 ? MRI->getVRegDef(Def->getOperand(1).getReg())
1059 : Def;
1060}
1061
1065 return nullptr;
1066}
1067
1070 if (Def->getOpcode() == TargetOpcode::G_CONSTANT ||
1071 Def->getOpcode() == SPIRV::OpConstantI)
1072 return Def;
1073 }
1074 return nullptr;
1075}
1076
1079 if (Def->getOpcode() == SPIRV::OpConstantI)
1080 return Def->getOperand(2).getImm();
1081 if (Def->getOpcode() == TargetOpcode::G_CONSTANT)
1082 return Def->getOperand(1).getCImm()->getZExtValue();
1083 }
1085}
1086
1091
1094
1095
1096
1098 while (VarPos != BB.end() && VarPos->getOpcode() != SPIRV::OpFunction) {
1099 ++VarPos;
1100 }
1101
1102
1103
1104 ++VarPos;
1105 while (VarPos != BB.end() &&
1106 VarPos->getOpcode() == SPIRV::OpFunctionParameter) {
1107 ++VarPos;
1108 }
1109
1110
1111 return VarPos != BB.end() && VarPos->getOpcode() == SPIRV::OpLabel ? ++VarPos
1112 : VarPos;
1113}
1114
1117
1118 if (Ty->getStructNumElements() != 2)
1119 return false;
1120
1123
1125 return false;
1126
1128 if (!ArrayElementType->isStructTy() ||
1130 return false;
1131
1133 if (T_in_struct != SecondElement)
1134 return false;
1135
1136 auto *Padding_in_struct =
1138 if (!Padding_in_struct || Padding_in_struct->getName() != "spirv.Padding")
1139 return false;
1140
1142 TotalSize = ArraySize + 1;
1143 OriginalElementType = ArrayElementType;
1144 return true;
1145}
1146
1148 if (!Ty->isStructTy())
1149 return Ty;
1150
1152 Type *OriginalElementType = nullptr;
1157 return ResultTy;
1158 }
1159
1162 for (Type *ElementTy : STy->elements()) {
1164 if (NewElementTy != ElementTy)
1166 NewElementTypes.push_back(NewElementTy);
1167 }
1168
1170 return Ty;
1171
1172 Type *ResultTy;
1173 if (STy->isLiteral())
1174 ResultTy =
1175 StructType::get(STy->getContext(), NewElementTypes, STy->isPacked());
1176 else {
1177 auto *NewTy = StructType::create(STy->getContext(), STy->getName());
1178 NewTy->setBody(NewElementTypes, STy->isPacked());
1179 ResultTy = NewTy;
1180 }
1181 return ResultTy;
1182}
1183
1184std::optionalSPIRV::LinkageType::LinkageType
1187 return std::nullopt;
1188
1190 return SPIRV::LinkageType::Import;
1191
1193 ST.canUseExtension(SPIRV::Extension::SPV_KHR_linkonce_odr))
1194 return SPIRV::LinkageType::LinkOnceODR;
1195
1196 return SPIRV::LinkageType::Export;
1197}
1198
1199}
unsigned const MachineRegisterInfo * MRI
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
Analysis containing CSE Info
Declares convenience wrapper classes for interpreting MachineInstr instances as specific generic oper...
const HexagonInstrInfo * TII
This file declares the MachineIRBuilder class.
uint64_t IntrinsicInst * II
static ConstantInt * getConstInt(MDNode *MD, unsigned NumOp)
Class for arbitrary precision integers.
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...
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.
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
Base class for all callable instructions (InvokeInst and CallInst) Holds everything related to callin...
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 or float/double,...
StringRef getAsCString() const
If this array is isCString(), then this method returns the array (without the trailing null byte) as ...
This is the shared class of boolean and integer constants.
uint64_t getZExtValue() const
Return the constant as a 64-bit unsigned integer value after it has been zero extended as appropriate...
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.
Class to represent function types.
ArrayRef< Type * > params() 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.
bool hasLocalLinkage() const
bool hasHiddenVisibility() const
bool isDeclarationForLinker() const
bool hasLinkOnceODRLinkage() const
This provides a uniform API for creating instructions and inserting them into a basic block: either a...
LLVM_ABI const Module * getModule() const
Return the module owning the function this instruction belongs to or nullptr it the function does not...
This is an important class for using LLVM in a threaded context.
Represents a single loop in the control flow graph.
Instances of this class represent a single low-level machine instruction.
void addOperand(const MCOperand Op)
static MCOperand createImm(int64_t Val)
const MDOperand & getOperand(unsigned I) const
unsigned getNumOperands() const
Return number of MDNode operands.
MachineInstrBundleIterator< MachineInstr > iterator
const MachineBasicBlock & front() const
Helper class to build MachineInstr.
MachineInstrBuilder buildInstr(unsigned Opcode)
Build and insert = Opcode .
MachineFunction & getMF()
Getter for the function we currently build.
MachineRegisterInfo * getMRI()
Getter for MRI.
const MachineInstrBuilder & addImm(int64_t Val) const
Add a new immediate operand.
const MachineInstrBuilder & addUse(Register RegNo, unsigned Flags=0, unsigned SubReg=0) const
Add a virtual register use operand.
MachineInstr * getInstr() const
If conversion operators fail, use this method to get the MachineInstr explicitly.
const MachineInstrBuilder & addDef(Register RegNo, unsigned Flags=0, unsigned SubReg=0) const
Add a virtual register definition operand.
Representation of each machine instruction.
unsigned getOpcode() const
Returns the opcode of this MachineInstr.
void setAsmPrinterFlag(uint8_t 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,...
A Module instance is used to store all the information related to an LLVM module.
NamedMDNode * getNamedMetadata(StringRef Name) const
Return the first NamedMDNode in the module with the specified name.
iterator_range< op_iterator > operands()
size_t GetNodeRank(BasicBlock *BB) const
Definition SPIRVUtils.cpp:694
void partialOrderVisit(BasicBlock &Start, std::function< bool(BasicBlock *)> Op)
Definition SPIRVUtils.cpp:785
bool compare(const BasicBlock *LHS, const BasicBlock *RHS) const
Definition SPIRVUtils.cpp:776
PartialOrderingVisitor(Function &F)
Definition SPIRVUtils.cpp:761
Wrapper class representing virtual and physical registers.
void assignSPIRVTypeToVReg(SPIRVType *Type, Register VReg, const MachineFunction &MF)
SPIRVType * getOrCreateSPIRVType(const Type *Type, MachineInstr &I, SPIRV::AccessQualifier::AccessQualifier AQ, bool EmitIR)
const TargetRegisterClass * getRegClass(SPIRVType *SpvType) const
LLT getRegType(SPIRVType *SpvType) const
bool canUseExtension(SPIRV::Extension::Extension E) const
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
StringRef - Represent a constant reference to a string, i.e.
std::string str() const
str - Get the contents as an std::string.
constexpr bool empty() const
empty - Check if the string is empty.
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.
static LLVM_ABI StructType * create(LLVMContext &Context, StringRef Name)
This creates an identified struct.
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...
LLVM_ABI std::string str() const
Return the twine contents as a std::string.
The instances of the Type class are immutable: once they are created, they are never changed.
static LLVM_ABI IntegerType * getInt64Ty(LLVMContext &C)
LLVM_ABI Type * getStructElementType(unsigned N) const
bool isArrayTy() const
True if this is an instance of ArrayType.
static LLVM_ABI IntegerType * getInt32Ty(LLVMContext &C)
Type * getArrayElementType() const
LLVM_ABI unsigned getStructNumElements() const
LLVM_ABI uint64_t getArrayNumElements() const
static LLVM_ABI Type * getVoidTy(LLVMContext &C)
static LLVM_ABI IntegerType * getInt8Ty(LLVMContext &C)
bool isStructTy() const
True if this is an instance of StructType.
static LLVM_ABI IntegerType * getInt16Ty(LLVMContext &C)
static LLVM_ABI IntegerType * getIntNTy(LLVMContext &C, unsigned N)
static LLVM_ABI Type * getDoubleTy(LLVMContext &C)
static LLVM_ABI Type * getFloatTy(LLVMContext &C)
static LLVM_ABI Type * getHalfTy(LLVMContext &C)
Value * getOperand(unsigned i) const
LLVM Value Representation.
LLVM_ABI StringRef getName() const
Return a constant reference to the value's name.
NodeTy * getNextNode()
Get the next node, or nullptr for the list tail.
#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.
FunctionType * getOriginalFunctionType(const Function &F)
Definition SPIRVUtils.cpp:82
static FunctionType * extractFunctionTypeFromMetadata(NamedMDNode *NMD, FunctionType *FTy, StringRef Name)
Definition SPIRVUtils.cpp:36
@ SingleThread
Synchronized with respect to signal handlers executing in the same thread.
@ System
Synchronized with respect to all concurrently executing threads.
std::enable_if_t< detail::IsValidPointer< X, Y >::value, X * > dyn_extract(Y &&MD)
Extract a Value from Metadata, if any.
This is an optimization pass for GlobalISel generic memory operations.
void buildOpName(Register Target, const StringRef &Name, MachineIRBuilder &MIRBuilder)
Definition SPIRVUtils.cpp:185
bool getVacantFunctionName(Module &M, std::string &Name)
Definition SPIRVUtils.cpp:846
std::string getStringImm(const MachineInstr &MI, unsigned StartIndex)
Definition SPIRVUtils.cpp:142
LLVM_ABI bool getBooleanLoopAttribute(const Loop *TheLoop, StringRef Name)
Returns true if Name is applied to TheLoop and enabled.
int64_t getIConstValSext(Register ConstReg, const MachineRegisterInfo *MRI)
Definition SPIRVUtils.cpp:460
bool isTypedPointerWrapper(const TargetExtType *ExtTy)
MachineInstrBuilder BuildMI(MachineFunction &MF, const MIMetadata &MIMD, const MCInstrDesc &MCID)
Builder interface. Specify how to create the initial instruction itself.
static void finishBuildOpDecorate(MachineInstrBuilder &MIB, const std::vector< uint32_t > &DecArgs, StringRef StrImm)
Definition SPIRVUtils.cpp:203
bool isTypeFoldingSupported(unsigned Opcode)
Definition SPIRVUtils.cpp:1050
static uint32_t convertCharsToWord(const StringRef &Str, unsigned i)
Definition SPIRVUtils.cpp:99
decltype(auto) dyn_cast(const From &Val)
dyn_cast - Return the argument parameter cast to the specified type.
MachineInstr * getDef(const MachineOperand &MO, const MachineRegisterInfo *MRI)
Definition SPIRVUtils.cpp:1062
void addNumImm(const APInt &Imm, MachineInstrBuilder &MIB)
Definition SPIRVUtils.cpp:156
auto successors(const MachineBasicBlock *BB)
CallInst * buildIntrWithMD(Intrinsic::ID IntrID, ArrayRef< Type * > Types, Value *Arg, Value *Arg2, ArrayRef< Constant * > Imms, IRBuilder<> &B)
Definition SPIRVUtils.cpp:913
bool matchPeeledArrayPattern(const StructType *Ty, Type *&OriginalElementType, uint64_t &TotalSize)
Definition SPIRVUtils.cpp:1115
void append_range(Container &C, Range &&R)
Wrapper function to append range R to container C.
unsigned getArrayComponentCount(const MachineRegisterInfo *MRI, const MachineInstr *ResType)
Definition SPIRVUtils.cpp:1087
bool sortBlocks(Function &F)
Definition SPIRVUtils.cpp:815
SmallVector< unsigned, 1 > getSpirvLoopControlOperandsFromLoopMetadata(Loop *L)
Definition SPIRVUtils.cpp:987
uint64_t getIConstVal(Register ConstReg, const MachineRegisterInfo *MRI)
Definition SPIRVUtils.cpp:454
SmallVector< MachineInstr *, 4 > createContinuedInstructions(MachineIRBuilder &MIRBuilder, unsigned Opcode, unsigned MinWC, unsigned ContinuedOpcode, ArrayRef< Register > Args, Register ReturnRegister, Register TypeID)
Definition SPIRVUtils.cpp:951
SPIRV::MemorySemantics::MemorySemantics getMemSemanticsForStorageClass(SPIRV::StorageClass::StorageClass SC)
Definition SPIRVUtils.cpp:369
MachineBasicBlock::iterator getFirstValidInstructionInsertPoint(MachineBasicBlock &BB)
Definition SPIRVUtils.cpp:1093
bool isNestedPointer(const Type *Ty)
Definition SPIRVUtils.cpp:924
MetadataAsValue * buildMD(Value *Arg)
std::string getOclOrSpirvBuiltinDemangledName(StringRef Name)
Definition SPIRVUtils.cpp:526
void buildOpDecorate(Register Reg, MachineIRBuilder &MIRBuilder, SPIRV::Decoration::Decoration Dec, const std::vector< uint32_t > &DecArgs, StringRef StrImm)
Definition SPIRVUtils.cpp:212
MachineBasicBlock::iterator getOpVariableMBBIt(MachineInstr &I)
Definition SPIRVUtils.cpp:297
Register createVirtualRegister(SPIRVType *SpvType, SPIRVGlobalRegistry *GR, MachineRegisterInfo *MRI, const MachineFunction &MF)
Definition SPIRVUtils.cpp:886
MachineInstr * getImm(const MachineOperand &MO, const MachineRegisterInfo *MRI)
Definition SPIRVUtils.cpp:1068
std::string getSPIRVStringOperand(const InstType &MI, unsigned StartIndex)
void buildOpMemberDecorate(Register Reg, MachineIRBuilder &MIRBuilder, SPIRV::Decoration::Decoration Dec, uint32_t Member, const std::vector< uint32_t > &DecArgs, StringRef StrImm)
Definition SPIRVUtils.cpp:231
Type * toTypedPointer(Type *Ty)
DEMANGLE_ABI char * itaniumDemangle(std::string_view mangled_name, bool ParseParams=true)
Returns a non-NULL pointer to a NUL-terminated C style string that should be explicitly freed,...
bool isSpecialOpaqueType(const Type *Ty)
Definition SPIRVUtils.cpp:572
void setRegClassType(Register Reg, SPIRVType *SpvType, SPIRVGlobalRegistry *GR, MachineRegisterInfo *MRI, const MachineFunction &MF, bool Force)
Definition SPIRVUtils.cpp:862
LLVM_ABI void report_fatal_error(Error Err, bool gen_crash_diag=true)
MachineBasicBlock::iterator getInsertPtValidEnd(MachineBasicBlock *MBB)
Definition SPIRVUtils.cpp:317
FunctionAddr VTableAddr Count
const MachineInstr SPIRVType
static bool isNonMangledOCLBuiltin(StringRef Name)
Definition SPIRVUtils.cpp:517
MachineInstr * passCopy(MachineInstr *Def, const MachineRegisterInfo *MRI)
Definition SPIRVUtils.cpp:1055
std::optional< SPIRV::LinkageType::LinkageType > getSpirvLinkageTypeFor(const SPIRVSubtarget &ST, const GlobalValue &GV)
Definition SPIRVUtils.cpp:1185
bool isEntryPoint(const Function &F)
Definition SPIRVUtils.cpp:581
const std::set< unsigned > & getTypeFoldingSupportedOpcodes()
Definition SPIRVUtils.cpp:1014
SPIRV::StorageClass::StorageClass addressSpaceToStorageClass(unsigned AddrSpace, const SPIRVSubtarget &STI)
Definition SPIRVUtils.cpp:331
LLVM_ABI std::optional< int > getOptionalIntLoopAttribute(const Loop *TheLoop, StringRef Name)
Find named metadata for a loop with an integer value.
AtomicOrdering
Atomic ordering for LLVM's memory model.
SPIRV::Scope::Scope getMemScope(LLVMContext &Ctx, SyncScope::ID Id)
Definition SPIRVUtils.cpp:405
static bool isPipeOrAddressSpaceCastBI(const StringRef MangledName)
Definition SPIRVUtils.cpp:479
void buildOpSpirvDecorations(Register Reg, MachineIRBuilder &MIRBuilder, const MDNode *GVarMD, const SPIRVSubtarget &ST)
Definition SPIRVUtils.cpp:255
std::string getStringValueFromReg(Register Reg, MachineRegisterInfo &MRI)
Definition SPIRVUtils.cpp:146
int64_t foldImm(const MachineOperand &MO, const MachineRegisterInfo *MRI)
Definition SPIRVUtils.cpp:1077
Type * parseBasicTypeName(StringRef &TypeName, LLVMContext &Ctx)
Definition SPIRVUtils.cpp:595
DWARFExpression::Operation Op
MachineInstr * getDefInstrMaybeConstant(Register &ConstReg, const MachineRegisterInfo *MRI)
Definition SPIRVUtils.cpp:431
decltype(auto) cast(const From &Val)
cast - Return the argument parameter cast to the specified type.
bool hasBuiltinTypePrefix(StringRef Name)
Definition SPIRVUtils.cpp:565
Type * getMDOperandAsType(const MDNode *N, unsigned I)
Definition SPIRVUtils.cpp:472
auto find_if(R &&Range, UnaryPredicate P)
Provide wrappers to std::find_if which take ranges instead of having to pass begin/end explicitly.
auto predecessors(const MachineBasicBlock *BB)
static size_t getPaddedLen(const StringRef &Str)
Definition SPIRVUtils.cpp:113
bool isSpvIntrinsic(const MachineInstr &MI, Intrinsic::ID IntrinsicID)
Definition SPIRVUtils.cpp:466
void addStringImm(const StringRef &Str, MCInst &Inst)
Definition SPIRVUtils.cpp:117
static bool isKernelQueryBI(const StringRef MangledName)
Definition SPIRVUtils.cpp:510
MachineInstr * getVRegDef(MachineRegisterInfo &MRI, Register Reg)
Definition SPIRVUtils.cpp:839
static bool isEnqueueKernelBI(const StringRef MangledName)
Definition SPIRVUtils.cpp:503
Type * reconstitutePeeledArrayType(Type *Ty)
Definition SPIRVUtils.cpp:1147
SPIRV::MemorySemantics::MemorySemantics getMemSemantics(AtomicOrdering Ord)
Definition SPIRVUtils.cpp:387