From bdb2a25e8d7ee153d47e5e9328469a703e219e9a Mon Sep 17 00:00:00 2001 From: Pavel Durov Date: Sat, 14 Sep 2024 15:29:19 +0100 Subject: [PATCH] Add module clone pass. --- llvm/include/llvm/InitializePasses.h | 1 + llvm/include/llvm/Transforms/Yk/ModuleClone.h | 10 +++ llvm/lib/CodeGen/CodeGen.cpp | 1 + llvm/lib/CodeGen/TargetPassConfig.cpp | 7 ++ llvm/lib/Transforms/Yk/CMakeLists.txt | 3 + llvm/lib/Transforms/Yk/ModuleClone.cpp | 78 +++++++++++++++++++ llvm/lib/YkIR/CMakeLists.txt | 2 + 7 files changed, 102 insertions(+) create mode 100644 llvm/include/llvm/Transforms/Yk/ModuleClone.h create mode 100644 llvm/lib/Transforms/Yk/ModuleClone.cpp diff --git a/llvm/include/llvm/InitializePasses.h b/llvm/include/llvm/InitializePasses.h index bab49b7675512f..fc3d06cf603432 100644 --- a/llvm/include/llvm/InitializePasses.h +++ b/llvm/include/llvm/InitializePasses.h @@ -344,6 +344,7 @@ void initializeXRayInstrumentationPass(PassRegistry&); void initializeYkStackmapsPass(PassRegistry&); void initializeYkSplitBlocksAfterCallsPass(PassRegistry&); void initializeYkBasicBlockTracerPass(PassRegistry&); +void initializeYkModuleClonePass(PassRegistry&); } // end namespace llvm #endif // LLVM_INITIALIZEPASSES_H diff --git a/llvm/include/llvm/Transforms/Yk/ModuleClone.h b/llvm/include/llvm/Transforms/Yk/ModuleClone.h new file mode 100644 index 00000000000000..4a6bdcf65db2d3 --- /dev/null +++ b/llvm/include/llvm/Transforms/Yk/ModuleClone.h @@ -0,0 +1,10 @@ +#ifndef LLVM_TRANSFORMS_YK_MODULE_CLONE_H +#define LLVM_TRANSFORMS_YK_MODULE_CLONE_H + +#include "llvm/Pass.h" + +namespace llvm { +ModulePass *createYkModuleClonePass(); +} // namespace llvm + +#endif diff --git a/llvm/lib/CodeGen/CodeGen.cpp b/llvm/lib/CodeGen/CodeGen.cpp index 77d7b6fefa7e39..eb51081c6ceaee 100644 --- a/llvm/lib/CodeGen/CodeGen.cpp +++ b/llvm/lib/CodeGen/CodeGen.cpp @@ -153,4 +153,5 @@ void llvm::initializeCodeGen(PassRegistry &Registry) { initializeYkStackmapsPass(Registry); initializeYkSplitBlocksAfterCallsPass(Registry); initializeYkBasicBlockTracerPass(Registry); + initializeYkModuleClonePass(Registry); } diff --git a/llvm/lib/CodeGen/TargetPassConfig.cpp b/llvm/lib/CodeGen/TargetPassConfig.cpp index 2fcfa3cb59180c..bca7d4b6316657 100644 --- a/llvm/lib/CodeGen/TargetPassConfig.cpp +++ b/llvm/lib/CodeGen/TargetPassConfig.cpp @@ -56,6 +56,7 @@ #include "llvm/Transforms/Yk/Stackmaps.h" #include "llvm/Transforms/Yk/NoCallsInEntryBlocks.h" #include "llvm/Transforms/Yk/BasicBlockTracer.h" +#include "llvm/Transforms/Yk/ModuleClone.h" #include #include #include @@ -297,6 +298,9 @@ static cl::opt YkBasicBlockTracer("yk-basicblock-tracer", cl::init(false), cl::NotHidden, cl::desc("Enables YK Software Tracer capability")); +static cl::opt + YkModuleClone("yk-module-clone", cl::init(false), cl::NotHidden, + cl::desc("Enables YK Module Cloning capability")); /// Allow standard passes to be disabled by command line options. This supports /// simple binary flags that either suppress the pass or do nothing. @@ -1190,6 +1194,9 @@ bool TargetPassConfig::addISelPasses() { if (YkBasicBlockTracer) { addPass(createYkBasicBlockTracerPass()); } + if (YkModuleClone){ + addPass(createYkModuleClonePass()); + } addISelPrepare(); return addCoreISelPasses(); diff --git a/llvm/lib/Transforms/Yk/CMakeLists.txt b/llvm/lib/Transforms/Yk/CMakeLists.txt index 3e5fba85082c29..7911cad4dfc592 100644 --- a/llvm/lib/Transforms/Yk/CMakeLists.txt +++ b/llvm/lib/Transforms/Yk/CMakeLists.txt @@ -8,6 +8,7 @@ add_llvm_component_library(LLVMYkPasses NoCallsInEntryBlocks.cpp SplitBlocksAfterCalls.cpp BasicBlockTracer.cpp + ModuleClone.cpp DEPENDS intrinsics_gen @@ -16,4 +17,6 @@ add_llvm_component_library(LLVMYkPasses Analysis Core Support + TransformUtils # Module Clone + Linker # Module Linker ) diff --git a/llvm/lib/Transforms/Yk/ModuleClone.cpp b/llvm/lib/Transforms/Yk/ModuleClone.cpp new file mode 100644 index 00000000000000..1cac96b7cb9773 --- /dev/null +++ b/llvm/lib/Transforms/Yk/ModuleClone.cpp @@ -0,0 +1,78 @@ +#include "llvm/Transforms/Yk/ModuleClone.h" +#include "llvm/IR/BasicBlock.h" +#include "llvm/IR/Function.h" +#include "llvm/IR/IRBuilder.h" +#include "llvm/IR/Instruction.h" +#include "llvm/IR/Instructions.h" +#include "llvm/IR/LLVMContext.h" +#include "llvm/IR/Module.h" +#include "llvm/InitializePasses.h" +#include "llvm/Linker/Linker.h" +#include "llvm/Pass.h" +#include "llvm/Transforms/Utils/Cloning.h" + +#define DEBUG_TYPE "yk-module-clone-pass" + +using namespace llvm; + +namespace llvm { +void initializeYkModuleClonePass(PassRegistry &); +} // namespace llvm + +namespace { +struct YkModuleClone : public ModulePass { + static char ID; + const std::string ClonePrefix = "__yk_clone_"; + + YkModuleClone() : ModulePass(ID) { + initializeYkModuleClonePass(*PassRegistry::getPassRegistry()); + } + + void updateClonedFunctions(Module &M) { + for (llvm::Function &F : M) { + if (F.hasExternalLinkage() && F.isDeclaration()) { + continue; + } + F.setName(ClonePrefix + F.getName().str()); + } + } + + void updateClonedGlobals(Module &M) { + for (llvm::GlobalVariable &GV : M.globals()) { + std::string GlobalName = GV.getName().str(); + if (GlobalName.find('.') == 0) { + continue; // This is likely not user-defined. Example: `.L.str`. + } + GV.setInitializer(nullptr); // Remove the initializer + GV.setLinkage(llvm::GlobalValue::ExternalLinkage); // Set external linkage + } + } + + bool runOnModule(Module &M) override { + if (M.getName() == "src/perf/collect.c") { + return false; + } + std::unique_ptr Cloned = CloneModule(M); + if (!Cloned) { + errs() << "Error: CloneModule returned null for module: " << M.getName() + << "\n"; + return false; + } + updateClonedFunctions(*Cloned); + updateClonedGlobals(*Cloned); + + llvm::Linker TheLinker(M); + if (TheLinker.linkInModule(std::move(Cloned))) { + llvm::report_fatal_error("Error linking the modules"); + return false; + } + return true; + } +}; +} // namespace + +char YkModuleClone::ID = 0; + +INITIALIZE_PASS(YkModuleClone, DEBUG_TYPE, "yk module clone", false, false) + +ModulePass *llvm::createYkModuleClonePass() { return new YkModuleClone(); } diff --git a/llvm/lib/YkIR/CMakeLists.txt b/llvm/lib/YkIR/CMakeLists.txt index 2464ccc11f8e84..32919c07f8352a 100644 --- a/llvm/lib/YkIR/CMakeLists.txt +++ b/llvm/lib/YkIR/CMakeLists.txt @@ -5,4 +5,6 @@ add_llvm_component_library(LLVMYkIR Core MC Support + TransformUtils + Linker )