LLVM 24.0.0git
IR2Vec.cpp
Go to the documentation of this file.
1//===- IR2Vec.cpp - Implementation of IR2Vec -----------------------------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM
4// Exceptions. See the LICENSE file for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8///
9/// \file
10/// This file implements the IR2Vec algorithm.
11///
12//===----------------------------------------------------------------------===//
13
15
17#include "llvm/ADT/Sequence.h"
18#include "llvm/ADT/Statistic.h"
19#include "llvm/IR/CFG.h"
20#include "llvm/IR/Module.h"
21#include "llvm/IR/PassManager.h"
22#include "llvm/Support/Debug.h"
23#include "llvm/Support/Errc.h"
24#include "llvm/Support/Error.h"
26#include "llvm/Support/Format.h"
28
29using namespace llvm;
30using namespace ir2vec;
31
32#define DEBUG_TYPE "ir2vec"
33
34STATISTIC(VocabMissCounter,
35 "Number of lookups to entities not present in the vocabulary");
36
37namespace llvm {
38namespace ir2vec {
40
41// FIXME: Use a default vocab when not specified
43 VocabFile("ir2vec-vocab-path", cl::Optional,
44 cl::desc("Path to the vocabulary file for IR2Vec"), cl::init(""),
46cl::opt<float> OpcWeight("ir2vec-opc-weight", cl::Optional, cl::init(1.0),
47 cl::desc("Weight for opcode embeddings"),
49cl::opt<float> TypeWeight("ir2vec-type-weight", cl::Optional, cl::init(0.5),
50 cl::desc("Weight for type embeddings"),
52cl::opt<float> ArgWeight("ir2vec-arg-weight", cl::Optional, cl::init(0.2),
53 cl::desc("Weight for argument embeddings"),
56 "ir2vec-kind", cl::Optional,
58 "Generate symbolic embeddings"),
60 "Generate flow-aware embeddings")),
61 cl::init(IR2VecKind::Symbolic), cl::desc("IR2Vec embedding kind"),
63
64} // namespace ir2vec
65} // namespace llvm
66
68
69// ==----------------------------------------------------------------------===//
70// Local helper functions
71//===----------------------------------------------------------------------===//
72namespace llvm::json {
73inline bool fromJSON(const llvm::json::Value &E, Embedding &Out,
75 std::vector<double> TempOut;
76 if (!llvm::json::fromJSON(E, TempOut, P))
77 return false;
78 Out = Embedding(std::move(TempOut));
79 return true;
80}
81} // namespace llvm::json
82
83// ==----------------------------------------------------------------------===//
84// Embedding
85//===----------------------------------------------------------------------===//
87 assert(this->size() == RHS.size() && "Vectors must have the same dimension");
88 std::transform(this->begin(), this->end(), RHS.begin(), this->begin(),
89 std::plus<double>());
90 return *this;
91}
92
94 Embedding Result(*this);
95 Result += RHS;
96 return Result;
97}
98
100 assert(this->size() == RHS.size() && "Vectors must have the same dimension");
101 std::transform(this->begin(), this->end(), RHS.begin(), this->begin(),
102 std::minus<double>());
103 return *this;
104}
105
107 Embedding Result(*this);
108 Result -= RHS;
109 return Result;
110}
111
113 std::transform(this->begin(), this->end(), this->begin(),
114 [Factor](double Elem) { return Elem * Factor; });
115 return *this;
116}
117
118Embedding Embedding::operator*(double Factor) const {
119 Embedding Result(*this);
120 Result *= Factor;
121 return Result;
122}
123
124Embedding &Embedding::scaleAndAdd(const Embedding &Src, float Factor) {
125 assert(this->size() == Src.size() && "Vectors must have the same dimension");
126 for (size_t Itr = 0; Itr < this->size(); ++Itr)
127 (*this)[Itr] += Src[Itr] * Factor;
128 return *this;
129}
130
132 double Tolerance) const {
133 assert(this->size() == RHS.size() && "Vectors must have the same dimension");
134 for (size_t Itr = 0; Itr < this->size(); ++Itr)
135 if (std::abs((*this)[Itr] - RHS[Itr]) > Tolerance) {
136 LLVM_DEBUG(errs() << "Embedding mismatch at index " << Itr << ": "
137 << (*this)[Itr] << " vs " << RHS[Itr]
138 << "; Tolerance: " << Tolerance << "\n");
139 return false;
140 }
141 return true;
142}
143
145 OS << " [";
146 for (const auto &Elem : Data)
147 OS << " " << format("%.2f", Elem) << " ";
148 OS << "]\n";
149}
150
151// ==----------------------------------------------------------------------===//
152// Embedder and its subclasses
153//===----------------------------------------------------------------------===//
154
155std::unique_ptr<Embedder> Embedder::create(IR2VecKind Mode, const Function &F,
156 const Vocabulary &Vocab) {
157 switch (Mode) {
159 return std::make_unique<SymbolicEmbedder>(F, Vocab);
161 return std::make_unique<FlowAwareEmbedder>(F, Vocab);
162 }
163 return nullptr;
164}
165
167 Embedding FuncVector(Dimension, 0.0);
168
169 if (F.isDeclaration())
170 return FuncVector;
171
172 // Consider only the basic blocks that are reachable from entry
173 for (const BasicBlock *BB : depth_first(&F))
174 FuncVector += computeEmbeddings(*BB);
175 return FuncVector;
176}
177
179 Embedding BBVector(Dimension, 0);
180
181 // We consider only the non-debug and non-pseudo instructions
182 for (const auto &I : BB)
183 if (!I.isDebugOrPseudoInst())
184 BBVector += computeEmbeddings(I);
185 return BBVector;
186}
187
189 // Currently, we always (re)compute the embeddings for symbolic embedder.
190 // This is cheaper than caching the vectors.
191 Embedding ArgEmb(Dimension, 0);
192 for (const auto &Op : I.operands())
193 ArgEmb += Vocab[*Op];
194 auto InstVector =
195 Vocab[I.getOpcode()] + Vocab[I.getType()->getTypeID()] + ArgEmb;
196 if (const auto *IC = dyn_cast<CmpInst>(&I))
197 InstVector += Vocab[IC->getPredicate()];
198 return InstVector;
199}
200
202 // If we have already computed the embedding for this instruction, return it
203 auto It = InstVecMap.find(&I);
204 if (It != InstVecMap.end())
205 return It->second;
206
207 // TODO: Handle call instructions differently.
208 // For now, we treat them like other instructions
209 Embedding ArgEmb(Dimension, 0);
210 for (const auto &Op : I.operands()) {
211 // If the operand is defined elsewhere, we use its embedding
212 if (const auto *DefInst = dyn_cast<Instruction>(Op)) {
213 auto DefIt = InstVecMap.find(DefInst);
214 // Fixme (#159171): Ideally we should never miss an instruction
215 // embedding here.
216 // But when we have cyclic dependencies (e.g., phi
217 // nodes), we might miss the embedding. In such cases, we fall back to
218 // using the vocabulary embedding. This can be fixed by iterating to a
219 // fixed-point, or by using a simple solver for the set of simultaneous
220 // equations.
221 // Another case when we might miss an instruction embedding is when
222 // the operand instruction is in a different basic block that has not
223 // been processed yet. This can be fixed by processing the basic blocks
224 // in a topological order.
225 if (DefIt != InstVecMap.end())
226 ArgEmb += DefIt->second;
227 else
228 ArgEmb += Vocab[*Op];
229 }
230 // If the operand is not defined by an instruction, we use the
231 // vocabulary
232 else {
233 LLVM_DEBUG(errs() << "Using embedding from vocabulary for operand: "
234 << *Op << "=" << Vocab[*Op][0] << "\n");
235 ArgEmb += Vocab[*Op];
236 }
237 }
238 // Create the instruction vector by combining opcode, type, and arguments
239 // embeddings
240 auto InstVector =
241 Vocab[I.getOpcode()] + Vocab[I.getType()->getTypeID()] + ArgEmb;
242 if (const auto *IC = dyn_cast<CmpInst>(&I))
243 InstVector += Vocab[IC->getPredicate()];
244 InstVecMap[&I] = InstVector;
245 return InstVector;
246}
247
248// ==----------------------------------------------------------------------===//
249// VocabStorage
250//===----------------------------------------------------------------------===//
251
252VocabStorage::VocabStorage(std::vector<std::vector<Embedding>> &&SectionData)
253 : Sections(std::move(SectionData)), TotalSize([&] {
254 assert(!Sections.empty() && "Vocabulary has no sections");
255 // Compute total size across all sections
256 size_t Size = 0;
257 for (const auto &Section : Sections) {
258 assert(!Section.empty() && "Vocabulary section is empty");
259 Size += Section.size();
260 }
261 return Size;
262 }()),
263 Dimension([&] {
264 // Get dimension from the first embedding in the first section - all
265 // embeddings must have the same dimension
266 assert(!Sections.empty() && "Vocabulary has no sections");
267 assert(!Sections[0].empty() && "First section of vocabulary is empty");
268 unsigned ExpectedDim = static_cast<unsigned>(Sections[0][0].size());
269
270 // Verify that all embeddings across all sections have the same
271 // dimension
272 [[maybe_unused]] auto allSameDim =
273 [ExpectedDim](const std::vector<Embedding> &Section) {
274 return std::all_of(Section.begin(), Section.end(),
275 [ExpectedDim](const Embedding &Emb) {
276 return Emb.size() == ExpectedDim;
277 });
278 };
279 assert(std::all_of(Sections.begin(), Sections.end(), allSameDim) &&
280 "All embeddings must have the same dimension");
281
282 return ExpectedDim;
283 }()) {}
284
286 assert(SectionId < Storage->Sections.size() && "Invalid section ID");
287 assert(LocalIndex < Storage->Sections[SectionId].size() &&
288 "Local index out of range");
289 return Storage->Sections[SectionId][LocalIndex];
290}
291
293 ++LocalIndex;
294 // Check if we need to move to the next section
295 if (SectionId < Storage->getNumSections() &&
296 LocalIndex >= Storage->Sections[SectionId].size()) {
297 assert(LocalIndex == Storage->Sections[SectionId].size() &&
298 "Local index should be at the end of the current section");
299 LocalIndex = 0;
300 ++SectionId;
301 }
302 return *this;
303}
304
306 const const_iterator &Other) const {
307 return Storage == Other.Storage && SectionId == Other.SectionId &&
308 LocalIndex == Other.LocalIndex;
309}
310
312 const const_iterator &Other) const {
313 return !(*this == Other);
314}
315
317 const json::Value &ParsedVocabValue,
318 VocabMap &TargetVocab, unsigned &Dim) {
319 json::Path::Root Path("");
320 const json::Object *RootObj = ParsedVocabValue.getAsObject();
321 if (!RootObj)
323 "JSON root is not an object");
324
325 const json::Value *SectionValue = RootObj->get(Key);
326 if (!SectionValue)
328 "Missing '" + std::string(Key) +
329 "' section in vocabulary file");
330 if (!json::fromJSON(*SectionValue, TargetVocab, Path))
332 "Unable to parse '" + std::string(Key) +
333 "' section from vocabulary");
334
335 Dim = TargetVocab.begin()->second.size();
336 if (Dim == 0)
338 "Dimension of '" + std::string(Key) +
339 "' section of the vocabulary is zero");
340
341 if (!std::all_of(TargetVocab.begin(), TargetVocab.end(),
342 [Dim](const std::pair<StringRef, Embedding> &Entry) {
343 return Entry.second.size() == Dim;
344 }))
345 return createStringError(
347 "All vectors in the '" + std::string(Key) +
348 "' section of the vocabulary are not of the same dimension");
349
350 return Error::success();
351}
352
353// ==----------------------------------------------------------------------===//
354// Vocabulary
355//===----------------------------------------------------------------------===//
356
358 assert(Opcode >= 1 && Opcode <= MaxOpcodes && "Invalid opcode");
359#define HANDLE_INST(NUM, OPCODE, CLASS) \
360 if (Opcode == NUM) { \
361 return #OPCODE; \
362 }
363#include "llvm/IR/Instruction.def"
364#undef HANDLE_INST
365 return "UnknownOpcode";
366}
367
368// Helper function to classify an operand into OperandKind
378
379unsigned Vocabulary::getPredicateLocalIndex(CmpInst::Predicate P) {
382 else
385}
386
387CmpInst::Predicate Vocabulary::getPredicateFromLocalIndex(unsigned LocalIndex) {
388 unsigned fcmpRange =
390 if (LocalIndex < fcmpRange)
392 LocalIndex);
393 else
395 LocalIndex - fcmpRange);
396}
397
399 static SmallString<16> PredNameBuffer;
401 PredNameBuffer = "FCMP_";
402 else
403 PredNameBuffer = "ICMP_";
404 PredNameBuffer += CmpInst::getPredicateName(Pred);
405 return PredNameBuffer;
406}
407
409 assert(Pos < NumCanonicalEntries && "Position out of bounds in vocabulary");
410 // Opcode
411 if (Pos < MaxOpcodes)
412 return getVocabKeyForOpcode(Pos + 1);
413 // Type
414 if (Pos < OperandBaseOffset)
415 return getVocabKeyForCanonicalTypeID(
416 static_cast<CanonicalTypeID>(Pos - MaxOpcodes));
417 // Operand
418 if (Pos < PredicateBaseOffset)
420 static_cast<OperandKind>(Pos - OperandBaseOffset));
421 // Predicates
422 return getVocabKeyForPredicate(getPredicate(Pos - PredicateBaseOffset));
423}
424
425// For now, assume vocabulary is stable unless explicitly invalidated.
427 ModuleAnalysisManager::Invalidator &Inv) const {
428 auto PAC = PA.getChecker<IR2VecVocabAnalysis>();
429 return !(PAC.preservedWhenStateless());
430}
431
433 float DummyVal = 0.1f;
434
435 // Create sections for opcodes, types, operands, and predicates
436 // Order must match Vocabulary::Section enum
437 std::vector<std::vector<Embedding>> Sections;
438 Sections.reserve(4);
439
440 // Opcodes section
441 std::vector<Embedding> OpcodeSec;
442 OpcodeSec.reserve(MaxOpcodes);
443 for (unsigned I = 0; I < MaxOpcodes; ++I) {
444 OpcodeSec.emplace_back(Dim, DummyVal);
445 DummyVal += 0.1f;
446 }
447 Sections.push_back(std::move(OpcodeSec));
448
449 // Types section
450 std::vector<Embedding> TypeSec;
451 TypeSec.reserve(MaxCanonicalTypeIDs);
452 for (unsigned I = 0; I < MaxCanonicalTypeIDs; ++I) {
453 TypeSec.emplace_back(Dim, DummyVal);
454 DummyVal += 0.1f;
455 }
456 Sections.push_back(std::move(TypeSec));
457
458 // Operands section
459 std::vector<Embedding> OperandSec;
460 OperandSec.reserve(MaxOperandKinds);
461 for (unsigned I = 0; I < MaxOperandKinds; ++I) {
462 OperandSec.emplace_back(Dim, DummyVal);
463 DummyVal += 0.1f;
464 }
465 Sections.push_back(std::move(OperandSec));
466
467 // Predicates section
468 std::vector<Embedding> PredicateSec;
469 PredicateSec.reserve(MaxPredicateKinds);
470 for (unsigned I = 0; I < MaxPredicateKinds; ++I) {
471 PredicateSec.emplace_back(Dim, DummyVal);
472 DummyVal += 0.1f;
473 }
474 Sections.push_back(std::move(PredicateSec));
475
476 return VocabStorage(std::move(Sections));
477}
478
479namespace {
480using VocabMap = std::map<std::string, Embedding>;
481
482/// Read vocabulary JSON file and populate the section maps.
483Error readVocabularyFromFile(StringRef VocabFilePath, VocabMap &OpcVocab,
484 VocabMap &TypeVocab, VocabMap &ArgVocab) {
485 auto BufOrError =
486 MemoryBuffer::getFileOrSTDIN(VocabFilePath, /*IsText=*/true);
487 if (!BufOrError)
488 return createFileError(VocabFilePath, BufOrError.getError());
489
490 auto Content = BufOrError.get()->getBuffer();
491
492 Expected<json::Value> ParsedVocabValue = json::parse(Content);
493 if (!ParsedVocabValue)
494 return ParsedVocabValue.takeError();
495
496 unsigned OpcodeDim = 0, TypeDim = 0, ArgDim = 0;
497 if (auto Err = VocabStorage::parseVocabSection("Opcodes", *ParsedVocabValue,
498 OpcVocab, OpcodeDim))
499 return Err;
500
501 if (auto Err = VocabStorage::parseVocabSection("Types", *ParsedVocabValue,
502 TypeVocab, TypeDim))
503 return Err;
504
505 if (auto Err = VocabStorage::parseVocabSection("Arguments", *ParsedVocabValue,
506 ArgVocab, ArgDim))
507 return Err;
508
509 if (!(OpcodeDim == TypeDim && TypeDim == ArgDim))
511 "Vocabulary sections have different dimensions");
512
513 return Error::success();
514}
515} // anonymous namespace
516
517/// Generate VocabStorage from vocabulary maps.
518VocabStorage Vocabulary::buildVocabStorage(const VocabMap &OpcVocab,
519 const VocabMap &TypeVocab,
520 const VocabMap &ArgVocab) {
521
522 // Helper for handling missing entities in the vocabulary.
523 // Currently, we use a zero vector. In the future, we will throw an error to
524 // ensure that *all* known entities are present in the vocabulary.
525 auto handleMissingEntity = [](const std::string &Val) {
526 LLVM_DEBUG(errs() << Val
527 << " is not in vocabulary, using zero vector; This "
528 "would result in an error in future.\n");
529 ++VocabMissCounter;
530 };
531
532 unsigned Dim = OpcVocab.begin()->second.size();
533 assert(Dim > 0 && "Vocabulary dimension must be greater than zero");
534
535 // Handle Opcodes
536 std::vector<Embedding> NumericOpcodeEmbeddings(Vocabulary::MaxOpcodes,
537 Embedding(Dim));
538 for (unsigned Opcode : seq(0u, Vocabulary::MaxOpcodes)) {
539 StringRef VocabKey = Vocabulary::getVocabKeyForOpcode(Opcode + 1);
540 auto It = OpcVocab.find(VocabKey.str());
541 if (It != OpcVocab.end())
542 NumericOpcodeEmbeddings[Opcode] = It->second;
543 else
544 handleMissingEntity(VocabKey.str());
545 }
546
547 // Handle Types - only canonical types are present in vocabulary
548 std::vector<Embedding> NumericTypeEmbeddings(Vocabulary::MaxCanonicalTypeIDs,
549 Embedding(Dim));
550 for (unsigned CTypeID : seq(0u, Vocabulary::MaxCanonicalTypeIDs)) {
551 StringRef VocabKey = Vocabulary::getVocabKeyForCanonicalTypeID(
552 static_cast<Vocabulary::CanonicalTypeID>(CTypeID));
553 if (auto It = TypeVocab.find(VocabKey.str()); It != TypeVocab.end()) {
554 NumericTypeEmbeddings[CTypeID] = It->second;
555 continue;
556 }
557 handleMissingEntity(VocabKey.str());
558 }
559
560 // Handle Arguments/Operands
561 std::vector<Embedding> NumericArgEmbeddings(Vocabulary::MaxOperandKinds,
562 Embedding(Dim));
563 for (unsigned OpKind : seq(0u, Vocabulary::MaxOperandKinds)) {
565 StringRef VocabKey = Vocabulary::getVocabKeyForOperandKind(Kind);
566 auto It = ArgVocab.find(VocabKey.str());
567 if (It != ArgVocab.end()) {
568 NumericArgEmbeddings[OpKind] = It->second;
569 continue;
570 }
571 handleMissingEntity(VocabKey.str());
572 }
573
574 // Handle Predicates: part of Operands section. We look up predicate keys
575 // in ArgVocab.
576 std::vector<Embedding> NumericPredEmbeddings(Vocabulary::MaxPredicateKinds,
577 Embedding(Dim, 0));
578 for (unsigned PK : seq(0u, Vocabulary::MaxPredicateKinds)) {
579 StringRef VocabKey =
580 Vocabulary::getVocabKeyForPredicate(Vocabulary::getPredicate(PK));
581 auto It = ArgVocab.find(VocabKey.str());
582 if (It != ArgVocab.end()) {
583 NumericPredEmbeddings[PK] = It->second;
584 continue;
585 }
586 handleMissingEntity(VocabKey.str());
587 }
588
589 // Create section-based storage instead of flat vocabulary
590 // Order must match Vocabulary::Section enum
591 std::vector<std::vector<Embedding>> Sections(4);
592 Sections[static_cast<unsigned>(Section::Opcodes)] =
593 std::move(NumericOpcodeEmbeddings); // Section::Opcodes
594 Sections[static_cast<unsigned>(Section::CanonicalTypes)] =
595 std::move(NumericTypeEmbeddings); // Section::CanonicalTypes
596 Sections[static_cast<unsigned>(Section::Operands)] =
597 std::move(NumericArgEmbeddings); // Section::Operands
598 Sections[static_cast<unsigned>(Section::Predicates)] =
599 std::move(NumericPredEmbeddings); // Section::Predicates
600
601 // Create VocabStorage from organized sections
602 return VocabStorage(std::move(Sections));
603}
604
605// ==----------------------------------------------------------------------===//
606// Vocabulary
607//===----------------------------------------------------------------------===//
608
610 float OpcWeight, float TypeWeight,
611 float ArgWeight) {
612 VocabMap OpcVocab, TypeVocab, ArgVocab;
613 if (auto Err =
614 readVocabularyFromFile(VocabFilePath, OpcVocab, TypeVocab, ArgVocab))
615 return std::move(Err);
616
617 // Scale the vocabulary sections based on the provided weights
618 auto scaleVocabSection = [](VocabMap &Vocab, float Weight) {
619 for (auto &Entry : Vocab)
620 Entry.second *= Weight;
621 };
622 scaleVocabSection(OpcVocab, OpcWeight);
623 scaleVocabSection(TypeVocab, TypeWeight);
624 scaleVocabSection(ArgVocab, ArgWeight);
625
626 // Generate the numeric lookup vocabulary
627 return Vocabulary(buildVocabStorage(OpcVocab, TypeVocab, ArgVocab));
628}
629
630// ==----------------------------------------------------------------------===//
631// IR2VecVocabAnalysis
632//===----------------------------------------------------------------------===//
633
634void IR2VecVocabAnalysis::emitError(Error Err) {
635 handleAllErrors(std::move(Err), [&](const ErrorInfoBase &EI) {
636 reportFatalUsageError(Twine("error reading vocabulary: ") + EI.message());
637 });
638}
639
642 // If vocabulary is already populated by the constructor, use it.
643 if (Vocab.has_value())
644 return Vocabulary(std::move(Vocab.value()));
645
646 // Otherwise, try to read from the vocabulary file specified via CLI.
647 if (VocabFile.empty())
648 // FIXME: Use default vocabulary
650 "IR2Vec vocabulary file path not specified; You may need to "
651 "set it using --ir2vec-vocab-path");
652
653 // Use the static factory method to load the vocabulary.
654 auto VocabOrErr =
656 if (!VocabOrErr)
657 emitError(VocabOrErr.takeError());
658
659 return std::move(*VocabOrErr);
660}
661
662// ==----------------------------------------------------------------------===//
663// Printer Passes
664//===----------------------------------------------------------------------===//
665
668 auto &Vocabulary = MAM.getResult<IR2VecVocabAnalysis>(M);
669 assert(Vocabulary.isValid() && "IR2Vec Vocabulary is invalid");
670
671 for (Function &F : M) {
673 if (!Emb) {
674 OS << "Error creating IR2Vec embeddings \n";
675 continue;
676 }
677
678 OS << "IR2Vec embeddings for function " << F.getName() << ":\n";
679 OS << "Function vector: ";
680 Emb->getFunctionVector().print(OS);
681
682 OS << "Basic block vectors:\n";
683 for (const BasicBlock &BB : F) {
684 OS << "Basic block: " << BB.getName() << ":\n";
685 Emb->getBBVector(BB).print(OS);
686 }
687
688 OS << "Instruction vectors:\n";
689 for (const BasicBlock &BB : F) {
690 for (const Instruction &I : BB) {
691 OS << "Instruction: ";
692 I.print(OS);
693 Emb->getInstVector(I).print(OS);
694 }
695 }
696 }
697 return PreservedAnalyses::all();
698}
699
702 auto &IR2VecVocabulary = MAM.getResult<IR2VecVocabAnalysis>(M);
703 assert(IR2VecVocabulary.isValid() && "IR2Vec Vocabulary is invalid");
704
705 // Print each entry
706 unsigned Pos = 0;
707 for (const auto &Entry : IR2VecVocabulary) {
708 OS << "Key: " << IR2VecVocabulary.getStringKey(Pos++) << ": ";
709 Entry.print(OS);
710 }
711 return PreservedAnalyses::all();
712}
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
#define clEnumValN(ENUMVAL, FLAGNAME, DESC)
This file builds on the ADT/GraphTraits.h file to build generic depth first graph iterator.
This file defines the IR2Vec vocabulary analysis(IR2VecVocabAnalysis), the core ir2vec::Embedder inte...
This file provides various utilities for inspecting and working with the control flow graph in LLVM I...
Module.h This file contains the declarations for the Module class.
This header defines various interfaces for pass management in LLVM.
#define F(x, y, z)
Definition MD5.cpp:54
#define I(x, y, z)
Definition MD5.cpp:57
#define P(N)
ModuleAnalysisManager MAM
Provides some synthesis utilities to produce sequences of values.
This file defines the 'Statistic' class, which is designed to be an easy way to expose various metric...
#define STATISTIC(VARNAME, DESC)
Definition Statistic.h:171
#define LLVM_DEBUG(...)
Definition Debug.h:119
LLVM Basic Block Representation.
Definition BasicBlock.h:62
Predicate
This enumeration lists the possible predicates for CmpInst subclasses.
Definition InstrTypes.h:740
static LLVM_ABI StringRef getPredicateName(Predicate P)
iterator find(const_arg_type_t< KeyT > Val)
Definition DenseMap.h:223
iterator end()
Definition DenseMap.h:141
Base class for error info classes.
Definition Error.h:44
virtual std::string message() const
Return the error message as a string.
Definition Error.h:52
Lightweight error class with error context and mandatory checking.
Definition Error.h:159
static ErrorSuccess success()
Create a success value.
Definition Error.h:336
Tagged union holding either a T or a Error.
Definition Error.h:485
Error takeError()
Take ownership of the stored error.
Definition Error.h:612
LLVM_ABI PreservedAnalyses run(Module &M, ModuleAnalysisManager &MAM)
Definition IR2Vec.cpp:666
This analysis provides the vocabulary for IR2Vec.
Definition IR2Vec.h:637
ir2vec::Vocabulary Result
Definition IR2Vec.h:647
LLVM_ABI Result run(Module &M, ModuleAnalysisManager &MAM)
Definition IR2Vec.cpp:641
static LLVM_ABI AnalysisKey Key
Definition IR2Vec.h:643
LLVM_ABI PreservedAnalyses run(Module &M, ModuleAnalysisManager &MAM)
Definition IR2Vec.cpp:700
static ErrorOr< std::unique_ptr< MemoryBuffer > > getFileOrSTDIN(const Twine &Filename, bool IsText=false, bool RequiresNullTerminator=true, std::optional< Align > Alignment=std::nullopt)
Open the specified file as a MemoryBuffer, or open stdin if the Filename is "-".
A Module instance is used to store all the information related to an LLVM module.
Definition Module.h:68
A set of analyses that are preserved following a run of a transformation pass.
Definition Analysis.h:112
static PreservedAnalyses all()
Construct a special preserved set that preserves all passes.
Definition Analysis.h:118
PreservedAnalysisChecker getChecker() const
Build a checker for this PreservedAnalyses and the specified analysis type.
Definition Analysis.h:275
SmallString - A SmallString is just a SmallVector with methods and accessors that make it work better...
Definition SmallString.h:26
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
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
Definition Twine.h:82
LLVM Value Representation.
Definition Value.h:75
static LLVM_ABI std::unique_ptr< Embedder > create(IR2VecKind Mode, const Function &F, const Vocabulary &Vocab)
Factory method to create an Embedder object.
Definition IR2Vec.cpp:155
const Vocabulary & Vocab
Definition IR2Vec.h:550
const unsigned Dimension
Dimension of the vector representation; captured from the input vocabulary.
Definition IR2Vec.h:553
LLVM_ABI Embedding computeEmbeddings() const
Function to compute embeddings.
Definition IR2Vec.cpp:166
const Function & F
Definition IR2Vec.h:549
Iterator support for section-based access.
Definition IR2Vec.h:202
const_iterator(const VocabStorage *Storage, unsigned SectionId, size_t LocalIndex)
Definition IR2Vec.h:208
LLVM_ABI bool operator!=(const const_iterator &Other) const
Definition IR2Vec.cpp:311
LLVM_ABI const_iterator & operator++()
Definition IR2Vec.cpp:292
LLVM_ABI const Embedding & operator*() const
Definition IR2Vec.cpp:285
LLVM_ABI bool operator==(const const_iterator &Other) const
Definition IR2Vec.cpp:305
Generic storage class for section-based vocabularies.
Definition IR2Vec.h:157
static LLVM_ABI Error parseVocabSection(StringRef Key, const json::Value &ParsedVocabValue, VocabMap &TargetVocab, unsigned &Dim)
Parse a vocabulary section from JSON and populate the target vocabulary map.
Definition IR2Vec.cpp:316
unsigned getNumSections() const
Get number of sections.
Definition IR2Vec.h:185
size_t size() const
Get total number of entries across all sections.
Definition IR2Vec.h:182
VocabStorage()=default
Default constructor creates empty storage (invalid state)
const_iterator begin() const
Definition IR2Vec.h:218
std::map< std::string, Embedding > VocabMap
Definition IR2Vec.h:223
Class for storing and accessing the IR2Vec vocabulary.
Definition IR2Vec.h:248
LLVM_ABI bool invalidate(Module &M, const PreservedAnalyses &PA, ModuleAnalysisManager::Invalidator &Inv) const
Definition IR2Vec.cpp:426
static LLVM_ABI Expected< Vocabulary > fromFile(StringRef VocabFilePath, float OpcWeight=1.0, float TypeWeight=0.5, float ArgWeight=0.2)
Create a Vocabulary by loading embeddings from a JSON file.
Definition IR2Vec.cpp:609
static LLVM_ABI OperandKind getOperandKind(const Value *Op)
Function to classify an operand into OperandKind.
Definition IR2Vec.cpp:369
static StringRef getVocabKeyForOperandKind(OperandKind Kind)
Function to get vocabulary key for a given OperandKind.
Definition IR2Vec.h:367
friend class llvm::IR2VecVocabAnalysis
Definition IR2Vec.h:249
static LLVM_ABI StringRef getStringKey(unsigned Pos)
Returns the string key for a given index position in the vocabulary.
Definition IR2Vec.cpp:408
static constexpr unsigned MaxCanonicalTypeIDs
Definition IR2Vec.h:319
static constexpr unsigned MaxOperandKinds
Definition IR2Vec.h:321
OperandKind
Operand kinds supported by IR2Vec Vocabulary.
Definition IR2Vec.h:305
static LLVM_ABI StringRef getVocabKeyForPredicate(CmpInst::Predicate P)
Function to get vocabulary key for a given predicate.
Definition IR2Vec.cpp:398
static LLVM_ABI StringRef getVocabKeyForOpcode(unsigned Opcode)
Function to get vocabulary key for a given Opcode.
Definition IR2Vec.cpp:357
bool isValid() const
Definition IR2Vec.h:347
static LLVM_ABI VocabStorage createDummyVocabForTest(unsigned Dim=1)
Create a dummy vocabulary for testing purposes.
Definition IR2Vec.cpp:432
static constexpr unsigned MaxPredicateKinds
Definition IR2Vec.h:325
CanonicalTypeID
Canonical type IDs supported by IR2Vec Vocabulary.
Definition IR2Vec.h:287
An Object is a JSON object, which maps strings to heterogenous JSON values.
Definition JSON.h:98
LLVM_ABI Value * get(StringRef K)
Definition JSON.cpp:30
The root is the trivial Path to the root value.
Definition JSON.h:700
A "cursor" marking a position within a Value.
Definition JSON.h:653
A Value is an JSON value of unknown type.
Definition JSON.h:291
const json::Object * getAsObject() const
Definition JSON.h:465
This class implements an extremely fast bulk output stream that can only output to a stream.
Definition raw_ostream.h:53
ValuesClass values(OptsTy... Options)
Helper to build a ValuesClass by forwarding a variable number of arguments as an initializer list to ...
initializer< Ty > init(const Ty &Val)
LLVM_ABI cl::opt< float > ArgWeight
LLVM_ABI cl::opt< std::string > VocabFile
LLVM_ABI cl::opt< float > OpcWeight
LLVM_ABI cl::opt< float > TypeWeight
LLVM_ABI cl::opt< IR2VecKind > IR2VecEmbeddingKind
LLVM_ABI llvm::cl::OptionCategory IR2VecCategory
LLVM_ABI llvm::Expected< Value > parse(llvm::StringRef JSON)
Parses the provided JSON source, or returns a ParseError.
Definition JSON.cpp:681
bool fromJSON(const Value &E, std::string &Out, Path P)
Definition JSON.h:729
ir2vec::Embedding Embedding
Definition MIR2Vec.h:80
This is an optimization pass for GlobalISel generic memory operations.
Error createFileError(const Twine &F, Error E)
Concatenate a source file path and/or name with an Error.
Definition Error.h:1415
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
Definition Casting.h:643
void handleAllErrors(Error E, HandlerTs &&... Handlers)
Behaves the same as handleErrors, except that by contract all errors must be handled by the given han...
Definition Error.h:1013
Error createStringError(std::error_code EC, char const *Fmt, const Ts &... Vals)
Create formatted StringError object.
Definition Error.h:1321
@ illegal_byte_sequence
Definition Errc.h:52
@ invalid_argument
Definition Errc.h:56
IR2VecKind
IR2Vec computes two kinds of embeddings: Symbolic and Flow-aware.
Definition IR2Vec.h:71
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
format_object< Ts... > format(const char *Fmt, const Ts &... Vals)
These are helper functions used to produce formatted output.
Definition Format.h:102
LLVM_ATTRIBUTE_VISIBILITY_DEFAULT AnalysisKey InnerAnalysisManagerProxy< AnalysisManagerT, IRUnitT, ExtraArgTs... >::Key
LLVM_ABI raw_fd_ostream & errs()
This returns a reference to a raw_ostream for standard error.
@ Other
Any other memory.
Definition ModRef.h:68
DWARFExpression::Operation Op
OutputIt move(R &&Range, OutputIt Out)
Provide wrappers to std::move which take ranges instead of having to pass begin/end explicitly.
Definition STLExtras.h:1917
constexpr auto seq(T Begin, T End)
Iterate over an integral type from Begin up to - but not including - End.
Definition Sequence.h:341
iterator_range< df_iterator< T > > depth_first(const T &G)
AnalysisManager< Module > ModuleAnalysisManager
Convenience typedef for the Module analysis manager.
Definition MIRParser.h:39
LLVM_ABI void reportFatalUsageError(Error Err)
Report a fatal error that does not indicate a bug in LLVM.
Definition Error.cpp:177
Implement std::hash so that hash_code can be used in STL containers.
Definition BitVector.h:878
A special type used by analysis passes to provide an address that identifies that particular analysis...
Definition Analysis.h:29
Embedding is a datatype that wraps std::vector<double>.
Definition IR2Vec.h:88
LLVM_ABI bool approximatelyEquals(const Embedding &RHS, double Tolerance=1e-4) const
Returns true if the embedding is approximately equal to the RHS embedding within the specified tolera...
Definition IR2Vec.cpp:131
LLVM_ABI Embedding & operator+=(const Embedding &RHS)
Arithmetic operators.
Definition IR2Vec.cpp:86
LLVM_ABI Embedding operator-(const Embedding &RHS) const
Definition IR2Vec.cpp:106
LLVM_ABI Embedding & operator-=(const Embedding &RHS)
Definition IR2Vec.cpp:99
LLVM_ABI Embedding operator*(double Factor) const
Definition IR2Vec.cpp:118
size_t size() const
Definition IR2Vec.h:101
LLVM_ABI Embedding & operator*=(double Factor)
Definition IR2Vec.cpp:112
LLVM_ABI Embedding operator+(const Embedding &RHS) const
Definition IR2Vec.cpp:93
LLVM_ABI Embedding & scaleAndAdd(const Embedding &Src, float Factor)
Adds Src Embedding scaled by Factor with the called Embedding.
Definition IR2Vec.cpp:124
LLVM_ABI void print(raw_ostream &OS) const
Definition IR2Vec.cpp:144