diff options
| author | Vlad Tsyrklevich <vlad@tsyrklevich.net> | 2018-03-08 18:48:03 +0000 |
|---|---|---|
| committer | Vlad Tsyrklevich <vlad@tsyrklevich.net> | 2018-03-08 18:48:03 +0000 |
| commit | 7b66ef10364d20acfa83934e04a04b2f799a0396 (patch) | |
| tree | 6ef5beba6fca6d412c9abcfbf21323ab95f61ca3 | |
| parent | d5e5992f9a2ef811536d42571de7d312774ad928 (diff) | |
| download | bcm5719-llvm-7b66ef10364d20acfa83934e04a04b2f799a0396.tar.gz bcm5719-llvm-7b66ef10364d20acfa83934e04a04b2f799a0396.zip | |
[ThinLTO] Keep available_externally symbols live
Summary:
This change fixes PR36483. The bug was originally introduced by a change
that marked non-prevailing symbols dead. This broke LowerTypeTests
handling of available_externally functions, which are non-prevailing.
LowerTypeTests uses liveness information to avoid emitting thunks for
unused functions.
Marking available_externally functions dead is incorrect, the functions
are used though the function definitions are not. This change keeps them
live, and lets the EliminateAvailableExternally/GlobalDCE passes remove
them later instead.
I've also enabled EliminateAvailableExternally for all optimization
levels, I believe it being disabled for O1 was an oversight.
Reviewers: pcc, tejohnson
Reviewed By: tejohnson
Subscribers: grimar, mehdi_amini, inglorion, eraman, llvm-commits
Differential Revision: https://reviews.llvm.org/D43690
llvm-svn: 327041
| -rw-r--r-- | llvm/lib/Transforms/IPO/FunctionImport.cpp | 22 | ||||
| -rw-r--r-- | llvm/test/ThinLTO/X86/deadstrip.ll | 9 | ||||
| -rw-r--r-- | llvm/test/Transforms/FunctionImport/Inputs/not-prevailing.ll | 6 | ||||
| -rw-r--r-- | llvm/test/Transforms/FunctionImport/not-prevailing.ll | 18 |
4 files changed, 52 insertions, 3 deletions
diff --git a/llvm/lib/Transforms/IPO/FunctionImport.cpp b/llvm/lib/Transforms/IPO/FunctionImport.cpp index b68058cbeea..c106f1105e7 100644 --- a/llvm/lib/Transforms/IPO/FunctionImport.cpp +++ b/llvm/lib/Transforms/IPO/FunctionImport.cpp @@ -544,9 +544,25 @@ void llvm::computeDeadSymbols( if (S->isLive()) return; - // We do not keep live symbols that are known to be non-prevailing. - if (isPrevailing(VI.getGUID()) == PrevailingType::No) - return; + // We only keep live symbols that are known to be non-prevailing if any are + // available_externally. Those symbols are discarded later in the + // EliminateAvailableExternally pass and setting them to not-live breaks + // downstreams users of liveness information (PR36483). + if (isPrevailing(VI.getGUID()) == PrevailingType::No) { + bool AvailableExternally = false; + for (auto &S : VI.getSummaryList()) + if (S->linkage() == GlobalValue::AvailableExternallyLinkage) + AvailableExternally = true; + + if (!AvailableExternally) + return; + +#ifndef NDEBUG + for (auto &S : VI.getSummaryList()) + assert(!GlobalValue::isInterposableLinkage(S->linkage()) && + "Symbol with interposable and available_externally linkages"); +#endif + } for (auto &S : VI.getSummaryList()) S->setLive(true); diff --git a/llvm/test/ThinLTO/X86/deadstrip.ll b/llvm/test/ThinLTO/X86/deadstrip.ll index e3f16a8e0b3..827ad225eda 100644 --- a/llvm/test/ThinLTO/X86/deadstrip.ll +++ b/llvm/test/ThinLTO/X86/deadstrip.ll @@ -14,6 +14,7 @@ ; RUN: -r %t1.bc,_dead_func,pl \ ; RUN: -r %t1.bc,_baz,l \ ; RUN: -r %t1.bc,_boo,l \ +; RUN: -r %t1.bc,_live_available_externally_func,l \ ; RUN: -r %t2.bc,_baz,pl \ ; RUN: -r %t2.bc,_boo,pl \ ; RUN: -r %t2.bc,_dead_func,l \ @@ -27,6 +28,8 @@ ; COMBINED-DAG: <COMBINED {{.*}} op2=119 ; Live, dso_local, Internal ; COMBINED-DAG: <COMBINED {{.*}} op2=103 +; Live, Local, AvailableExternally +; COMBINED-DAG: <COMBINED {{.*}} op2=97 ; Live, Local, External ; COMBINED-DAG: <COMBINED {{.*}} op2=96 ; COMBINED-DAG: <COMBINED {{.*}} op2=96 @@ -79,6 +82,7 @@ ; RUN: -r %t1.bc,_dead_func,pl \ ; RUN: -r %t1.bc,_baz,l \ ; RUN: -r %t1.bc,_boo,l \ +; RUN: -r %t1.bc,_live_available_externally_func,l \ ; RUN: -r %t3.bc,_baz,pl \ ; RUN: -r %t3.bc,_boo,pl \ ; RUN: -r %t3.bc,_dead_func,l \ @@ -124,8 +128,13 @@ define void @dead_func() { ret void } +define available_externally void @live_available_externally_func() { + ret void +} + define void @main() { call void @bar() call void @bar_internal() + call void @live_available_externally_func() ret void } diff --git a/llvm/test/Transforms/FunctionImport/Inputs/not-prevailing.ll b/llvm/test/Transforms/FunctionImport/Inputs/not-prevailing.ll new file mode 100644 index 00000000000..ca17d7f377c --- /dev/null +++ b/llvm/test/Transforms/FunctionImport/Inputs/not-prevailing.ll @@ -0,0 +1,6 @@ +target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" +target triple = "x86_64-unknown-linux-gnu" + +define weak i32 @foo() { + ret i32 0 +} diff --git a/llvm/test/Transforms/FunctionImport/not-prevailing.ll b/llvm/test/Transforms/FunctionImport/not-prevailing.ll new file mode 100644 index 00000000000..1dcdbe60bb0 --- /dev/null +++ b/llvm/test/Transforms/FunctionImport/not-prevailing.ll @@ -0,0 +1,18 @@ +; RUN: opt -module-summary %s -o %t1.bc +; RUN: opt -module-summary -o %t2.bc %S/Inputs/not-prevailing.ll +; RUN: not --crash llvm-lto2 run -o %t3.bc %t1.bc %t2.bc -r %t1.bc,bar,px \ +; RUN: -r %t1.bc,foo,x -r %t2.bc,foo,x -save-temps 2>&1 | FileCheck %s + +; CHECK: Assertion {{.*}} "Symbol with interposable and available_externally linkages"' failed + +target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" +target triple = "x86_64-unknown-linux-gnu" + +define available_externally i32 @foo() { + ret i32 1 +} + +define i32 @bar() { + %1 = call i32 @foo() + ret i32 %1 +} |

