aboutsummaryrefslogtreecommitdiff
path: root/llvm/tools
diff options
context:
space:
mode:
Diffstat (limited to 'llvm/tools')
-rw-r--r--llvm/tools/llvm-dis/llvm-dis.cpp14
-rw-r--r--llvm/tools/llvm-ir2vec/CMakeLists.txt10
-rw-r--r--llvm/tools/llvm-ir2vec/llvm-ir2vec.cpp314
-rw-r--r--llvm/tools/llvm-mc/Disassembler.cpp6
-rw-r--r--llvm/tools/llvm-objdump/llvm-objdump.cpp180
-rw-r--r--llvm/tools/llvm-profdata/llvm-profdata.cpp50
-rw-r--r--llvm/tools/llvm-readobj/ELFDumper.cpp2
7 files changed, 459 insertions, 117 deletions
diff --git a/llvm/tools/llvm-dis/llvm-dis.cpp b/llvm/tools/llvm-dis/llvm-dis.cpp
index 422eb85..2b43d27 100644
--- a/llvm/tools/llvm-dis/llvm-dis.cpp
+++ b/llvm/tools/llvm-dis/llvm-dis.cpp
@@ -131,20 +131,6 @@ public:
printDebugLoc(DL,OS);
OS << "]";
}
- if (const DbgDeclareInst *DDI = dyn_cast<DbgDeclareInst>(I)) {
- if (!Padded) {
- OS.PadToColumn(50);
- OS << ";";
- }
- OS << " [debug variable = " << DDI->getVariable()->getName() << "]";
- }
- else if (const DbgValueInst *DVI = dyn_cast<DbgValueInst>(I)) {
- if (!Padded) {
- OS.PadToColumn(50);
- OS << ";";
- }
- OS << " [debug variable = " << DVI->getVariable()->getName() << "]";
- }
}
}
};
diff --git a/llvm/tools/llvm-ir2vec/CMakeLists.txt b/llvm/tools/llvm-ir2vec/CMakeLists.txt
new file mode 100644
index 0000000..a4cf969
--- /dev/null
+++ b/llvm/tools/llvm-ir2vec/CMakeLists.txt
@@ -0,0 +1,10 @@
+set(LLVM_LINK_COMPONENTS
+ Analysis
+ Core
+ IRReader
+ Support
+ )
+
+add_llvm_tool(llvm-ir2vec
+ llvm-ir2vec.cpp
+ )
diff --git a/llvm/tools/llvm-ir2vec/llvm-ir2vec.cpp b/llvm/tools/llvm-ir2vec/llvm-ir2vec.cpp
new file mode 100644
index 0000000..e1e5fad
--- /dev/null
+++ b/llvm/tools/llvm-ir2vec/llvm-ir2vec.cpp
@@ -0,0 +1,314 @@
+//===- llvm-ir2vec.cpp - IR2Vec Embedding Generation Tool -----------------===//
+//
+// 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 IR2Vec embedding generation tool.
+///
+/// This tool provides two main functionalities:
+///
+/// 1. Triplet Generation Mode (--mode=triplets):
+/// Generates triplets (opcode, type, operands) for vocabulary training.
+/// Usage: llvm-ir2vec --mode=triplets input.bc -o triplets.txt
+///
+/// 2. Embedding Generation Mode (--mode=embeddings):
+/// Generates IR2Vec embeddings using a trained vocabulary.
+/// Usage: llvm-ir2vec --mode=embeddings --ir2vec-vocab-path=vocab.json
+/// --level=func input.bc -o embeddings.txt Levels: --level=inst
+/// (instructions), --level=bb (basic blocks), --level=func (functions)
+/// (See IR2Vec.cpp for more embedding generation options)
+///
+//===----------------------------------------------------------------------===//
+
+#include "llvm/Analysis/IR2Vec.h"
+#include "llvm/IR/BasicBlock.h"
+#include "llvm/IR/Function.h"
+#include "llvm/IR/Instructions.h"
+#include "llvm/IR/LLVMContext.h"
+#include "llvm/IR/Module.h"
+#include "llvm/IR/PassInstrumentation.h"
+#include "llvm/IR/PassManager.h"
+#include "llvm/IR/Type.h"
+#include "llvm/IRReader/IRReader.h"
+#include "llvm/Support/CommandLine.h"
+#include "llvm/Support/Debug.h"
+#include "llvm/Support/Errc.h"
+#include "llvm/Support/InitLLVM.h"
+#include "llvm/Support/SourceMgr.h"
+#include "llvm/Support/raw_ostream.h"
+
+#define DEBUG_TYPE "ir2vec"
+
+namespace llvm {
+namespace ir2vec {
+
+static cl::OptionCategory IR2VecToolCategory("IR2Vec Tool Options");
+
+static cl::opt<std::string>
+ InputFilename(cl::Positional,
+ cl::desc("<input bitcode file or '-' for stdin>"),
+ cl::init("-"), cl::cat(IR2VecToolCategory));
+
+static cl::opt<std::string> OutputFilename("o", cl::desc("Output filename"),
+ cl::value_desc("filename"),
+ cl::init("-"),
+ cl::cat(IR2VecToolCategory));
+
+enum ToolMode {
+ TripletMode, // Generate triplets for vocabulary training
+ EmbeddingMode // Generate embeddings using trained vocabulary
+};
+
+static cl::opt<ToolMode>
+ Mode("mode", cl::desc("Tool operation mode:"),
+ cl::values(clEnumValN(TripletMode, "triplets",
+ "Generate triplets for vocabulary training"),
+ clEnumValN(EmbeddingMode, "embeddings",
+ "Generate embeddings using trained vocabulary")),
+ cl::init(EmbeddingMode), cl::cat(IR2VecToolCategory));
+
+static cl::opt<std::string>
+ FunctionName("function", cl::desc("Process specific function only"),
+ cl::value_desc("name"), cl::Optional, cl::init(""),
+ cl::cat(IR2VecToolCategory));
+
+enum EmbeddingLevel {
+ InstructionLevel, // Generate instruction-level embeddings
+ BasicBlockLevel, // Generate basic block-level embeddings
+ FunctionLevel // Generate function-level embeddings
+};
+
+static cl::opt<EmbeddingLevel>
+ Level("level", cl::desc("Embedding generation level (for embedding mode):"),
+ cl::values(clEnumValN(InstructionLevel, "inst",
+ "Generate instruction-level embeddings"),
+ clEnumValN(BasicBlockLevel, "bb",
+ "Generate basic block-level embeddings"),
+ clEnumValN(FunctionLevel, "func",
+ "Generate function-level embeddings")),
+ cl::init(FunctionLevel), cl::cat(IR2VecToolCategory));
+
+namespace {
+
+/// Helper class for collecting IR triplets and generating embeddings
+class IR2VecTool {
+private:
+ Module &M;
+ ModuleAnalysisManager MAM;
+ const Vocabulary *Vocab = nullptr;
+
+public:
+ explicit IR2VecTool(Module &M) : M(M) {}
+
+ /// Initialize the IR2Vec vocabulary analysis
+ bool initializeVocabulary() {
+ // Register and run the IR2Vec vocabulary analysis
+ // The vocabulary file path is specified via --ir2vec-vocab-path global
+ // option
+ MAM.registerPass([&] { return PassInstrumentationAnalysis(); });
+ MAM.registerPass([&] { return IR2VecVocabAnalysis(); });
+ Vocab = &MAM.getResult<IR2VecVocabAnalysis>(M);
+ return Vocab->isValid();
+ }
+
+ /// Generate triplets for the entire module
+ void generateTriplets(raw_ostream &OS) const {
+ for (const Function &F : M)
+ generateTriplets(F, OS);
+ }
+
+ /// Generate triplets for a single function
+ void generateTriplets(const Function &F, raw_ostream &OS) const {
+ if (F.isDeclaration())
+ return;
+
+ std::string LocalOutput;
+ raw_string_ostream LocalOS(LocalOutput);
+
+ for (const BasicBlock &BB : F)
+ traverseBasicBlock(BB, LocalOS);
+
+ LocalOS.flush();
+ OS << LocalOutput;
+ }
+
+ /// Generate embeddings for the entire module
+ void generateEmbeddings(raw_ostream &OS) const {
+ if (!Vocab->isValid()) {
+ OS << "Error: Vocabulary is not valid. IR2VecTool not initialized.\n";
+ return;
+ }
+
+ for (const Function &F : M)
+ generateEmbeddings(F, OS);
+ }
+
+ /// Generate embeddings for a single function
+ void generateEmbeddings(const Function &F, raw_ostream &OS) const {
+ if (F.isDeclaration()) {
+ OS << "Function " << F.getName() << " is a declaration, skipping.\n";
+ return;
+ }
+
+ // Create embedder for this function
+ assert(Vocab->isValid() && "Vocabulary is not valid");
+ auto Emb = Embedder::create(IR2VecKind::Symbolic, F, *Vocab);
+ if (!Emb) {
+ OS << "Error: Failed to create embedder for function " << F.getName()
+ << "\n";
+ return;
+ }
+
+ OS << "Function: " << F.getName() << "\n";
+
+ // Generate embeddings based on the specified level
+ switch (Level) {
+ case FunctionLevel: {
+ Emb->getFunctionVector().print(OS);
+ break;
+ }
+ case BasicBlockLevel: {
+ const auto &BBVecMap = Emb->getBBVecMap();
+ for (const BasicBlock &BB : F) {
+ auto It = BBVecMap.find(&BB);
+ if (It != BBVecMap.end()) {
+ OS << BB.getName() << ":";
+ It->second.print(OS);
+ }
+ }
+ break;
+ }
+ case InstructionLevel: {
+ const auto &InstMap = Emb->getInstVecMap();
+ for (const BasicBlock &BB : F) {
+ for (const Instruction &I : BB) {
+ auto It = InstMap.find(&I);
+ if (It != InstMap.end()) {
+ I.print(OS);
+ It->second.print(OS);
+ }
+ }
+ }
+ break;
+ }
+ }
+ }
+
+private:
+ /// Process a single basic block for triplet generation
+ void traverseBasicBlock(const BasicBlock &BB, raw_string_ostream &OS) const {
+ // Consider only non-debug and non-pseudo instructions
+ for (const auto &I : BB.instructionsWithoutDebug()) {
+ StringRef OpcStr = Vocabulary::getVocabKeyForOpcode(I.getOpcode());
+ StringRef TypeStr =
+ Vocabulary::getVocabKeyForTypeID(I.getType()->getTypeID());
+
+ OS << '\n' << OpcStr << ' ' << TypeStr << ' ';
+
+ LLVM_DEBUG({
+ I.print(dbgs());
+ dbgs() << "\n";
+ I.getType()->print(dbgs());
+ dbgs() << " Type\n";
+ });
+
+ for (const Use &U : I.operands())
+ OS << Vocabulary::getVocabKeyForOperandKind(
+ Vocabulary::getOperandKind(U.get()))
+ << ' ';
+ }
+ }
+};
+
+Error processModule(Module &M, raw_ostream &OS) {
+ IR2VecTool Tool(M);
+
+ if (Mode == EmbeddingMode) {
+ // Initialize vocabulary for embedding generation
+ // Note: Requires --ir2vec-vocab-path option to be set
+ if (!Tool.initializeVocabulary())
+ return createStringError(
+ errc::invalid_argument,
+ "Failed to initialize IR2Vec vocabulary. "
+ "Make sure to specify --ir2vec-vocab-path for embedding mode.");
+
+ if (!FunctionName.empty()) {
+ // Process single function
+ if (const Function *F = M.getFunction(FunctionName))
+ Tool.generateEmbeddings(*F, OS);
+ else
+ return createStringError(errc::invalid_argument,
+ "Function '%s' not found",
+ FunctionName.c_str());
+ } else {
+ // Process all functions
+ Tool.generateEmbeddings(OS);
+ }
+ } else {
+ // Triplet generation mode - no vocabulary needed
+ if (!FunctionName.empty())
+ // Process single function
+ if (const Function *F = M.getFunction(FunctionName))
+ Tool.generateTriplets(*F, OS);
+ else
+ return createStringError(errc::invalid_argument,
+ "Function '%s' not found",
+ FunctionName.c_str());
+ else
+ // Process all functions
+ Tool.generateTriplets(OS);
+ }
+ return Error::success();
+}
+} // namespace
+} // namespace ir2vec
+} // namespace llvm
+
+int main(int argc, char **argv) {
+ using namespace llvm;
+ using namespace llvm::ir2vec;
+
+ InitLLVM X(argc, argv);
+ cl::HideUnrelatedOptions(IR2VecToolCategory);
+ cl::ParseCommandLineOptions(
+ argc, argv,
+ "IR2Vec - Embedding Generation Tool\n"
+ "Generates embeddings for a given LLVM IR and "
+ "supports triplet generation for vocabulary "
+ "training and embedding generation.\n\n"
+ "See https://llvm.org/docs/CommandGuide/llvm-ir2vec.html for more "
+ "information.\n");
+
+ // Validate command line options
+ if (Mode == TripletMode && Level.getNumOccurrences() > 0)
+ errs() << "Warning: --level option is ignored in triplet mode\n";
+
+ // Parse the input LLVM IR file or stdin
+ SMDiagnostic Err;
+ LLVMContext Context;
+ std::unique_ptr<Module> M = parseIRFile(InputFilename, Err, Context);
+ if (!M) {
+ Err.print(argv[0], errs());
+ return 1;
+ }
+
+ std::error_code EC;
+ raw_fd_ostream OS(OutputFilename, EC);
+ if (EC) {
+ errs() << "Error opening output file: " << EC.message() << "\n";
+ return 1;
+ }
+
+ if (Error Err = processModule(*M, OS)) {
+ handleAllErrors(std::move(Err), [&](const ErrorInfoBase &EIB) {
+ errs() << "Error: " << EIB.message() << "\n";
+ });
+ return 1;
+ }
+
+ return 0;
+}
diff --git a/llvm/tools/llvm-mc/Disassembler.cpp b/llvm/tools/llvm-mc/Disassembler.cpp
index 607184e..8672793 100644
--- a/llvm/tools/llvm-mc/Disassembler.cpp
+++ b/llvm/tools/llvm-mc/Disassembler.cpp
@@ -45,7 +45,11 @@ static bool PrintInsts(const MCDisassembler &DisAsm, const ByteArrayTy &Bytes,
MCInst Inst;
MCDisassembler::DecodeStatus S;
- S = DisAsm.getInstruction(Inst, Size, Data.slice(Index), Index, nulls());
+ if (STI.getTargetTriple().getArch() == Triple::hexagon)
+ S = DisAsm.getInstructionBundle(Inst, Size, Data.slice(Index), Index,
+ nulls());
+ else
+ S = DisAsm.getInstruction(Inst, Size, Data.slice(Index), Index, nulls());
switch (S) {
case MCDisassembler::Fail:
SM.PrintMessage(SMLoc::getFromPointer(Bytes.second[Index]),
diff --git a/llvm/tools/llvm-objdump/llvm-objdump.cpp b/llvm/tools/llvm-objdump/llvm-objdump.cpp
index c5967cd..74eb903 100644
--- a/llvm/tools/llvm-objdump/llvm-objdump.cpp
+++ b/llvm/tools/llvm-objdump/llvm-objdump.cpp
@@ -693,6 +693,30 @@ public:
} else
OS << "\t<unknown>";
}
+
+ virtual void emitPostInstructionInfo(formatted_raw_ostream &FOS,
+ const MCAsmInfo &MAI,
+ const MCSubtargetInfo &STI,
+ StringRef Comments,
+ LiveVariablePrinter &LVP) {
+ do {
+ if (!Comments.empty()) {
+ // Emit a line of comments.
+ StringRef Comment;
+ std::tie(Comment, Comments) = Comments.split('\n');
+ // MAI.getCommentColumn() assumes that instructions are printed at the
+ // position of 8, while getInstStartColumn() returns the actual
+ // position.
+ unsigned CommentColumn =
+ MAI.getCommentColumn() - 8 + getInstStartColumn(STI);
+ FOS.PadToColumn(CommentColumn);
+ FOS << MAI.getCommentString() << ' ' << Comment;
+ }
+ LVP.printAfterInst(FOS);
+ FOS << "\n";
+ } while (!Comments.empty());
+ FOS.flush();
+ }
};
PrettyPrinter PrettyPrinterInst;
@@ -714,6 +738,35 @@ public:
}
}
}
+
+ std::string getInstructionSeparator() const {
+ SmallString<40> Separator;
+ raw_svector_ostream OS(Separator);
+ if (ShouldClosePacket) {
+ OS << " }";
+ if (IsLoop0 || IsLoop1)
+ OS << " ";
+ if (IsLoop0)
+ OS << (IsLoop1 ? ":endloop01" : ":endloop0");
+ else if (IsLoop1)
+ OS << ":endloop1";
+ }
+ OS << '\n';
+ return OS.str().str();
+ }
+
+ void emitPostInstructionInfo(formatted_raw_ostream &FOS, const MCAsmInfo &MAI,
+ const MCSubtargetInfo &STI, StringRef Comments,
+ LiveVariablePrinter &LVP) override {
+ // Hexagon does not write anything to the comment stream, so we can just
+ // print the separator.
+ LVP.printAfterInst(FOS);
+ FOS << getInstructionSeparator();
+ FOS.flush();
+ if (ShouldClosePacket)
+ reset();
+ }
+
void printInst(MCInstPrinter &IP, const MCInst *MI, ArrayRef<uint8_t> Bytes,
object::SectionedAddress Address, formatted_raw_ostream &OS,
StringRef Annot, MCSubtargetInfo const &STI, SourcePrinter *SP,
@@ -724,60 +777,64 @@ public:
if (!MI) {
printLead(Bytes, Address.Address, OS);
OS << " <unknown>";
+ reset();
return;
}
- std::string Buffer;
+
+ StringRef Preamble = IsStartOfBundle ? " { " : " ";
+
+ if (SP && (PrintSource || PrintLines))
+ SP->printSourceLine(OS, Address, ObjectFilename, LVP, "");
+ printLead(Bytes, Address.Address, OS);
+ OS << Preamble;
+ std::string Buf;
{
- raw_string_ostream TempStream(Buffer);
+ raw_string_ostream TempStream(Buf);
IP.printInst(MI, Address.Address, "", STI, TempStream);
}
- StringRef Contents(Buffer);
- // Split off bundle attributes
- auto PacketBundle = Contents.rsplit('\n');
- // Split off first instruction from the rest
- auto HeadTail = PacketBundle.first.split('\n');
- auto Preamble = " { ";
- auto Separator = "";
-
- // Hexagon's packets require relocations to be inline rather than
- // clustered at the end of the packet.
- std::vector<RelocationRef>::const_iterator RelCur = Rels->begin();
- std::vector<RelocationRef>::const_iterator RelEnd = Rels->end();
- auto PrintReloc = [&]() -> void {
- while ((RelCur != RelEnd) && (RelCur->getOffset() <= Address.Address)) {
- if (RelCur->getOffset() == Address.Address) {
- printRelocation(OS, ObjectFilename, *RelCur, Address.Address, false);
- return;
- }
- ++RelCur;
- }
- };
+ StringRef Contents(Buf);
+
+ auto Duplex = Contents.split('\v');
+ bool HasDuplex = !Duplex.second.empty();
+ if (HasDuplex) {
+ OS << Duplex.first;
+ OS << "; ";
+ OS << Duplex.second;
+ } else {
+ OS << Duplex.first;
+ }
- while (!HeadTail.first.empty()) {
- OS << Separator;
- Separator = "\n";
- if (SP && (PrintSource || PrintLines))
- SP->printSourceLine(OS, Address, ObjectFilename, LVP, "");
- printLead(Bytes, Address.Address, OS);
- OS << Preamble;
- Preamble = " ";
- StringRef Inst;
- auto Duplex = HeadTail.first.split('\v');
- if (!Duplex.second.empty()) {
- OS << Duplex.first;
- OS << "; ";
- Inst = Duplex.second;
- }
+ uint32_t Instruction = support::endian::read32le(Bytes.data());
+
+ uint32_t ParseMask = 0x0000c000;
+ uint32_t PacketEndMask = 0x0000c000;
+ uint32_t LoopEndMask = 0x00008000;
+ uint32_t ParseBits = Instruction & ParseMask;
+
+ if (ParseBits == LoopEndMask) {
+ if (IsStartOfBundle)
+ IsLoop0 = true;
else
- Inst = HeadTail.first;
- OS << Inst;
- HeadTail = HeadTail.second.split('\n');
- if (HeadTail.first.empty())
- OS << " } " << PacketBundle.second;
- PrintReloc();
- Bytes = Bytes.slice(4);
- Address.Address += 4;
+ IsLoop1 = true;
}
+
+ IsStartOfBundle = false;
+
+ if (ParseBits == PacketEndMask || HasDuplex)
+ ShouldClosePacket = true;
+ }
+
+private:
+ bool IsStartOfBundle = true;
+ bool IsLoop0 = false;
+ bool IsLoop1 = false;
+ bool ShouldClosePacket = false;
+
+ void reset() {
+ IsStartOfBundle = true;
+ IsLoop0 = false;
+ IsLoop1 = false;
+ ShouldClosePacket = false;
}
};
HexagonPrettyPrinter HexagonPrettyPrinterInst;
@@ -1610,29 +1667,6 @@ static StringRef getSegmentName(const MachOObjectFile *MachO,
return "";
}
-static void emitPostInstructionInfo(formatted_raw_ostream &FOS,
- const MCAsmInfo &MAI,
- const MCSubtargetInfo &STI,
- StringRef Comments,
- LiveVariablePrinter &LVP) {
- do {
- if (!Comments.empty()) {
- // Emit a line of comments.
- StringRef Comment;
- std::tie(Comment, Comments) = Comments.split('\n');
- // MAI.getCommentColumn() assumes that instructions are printed at the
- // position of 8, while getInstStartColumn() returns the actual position.
- unsigned CommentColumn =
- MAI.getCommentColumn() - 8 + getInstStartColumn(STI);
- FOS.PadToColumn(CommentColumn);
- FOS << MAI.getCommentString() << ' ' << Comment;
- }
- LVP.printAfterInst(FOS);
- FOS << '\n';
- } while (!Comments.empty());
- FOS.flush();
-}
-
static void createFakeELFSections(ObjectFile &Obj) {
assert(Obj.isELF());
if (auto *Elf32LEObj = dyn_cast<ELF32LEObjectFile>(&Obj))
@@ -2526,15 +2560,15 @@ disassembleObject(ObjectFile &Obj, const ObjectFile &DbgObj,
}
assert(DT->Context->getAsmInfo());
- emitPostInstructionInfo(FOS, *DT->Context->getAsmInfo(),
- *DT->SubtargetInfo, CommentStream.str(), LVP);
+ DT->Printer->emitPostInstructionInfo(FOS, *DT->Context->getAsmInfo(),
+ *DT->SubtargetInfo,
+ CommentStream.str(), LVP);
Comments.clear();
if (BTF)
printBTFRelocation(FOS, *BTF, {Index, Section.getIndex()}, LVP);
- // Hexagon handles relocs in pretty printer
- if (InlineRelocs && Obj.getArch() != Triple::hexagon) {
+ if (InlineRelocs) {
while (findRel()) {
// When --adjust-vma is used, update the address printed.
printRelocation(FOS, Obj.getFileName(), *RelCur,
diff --git a/llvm/tools/llvm-profdata/llvm-profdata.cpp b/llvm/tools/llvm-profdata/llvm-profdata.cpp
index 45eac90..207ae2d 100644
--- a/llvm/tools/llvm-profdata/llvm-profdata.cpp
+++ b/llvm/tools/llvm-profdata/llvm-profdata.cpp
@@ -47,7 +47,6 @@
#include <algorithm>
#include <cmath>
#include <optional>
-#include <queue>
using namespace llvm;
using ProfCorrelatorKind = InstrProfCorrelator::ProfCorrelatorKind;
@@ -2849,9 +2848,8 @@ static int showInstrProfile(ShowFormat SFormat, raw_fd_ostream &OS) {
auto FS = vfs::getRealFileSystem();
auto ReaderOrErr = InstrProfReader::create(Filename, *FS);
std::vector<uint32_t> Cutoffs = std::move(DetailedSummaryCutoffs);
- if (ShowDetailedSummary && Cutoffs.empty()) {
+ if (Cutoffs.empty() && (ShowDetailedSummary || ShowHotFuncList))
Cutoffs = ProfileSummaryBuilder::DefaultCutoffs;
- }
InstrProfSummaryBuilder Builder(std::move(Cutoffs));
if (Error E = ReaderOrErr.takeError())
exitWithError(std::move(E), Filename);
@@ -2863,15 +2861,7 @@ static int showInstrProfile(ShowFormat SFormat, raw_fd_ostream &OS) {
int NumVPKind = IPVK_Last - IPVK_First + 1;
std::vector<ValueSitesStats> VPStats(NumVPKind);
- auto MinCmp = [](const std::pair<std::string, uint64_t> &v1,
- const std::pair<std::string, uint64_t> &v2) {
- return v1.second > v2.second;
- };
-
- std::priority_queue<std::pair<std::string, uint64_t>,
- std::vector<std::pair<std::string, uint64_t>>,
- decltype(MinCmp)>
- HottestFuncs(MinCmp);
+ std::vector<std::pair<StringRef, uint64_t>> NameAndMaxCount;
if (!TextFormat && OnlyListBelow) {
OS << "The list of functions with the maximum counter less than "
@@ -2946,15 +2936,8 @@ static int showInstrProfile(ShowFormat SFormat, raw_fd_ostream &OS) {
} else if (OnlyListBelow)
continue;
- if (TopNFunctions) {
- if (HottestFuncs.size() == TopNFunctions) {
- if (HottestFuncs.top().second < FuncMax) {
- HottestFuncs.pop();
- HottestFuncs.emplace(std::make_pair(std::string(Func.Name), FuncMax));
- }
- } else
- HottestFuncs.emplace(std::make_pair(std::string(Func.Name), FuncMax));
- }
+ if (TopNFunctions || ShowHotFuncList)
+ NameAndMaxCount.emplace_back(Func.Name, FuncMax);
if (Show) {
if (!ShownFunctions)
@@ -3034,16 +3017,27 @@ static int showInstrProfile(ShowFormat SFormat, raw_fd_ostream &OS) {
<< "): " << PS->getNumFunctions() - BelowCutoffFunctions << "\n";
}
+ // Sort by MaxCount in decreasing order
+ llvm::stable_sort(NameAndMaxCount, [](const auto &L, const auto &R) {
+ return L.second > R.second;
+ });
if (TopNFunctions) {
- std::vector<std::pair<std::string, uint64_t>> SortedHottestFuncs;
- while (!HottestFuncs.empty()) {
- SortedHottestFuncs.emplace_back(HottestFuncs.top());
- HottestFuncs.pop();
- }
OS << "Top " << TopNFunctions
<< " functions with the largest internal block counts: \n";
- for (auto &hotfunc : llvm::reverse(SortedHottestFuncs))
- OS << " " << hotfunc.first << ", max count = " << hotfunc.second << "\n";
+ auto TopFuncs = ArrayRef(NameAndMaxCount).take_front(TopNFunctions);
+ for (auto [Name, MaxCount] : TopFuncs)
+ OS << " " << Name << ", max count = " << MaxCount << "\n";
+ }
+
+ if (ShowHotFuncList) {
+ auto HotCountThreshold =
+ ProfileSummaryBuilder::getHotCountThreshold(PS->getDetailedSummary());
+ OS << "# Hot count threshold: " << HotCountThreshold << "\n";
+ for (auto [Name, MaxCount] : NameAndMaxCount) {
+ if (MaxCount < HotCountThreshold)
+ break;
+ OS << Name << "\n";
+ }
}
if (ShownFunctions && ShowIndirectCallTargets) {
diff --git a/llvm/tools/llvm-readobj/ELFDumper.cpp b/llvm/tools/llvm-readobj/ELFDumper.cpp
index 465c1896..ccc64fe 100644
--- a/llvm/tools/llvm-readobj/ELFDumper.cpp
+++ b/llvm/tools/llvm-readobj/ELFDumper.cpp
@@ -5511,7 +5511,7 @@ template <typename ELFT> static GNUAbiTag getGNUAbiTag(ArrayRef<uint8_t> Desc) {
return {"", "", /*IsValid=*/false};
static const char *OSNames[] = {
- "Linux", "Hurd", "Solaris", "FreeBSD", "NetBSD", "Syllable", "NaCl",
+ "Linux", "Hurd", "Solaris", "FreeBSD", "NetBSD", "Syllable",
};
StringRef OSName = "Unknown";
if (Words[0] < std::size(OSNames))