forked from OSchip/llvm-project
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:
parent
6b54c7e11b
commit
5e8b94c137
|
@ -198,7 +198,7 @@ static void addIntrinsicToSummary(
|
|||
static void
|
||||
computeFunctionSummary(ModuleSummaryIndex &Index, const Module &M,
|
||||
const Function &F, BlockFrequencyInfo *BFI,
|
||||
ProfileSummaryInfo *PSI, bool HasLocalsInUsed,
|
||||
ProfileSummaryInfo *PSI, bool HasLocalsInUsedOrAsm,
|
||||
DenseSet<GlobalValue::GUID> &CantBePromoted) {
|
||||
// Summary not currently supported for anonymous functions, they should
|
||||
// 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
|
||||
// reference (which would require renaming and promotion of the
|
||||
// referenced value).
|
||||
if (HasLocalsInUsed && CI && CI->isInlineAsm())
|
||||
if (HasLocalsInUsedOrAsm && CI && CI->isInlineAsm())
|
||||
HasInlineAsmMaybeReferencingInternal = true;
|
||||
|
||||
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
|
||||
// index.
|
||||
for (auto &F : M) {
|
||||
|
@ -399,7 +451,8 @@ ModuleSummaryIndex llvm::buildModuleSummaryIndex(
|
|||
BFI = BFIPtr.get();
|
||||
}
|
||||
|
||||
computeFunctionSummary(Index, M, F, BFI, PSI, !LocalsUsed.empty(),
|
||||
computeFunctionSummary(Index, M, F, BFI, PSI,
|
||||
!LocalsUsed.empty() || HasLocalInlineAsmSymbol,
|
||||
CantBePromoted);
|
||||
}
|
||||
|
||||
|
@ -437,57 +490,6 @@ ModuleSummaryIndex llvm::buildModuleSummaryIndex(
|
|||
setLiveRoot(Index, "llvm.global_dtors");
|
||||
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;
|
||||
if (auto *MD =
|
||||
mdconst::extract_or_null<ConstantInt>(M.getModuleFlag("ThinLTO")))
|
||||
|
|
|
@ -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
|
||||
}
|
Loading…
Reference in New Issue