LLVM 24.0.0git
MIR2Vec.cpp
Go to the documentation of this file.
1//===- MIR2Vec.cpp - Implementation of MIR2Vec ---------------------------===//
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 MIR2Vec algorithm for Machine IR embeddings.
11///
12//===----------------------------------------------------------------------===//
13
16#include "llvm/ADT/Statistic.h"
18#include "llvm/IR/Module.h"
20#include "llvm/Pass.h"
21#include "llvm/Support/Errc.h"
23#include "llvm/Support/Regex.h"
24
25using namespace llvm;
26using namespace mir2vec;
27
28#define DEBUG_TYPE "mir2vec"
29
30STATISTIC(MIRVocabMissCounter,
31 "Number of lookups to MIR entities not present in the vocabulary");
32STATISTIC(MIRClasslessRegCounter,
33 "Number of register operands with no register class");
34
35namespace llvm {
36namespace mir2vec {
38
39// FIXME: Use a default vocab when not specified
41 VocabFile("mir2vec-vocab-path",
42 cl::desc("Path to the vocabulary file for MIR2Vec"), cl::init(""),
44cl::opt<float> OpcWeight("mir2vec-opc-weight", cl::init(1.0),
45 cl::desc("Weight for machine opcode embeddings"),
48 CommonOperandWeight("mir2vec-common-operand-weight", cl::init(1.0),
49 cl::desc("Weight for common operand embeddings"),
52 RegOperandWeight("mir2vec-reg-operand-weight", cl::init(1.0),
53 cl::desc("Weight for register operand embeddings"),
56 "mir2vec-kind",
58 "Generate symbolic embeddings for MIR")),
59 cl::init(MIR2VecKind::Symbolic), cl::desc("MIR2Vec embedding kind"),
61
63 "mir2vec-print-all-vocab-entries", cl::init(false),
64 cl::desc("Print all vocabulary entries including zero embeddings"),
66
67} // namespace mir2vec
68} // namespace llvm
69
70//===----------------------------------------------------------------------===//
71// Vocabulary
72//===----------------------------------------------------------------------===//
73
74MIRVocabulary::MIRVocabulary(VocabMap &&OpcodeMap, VocabMap &&CommonOperandMap,
75 VocabMap &&PhysicalRegisterMap,
76 VocabMap &&VirtualRegisterMap,
77 const TargetInstrInfo &TII,
79 const MachineRegisterInfo &MRI)
80 : TII(TII), TRI(TRI), MRI(MRI) {
81 buildCanonicalOpcodeMapping();
82 unsigned CanonicalOpcodeCount = UniqueBaseOpcodeNames.size();
83 assert(CanonicalOpcodeCount > 0 &&
84 "No canonical opcodes found for target - invalid vocabulary");
85
86 buildRegisterOperandMapping();
87
88 // Define layout of vocabulary sections
89 Layout.OpcodeBase = 0;
90 Layout.CommonOperandBase = CanonicalOpcodeCount;
91 // We expect same classes for physical and virtual registers
92 Layout.PhyRegBase = Layout.CommonOperandBase + std::size(CommonOperandNames);
93 Layout.VirtRegBase = Layout.PhyRegBase + RegisterOperandNames.size();
94
95 generateStorage(OpcodeMap, CommonOperandMap, PhysicalRegisterMap,
96 VirtualRegisterMap);
97 Layout.TotalEntries = Storage.size();
98}
99
101MIRVocabulary::create(VocabMap &&OpcodeMap, VocabMap &&CommonOperandMap,
102 VocabMap &&PhyRegMap, VocabMap &&VirtRegMap,
103 const TargetInstrInfo &TII, const TargetRegisterInfo &TRI,
104 const MachineRegisterInfo &MRI) {
105 if (OpcodeMap.empty() || CommonOperandMap.empty() || PhyRegMap.empty() ||
106 VirtRegMap.empty())
108 "Empty vocabulary entries provided");
109
110 MIRVocabulary Vocab(std::move(OpcodeMap), std::move(CommonOperandMap),
111 std::move(PhyRegMap), std::move(VirtRegMap), TII, TRI,
112 MRI);
113
114 // Validate Storage after construction
115 if (!Vocab.Storage.isValid())
117 "Failed to create valid vocabulary storage");
118 Vocab.ZeroEmbedding = Embedding(Vocab.Storage.getDimension(), 0.0);
119 return std::move(Vocab);
120}
121
123 // Extract base instruction name using regex to capture letters and
124 // underscores Examples: "ADD32rr" -> "ADD", "ARITH_FENCE" -> "ARITH_FENCE"
125 //
126 // TODO: Consider more sophisticated extraction:
127 // - Handle complex prefixes like "AVX1_SETALLONES" correctly (Currently, it
128 // would naively map to "AVX")
129 // - Extract width suffixes (8,16,32,64) as separate features
130 // - Capture addressing mode suffixes (r,i,m,ri,etc.) for better analysis
131 // (Currently, instances like "MOV32mi" map to "MOV", but "ADDPDrr" would map
132 // to "ADDPDrr")
133
134 assert(!InstrName.empty() && "Instruction name should not be empty");
135
136 // Use regex to extract initial sequence of letters and underscores
137 static const Regex BaseOpcodeRegex("([a-zA-Z_]+)");
139
140 if (BaseOpcodeRegex.match(InstrName, &Matches) && Matches.size() > 1) {
141 StringRef Match = Matches[1];
142 // Trim trailing underscores
143 while (!Match.empty() && Match.back() == '_')
144 Match = Match.drop_back();
145 return Match.str();
146 }
147
148 // Fallback to original name if no pattern matches
149 return InstrName.str();
150}
151
153 assert(!UniqueBaseOpcodeNames.empty() && "Canonical mapping not built");
154 auto It = std::find(UniqueBaseOpcodeNames.begin(),
155 UniqueBaseOpcodeNames.end(), BaseName.str());
156 assert(It != UniqueBaseOpcodeNames.end() &&
157 "Base name not found in unique opcodes");
158 return std::distance(UniqueBaseOpcodeNames.begin(), It);
159}
160
161unsigned MIRVocabulary::getCanonicalOpcodeIndex(unsigned Opcode) const {
162 auto BaseOpcode = extractBaseOpcodeName(TII.getName(Opcode));
163 return getCanonicalIndexForBaseName(BaseOpcode);
164}
165
166unsigned
168 auto It = std::find(std::begin(CommonOperandNames),
169 std::end(CommonOperandNames), OperandName);
170 assert(It != std::end(CommonOperandNames) &&
171 "Operand name not found in common operands");
172 return Layout.CommonOperandBase +
173 std::distance(std::begin(CommonOperandNames), It);
174}
175
176unsigned
178 bool IsPhysical) const {
179 auto It = std::find(RegisterOperandNames.begin(), RegisterOperandNames.end(),
180 RegName);
181 assert(It != RegisterOperandNames.end() &&
182 "Register name not found in register operands");
183 unsigned LocalIndex = std::distance(RegisterOperandNames.begin(), It);
184 return (IsPhysical ? Layout.PhyRegBase : Layout.VirtRegBase) + LocalIndex;
185}
186
187std::string MIRVocabulary::getStringKey(unsigned Pos) const {
188 assert(Pos < Layout.TotalEntries && "Position out of bounds in vocabulary");
189
190 // Handle opcodes section
191 if (Pos < Layout.CommonOperandBase) {
192 // Convert canonical index back to base opcode name
193 auto It = UniqueBaseOpcodeNames.begin();
194 std::advance(It, Pos);
195 assert(It != UniqueBaseOpcodeNames.end() &&
196 "Canonical index out of bounds in opcode section");
197 return *It;
198 }
199
200 auto getLocalIndex = [](unsigned Pos, size_t BaseOffset, size_t Bound,
201 const char *Msg) {
202 unsigned LocalIndex = Pos - BaseOffset;
203 assert(LocalIndex < Bound && Msg);
204 return LocalIndex;
205 };
206
207 // Handle common operands section
208 if (Pos < Layout.PhyRegBase) {
209 unsigned LocalIndex = getLocalIndex(
210 Pos, Layout.CommonOperandBase, std::size(CommonOperandNames),
211 "Local index out of bounds in common operands");
212 return CommonOperandNames[LocalIndex].str();
213 }
214
215 // Handle physical registers section
216 if (Pos < Layout.VirtRegBase) {
217 unsigned LocalIndex =
218 getLocalIndex(Pos, Layout.PhyRegBase, RegisterOperandNames.size(),
219 "Local index out of bounds in physical registers");
220 return "PhyReg_" + RegisterOperandNames[LocalIndex];
221 }
222
223 // Handle virtual registers section
224 unsigned LocalIndex =
225 getLocalIndex(Pos, Layout.VirtRegBase, RegisterOperandNames.size(),
226 "Local index out of bounds in virtual registers");
227 return "VirtReg_" + RegisterOperandNames[LocalIndex];
228}
229
230void MIRVocabulary::generateStorage(const VocabMap &OpcodeMap,
231 const VocabMap &CommonOperandsMap,
232 const VocabMap &PhyRegMap,
233 const VocabMap &VirtRegMap) {
234
235 // Helper for handling missing entities in the vocabulary.
236 // Currently, we use a zero vector. In the future, we will throw an error to
237 // ensure that *all* known entities are present in the vocabulary.
238 auto handleMissingEntity = [](StringRef Key) {
239 LLVM_DEBUG(errs() << "MIR2Vec: Missing vocabulary entry for " << Key
240 << "; using zero vector. This will result in an error "
241 "in the future.\n");
242 ++MIRVocabMissCounter;
243 };
244
245 // Initialize opcode embeddings section
246 unsigned EmbeddingDim = OpcodeMap.begin()->second.size();
247 std::vector<Embedding> OpcodeEmbeddings(Layout.CommonOperandBase,
248 Embedding(EmbeddingDim));
249
250 // Populate opcode embeddings using canonical mapping
251 for (auto COpcodeName : UniqueBaseOpcodeNames) {
252 if (auto It = OpcodeMap.find(COpcodeName); It != OpcodeMap.end()) {
253 auto COpcodeIndex = getCanonicalIndexForBaseName(COpcodeName);
254 assert(COpcodeIndex < Layout.CommonOperandBase &&
255 "Canonical index out of bounds");
256 OpcodeEmbeddings[COpcodeIndex] = It->second;
257 } else {
258 handleMissingEntity(COpcodeName);
259 }
260 }
261
262 // Initialize common operand embeddings section
263 std::vector<Embedding> CommonOperandEmbeddings(std::size(CommonOperandNames),
264 Embedding(EmbeddingDim));
265 unsigned OperandIndex = 0;
266 for (const auto &CommonOperandName : CommonOperandNames) {
267 if (auto It = CommonOperandsMap.find(CommonOperandName.str());
268 It != CommonOperandsMap.end()) {
269 CommonOperandEmbeddings[OperandIndex] = It->second;
270 } else {
271 handleMissingEntity(CommonOperandName);
272 }
273 ++OperandIndex;
274 }
275
276 // Helper lambda for creating register operand embeddings
277 auto createRegisterEmbeddings = [&](const VocabMap &RegMap) {
278 std::vector<Embedding> RegEmbeddings(TRI.getNumRegClasses(),
279 Embedding(EmbeddingDim));
280 unsigned RegOperandIndex = 0;
281 for (const auto &RegOperandName : RegisterOperandNames) {
282 if (auto It = RegMap.find(RegOperandName); It != RegMap.end())
283 RegEmbeddings[RegOperandIndex] = It->second;
284 else
285 handleMissingEntity(RegOperandName);
286 ++RegOperandIndex;
287 }
288 return RegEmbeddings;
289 };
290
291 // Initialize register operand embeddings sections
292 std::vector<Embedding> PhyRegEmbeddings = createRegisterEmbeddings(PhyRegMap);
293 std::vector<Embedding> VirtRegEmbeddings =
294 createRegisterEmbeddings(VirtRegMap);
295
296 // Scale the vocabulary sections based on the provided weights
297 auto scaleVocabSection = [](std::vector<Embedding> &Embeddings,
298 double Weight) {
299 for (auto &Embedding : Embeddings)
300 Embedding *= Weight;
301 };
302 scaleVocabSection(OpcodeEmbeddings, OpcWeight);
303 scaleVocabSection(CommonOperandEmbeddings, CommonOperandWeight);
304 scaleVocabSection(PhyRegEmbeddings, RegOperandWeight);
305 scaleVocabSection(VirtRegEmbeddings, RegOperandWeight);
306
307 std::vector<std::vector<Embedding>> Sections(
308 static_cast<unsigned>(Section::MaxSections));
309 Sections[static_cast<unsigned>(Section::Opcodes)] =
310 std::move(OpcodeEmbeddings);
311 Sections[static_cast<unsigned>(Section::CommonOperands)] =
312 std::move(CommonOperandEmbeddings);
313 Sections[static_cast<unsigned>(Section::PhyRegisters)] =
314 std::move(PhyRegEmbeddings);
315 Sections[static_cast<unsigned>(Section::VirtRegisters)] =
316 std::move(VirtRegEmbeddings);
317
318 Storage = ir2vec::VocabStorage(std::move(Sections));
319}
320
321void MIRVocabulary::buildCanonicalOpcodeMapping() {
322 // Check if already built
323 if (!UniqueBaseOpcodeNames.empty())
324 return;
325
326 // Build mapping from opcodes to canonical base opcode indices
327 for (unsigned Opcode = 0; Opcode < TII.getNumOpcodes(); ++Opcode) {
328 std::string BaseOpcode = extractBaseOpcodeName(TII.getName(Opcode));
329 UniqueBaseOpcodeNames.insert(BaseOpcode);
330 }
331
332 LLVM_DEBUG(dbgs() << "MIR2Vec: Built canonical mapping for target with "
333 << UniqueBaseOpcodeNames.size()
334 << " unique base opcodes\n");
335}
336
337void MIRVocabulary::buildRegisterOperandMapping() {
338 // Check if already built
339 if (!RegisterOperandNames.empty())
340 return;
341
342 for (unsigned RC = 0; RC < TRI.getNumRegClasses(); ++RC) {
343 const TargetRegisterClass *RegClass = TRI.getRegClass(RC);
344 if (!RegClass)
345 continue;
346
347 // Get the register class name
348 StringRef ClassName = TRI.getRegClassName(RegClass);
349 RegisterOperandNames.push_back(ClassName.str());
350 }
351}
352
353unsigned MIRVocabulary::getCommonOperandIndex(
354 MachineOperand::MachineOperandType OperandType) const {
355 assert(OperandType != MachineOperand::MO_Register &&
356 "Expected non-register operand type");
357 assert(OperandType > MachineOperand::MO_Register &&
358 OperandType < MachineOperand::MO_Last && "Operand type out of bounds");
359 return static_cast<unsigned>(OperandType) - 1;
360}
361
362std::optional<unsigned>
363MIRVocabulary::getRegisterOperandIndex(Register Reg) const {
364 assert(!RegisterOperandNames.empty() && "Register operand mapping not built");
365 assert(Reg.isValid() && "Invalid register; not expected here");
366 assert((Reg.isPhysical() || Reg.isVirtual()) &&
367 "Expected a physical or virtual register");
368
369 const TargetRegisterClass *RegClass = nullptr;
370
371 // For physical registers, use TRI to get minimal register class as a
372 // physical register can belong to multiple classes. For virtual
373 // registers, use MRI to uniquely identify the assigned register class.
374 if (Reg.isPhysical())
375 RegClass = TRI.getMinimalPhysRegClass(Reg);
376 else
377 RegClass = MRI.getRegClassOrNull(Reg);
378
379 // Not every register belongs to a register class. This can happen for
380 // physical registers, e.g. X86's $mxcsr and $fpcw or AMDGPU's $mode, for
381 // which getMinimalPhysRegClass() returns nullptr. It can also happen for
382 // generic virtual registers that have not yet been through (or completed)
383 // GlobalISel's register bank selection, and thus carry an LLT or a
384 // RegisterBank instead of a TargetRegisterClass, for which
385 // getRegClassOrNull() returns nullptr.
386 // TODO: Avoid special-casing these registers at every use site. Classless
387 // registers currently fall back to a zero embedding in operator[] and to
388 // VirtRegBase in getEntityIDForRegister(), which is the same ad-hoc handling
389 // the invalid/stack-slot cases already get. Give them a real vocabulary
390 // representation instead -- e.g. an explicit "no register class" entry, or
391 // keying generic vregs on their LLT/RegisterBank -- so that the lookup is
392 // total and the callers need no fallbacks.
393 if (!RegClass) {
394 LLVM_DEBUG(errs() << "MIR2Vec: No register class for register " << Reg.id()
395 << "; using zero vector.\n");
396 ++MIRClasslessRegCounter;
397 return std::nullopt;
398 }
399
400 return RegClass->getID();
401}
402
404 const TargetInstrInfo &TII, const TargetRegisterInfo &TRI,
405 const MachineRegisterInfo &MRI, unsigned Dim) {
406 assert(Dim > 0 && "Dimension must be greater than zero");
407
408 float DummyVal = 0.1f;
409
410 VocabMap DummyOpcMap, DummyOperandMap, DummyPhyRegMap, DummyVirtRegMap;
411
412 // Process opcodes directly without creating temporary vocabulary
413 for (unsigned Opcode = 0; Opcode < TII.getNumOpcodes(); ++Opcode) {
414 std::string BaseOpcode = extractBaseOpcodeName(TII.getName(Opcode));
415 if (DummyOpcMap.count(BaseOpcode) == 0) { // Only add if not already present
416 DummyOpcMap[BaseOpcode] = Embedding(Dim, DummyVal);
417 DummyVal += 0.1f;
418 }
419 }
420
421 // Add common operands
422 for (const auto &CommonOperandName : CommonOperandNames) {
423 DummyOperandMap[CommonOperandName.str()] = Embedding(Dim, DummyVal);
424 DummyVal += 0.1f;
425 }
426
427 // Process register classes directly
428 for (unsigned RC = 0; RC < TRI.getNumRegClasses(); ++RC) {
429 const TargetRegisterClass *RegClass = TRI.getRegClass(RC);
430 if (!RegClass)
431 continue;
432
433 std::string ClassName = TRI.getRegClassName(RegClass);
434 DummyPhyRegMap[ClassName] = Embedding(Dim, DummyVal);
435 DummyVirtRegMap[ClassName] = Embedding(Dim, DummyVal);
436 DummyVal += 0.1f;
437 }
438
439 // Create vocabulary directly without temporary instance
441 std::move(DummyOpcMap), std::move(DummyOperandMap),
442 std::move(DummyPhyRegMap), std::move(DummyVirtRegMap), TII, TRI, MRI);
443}
444
445//===----------------------------------------------------------------------===//
446// MIR2VecVocabProvider and MIR2VecVocabLegacyAnalysis
447//===----------------------------------------------------------------------===//
448
451 VocabMap OpcVocab, CommonOperandVocab, PhyRegVocabMap, VirtRegVocabMap;
452
453 if (Error Err = readVocabulary(OpcVocab, CommonOperandVocab, PhyRegVocabMap,
454 VirtRegVocabMap))
455 return std::move(Err);
456
457 for (const auto &F : M) {
458 if (F.isDeclaration())
459 continue;
460
461 if (auto *MF = MMI.getMachineFunction(F)) {
462 auto &Subtarget = MF->getSubtarget();
463 if (const auto *TII = Subtarget.getInstrInfo())
464 if (const auto *TRI = Subtarget.getRegisterInfo())
466 std::move(OpcVocab), std::move(CommonOperandVocab),
467 std::move(PhyRegVocabMap), std::move(VirtRegVocabMap), *TII, *TRI,
468 MF->getRegInfo());
469 }
470 }
472 "No machine functions found in module");
473}
474
475Error MIR2VecVocabProvider::readVocabulary(VocabMap &OpcodeVocab,
476 VocabMap &CommonOperandVocab,
477 VocabMap &PhyRegVocabMap,
478 VocabMap &VirtRegVocabMap) {
479 if (VocabFile.empty())
480 return createStringError(
482 "MIR2Vec vocabulary file path not specified; set it "
483 "using --mir2vec-vocab-path");
484
485 auto BufOrError = MemoryBuffer::getFileOrSTDIN(VocabFile, /*IsText=*/true);
486 if (!BufOrError)
487 return createFileError(VocabFile, BufOrError.getError());
488
489 auto Content = BufOrError.get()->getBuffer();
490
491 Expected<json::Value> ParsedVocabValue = json::parse(Content);
492 if (!ParsedVocabValue)
493 return ParsedVocabValue.takeError();
494
495 unsigned OpcodeDim = 0, CommonOperandDim = 0, PhyRegOperandDim = 0,
496 VirtRegOperandDim = 0;
498 "Opcodes", *ParsedVocabValue, OpcodeVocab, OpcodeDim))
499 return Err;
500
502 "CommonOperands", *ParsedVocabValue, CommonOperandVocab,
503 CommonOperandDim))
504 return Err;
505
507 "PhysicalRegisters", *ParsedVocabValue, PhyRegVocabMap,
508 PhyRegOperandDim))
509 return Err;
510
512 "VirtualRegisters", *ParsedVocabValue, VirtRegVocabMap,
513 VirtRegOperandDim))
514 return Err;
515
516 // All sections must have the same embedding dimension
517 if (!(OpcodeDim == CommonOperandDim && CommonOperandDim == PhyRegOperandDim &&
518 PhyRegOperandDim == VirtRegOperandDim)) {
519 return createStringError(
521 "MIR2Vec vocabulary sections have different dimensions");
522 }
523
524 return Error::success();
525}
526
529 "MIR2Vec Vocabulary Analysis", false, true)
532 "MIR2Vec Vocabulary Analysis", false, true)
533
534StringRef MIR2VecVocabLegacyAnalysis::getPassName() const {
535 return "MIR2Vec Vocabulary Analysis";
536}
537
538//===----------------------------------------------------------------------===//
539// MIREmbedder and its subclasses
540//===----------------------------------------------------------------------===//
541
542std::unique_ptr<MIREmbedder> MIREmbedder::create(MIR2VecKind Mode,
543 const MachineFunction &MF,
544 const MIRVocabulary &Vocab) {
545 switch (Mode) {
547 return std::make_unique<SymbolicMIREmbedder>(MF, Vocab);
548 }
549 return nullptr;
550}
551
554
555 // Get instruction info for opcode name resolution
556 const auto &Subtarget = MF.getSubtarget();
557 const auto *TII = Subtarget.getInstrInfo();
558 if (!TII) {
559 MF.getFunction().getContext().emitError(
560 "MIR2Vec: No TargetInstrInfo available; cannot compute embeddings");
561 return MBBVector;
562 }
563
564 // Process each machine instruction in the basic block
565 for (const auto &MI : MBB) {
566 // Skip debug instructions and other metadata
567 if (MI.isDebugInstr())
568 continue;
570 }
571
572 return MBBVector;
573}
574
576 Embedding MFuncVector(Dimension, 0);
577
578 if (MF.empty())
579 return MFuncVector;
580
581 // Consider all reachable machine basic blocks in the function
582 for (const auto *MBB : depth_first(&MF))
583 MFuncVector += computeEmbeddings(*MBB);
584 return MFuncVector;
585}
586
590
591std::unique_ptr<SymbolicMIREmbedder>
593 const MIRVocabulary &Vocab) {
594 return std::make_unique<SymbolicMIREmbedder>(MF, Vocab);
595}
596
598 // Skip debug instructions and other metadata
599 if (MI.isDebugInstr())
600 return Embedding(Dimension, 0);
601
602 // Opcode embedding
603 Embedding InstructionEmbedding = Vocab[MI.getOpcode()];
604
605 // Add operand contributions
606 for (const MachineOperand &MO : MI.operands())
607 InstructionEmbedding += Vocab[MO];
608
609 return InstructionEmbedding;
610}
611
612//===----------------------------------------------------------------------===//
613// Printer Passes
614//===----------------------------------------------------------------------===//
615
618 "MIR2Vec Vocabulary Printer Pass", false, true)
622 "MIR2Vec Vocabulary Printer Pass", false, true)
623
627
630 auto MIR2VecVocabOrErr = Analysis.getMIR2VecVocabulary(M);
631
632 if (!MIR2VecVocabOrErr) {
633 OS << "MIR2Vec Vocabulary Printer: Failed to get vocabulary - "
634 << toString(MIR2VecVocabOrErr.takeError()) << "\n";
635 return false;
636 }
637
638 auto &MIR2VecVocab = *MIR2VecVocabOrErr;
639 unsigned Pos = 0;
640 for (const auto &Entry : MIR2VecVocab) {
641 // Skip zero embeddings to avoid printing entries not in the vocabulary.
642 // This makes the output stable across changes to the opcode list.
643 if (PrintAllVocabEntries || !Entry.isZero()) {
644 OS << "Key: " << MIR2VecVocab.getStringKey(Pos) << ": ";
645 Entry.print(OS);
646 }
647 ++Pos;
648 }
649
650 return false;
651}
652
657
660 "MIR2Vec Embedder Printer Pass", false, true)
664 "MIR2Vec Embedder Printer Pass", false, true)
665
668 auto VocabOrErr =
669 Analysis.getMIR2VecVocabulary(*MF.getFunction().getParent());
670 assert(VocabOrErr && "Failed to get MIR2Vec vocabulary");
671 auto &MIRVocab = *VocabOrErr;
672
673 auto Emb = mir2vec::MIREmbedder::create(MIR2VecEmbeddingKind, MF, MIRVocab);
674 if (!Emb) {
675 OS << "Error creating MIR2Vec embeddings for function " << MF.getName()
676 << "\n";
677 return false;
678 }
679
680 OS << "MIR2Vec embeddings for machine function " << MF.getName() << ":\n";
681 OS << "Machine Function vector: ";
682 Emb->getMFunctionVector().print(OS);
683
684 OS << "Machine basic block vectors:\n";
685 for (const MachineBasicBlock &MBB : MF) {
686 OS << "Machine basic block: " << MBB.getFullName() << ":\n";
687 Emb->getMBBVector(MBB).print(OS);
688 }
689
690 OS << "Machine instruction vectors:\n";
691 for (const MachineBasicBlock &MBB : MF) {
692 for (const MachineInstr &MI : MBB) {
693 // Skip debug instructions as they are not
694 // embedded
695 if (MI.isDebugInstr())
696 continue;
697
698 OS << "Machine instruction: ";
699 MI.print(OS);
700 Emb->getMInstVector(MI).print(OS);
701 }
702 }
703
704 return false;
705}
706
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
MachineBasicBlock & MBB
block Block Frequency Analysis
#define clEnumValN(ENUMVAL, FLAGNAME, DESC)
This file builds on the ADT/GraphTraits.h file to build generic depth first graph iterator.
const HexagonInstrInfo * TII
IRTranslator LLVM IR MI
Module.h This file contains the declarations for the Module class.
#define RegName(no)
#define F(x, y, z)
Definition MD5.cpp:54
This file defines the MIR2Vec framework for generating Machine IR embeddings.
Register Reg
Register const TargetRegisterInfo * TRI
#define INITIALIZE_PASS_DEPENDENCY(depName)
Definition PassSupport.h:42
#define INITIALIZE_PASS_END(passName, arg, name, cfg, analysis)
Definition PassSupport.h:44
#define INITIALIZE_PASS_BEGIN(passName, arg, name, cfg, analysis)
Definition PassSupport.h:39
SmallVector< MachineBasicBlock *, 4 > MBBVector
const char * Msg
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
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
unsigned getID() const
getID() - Return the register class ID number.
This pass prints the MIR2Vec embeddings for machine functions, basic blocks, and instructions.
Definition MIR2Vec.h:448
MIR2VecPrinterLegacyPass(raw_ostream &OS)
Definition MIR2Vec.h:453
bool runOnMachineFunction(MachineFunction &MF) override
runOnMachineFunction - This method must be overloaded to perform the desired machine code transformat...
Definition MIR2Vec.cpp:666
Pass to analyze and populate MIR2Vec vocabulary from a module.
Definition MIR2Vec.h:393
This pass prints the embeddings in the MIR2Vec vocabulary.
Definition MIR2Vec.h:425
bool doFinalization(Module &M) override
doFinalization - Virtual method overriden by subclasses to do any necessary clean up after all passes...
Definition MIR2Vec.cpp:628
bool runOnMachineFunction(MachineFunction &MF) override
runOnMachineFunction - This method must be overloaded to perform the desired machine code transformat...
Definition MIR2Vec.cpp:624
MIR2VecVocabPrinterLegacyPass(raw_ostream &OS)
Definition MIR2Vec.h:430
LLVM_ABI Expected< mir2vec::MIRVocabulary > getVocabulary(const Module &M)
Definition MIR2Vec.cpp:450
MachineFunctionPass - This class adapts the FunctionPass interface to allow convenient creation of pa...
Representation of each machine instruction.
MachineOperand class - Representation of each machine instruction operand.
@ MO_Register
Register operand.
MachineRegisterInfo - Keep track of information for virtual and physical registers,...
const TargetRegisterClass * getRegClassOrNull(Register Reg) const
Return the register class of Reg, or null if Reg has not been assigned a register class yet.
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
AnalysisType & getAnalysis() const
getAnalysis<AnalysisType>() - This function is used by subclasses to get to the analysis information ...
LLVM_ABI bool match(StringRef String, SmallVectorImpl< StringRef > *Matches=nullptr, std::string *Error=nullptr) const
matches - Match the regex against a given String.
Definition Regex.cpp:84
Wrapper class representing virtual and physical registers.
Definition Register.h:20
constexpr bool isValid() const
Definition Register.h:112
constexpr bool isVirtual() const
Return true if the specified register number is in the virtual register namespace.
Definition Register.h:79
constexpr unsigned id() const
Definition Register.h:100
constexpr bool isPhysical() const
Return true if the specified register number is in the physical register namespace.
Definition Register.h:83
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
Represent a constant reference to a string, i.e.
Definition StringRef.h:56
std::string str() const
Get the contents as an std::string.
Definition StringRef.h:222
constexpr bool empty() const
Check if the string is empty.
Definition StringRef.h:141
char back() const
Get the last character in the string.
Definition StringRef.h:153
StringRef drop_back(size_t N=1) const
Return a StringRef equal to 'this' but with the last N elements dropped.
Definition StringRef.h:642
TargetInstrInfo - Interface to description of machine instruction set.
TargetRegisterInfo base class - We assume that the target defines a static array of TargetRegisterDes...
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 getDimension() const
Get vocabulary dimension.
Definition IR2Vec.h:196
bool isValid() const
Check if vocabulary is valid (has data)
Definition IR2Vec.h:199
const unsigned Dimension
Dimension of the embeddings; Captured from the vocabulary.
Definition MIR2Vec.h:305
const MIRVocabulary & Vocab
Definition MIR2Vec.h:302
MIREmbedder(const MachineFunction &MF, const MIRVocabulary &Vocab)
Definition MIR2Vec.h:310
LLVM_ABI Embedding computeEmbeddings() const
Function to compute embeddings.
Definition MIR2Vec.cpp:575
const MachineFunction & MF
Definition MIR2Vec.h:301
static LLVM_ABI std::unique_ptr< MIREmbedder > create(MIR2VecKind Mode, const MachineFunction &MF, const MIRVocabulary &Vocab)
Factory method to create an Embedder object of the specified kind Returns nullptr if the requested ki...
Definition MIR2Vec.cpp:542
Class for storing and accessing the MIR2Vec vocabulary.
Definition MIR2Vec.h:87
LLVM_ABI unsigned getCanonicalIndexForOperandName(StringRef OperandName) const
Definition MIR2Vec.cpp:167
LLVM_ABI unsigned getCanonicalIndexForRegisterClass(StringRef RegName, bool IsPhysical=true) const
Definition MIR2Vec.cpp:177
static LLVM_ABI Expected< MIRVocabulary > create(VocabMap &&OpcMap, VocabMap &&CommonOperandsMap, VocabMap &&PhyRegMap, VocabMap &&VirtRegMap, const TargetInstrInfo &TII, const TargetRegisterInfo &TRI, const MachineRegisterInfo &MRI)
Factory method to create MIRVocabulary from vocabulary map.
Definition MIR2Vec.cpp:101
static LLVM_ABI std::string extractBaseOpcodeName(StringRef InstrName)
Static method for extracting base opcode names (public for testing)
Definition MIR2Vec.cpp:122
static LLVM_ABI Expected< MIRVocabulary > createDummyVocabForTest(const TargetInstrInfo &TII, const TargetRegisterInfo &TRI, const MachineRegisterInfo &MRI, unsigned Dim=1)
Create a dummy vocabulary for testing purposes.
Definition MIR2Vec.cpp:403
LLVM_ABI std::string getStringKey(unsigned Pos) const
Get the string key for a vocabulary entry at the given position.
Definition MIR2Vec.cpp:187
LLVM_ABI unsigned getCanonicalIndexForBaseName(StringRef BaseName) const
Get indices from opcode or operand names.
Definition MIR2Vec.cpp:152
static std::unique_ptr< SymbolicMIREmbedder > create(const MachineFunction &MF, const MIRVocabulary &Vocab)
Definition MIR2Vec.cpp:592
SymbolicMIREmbedder(const MachineFunction &F, const MIRVocabulary &Vocab)
Definition MIR2Vec.cpp:587
This class implements an extremely fast bulk output stream that can only output to a stream.
Definition raw_ostream.h:53
OperandType
Operands are tagged with one of the values of this enum.
Definition MCInstrDesc.h:59
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 llvm::Expected< Value > parse(llvm::StringRef JSON)
Parses the provided JSON source, or returns a ParseError.
Definition JSON.cpp:681
LLVM_ABI llvm::cl::OptionCategory MIR2VecCategory
static cl::opt< bool > PrintAllVocabEntries("mir2vec-print-all-vocab-entries", cl::init(false), cl::desc("Print all vocabulary entries including zero embeddings"), cl::cat(MIR2VecCategory))
LLVM_ABI cl::opt< float > RegOperandWeight
Definition MIR2Vec.h:78
ir2vec::Embedding Embedding
Definition MIR2Vec.h:80
LLVM_ABI cl::opt< float > OpcWeight
cl::opt< MIR2VecKind > MIR2VecEmbeddingKind("mir2vec-kind", cl::values(clEnumValN(MIR2VecKind::Symbolic, "symbolic", "Generate symbolic embeddings for MIR")), cl::init(MIR2VecKind::Symbolic), cl::desc("MIR2Vec embedding kind"), cl::cat(MIR2VecCategory))
static cl::opt< std::string > VocabFile("mir2vec-vocab-path", cl::desc("Path to the vocabulary file for MIR2Vec"), cl::init(""), cl::cat(MIR2VecCategory))
LLVM_ABI cl::opt< float > CommonOperandWeight
Definition MIR2Vec.h:78
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
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
LLVM_ABI MachineFunctionPass * createMIR2VecPrinterLegacyPass(raw_ostream &OS)
Create a machine pass that prints MIR2Vec embeddings.
Definition MIR2Vec.cpp:707
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
Definition Debug.cpp:209
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.
LLVM_ABI MachineFunctionPass * createMIR2VecVocabPrinterLegacyPass(raw_ostream &OS)
MIR2VecVocabPrinter pass - This pass prints out the MIR2Vec vocabulary contents to the given stream a...
Definition MIR2Vec.cpp:654
MIR2VecKind
Definition MIR2Vec.h:69
std::string toString(const APInt &I, unsigned Radix, bool Signed, bool formatAsCLiteral=false, bool UpperCase=true, bool InsertSeparators=false)
iterator_range< df_iterator< T > > depth_first(const T &G)
MCRegisterClass TargetRegisterClass
Definition FastISel.h:58