28 #include <unordered_map>
31 #define DEBUG_TYPE "globaldce"
33 STATISTIC(NumAliases ,
"Number of global aliases removed");
34 STATISTIC(NumFunctions,
"Number of functions removed");
35 STATISTIC(NumIFuncs,
"Number of indirect functions removed");
36 STATISTIC(NumVariables,
"Number of global variables removed");
39 class GlobalDCELegacyPass :
public ModulePass {
49 bool runOnModule(
Module &M)
override {
54 auto PA = Impl.run(M, DummyMAM);
55 return !PA.areAllPreserved();
65 "Dead Global Elimination",
false,
false)
69 return new GlobalDCELegacyPass();
75 if (Entry.
size() != 1 || !isa<ReturnInst>(Entry.
front()))
90 ComdatMembers.insert(std::make_pair(
C, &
F));
93 ComdatMembers.insert(std::make_pair(
C, &GV));
96 ComdatMembers.insert(std::make_pair(
C, &GA));
100 Changed |= RemoveUnusedGlobalValue(GO);
104 if (!GO.isDeclaration() && !GO.hasAvailableExternallyLinkage())
105 if (!GO.isDiscardableIfUnused())
110 Changed |= RemoveUnusedGlobalValue(GA);
112 if (!GA.isDiscardableIfUnused())
117 Changed |= RemoveUnusedGlobalValue(GIF);
119 if (!GIF.isDiscardableIfUnused())
120 GlobalIsNeeded(&GIF);
128 std::vector<GlobalVariable *> DeadGlobalVars;
130 if (!AliveGlobals.count(&GV)) {
131 DeadGlobalVars.push_back(&GV);
132 if (GV.hasInitializer()) {
134 GV.setInitializer(
nullptr);
141 std::vector<Function *> DeadFunctions;
143 if (!AliveGlobals.count(&
F)) {
144 DeadFunctions.push_back(&
F);
145 if (!
F.isDeclaration())
150 std::vector<GlobalAlias*> DeadAliases;
152 if (!AliveGlobals.count(&GA)) {
153 DeadAliases.push_back(&GA);
154 GA.setAliasee(
nullptr);
158 std::vector<GlobalIFunc*> DeadIFuncs;
160 if (!AliveGlobals.count(&GIF)) {
161 DeadIFuncs.push_back(&GIF);
162 GIF.setResolver(
nullptr);
167 auto EraseUnusedGlobalValue = [&](
GlobalValue *GV) {
168 RemoveUnusedGlobalValue(*GV);
169 GV->eraseFromParent();
173 NumFunctions += DeadFunctions.size();
175 EraseUnusedGlobalValue(
F);
177 NumVariables += DeadGlobalVars.size();
179 EraseUnusedGlobalValue(GV);
181 NumAliases += DeadAliases.size();
183 EraseUnusedGlobalValue(GA);
185 NumIFuncs += DeadIFuncs.size();
187 EraseUnusedGlobalValue(GIF);
190 AliveGlobals.clear();
191 SeenConstants.clear();
192 ComdatMembers.clear();
203 if (!AliveGlobals.insert(G).second)
207 for (
auto &&CM :
make_range(ComdatMembers.equal_range(
C)))
208 GlobalIsNeeded(CM.second);
214 if (GV->hasInitializer())
215 MarkUsedGlobalsAsNeeded(GV->getInitializer());
218 MarkUsedGlobalsAsNeeded(GIS->getIndirectSymbol());
227 MarkUsedGlobalsAsNeeded(cast<Constant>(U.get()));
231 for (
Use &U :
I.operands())
234 else if (
Constant *
C = dyn_cast<Constant>(U))
235 MarkUsedGlobalsAsNeeded(
C);
239 void GlobalDCEPass::MarkUsedGlobalsAsNeeded(
Constant *
C) {
241 return GlobalIsNeeded(GV);
248 if (Op && SeenConstants.insert(Op).second)
249 MarkUsedGlobalsAsNeeded(Op);
259 bool GlobalDCEPass::RemoveUnusedGlobalValue(
GlobalValue &GV) {
Return a value (possibly void), from a function.
static PassRegistry * getPassRegistry()
getPassRegistry - Access the global registry object, which is automatically initialized at applicatio...
STATISTIC(NumFunctions,"Total number of functions")
A Module instance is used to store all the information related to an LLVM module. ...
void initializeGlobalDCELegacyPassPass(PassRegistry &)
const Instruction & front() const
Value * getReturnValue() const
Convenience accessor. Returns null if there is no return value.
A Use represents the edge between a Value definition and its users.
Pass to remove unused function declarations.
ModulePass * createGlobalDCEPass()
createGlobalDCEPass - This transform is designed to eliminate unreachable internal globals (functions...
static PreservedAnalyses none()
Convenience factory function for the empty preserved set.
A set of analyses that are preserved following a run of a transformation pass.
LLVM Basic Block Representation.
This is an important base class in LLVM.
This file contains the declarations for the subclasses of Constant, which represent the different fla...
bool isSafeToDestroyConstant(const Constant *C)
It is safe to destroy a constant iff it is only used by constants itself.
static PreservedAnalyses all()
Construct a special preserved set that preserves all passes.
iterator_range< T > make_range(T x, T y)
Convenience function for iterating over sub-ranges.
INITIALIZE_PASS(GlobalDCELegacyPass,"globaldce","Dead Global Elimination", false, false) ModulePass *llvm
Module.h This file contains the declarations for the Module class.
static bool isEmptyFunction(Function *F)
Returns true if F contains only a single "ret" instruction.
const BasicBlock & getEntryBlock() const
static GCRegistry::Add< ShadowStackGC > C("shadow-stack","Very portable GC for uncooperative code generators")
ModulePass class - This class is used to implement unstructured interprocedural optimizations and ana...
LLVM_NODISCARD std::enable_if<!is_simple_type< Y >::value, typename cast_retty< X, const Y >::ret_type >::type dyn_cast(const Y &Val)
void destroyConstant()
Called if some element of this constant is no longer valid.
void removeDeadConstantUsers() const
If there are any dead constant users dangling off of this constant, remove them.
A container for analyses that lazily runs them and caches their results.
bool optimizeGlobalCtorsList(Module &M, function_ref< bool(Function *)> ShouldRemove)
Call "ShouldRemove" for every entry in M's global_ctor list and remove the entries for which it ret...
PreservedAnalyses run(Module &M, ModuleAnalysisManager &)