summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBruno Cardoso Lopes <bruno.cardoso@gmail.com>2014-08-25 17:51:14 +0000
committerBruno Cardoso Lopes <bruno.cardoso@gmail.com>2014-08-25 17:51:14 +0000
commite2a1fa35dfba8efbec2d4468d1dc44c7ecf7f2d7 (patch)
tree2909ab164b41ad8ed9ece82e69c9a8979bb4def0
parent356c4ac88b6a488536c19b743747c4decab92a21 (diff)
downloadbcm5719-llvm-e2a1fa35dfba8efbec2d4468d1dc44c7ecf7f2d7.tar.gz
bcm5719-llvm-e2a1fa35dfba8efbec2d4468d1dc44c7ecf7f2d7.zip
Remove dangling initializers in GlobalDCE
GlobalDCE deletes global vars and updates their initializers to nullptr while leaving underlying constants to be cleaned up later by its uses. The clean up may never happen, fix this by forcing it every time it's safe to destroy constants. Final patch by Rafael Espindola http://reviews.llvm.org/D4931 <rdar://problem/17523868> llvm-svn: 216390
-rw-r--r--llvm/lib/Transforms/IPO/GlobalDCE.cpp8
-rw-r--r--llvm/lib/Transforms/Utils/GlobalStatus.cpp3
-rw-r--r--llvm/test/Transforms/GlobalDCE/deadblockaddr.ll16
3 files changed, 26 insertions, 1 deletions
diff --git a/llvm/lib/Transforms/IPO/GlobalDCE.cpp b/llvm/lib/Transforms/IPO/GlobalDCE.cpp
index 7e7a4c0ae83..e50cdb7358c 100644
--- a/llvm/lib/Transforms/IPO/GlobalDCE.cpp
+++ b/llvm/lib/Transforms/IPO/GlobalDCE.cpp
@@ -22,6 +22,7 @@
#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;
@@ -141,7 +142,12 @@ bool GlobalDCE::runOnModule(Module &M) {
I != E; ++I)
if (!AliveGlobals.count(I)) {
DeadGlobalVars.push_back(I); // Keep track of dead globals
- I->setInitializer(nullptr);
+ if (I->hasInitializer()) {
+ Constant *Init = I->getInitializer();
+ I->setInitializer(nullptr);
+ if (isSafeToDestroyConstant(Init))
+ Init->destroyConstant();
+ }
}
// The second pass drops the bodies of functions which are dead...
diff --git a/llvm/lib/Transforms/Utils/GlobalStatus.cpp b/llvm/lib/Transforms/Utils/GlobalStatus.cpp
index 33e34a9941e..97a0b4ee5ac 100644
--- a/llvm/lib/Transforms/Utils/GlobalStatus.cpp
+++ b/llvm/lib/Transforms/Utils/GlobalStatus.cpp
@@ -35,6 +35,9 @@ bool llvm::isSafeToDestroyConstant(const Constant *C) {
if (isa<GlobalValue>(C))
return false;
+ if (isa<ConstantInt>(C) || isa<ConstantFP>(C))
+ return false;
+
for (const User *U : C->users())
if (const Constant *CU = dyn_cast<Constant>(U)) {
if (!isSafeToDestroyConstant(CU))
diff --git a/llvm/test/Transforms/GlobalDCE/deadblockaddr.ll b/llvm/test/Transforms/GlobalDCE/deadblockaddr.ll
new file mode 100644
index 00000000000..1ec5994d004
--- /dev/null
+++ b/llvm/test/Transforms/GlobalDCE/deadblockaddr.ll
@@ -0,0 +1,16 @@
+; RUN: opt -globaldce -simplifycfg -S < %s | FileCheck %s
+
+; Tests whether globaldce does the right cleanup while removing @bar
+; so that a dead BlockAddress reference to foo won't prevent other passes
+; to work properly, e.g. simplifycfg
+@bar = internal unnamed_addr constant i8* blockaddress(@foo, %L1)
+
+; CHECK-LABEL: foo
+; CHECK-NOT: br label %L1
+; CHECK: ret void
+define void @foo() {
+entry:
+ br label %L1
+L1:
+ ret void
+}
OpenPOWER on IntegriCloud