Make constmerge a two-pass algorithm so that it won't miss merging

opporuntities. Fixes PR8978.


git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@123541 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Nick Lewycky 2011-01-15 18:14:21 +00:00
parent 111fd9ce64
commit 2820c25e84
2 changed files with 52 additions and 4 deletions

View File

@ -101,14 +101,17 @@ bool ConstantMerge::runOnModule(Module &M) {
continue;
}
// Only process constants with initializers in the default addres space.
// Only process constants with initializers in the default address space.
if (!GV->isConstant() ||!GV->hasDefinitiveInitializer() ||
GV->getType()->getAddressSpace() != 0 || !GV->getSection().empty() ||
GV->getType()->getAddressSpace() != 0 || GV->hasSection() ||
// Don't touch values marked with attribute(used).
UsedGlobals.count(GV))
continue;
// Start by filling slots with only the globals we aren't allowed to
// delete because they're externally visible.
if (GV->hasLocalLinkage())
continue;
Constant *Init = GV->getInitializer();
@ -117,7 +120,32 @@ bool ConstantMerge::runOnModule(Module &M) {
if (Slot == 0) { // Nope, add it to the map.
Slot = GV;
} else if (GV->hasLocalLinkage()) { // Yup, this is a duplicate!
}
}
for (Module::global_iterator GVI = M.global_begin(), E = M.global_end();
GVI != E; ) {
GlobalVariable *GV = GVI++;
// Only process constants with initializers in the default address space.
if (!GV->isConstant() ||!GV->hasDefinitiveInitializer() ||
GV->getType()->getAddressSpace() != 0 || GV->hasSection() ||
// Don't touch values marked with attribute(used).
UsedGlobals.count(GV))
continue;
// Only look at the remaining globals now.
if (!GV->hasLocalLinkage())
continue;
Constant *Init = GV->getInitializer();
// Check to see if the initializer is already known.
GlobalVariable *&Slot = CMap[Init];
if (Slot == 0) { // Nope, add it to the map.
Slot = GV;
} else { // Yup, this is a duplicate!
// Make all uses of the duplicate constant use the canonical version.
Replacements.push_back(std::make_pair(GV, Slot));
}
@ -135,6 +163,8 @@ bool ConstantMerge::runOnModule(Module &M) {
Replacements[i].first->replaceAllUsesWith(Replacements[i].second);
// Delete the global value from the module.
assert(Replacements[i].first->hasLocalLinkage() &&
"Refusing to delete an externally visible global variable.");
Replacements[i].first->eraseFromParent();
}

View File

@ -0,0 +1,18 @@
; RUN: opt -constmerge %s -S -o - | FileCheck %s
; PR8978
declare i32 @zed(%struct.foobar*, %struct.foobar*)
%struct.foobar = type { i32 }
; CHECK: bar.d
@bar.d = constant %struct.foobar zeroinitializer, align 4
; CHECK-NOT: foo.d
@foo.d = internal constant %struct.foobar zeroinitializer, align 4
define i32 @main() nounwind ssp {
entry:
; CHECK: bar.d
%call2 = tail call i32 @zed(%struct.foobar* @foo.d, %struct.foobar* @bar.d)
nounwind
ret i32 0
}