Files
TheRock/compiler/amd-llvm/llvm/tools/llvm-ir2vec/lib/MIRUtils/MIRUtils.cpp
T
derek.holloway 7502bf64a4
CodeQL / Analyze (actions) (push) Canceled after 0s
CodeQL / Analyze (python) (push) Canceled after 0s
pre-commit / pre-commit (push) Canceled after 0s
Multi-Arch CI / setup (push) Canceled after 0s
Publish build_manylinux_x86_64 images / publish_build_manylinux_x86_64 (push) Canceled after 0s
Setup (Multi-Arch) / setup (push) Canceled after 0s
Multi-Arch CI / Linux::${{ fromJSON(needs.setup.outputs.linux_build_config || '{}').build_variant_label || 'skip' }} (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Publish no_rocm_image_ubi10 image / publish_no_rocm_image_ubi10 (push) Canceled after 0s
Multi-Arch CI / Windows::${{ fromJSON(needs.setup.outputs.windows_build_config || '{}').build_variant_label || 'skip' }} (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Multi-Arch CI / Manifest Diff (push) Canceled after 0s
TheRock Manifest Diff Report / Generate Manifest Diff Report (push) Canceled after 0s
Multi-Arch CI / CI Summary (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04 (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04_ocl_rt images / publish_no_rocm_image_ubuntu24_04_ocl_rt (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_rocgdb (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04_rocgdb images / publish_no_rocm_image_ubuntu24_04_rocgdb (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_ocl_rt (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Unit Tests / Unit Tests :: ubuntu-24.04 (push) Canceled after 0s
Unit Tests / Unit Tests :: windows-2022 (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_media (push) Canceled after 0s
Unit Tests / Unit Tests Summary (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_openmpi (push) Canceled after 0s
Flatten subprojects into a single base monorepo
2026-09-02 16:34:47 -07:00

237 lines
7.3 KiB
C++

//===- MIRUtils.cpp - MIR2Vec Embedding Generation --------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
///
/// \file
/// This file implements the MIR2VecTool class for MIR2Vec embedding generation
/// from LLVM Machine IR. It has no dependency on the IR2Vec embedding API.
///
//===----------------------------------------------------------------------===//
#include "MIRUtils.h"
#include "llvm/CodeGen/MIR2Vec.h"
#include "llvm/CodeGen/MIRParser/MIRParser.h"
#include "llvm/CodeGen/MachineFunction.h"
#include "llvm/CodeGen/MachineModuleInfo.h"
#include "llvm/CodeGen/TargetInstrInfo.h"
#include "llvm/CodeGen/TargetRegisterInfo.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/WithColor.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/Target/TargetMachine.h"
#define DEBUG_TYPE "ir2vec"
namespace llvm {
namespace mir2vec {
bool MIR2VecTool::initializeVocabulary(const Module &M) {
MIR2VecVocabProvider Provider(MMI);
auto VocabOrErr = Provider.getVocabulary(M);
if (!VocabOrErr) {
WithColor::error(errs(), ToolName)
<< "Failed to load MIR2Vec vocabulary - "
<< toString(VocabOrErr.takeError()) << "\n";
return false;
}
Vocab = std::make_unique<MIRVocabulary>(std::move(*VocabOrErr));
return true;
}
bool MIR2VecTool::initializeVocabularyForLayout(const Module &M) {
for (const Function &F : M.getFunctionDefs()) {
MachineFunction *MF = MMI.getMachineFunction(F);
if (!MF)
continue;
const TargetInstrInfo &TII = *MF->getSubtarget().getInstrInfo();
const TargetRegisterInfo &TRI = *MF->getSubtarget().getRegisterInfo();
const MachineRegisterInfo &MRI = MF->getRegInfo();
auto VocabOrErr = MIRVocabulary::createDummyVocabForTest(TII, TRI, MRI, 1);
if (!VocabOrErr) {
WithColor::error(errs(), ToolName)
<< "Failed to create dummy vocabulary - "
<< toString(VocabOrErr.takeError()) << "\n";
return false;
}
Vocab = std::make_unique<MIRVocabulary>(std::move(*VocabOrErr));
return true;
}
WithColor::error(errs(), ToolName)
<< "No machine functions found to initialize vocabulary\n";
return false;
}
TripletResult MIR2VecTool::generateTriplets(const MachineFunction &MF) const {
TripletResult Result;
Result.MaxRelation = MIRNextRelation;
if (!Vocab) {
WithColor::error(errs(), ToolName)
<< "MIR Vocabulary must be initialized for triplet generation.\n";
return Result;
}
unsigned PrevOpcode = 0;
bool HasPrevOpcode = false;
for (const MachineBasicBlock &MBB : MF) {
for (const MachineInstr &MI : MBB) {
if (MI.isDebugInstr())
continue;
unsigned OpcodeID = Vocab->getEntityIDForOpcode(MI.getOpcode());
if (HasPrevOpcode) {
Result.Triplets.push_back({PrevOpcode, OpcodeID, MIRNextRelation});
LLVM_DEBUG(dbgs() << Vocab->getStringKey(PrevOpcode) << '\t'
<< Vocab->getStringKey(OpcodeID) << '\t' << "Next\n");
}
unsigned ArgIndex = 0;
for (const MachineOperand &MO : MI.operands()) {
auto OperandID = Vocab->getEntityIDForMachineOperand(MO);
unsigned RelationID = MIRArgRelation + ArgIndex;
Result.Triplets.push_back({OpcodeID, OperandID, RelationID});
LLVM_DEBUG({
std::string OperandStr = Vocab->getStringKey(OperandID);
dbgs() << Vocab->getStringKey(OpcodeID) << '\t' << OperandStr << '\t'
<< "Arg" << ArgIndex << '\n';
});
++ArgIndex;
}
if (ArgIndex > 0)
Result.MaxRelation =
std::max(Result.MaxRelation, MIRArgRelation + ArgIndex - 1);
PrevOpcode = OpcodeID;
HasPrevOpcode = true;
}
}
return Result;
}
TripletResult MIR2VecTool::generateTriplets(const Module &M) const {
TripletResult Result;
Result.MaxRelation = MIRNextRelation;
for (const Function &F : M.getFunctionDefs()) {
MachineFunction *MF = MMI.getMachineFunction(F);
if (!MF) {
WithColor::warning(errs(), ToolName)
<< "No MachineFunction for " << F.getName() << "\n";
continue;
}
TripletResult FuncResult = generateTriplets(*MF);
Result.MaxRelation = std::max(Result.MaxRelation, FuncResult.MaxRelation);
Result.Triplets.insert(Result.Triplets.end(), FuncResult.Triplets.begin(),
FuncResult.Triplets.end());
}
return Result;
}
void MIR2VecTool::writeTripletsToStream(const Module &M,
raw_ostream &OS) const {
auto Result = generateTriplets(M);
OS << "MAX_RELATION=" << Result.MaxRelation << '\n';
for (const auto &T : Result.Triplets)
OS << T.Head << '\t' << T.Tail << '\t' << T.Relation << '\n';
}
EntityList MIR2VecTool::collectEntityMappings() const {
if (!Vocab) {
WithColor::error(errs(), ToolName)
<< "Vocabulary must be initialized for entity mappings.\n";
return {};
}
const unsigned EntityCount = Vocab->getCanonicalSize();
EntityList Result;
for (unsigned EntityID = 0; EntityID < EntityCount; ++EntityID)
Result.push_back(Vocab->getStringKey(EntityID));
return Result;
}
void MIR2VecTool::writeEntitiesToStream(raw_ostream &OS) const {
auto Entities = collectEntityMappings();
if (Entities.empty())
return;
OS << Entities.size() << "\n";
for (unsigned EntityID = 0; EntityID < Entities.size(); ++EntityID)
OS << Entities[EntityID] << '\t' << EntityID << '\n';
}
void MIR2VecTool::writeEmbeddingsToStream(const Module &M, raw_ostream &OS,
EmbeddingLevel Level) const {
if (!Vocab) {
WithColor::error(errs(), ToolName) << "Vocabulary not initialized.\n";
return;
}
for (const Function &F : M.getFunctionDefs()) {
MachineFunction *MF = MMI.getMachineFunction(F);
if (!MF) {
WithColor::warning(errs(), ToolName)
<< "No MachineFunction for " << F.getName() << "\n";
continue;
}
writeEmbeddingsToStream(*MF, OS, Level);
}
}
void MIR2VecTool::writeEmbeddingsToStream(MachineFunction &MF, raw_ostream &OS,
EmbeddingLevel Level) const {
if (!Vocab) {
WithColor::error(errs(), ToolName) << "Vocabulary not initialized.\n";
return;
}
auto Emb = MIREmbedder::create(MIR2VecKind::Symbolic, MF, *Vocab);
if (!Emb) {
WithColor::error(errs(), ToolName)
<< "Failed to create embedder for " << MF.getName() << "\n";
return;
}
OS << "MIR2Vec embeddings for machine function " << MF.getName() << ":\n";
switch (Level) {
case FunctionLevel:
OS << "Function vector: ";
Emb->getMFunctionVector().print(OS);
break;
case BasicBlockLevel:
OS << "Basic block vectors:\n";
for (const MachineBasicBlock &MBB : MF) {
OS << "MBB " << MBB.getName() << ": ";
Emb->getMBBVector(MBB).print(OS);
}
break;
case InstructionLevel:
OS << "Instruction vectors:\n";
for (const MachineBasicBlock &MBB : MF) {
for (const MachineInstr &MI : MBB) {
OS << MI << " -> ";
Emb->getMInstVector(MI).print(OS);
}
}
break;
}
}
} // namespace mir2vec
} // namespace llvm