summaryrefslogtreecommitdiff
path: root/lib/Analysis/ModuleSummaryAnalysis.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lib/Analysis/ModuleSummaryAnalysis.cpp')
-rw-r--r--lib/Analysis/ModuleSummaryAnalysis.cpp172
1 files changed, 110 insertions, 62 deletions
diff --git a/lib/Analysis/ModuleSummaryAnalysis.cpp b/lib/Analysis/ModuleSummaryAnalysis.cpp
index e9e354ebb88f..d54fb700200d 100644
--- a/lib/Analysis/ModuleSummaryAnalysis.cpp
+++ b/lib/Analysis/ModuleSummaryAnalysis.cpp
@@ -13,23 +13,47 @@
//===----------------------------------------------------------------------===//
#include "llvm/Analysis/ModuleSummaryAnalysis.h"
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/DenseSet.h"
#include "llvm/ADT/MapVector.h"
+#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/SetVector.h"
-#include "llvm/ADT/Triple.h"
+#include "llvm/ADT/SmallPtrSet.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/StringRef.h"
#include "llvm/Analysis/BlockFrequencyInfo.h"
-#include "llvm/Analysis/BlockFrequencyInfoImpl.h"
#include "llvm/Analysis/BranchProbabilityInfo.h"
#include "llvm/Analysis/IndirectCallPromotionAnalysis.h"
#include "llvm/Analysis/LoopInfo.h"
#include "llvm/Analysis/ProfileSummaryInfo.h"
#include "llvm/Analysis/TypeMetadataUtils.h"
+#include "llvm/IR/Attributes.h"
+#include "llvm/IR/BasicBlock.h"
#include "llvm/IR/CallSite.h"
+#include "llvm/IR/Constant.h"
+#include "llvm/IR/Constants.h"
#include "llvm/IR/Dominators.h"
-#include "llvm/IR/InstIterator.h"
+#include "llvm/IR/Function.h"
+#include "llvm/IR/GlobalAlias.h"
+#include "llvm/IR/GlobalValue.h"
+#include "llvm/IR/GlobalVariable.h"
+#include "llvm/IR/Instructions.h"
#include "llvm/IR/IntrinsicInst.h"
-#include "llvm/IR/ValueSymbolTable.h"
+#include "llvm/IR/Intrinsics.h"
+#include "llvm/IR/Metadata.h"
+#include "llvm/IR/Module.h"
+#include "llvm/IR/ModuleSummaryIndex.h"
+#include "llvm/IR/Use.h"
+#include "llvm/IR/User.h"
#include "llvm/Object/ModuleSymbolTable.h"
+#include "llvm/Object/SymbolicFile.h"
#include "llvm/Pass.h"
+#include "llvm/Support/Casting.h"
+#include <algorithm>
+#include <cassert>
+#include <cstdint>
+#include <vector>
+
using namespace llvm;
#define DEBUG_TYPE "module-summary-analysis"
@@ -174,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.
@@ -191,9 +215,13 @@ computeFunctionSummary(ModuleSummaryIndex &Index, const Module &M,
SetVector<FunctionSummary::ConstVCall> TypeTestAssumeConstVCalls,
TypeCheckedLoadConstVCalls;
ICallPromotionAnalysis ICallAnalysis;
+ SmallPtrSet<const User *, 8> Visited;
+
+ // Add personality function, prefix data and prologue data to function's ref
+ // list.
+ findRefEdges(Index, &F, RefEdges, Visited);
bool HasInlineAsmMaybeReferencingInternal = false;
- SmallPtrSet<const User *, 8> Visited;
for (const BasicBlock &BB : F)
for (const Instruction &I : BB) {
if (isa<DbgInfoIntrinsic>(I))
@@ -210,11 +238,16 @@ 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();
auto *CalledFunction = CS.getCalledFunction();
+ if (CalledValue && !CalledFunction) {
+ CalledValue = CalledValue->stripPointerCastsNoFollowAliases();
+ // Stripping pointer casts can reveal a called function.
+ CalledFunction = dyn_cast<Function>(CalledValue);
+ }
// Check if this is an alias to a function. If so, get the
// called aliasee for the checks below.
if (auto *GA = dyn_cast<GlobalAlias>(CalledValue)) {
@@ -248,7 +281,7 @@ computeFunctionSummary(ModuleSummaryIndex &Index, const Module &M,
if (CI && CI->isInlineAsm())
continue;
// Skip direct calls.
- if (!CS.getCalledValue() || isa<Constant>(CS.getCalledValue()))
+ if (!CalledValue || isa<Constant>(CalledValue))
continue;
uint32_t NumVals, NumCandidates;
@@ -275,11 +308,17 @@ computeFunctionSummary(ModuleSummaryIndex &Index, const Module &M,
// FIXME: refactor this to use the same code that inliner is using.
F.isVarArg();
GlobalValueSummary::GVFlags Flags(F.getLinkage(), NotEligibleForImport,
- /* Live = */ false);
+ /* Live = */ false, F.isDSOLocal());
+ FunctionSummary::FFlags FunFlags{
+ F.hasFnAttribute(Attribute::ReadNone),
+ F.hasFnAttribute(Attribute::ReadOnly),
+ F.hasFnAttribute(Attribute::NoRecurse),
+ F.returnDoesNotAlias(),
+ };
auto FuncSummary = llvm::make_unique<FunctionSummary>(
- Flags, NumInsts, RefEdges.takeVector(), CallGraphEdges.takeVector(),
- TypeTests.takeVector(), TypeTestAssumeVCalls.takeVector(),
- TypeCheckedLoadVCalls.takeVector(),
+ Flags, NumInsts, FunFlags, RefEdges.takeVector(),
+ CallGraphEdges.takeVector(), TypeTests.takeVector(),
+ TypeTestAssumeVCalls.takeVector(), TypeCheckedLoadVCalls.takeVector(),
TypeTestAssumeConstVCalls.takeVector(),
TypeCheckedLoadConstVCalls.takeVector());
if (NonRenamableLocal)
@@ -295,7 +334,7 @@ computeVariableSummary(ModuleSummaryIndex &Index, const GlobalVariable &V,
findRefEdges(Index, &V, RefEdges, Visited);
bool NonRenamableLocal = isNonRenamableLocal(V);
GlobalValueSummary::GVFlags Flags(V.getLinkage(), NonRenamableLocal,
- /* Live = */ false);
+ /* Live = */ false, V.isDSOLocal());
auto GVarSummary =
llvm::make_unique<GlobalVarSummary>(Flags, RefEdges.takeVector());
if (NonRenamableLocal)
@@ -308,8 +347,8 @@ computeAliasSummary(ModuleSummaryIndex &Index, const GlobalAlias &A,
DenseSet<GlobalValue::GUID> &CantBePromoted) {
bool NonRenamableLocal = isNonRenamableLocal(A);
GlobalValueSummary::GVFlags Flags(A.getLinkage(), NonRenamableLocal,
- /* Live = */ false);
- auto AS = llvm::make_unique<AliasSummary>(Flags, ArrayRef<ValueInfo>{});
+ /* Live = */ false, A.isDSOLocal());
+ auto AS = llvm::make_unique<AliasSummary>(Flags);
auto *Aliasee = A.getBaseObject();
auto *AliaseeSummary = Index.getGlobalValueSummary(*Aliasee);
assert(AliaseeSummary && "Alias expects aliasee summary to be parsed");
@@ -352,6 +391,59 @@ 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,
+ /* Local */ GV->isDSOLocal());
+ 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) {
@@ -369,7 +461,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);
}
@@ -401,52 +494,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 (isa<Function>(GV)) {
- std::unique_ptr<FunctionSummary> Summary =
- llvm::make_unique<FunctionSummary>(
- GVFlags, 0, 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")))
@@ -503,6 +550,7 @@ ModuleSummaryIndexAnalysis::run(Module &M, ModuleAnalysisManager &AM) {
}
char ModuleSummaryIndexWrapperPass::ID = 0;
+
INITIALIZE_PASS_BEGIN(ModuleSummaryIndexWrapperPass, "module-summary-analysis",
"Module Summary Analysis", false, true)
INITIALIZE_PASS_DEPENDENCY(BlockFrequencyInfoWrapperPass)