From 578d2e2cb14106a93dc820cff25a7f2bc93629bc Mon Sep 17 00:00:00 2001 From: Juneyoung Lee Date: Sun, 2 Feb 2020 02:34:10 +0900 Subject: [PATCH] [llvm-extract] Add -keep-const-init commandline option Summary: This adds -keep-const-init option to llvm-extract which preserves initializers of used global constants. For example: ``` $ cat a.ll @g = constant i32 0 define i32 @f() { %v = load i32, i32* @g ret i32 %v } $ llvm-extract --func=f a.ll -S -o - @g = external constant i32 define i32 @f() { .. } $ llvm-extract --func=f a.ll -keep-const-init -S -o - @g = constant i32 0 define i32 @f() { .. } ``` This option is useful in checking whether a function that uses a constant global is optimized correctly. Reviewers: jsji, MaskRay, david2050 Reviewed By: MaskRay Subscribers: hiraditya, llvm-commits Tags: #llvm Differential Revision: https://reviews.llvm.org/D73833 --- llvm/docs/CommandGuide/llvm-extract.rst | 4 ++++ llvm/include/llvm/Transforms/IPO.h | 6 ++++-- llvm/lib/Transforms/IPO/ExtractGV.cpp | 13 ++++++++----- llvm/test/tools/llvm-extract/keep-constinit.ll | 12 ++++++++++++ llvm/tools/llvm-extract/llvm-extract.cpp | 6 +++++- 5 files changed, 33 insertions(+), 8 deletions(-) create mode 100644 llvm/test/tools/llvm-extract/keep-constinit.ll diff --git a/llvm/docs/CommandGuide/llvm-extract.rst b/llvm/docs/CommandGuide/llvm-extract.rst index cd8828b23724..8e23e70cc402 100644 --- a/llvm/docs/CommandGuide/llvm-extract.rst +++ b/llvm/docs/CommandGuide/llvm-extract.rst @@ -55,6 +55,10 @@ OPTIONS bitcode. All global variables matching the regular expression will be extracted. May be specified multiple times. +**--keep-const-init** + + Preserve the values of constant globals. + **-help** Print a summary of command line options. diff --git a/llvm/include/llvm/Transforms/IPO.h b/llvm/include/llvm/Transforms/IPO.h index daf44822aeb4..ee411a10740a 100644 --- a/llvm/include/llvm/Transforms/IPO.h +++ b/llvm/include/llvm/Transforms/IPO.h @@ -84,10 +84,12 @@ ModulePass *createEliminateAvailableExternallyPass(); //===----------------------------------------------------------------------===// /// createGVExtractionPass - If deleteFn is true, this pass deletes /// the specified global values. Otherwise, it deletes as much of the module as -/// possible, except for the global values specified. +/// possible, except for the global values specified. If keepConstInit is true, +/// the initializers of global constants are not deleted even if they are +/// unused. /// ModulePass *createGVExtractionPass(std::vector& GVs, bool - deleteFn = false); + deleteFn = false, bool keepConstInit = false); //===----------------------------------------------------------------------===// /// This pass performs iterative function importing from other modules. diff --git a/llvm/lib/Transforms/IPO/ExtractGV.cpp b/llvm/lib/Transforms/IPO/ExtractGV.cpp index f77b528fc42d..b45766a8e783 100644 --- a/llvm/lib/Transforms/IPO/ExtractGV.cpp +++ b/llvm/lib/Transforms/IPO/ExtractGV.cpp @@ -54,6 +54,7 @@ namespace { class GVExtractorPass : public ModulePass { SetVector Named; bool deleteStuff; + bool keepConstInit; public: static char ID; // Pass identification, replacement for typeid @@ -61,8 +62,9 @@ namespace { /// Otherwise, it deletes as much of the module as possible, except for the /// global values specified. explicit GVExtractorPass(std::vector &GVs, - bool deleteS = true) - : ModulePass(ID), Named(GVs.begin(), GVs.end()), deleteStuff(deleteS) {} + bool deleteS = true, bool keepConstInit = false) + : ModulePass(ID), Named(GVs.begin(), GVs.end()), deleteStuff(deleteS), + keepConstInit(keepConstInit) {} bool runOnModule(Module &M) override { if (skipModule(M)) @@ -83,7 +85,8 @@ namespace { for (Module::global_iterator I = M.global_begin(), E = M.global_end(); I != E; ++I) { bool Delete = - deleteStuff == (bool)Named.count(&*I) && !I->isDeclaration(); + deleteStuff == (bool)Named.count(&*I) && !I->isDeclaration() && + (!I->isConstant() || !keepConstInit); if (!Delete) { if (I->hasAvailableExternallyLinkage()) continue; @@ -156,6 +159,6 @@ namespace { } ModulePass *llvm::createGVExtractionPass(std::vector &GVs, - bool deleteFn) { - return new GVExtractorPass(GVs, deleteFn); + bool deleteFn, bool keepConstInit) { + return new GVExtractorPass(GVs, deleteFn, keepConstInit); } diff --git a/llvm/test/tools/llvm-extract/keep-constinit.ll b/llvm/test/tools/llvm-extract/keep-constinit.ll new file mode 100644 index 000000000000..de4b3fe7bf60 --- /dev/null +++ b/llvm/test/tools/llvm-extract/keep-constinit.ll @@ -0,0 +1,12 @@ +; RUN: llvm-extract -func foo -keep-const-init -S < %s | FileCheck %s +; RUN: llvm-extract -func foo -S < %s | FileCheck %s --check-prefix=CHECK2 + +; CHECK: @cv = constant i32 0 +; CHECK2: @cv = external constant i32 + +@cv = constant i32 0 + +define i32 @foo() { + %v = load i32, i32* @cv + ret i32 %v +} diff --git a/llvm/tools/llvm-extract/llvm-extract.cpp b/llvm/tools/llvm-extract/llvm-extract.cpp index dddc0d9baa08..ac70b5f5a0d8 100644 --- a/llvm/tools/llvm-extract/llvm-extract.cpp +++ b/llvm/tools/llvm-extract/llvm-extract.cpp @@ -53,6 +53,10 @@ static cl::opt DeleteFn("delete", cl::desc("Delete specified Globals from Module"), cl::cat(ExtractCat)); +static cl::opt KeepConstInit("keep-const-init", + cl::desc("Keep initializers of constants"), + cl::cat(ExtractCat)); + static cl::opt Recursive("recursive", cl::desc("Recursively extract all called functions"), cl::cat(ExtractCat)); @@ -333,7 +337,7 @@ int main(int argc, char **argv) { { std::vector Gvs(GVs.begin(), GVs.end()); legacy::PassManager Extract; - Extract.add(createGVExtractionPass(Gvs, DeleteFn)); + Extract.add(createGVExtractionPass(Gvs, DeleteFn, KeepConstInit)); Extract.run(*M); // Now that we have all the GVs we want, mark the module as fully