Reid Kleckner
2015-Jun-04 23:51 UTC
[LLVMdev] Removing AvailableExternal values in GlobalDCE (was Re: RFC: ThinLTO Impementation Plan)
On Thu, Jun 4, 2015 at 3:58 PM, Duncan P. N. Exon Smith < dexonsmith at apple.com> wrote:> > > Personally, I think the right approach is to add a bool to > createGlobalDCEPass defaulting to true named something like > IsAfterInlining. In most standard pass pipelines, GlobalDCE runs after > inlining for obvious reasons, so the default makes sense. The special case > is the LTO pass pipeline, where the code will be reloaded and reoptimized > later. IMO it's natural to put the customization there. > > That's a good point. But I still like these as separate passes.Hm, yeah, that's pretty sane. So, add a pass to downgrade available_externally global definitions to declarations with external linkage, add it to the standard -O2 pass pipeline, ensure that it's not part of LTO, and then call it done? -------------- next part -------------- An HTML attachment was scrubbed... URL: <http://lists.llvm.org/pipermail/llvm-dev/attachments/20150604/282219a4/attachment.html>
Duncan P. N. Exon Smith
2015-Jun-05 00:02 UTC
[LLVMdev] Removing AvailableExternal values in GlobalDCE (was Re: RFC: ThinLTO Impementation Plan)
> On 2015 Jun 4, at 16:51, Reid Kleckner <rnk at google.com> wrote: > > On Thu, Jun 4, 2015 at 3:58 PM, Duncan P. N. Exon Smith <dexonsmith at apple.com> wrote: > > Personally, I think the right approach is to add a bool to createGlobalDCEPass defaulting to true named something like IsAfterInlining. In most standard pass pipelines, GlobalDCE runs after inlining for obvious reasons, so the default makes sense. The special case is the LTO pass pipeline, where the code will be reloaded and reoptimized later. IMO it's natural to put the customization there. > > That's a good point. But I still like these as separate passes. > > Hm, yeah, that's pretty sane. So, add a pass to downgrade available_externally global definitions to declarations with external linkage, add it to the standard -O2 pass pipeline, ensure that it's not part of LTO, and then call it done?SGTM.
Teresa Johnson
2015-Jun-05 00:17 UTC
[LLVMdev] Removing AvailableExternal values in GlobalDCE (was Re: RFC: ThinLTO Impementation Plan)
On Thu, Jun 4, 2015 at 5:02 PM, Duncan P. N. Exon Smith <dexonsmith at apple.com> wrote:> >> On 2015 Jun 4, at 16:51, Reid Kleckner <rnk at google.com> wrote: >> >> On Thu, Jun 4, 2015 at 3:58 PM, Duncan P. N. Exon Smith <dexonsmith at apple.com> wrote: >> > Personally, I think the right approach is to add a bool to createGlobalDCEPass defaulting to true named something like IsAfterInlining. In most standard pass pipelines, GlobalDCE runs after inlining for obvious reasons, so the default makes sense. The special case is the LTO pass pipeline, where the code will be reloaded and reoptimized later. IMO it's natural to put the customization there. >> >> That's a good point. But I still like these as separate passes. >> >> Hm, yeah, that's pretty sane. So, add a pass to downgrade available_externally global definitions to declarations with external linkage, add it to the standard -O2 pass pipeline, ensure that it's not part of LTO, and then call it done? > > SGTM.Agreed. Although I assume you mean invoke the new pass under a ThinLTO-only option so that avail extern are not dropped in the compile pass before the LTO link? Teresa -- Teresa Johnson | Software Engineer | tejohnson at google.com | 408-460-2413
Duncan P. N. Exon Smith
2015-Jun-08 20:39 UTC
[LLVMdev] Removing AvailableExternal values in GlobalDCE (was Re: RFC: ThinLTO Impementation Plan)
> On 2015 Jun 8, at 13:35, Eric Christopher <echristo at gmail.com> wrote: > > > > On Mon, Jun 8, 2015 at 1:33 PM Reid Kleckner <rnk at google.com> wrote: > On Mon, Jun 8, 2015 at 1:08 PM, Eric Christopher <echristo at gmail.com> wrote: > I'd rather not have it be an llvm option at all. Just construct a different set of passes... > > This would also solve the problem of needing multiple sets of options to be passed to the builder. It'd be a bit of a change (i.e. having clang do the pass setup), but I think it'd be worth it to have clang be able to explicitly say which passes it wants. > > It's also a major change and would probably need to be discussed more widely so for now I guess this is sorta ok. > > I think for now the bool on PassManagerBuilder is a good way to make progress. Eventually, we may want to customize the LTO compilation phase optimization more fully (use lower inlining threshold, defer vectorization to link time), but we can cross that bridge when we get there. > > Precisely. In case it wasn't clear I was saying this.This SGTM too.
Teresa Johnson
2015-Jun-08 21:13 UTC
[LLVMdev] Removing AvailableExternal values in GlobalDCE (was Re: RFC: ThinLTO Impementation Plan)
New patches attached. Passes llvm/clang regression tests. PTAL Thanks! Teresa On Mon, Jun 8, 2015 at 1:39 PM, Duncan P. N. Exon Smith <dexonsmith at apple.com> wrote:> >> On 2015 Jun 8, at 13:35, Eric Christopher <echristo at gmail.com> wrote: >> >> >> >> On Mon, Jun 8, 2015 at 1:33 PM Reid Kleckner <rnk at google.com> wrote: >> On Mon, Jun 8, 2015 at 1:08 PM, Eric Christopher <echristo at gmail.com> wrote: >> I'd rather not have it be an llvm option at all. Just construct a different set of passes... >> >> This would also solve the problem of needing multiple sets of options to be passed to the builder. It'd be a bit of a change (i.e. having clang do the pass setup), but I think it'd be worth it to have clang be able to explicitly say which passes it wants. >> >> It's also a major change and would probably need to be discussed more widely so for now I guess this is sorta ok. >> >> I think for now the bool on PassManagerBuilder is a good way to make progress. Eventually, we may want to customize the LTO compilation phase optimization more fully (use lower inlining threshold, defer vectorization to link time), but we can cross that bridge when we get there. >> >> Precisely. In case it wasn't clear I was saying this. > > This SGTM too.-- Teresa Johnson | Software Engineer | tejohnson at google.com | 408-460-2413 -------------- next part -------------- Index: include/clang/Driver/Options.td ==================================================================--- include/clang/Driver/Options.td (revision 237590) +++ include/clang/Driver/Options.td (working copy) @@ -636,7 +636,7 @@ def flat__namespace : Flag<["-"], "flat_namespace" def flax_vector_conversions : Flag<["-"], "flax-vector-conversions">, Group<f_Group>; def flimited_precision_EQ : Joined<["-"], "flimited-precision=">, Group<f_Group>; def flto_EQ : Joined<["-"], "flto=">, Group<clang_ignored_gcc_optimization_f_Group>; -def flto : Flag<["-"], "flto">, Group<f_Group>; +def flto : Flag<["-"], "flto">, Flags<[CC1Option]>, Group<f_Group>; def fno_lto : Flag<["-"], "fno-lto">, Group<f_Group>; def fmacro_backtrace_limit_EQ : Joined<["-"], "fmacro-backtrace-limit=">, Group<f_Group>, Flags<[DriverOption, CoreOption]>; Index: include/clang/Frontend/CodeGenOptions.def ==================================================================--- include/clang/Frontend/CodeGenOptions.def (revision 237590) +++ include/clang/Frontend/CodeGenOptions.def (working copy) @@ -67,6 +67,8 @@ CODEGENOPT(InstrumentFunctions , 1, 0) ///< Set wh CODEGENOPT(InstrumentForProfiling , 1, 0) ///< Set when -pg is enabled. CODEGENOPT(LessPreciseFPMAD , 1, 0) ///< Enable less precise MAD instructions to ///< be generated. +CODEGENOPT(PrepareForLTO , 1, 0) ///< Set when -flto is enabled on the + ///< compile step. CODEGENOPT(MergeAllConstants , 1, 1) ///< Merge identical constants. CODEGENOPT(MergeFunctions , 1, 0) ///< Set when -fmerge-functions is enabled. CODEGENOPT(MSVolatile , 1, 0) ///< Set when /volatile:ms is enabled. Index: lib/CodeGen/BackendUtil.cpp ==================================================================--- lib/CodeGen/BackendUtil.cpp (revision 237590) +++ lib/CodeGen/BackendUtil.cpp (working copy) @@ -287,6 +287,7 @@ void EmitAssemblyHelper::CreatePasses() { PMBuilder.DisableUnitAtATime = !CodeGenOpts.UnitAtATime; PMBuilder.DisableUnrollLoops = !CodeGenOpts.UnrollLoops; PMBuilder.MergeFunctions = CodeGenOpts.MergeFunctions; + PMBuilder.PrepareForLTO = CodeGenOpts.PrepareForLTO; PMBuilder.RerollLoops = CodeGenOpts.RerollLoops; PMBuilder.addExtension(PassManagerBuilder::EP_EarlyAsPossible, Index: lib/Driver/Tools.cpp ==================================================================--- lib/Driver/Tools.cpp (revision 237590) +++ lib/Driver/Tools.cpp (working copy) @@ -2676,6 +2676,10 @@ void Clang::ConstructJob(Compilation &C, const Job assert((isa<CompileJobAction>(JA) || isa<BackendJobAction>(JA)) && "Invalid action for clang tool."); + if (JA.getType() == types::TY_LTO_IR || + JA.getType() == types::TY_LTO_BC) { + CmdArgs.push_back("-flto"); + } if (JA.getType() == types::TY_Nothing) { CmdArgs.push_back("-fsyntax-only"); } else if (JA.getType() == types::TY_LLVM_IR || Index: lib/Frontend/CompilerInvocation.cpp ==================================================================--- lib/Frontend/CompilerInvocation.cpp (revision 237590) +++ lib/Frontend/CompilerInvocation.cpp (working copy) @@ -489,6 +489,8 @@ static bool ParseCodeGenArgs(CodeGenOptions &Opts, Opts.MergeFunctions = Args.hasArg(OPT_fmerge_functions); + Opts.PrepareForLTO = Args.hasArg(OPT_flto); + Opts.MSVolatile = Args.hasArg(OPT_fms_volatile); Opts.VectorizeBB = Args.hasArg(OPT_vectorize_slp_aggressive); Index: test/CodeGen/available-externally-suppress.c ==================================================================--- test/CodeGen/available-externally-suppress.c (revision 237590) +++ test/CodeGen/available-externally-suppress.c (working copy) @@ -1,6 +1,10 @@ // RUN: %clang_cc1 -emit-llvm -o - -triple x86_64-apple-darwin10 %s | FileCheck %s +// RUN: %clang_cc1 -O2 -fno-inline -emit-llvm -o - -triple x86_64-apple-darwin10 %s | FileCheck %s +// RUN: %clang_cc1 -flto -O2 -fno-inline -emit-llvm -o - -triple x86_64-apple-darwin10 %s | FileCheck %s -check-prefix=LTO // Ensure that we don't emit available_externally functions at -O0. +// Also should not emit them at -O2, unless -flto is present in which case +// we should preserve them for link-time inlining decisions. int x; inline void f0(int y) { x = y; } @@ -7,6 +11,8 @@ inline void f0(int y) { x = y; } // CHECK-LABEL: define void @test() // CHECK: declare void @f0(i32) +// LTO-LABEL: define void @test() +// LTO: define available_externally void @f0 void test() { f0(17); } @@ -19,9 +25,13 @@ inline int __attribute__((always_inline)) f1(int x } // CHECK: @test1 +// LTO: @test1 int test1(int x) { // CHECK: br i1 // CHECK-NOT: call {{.*}} @f1 // CHECK: ret i32 + // LTO: br i1 + // LTO-NOT: call {{.*}} @f1 + // LTO: ret i32 return f1(x); } -------------- next part -------------- Index: include/llvm/InitializePasses.h ==================================================================--- include/llvm/InitializePasses.h (revision 237590) +++ include/llvm/InitializePasses.h (working copy) @@ -130,6 +130,7 @@ void initializeSanitizerCoverageModulePass(PassReg void initializeDataFlowSanitizerPass(PassRegistry&); void initializeScalarizerPass(PassRegistry&); void initializeEarlyCSELegacyPassPass(PassRegistry &); +void initializeElimAvailExternPass(PassRegistry&); void initializeExpandISelPseudosPass(PassRegistry&); void initializeFunctionAttrsPass(PassRegistry&); void initializeGCMachineCodeAnalysisPass(PassRegistry&); Index: include/llvm/Transforms/IPO.h ==================================================================--- include/llvm/Transforms/IPO.h (revision 237590) +++ include/llvm/Transforms/IPO.h (working copy) @@ -71,6 +71,12 @@ ModulePass *createGlobalOptimizerPass(); ModulePass *createGlobalDCEPass(); //===----------------------------------------------------------------------===// +/// createElimAvailExternPass - This transform is designed to eliminate +/// available external globals (functions or global variables) +/// +ModulePass *createElimAvailExternPass(); + +//===----------------------------------------------------------------------===// /// 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. Index: include/llvm/Transforms/IPO/PassManagerBuilder.h ==================================================================--- include/llvm/Transforms/IPO/PassManagerBuilder.h (revision 237590) +++ include/llvm/Transforms/IPO/PassManagerBuilder.h (working copy) @@ -121,6 +121,7 @@ class PassManagerBuilder { bool VerifyInput; bool VerifyOutput; bool MergeFunctions; + bool PrepareForLTO; private: /// ExtensionList - This is list of all of the extensions that are registered. Index: lib/Transforms/IPO/CMakeLists.txt ==================================================================--- lib/Transforms/IPO/CMakeLists.txt (revision 237590) +++ lib/Transforms/IPO/CMakeLists.txt (working copy) @@ -3,6 +3,7 @@ add_llvm_library(LLVMipo BarrierNoopPass.cpp ConstantMerge.cpp DeadArgumentElimination.cpp + ElimAvailExtern.cpp ExtractGV.cpp FunctionAttrs.cpp GlobalDCE.cpp Index: lib/Transforms/IPO/ElimAvailExtern.cpp ==================================================================--- lib/Transforms/IPO/ElimAvailExtern.cpp (revision 0) +++ lib/Transforms/IPO/ElimAvailExtern.cpp (working copy) @@ -0,0 +1,93 @@ +//===-- ElimAvailExtern.cpp - DCE unreachable internal functions ----------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This transform is designed to eliminate available external global +// definitions from the program, turning them into declarations. +// +//===----------------------------------------------------------------------===// + +#include "llvm/Transforms/IPO.h" +#include "llvm/ADT/Statistic.h" +#include "llvm/IR/Constants.h" +#include "llvm/IR/Instructions.h" +#include "llvm/IR/Module.h" +#include "llvm/Transforms/Utils/CtorUtils.h" +#include "llvm/Transforms/Utils/GlobalStatus.h" +#include "llvm/Pass.h" +using namespace llvm; + +#define DEBUG_TYPE "elimavailextern" + +STATISTIC(NumAliases , "Number of global aliases removed"); +STATISTIC(NumFunctions, "Number of functions removed"); +STATISTIC(NumVariables, "Number of global variables removed"); + +namespace { + struct ElimAvailExtern : public ModulePass { + static char ID; // Pass identification, replacement for typeid + ElimAvailExtern() : ModulePass(ID) { + initializeElimAvailExternPass(*PassRegistry::getPassRegistry()); + } + + // run - Do the ElimAvailExtern pass on the specified module, optionally + // updating the specified callgraph to reflect the changes. + // + bool runOnModule(Module &M) override; + }; +} + +char ElimAvailExtern::ID = 0; +INITIALIZE_PASS(ElimAvailExtern, "elimavailextern", + "Eliminate Available External Globals", false, false) + +ModulePass *llvm::createElimAvailExternPass() { return new ElimAvailExtern(); } + +bool ElimAvailExtern::runOnModule(Module &M) { + bool Changed = false; + + // Drop initializers of available externally global variables. + for (Module::global_iterator I = M.global_begin(), E = M.global_end(); + I != E; ++I) { + if (!I->hasAvailableExternallyLinkage()) + continue; + if (I->hasInitializer()) { + Constant *Init = I->getInitializer(); + I->setInitializer(nullptr); + if (isSafeToDestroyConstant(Init)) + Init->destroyConstant(); + } + I->removeDeadConstantUsers(); + I->setLinkage(GlobalValue::ExternalLinkage); + NumVariables++; + } + + // Drop the bodies of available externally functions. + for (Module::iterator I = M.begin(), E = M.end(); I != E; ++I) { + if (!I->hasAvailableExternallyLinkage()) + continue; + if (!I->isDeclaration()) + // This will set the linkage to external + I->deleteBody(); + I->removeDeadConstantUsers(); + NumFunctions++; + } + + // Drop targets of available externally aliases. + for (Module::alias_iterator I = M.alias_begin(), E = M.alias_end(); I != E; + ++I) { + if (!I->hasAvailableExternallyLinkage()) + continue; + I->setAliasee(nullptr); + I->removeDeadConstantUsers(); + I->setLinkage(GlobalValue::ExternalLinkage); + NumAliases++; + } + + return Changed; +} Index: lib/Transforms/IPO/PassManagerBuilder.cpp ==================================================================--- lib/Transforms/IPO/PassManagerBuilder.cpp (revision 237590) +++ lib/Transforms/IPO/PassManagerBuilder.cpp (working copy) @@ -106,6 +106,7 @@ PassManagerBuilder::PassManagerBuilder() { VerifyInput = false; VerifyOutput = false; MergeFunctions = false; + PrepareForLTO = false; } PassManagerBuilder::~PassManagerBuilder() { @@ -407,6 +408,17 @@ void PassManagerBuilder::populateModulePassManager // GlobalOpt already deletes dead functions and globals, at -O2 try a // late pass of GlobalDCE. It is capable of deleting dead cycles. if (OptLevel > 1) { + if (!PrepareForLTO) { + // Remove avail extern fns and globals definitions if we aren't + // compiling an object file for later LTO. For LTO we want to preserve + // these so they are eligible for inlining at link-time. Note if they + // are unreferenced they will be removed by GlobalDCE below, so + // this only impacts referenced available externally globals. + // Eventually they will be suppressed during codegen, but eliminating + // here enables more opportunity for GlobalDCE as it may make + // globals referenced by available external functions dead. + MPM.add(createElimAvailExternPass()); + } MPM.add(createGlobalDCEPass()); // Remove dead fns and globals. MPM.add(createConstantMergePass()); // Merge dup global constants }
Duncan P. N. Exon Smith
2015-Jun-08 21:31 UTC
[LLVMdev] Removing AvailableExternal values in GlobalDCE (was Re: RFC: ThinLTO Impementation Plan)
bcc:llvmdev, +llvm-commits> On 2015 Jun 8, at 14:13, Teresa Johnson <tejohnson at google.com> wrote: > > New patches attached. Passes llvm/clang regression tests. PTAL > Thanks! > Teresa > > On Mon, Jun 8, 2015 at 1:39 PM, Duncan P. N. Exon Smith > <dexonsmith at apple.com> wrote: >> >>> On 2015 Jun 8, at 13:35, Eric Christopher <echristo at gmail.com> wrote: >>> >>> >>> >>> On Mon, Jun 8, 2015 at 1:33 PM Reid Kleckner <rnk at google.com> wrote: >>> On Mon, Jun 8, 2015 at 1:08 PM, Eric Christopher <echristo at gmail.com> wrote: >>> I'd rather not have it be an llvm option at all. Just construct a different set of passes... >>> >>> This would also solve the problem of needing multiple sets of options to be passed to the builder. It'd be a bit of a change (i.e. having clang do the pass setup), but I think it'd be worth it to have clang be able to explicitly say which passes it wants. >>> >>> It's also a major change and would probably need to be discussed more widely so for now I guess this is sorta ok. >>> >>> I think for now the bool on PassManagerBuilder is a good way to make progress. Eventually, we may want to customize the LTO compilation phase optimization more fully (use lower inlining threshold, defer vectorization to link time), but we can cross that bridge when we get there. >>> >>> Precisely. In case it wasn't clear I was saying this. >> >> This SGTM too. > > > > -- > Teresa Johnson | Software Engineer | tejohnson at google.com | 408-460-2413 > <patch.ElimAE_clang2.txt><patch.ElimAE_llvm2.txt>LLVM patch LGTM, with a few bikesheds below.> Index: include/llvm/InitializePasses.h > ==================================================================> --- include/llvm/InitializePasses.h (revision 237590) > +++ include/llvm/InitializePasses.h (working copy) > @@ -130,6 +130,7 @@ void initializeSanitizerCoverageModulePass(PassReg > void initializeDataFlowSanitizerPass(PassRegistry&); > void initializeScalarizerPass(PassRegistry&); > void initializeEarlyCSELegacyPassPass(PassRegistry &); > +void initializeElimAvailExternPass(PassRegistry&); > void initializeExpandISelPseudosPass(PassRegistry&); > void initializeFunctionAttrsPass(PassRegistry&); > void initializeGCMachineCodeAnalysisPass(PassRegistry&); > Index: include/llvm/Transforms/IPO.h > ==================================================================> --- include/llvm/Transforms/IPO.h (revision 237590) > +++ include/llvm/Transforms/IPO.h (working copy) > @@ -71,6 +71,12 @@ ModulePass *createGlobalOptimizerPass(); > ModulePass *createGlobalDCEPass(); > > //===----------------------------------------------------------------------===// > +/// createElimAvailExternPass - This transform is designed to eliminateThis is old-style commenting. Please skip the name of the function in the doxygen comment.> +/// available external globals (functions or global variables) > +/// > +ModulePass *createElimAvailExternPass();This name isn't clear to me. "elimavailextern" is fine as command-line shorthand, but I think the function should be more explicit, something like `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. > Index: include/llvm/Transforms/IPO/PassManagerBuilder.h > ==================================================================> --- include/llvm/Transforms/IPO/PassManagerBuilder.h (revision 237590) > +++ include/llvm/Transforms/IPO/PassManagerBuilder.h (working copy) > @@ -121,6 +121,7 @@ class PassManagerBuilder { > bool VerifyInput; > bool VerifyOutput; > bool MergeFunctions; > + bool PrepareForLTO; > > private: > /// ExtensionList - This is list of all of the extensions that are registered. > Index: lib/Transforms/IPO/CMakeLists.txt > ==================================================================> --- lib/Transforms/IPO/CMakeLists.txt (revision 237590) > +++ lib/Transforms/IPO/CMakeLists.txt (working copy) > @@ -3,6 +3,7 @@ add_llvm_library(LLVMipo > BarrierNoopPass.cpp > ConstantMerge.cpp > DeadArgumentElimination.cpp > + ElimAvailExtern.cpp > ExtractGV.cpp > FunctionAttrs.cpp > GlobalDCE.cpp > Index: lib/Transforms/IPO/ElimAvailExtern.cpp > ==================================================================> --- lib/Transforms/IPO/ElimAvailExtern.cpp (revision 0) > +++ lib/Transforms/IPO/ElimAvailExtern.cpp (working copy) > @@ -0,0 +1,93 @@ > +//===-- ElimAvailExtern.cpp - DCE unreachable internal functions ----------------===// > +// > +// The LLVM Compiler Infrastructure > +// > +// This file is distributed under the University of Illinois Open Source > +// License. See LICENSE.TXT for details. > +// > +//===----------------------------------------------------------------------===// > +// > +// This transform is designed to eliminate available external global > +// definitions from the program, turning them into declarations. > +// > +//===----------------------------------------------------------------------===// > + > +#include "llvm/Transforms/IPO.h" > +#include "llvm/ADT/Statistic.h" > +#include "llvm/IR/Constants.h" > +#include "llvm/IR/Instructions.h" > +#include "llvm/IR/Module.h" > +#include "llvm/Transforms/Utils/CtorUtils.h" > +#include "llvm/Transforms/Utils/GlobalStatus.h" > +#include "llvm/Pass.h" > +using namespace llvm; > + > +#define DEBUG_TYPE "elimavailextern"Would this be better with hyphens ("elim-avail-extern")? I don't really have an opinion of which is better, just asking.> + > +STATISTIC(NumAliases , "Number of global aliases removed"); > +STATISTIC(NumFunctions, "Number of functions removed"); > +STATISTIC(NumVariables, "Number of global variables removed"); > + > +namespace { > + struct ElimAvailExtern : public ModulePass {I think the class name (like the `create*()` function) should be spelled out more explicilty: `EliminateAvailableExternally`.> + static char ID; // Pass identification, replacement for typeid > + ElimAvailExtern() : ModulePass(ID) { > + initializeElimAvailExternPass(*PassRegistry::getPassRegistry()); > + } > + > + // run - Do the ElimAvailExtern pass on the specified module, optionally > + // updating the specified callgraph to reflect the changes. > + // > + bool runOnModule(Module &M) override; > + }; > +} > + > +char ElimAvailExtern::ID = 0; > +INITIALIZE_PASS(ElimAvailExtern, "elimavailextern",If add hyphens to the `DEBUG_TYPE`, add hyphens here too.> + "Eliminate Available External Globals", false, false)s/External/Externally/> + > +ModulePass *llvm::createElimAvailExternPass() { return new ElimAvailExtern(); } > + > +bool ElimAvailExtern::runOnModule(Module &M) { > + bool Changed = false; > + > + // Drop initializers of available externally global variables. > + for (Module::global_iterator I = M.global_begin(), E = M.global_end(); > + I != E; ++I) { > + if (!I->hasAvailableExternallyLinkage()) > + continue; > + if (I->hasInitializer()) { > + Constant *Init = I->getInitializer(); > + I->setInitializer(nullptr); > + if (isSafeToDestroyConstant(Init)) > + Init->destroyConstant(); > + } > + I->removeDeadConstantUsers(); > + I->setLinkage(GlobalValue::ExternalLinkage); > + NumVariables++; > + } > + > + // Drop the bodies of available externally functions. > + for (Module::iterator I = M.begin(), E = M.end(); I != E; ++I) { > + if (!I->hasAvailableExternallyLinkage()) > + continue; > + if (!I->isDeclaration()) > + // This will set the linkage to external > + I->deleteBody(); > + I->removeDeadConstantUsers(); > + NumFunctions++; > + } > + > + // Drop targets of available externally aliases. > + for (Module::alias_iterator I = M.alias_begin(), E = M.alias_end(); I != E; > + ++I) { > + if (!I->hasAvailableExternallyLinkage()) > + continue; > + I->setAliasee(nullptr); > + I->removeDeadConstantUsers(); > + I->setLinkage(GlobalValue::ExternalLinkage); > + NumAliases++; > + } > + > + return Changed; > +} > Index: lib/Transforms/IPO/PassManagerBuilder.cpp > ==================================================================> --- lib/Transforms/IPO/PassManagerBuilder.cpp (revision 237590) > +++ lib/Transforms/IPO/PassManagerBuilder.cpp (working copy) > @@ -106,6 +106,7 @@ PassManagerBuilder::PassManagerBuilder() { > VerifyInput = false; > VerifyOutput = false; > MergeFunctions = false; > + PrepareForLTO = false; > } > > PassManagerBuilder::~PassManagerBuilder() { > @@ -407,6 +408,17 @@ void PassManagerBuilder::populateModulePassManager > // GlobalOpt already deletes dead functions and globals, at -O2 try a > // late pass of GlobalDCE. It is capable of deleting dead cycles. > if (OptLevel > 1) { > + if (!PrepareForLTO) { > + // Remove avail extern fns and globals definitions if we aren't > + // compiling an object file for later LTO. For LTO we want to preserve > + // these so they are eligible for inlining at link-time. Note if they > + // are unreferenced they will be removed by GlobalDCE below, so > + // this only impacts referenced available externally globals. > + // Eventually they will be suppressed during codegen, but eliminating > + // here enables more opportunity for GlobalDCE as it may make > + // globals referenced by available external functions dead. > + MPM.add(createElimAvailExternPass()); > + } > MPM.add(createGlobalDCEPass()); // Remove dead fns and globals. > MPM.add(createConstantMergePass()); // Merge dup global constants > } >
Seemingly Similar Threads
- [LLVMdev] Removing AvailableExternal values in GlobalDCE (was Re: RFC: ThinLTO Impementation Plan)
- [LLVMdev] Removing AvailableExternal values in GlobalDCE (was Re: RFC: ThinLTO Impementation Plan)
- [LLVMdev] Removing AvailableExternal values in GlobalDCE (was Re: RFC: ThinLTO Impementation Plan)
- [LLVMdev] Removing AvailableExternal values in GlobalDCE (was Re: RFC: ThinLTO Impementation Plan)
- [LLVMdev] Removing AvailableExternal values in GlobalDCE (was Re: RFC: ThinLTO Impementation Plan)