diff options
Diffstat (limited to 'lib/Analysis/ModuleSummaryAnalysis.cpp')
-rw-r--r-- | lib/Analysis/ModuleSummaryAnalysis.cpp | 172 |
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) |