aboutsummaryrefslogtreecommitdiff
path: root/llvm/tools
diff options
context:
space:
mode:
Diffstat (limited to 'llvm/tools')
-rw-r--r--llvm/tools/llvm-ir2vec/llvm-ir2vec.cpp65
-rw-r--r--llvm/tools/llvm-objdump/CMakeLists.txt1
-rw-r--r--llvm/tools/llvm-objdump/COFFDump.cpp2
-rw-r--r--llvm/tools/llvm-objdump/DXContainerDump.cpp30
-rw-r--r--llvm/tools/llvm-objdump/llvm-objdump.cpp5
-rw-r--r--llvm/tools/llvm-objdump/llvm-objdump.h3
-rw-r--r--llvm/tools/llvm-readobj/ELFDumper.cpp2
-rw-r--r--llvm/tools/llvm-reduce/deltas/ReduceOperands.cpp3
-rw-r--r--llvm/tools/llvm-split/CMakeLists.txt1
-rw-r--r--llvm/tools/llvm-split/llvm-split.cpp176
-rw-r--r--llvm/tools/opt/optdriver.cpp3
11 files changed, 250 insertions, 41 deletions
diff --git a/llvm/tools/llvm-ir2vec/llvm-ir2vec.cpp b/llvm/tools/llvm-ir2vec/llvm-ir2vec.cpp
index f6ed94b..8e17a4a 100644
--- a/llvm/tools/llvm-ir2vec/llvm-ir2vec.cpp
+++ b/llvm/tools/llvm-ir2vec/llvm-ir2vec.cpp
@@ -9,22 +9,22 @@
/// \file
/// This file implements the IR2Vec embedding generation tool.
///
-/// This tool provides three main modes:
+/// This tool provides three main subcommands:
///
-/// 1. Triplet Generation Mode (--mode=triplets):
+/// 1. Triplet Generation (triplets):
/// Generates numeric triplets (head, tail, relation) for vocabulary
/// training. Output format: MAX_RELATION=N header followed by
/// head\ttail\trelation lines. Relations: 0=Type, 1=Next, 2+=Arg0,Arg1,...
-/// Usage: llvm-ir2vec --mode=triplets input.bc -o train2id.txt
+/// Usage: llvm-ir2vec triplets input.bc -o train2id.txt
///
-/// 2. Entities Generation Mode (--mode=entities):
+/// 2. Entity Mappings (entities):
/// Generates entity mappings for vocabulary training.
/// Output format: <total_entities> header followed by entity\tid lines.
-/// Usage: llvm-ir2vec --mode=entities input.bc -o entity2id.txt
+/// Usage: llvm-ir2vec entities input.bc -o entity2id.txt
///
-/// 3. Embedding Generation Mode (--mode=embeddings):
+/// 3. Embedding Generation (embeddings):
/// Generates IR2Vec embeddings using a trained vocabulary.
-/// Usage: llvm-ir2vec --mode=embeddings --ir2vec-vocab-path=vocab.json
+/// Usage: llvm-ir2vec 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)
@@ -55,36 +55,33 @@ namespace ir2vec {
static cl::OptionCategory IR2VecToolCategory("IR2Vec Tool Options");
+// Subcommands
+static cl::SubCommand
+ TripletsSubCmd("triplets", "Generate triplets for vocabulary training");
+static cl::SubCommand
+ EntitiesSubCmd("entities",
+ "Generate entity mappings for vocabulary training");
+static cl::SubCommand
+ EmbeddingsSubCmd("embeddings",
+ "Generate embeddings using trained vocabulary");
+
+// Common options
static cl::opt<std::string>
InputFilename(cl::Positional,
cl::desc("<input bitcode file or '-' for stdin>"),
- cl::init("-"), cl::cat(IR2VecToolCategory));
+ cl::init("-"), cl::sub(TripletsSubCmd),
+ cl::sub(EmbeddingsSubCmd), 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
- EntityMode, // Generate entity mappings 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(EntityMode, "entities",
- "Generate entity mappings for vocabulary training"),
- clEnumValN(EmbeddingMode, "embeddings",
- "Generate embeddings using trained vocabulary")),
- cl::init(EmbeddingMode), cl::cat(IR2VecToolCategory));
-
+// Embedding-specific options
static cl::opt<std::string>
FunctionName("function", cl::desc("Process specific function only"),
cl::value_desc("name"), cl::Optional, cl::init(""),
- cl::cat(IR2VecToolCategory));
+ cl::sub(EmbeddingsSubCmd), cl::cat(IR2VecToolCategory));
enum EmbeddingLevel {
InstructionLevel, // Generate instruction-level embeddings
@@ -93,14 +90,15 @@ enum EmbeddingLevel {
};
static cl::opt<EmbeddingLevel>
- Level("level", cl::desc("Embedding generation level (for embedding mode):"),
+ Level("level", cl::desc("Embedding generation level:"),
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));
+ cl::init(FunctionLevel), cl::sub(EmbeddingsSubCmd),
+ cl::cat(IR2VecToolCategory));
namespace {
@@ -291,7 +289,7 @@ public:
Error processModule(Module &M, raw_ostream &OS) {
IR2VecTool Tool(M);
- if (Mode == EmbeddingMode) {
+ if (EmbeddingsSubCmd) {
// Initialize vocabulary for embedding generation
// Note: Requires --ir2vec-vocab-path option to be set
auto VocabStatus = Tool.initializeVocabulary();
@@ -311,6 +309,7 @@ Error processModule(Module &M, raw_ostream &OS) {
Tool.generateEmbeddings(OS);
}
} else {
+ // Both triplets and entities use triplet generation
Tool.generateTriplets(OS);
}
return Error::success();
@@ -334,14 +333,6 @@ int main(int argc, char **argv) {
"See https://llvm.org/docs/CommandGuide/llvm-ir2vec.html for more "
"information.\n");
- // Validate command line options
- if (Mode != EmbeddingMode) {
- if (Level.getNumOccurrences() > 0)
- errs() << "Warning: --level option is ignored\n";
- if (FunctionName.getNumOccurrences() > 0)
- errs() << "Warning: --function option is ignored\n";
- }
-
std::error_code EC;
raw_fd_ostream OS(OutputFilename, EC);
if (EC) {
@@ -349,7 +340,7 @@ int main(int argc, char **argv) {
return 1;
}
- if (Mode == EntityMode) {
+ if (EntitiesSubCmd) {
// Just dump entity mappings without processing any IR
IR2VecTool::generateEntityMappings(OS);
return 0;
diff --git a/llvm/tools/llvm-objdump/CMakeLists.txt b/llvm/tools/llvm-objdump/CMakeLists.txt
index 7e3197f..41d301c 100644
--- a/llvm/tools/llvm-objdump/CMakeLists.txt
+++ b/llvm/tools/llvm-objdump/CMakeLists.txt
@@ -28,6 +28,7 @@ add_llvm_tool(llvm-objdump
llvm-objdump.cpp
SourcePrinter.cpp
COFFDump.cpp
+ DXContainerDump.cpp
ELFDump.cpp
MachODump.cpp
OffloadDump.cpp
diff --git a/llvm/tools/llvm-objdump/COFFDump.cpp b/llvm/tools/llvm-objdump/COFFDump.cpp
index b22c9a4..de82561 100644
--- a/llvm/tools/llvm-objdump/COFFDump.cpp
+++ b/llvm/tools/llvm-objdump/COFFDump.cpp
@@ -187,7 +187,7 @@ void COFFDumper::printPEHeader(const PEHeader &Hdr) const {
Size = Data->Size;
}
outs() << format("Entry %x ", I) << formatAddr(Addr)
- << format(" %08x %s\n", uint32_t(Size), DirName[I]);
+ << format(" %08x %s\n", Size, DirName[I]);
}
}
diff --git a/llvm/tools/llvm-objdump/DXContainerDump.cpp b/llvm/tools/llvm-objdump/DXContainerDump.cpp
new file mode 100644
index 0000000..2fb0734
--- /dev/null
+++ b/llvm/tools/llvm-objdump/DXContainerDump.cpp
@@ -0,0 +1,30 @@
+//===----------------------------------------------------------------------===//
+//
+// 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 DXContainer-specific dumper for llvm-objdump.
+///
+//===----------------------------------------------------------------------===//
+
+#include "llvm-objdump.h"
+#include "llvm/Object/DXContainer.h"
+
+using namespace llvm;
+
+namespace {
+class DXContainerDumper : public objdump::Dumper {
+public:
+ DXContainerDumper(const object::DXContainerObjectFile &Obj)
+ : objdump::Dumper(Obj) {}
+};
+} // namespace
+
+std::unique_ptr<objdump::Dumper> llvm::objdump::createDXContainerDumper(
+ const object::DXContainerObjectFile &Obj) {
+ return std::make_unique<DXContainerDumper>(Obj);
+}
diff --git a/llvm/tools/llvm-objdump/llvm-objdump.cpp b/llvm/tools/llvm-objdump/llvm-objdump.cpp
index 0316c4b..c19c698 100644
--- a/llvm/tools/llvm-objdump/llvm-objdump.cpp
+++ b/llvm/tools/llvm-objdump/llvm-objdump.cpp
@@ -50,6 +50,7 @@
#include "llvm/Object/BuildID.h"
#include "llvm/Object/COFF.h"
#include "llvm/Object/COFFImportFile.h"
+#include "llvm/Object/DXContainer.h"
#include "llvm/Object/ELFObjectFile.h"
#include "llvm/Object/ELFTypes.h"
#include "llvm/Object/FaultMapParser.h"
@@ -386,6 +387,8 @@ static Expected<std::unique_ptr<Dumper>> createDumper(const ObjectFile &Obj) {
return createWasmDumper(*O);
if (const auto *O = dyn_cast<XCOFFObjectFile>(&Obj))
return createXCOFFDumper(*O);
+ if (const auto *O = dyn_cast<DXContainerObjectFile>(&Obj))
+ return createDXContainerDumper(*O);
return createStringError(errc::invalid_argument,
"unsupported object file format");
@@ -2736,7 +2739,7 @@ void Dumper::printRelocations() {
for (const SectionRef &Section : ToolSectionFilter(O, &Ndx)) {
if (O.isELF() && (ELFSectionRef(Section).getFlags() & ELF::SHF_ALLOC))
continue;
- if (Section.relocation_begin() == Section.relocation_end())
+ if (Section.relocations().empty())
continue;
Expected<section_iterator> SecOrErr = Section.getRelocatedSection();
if (!SecOrErr)
diff --git a/llvm/tools/llvm-objdump/llvm-objdump.h b/llvm/tools/llvm-objdump/llvm-objdump.h
index ce06429..3525be9 100644
--- a/llvm/tools/llvm-objdump/llvm-objdump.h
+++ b/llvm/tools/llvm-objdump/llvm-objdump.h
@@ -36,6 +36,7 @@ class ELFObjectFileBase;
class MachOObjectFile;
class WasmObjectFile;
class XCOFFObjectFile;
+class DXContainer;
} // namespace object
namespace objdump {
@@ -105,6 +106,8 @@ std::unique_ptr<Dumper> createELFDumper(const object::ELFObjectFileBase &Obj);
std::unique_ptr<Dumper> createMachODumper(const object::MachOObjectFile &Obj);
std::unique_ptr<Dumper> createWasmDumper(const object::WasmObjectFile &Obj);
std::unique_ptr<Dumper> createXCOFFDumper(const object::XCOFFObjectFile &Obj);
+std::unique_ptr<Dumper>
+createDXContainerDumper(const object::DXContainerObjectFile &Obj);
// Various helper functions.
diff --git a/llvm/tools/llvm-readobj/ELFDumper.cpp b/llvm/tools/llvm-readobj/ELFDumper.cpp
index 66153ad..26a84fa 100644
--- a/llvm/tools/llvm-readobj/ELFDumper.cpp
+++ b/llvm/tools/llvm-readobj/ELFDumper.cpp
@@ -2215,7 +2215,7 @@ template <typename ELFT> void ELFDumper<ELFT>::parseDynamicTable() {
const uint64_t FileSize = Obj.getBufSize();
const uint64_t DerivedSize =
(uint64_t)HashTable->nchain * DynSymRegion->EntSize;
- const uint64_t Offset = (const uint8_t *)DynSymRegion->Addr - Obj.base();
+ const uint64_t Offset = DynSymRegion->Addr - Obj.base();
if (DerivedSize > FileSize - Offset)
reportUniqueWarning(
"the size (0x" + Twine::utohexstr(DerivedSize) +
diff --git a/llvm/tools/llvm-reduce/deltas/ReduceOperands.cpp b/llvm/tools/llvm-reduce/deltas/ReduceOperands.cpp
index 8b64467..79272fe 100644
--- a/llvm/tools/llvm-reduce/deltas/ReduceOperands.cpp
+++ b/llvm/tools/llvm-reduce/deltas/ReduceOperands.cpp
@@ -73,6 +73,9 @@ static bool shouldReduceOperand(Use &Op) {
if (&CB->getCalledOperandUse() == &Op)
return false;
}
+ // lifetime intrinsic argument must be an alloca.
+ if (isa<LifetimeIntrinsic>(Op.getUser()))
+ return false;
return true;
}
diff --git a/llvm/tools/llvm-split/CMakeLists.txt b/llvm/tools/llvm-split/CMakeLists.txt
index 1104e31..b755755 100644
--- a/llvm/tools/llvm-split/CMakeLists.txt
+++ b/llvm/tools/llvm-split/CMakeLists.txt
@@ -12,6 +12,7 @@ set(LLVM_LINK_COMPONENTS
Support
Target
TargetParser
+ ipo
)
add_llvm_tool(llvm-split
diff --git a/llvm/tools/llvm-split/llvm-split.cpp b/llvm/tools/llvm-split/llvm-split.cpp
index 9f6678a..97713c4 100644
--- a/llvm/tools/llvm-split/llvm-split.cpp
+++ b/llvm/tools/llvm-split/llvm-split.cpp
@@ -11,14 +11,19 @@
//
//===----------------------------------------------------------------------===//
+#include "llvm/ADT/SmallString.h"
+#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/Bitcode/BitcodeWriter.h"
#include "llvm/IR/LLVMContext.h"
+#include "llvm/IR/PassInstrumentation.h"
+#include "llvm/IR/PassManager.h"
#include "llvm/IR/Verifier.h"
#include "llvm/IRReader/IRReader.h"
#include "llvm/MC/TargetRegistry.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/FileSystem.h"
+#include "llvm/Support/FormatVariadic.h"
#include "llvm/Support/InitLLVM.h"
#include "llvm/Support/SourceMgr.h"
#include "llvm/Support/TargetSelect.h"
@@ -27,7 +32,9 @@
#include "llvm/Support/raw_ostream.h"
#include "llvm/Target/TargetMachine.h"
#include "llvm/TargetParser/Triple.h"
+#include "llvm/Transforms/IPO/GlobalDCE.h"
#include "llvm/Transforms/Utils/SplitModule.h"
+#include "llvm/Transforms/Utils/SplitModuleByCategory.h"
using namespace llvm;
@@ -70,6 +77,164 @@ static cl::opt<std::string>
MCPU("mcpu", cl::desc("Target CPU, ignored if --mtriple is not used"),
cl::value_desc("cpu"), cl::cat(SplitCategory));
+enum class SplitByCategoryType {
+ SBCT_ByModuleId,
+ SBCT_ByKernel,
+ SBCT_None,
+};
+
+static cl::opt<SplitByCategoryType> SplitByCategory(
+ "split-by-category",
+ cl::desc("Split by category. If present, splitting by category is used "
+ "with the specified categorization type."),
+ cl::Optional, cl::init(SplitByCategoryType::SBCT_None),
+ cl::values(clEnumValN(SplitByCategoryType::SBCT_ByModuleId, "module-id",
+ "one output module per translation unit marked with "
+ "\"module-id\" attribute"),
+ clEnumValN(SplitByCategoryType::SBCT_ByKernel, "kernel",
+ "one output module per kernel")),
+ cl::cat(SplitCategory));
+
+static cl::opt<bool> OutputAssembly{
+ "S", cl::desc("Write output as LLVM assembly"), cl::cat(SplitCategory)};
+
+void writeStringToFile(StringRef Content, StringRef Path) {
+ std::error_code EC;
+ raw_fd_ostream OS(Path, EC);
+ if (EC) {
+ errs() << formatv("error opening file: {0}, error: {1}\n", Path,
+ EC.message());
+ exit(1);
+ }
+
+ OS << Content << "\n";
+}
+
+void writeModuleToFile(const Module &M, StringRef Path, bool OutputAssembly) {
+ int FD = -1;
+ if (std::error_code EC = sys::fs::openFileForWrite(Path, FD)) {
+ errs() << formatv("error opening file: {0}, error: {1}", Path, EC.message())
+ << '\n';
+ exit(1);
+ }
+
+ raw_fd_ostream OS(FD, /*ShouldClose*/ true);
+ if (OutputAssembly)
+ M.print(OS, /*AssemblyAnnotationWriter*/ nullptr);
+ else
+ WriteBitcodeToFile(M, OS);
+}
+
+/// EntryPointCategorizer is used for splitting by category either by module-id
+/// or by kernels. It doesn't provide categories for functions other than
+/// kernels. Categorizer computes a string key for the given Function and
+/// records the association between the string key and an integer category. If a
+/// string key is already belongs to some category than the corresponding
+/// integer category is returned.
+class EntryPointCategorizer {
+public:
+ EntryPointCategorizer(SplitByCategoryType Type) : Type(Type) {}
+
+ EntryPointCategorizer() = delete;
+ EntryPointCategorizer(EntryPointCategorizer &) = delete;
+ EntryPointCategorizer &operator=(const EntryPointCategorizer &) = delete;
+ EntryPointCategorizer(EntryPointCategorizer &&) = default;
+ EntryPointCategorizer &operator=(EntryPointCategorizer &&) = default;
+
+ /// Returns integer specifying the category for the given \p F.
+ /// If the given function isn't a kernel then returns std::nullopt.
+ std::optional<int> operator()(const Function &F) {
+ if (!isEntryPoint(F))
+ return std::nullopt; // skip the function.
+
+ auto StringKey = computeFunctionCategory(Type, F);
+ if (auto it = StrKeyToID.find(StringRef(StringKey)); it != StrKeyToID.end())
+ return it->second;
+
+ int ID = static_cast<int>(StrKeyToID.size());
+ return StrKeyToID.try_emplace(std::move(StringKey), ID).first->second;
+ }
+
+private:
+ static bool isEntryPoint(const Function &F) {
+ if (F.isDeclaration())
+ return false;
+
+ return F.getCallingConv() == CallingConv::SPIR_KERNEL ||
+ F.getCallingConv() == CallingConv::AMDGPU_KERNEL ||
+ F.getCallingConv() == CallingConv::PTX_Kernel;
+ }
+
+ static SmallString<0> computeFunctionCategory(SplitByCategoryType Type,
+ const Function &F) {
+ static constexpr char ATTR_MODULE_ID[] = "module-id";
+ SmallString<0> Key;
+ switch (Type) {
+ case SplitByCategoryType::SBCT_ByKernel:
+ Key = F.getName().str();
+ break;
+ case SplitByCategoryType::SBCT_ByModuleId:
+ Key = F.getFnAttribute(ATTR_MODULE_ID).getValueAsString().str();
+ break;
+ default:
+ llvm_unreachable("unexpected mode.");
+ }
+
+ return Key;
+ }
+
+private:
+ struct KeyInfo {
+ static SmallString<0> getEmptyKey() { return SmallString<0>(""); }
+
+ static SmallString<0> getTombstoneKey() { return SmallString<0>("-"); }
+
+ static bool isEqual(const SmallString<0> &LHS, const SmallString<0> &RHS) {
+ return LHS == RHS;
+ }
+
+ static unsigned getHashValue(const SmallString<0> &S) {
+ return llvm::hash_value(StringRef(S));
+ }
+ };
+
+ SplitByCategoryType Type;
+ DenseMap<SmallString<0>, int, KeyInfo> StrKeyToID;
+};
+
+void cleanupModule(Module &M) {
+ ModuleAnalysisManager MAM;
+ MAM.registerPass([&] { return PassInstrumentationAnalysis(); });
+ ModulePassManager MPM;
+ MPM.addPass(GlobalDCEPass()); // Delete unreachable globals.
+ MPM.run(M, MAM);
+}
+
+Error runSplitModuleByCategory(std::unique_ptr<Module> M) {
+ size_t OutputID = 0;
+ auto PostSplitCallback = [&](std::unique_ptr<Module> MPart) {
+ if (verifyModule(*MPart)) {
+ errs() << "Broken Module!\n";
+ exit(1);
+ }
+
+ // TODO: DCE is a crucial pass since it removes unused declarations.
+ // At the moment, LIT checking can't be perfomed without DCE.
+ cleanupModule(*MPart);
+ size_t ID = OutputID;
+ ++OutputID;
+ StringRef ModuleSuffix = OutputAssembly ? ".ll" : ".bc";
+ std::string ModulePath =
+ (Twine(OutputFilename) + "_" + Twine(ID) + ModuleSuffix).str();
+ writeModuleToFile(*MPart, ModulePath, OutputAssembly);
+ };
+
+ auto Categorizer = EntryPointCategorizer(SplitByCategory);
+ splitModuleTransitiveFromEntryPoints(std::move(M), Categorizer,
+ PostSplitCallback);
+ return Error::success();
+}
+
int main(int argc, char **argv) {
InitLLVM X(argc, argv);
@@ -123,6 +288,17 @@ int main(int argc, char **argv) {
Out->keep();
};
+ if (SplitByCategory != SplitByCategoryType::SBCT_None) {
+ auto E = runSplitModuleByCategory(std::move(M));
+ if (E) {
+ errs() << E << "\n";
+ Err.print(argv[0], errs());
+ return 1;
+ }
+
+ return 0;
+ }
+
if (TM) {
if (PreserveLocals) {
errs() << "warning: --preserve-locals has no effect when using "
diff --git a/llvm/tools/opt/optdriver.cpp b/llvm/tools/opt/optdriver.cpp
index 4a3b058..a185ea4 100644
--- a/llvm/tools/opt/optdriver.cpp
+++ b/llvm/tools/opt/optdriver.cpp
@@ -224,7 +224,8 @@ static cl::opt<bool> EnableProfileVerification(
#else
cl::init(false),
#endif
- cl::desc("Start the pipeline with prof-inject and end it with prof-check"));
+ cl::desc(
+ "Start the pipeline with prof-inject and end it with prof-verify"));
static cl::opt<std::string> ClDataLayout("data-layout",
cl::desc("data layout string to use"),