diff options
Diffstat (limited to 'llvm')
-rw-r--r-- | llvm/lib/Transforms/IPO/GlobalDCE.cpp | 8 | ||||
-rw-r--r-- | llvm/lib/Transforms/Utils/GlobalStatus.cpp | 3 | ||||
-rw-r--r-- | llvm/test/Transforms/GlobalDCE/deadblockaddr.ll | 16 |
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 +} |