GlobalOpt does not treat externally_initialized globals correctly

GlobalOpt currently merges stores into the initialisers of internal,
externally_initialized globals, but should not do so as the value of the global
may change between the initialiser and any code in the module being run.

llvm-svn: 250035
This commit is contained in:
Oliver Stannard 2015-10-12 13:20:52 +00:00
parent 20c1971db3
commit 939724cd02
3 changed files with 42 additions and 1 deletions

View File

@ -1804,7 +1804,7 @@ bool GlobalOpt::ProcessInternalGlobal(GlobalVariable *GV,
GVI = FirstNewGV; // Don't skip the newly produced globals!
return true;
}
} else if (GS.StoredType == GlobalStatus::StoredOnce) {
} else if (GS.StoredType == GlobalStatus::StoredOnce && GS.StoredOnceValue) {
// If the initial value for the global was an undef value, and if only
// one other value was stored into it, we can just change the
// initializer to be the stored value, then delete all stores to the

View File

@ -49,6 +49,10 @@ bool llvm::isSafeToDestroyConstant(const Constant *C) {
static bool analyzeGlobalAux(const Value *V, GlobalStatus &GS,
SmallPtrSetImpl<const PHINode *> &PhiUsers) {
if (const GlobalVariable *GV = dyn_cast<GlobalVariable>(V))
if (GV->isExternallyInitialized())
GS.StoredType = GlobalStatus::StoredOnce;
for (const Use &U : V->uses()) {
const User *UR = U.getUser();
if (const ConstantExpr *CE = dyn_cast<ConstantExpr>(UR)) {

View File

@ -0,0 +1,37 @@
; RUN: opt < %s -S -globalopt | FileCheck %s
; This global is externally_initialized, which may modify the value between
; it's static initializer and any code in this module being run, so the only
; write to it cannot be merged into the static initialiser.
; CHECK: @a = internal unnamed_addr externally_initialized global i32 undef
@a = internal externally_initialized global i32 undef
; This global is stored to by the external initialization, so cannot be
; constant-propagated and removed, despite the fact that there are no writes
; to it.
; CHECK: @b = internal unnamed_addr externally_initialized global i32 undef
@b = internal externally_initialized global i32 undef
define void @foo() {
; CHECK-LABEL: foo
entry:
; CHECK: store i32 42, i32* @a
store i32 42, i32* @a
ret void
}
define i32 @bar() {
; CHECK-LABEL: bar
entry:
; CHECK: %val = load i32, i32* @a
%val = load i32, i32* @a
ret i32 %val
}
define i32 @baz() {
; CHECK-LABEL: baz
entry:
; CHECK: %val = load i32, i32* @b
%val = load i32, i32* @b
ret i32 %val
}