34#define DEBUG_TYPE "ir2vec"
37 "Number of lookups to entities not present in the vocabulary");
54 std::vector<double> TempOut;
66 assert(this->
size() == RHS.
size() &&
"Vectors must have the same dimension");
67 std::transform(this->
begin(), this->
end(), RHS.
begin(), this->begin(),
79 assert(this->
size() == RHS.
size() &&
"Vectors must have the same dimension");
80 std::transform(this->
begin(), this->
end(), RHS.
begin(), this->begin(),
81 std::minus<double>());
93 [Factor](
double Elem) {
return Elem * Factor; });
104 assert(this->
size() == Src.
size() &&
"Vectors must have the same dimension");
105 for (
size_t Itr = 0; Itr < this->
size(); ++Itr)
106 (*
this)[Itr] += Src[Itr] * Factor;
111 double Tolerance)
const {
112 assert(this->
size() == RHS.
size() &&
"Vectors must have the same dimension");
113 for (
size_t Itr = 0; Itr < this->
size(); ++Itr)
114 if (std::abs((*
this)[Itr] - RHS[Itr]) > Tolerance) {
115 LLVM_DEBUG(
errs() <<
"Embedding mismatch at index " << Itr <<
": "
116 << (*
this)[Itr] <<
" vs " << RHS[Itr]
117 <<
"; Tolerance: " << Tolerance <<
"\n");
125 for (
const auto &Elem : Data)
126 OS <<
" " <<
format(
"%.2f", Elem) <<
" ";
138 return std::make_unique<SymbolicEmbedder>(
F,
Vocab);
140 return std::make_unique<FlowAwareEmbedder>(
F,
Vocab);
148 if (
F.isDeclaration())
161 for (
const auto &
I : BB)
171 for (
const auto &
Op :
I.operands())
174 Vocab[
I.getOpcode()] +
Vocab[
I.getType()->getTypeID()] + ArgEmb;
176 InstVector +=
Vocab[IC->getPredicate()];
182 auto It = InstVecMap.
find(&
I);
183 if (It != InstVecMap.
end())
189 for (
const auto &
Op :
I.operands()) {
192 auto DefIt = InstVecMap.
find(DefInst);
204 if (DefIt != InstVecMap.
end())
205 ArgEmb += DefIt->second;
212 LLVM_DEBUG(
errs() <<
"Using embedding from vocabulary for operand: "
220 Vocab[
I.getOpcode()] +
Vocab[
I.getType()->getTypeID()] + ArgEmb;
222 InstVector +=
Vocab[IC->getPredicate()];
223 InstVecMap[&
I] = InstVector;
232 : Sections(
std::
move(SectionData)), TotalSize([&] {
233 assert(!Sections.empty() &&
"Vocabulary has no sections");
236 for (
const auto &Section : Sections) {
237 assert(!Section.empty() &&
"Vocabulary section is empty");
238 Size += Section.size();
245 assert(!Sections.empty() &&
"Vocabulary has no sections");
246 assert(!Sections[0].empty() &&
"First section of vocabulary is empty");
247 unsigned ExpectedDim =
static_cast<unsigned>(Sections[0][0].size());
251 [[maybe_unused]]
auto allSameDim =
252 [ExpectedDim](
const std::vector<Embedding> &Section) {
253 return std::all_of(Section.begin(), Section.end(),
255 return Emb.size() == ExpectedDim;
258 assert(std::all_of(Sections.begin(), Sections.end(), allSameDim) &&
259 "All embeddings must have the same dimension");
265 assert(SectionId < Storage->Sections.size() &&
"Invalid section ID");
266 assert(LocalIndex < Storage->Sections[SectionId].
size() &&
267 "Local index out of range");
268 return Storage->Sections[SectionId][LocalIndex];
275 LocalIndex >= Storage->Sections[SectionId].size()) {
276 assert(LocalIndex == Storage->Sections[SectionId].size() &&
277 "Local index should be at the end of the current section");
286 return Storage ==
Other.Storage && SectionId ==
Other.SectionId &&
287 LocalIndex ==
Other.LocalIndex;
292 return !(*
this ==
Other);
297 VocabMap &TargetVocab,
unsigned &Dim) {
302 "JSON root is not an object");
307 "Missing '" + std::string(
Key) +
308 "' section in vocabulary file");
311 "Unable to parse '" + std::string(
Key) +
312 "' section from vocabulary");
314 Dim = TargetVocab.begin()->second.size();
317 "Dimension of '" + std::string(
Key) +
318 "' section of the vocabulary is zero");
320 if (!std::all_of(TargetVocab.begin(), TargetVocab.end(),
321 [Dim](
const std::pair<StringRef, Embedding> &Entry) {
322 return Entry.second.size() == Dim;
326 "All vectors in the '" + std::string(
Key) +
327 "' section of the vocabulary are not of the same dimension");
337 assert(Opcode >= 1 && Opcode <= MaxOpcodes &&
"Invalid opcode");
338#define HANDLE_INST(NUM, OPCODE, CLASS) \
339 if (Opcode == NUM) { \
342#include "llvm/IR/Instruction.def"
344 return "UnknownOpcode";
369 if (LocalIndex < fcmpRange)
374 LocalIndex - fcmpRange);
380 PredNameBuffer =
"FCMP_";
382 PredNameBuffer =
"ICMP_";
384 return PredNameBuffer;
388 assert(Pos < NumCanonicalEntries &&
"Position out of bounds in vocabulary");
390 if (Pos < MaxOpcodes)
393 if (Pos < OperandBaseOffset)
394 return getVocabKeyForCanonicalTypeID(
397 if (Pos < PredicateBaseOffset)
399 static_cast<OperandKind>(Pos - OperandBaseOffset));
406 ModuleAnalysisManager::Invalidator &Inv)
const {
408 return !(PAC.preservedWhenStateless());
412 float DummyVal = 0.1f;
416 std::vector<std::vector<Embedding>> Sections;
420 std::vector<Embedding> OpcodeSec;
421 OpcodeSec.reserve(MaxOpcodes);
422 for (
unsigned I = 0;
I < MaxOpcodes; ++
I) {
423 OpcodeSec.emplace_back(Dim, DummyVal);
426 Sections.push_back(std::move(OpcodeSec));
429 std::vector<Embedding> TypeSec;
432 TypeSec.emplace_back(Dim, DummyVal);
435 Sections.push_back(std::move(TypeSec));
438 std::vector<Embedding> OperandSec;
441 OperandSec.emplace_back(Dim, DummyVal);
444 Sections.push_back(std::move(OperandSec));
447 std::vector<Embedding> PredicateSec;
450 PredicateSec.emplace_back(Dim, DummyVal);
453 Sections.push_back(std::move(PredicateSec));
459using VocabMap = std::map<std::string, Embedding>;
469 auto Content = BufOrError.get()->getBuffer();
472 if (!ParsedVocabValue)
475 unsigned OpcodeDim = 0, TypeDim = 0, ArgDim = 0;
477 OpcVocab, OpcodeDim))
488 if (!(OpcodeDim == TypeDim && TypeDim == ArgDim))
490 "Vocabulary sections have different dimensions");
504 auto handleMissingEntity = [](
const std::string &Val) {
506 <<
" is not in vocabulary, using zero vector; This "
507 "would result in an error in future.\n");
511 unsigned Dim = OpcVocab.
begin()->second.size();
512 assert(Dim > 0 &&
"Vocabulary dimension must be greater than zero");
515 std::vector<Embedding> NumericOpcodeEmbeddings(Vocabulary::MaxOpcodes,
517 for (
unsigned Opcode :
seq(0u, Vocabulary::MaxOpcodes)) {
519 auto It = OpcVocab.find(VocabKey.
str());
520 if (It != OpcVocab.end())
521 NumericOpcodeEmbeddings[Opcode] = It->second;
523 handleMissingEntity(VocabKey.
str());
530 StringRef VocabKey = Vocabulary::getVocabKeyForCanonicalTypeID(
532 if (
auto It = TypeVocab.find(VocabKey.
str()); It != TypeVocab.end()) {
533 NumericTypeEmbeddings[CTypeID] = It->second;
536 handleMissingEntity(VocabKey.
str());
545 auto It = ArgVocab.find(VocabKey.
str());
546 if (It != ArgVocab.end()) {
547 NumericArgEmbeddings[OpKind] = It->second;
550 handleMissingEntity(VocabKey.
str());
560 auto It = ArgVocab.find(VocabKey.
str());
561 if (It != ArgVocab.end()) {
562 NumericPredEmbeddings[PK] = It->second;
565 handleMissingEntity(VocabKey.
str());
570 std::vector<std::vector<Embedding>> Sections(4);
571 Sections[
static_cast<unsigned>(Section::Opcodes)] =
572 std::move(NumericOpcodeEmbeddings);
573 Sections[
static_cast<unsigned>(Section::CanonicalTypes)] =
574 std::move(NumericTypeEmbeddings);
575 Sections[
static_cast<unsigned>(Section::Operands)] =
576 std::move(NumericArgEmbeddings);
577 Sections[
static_cast<unsigned>(Section::Predicates)] =
578 std::move(NumericPredEmbeddings);
589 float OpcWeight,
float TypeWeight,
591 VocabMap OpcVocab, TypeVocab, ArgVocab;
593 readVocabularyFromFile(VocabFilePath, OpcVocab, TypeVocab, ArgVocab))
594 return std::move(Err);
597 auto scaleVocabSection = [](VocabMap &Vocab,
float Weight) {
598 for (
auto &Entry : Vocab)
599 Entry.second *= Weight;
601 scaleVocabSection(OpcVocab, OpcWeight);
602 scaleVocabSection(TypeVocab, TypeWeight);
603 scaleVocabSection(ArgVocab, ArgWeight);
606 return Vocabulary(buildVocabStorage(OpcVocab, TypeVocab, ArgVocab));
613void IR2VecVocabAnalysis::emitError(
Error Err) {
622 if (Vocab.has_value())
627 if (Opts.ir2vec_vocab_path.empty())
630 "IR2Vec vocabulary file path not specified; You may need to "
631 "set it using --ir2vec-vocab-path");
636 Opts.ir2vec_type_weight, Opts.ir2vec_arg_weight);
638 emitError(VocabOrErr.takeError());
640 return std::move(*VocabOrErr);
656 OS <<
"Error creating IR2Vec embeddings \n";
660 OS <<
"IR2Vec embeddings for function " <<
F.getName() <<
":\n";
661 OS <<
"Function vector: ";
662 Emb->getFunctionVector().print(OS);
664 OS <<
"Basic block vectors:\n";
666 OS <<
"Basic block: " << BB.getName() <<
":\n";
667 Emb->getBBVector(BB).print(OS);
670 OS <<
"Instruction vectors:\n";
673 OS <<
"Instruction: ";
675 Emb->getInstVector(
I).print(OS);
685 assert(IR2VecVocabulary.isValid() &&
"IR2Vec Vocabulary is invalid");
689 for (
const auto &Entry : IR2VecVocabulary) {
690 OS <<
"Key: " << IR2VecVocabulary.getStringKey(Pos++) <<
": ";
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
static GCRegistry::Add< ShadowStackGC > C("shadow-stack", "Very portable GC for uncooperative code generators")
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.
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)
LLVM Basic Block Representation.
Predicate
This enumeration lists the possible predicates for CmpInst subclasses.
static LLVM_ABI StringRef getPredicateName(Predicate P)
iterator find(const_arg_type_t< KeyT > Val)
Base class for error info classes.
virtual std::string message() const
Return the error message as a string.
Lightweight error class with error context and mandatory checking.
static ErrorSuccess success()
Create a success value.
Tagged union holding either a T or a Error.
Error takeError()
Take ownership of the stored error.
LLVM_ABI PreservedAnalyses run(Module &M, ModuleAnalysisManager &MAM)
This analysis provides the vocabulary for IR2Vec.
ir2vec::Vocabulary Result
LLVM_ABI Result run(Module &M, ModuleAnalysisManager &MAM)
static LLVM_ABI AnalysisKey Key
LLVM_ABI PreservedAnalyses run(Module &M, ModuleAnalysisManager &MAM)
This is an important class for using LLVM in a threaded context.
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.
A set of analyses that are preserved following a run of a transformation pass.
static PreservedAnalyses all()
Construct a special preserved set that preserves all passes.
PreservedAnalysisChecker getChecker() const
Build a checker for this PreservedAnalyses and the specified analysis type.
SmallString - A SmallString is just a SmallVector with methods and accessors that make it work better...
Represent a constant reference to a string, i.e.
std::string str() const
Get the contents as an std::string.
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
LLVM Value Representation.
static LLVM_ABI std::unique_ptr< Embedder > create(IR2VecKind Mode, const Function &F, const Vocabulary &Vocab)
Factory method to create an Embedder object.
const unsigned Dimension
Dimension of the vector representation; captured from the input vocabulary.
LLVM_ABI Embedding computeEmbeddings() const
Function to compute embeddings.
Iterator support for section-based access.
const_iterator(const VocabStorage *Storage, unsigned SectionId, size_t LocalIndex)
LLVM_ABI bool operator!=(const const_iterator &Other) const
LLVM_ABI const_iterator & operator++()
LLVM_ABI const Embedding & operator*() const
LLVM_ABI bool operator==(const const_iterator &Other) const
Generic storage class for section-based vocabularies.
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.
unsigned getNumSections() const
Get number of sections.
size_t size() const
Get total number of entries across all sections.
VocabStorage()=default
Default constructor creates empty storage (invalid state)
const_iterator begin() const
std::map< std::string, Embedding > VocabMap
Class for storing and accessing the IR2Vec vocabulary.
LLVM_ABI bool invalidate(Module &M, const PreservedAnalyses &PA, ModuleAnalysisManager::Invalidator &Inv) const
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.
static LLVM_ABI OperandKind getOperandKind(const Value *Op)
Function to classify an operand into OperandKind.
static StringRef getVocabKeyForOperandKind(OperandKind Kind)
Function to get vocabulary key for a given OperandKind.
friend class llvm::IR2VecVocabAnalysis
static LLVM_ABI StringRef getStringKey(unsigned Pos)
Returns the string key for a given index position in the vocabulary.
static constexpr unsigned MaxCanonicalTypeIDs
static constexpr unsigned MaxOperandKinds
OperandKind
Operand kinds supported by IR2Vec Vocabulary.
static LLVM_ABI StringRef getVocabKeyForPredicate(CmpInst::Predicate P)
Function to get vocabulary key for a given predicate.
static LLVM_ABI StringRef getVocabKeyForOpcode(unsigned Opcode)
Function to get vocabulary key for a given Opcode.
static LLVM_ABI VocabStorage createDummyVocabForTest(unsigned Dim=1)
Create a dummy vocabulary for testing purposes.
static constexpr unsigned MaxPredicateKinds
CanonicalTypeID
Canonical type IDs supported by IR2Vec Vocabulary.
An Object is a JSON object, which maps strings to heterogenous JSON values.
LLVM_ABI Value * get(StringRef K)
The root is the trivial Path to the root value.
A "cursor" marking a position within a Value.
A Value is an JSON value of unknown type.
const json::Object * getAsObject() const
This class implements an extremely fast bulk output stream that can only output to a stream.
LLVM_ABI IR2VecKind getEmbeddingKind(const LLVMContext &C)
Return -ir2vec-kind.
LLVM_ABI StringRef getVocabFile(const LLVMContext &C)
Return -ir2vec-vocab-path.
LLVM_ABI llvm::Expected< Value > parse(llvm::StringRef JSON)
Parses the provided JSON source, or returns a ParseError.
bool fromJSON(const Value &E, std::string &Out, Path P)
ir2vec::Embedding Embedding
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.
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
void handleAllErrors(Error E, HandlerTs &&... Handlers)
Behaves the same as handleErrors, except that by contract all errors must be handled by the given han...
Error createStringError(std::error_code EC, char const *Fmt, const Ts &... Vals)
Create formatted StringError object.
const AnalysisOptions & getAnalysisOptions(const LLVMContext &C)
IR2VecKind
IR2Vec computes two kinds of embeddings: Symbolic and Flow-aware.
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...
format_object< Ts... > format(const char *Fmt, const Ts &... Vals)
These are helper functions used to produce formatted output.
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.
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.
constexpr auto seq(T Begin, T End)
Iterate over an integral type from Begin up to - but not including - End.
iterator_range< df_iterator< T > > depth_first(const T &G)
AnalysisManager< Module > ModuleAnalysisManager
Convenience typedef for the Module analysis manager.
LLVM_ABI void reportFatalUsageError(Error Err)
Report a fatal error that does not indicate a bug in LLVM.
Implement std::hash so that hash_code can be used in STL containers.
A special type used by analysis passes to provide an address that identifies that particular analysis...
Embedding is a datatype that wraps std::vector<double>.
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...
LLVM_ABI Embedding & operator+=(const Embedding &RHS)
Arithmetic operators.
LLVM_ABI Embedding operator-(const Embedding &RHS) const
LLVM_ABI Embedding & operator-=(const Embedding &RHS)
LLVM_ABI Embedding operator*(double Factor) const
LLVM_ABI Embedding & operator*=(double Factor)
LLVM_ABI Embedding operator+(const Embedding &RHS) const
LLVM_ABI Embedding & scaleAndAdd(const Embedding &Src, float Factor)
Adds Src Embedding scaled by Factor with the called Embedding.
LLVM_ABI void print(raw_ostream &OS) const