summaryrefslogtreecommitdiffstats
path: root/llvm/lib/Transforms/IPO/ElimAvailExtern.cpp
diff options
context:
space:
mode:
authorTeresa Johnson <tejohnson@google.com>2015-07-06 16:22:42 +0000
committerTeresa Johnson <tejohnson@google.com>2015-07-06 16:22:42 +0000
commitd3a33a16bb002d273ae47ad09ef6de38a0c86fdb (patch)
tree251d77a1b4ff062f0e267417aac765a70c664930 /llvm/lib/Transforms/IPO/ElimAvailExtern.cpp
parent0e224a646c549e934dacf09e75000c2132ddb8a0 (diff)
downloadbcm5719-llvm-d3a33a16bb002d273ae47ad09ef6de38a0c86fdb.tar.gz
bcm5719-llvm-d3a33a16bb002d273ae47ad09ef6de38a0c86fdb.zip
Resubmit "Add new EliminateAvailableExternally module pass" (r239480)
This change includes a fix for https://code.google.com/p/chromium/issues/detail?id=499508#c3, which required updating the visibility for symbols with eliminated definitions. --Original Commit Message-- Add new EliminateAvailableExternally module pass, which is performed in O2 compiles just before GlobalDCE, unless we are preparing for LTO. This pass eliminates available externally globals (turning them into declarations), regardless of whether they are dead/unreferenced, since we are guaranteed to have a copy available elsewhere at link time. This enables additional opportunities for GlobalDCE. If we are preparing for LTO (e.g. a -flto -c compile), the pass is not included as we want to preserve available externally functions for possible link time inlining. The FE indicates whether we are doing an -flto compile via the new PrepareForLTO flag on the PassManagerBuilder. llvm-svn: 241466
Diffstat (limited to 'llvm/lib/Transforms/IPO/ElimAvailExtern.cpp')
-rw-r--r--llvm/lib/Transforms/IPO/ElimAvailExtern.cpp99
1 files changed, 99 insertions, 0 deletions
diff --git a/llvm/lib/Transforms/IPO/ElimAvailExtern.cpp b/llvm/lib/Transforms/IPO/ElimAvailExtern.cpp
new file mode 100644
index 00000000000..1566e85e99b
--- /dev/null
+++ b/llvm/lib/Transforms/IPO/ElimAvailExtern.cpp
@@ -0,0 +1,99 @@
+//===-- 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 "elim-avail-extern"
+
+STATISTIC(NumAliases , "Number of global aliases removed");
+STATISTIC(NumFunctions, "Number of functions removed");
+STATISTIC(NumVariables, "Number of global variables removed");
+
+namespace {
+ struct EliminateAvailableExternally : public ModulePass {
+ static char ID; // Pass identification, replacement for typeid
+ EliminateAvailableExternally() : ModulePass(ID) {
+ initializeEliminateAvailableExternallyPass(
+ *PassRegistry::getPassRegistry());
+ }
+
+ // run - Do the EliminateAvailableExternally pass on the specified module,
+ // optionally updating the specified callgraph to reflect the changes.
+ //
+ bool runOnModule(Module &M) override;
+ };
+}
+
+char EliminateAvailableExternally::ID = 0;
+INITIALIZE_PASS(EliminateAvailableExternally, "elim-avail-extern",
+ "Eliminate Available Externally Globals", false, false)
+
+ModulePass *llvm::createEliminateAvailableExternallyPass() {
+ return new EliminateAvailableExternally();
+}
+
+bool EliminateAvailableExternally::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);
+ I->setVisibility(GlobalValue::DefaultVisibility);
+ 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->setVisibility(GlobalValue::DefaultVisibility);
+ 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);
+ I->setVisibility(GlobalValue::DefaultVisibility);
+ NumAliases++;
+ }
+
+ return Changed;
+}
OpenPOWER on IntegriCloud