From 4563a06cee2e669a0e075ce98d0484adc7593dd4 Mon Sep 17 00:00:00 2001 From: Justin Bogner Date: Tue, 26 Apr 2016 20:15:52 +0000 Subject: [PATCH] PM: Port Internalize to the new pass manager llvm-svn: 267596 --- llvm/include/llvm/InitializePasses.h | 2 +- .../include/llvm/Transforms/IPO/Internalize.h | 61 ++++++- llvm/lib/LTO/LTOCodeGenerator.cpp | 2 +- llvm/lib/Passes/PassBuilder.cpp | 1 + llvm/lib/Passes/PassRegistry.def | 1 + llvm/lib/Transforms/IPO/IPO.cpp | 2 +- llvm/lib/Transforms/IPO/Internalize.cpp | 171 ++++++++---------- llvm/test/Transforms/Internalize/used.ll | 1 + 8 files changed, 136 insertions(+), 105 deletions(-) diff --git a/llvm/include/llvm/InitializePasses.h b/llvm/include/llvm/InitializePasses.h index 75738891c1bb3..3b1bb9c4b8426 100644 --- a/llvm/include/llvm/InitializePasses.h +++ b/llvm/include/llvm/InitializePasses.h @@ -154,7 +154,7 @@ void initializeInlineCostAnalysisPass(PassRegistry&); void initializeInstructionCombiningPassPass(PassRegistry&); void initializeInstCountPass(PassRegistry&); void initializeInstNamerPass(PassRegistry&); -void initializeInternalizePassPass(PassRegistry&); +void initializeInternalizeLegacyPassPass(PassRegistry&); void initializeIntervalPartitionPass(PassRegistry&); void initializeIRTranslatorPass(PassRegistry &); void initializeJumpThreadingPass(PassRegistry&); diff --git a/llvm/include/llvm/Transforms/IPO/Internalize.h b/llvm/include/llvm/Transforms/IPO/Internalize.h index 141307e92e907..604c8b300ca26 100644 --- a/llvm/include/llvm/Transforms/IPO/Internalize.h +++ b/llvm/include/llvm/Transforms/IPO/Internalize.h @@ -6,22 +6,75 @@ // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// +// +// This pass loops over all of the functions and variables in the input module. +// If the function or variable does not need to be preserved according to the +// client supplied callback, it is marked as internal. +// +// This transformation would not be legal in a regular compilation, but it gets +// extra information from the linker about what is safe. +// +// For example: Internalizing a function with external linkage. Only if we are +// told it is only used from within this module, it is safe to do it. +// +//===----------------------------------------------------------------------===// #ifndef LLVM_TRANSFORMS_IPO_INTERNALIZE_H #define LLVM_TRANSFORMS_IPO_INTERNALIZE_H +#include "llvm/ADT/StringSet.h" #include "llvm/IR/GlobalValue.h" - +#include "llvm/IR/PassManager.h" #include +#include namespace llvm { class Module; class CallGraph; -bool internalizeModule( +/// A pass that internalizes all functions and variables other than those that +/// must be preserved according to \c MustPreserveGV. +class InternalizePass : public PassInfoMixin { + /// Client supplied callback to control wheter a symbol must be preserved. + const std::function MustPreserveGV; + /// Set of symbols private to the compiler that this pass should not touch. + StringSet<> AlwaysPreserved; + + /// Return false if we're allowed to internalize this GV. + bool shouldPreserveGV(const GlobalValue &GV); + /// Internalize GV if it is possible to do so, i.e. it is not externally + /// visible and is not a member of an externally visible comdat. + bool maybeInternalize(GlobalValue &GV, + const std::set &ExternalComdats); + /// If GV is part of a comdat and is externally visible, keep track of its + /// comdat so that we don't internalize any of its members. + void checkComdatVisibility(GlobalValue &GV, + std::set &ExternalComdats); + +public: + InternalizePass(); + InternalizePass( + const std::function MustPreserveGV) + : MustPreserveGV(std::move(MustPreserveGV)) {} + + /// Run the internalizer on \p TheModule, returns true if any changes was + /// made. + /// + /// If the CallGraph \p CG is supplied, it will be updated when + /// internalizing a function (by removing any edge from the "external node") + bool internalizeModule(Module &TheModule, CallGraph *CG = nullptr); + + PreservedAnalyses run(Module &M, AnalysisManager &AM); +}; + +/// Helper function to internalize functions and variables in a Module. +inline bool internalizeModule( Module &TheModule, - const std::function &MustPreserveGV, - CallGraph *CG = nullptr); + const std::function MustPreserveGV, + CallGraph *CG = nullptr) { + return InternalizePass(std::move(MustPreserveGV)) + .internalizeModule(TheModule, CG); } +} // end namespace llvm #endif // LLVM_TRANSFORMS_IPO_INTERNALIZE_H diff --git a/llvm/lib/LTO/LTOCodeGenerator.cpp b/llvm/lib/LTO/LTOCodeGenerator.cpp index b98cb7dc6e608..53035c0f69c22 100644 --- a/llvm/lib/LTO/LTOCodeGenerator.cpp +++ b/llvm/lib/LTO/LTOCodeGenerator.cpp @@ -96,7 +96,7 @@ LTOCodeGenerator::~LTOCodeGenerator() {} void LTOCodeGenerator::initializeLTOPasses() { PassRegistry &R = *PassRegistry::getPassRegistry(); - initializeInternalizePassPass(R); + initializeInternalizeLegacyPassPass(R); initializeIPSCCPPass(R); initializeGlobalOptLegacyPassPass(R); initializeConstantMergePass(R); diff --git a/llvm/lib/Passes/PassBuilder.cpp b/llvm/lib/Passes/PassBuilder.cpp index f2acd9af831f0..63c329133dd41 100644 --- a/llvm/lib/Passes/PassBuilder.cpp +++ b/llvm/lib/Passes/PassBuilder.cpp @@ -49,6 +49,7 @@ #include "llvm/Transforms/IPO/FunctionAttrs.h" #include "llvm/Transforms/IPO/GlobalOpt.h" #include "llvm/Transforms/IPO/InferFunctionAttrs.h" +#include "llvm/Transforms/IPO/Internalize.h" #include "llvm/Transforms/IPO/StripDeadPrototypes.h" #include "llvm/Transforms/InstCombine/InstCombine.h" #include "llvm/Transforms/InstrProfiling.h" diff --git a/llvm/lib/Passes/PassRegistry.def b/llvm/lib/Passes/PassRegistry.def index d36146661eb32..c70cdce2384f5 100644 --- a/llvm/lib/Passes/PassRegistry.def +++ b/llvm/lib/Passes/PassRegistry.def @@ -38,6 +38,7 @@ MODULE_ALIAS_ANALYSIS("globals-aa", GlobalsAA()) MODULE_PASS("forceattrs", ForceFunctionAttrsPass()) MODULE_PASS("globalopt", GlobalOptPass()) MODULE_PASS("inferattrs", InferFunctionAttrsPass()) +MODULE_PASS("internalize", InternalizePass()) MODULE_PASS("instrprof", InstrProfiling()) MODULE_PASS("invalidate", InvalidateAllAnalysesPass()) MODULE_PASS("no-op-module", NoOpModulePass()) diff --git a/llvm/lib/Transforms/IPO/IPO.cpp b/llvm/lib/Transforms/IPO/IPO.cpp index 514b3cc895ad5..4910f7f591dab 100644 --- a/llvm/lib/Transforms/IPO/IPO.cpp +++ b/llvm/lib/Transforms/IPO/IPO.cpp @@ -35,7 +35,7 @@ void llvm::initializeIPO(PassRegistry &Registry) { initializeAlwaysInlinerPass(Registry); initializeSimpleInlinerPass(Registry); initializeInferFunctionAttrsLegacyPassPass(Registry); - initializeInternalizePassPass(Registry); + initializeInternalizeLegacyPassPass(Registry); initializeLoopExtractorPass(Registry); initializeBlockExtractorPassPass(Registry); initializeSingleLoopExtractorPass(Registry); diff --git a/llvm/lib/Transforms/IPO/Internalize.cpp b/llvm/lib/Transforms/IPO/Internalize.cpp index 6db826ffe629e..8c5c6f77077c0 100644 --- a/llvm/lib/Transforms/IPO/Internalize.cpp +++ b/llvm/lib/Transforms/IPO/Internalize.cpp @@ -8,8 +8,8 @@ //===----------------------------------------------------------------------===// // // This pass loops over all of the functions and variables in the input module. -// If the function or variable is not in the list of external names given to -// the pass it is marked as internal. +// If the function or variable does not need to be preserved according to the +// client supplied callback, it is marked as internal. // // This transformation would not be legal in a regular compilation, but it gets // extra information from the linker about what is safe. @@ -20,7 +20,6 @@ //===----------------------------------------------------------------------===// #include "llvm/Transforms/IPO/Internalize.h" -#include "llvm/Transforms/IPO.h" #include "llvm/ADT/SmallPtrSet.h" #include "llvm/ADT/Statistic.h" #include "llvm/ADT/StringSet.h" @@ -30,6 +29,7 @@ #include "llvm/Support/CommandLine.h" #include "llvm/Support/Debug.h" #include "llvm/Support/raw_ostream.h" +#include "llvm/Transforms/IPO.h" #include "llvm/Transforms/Utils/GlobalStatus.h" #include #include @@ -53,7 +53,6 @@ static cl::list cl::desc("A list of symbol names to preserve"), cl::CommaSeparated); namespace { - // Helper to load an API list to preserve from file and expose it as a functor // for internalization. class PreserveAPIList { @@ -88,91 +87,33 @@ class PreserveAPIList { } } }; +} // end anonymous namespace -// Internalization exposed as a pass -class InternalizePass : public ModulePass { - // Client supplied callback to control wheter a symbol must be preserved. - std::function MustPreserveGV; - -public: - static char ID; // Pass identification, replacement for typeid - - InternalizePass() : ModulePass(ID), MustPreserveGV(PreserveAPIList()) {} - - InternalizePass(std::function MustPreserveGV) - : ModulePass(ID), MustPreserveGV(std::move(MustPreserveGV)) { - initializeInternalizePassPass(*PassRegistry::getPassRegistry()); - } - - bool runOnModule(Module &M) override { - if (skipModule(M)) - return false; - - CallGraphWrapperPass *CGPass = - getAnalysisIfAvailable(); - CallGraph *CG = CGPass ? &CGPass->getCallGraph() : nullptr; - return internalizeModule(M, MustPreserveGV, CG); - } - - void getAnalysisUsage(AnalysisUsage &AU) const override { - AU.setPreservesCFG(); - AU.addPreserved(); - } -}; - -// Helper class to perform internalization. -class Internalizer { - // Client supplied callback to control wheter a symbol must be preserved. - const std::function &MustPreserveGV; - - // Set of symbols private to the compiler that this pass should not touch. - StringSet<> AlwaysPreserved; - - // Return false if we're allowed to internalize this GV. - bool ShouldPreserveGV(const GlobalValue &GV) { - // Function must be defined here - if (GV.isDeclaration()) - return true; +bool InternalizePass::shouldPreserveGV(const GlobalValue &GV) { + // Function must be defined here + if (GV.isDeclaration()) + return true; - // Available externally is really just a "declaration with a body". - if (GV.hasAvailableExternallyLinkage()) - return true; + // Available externally is really just a "declaration with a body". + if (GV.hasAvailableExternallyLinkage()) + return true; - // Assume that dllexported symbols are referenced elsewhere - if (GV.hasDLLExportStorageClass()) - return true; + // Assume that dllexported symbols are referenced elsewhere + if (GV.hasDLLExportStorageClass()) + return true; - // Already local, has nothing to do. - if (GV.hasLocalLinkage()) - return false; + // Already local, has nothing to do. + if (GV.hasLocalLinkage()) + return false; - // Check some special cases - if (AlwaysPreserved.count(GV.getName())) - return true; + // Check some special cases + if (AlwaysPreserved.count(GV.getName())) + return true; - return MustPreserveGV(GV); - } - - bool maybeInternalize(GlobalValue &GV, - const std::set &ExternalComdats); - void checkComdatVisibility(GlobalValue &GV, - std::set &ExternalComdats); - -public: - Internalizer(const std::function &MustPreserveGV) - : MustPreserveGV(MustPreserveGV) {} - - /// Run the internalizer on \p TheModule, returns true if any changes was - /// made. - /// - /// If the CallGraph \p CG is supplied, it will be updated when - /// internalizing a function (by removing any edge from the "external node") - bool internalizeModule(Module &TheModule, CallGraph *CG = nullptr); -}; + return MustPreserveGV(GV); +} -// Internalize GV if it is possible to do so, i.e. it is not externally visible -// and is not a member of an externally visible comdat. -bool Internalizer::maybeInternalize( +bool InternalizePass::maybeInternalize( GlobalValue &GV, const std::set &ExternalComdats) { if (Comdat *C = GV.getComdat()) { if (ExternalComdats.count(C)) @@ -188,7 +129,7 @@ bool Internalizer::maybeInternalize( if (GV.hasLocalLinkage()) return false; - if (ShouldPreserveGV(GV)) + if (shouldPreserveGV(GV)) return false; } @@ -199,17 +140,17 @@ bool Internalizer::maybeInternalize( // If GV is part of a comdat and is externally visible, keep track of its // comdat so that we don't internalize any of its members. -void Internalizer::checkComdatVisibility( +void InternalizePass::checkComdatVisibility( GlobalValue &GV, std::set &ExternalComdats) { Comdat *C = GV.getComdat(); if (!C) return; - if (ShouldPreserveGV(GV)) + if (shouldPreserveGV(GV)) ExternalComdats.insert(C); } -bool Internalizer::internalizeModule(Module &M, CallGraph *CG) { +bool InternalizePass::internalizeModule(Module &M, CallGraph *CG) { bool Changed = false; CallGraphNode *ExternalNode = CG ? CG->getExternalCallingNode() : nullptr; @@ -296,24 +237,58 @@ bool Internalizer::internalizeModule(Module &M, CallGraph *CG) { return Changed; } -} // end anonymous namespace +InternalizePass::InternalizePass() : MustPreserveGV(PreserveAPIList()) {} + +PreservedAnalyses InternalizePass::run(Module &M, AnalysisManager &AM) { + if (!internalizeModule(M, AM.getCachedResult(M))) + return PreservedAnalyses::all(); + + PreservedAnalyses PA; + PA.preserve(); + return PA; +} -char InternalizePass::ID = 0; -INITIALIZE_PASS(InternalizePass, "internalize", "Internalize Global Symbols", - false, false) +namespace { +class InternalizeLegacyPass : public ModulePass { + // Client supplied callback to control wheter a symbol must be preserved. + std::function MustPreserveGV; -/// Public API below +public: + static char ID; // Pass identification, replacement for typeid + + InternalizeLegacyPass() : ModulePass(ID), MustPreserveGV(PreserveAPIList()) {} + + InternalizeLegacyPass(std::function MustPreserveGV) + : ModulePass(ID), MustPreserveGV(std::move(MustPreserveGV)) { + initializeInternalizeLegacyPassPass(*PassRegistry::getPassRegistry()); + } -bool llvm::internalizeModule( - Module &TheModule, - const std::function &MustPreserveGV, - CallGraph *CG) { - return Internalizer(MustPreserveGV).internalizeModule(TheModule, CG); + bool runOnModule(Module &M) override { + if (skipModule(M)) + return false; + + CallGraphWrapperPass *CGPass = + getAnalysisIfAvailable(); + CallGraph *CG = CGPass ? &CGPass->getCallGraph() : nullptr; + return internalizeModule(M, MustPreserveGV, CG); + } + + void getAnalysisUsage(AnalysisUsage &AU) const override { + AU.setPreservesCFG(); + AU.addPreserved(); + } +}; } -ModulePass *llvm::createInternalizePass() { return new InternalizePass(); } +char InternalizeLegacyPass::ID = 0; +INITIALIZE_PASS(InternalizeLegacyPass, "internalize", + "Internalize Global Symbols", false, false) + +ModulePass *llvm::createInternalizePass() { + return new InternalizeLegacyPass(); +} ModulePass *llvm::createInternalizePass( std::function MustPreserveGV) { - return new InternalizePass(std::move(MustPreserveGV)); + return new InternalizeLegacyPass(std::move(MustPreserveGV)); } diff --git a/llvm/test/Transforms/Internalize/used.ll b/llvm/test/Transforms/Internalize/used.ll index 85b85acd5083f..7c1c7413d4622 100644 --- a/llvm/test/Transforms/Internalize/used.ll +++ b/llvm/test/Transforms/Internalize/used.ll @@ -1,4 +1,5 @@ ; RUN: opt < %s -internalize -S | FileCheck %s +; RUN: opt < %s -passes=internalize -S | FileCheck %s @llvm.used = appending global [1 x void ()*] [void ()* @f], section "llvm.metadata"