diff --git a/llvm/lib/Transforms/IPO/GlobalOpt.cpp b/llvm/lib/Transforms/IPO/GlobalOpt.cpp --- a/llvm/lib/Transforms/IPO/GlobalOpt.cpp +++ b/llvm/lib/Transforms/IPO/GlobalOpt.cpp @@ -1598,6 +1598,33 @@ if (optimizeOnceStoredGlobal(GV, StoredOnceValue, GS.Ordering, DL, GetTLI)) return true; + // If the store dominates any loads, those loads will always load the + // stored value (as opposed to the initializer), even in the presence of + // recursion. Restrict to the case where all loads/stores of the global are + // in the same function. + if (!GS.HasMultipleAccessingFunctions && GS.AccessingFunction) { + SmallVector Loads; + for (User *U : GV->users()) { + if (auto *LI = dyn_cast(U)) + Loads.push_back(LI); + } + // Only compute DT if we have any loads to examine. + bool MadeChange = false; + if (!Loads.empty()) { + auto &DT = LookupDomTree(*const_cast(GS.AccessingFunction)); + for (auto *LI : Loads) { + if (LI->getType() == StoredOnceValue->getType() && + DT.dominates(GS.StoredOnceStore, LI)) { + LI->replaceAllUsesWith(StoredOnceValue); + LI->eraseFromParent(); + MadeChange = true; + } + } + } + if (MadeChange) + return true; + } + // Otherwise, if the global was not a boolean, we can shrink it to be a // boolean. Skip this optimization for AS that doesn't allow an initializer. if (SOVConstant && GS.Ordering == AtomicOrdering::NotAtomic && diff --git a/llvm/test/Transforms/GlobalOpt/stored-once-forward-value.ll b/llvm/test/Transforms/GlobalOpt/stored-once-forward-value.ll --- a/llvm/test/Transforms/GlobalOpt/stored-once-forward-value.ll +++ b/llvm/test/Transforms/GlobalOpt/stored-once-forward-value.ll @@ -10,10 +10,8 @@ define i1 @dom_const() { ; CHECK-LABEL: @dom_const( -; CHECK-NEXT: store i1 true, ptr @g1, align 1 ; CHECK-NEXT: call void @b() -; CHECK-NEXT: [[R:%.*]] = load i1, ptr @g1, align 1 -; CHECK-NEXT: ret i1 [[R]] +; CHECK-NEXT: ret i1 true ; store i1 true, ptr @g1 call void @b() @@ -23,10 +21,8 @@ define i32 @dom_arg(i32 %a) { ; CHECK-LABEL: @dom_arg( -; CHECK-NEXT: store i32 [[A:%.*]], ptr @g2, align 4 ; CHECK-NEXT: call void @b() -; CHECK-NEXT: [[R:%.*]] = load i32, ptr @g2, align 4 -; CHECK-NEXT: ret i32 [[R]] +; CHECK-NEXT: ret i32 [[A:%.*]] ; store i32 %a, ptr @g2 call void @b()