From a0706a9ff4469b137ed6eea3f484a0152bab4c88 Mon Sep 17 00:00:00 2001 From: Rafael Espindola Date: Mon, 25 Jun 2012 14:30:31 +0000 Subject: [PATCH] If a constant or a function has linkonce_odr linkage and unnamed_addr, mark it hidden. Being linkonce_odr guarantees that it is available in every dso that needs it. Being a constant/function with unnamed_addr guarantees that the copies don't have to be merged. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@159136 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/llvm/GlobalValue.h | 6 ++++++ lib/Transforms/IPO/GlobalOpt.cpp | 11 +++++++++++ test/Transforms/GlobalOpt/hidden.ll | 14 ++++++++++++++ 3 files changed, 31 insertions(+) create mode 100644 test/Transforms/GlobalOpt/hidden.ll diff --git a/include/llvm/GlobalValue.h b/include/llvm/GlobalValue.h index 8b969f3354c..3b83b5a05c2 100644 --- a/include/llvm/GlobalValue.h +++ b/include/llvm/GlobalValue.h @@ -122,6 +122,9 @@ public: static bool isAvailableExternallyLinkage(LinkageTypes Linkage) { return Linkage == AvailableExternallyLinkage; } + static bool isLinkOnceODRLinkage(LinkageTypes Linkage) { + return Linkage == LinkOnceODRLinkage; + } static bool isLinkOnceLinkage(LinkageTypes Linkage) { return Linkage == LinkOnceAnyLinkage || Linkage == LinkOnceODRLinkage; } @@ -202,6 +205,9 @@ public: bool hasAvailableExternallyLinkage() const { return isAvailableExternallyLinkage(Linkage); } + bool hasLinkOnceODRLinkage() const { + return isLinkOnceODRLinkage(Linkage); + } bool hasLinkOnceLinkage() const { return isLinkOnceLinkage(Linkage); } diff --git a/lib/Transforms/IPO/GlobalOpt.cpp b/lib/Transforms/IPO/GlobalOpt.cpp index 35f98b22653..2f1af187f92 100644 --- a/lib/Transforms/IPO/GlobalOpt.cpp +++ b/lib/Transforms/IPO/GlobalOpt.cpp @@ -1731,6 +1731,12 @@ bool GlobalOpt::ProcessGlobal(GlobalVariable *GV, return true; } + if (GV->hasLinkOnceODRLinkage() && GV->hasUnnamedAddr() && GV->isConstant() && + GV->getVisibility() != GlobalValue::HiddenVisibility) { + GV->setVisibility(GlobalValue::HiddenVisibility); + return true; + } + if (!GV->hasLocalLinkage()) return false; @@ -1743,6 +1749,7 @@ bool GlobalOpt::ProcessGlobal(GlobalVariable *GV, if (!GS.isCompared && !GV->hasUnnamedAddr()) { GV->setUnnamedAddr(true); NumUnnamed++; + return true; } if (GV->isConstant() || !GV->hasInitializer()) @@ -1917,6 +1924,10 @@ bool GlobalOpt::OptimizeFunctions(Module &M) { F->eraseFromParent(); Changed = true; ++NumFnDeleted; + } else if (F->hasLinkOnceODRLinkage() && F->hasUnnamedAddr() && + F->getVisibility() != GlobalValue::HiddenVisibility) { + F->setVisibility(GlobalValue::HiddenVisibility); + Changed = true; } else if (F->hasLocalLinkage()) { if (F->getCallingConv() == CallingConv::C && !F->isVarArg() && !F->hasAddressTaken()) { diff --git a/test/Transforms/GlobalOpt/hidden.ll b/test/Transforms/GlobalOpt/hidden.ll new file mode 100644 index 00000000000..301e158d534 --- /dev/null +++ b/test/Transforms/GlobalOpt/hidden.ll @@ -0,0 +1,14 @@ +; RUN: opt %s -globalopt -S | FileCheck %s + +@foo = linkonce_odr unnamed_addr constant i32 42 +; CHECK: @foo = linkonce_odr hidden unnamed_addr constant i32 42 + +define linkonce_odr void @bar() unnamed_addr { +; CHECK: define linkonce_odr hidden void @bar() unnamed_addr { + ret void +} + +define i32* @zed() { + call void @bar() + ret i32* @foo +} -- 2.34.1