From 72f3c1b1cc1ed1989cbfd649ce33caee52ede172 Mon Sep 17 00:00:00 2001 From: Nick Lewycky Date: Sat, 15 Jan 2011 18:14:21 +0000 Subject: [PATCH] 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 --- lib/Transforms/IPO/ConstantMerge.cpp | 38 +++++++++++++++++++--- .../ConstantMerge/2011-01-15-EitherOrder.ll | 18 ++++++++++ 2 files changed, 52 insertions(+), 4 deletions(-) create mode 100644 test/Transforms/ConstantMerge/2011-01-15-EitherOrder.ll diff --git a/lib/Transforms/IPO/ConstantMerge.cpp b/lib/Transforms/IPO/ConstantMerge.cpp index ea01ffeeb5..8efad05855 100644 --- a/lib/Transforms/IPO/ConstantMerge.cpp +++ b/lib/Transforms/IPO/ConstantMerge.cpp @@ -101,15 +101,18 @@ 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(); // Check to see if the initializer is already known. @@ -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(); } diff --git a/test/Transforms/ConstantMerge/2011-01-15-EitherOrder.ll b/test/Transforms/ConstantMerge/2011-01-15-EitherOrder.ll new file mode 100644 index 0000000000..7001ce1ba4 --- /dev/null +++ b/test/Transforms/ConstantMerge/2011-01-15-EitherOrder.ll @@ -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 +} + -- 2.11.4.GIT