mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2025-01-31 20:51:52 +01:00
[ThinLTO] Convert dead alias to declarations
Summary: This complements the fixes in r323633 and r324075 which drop the definitions of dead functions and variables, respectively. Fixes PR36208. Reviewers: grimar, rafael Subscribers: mehdi_amini, llvm-commits, inglorion Differential Revision: https://reviews.llvm.org/D42856 llvm-svn: 324242
This commit is contained in:
parent
9179adab3b
commit
2d6d4466b4
@ -122,8 +122,9 @@ void computeDeadSymbols(
|
|||||||
const DenseSet<GlobalValue::GUID> &GUIDPreservedSymbols,
|
const DenseSet<GlobalValue::GUID> &GUIDPreservedSymbols,
|
||||||
function_ref<PrevailingType(GlobalValue::GUID)> isPrevailing);
|
function_ref<PrevailingType(GlobalValue::GUID)> isPrevailing);
|
||||||
|
|
||||||
/// Converts value \p GV to declaration.
|
/// Converts value \p GV to declaration, or replaces with a declaration if
|
||||||
void convertToDeclaration(GlobalValue &GV);
|
/// it is an alias. Returns true if converted, false if replaced.
|
||||||
|
bool convertToDeclaration(GlobalValue &GV);
|
||||||
|
|
||||||
/// Compute the set of summaries needed for a ThinLTO backend compilation of
|
/// Compute the set of summaries needed for a ThinLTO backend compilation of
|
||||||
/// \p ModulePath.
|
/// \p ModulePath.
|
||||||
|
@ -401,18 +401,14 @@ Error lto::backend(Config &C, AddStreamFn AddStream,
|
|||||||
|
|
||||||
static void dropDeadSymbols(Module &Mod, const GVSummaryMapTy &DefinedGlobals,
|
static void dropDeadSymbols(Module &Mod, const GVSummaryMapTy &DefinedGlobals,
|
||||||
const ModuleSummaryIndex &Index) {
|
const ModuleSummaryIndex &Index) {
|
||||||
auto MaybeDrop = [&](GlobalValue &GV) {
|
std::vector<GlobalValue *> ReplacedGlobals;
|
||||||
|
for (auto &GV : Mod.global_values())
|
||||||
if (GlobalValueSummary *GVS = DefinedGlobals.lookup(GV.getGUID()))
|
if (GlobalValueSummary *GVS = DefinedGlobals.lookup(GV.getGUID()))
|
||||||
if (!Index.isGlobalValueLive(GVS))
|
if (!Index.isGlobalValueLive(GVS) && !convertToDeclaration(GV))
|
||||||
convertToDeclaration(GV);
|
ReplacedGlobals.push_back(&GV);
|
||||||
};
|
|
||||||
|
|
||||||
// Process functions and global now.
|
for (GlobalValue *GV : ReplacedGlobals)
|
||||||
// FIXME: add support for aliases (needs support in convertToDeclaration).
|
GV->eraseFromParent();
|
||||||
for (auto &GV : Mod)
|
|
||||||
MaybeDrop(GV);
|
|
||||||
for (auto &GV : Mod.globals())
|
|
||||||
MaybeDrop(GV);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Error lto::thinBackend(Config &Conf, unsigned Task, AddStreamFn AddStream,
|
Error lto::thinBackend(Config &Conf, unsigned Task, AddStreamFn AddStream,
|
||||||
|
@ -613,7 +613,7 @@ llvm::EmitImportsFiles(StringRef ModulePath, StringRef OutputFilename,
|
|||||||
return std::error_code();
|
return std::error_code();
|
||||||
}
|
}
|
||||||
|
|
||||||
void llvm::convertToDeclaration(GlobalValue &GV) {
|
bool llvm::convertToDeclaration(GlobalValue &GV) {
|
||||||
DEBUG(dbgs() << "Converting to a declaration: `" << GV.getName() << "\n");
|
DEBUG(dbgs() << "Converting to a declaration: `" << GV.getName() << "\n");
|
||||||
if (Function *F = dyn_cast<Function>(&GV)) {
|
if (Function *F = dyn_cast<Function>(&GV)) {
|
||||||
F->deleteBody();
|
F->deleteBody();
|
||||||
@ -624,14 +624,24 @@ void llvm::convertToDeclaration(GlobalValue &GV) {
|
|||||||
V->setLinkage(GlobalValue::ExternalLinkage);
|
V->setLinkage(GlobalValue::ExternalLinkage);
|
||||||
V->clearMetadata();
|
V->clearMetadata();
|
||||||
V->setComdat(nullptr);
|
V->setComdat(nullptr);
|
||||||
} else
|
} else {
|
||||||
// For now we don't resolve or drop aliases. Once we do we'll
|
GlobalValue *NewGV;
|
||||||
// need to add support here for creating either a function or
|
if (GV.getValueType()->isFunctionTy())
|
||||||
// variable declaration, and return the new GlobalValue* for
|
NewGV =
|
||||||
// the caller to use.
|
Function::Create(cast<FunctionType>(GV.getValueType()),
|
||||||
// Support of dropping aliases is required for correct dead code
|
GlobalValue::ExternalLinkage, "", GV.getParent());
|
||||||
// elimination performed in thin LTO backends (see 'dropDeadSymbols').
|
else
|
||||||
llvm_unreachable("Expected function or variable");
|
NewGV =
|
||||||
|
new GlobalVariable(*GV.getParent(), GV.getValueType(),
|
||||||
|
/*isConstant*/ false, GlobalValue::ExternalLinkage,
|
||||||
|
/*init*/ nullptr, "",
|
||||||
|
/*insertbefore*/ nullptr, GV.getThreadLocalMode(),
|
||||||
|
GV.getType()->getAddressSpace());
|
||||||
|
NewGV->takeName(&GV);
|
||||||
|
GV.replaceAllUsesWith(NewGV);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Fixup WeakForLinker linkages in \p TheModule based on summary analysis.
|
/// Fixup WeakForLinker linkages in \p TheModule based on summary analysis.
|
||||||
@ -666,9 +676,13 @@ void llvm::thinLTOResolveWeakForLinkerModule(
|
|||||||
// interposable property and possibly get inlined. Simply drop
|
// interposable property and possibly get inlined. Simply drop
|
||||||
// the definition in that case.
|
// the definition in that case.
|
||||||
if (GlobalValue::isAvailableExternallyLinkage(NewLinkage) &&
|
if (GlobalValue::isAvailableExternallyLinkage(NewLinkage) &&
|
||||||
GlobalValue::isInterposableLinkage(GV.getLinkage()))
|
GlobalValue::isInterposableLinkage(GV.getLinkage())) {
|
||||||
convertToDeclaration(GV);
|
if (!convertToDeclaration(GV))
|
||||||
else {
|
// FIXME: Change this to collect replaced GVs and later erase
|
||||||
|
// them from the parent module once thinLTOResolveWeakForLinkerGUID is
|
||||||
|
// changed to enable this for aliases.
|
||||||
|
llvm_unreachable("Expected GV to be converted");
|
||||||
|
} else {
|
||||||
DEBUG(dbgs() << "ODR fixing up linkage for `" << GV.getName() << "` from "
|
DEBUG(dbgs() << "ODR fixing up linkage for `" << GV.getName() << "` from "
|
||||||
<< GV.getLinkage() << " to " << NewLinkage << "\n");
|
<< GV.getLinkage() << " to " << NewLinkage << "\n");
|
||||||
GV.setLinkage(NewLinkage);
|
GV.setLinkage(NewLinkage);
|
||||||
|
43
test/LTO/Resolution/X86/not-prevailing-alias.ll
Normal file
43
test/LTO/Resolution/X86/not-prevailing-alias.ll
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
; Test to ensure that dead alias are dropped by converting to a declaration
|
||||||
|
; RUN: opt -module-summary %s -o %t1.bc
|
||||||
|
; RUN: llvm-lto2 run %t1.bc -r %t1.bc,barAlias,x \
|
||||||
|
; RUN: -r %t1.bc,bar,x -r %t1.bc,zed,px \
|
||||||
|
; RUN: -r %t1.bc,var,x -r %t1.bc,varAlias,x \
|
||||||
|
; RUN: -o %t2.o -save-temps
|
||||||
|
|
||||||
|
; Check that bar and barAlias were dropped to declarations
|
||||||
|
; RUN: llvm-dis %t2.o.1.1.promote.bc -o - | FileCheck %s --check-prefix=DROP
|
||||||
|
; DROP-DAG: declare void @bar()
|
||||||
|
; DROP-DAG: declare void @barAlias()
|
||||||
|
; DROP-DAG: @var = external global i32
|
||||||
|
; DROP-DAG: @varAlias = external global i32
|
||||||
|
|
||||||
|
; Check that 'barAlias' and 'varAlias' were not inlined.
|
||||||
|
; RUN: llvm-objdump -d %t2.o.1 | FileCheck %s
|
||||||
|
; CHECK: zed:
|
||||||
|
; CHECK-NEXT: {{.*}} pushq
|
||||||
|
; CHECK-NEXT: {{.*}} callq 0
|
||||||
|
; CHECK-NEXT: movq (%rip), %rax
|
||||||
|
|
||||||
|
; Check that 'barAlias' and 'varAlias' produced as undefined.
|
||||||
|
; RUN: llvm-readelf --symbols %t2.o.1 | FileCheck %s --check-prefix=SYMBOLS
|
||||||
|
; SYMBOLS: NOTYPE GLOBAL DEFAULT UND barAlias
|
||||||
|
; SYMBOLS: NOTYPE GLOBAL DEFAULT UND varAlias
|
||||||
|
; SYMBOLS: FUNC GLOBAL DEFAULT 2 zed
|
||||||
|
|
||||||
|
target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
|
||||||
|
target triple = "x86_64-unknown-linux-gnu"
|
||||||
|
|
||||||
|
@barAlias = alias void(), void()* @bar
|
||||||
|
define void @bar() {
|
||||||
|
ret void
|
||||||
|
}
|
||||||
|
|
||||||
|
@var = global i32 99
|
||||||
|
@varAlias = alias i32, i32* @var
|
||||||
|
|
||||||
|
define i32 @zed() {
|
||||||
|
call void @barAlias()
|
||||||
|
%1 = load i32, i32* @varAlias, align 4
|
||||||
|
ret i32 %1
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user