33#define DEBUG_TYPE "ir2vec"
36 "Number of lookups to entities not present in the vocabulary");
48 cl::desc(
"Weight for opcode embeddings"),
51 cl::desc(
"Weight for type embeddings"),
54 cl::desc(
"Weight for argument embeddings"),
59 "Generate symbolic embeddings"),
61 "Generate flow-aware embeddings")),
76 std::vector<double> TempOut;
88 assert(this->
size() == RHS.
size() &&
"Vectors must have the same dimension");
89 std::transform(this->
begin(), this->
end(), RHS.
begin(), this->begin(),
101 assert(this->
size() == RHS.
size() &&
"Vectors must have the same dimension");
102 std::transform(this->
begin(), this->
end(), RHS.
begin(), this->begin(),
103 std::minus<double>());
115 [Factor](
double Elem) {
return Elem * Factor; });
126 assert(this->
size() == Src.
size() &&
"Vectors must have the same dimension");
127 for (
size_t Itr = 0; Itr < this->
size(); ++Itr)
128 (*
this)[Itr] += Src[Itr] * Factor;
133 double Tolerance)
const {
134 assert(this->
size() == RHS.
size() &&
"Vectors must have the same dimension");
135 for (
size_t Itr = 0; Itr < this->
size(); ++Itr)
136 if (std::abs((*
this)[Itr] - RHS[Itr]) > Tolerance) {
137 LLVM_DEBUG(
errs() <<
"Embedding mismatch at index " << Itr <<
": "
138 << (*
this)[Itr] <<
" vs " << RHS[Itr]
139 <<
"; Tolerance: " << Tolerance <<
"\n");
147 for (
const auto &Elem : Data)
148 OS <<
" " <<
format(
"%.2f", Elem) <<
" ";
165 return std::make_unique<SymbolicEmbedder>(
F,
Vocab);
167 return std::make_unique<FlowAwareEmbedder>(
F,
Vocab);
200 if (
F.isDeclaration())
216 for (
const auto &
Op :
I.operands())
219 Vocab[
I.getOpcode()] +
Vocab[
I.getType()->getTypeID()] + ArgEmb;
221 InstVector +=
Vocab[IC->getPredicate()];
223 BBVector += InstVector;
236 for (
const auto &
Op :
I.operands()) {
241 "Instruction should have been processed before its operands");
242 ArgEmb += DefIt->second;
247 LLVM_DEBUG(
errs() <<
"Using embedding from vocabulary for operand: "
255 Vocab[
I.getOpcode()] +
Vocab[
I.getType()->getTypeID()] + ArgEmb;
258 InstVector +=
Vocab[IC->getPredicate()];
260 BBVector += InstVector;
270 : Sections(
std::
move(SectionData)), TotalSize([&] {
271 assert(!Sections.empty() &&
"Vocabulary has no sections");
274 for (
const auto &Section : Sections) {
275 assert(!Section.empty() &&
"Vocabulary section is empty");
276 Size += Section.size();
283 assert(!Sections.empty() &&
"Vocabulary has no sections");
284 assert(!Sections[0].empty() &&
"First section of vocabulary is empty");
285 unsigned ExpectedDim =
static_cast<unsigned>(Sections[0][0].size());
289 [[maybe_unused]]
auto allSameDim =
290 [ExpectedDim](
const std::vector<Embedding> &Section) {
291 return std::all_of(Section.begin(), Section.end(),
293 return Emb.size() == ExpectedDim;
296 assert(std::all_of(Sections.begin(), Sections.end(), allSameDim) &&
297 "All embeddings must have the same dimension");
303 assert(SectionId < Storage->Sections.size() &&
"Invalid section ID");
304 assert(LocalIndex < Storage->Sections[SectionId].
size() &&
305 "Local index out of range");
306 return Storage->Sections[SectionId][LocalIndex];
313 LocalIndex >= Storage->Sections[SectionId].size()) {
314 assert(LocalIndex == Storage->Sections[SectionId].size() &&
315 "Local index should be at the end of the current section");
324 return Storage ==
Other.Storage && SectionId ==
Other.SectionId &&
325 LocalIndex ==
Other.LocalIndex;
330 return !(*
this ==
Other);
338 assert(Opcode >= 1 && Opcode <= MaxOpcodes &&
"Invalid opcode");
339#define HANDLE_INST(NUM, OPCODE, CLASS) \
340 if (Opcode == NUM) { \
343#include "llvm/IR/Instruction.def"
345 return "UnknownOpcode";
370 if (LocalIndex < fcmpRange)
375 LocalIndex - fcmpRange);
381 PredNameBuffer =
"FCMP_";
383 PredNameBuffer =
"ICMP_";
385 return PredNameBuffer;
389 assert(Pos < NumCanonicalEntries &&
"Position out of bounds in vocabulary");
391 if (Pos < MaxOpcodes)
394 if (Pos < OperandBaseOffset)
395 return getVocabKeyForCanonicalTypeID(
398 if (Pos < PredicateBaseOffset)
400 static_cast<OperandKind>(Pos - OperandBaseOffset));
407 ModuleAnalysisManager::Invalidator &Inv)
const {
409 return !(PAC.preservedWhenStateless());
413 float DummyVal = 0.1f;
417 std::vector<std::vector<Embedding>> Sections;
421 std::vector<Embedding> OpcodeSec;
422 OpcodeSec.reserve(MaxOpcodes);
423 for (
unsigned I = 0;
I < MaxOpcodes; ++
I) {
424 OpcodeSec.emplace_back(Dim, DummyVal);
427 Sections.push_back(std::move(OpcodeSec));
430 std::vector<Embedding> TypeSec;
433 TypeSec.emplace_back(Dim, DummyVal);
436 Sections.push_back(std::move(TypeSec));
439 std::vector<Embedding> OperandSec;
442 OperandSec.emplace_back(Dim, DummyVal);
445 Sections.push_back(std::move(OperandSec));
448 std::vector<Embedding> PredicateSec;
451 PredicateSec.emplace_back(Dim, DummyVal);
454 Sections.push_back(std::move(PredicateSec));
463Error IR2VecVocabAnalysis::parseVocabSection(
470 "JSON root is not an object");
475 "Missing '" + std::string(
Key) +
476 "' section in vocabulary file");
479 "Unable to parse '" + std::string(
Key) +
480 "' section from vocabulary");
482 Dim = TargetVocab.begin()->second.size();
485 "Dimension of '" + std::string(
Key) +
486 "' section of the vocabulary is zero");
488 if (!std::all_of(TargetVocab.begin(), TargetVocab.end(),
489 [Dim](
const std::pair<StringRef, Embedding> &Entry) {
490 return Entry.second.size() == Dim;
494 "All vectors in the '" + std::string(
Key) +
495 "' section of the vocabulary are not of the same dimension");
502Error IR2VecVocabAnalysis::readVocabulary(VocabMap &OpcVocab,
504 VocabMap &ArgVocab) {
509 auto Content = BufOrError.get()->getBuffer();
512 if (!ParsedVocabValue)
515 unsigned OpcodeDim = 0, TypeDim = 0, ArgDim = 0;
517 parseVocabSection(
"Opcodes", *ParsedVocabValue, OpcVocab, OpcodeDim))
521 parseVocabSection(
"Types", *ParsedVocabValue, TypeVocab, TypeDim))
525 parseVocabSection(
"Arguments", *ParsedVocabValue, ArgVocab, ArgDim))
528 if (!(OpcodeDim == TypeDim && TypeDim == ArgDim))
530 "Vocabulary sections have different dimensions");
535void IR2VecVocabAnalysis::generateVocabStorage(VocabMap &OpcVocab,
537 VocabMap &ArgVocab) {
542 auto handleMissingEntity = [](
const std::string &Val) {
544 <<
" is not in vocabulary, using zero vector; This "
545 "would result in an error in future.\n");
549 unsigned Dim = OpcVocab.begin()->second.size();
550 assert(Dim > 0 &&
"Vocabulary dimension must be greater than zero");
553 std::vector<Embedding> NumericOpcodeEmbeddings(Vocabulary::MaxOpcodes,
555 for (
unsigned Opcode :
seq(0u, Vocabulary::MaxOpcodes)) {
557 auto It = OpcVocab.find(VocabKey.
str());
558 if (It != OpcVocab.end())
559 NumericOpcodeEmbeddings[Opcode] = It->second;
561 handleMissingEntity(VocabKey.
str());
568 StringRef VocabKey = Vocabulary::getVocabKeyForCanonicalTypeID(
570 if (
auto It = TypeVocab.find(VocabKey.
str()); It != TypeVocab.end()) {
571 NumericTypeEmbeddings[CTypeID] = It->second;
574 handleMissingEntity(VocabKey.
str());
583 auto It = ArgVocab.find(VocabKey.
str());
584 if (It != ArgVocab.end()) {
585 NumericArgEmbeddings[OpKind] = It->second;
588 handleMissingEntity(VocabKey.
str());
598 auto It = ArgVocab.find(VocabKey.
str());
599 if (It != ArgVocab.end()) {
600 NumericPredEmbeddings[PK] = It->second;
603 handleMissingEntity(VocabKey.
str());
608 std::vector<std::vector<Embedding>> Sections(4);
609 Sections[
static_cast<unsigned>(Vocabulary::Section::Opcodes)] =
610 std::move(NumericOpcodeEmbeddings);
611 Sections[
static_cast<unsigned>(Vocabulary::Section::CanonicalTypes)] =
612 std::move(NumericTypeEmbeddings);
613 Sections[
static_cast<unsigned>(Vocabulary::Section::Operands)] =
614 std::move(NumericArgEmbeddings);
615 Sections[
static_cast<unsigned>(Vocabulary::Section::Predicates)] =
616 std::move(NumericPredEmbeddings);
619 Vocab.emplace(std::move(Sections));
622void IR2VecVocabAnalysis::emitError(
Error Err, LLVMContext &Ctx) {
630 auto Ctx = &M.getContext();
632 if (Vocab.has_value())
638 Ctx->emitError(
"IR2Vec vocabulary file path not specified; You may need to "
639 "set it using --ir2vec-vocab-path");
643 VocabMap OpcVocab, TypeVocab, ArgVocab;
644 if (
auto Err = readVocabulary(OpcVocab, TypeVocab, ArgVocab)) {
645 emitError(std::move(Err), *Ctx);
650 auto scaleVocabSection = [](VocabMap &Vocab,
double Weight) {
651 for (
auto &Entry : Vocab)
652 Entry.second *= Weight;
659 generateVocabStorage(OpcVocab, TypeVocab, ArgVocab);
676 OS <<
"Error creating IR2Vec embeddings \n";
680 OS <<
"IR2Vec embeddings for function " <<
F.getName() <<
":\n";
681 OS <<
"Function vector: ";
682 Emb->getFunctionVector().print(OS);
684 OS <<
"Basic block vectors:\n";
685 const auto &BBMap = Emb->getBBVecMap();
687 auto It = BBMap.find(&BB);
688 if (It != BBMap.end()) {
689 OS <<
"Basic block: " << BB.
getName() <<
":\n";
690 It->second.print(OS);
694 OS <<
"Instruction vectors:\n";
695 const auto &InstMap = Emb->getInstVecMap();
698 auto It = InstMap.find(&
I);
699 if (It != InstMap.end()) {
700 OS <<
"Instruction: ";
702 It->second.print(OS);
713 assert(IR2VecVocabulary.isValid() &&
"IR2Vec Vocabulary is invalid");
717 for (
const auto &Entry : IR2VecVocabulary) {
718 OS <<
"Key: " << IR2VecVocabulary.getStringKey(Pos++) <<
": ";
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.
ModuleAnalysisManager MAM
Provides some synthesis utilities to produce sequences of values.
This file defines the SmallVector class.
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.
LLVM_ABI iterator_range< filter_iterator< BasicBlock::const_iterator, std::function< bool(const Instruction &)> > > instructionsWithoutDebug(bool SkipPseudoOp=true) const
Return a const iterator range over the instructions in the block, skipping any debug instructions.
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)
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)
LLVM_ABI void emitError(const Instruction *I, const Twine &ErrorStr)
emitError - Emit an error message to the currently installed error handler with optional location inf...
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...
StringRef - Represent a constant reference to a string, i.e.
std::string str() const
str - Get the contents as an std::string.
LLVM Value Representation.
LLVM_ABI StringRef getName() const
Return a constant reference to the value's name.
LLVM_ABI const Embedding & getBBVector(const BasicBlock &BB) const
Returns the embedding for a given basic block in the function F if it has been computed.
static LLVM_ABI std::unique_ptr< Embedder > create(IR2VecKind Mode, const Function &F, const Vocabulary &Vocab)
Factory method to create an Embedder object.
LLVM_ABI const BBEmbeddingsMap & getBBVecMap() const
Returns a map containing basic block and the corresponding embeddings for the function F if it has be...
void computeEmbeddings() const
Function to compute embeddings.
LLVM_ABI const InstEmbeddingsMap & getInstVecMap() const
Returns a map containing instructions and the corresponding embeddings for the function F if it has b...
const float OpcWeight
Weights for different entities (like opcode, arguments, types) in the IR instructions to generate the...
const unsigned Dimension
Dimension of the vector representation; captured from the input vocabulary.
LLVM_ABI Embedder(const Function &F, const Vocabulary &Vocab)
LLVM_ABI const Embedding & getFunctionVector() const
Computes and returns the embedding for the current function.
InstEmbeddingsMap InstVecMap
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.
unsigned getNumSections() const
Get number of sections.
VocabStorage()
Default constructor creates empty storage (invalid state)
size_t size() const
Get total number of entries across all sections.
Class for storing and accessing the IR2Vec vocabulary.
static LLVM_ABI StringRef getVocabKeyForOperandKind(OperandKind Kind)
Function to get vocabulary key for a given OperandKind.
LLVM_ABI bool invalidate(Module &M, const PreservedAnalyses &PA, ModuleAnalysisManager::Invalidator &Inv) const
static LLVM_ABI OperandKind getOperandKind(const Value *Op)
Function to classify an operand into 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.
LLVM_ABI bool isValid() const
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.
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)
DenseMap< const Instruction *, Embedding > InstEmbeddingsMap
static cl::opt< std::string > VocabFile("ir2vec-vocab-path", cl::Optional, cl::desc("Path to the vocabulary file for IR2Vec"), cl::init(""), cl::cat(IR2VecCategory))
LLVM_ABI cl::opt< float > ArgWeight
DenseMap< const BasicBlock *, Embedding > BBEmbeddingsMap
LLVM_ABI cl::opt< float > OpcWeight
LLVM_ABI cl::opt< float > TypeWeight
LLVM_ABI cl::opt< IR2VecKind > IR2VecEmbeddingKind
llvm::cl::OptionCategory IR2VecCategory
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)
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.
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.
iterator_range< df_iterator< T > > depth_first(const T &G)
auto seq(T Begin, T End)
Iterate over an integral type from Begin up to - but not including - End.
AnalysisManager< Module > ModuleAnalysisManager
Convenience typedef for the Module analysis manager.
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