mirror of
https://github.com/RPCS3/llvm.git
synced 2025-01-11 06:56:12 +00:00
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> git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@216390 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
a696ccb89e
commit
ff69509f94
@ -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...
|
||||
|
@ -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))
|
||||
|
16
test/Transforms/GlobalDCE/deadblockaddr.ll
Normal file
16
test/Transforms/GlobalDCE/deadblockaddr.ll
Normal file
@ -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
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user