1
0
mirror of https://github.com/RPCS3/llvm-mirror.git synced 2024-11-22 18:54:02 +01:00

ModuleSummaryAnalysis: Correctly handle refs from function inline asm to module inline asm.

If a function contains inline asm and the module-level inline asm
contains the definition of a local symbol, prevent the function from
being imported in case the function-level inline asm refers to a
symbol in the module-level inline asm.

Differential Revision: https://reviews.llvm.org/D37370

llvm-svn: 312332
This commit is contained in:
Peter Collingbourne 2017-09-01 16:24:02 +00:00
parent 1bbda74bca
commit a538f8987b
2 changed files with 72 additions and 54 deletions

View File

@ -198,7 +198,7 @@ static void addIntrinsicToSummary(
static void static void
computeFunctionSummary(ModuleSummaryIndex &Index, const Module &M, computeFunctionSummary(ModuleSummaryIndex &Index, const Module &M,
const Function &F, BlockFrequencyInfo *BFI, const Function &F, BlockFrequencyInfo *BFI,
ProfileSummaryInfo *PSI, bool HasLocalsInUsed, ProfileSummaryInfo *PSI, bool HasLocalsInUsedOrAsm,
DenseSet<GlobalValue::GUID> &CantBePromoted) { DenseSet<GlobalValue::GUID> &CantBePromoted) {
// Summary not currently supported for anonymous functions, they should // Summary not currently supported for anonymous functions, they should
// have been named. // have been named.
@ -234,7 +234,7 @@ computeFunctionSummary(ModuleSummaryIndex &Index, const Module &M,
// a local value from inline assembly to ensure we don't export a // a local value from inline assembly to ensure we don't export a
// reference (which would require renaming and promotion of the // reference (which would require renaming and promotion of the
// referenced value). // referenced value).
if (HasLocalsInUsed && CI && CI->isInlineAsm()) if (HasLocalsInUsedOrAsm && CI && CI->isInlineAsm())
HasInlineAsmMaybeReferencingInternal = true; HasInlineAsmMaybeReferencingInternal = true;
auto *CalledValue = CS.getCalledValue(); auto *CalledValue = CS.getCalledValue();
@ -382,6 +382,58 @@ ModuleSummaryIndex llvm::buildModuleSummaryIndex(
} }
} }
bool HasLocalInlineAsmSymbol = false;
if (!M.getModuleInlineAsm().empty()) {
// Collect the local values defined by module level asm, and set up
// summaries for these symbols so that they can be marked as NoRename,
// to prevent export of any use of them in regular IR that would require
// renaming within the module level asm. Note we don't need to create a
// summary for weak or global defs, as they don't need to be flagged as
// NoRename, and defs in module level asm can't be imported anyway.
// Also, any values used but not defined within module level asm should
// be listed on the llvm.used or llvm.compiler.used global and marked as
// referenced from there.
ModuleSymbolTable::CollectAsmSymbols(
M, [&](StringRef Name, object::BasicSymbolRef::Flags Flags) {
// Symbols not marked as Weak or Global are local definitions.
if (Flags & (object::BasicSymbolRef::SF_Weak |
object::BasicSymbolRef::SF_Global))
return;
HasLocalInlineAsmSymbol = true;
GlobalValue *GV = M.getNamedValue(Name);
if (!GV)
return;
assert(GV->isDeclaration() && "Def in module asm already has definition");
GlobalValueSummary::GVFlags GVFlags(GlobalValue::InternalLinkage,
/* NotEligibleToImport = */ true,
/* Live = */ true);
CantBePromoted.insert(GlobalValue::getGUID(Name));
// Create the appropriate summary type.
if (Function *F = dyn_cast<Function>(GV)) {
std::unique_ptr<FunctionSummary> Summary =
llvm::make_unique<FunctionSummary>(
GVFlags, 0,
FunctionSummary::FFlags{
F->hasFnAttribute(Attribute::ReadNone),
F->hasFnAttribute(Attribute::ReadOnly),
F->hasFnAttribute(Attribute::NoRecurse),
F->returnDoesNotAlias()},
ArrayRef<ValueInfo>{}, ArrayRef<FunctionSummary::EdgeTy>{},
ArrayRef<GlobalValue::GUID>{},
ArrayRef<FunctionSummary::VFuncId>{},
ArrayRef<FunctionSummary::VFuncId>{},
ArrayRef<FunctionSummary::ConstVCall>{},
ArrayRef<FunctionSummary::ConstVCall>{});
Index.addGlobalValueSummary(Name, std::move(Summary));
} else {
std::unique_ptr<GlobalVarSummary> Summary =
llvm::make_unique<GlobalVarSummary>(GVFlags,
ArrayRef<ValueInfo>{});
Index.addGlobalValueSummary(Name, std::move(Summary));
}
});
}
// Compute summaries for all functions defined in module, and save in the // Compute summaries for all functions defined in module, and save in the
// index. // index.
for (auto &F : M) { for (auto &F : M) {
@ -399,7 +451,8 @@ ModuleSummaryIndex llvm::buildModuleSummaryIndex(
BFI = BFIPtr.get(); BFI = BFIPtr.get();
} }
computeFunctionSummary(Index, M, F, BFI, PSI, !LocalsUsed.empty(), computeFunctionSummary(Index, M, F, BFI, PSI,
!LocalsUsed.empty() || HasLocalInlineAsmSymbol,
CantBePromoted); CantBePromoted);
} }
@ -437,57 +490,6 @@ ModuleSummaryIndex llvm::buildModuleSummaryIndex(
setLiveRoot(Index, "llvm.global_dtors"); setLiveRoot(Index, "llvm.global_dtors");
setLiveRoot(Index, "llvm.global.annotations"); setLiveRoot(Index, "llvm.global.annotations");
if (!M.getModuleInlineAsm().empty()) {
// Collect the local values defined by module level asm, and set up
// summaries for these symbols so that they can be marked as NoRename,
// to prevent export of any use of them in regular IR that would require
// renaming within the module level asm. Note we don't need to create a
// summary for weak or global defs, as they don't need to be flagged as
// NoRename, and defs in module level asm can't be imported anyway.
// Also, any values used but not defined within module level asm should
// be listed on the llvm.used or llvm.compiler.used global and marked as
// referenced from there.
ModuleSymbolTable::CollectAsmSymbols(
M, [&M, &Index, &CantBePromoted](StringRef Name,
object::BasicSymbolRef::Flags Flags) {
// Symbols not marked as Weak or Global are local definitions.
if (Flags & (object::BasicSymbolRef::SF_Weak |
object::BasicSymbolRef::SF_Global))
return;
GlobalValue *GV = M.getNamedValue(Name);
if (!GV)
return;
assert(GV->isDeclaration() && "Def in module asm already has definition");
GlobalValueSummary::GVFlags GVFlags(GlobalValue::InternalLinkage,
/* NotEligibleToImport = */ true,
/* Live = */ true);
CantBePromoted.insert(GlobalValue::getGUID(Name));
// Create the appropriate summary type.
if (Function *F = dyn_cast<Function>(GV)) {
std::unique_ptr<FunctionSummary> Summary =
llvm::make_unique<FunctionSummary>(
GVFlags, 0,
FunctionSummary::FFlags{
F->hasFnAttribute(Attribute::ReadNone),
F->hasFnAttribute(Attribute::ReadOnly),
F->hasFnAttribute(Attribute::NoRecurse),
F->returnDoesNotAlias()},
ArrayRef<ValueInfo>{}, ArrayRef<FunctionSummary::EdgeTy>{},
ArrayRef<GlobalValue::GUID>{},
ArrayRef<FunctionSummary::VFuncId>{},
ArrayRef<FunctionSummary::VFuncId>{},
ArrayRef<FunctionSummary::ConstVCall>{},
ArrayRef<FunctionSummary::ConstVCall>{});
Index.addGlobalValueSummary(Name, std::move(Summary));
} else {
std::unique_ptr<GlobalVarSummary> Summary =
llvm::make_unique<GlobalVarSummary>(GVFlags,
ArrayRef<ValueInfo>{});
Index.addGlobalValueSummary(Name, std::move(Summary));
}
});
}
bool IsThinLTO = true; bool IsThinLTO = true;
if (auto *MD = if (auto *MD =
mdconst::extract_or_null<ConstantInt>(M.getModuleFlag("ThinLTO"))) mdconst::extract_or_null<ConstantInt>(M.getModuleFlag("ThinLTO")))

View File

@ -0,0 +1,16 @@
; REQUIRES: arm-registered-target
; RUN: opt -module-summary -o %t %s
; RUN: llvm-bcanalyzer -dump %t | FileCheck %s
target datalayout = "e-m:e-p:32:32-i64:64-v128:64:128-a:0:32-n32-S64"
target triple = "thumbv7--linux-android"
module asm "asm:"
module asm "bx lr"
; NotEligibleToImport
; CHECK: <PERMODULE {{.*}} op1=16
define void @f() {
call void asm sideeffect "bl asm\0A", ""()
ret void
}