//===-- GlobalDCE.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 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
//
//===----------------------------------------------------------------------===//
+#define DEBUG_TYPE "globaldce"
#include "llvm/Transforms/IPO.h"
#include "llvm/Constants.h"
#include "llvm/Module.h"
#include "llvm/Pass.h"
-#include "Support/Statistic.h"
+#include "llvm/ADT/Statistic.h"
+#include "llvm/Support/Compiler.h"
#include <set>
+using namespace llvm;
-namespace {
- Statistic<> NumFunctions("globaldce","Number of functions removed");
- Statistic<> NumVariables("globaldce","Number of global variables removed");
- Statistic<> NumCPRs("globaldce", "Number of const pointer refs removed");
+STATISTIC(NumFunctions, "Number of functions removed");
+STATISTIC(NumVariables, "Number of global variables removed");
- struct GlobalDCE : public Pass {
+namespace {
+ struct VISIBILITY_HIDDEN GlobalDCE : public ModulePass {
+ static char ID; // Pass identification, replacement for typeid
+ GlobalDCE() : ModulePass((intptr_t)&ID) {}
+
// run - Do the GlobalDCE pass on the specified module, optionally updating
// the specified callgraph to reflect the changes.
//
- bool run(Module &M);
+ bool runOnModule(Module &M);
private:
std::set<GlobalValue*> AliveGlobals;
void GlobalIsNeeded(GlobalValue *GV);
void MarkUsedGlobalsAsNeeded(Constant *C);
- bool RemoveUnusedConstantPointerRef(GlobalValue &GV);
- bool SafeToDestroyConstant(Constant *C);
+ bool SafeToDestroyConstant(Constant* C);
+ bool RemoveUnusedGlobalValue(GlobalValue &GV);
};
- RegisterOpt<GlobalDCE> X("globaldce", "Dead Global Elimination");
}
-Pass *createGlobalDCEPass() { return new GlobalDCE(); }
+char GlobalDCE::ID = 0;
+static RegisterPass<GlobalDCE> X("globaldce", "Dead Global Elimination");
-bool GlobalDCE::run(Module &M) {
+ModulePass *llvm::createGlobalDCEPass() { return new GlobalDCE(); }
+
+bool GlobalDCE::runOnModule(Module &M) {
bool Changed = false;
// Loop over the module, adding globals which are obviously necessary.
for (Module::iterator I = M.begin(), E = M.end(); I != E; ++I) {
- Changed |= RemoveUnusedConstantPointerRef(*I);
+ Changed |= RemoveUnusedGlobalValue(*I);
// Functions with external linkage are needed if they have a body
if ((!I->hasInternalLinkage() && !I->hasLinkOnceLinkage()) &&
- !I->isExternal())
+ !I->isDeclaration())
GlobalIsNeeded(I);
}
- for (Module::giterator I = M.gbegin(), E = M.gend(); I != E; ++I) {
- Changed |= RemoveUnusedConstantPointerRef(*I);
+ for (Module::global_iterator I = M.global_begin(), E = M.global_end();
+ I != E; ++I) {
+ Changed |= RemoveUnusedGlobalValue(*I);
// Externally visible & appending globals are needed, if they have an
// initializer.
if ((!I->hasInternalLinkage() && !I->hasLinkOnceLinkage()) &&
- !I->isExternal())
+ !I->isDeclaration())
GlobalIsNeeded(I);
}
+ for (Module::alias_iterator I = M.alias_begin(), E = M.alias_end();
+ I != E; ++I) {
+ // Aliases are always needed even if they are not used.
+ MarkUsedGlobalsAsNeeded(I->getAliasee());
+ }
+
// Now that all globals which are needed are in the AliveGlobals set, we loop
// through the program, deleting those which are not alive.
//
// The first pass is to drop initializers of global variables which are dead.
std::vector<GlobalVariable*> DeadGlobalVars; // Keep track of dead globals
- for (Module::giterator I = M.gbegin(), E = M.gend(); I != E; ++I)
+ for (Module::global_iterator I = M.global_begin(), E = M.global_end(); I != E; ++I)
if (!AliveGlobals.count(I)) {
DeadGlobalVars.push_back(I); // Keep track of dead globals
I->setInitializer(0);
for (Module::iterator I = M.begin(), E = M.end(); I != E; ++I)
if (!AliveGlobals.count(I)) {
DeadFunctions.push_back(I); // Keep track of dead globals
- if (!I->isExternal())
+ if (!I->isDeclaration())
I->deleteBody();
}
// Now that all interreferences have been dropped, delete the actual objects
// themselves.
for (unsigned i = 0, e = DeadFunctions.size(); i != e; ++i) {
- RemoveUnusedConstantPointerRef(*DeadFunctions[i]);
+ RemoveUnusedGlobalValue(*DeadFunctions[i]);
M.getFunctionList().erase(DeadFunctions[i]);
}
NumFunctions += DeadFunctions.size();
if (!DeadGlobalVars.empty()) {
for (unsigned i = 0, e = DeadGlobalVars.size(); i != e; ++i) {
- RemoveUnusedConstantPointerRef(*DeadGlobalVars[i]);
+ RemoveUnusedGlobalValue(*DeadGlobalVars[i]);
M.getGlobalList().erase(DeadGlobalVars[i]);
}
NumVariables += DeadGlobalVars.size();
Changed = true;
}
-
+
// Make sure that all memory is released
AliveGlobals.clear();
return Changed;
// referenced by the initializer to the alive set.
if (GV->hasInitializer())
MarkUsedGlobalsAsNeeded(GV->getInitializer());
- } else {
+ } else if (!isa<GlobalAlias>(G)) {
// Otherwise this must be a function object. We have to scan the body of
// the function looking for constants and global values which are used as
// operands. Any operands of these types must be processed to ensure that
if (GlobalValue *GV = dyn_cast<GlobalValue>(*U))
GlobalIsNeeded(GV);
else if (Constant *C = dyn_cast<Constant>(*U))
- MarkUsedGlobalsAsNeeded(C);
+ MarkUsedGlobalsAsNeeded(C);
}
}
void GlobalDCE::MarkUsedGlobalsAsNeeded(Constant *C) {
- if (ConstantPointerRef *CPR = dyn_cast<ConstantPointerRef>(C))
- GlobalIsNeeded(CPR->getValue());
+ if (GlobalValue *GV = dyn_cast<GlobalValue>(C))
+ GlobalIsNeeded(GV);
else {
// Loop over all of the operands of the constant, adding any globals they
// use to the list of needed globals.
}
}
-// RemoveUnusedConstantPointerRef - Loop over all of the uses of the specified
+// RemoveUnusedGlobalValue - Loop over all of the uses of the specified
// GlobalValue, looking for the constant pointer ref that may be pointing to it.
// If found, check to see if the constant pointer ref is safe to destroy, and if
// so, nuke it. This will reduce the reference count on the global value, which
// might make it deader.
//
-bool GlobalDCE::RemoveUnusedConstantPointerRef(GlobalValue &GV) {
- for (Value::use_iterator I = GV.use_begin(), E = GV.use_end(); I != E; ++I)
- if (ConstantPointerRef *CPR = dyn_cast<ConstantPointerRef>(*I))
- if (SafeToDestroyConstant(CPR)) { // Only if unreferenced...
- CPR->destroyConstant();
- ++NumCPRs;
- return true;
- }
-
- return false;
+bool GlobalDCE::RemoveUnusedGlobalValue(GlobalValue &GV) {
+ if (GV.use_empty()) return false;
+ GV.removeDeadConstantUsers();
+ return GV.use_empty();
}
// SafeToDestroyConstant - It is safe to destroy a constant iff it is only used
} else {
return false;
}
-
return true;
}