patch/idea: set unnamed_addr on linkonce_odr early
Rafael EspĂndola via llvm-commits
llvm-commits at lists.llvm.org
Tue Dec 22 14:37:46 PST 2015
The attached patch changes GlobalOpt to set unnamed_addr on
linkonce_odr GVs. The idea is that it marks that the address of *this*
GV is not relevant. If it is in another module the IR linker will
correctly drop the unnamed_addr.
With that we can simplify LTO since we can depend on unnamed_addr to
decide whether a linkonce_odr can be removed from the symbol table or
not.
I tested the attached patch with a clang bootstrap on linux. There
were only 69 GVs with linkonce_odr left in clang, and they all seem to
have their addresses used.
Cheers,
Rafael
-------------- next part --------------
diff --git a/lib/CodeGen/Analysis.cpp b/lib/CodeGen/Analysis.cpp
index 75579a2..857c813 100644
--- a/lib/CodeGen/Analysis.cpp
+++ b/lib/CodeGen/Analysis.cpp
@@ -624,9 +624,6 @@ bool llvm::canBeOmittedFromSymbolTable(const GlobalValue *GV) {
if (!GV->hasLinkOnceODRLinkage())
return false;
- if (GV->hasUnnamedAddr())
- return true;
-
// If it is a non constant variable, it needs to be uniqued across shared
// objects.
if (const GlobalVariable *Var = dyn_cast<GlobalVariable>(GV)) {
@@ -639,11 +636,7 @@ bool llvm::canBeOmittedFromSymbolTable(const GlobalValue *GV) {
if (isa<GlobalAlias>(GV))
return false;
- GlobalStatus GS;
- if (GlobalStatus::analyzeGlobal(GV, GS))
- return false;
-
- return !GS.IsCompared;
+ return GV->hasUnnamedAddr();
}
static void collectFuncletMembers(
diff --git a/lib/Transforms/IPO/GlobalOpt.cpp b/lib/Transforms/IPO/GlobalOpt.cpp
index fd773690..03acd99 100644
--- a/lib/Transforms/IPO/GlobalOpt.cpp
+++ b/lib/Transforms/IPO/GlobalOpt.cpp
@@ -1706,23 +1706,25 @@ bool GlobalOpt::deleteIfDead(GlobalValue &GV) {
/// Analyze the specified global variable and optimize it if possible. If we
/// make a change, return true.
bool GlobalOpt::processGlobal(GlobalValue &GV) {
- // Do more involved optimizations if the global is internal.
- if (!GV.hasLocalLinkage())
+ if (!GV.hasLocalLinkage() && !GV.hasLinkOnceODRLinkage())
return false;
GlobalStatus GS;
-
if (GlobalStatus::analyzeGlobal(&GV, GS))
return false;
+ auto *GVar = dyn_cast<GlobalVariable>(&GV);
bool Changed = false;
- if (!GS.IsCompared && !GV.hasUnnamedAddr()) {
+ if (!GS.IsCompared && !GV.hasUnnamedAddr() && (!GVar || GVar->isConstant())) {
GV.setUnnamedAddr(true);
NumUnnamed++;
Changed = true;
}
- auto *GVar = dyn_cast<GlobalVariable>(&GV);
+ // Do more involved optimizations if the global is internal.
+ if (!GV.hasLocalLinkage())
+ return false;
+
if (!GVar)
return Changed;
diff --git a/test/CodeGen/PowerPC/weak_def_can_be_hidden.ll b/test/CodeGen/PowerPC/weak_def_can_be_hidden.ll
index 0b87613..45220af 100644
--- a/test/CodeGen/PowerPC/weak_def_can_be_hidden.ll
+++ b/test/CodeGen/PowerPC/weak_def_can_be_hidden.ll
@@ -3,7 +3,7 @@
; RUN: llc -mtriple=powerpc-apple-darwin9 -O0 < %s | FileCheck --check-prefix=CHECK-D89 %s
; RUN: llc -mtriple=powerpc-apple-darwin8 -O0 < %s | FileCheck --check-prefix=CHECK-D89 %s
- at v1 = linkonce_odr constant i32 32
+ at v1 = linkonce_odr unnamed_addr constant i32 32
; CHECK: .globl _v1
; CHECK: .weak_def_can_be_hidden _v1
@@ -26,7 +26,7 @@ define i32* @f2() {
ret i32* @v2
}
- at v3 = linkonce_odr unnamed_addr global i32 32
+ at v3 = linkonce_odr unnamed_addr constant i32 32
; CHECK: .globl _v3
; CHECK: .weak_def_can_be_hidden _v3
diff --git a/test/CodeGen/X86/weak_def_can_be_hidden.ll b/test/CodeGen/X86/weak_def_can_be_hidden.ll
index 8e6d34c..673b814 100644
--- a/test/CodeGen/X86/weak_def_can_be_hidden.ll
+++ b/test/CodeGen/X86/weak_def_can_be_hidden.ll
@@ -4,7 +4,7 @@
; RUN: llc -mtriple=i686-apple-darwin9 -O0 < %s | FileCheck --check-prefix=CHECK-D89 %s
; RUN: llc -mtriple=i686-apple-darwin8 -O0 < %s | FileCheck --check-prefix=CHECK-D89 %s
- at v1 = linkonce_odr constant i32 32
+ at v1 = linkonce_odr unnamed_addr constant i32 32
; CHECK: .globl _v1
; CHECK: .weak_def_can_be_hidden _v1
@@ -27,7 +27,7 @@ define i32* @f2() {
ret i32* @v2
}
- at v3 = linkonce_odr unnamed_addr global i32 32
+ at v3 = linkonce_odr unnamed_addr constant i32 32
; CHECK: .globl _v3
; CHECK: .weak_def_can_be_hidden _v3
diff --git a/test/LTO/X86/cfi_endproc.ll b/test/LTO/X86/cfi_endproc.ll
index 57d822b..7a9ab2b 100644
--- a/test/LTO/X86/cfi_endproc.ll
+++ b/test/LTO/X86/cfi_endproc.ll
@@ -33,8 +33,8 @@ define i32* @get_zed1() {
ret i32* @zed1
}
-; ZED1_AND_ZED2: d zed2
- at zed2 = linkonce_odr unnamed_addr global i32 42
+; ZED1_AND_ZED2: r zed2
+ at zed2 = linkonce_odr unnamed_addr constant i32 42
define i32 @useZed2() {
%x = load i32, i32* @zed2
diff --git a/test/LTO/X86/linkonce_odr_func.ll b/test/LTO/X86/linkonce_odr_func.ll
index 671b30a..4821528 100644
--- a/test/LTO/X86/linkonce_odr_func.ll
+++ b/test/LTO/X86/linkonce_odr_func.ll
@@ -7,7 +7,7 @@ target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f3
target triple = "x86_64-unknown-linux-gnu"
; CHECK: t foo1
-define linkonce_odr void @foo1() noinline {
+define linkonce_odr void @foo1() unnamed_addr noinline{
ret void
}
@@ -17,7 +17,7 @@ define linkonce_odr void @foo2() noinline {
}
; CHECK: t foo3
-define linkonce_odr void @foo3() noinline {
+define linkonce_odr void @foo3() unnamed_addr noinline {
ret void
}
@@ -27,7 +27,7 @@ define linkonce_odr void @foo4() noinline {
}
; CHECK: r v1
- at v1 = linkonce_odr constant i32 32
+ at v1 = linkonce_odr unnamed_addr constant i32 32
define i32 @useV1() {
%x = load i32, i32* @v1
diff --git a/test/Transforms/GlobalOpt/2008-04-26-SROA-Global-Align.ll b/test/Transforms/GlobalOpt/2008-04-26-SROA-Global-Align.ll
index 934d928..3d7a122 100644
--- a/test/Transforms/GlobalOpt/2008-04-26-SROA-Global-Align.ll
+++ b/test/Transforms/GlobalOpt/2008-04-26-SROA-Global-Align.ll
@@ -2,9 +2,9 @@
; alignments. Elements 0 and 2 must be 16-byte aligned, and element
; 1 must be at least 8 byte aligned (but could be more).
-; RUN: opt < %s -globalopt -S | grep "@G.0 = internal unnamed_addr global .*align 16"
-; RUN: opt < %s -globalopt -S | grep "@G.1 = internal unnamed_addr global .*align 8"
-; RUN: opt < %s -globalopt -S | grep "@G.2 = internal unnamed_addr global .*align 16"
+; RUN: opt < %s -globalopt -S | grep "@G.0 = internal global .*align 16"
+; RUN: opt < %s -globalopt -S | grep "@G.1 = internal global .*align 8"
+; RUN: opt < %s -globalopt -S | grep "@G.2 = internal global .*align 16"
; rdar://5891920
target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:32:32-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128"
diff --git a/test/Transforms/GlobalOpt/2009-03-07-PromotePtrToBool.ll b/test/Transforms/GlobalOpt/2009-03-07-PromotePtrToBool.ll
index 469fa76..2a0cbb4 100644
--- a/test/Transforms/GlobalOpt/2009-03-07-PromotePtrToBool.ll
+++ b/test/Transforms/GlobalOpt/2009-03-07-PromotePtrToBool.ll
@@ -1,4 +1,4 @@
-; RUN: opt < %s -globalopt -S | grep "@X = internal unnamed_addr global i32"
+; RUN: opt < %s -globalopt -S | grep "@X = internal global i32"
target datalayout = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-f32:32:32-f64:32:64-v64:64:64-v128:128:128-a0:0:64-f80:128:128"
target triple = "i386-apple-darwin7"
@X = internal global i32* null ; <i32**> [#uses=2]
diff --git a/test/Transforms/GlobalOpt/2009-11-16-MallocSingleStoreToGlobalVar.ll b/test/Transforms/GlobalOpt/2009-11-16-MallocSingleStoreToGlobalVar.ll
index 25bb976..705137c 100644
--- a/test/Transforms/GlobalOpt/2009-11-16-MallocSingleStoreToGlobalVar.ll
+++ b/test/Transforms/GlobalOpt/2009-11-16-MallocSingleStoreToGlobalVar.ll
@@ -8,7 +8,7 @@ target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f3
target triple = "x86_64-apple-darwin10.0"
@TOP = internal global i64* null ; <i64**> [#uses=2]
-; CHECK: @TOP = internal unnamed_addr global i64* null
+; CHECK: @TOP = internal global i64* null
@channelColumns = internal global i64 0 ; <i64*> [#uses=2]
; Derived from @DescribeChannel() in yacr2
diff --git a/test/Transforms/GlobalOpt/atomic.ll b/test/Transforms/GlobalOpt/atomic.ll
index 563c1fe..fd0a90f 100644
--- a/test/Transforms/GlobalOpt/atomic.ll
+++ b/test/Transforms/GlobalOpt/atomic.ll
@@ -4,7 +4,7 @@
@GV2 = internal global i32 0
; CHECK: @GV1 = internal unnamed_addr constant i64 1
-; CHECK: @GV2 = internal unnamed_addr global i32 0
+; CHECK: @GV2 = internal global i32 0
define void @test1() {
entry:
diff --git a/test/Transforms/GlobalOpt/externally-initialized-aggregate.ll b/test/Transforms/GlobalOpt/externally-initialized-aggregate.ll
index b446d24..f5e6255 100644
--- a/test/Transforms/GlobalOpt/externally-initialized-aggregate.ll
+++ b/test/Transforms/GlobalOpt/externally-initialized-aggregate.ll
@@ -4,11 +4,11 @@
; should keep that flag set on all of the new globals. This will prevent the
; store to @a[0] from being constant propagated to the load in @foo, but will not
; prevent @a[1] from being removed since it is dead.
-; CHECK: @a.0 = internal unnamed_addr externally_initialized global i32 undef
+; CHECK: @a.0 = internal externally_initialized global i32 undef
; CHECK-NOT @a.1
@a = internal externally_initialized global [2 x i32] undef, align 4
; This is the same, but a struct rather than an array.
-; CHECK: @b.0 = internal unnamed_addr externally_initialized global i32 undef
+; CHECK: @b.0 = internal externally_initialized global i32 undef
; CHECK-NOT @b.1
@b = internal externally_initialized global {i32, i32} undef, align 4
diff --git a/test/Transforms/GlobalOpt/externally-initialized.ll b/test/Transforms/GlobalOpt/externally-initialized.ll
index c01ba10..7194419 100644
--- a/test/Transforms/GlobalOpt/externally-initialized.ll
+++ b/test/Transforms/GlobalOpt/externally-initialized.ll
@@ -3,13 +3,13 @@
; 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
+; CHECK: @a = internal 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
+; CHECK: @b = internal externally_initialized global i32 undef
@b = internal externally_initialized global i32 undef
diff --git a/test/Transforms/GlobalOpt/globalsra-unknown-index.ll b/test/Transforms/GlobalOpt/globalsra-unknown-index.ll
index 5194b2c..db13fdc 100644
--- a/test/Transforms/GlobalOpt/globalsra-unknown-index.ll
+++ b/test/Transforms/GlobalOpt/globalsra-unknown-index.ll
@@ -1,5 +1,5 @@
; RUN: opt < %s -globalopt -S > %t
-; RUN: grep "@Y = internal unnamed_addr global \[3 x [%]struct.X\] zeroinitializer" %t
+; RUN: grep "@Y = internal global \[3 x [%]struct.X\] zeroinitializer" %t
; RUN: grep load %t | count 6
; RUN: grep "add i32 [%]a, [%]b" %t | count 3
diff --git a/test/Transforms/GlobalOpt/pr21191.ll b/test/Transforms/GlobalOpt/pr21191.ll
index 34e15cb..ad037d2 100644
--- a/test/Transforms/GlobalOpt/pr21191.ll
+++ b/test/Transforms/GlobalOpt/pr21191.ll
@@ -6,12 +6,12 @@ $c = comdat any
define linkonce_odr void @foo() comdat($c) {
ret void
}
-; CHECK: define linkonce_odr void @foo() comdat($c)
+; CHECK: define linkonce_odr void @foo() unnamed_addr comdat($c)
define linkonce_odr void @bar() comdat($c) {
ret void
}
-; CHECK: define linkonce_odr void @bar() comdat($c)
+; CHECK: define linkonce_odr void @bar() unnamed_addr comdat($c)
define void @zed() {
call void @foo()
diff --git a/test/Transforms/GlobalOpt/unnamed-addr.ll b/test/Transforms/GlobalOpt/unnamed-addr.ll
index de436c6..720b5f3 100644
--- a/test/Transforms/GlobalOpt/unnamed-addr.ll
+++ b/test/Transforms/GlobalOpt/unnamed-addr.ll
@@ -2,13 +2,13 @@
@a = internal global i32 0, align 4
@b = internal global i32 0, align 4
- at c = internal global i32 0, align 4
+ at c = internal constant i32 0, align 4
@d = internal constant [4 x i8] c"foo\00", align 1
@e = linkonce_odr global i32 0
; CHECK: @a = internal global i32 0, align 4
; CHECK: @b = internal global i32 0, align 4
-; CHECK: @c = internal unnamed_addr global i32 0, align 4
+; CHECK: @c = internal unnamed_addr constant i32 0, align 4
; CHECK: @d = internal unnamed_addr constant [4 x i8] c"foo\00", align 1
; CHECK: @e = linkonce_odr global i32 0
diff --git a/test/tools/gold/X86/coff.ll b/test/tools/gold/X86/coff.ll
index 5d8a1c9..f503a9f 100644
--- a/test/tools/gold/X86/coff.ll
+++ b/test/tools/gold/X86/coff.ll
@@ -16,7 +16,7 @@ define hidden void @g() {
ret void
}
-; CHECK: define internal void @h() {
-define linkonce_odr void @h() {
+; CHECK: define internal void @h() unnamed_addr {
+define linkonce_odr void @h() unnamed_addr {
ret void
}
diff --git a/test/tools/gold/X86/emit-llvm.ll b/test/tools/gold/X86/emit-llvm.ll
index 4a6d596..49b6277 100644
--- a/test/tools/gold/X86/emit-llvm.ll
+++ b/test/tools/gold/X86/emit-llvm.ll
@@ -53,7 +53,7 @@ define void @f3() {
; CHECK-DAG: define internal void @f4()
; OPT2-NOT: @f4
-define linkonce_odr void @f4() {
+define linkonce_odr void @f4() unnamed_addr {
ret void
}
diff --git a/tools/gold/gold-plugin.cpp b/tools/gold/gold-plugin.cpp
index b6acea7..e95b8c4 100644
--- a/tools/gold/gold-plugin.cpp
+++ b/tools/gold/gold-plugin.cpp
@@ -595,8 +595,7 @@ getFunctionIndexForFile(claimed_file &F, ld_plugin_input_file &Info) {
static std::unique_ptr<Module>
getModuleForFile(LLVMContext &Context, claimed_file &F,
ld_plugin_input_file &Info, raw_fd_ostream *ApiFile,
- StringSet<> &Internalize, StringSet<> &Maybe,
- std::vector<GlobalValue *> &Keep) {
+ StringSet<> &Internalize, std::vector<GlobalValue *> &Keep) {
if (get_symbols(F.handle, F.syms.size(), F.syms.data()) != LDPS_OK)
message(LDPL_FATAL, "Failed to get symbol information");
@@ -647,12 +646,16 @@ getModuleForFile(LLVMContext &Context, claimed_file &F,
}
ResolutionInfo &Res = ResInfo[Sym.name];
- if (Resolution == LDPR_PREVAILING_DEF_IRONLY_EXP && !Res.IsLinkonceOdr)
- Resolution = LDPR_PREVAILING_DEF;
-
GV->setUnnamedAddr(Res.UnnamedAddr);
GV->setVisibility(Res.Visibility);
+ if (Resolution == LDPR_PREVAILING_DEF_IRONLY_EXP) {
+ if (!Res.IsLinkonceOdr)
+ Resolution = LDPR_PREVAILING_DEF;
+ else if (canBeOmittedFromSymbolTable(GV))
+ Resolution = LDPR_PREVAILING_DEF_IRONLY;
+ }
+
// Override gold's resolution for common symbols. We want the largest
// one to win.
if (GV->hasCommonLinkage()) {
@@ -714,16 +717,10 @@ getModuleForFile(LLVMContext &Context, claimed_file &F,
}
break;
- case LDPR_PREVAILING_DEF_IRONLY_EXP: {
- // We can only check for address uses after we merge the modules. The
- // reason is that this GV might have a copy in another module
- // and in that module the address might be significant, but that
- // copy will be LDPR_PREEMPTED_IR.
- Maybe.insert(GV->getName());
+ case LDPR_PREVAILING_DEF_IRONLY_EXP:
Keep.push_back(GV);
break;
}
- }
freeSymName(Sym);
}
@@ -896,12 +893,11 @@ static ld_plugin_status allSymbolsReadHook(raw_fd_ostream *ApiFile) {
std::string DefaultTriple = sys::getDefaultTargetTriple();
StringSet<> Internalize;
- StringSet<> Maybe;
for (claimed_file &F : Modules) {
PluginInputFile InputFile(F.handle);
std::vector<GlobalValue *> Keep;
- std::unique_ptr<Module> M = getModuleForFile(
- Context, F, InputFile.file(), ApiFile, Internalize, Maybe, Keep);
+ std::unique_ptr<Module> M = getModuleForFile(Context, F, InputFile.file(),
+ ApiFile, Internalize, Keep);
if (!options::triple.empty())
M->setTargetTriple(options::triple.c_str());
else if (M->getTargetTriple().empty())
@@ -917,15 +913,6 @@ static ld_plugin_status allSymbolsReadHook(raw_fd_ostream *ApiFile) {
internalize(*GV);
}
- for (const auto &Name : Maybe) {
- GlobalValue *GV = Combined->getNamedValue(Name.first());
- if (!GV)
- continue;
- GV->setLinkage(GlobalValue::LinkOnceODRLinkage);
- if (canBeOmittedFromSymbolTable(GV))
- internalize(*GV);
- }
-
if (options::TheOutputType == options::OT_DISABLE)
return LDPS_OK;
More information about the llvm-commits
mailing list