Index: llvm/trunk/include/llvm/InitializePasses.h =================================================================== --- llvm/trunk/include/llvm/InitializePasses.h +++ llvm/trunk/include/llvm/InitializePasses.h @@ -142,7 +142,7 @@ void initializeGCMachineCodeAnalysisPass(PassRegistry&); void initializeGCModuleInfoPass(PassRegistry&); void initializeGVNLegacyPassPass(PassRegistry&); -void initializeGlobalDCEPass(PassRegistry&); +void initializeGlobalDCELegacyPassPass(PassRegistry&); void initializeGlobalOptLegacyPassPass(PassRegistry&); void initializeGlobalsAAWrapperPassPass(PassRegistry&); void initializeIPCPPass(PassRegistry&); Index: llvm/trunk/include/llvm/Transforms/IPO/GlobalDCE.h =================================================================== --- llvm/trunk/include/llvm/Transforms/IPO/GlobalDCE.h +++ llvm/trunk/include/llvm/Transforms/IPO/GlobalDCE.h @@ -0,0 +1,46 @@ +//===-- GlobalDCE.h - 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 unreachable internal globals from the +// program. It uses an aggressive algorithm, searching out globals that are +// known to be alive. After it finds all of the globals which are needed, it +// deletes whatever is left over. This allows it to delete recursive chunks of +// the program which are unreachable. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_TRANSFORMS_IPO_GLOBALDCE_H +#define LLVM_TRANSFORMS_IPO_GLOBALDCE_H + +#include "llvm/IR/Module.h" +#include "llvm/IR/PassManager.h" +#include + +namespace llvm { + +/// Pass to remove unused function declarations. +class GlobalDCEPass : public PassInfoMixin { +public: + PreservedAnalyses run(Module &M); + +private: + SmallPtrSet AliveGlobals; + SmallPtrSet SeenConstants; + std::unordered_multimap ComdatMembers; + + /// Mark the specific global value as needed, and + /// recursively mark anything that it uses as also needed. + void GlobalIsNeeded(GlobalValue *GV); + void MarkUsedGlobalsAsNeeded(Constant *C); + bool RemoveUnusedGlobalValue(GlobalValue &GV); +}; + +} + +#endif // LLVM_TRANSFORMS_IPO_GLOBALDCE_H Index: llvm/trunk/lib/LTO/LTOCodeGenerator.cpp =================================================================== --- llvm/trunk/lib/LTO/LTOCodeGenerator.cpp +++ llvm/trunk/lib/LTO/LTOCodeGenerator.cpp @@ -104,7 +104,7 @@ initializeInstructionCombiningPassPass(R); initializeSimpleInlinerPass(R); initializePruneEHPass(R); - initializeGlobalDCEPass(R); + initializeGlobalDCELegacyPassPass(R); initializeArgPromotionPass(R); initializeJumpThreadingPass(R); initializeSROALegacyPassPass(R); Index: llvm/trunk/lib/Passes/PassBuilder.cpp =================================================================== --- llvm/trunk/lib/Passes/PassBuilder.cpp +++ llvm/trunk/lib/Passes/PassBuilder.cpp @@ -47,6 +47,7 @@ #include "llvm/Target/TargetMachine.h" #include "llvm/Transforms/IPO/ForceFunctionAttrs.h" #include "llvm/Transforms/IPO/FunctionAttrs.h" +#include "llvm/Transforms/IPO/GlobalDCE.h" #include "llvm/Transforms/IPO/GlobalOpt.h" #include "llvm/Transforms/IPO/InferFunctionAttrs.h" #include "llvm/Transforms/IPO/Internalize.h" Index: llvm/trunk/lib/Passes/PassRegistry.def =================================================================== --- llvm/trunk/lib/Passes/PassRegistry.def +++ llvm/trunk/lib/Passes/PassRegistry.def @@ -36,6 +36,7 @@ #define MODULE_PASS(NAME, CREATE_PASS) #endif MODULE_PASS("forceattrs", ForceFunctionAttrsPass()) +MODULE_PASS("globaldce", GlobalDCEPass()) MODULE_PASS("globalopt", GlobalOptPass()) MODULE_PASS("inferattrs", InferFunctionAttrsPass()) MODULE_PASS("internalize", InternalizePass()) Index: llvm/trunk/lib/Transforms/IPO/GlobalDCE.cpp =================================================================== --- llvm/trunk/lib/Transforms/IPO/GlobalDCE.cpp +++ llvm/trunk/lib/Transforms/IPO/GlobalDCE.cpp @@ -15,6 +15,7 @@ // //===----------------------------------------------------------------------===// +#include "llvm/Transforms/IPO/GlobalDCE.h" #include "llvm/ADT/SmallPtrSet.h" #include "llvm/ADT/Statistic.h" #include "llvm/IR/Constants.h" @@ -34,31 +35,38 @@ STATISTIC(NumVariables, "Number of global variables removed"); namespace { - struct GlobalDCE : public ModulePass { + class GlobalDCELegacyPass : public ModulePass { + public: static char ID; // Pass identification, replacement for typeid - GlobalDCE() : ModulePass(ID) { - initializeGlobalDCEPass(*PassRegistry::getPassRegistry()); + GlobalDCELegacyPass() : ModulePass(ID) { + initializeGlobalDCELegacyPassPass(*PassRegistry::getPassRegistry()); } // run - Do the GlobalDCE pass on the specified module, optionally updating // the specified callgraph to reflect the changes. // - bool runOnModule(Module &M) override; + bool runOnModule(Module &M) override { + if (skipModule(M)) + return false; - private: - SmallPtrSet AliveGlobals; - SmallPtrSet SeenConstants; - std::unordered_multimap ComdatMembers; - - /// GlobalIsNeeded - mark the specific global value as needed, and - /// recursively mark anything that it uses as also needed. - void GlobalIsNeeded(GlobalValue *GV); - void MarkUsedGlobalsAsNeeded(Constant *C); + auto PA = Impl.run(M); + return !PA.areAllPreserved(); + } - bool RemoveUnusedGlobalValue(GlobalValue &GV); + private: + GlobalDCEPass Impl; }; } +char GlobalDCELegacyPass::ID = 0; +INITIALIZE_PASS(GlobalDCELegacyPass, "globaldce", + "Dead Global Elimination", false, false) + +// Public interface to the GlobalDCEPass. +ModulePass *llvm::createGlobalDCEPass() { + return new GlobalDCELegacyPass(); +} + /// Returns true if F contains only a single "ret" instruction. static bool isEmptyFunction(Function *F) { BasicBlock &Entry = F->getEntryBlock(); @@ -68,16 +76,7 @@ return RI.getReturnValue() == nullptr; } -char GlobalDCE::ID = 0; -INITIALIZE_PASS(GlobalDCE, "globaldce", - "Dead Global Elimination", false, false) - -ModulePass *llvm::createGlobalDCEPass() { return new GlobalDCE(); } - -bool GlobalDCE::runOnModule(Module &M) { - if (skipModule(M)) - return false; - +PreservedAnalyses GlobalDCEPass::run(Module &M) { bool Changed = false; // Remove empty functions from the global ctors list. @@ -188,12 +187,14 @@ SeenConstants.clear(); ComdatMembers.clear(); - return Changed; + if (Changed) + return PreservedAnalyses::none(); + return PreservedAnalyses::all(); } /// GlobalIsNeeded - the specific global value as needed, and /// recursively mark anything that it uses as also needed. -void GlobalDCE::GlobalIsNeeded(GlobalValue *G) { +void GlobalDCEPass::GlobalIsNeeded(GlobalValue *G) { // If the global is already in the set, no need to reprocess it. if (!AliveGlobals.insert(G).second) return; @@ -231,7 +232,7 @@ } } -void GlobalDCE::MarkUsedGlobalsAsNeeded(Constant *C) { +void GlobalDCEPass::MarkUsedGlobalsAsNeeded(Constant *C) { if (GlobalValue *GV = dyn_cast(C)) return GlobalIsNeeded(GV); @@ -251,7 +252,7 @@ // so, nuke it. This will reduce the reference count on the global value, which // might make it deader. // -bool GlobalDCE::RemoveUnusedGlobalValue(GlobalValue &GV) { +bool GlobalDCEPass::RemoveUnusedGlobalValue(GlobalValue &GV) { if (GV.use_empty()) return false; GV.removeDeadConstantUsers(); Index: llvm/trunk/lib/Transforms/IPO/IPO.cpp =================================================================== --- llvm/trunk/lib/Transforms/IPO/IPO.cpp +++ llvm/trunk/lib/Transforms/IPO/IPO.cpp @@ -29,7 +29,7 @@ initializeDAEPass(Registry); initializeDAHPass(Registry); initializeForceFunctionAttrsLegacyPassPass(Registry); - initializeGlobalDCEPass(Registry); + initializeGlobalDCELegacyPassPass(Registry); initializeGlobalOptLegacyPassPass(Registry); initializeIPCPPass(Registry); initializeAlwaysInlinerPass(Registry); Index: llvm/trunk/test/Transforms/GlobalDCE/basicvariabletest.ll =================================================================== --- llvm/trunk/test/Transforms/GlobalDCE/basicvariabletest.ll +++ llvm/trunk/test/Transforms/GlobalDCE/basicvariabletest.ll @@ -1,4 +1,4 @@ -; RUN: opt < %s -globaldce -S | FileCheck %s +; RUN: opt < %s -passes=globaldce -S | FileCheck %s ; CHECK-NOT: global @X = external global i32