mirror of
https://github.com/RPCSX/llvm.git
synced 2024-11-25 04:39:44 +00:00
Always traverse GlobalVariable initializer when computing the export list
Summary: We are always importing the initializer for a GlobalVariable. So if a GlobalVariable is in the export-list, we pull in any refs as well. Reviewers: tejohnson Subscribers: llvm-commits Differential Revision: http://reviews.llvm.org/D19102 From: Mehdi Amini <mehdi.amini@apple.com> git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@267303 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
1e7e2b2b55
commit
aa73713b9a
@ -131,23 +131,54 @@ static const GlobalValueSummary *selectCallee(GlobalValue::GUID GUID,
|
||||
return selectCallee(CalleeInfoList->second, Threshold);
|
||||
}
|
||||
|
||||
/// Return true if the global \p GUID is exported by module \p ExportModulePath.
|
||||
static bool isGlobalExported(const ModuleSummaryIndex &Index,
|
||||
StringRef ExportModulePath,
|
||||
GlobalValue::GUID GUID) {
|
||||
auto CalleeInfoList = Index.findGlobalValueInfoList(GUID);
|
||||
if (CalleeInfoList == Index.end())
|
||||
// This global does not have a summary, it is not part of the ThinLTO
|
||||
// process
|
||||
return false;
|
||||
auto DefinedInCalleeModule = llvm::find_if(
|
||||
CalleeInfoList->second,
|
||||
[&](const std::unique_ptr<GlobalValueInfo> &GlobInfo) {
|
||||
auto *Summary = GlobInfo->summary();
|
||||
assert(Summary && "Unexpected GlobalValueInfo without summary");
|
||||
return Summary->modulePath() == ExportModulePath;
|
||||
});
|
||||
return (DefinedInCalleeModule != CalleeInfoList->second.end());
|
||||
/// Mark the global \p GUID as export by module \p ExportModulePath if found in
|
||||
/// this module. If it is a GlobalVariable, we also mark any referenced global
|
||||
/// in the current module as exported.
|
||||
static void exportGlobalInModule(const ModuleSummaryIndex &Index,
|
||||
StringRef ExportModulePath,
|
||||
GlobalValue::GUID GUID,
|
||||
FunctionImporter::ExportSetTy &ExportList) {
|
||||
auto FindGlobalInfoInModule =
|
||||
[&](GlobalValue::GUID GUID) -> GlobalValueInfo *{
|
||||
auto InfoList = Index.findGlobalValueInfoList(GUID);
|
||||
if (InfoList == Index.end())
|
||||
// This global does not have a summary, it is not part of the ThinLTO
|
||||
// process
|
||||
return nullptr;
|
||||
auto Info = llvm::find_if(
|
||||
InfoList->second,
|
||||
[&](const std::unique_ptr<GlobalValueInfo> &GlobInfo) {
|
||||
auto *Summary = GlobInfo->summary();
|
||||
assert(Summary && "Unexpected GlobalValueInfo without summary");
|
||||
return Summary->modulePath() == ExportModulePath;
|
||||
});
|
||||
if (Info == InfoList->second.end())
|
||||
return nullptr;
|
||||
return Info->get();
|
||||
};
|
||||
|
||||
auto *GVInfo = FindGlobalInfoInModule(GUID);
|
||||
if (!GVInfo)
|
||||
return;
|
||||
// We found it in the current module, mark as exported
|
||||
ExportList.insert(GUID);
|
||||
|
||||
auto *Summary = GVInfo->summary();
|
||||
auto GVS = dyn_cast<GlobalVarSummary>(Summary);
|
||||
if (!GVS)
|
||||
return;
|
||||
// FunctionImportGlobalProcessing::doPromoteLocalToGlobal() will always
|
||||
// trigger importing the initializer for `constant unnamed addr` globals that
|
||||
// are referenced. We conservatively export all the referenced symbols for
|
||||
// every global to workaround this, so that the ExportList is accurate.
|
||||
// FIXME: with a "isConstant" flag in the summary we could be more targetted.
|
||||
for (auto &Ref : GVS->refs()) {
|
||||
auto GUID = Ref.getGUID();
|
||||
auto *RefInfo = FindGlobalInfoInModule(GUID);
|
||||
if (RefInfo)
|
||||
// Found a ref in the current module, mark it as exported
|
||||
ExportList.insert(GUID);
|
||||
}
|
||||
}
|
||||
|
||||
using EdgeInfo = std::pair<const FunctionSummary *, unsigned /* Threshold */>;
|
||||
@ -211,13 +242,11 @@ static void computeImportForFunction(
|
||||
// to the outside if they are defined in the same source module.
|
||||
for (auto &Edge : ResolvedCalleeSummary->calls()) {
|
||||
auto CalleeGUID = Edge.first.getGUID();
|
||||
if (isGlobalExported(Index, ExportModulePath, CalleeGUID))
|
||||
ExportList.insert(CalleeGUID);
|
||||
exportGlobalInModule(Index, ExportModulePath, CalleeGUID, ExportList);
|
||||
}
|
||||
for (auto &Ref : ResolvedCalleeSummary->refs()) {
|
||||
auto GUID = Ref.getGUID();
|
||||
if (isGlobalExported(Index, ExportModulePath, GUID))
|
||||
ExportList.insert(GUID);
|
||||
exportGlobalInModule(Index, ExportModulePath, GUID, ExportList);
|
||||
}
|
||||
}
|
||||
|
||||
|
16
test/ThinLTO/X86/Inputs/referenced_by_constant.ll
Normal file
16
test/ThinLTO/X86/Inputs/referenced_by_constant.ll
Normal file
@ -0,0 +1,16 @@
|
||||
|
||||
target datalayout = "e-m:o-i64:64-f80:128-n8:16:32:64-S128"
|
||||
target triple = "x86_64-apple-macosx10.11.0"
|
||||
|
||||
define void @referencedbyglobal() {
|
||||
ret void
|
||||
}
|
||||
|
||||
@someglobal = internal unnamed_addr constant i8* bitcast (void ()* @referencedbyglobal to i8*)
|
||||
@ptr = global i8** null
|
||||
|
||||
define void @bar() #0 align 2 {
|
||||
store i8** getelementptr inbounds (i8*, i8** @someglobal, i64 0) , i8*** @ptr, align 8
|
||||
ret void
|
||||
}
|
||||
|
21
test/ThinLTO/X86/referenced_by_constant.ll
Normal file
21
test/ThinLTO/X86/referenced_by_constant.ll
Normal file
@ -0,0 +1,21 @@
|
||||
; Do setup work for all below tests: generate bitcode and combined index
|
||||
; RUN: opt -module-summary %s -o %t.bc
|
||||
; RUN: opt -module-summary %p/Inputs/referenced_by_constant.ll -o %t2.bc
|
||||
; RUN: llvm-lto -thinlto-action=thinlink -o %t3.bc %t.bc %t2.bc
|
||||
|
||||
; Check the import side: we import bar() and @someglobal, but not @referencedbyglobal()
|
||||
; RUN: llvm-lto -thinlto-action=import %t.bc -thinlto-index=%t3.bc -o - | llvm-dis -o - | FileCheck %s --check-prefix=IMPORT
|
||||
; IMPORT: @someglobal.llvm.0 =
|
||||
; IMPORT: define available_externally void @bar()
|
||||
; IMPORT: declare void @referencedbyglobal()
|
||||
|
||||
target datalayout = "e-m:o-i64:64-f80:128-n8:16:32:64-S128"
|
||||
target triple = "x86_64-apple-macosx10.11.0"
|
||||
|
||||
declare void @bar()
|
||||
|
||||
define void @foo() {
|
||||
call void @bar()
|
||||
ret void
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user