13ca95b02SDimitry Andric //===- ModuleSummaryAnalysis.cpp - Module summary index builder -----------===//
23ca95b02SDimitry Andric //
33ca95b02SDimitry Andric // The LLVM Compiler Infrastructure
43ca95b02SDimitry Andric //
53ca95b02SDimitry Andric // This file is distributed under the University of Illinois Open Source
63ca95b02SDimitry Andric // License. See LICENSE.TXT for details.
73ca95b02SDimitry Andric //
83ca95b02SDimitry Andric //===----------------------------------------------------------------------===//
93ca95b02SDimitry Andric //
103ca95b02SDimitry Andric // This pass builds a ModuleSummaryIndex object for the module, to be written
113ca95b02SDimitry Andric // to bitcode or LLVM assembly.
123ca95b02SDimitry Andric //
133ca95b02SDimitry Andric //===----------------------------------------------------------------------===//
143ca95b02SDimitry Andric
153ca95b02SDimitry Andric #include "llvm/Analysis/ModuleSummaryAnalysis.h"
162cab237bSDimitry Andric #include "llvm/ADT/ArrayRef.h"
172cab237bSDimitry Andric #include "llvm/ADT/DenseSet.h"
18d88c1a5aSDimitry Andric #include "llvm/ADT/MapVector.h"
192cab237bSDimitry Andric #include "llvm/ADT/STLExtras.h"
20d88c1a5aSDimitry Andric #include "llvm/ADT/SetVector.h"
212cab237bSDimitry Andric #include "llvm/ADT/SmallPtrSet.h"
222cab237bSDimitry Andric #include "llvm/ADT/SmallVector.h"
232cab237bSDimitry Andric #include "llvm/ADT/StringRef.h"
243ca95b02SDimitry Andric #include "llvm/Analysis/BlockFrequencyInfo.h"
253ca95b02SDimitry Andric #include "llvm/Analysis/BranchProbabilityInfo.h"
263ca95b02SDimitry Andric #include "llvm/Analysis/IndirectCallPromotionAnalysis.h"
273ca95b02SDimitry Andric #include "llvm/Analysis/LoopInfo.h"
28d88c1a5aSDimitry Andric #include "llvm/Analysis/ProfileSummaryInfo.h"
29d88c1a5aSDimitry Andric #include "llvm/Analysis/TypeMetadataUtils.h"
302cab237bSDimitry Andric #include "llvm/IR/Attributes.h"
312cab237bSDimitry Andric #include "llvm/IR/BasicBlock.h"
323ca95b02SDimitry Andric #include "llvm/IR/CallSite.h"
332cab237bSDimitry Andric #include "llvm/IR/Constant.h"
342cab237bSDimitry Andric #include "llvm/IR/Constants.h"
353ca95b02SDimitry Andric #include "llvm/IR/Dominators.h"
362cab237bSDimitry Andric #include "llvm/IR/Function.h"
372cab237bSDimitry Andric #include "llvm/IR/GlobalAlias.h"
382cab237bSDimitry Andric #include "llvm/IR/GlobalValue.h"
392cab237bSDimitry Andric #include "llvm/IR/GlobalVariable.h"
402cab237bSDimitry Andric #include "llvm/IR/Instructions.h"
413ca95b02SDimitry Andric #include "llvm/IR/IntrinsicInst.h"
422cab237bSDimitry Andric #include "llvm/IR/Intrinsics.h"
432cab237bSDimitry Andric #include "llvm/IR/Metadata.h"
442cab237bSDimitry Andric #include "llvm/IR/Module.h"
452cab237bSDimitry Andric #include "llvm/IR/ModuleSummaryIndex.h"
462cab237bSDimitry Andric #include "llvm/IR/Use.h"
472cab237bSDimitry Andric #include "llvm/IR/User.h"
487a7e6055SDimitry Andric #include "llvm/Object/ModuleSymbolTable.h"
492cab237bSDimitry Andric #include "llvm/Object/SymbolicFile.h"
503ca95b02SDimitry Andric #include "llvm/Pass.h"
512cab237bSDimitry Andric #include "llvm/Support/Casting.h"
524ba319b5SDimitry Andric #include "llvm/Support/CommandLine.h"
532cab237bSDimitry Andric #include <algorithm>
542cab237bSDimitry Andric #include <cassert>
552cab237bSDimitry Andric #include <cstdint>
562cab237bSDimitry Andric #include <vector>
572cab237bSDimitry Andric
583ca95b02SDimitry Andric using namespace llvm;
593ca95b02SDimitry Andric
603ca95b02SDimitry Andric #define DEBUG_TYPE "module-summary-analysis"
613ca95b02SDimitry Andric
624ba319b5SDimitry Andric // Option to force edges cold which will block importing when the
634ba319b5SDimitry Andric // -import-cold-multiplier is set to 0. Useful for debugging.
644ba319b5SDimitry Andric FunctionSummary::ForceSummaryHotnessType ForceSummaryEdgesCold =
654ba319b5SDimitry Andric FunctionSummary::FSHT_None;
664ba319b5SDimitry Andric cl::opt<FunctionSummary::ForceSummaryHotnessType, true> FSEC(
674ba319b5SDimitry Andric "force-summary-edges-cold", cl::Hidden, cl::location(ForceSummaryEdgesCold),
684ba319b5SDimitry Andric cl::desc("Force all edges in the function summary to cold"),
694ba319b5SDimitry Andric cl::values(clEnumValN(FunctionSummary::FSHT_None, "none", "None."),
704ba319b5SDimitry Andric clEnumValN(FunctionSummary::FSHT_AllNonCritical,
714ba319b5SDimitry Andric "all-non-critical", "All non-critical edges."),
724ba319b5SDimitry Andric clEnumValN(FunctionSummary::FSHT_All, "all", "All edges.")));
734ba319b5SDimitry Andric
743ca95b02SDimitry Andric // Walk through the operands of a given User via worklist iteration and populate
753ca95b02SDimitry Andric // the set of GlobalValue references encountered. Invoked either on an
763ca95b02SDimitry Andric // Instruction or a GlobalVariable (which walks its initializer).
774ba319b5SDimitry Andric // Return true if any of the operands contains blockaddress. This is important
784ba319b5SDimitry Andric // to know when computing summary for global var, because if global variable
794ba319b5SDimitry Andric // references basic block address we can't import it separately from function
804ba319b5SDimitry Andric // containing that basic block. For simplicity we currently don't import such
814ba319b5SDimitry Andric // global vars at all. When importing function we aren't interested if any
824ba319b5SDimitry Andric // instruction in it takes an address of any basic block, because instruction
834ba319b5SDimitry Andric // can only take an address of basic block located in the same function.
findRefEdges(ModuleSummaryIndex & Index,const User * CurUser,SetVector<ValueInfo> & RefEdges,SmallPtrSet<const User *,8> & Visited)844ba319b5SDimitry Andric static bool findRefEdges(ModuleSummaryIndex &Index, const User *CurUser,
850f5676f4SDimitry Andric SetVector<ValueInfo> &RefEdges,
863ca95b02SDimitry Andric SmallPtrSet<const User *, 8> &Visited) {
874ba319b5SDimitry Andric bool HasBlockAddress = false;
883ca95b02SDimitry Andric SmallVector<const User *, 32> Worklist;
893ca95b02SDimitry Andric Worklist.push_back(CurUser);
903ca95b02SDimitry Andric
913ca95b02SDimitry Andric while (!Worklist.empty()) {
923ca95b02SDimitry Andric const User *U = Worklist.pop_back_val();
933ca95b02SDimitry Andric
943ca95b02SDimitry Andric if (!Visited.insert(U).second)
953ca95b02SDimitry Andric continue;
963ca95b02SDimitry Andric
973ca95b02SDimitry Andric ImmutableCallSite CS(U);
983ca95b02SDimitry Andric
993ca95b02SDimitry Andric for (const auto &OI : U->operands()) {
1003ca95b02SDimitry Andric const User *Operand = dyn_cast<User>(OI);
1013ca95b02SDimitry Andric if (!Operand)
1023ca95b02SDimitry Andric continue;
1034ba319b5SDimitry Andric if (isa<BlockAddress>(Operand)) {
1044ba319b5SDimitry Andric HasBlockAddress = true;
1053ca95b02SDimitry Andric continue;
1064ba319b5SDimitry Andric }
107d88c1a5aSDimitry Andric if (auto *GV = dyn_cast<GlobalValue>(Operand)) {
1083ca95b02SDimitry Andric // We have a reference to a global value. This should be added to
1093ca95b02SDimitry Andric // the reference set unless it is a callee. Callees are handled
1103ca95b02SDimitry Andric // specially by WriteFunction and are added to a separate list.
1113ca95b02SDimitry Andric if (!(CS && CS.isCallee(&OI)))
1120f5676f4SDimitry Andric RefEdges.insert(Index.getOrInsertValueInfo(GV));
1133ca95b02SDimitry Andric continue;
1143ca95b02SDimitry Andric }
1153ca95b02SDimitry Andric Worklist.push_back(Operand);
1163ca95b02SDimitry Andric }
1173ca95b02SDimitry Andric }
1184ba319b5SDimitry Andric return HasBlockAddress;
1193ca95b02SDimitry Andric }
1203ca95b02SDimitry Andric
getHotness(uint64_t ProfileCount,ProfileSummaryInfo * PSI)121d88c1a5aSDimitry Andric static CalleeInfo::HotnessType getHotness(uint64_t ProfileCount,
122d88c1a5aSDimitry Andric ProfileSummaryInfo *PSI) {
123d88c1a5aSDimitry Andric if (!PSI)
124d88c1a5aSDimitry Andric return CalleeInfo::HotnessType::Unknown;
125d88c1a5aSDimitry Andric if (PSI->isHotCount(ProfileCount))
126d88c1a5aSDimitry Andric return CalleeInfo::HotnessType::Hot;
127d88c1a5aSDimitry Andric if (PSI->isColdCount(ProfileCount))
128d88c1a5aSDimitry Andric return CalleeInfo::HotnessType::Cold;
129d88c1a5aSDimitry Andric return CalleeInfo::HotnessType::None;
130d88c1a5aSDimitry Andric }
131d88c1a5aSDimitry Andric
isNonRenamableLocal(const GlobalValue & GV)13295ec533aSDimitry Andric static bool isNonRenamableLocal(const GlobalValue &GV) {
13395ec533aSDimitry Andric return GV.hasSection() && GV.hasLocalLinkage();
13495ec533aSDimitry Andric }
13595ec533aSDimitry Andric
1367a7e6055SDimitry Andric /// Determine whether this call has all constant integer arguments (excluding
1377a7e6055SDimitry Andric /// "this") and summarize it to VCalls or ConstVCalls as appropriate.
addVCallToSet(DevirtCallSite Call,GlobalValue::GUID Guid,SetVector<FunctionSummary::VFuncId> & VCalls,SetVector<FunctionSummary::ConstVCall> & ConstVCalls)1387a7e6055SDimitry Andric static void addVCallToSet(DevirtCallSite Call, GlobalValue::GUID Guid,
1397a7e6055SDimitry Andric SetVector<FunctionSummary::VFuncId> &VCalls,
1407a7e6055SDimitry Andric SetVector<FunctionSummary::ConstVCall> &ConstVCalls) {
1417a7e6055SDimitry Andric std::vector<uint64_t> Args;
1427a7e6055SDimitry Andric // Start from the second argument to skip the "this" pointer.
1437a7e6055SDimitry Andric for (auto &Arg : make_range(Call.CS.arg_begin() + 1, Call.CS.arg_end())) {
1447a7e6055SDimitry Andric auto *CI = dyn_cast<ConstantInt>(Arg);
1457a7e6055SDimitry Andric if (!CI || CI->getBitWidth() > 64) {
1467a7e6055SDimitry Andric VCalls.insert({Guid, Call.Offset});
1477a7e6055SDimitry Andric return;
1487a7e6055SDimitry Andric }
1497a7e6055SDimitry Andric Args.push_back(CI->getZExtValue());
1507a7e6055SDimitry Andric }
1517a7e6055SDimitry Andric ConstVCalls.insert({{Guid, Call.Offset}, std::move(Args)});
1527a7e6055SDimitry Andric }
1537a7e6055SDimitry Andric
1547a7e6055SDimitry Andric /// If this intrinsic call requires that we add information to the function
1557a7e6055SDimitry Andric /// summary, do so via the non-constant reference arguments.
addIntrinsicToSummary(const CallInst * CI,SetVector<GlobalValue::GUID> & TypeTests,SetVector<FunctionSummary::VFuncId> & TypeTestAssumeVCalls,SetVector<FunctionSummary::VFuncId> & TypeCheckedLoadVCalls,SetVector<FunctionSummary::ConstVCall> & TypeTestAssumeConstVCalls,SetVector<FunctionSummary::ConstVCall> & TypeCheckedLoadConstVCalls,DominatorTree & DT)1567a7e6055SDimitry Andric static void addIntrinsicToSummary(
1577a7e6055SDimitry Andric const CallInst *CI, SetVector<GlobalValue::GUID> &TypeTests,
1587a7e6055SDimitry Andric SetVector<FunctionSummary::VFuncId> &TypeTestAssumeVCalls,
1597a7e6055SDimitry Andric SetVector<FunctionSummary::VFuncId> &TypeCheckedLoadVCalls,
1607a7e6055SDimitry Andric SetVector<FunctionSummary::ConstVCall> &TypeTestAssumeConstVCalls,
161*b5893f02SDimitry Andric SetVector<FunctionSummary::ConstVCall> &TypeCheckedLoadConstVCalls,
162*b5893f02SDimitry Andric DominatorTree &DT) {
1637a7e6055SDimitry Andric switch (CI->getCalledFunction()->getIntrinsicID()) {
1647a7e6055SDimitry Andric case Intrinsic::type_test: {
1657a7e6055SDimitry Andric auto *TypeMDVal = cast<MetadataAsValue>(CI->getArgOperand(1));
1667a7e6055SDimitry Andric auto *TypeId = dyn_cast<MDString>(TypeMDVal->getMetadata());
1677a7e6055SDimitry Andric if (!TypeId)
1687a7e6055SDimitry Andric break;
1697a7e6055SDimitry Andric GlobalValue::GUID Guid = GlobalValue::getGUID(TypeId->getString());
1707a7e6055SDimitry Andric
1717a7e6055SDimitry Andric // Produce a summary from type.test intrinsics. We only summarize type.test
1727a7e6055SDimitry Andric // intrinsics that are used other than by an llvm.assume intrinsic.
1737a7e6055SDimitry Andric // Intrinsics that are assumed are relevant only to the devirtualization
1747a7e6055SDimitry Andric // pass, not the type test lowering pass.
1757a7e6055SDimitry Andric bool HasNonAssumeUses = llvm::any_of(CI->uses(), [](const Use &CIU) {
1767a7e6055SDimitry Andric auto *AssumeCI = dyn_cast<CallInst>(CIU.getUser());
1777a7e6055SDimitry Andric if (!AssumeCI)
1787a7e6055SDimitry Andric return true;
1797a7e6055SDimitry Andric Function *F = AssumeCI->getCalledFunction();
1807a7e6055SDimitry Andric return !F || F->getIntrinsicID() != Intrinsic::assume;
1817a7e6055SDimitry Andric });
1827a7e6055SDimitry Andric if (HasNonAssumeUses)
1837a7e6055SDimitry Andric TypeTests.insert(Guid);
1847a7e6055SDimitry Andric
1857a7e6055SDimitry Andric SmallVector<DevirtCallSite, 4> DevirtCalls;
1867a7e6055SDimitry Andric SmallVector<CallInst *, 4> Assumes;
187*b5893f02SDimitry Andric findDevirtualizableCallsForTypeTest(DevirtCalls, Assumes, CI, DT);
1887a7e6055SDimitry Andric for (auto &Call : DevirtCalls)
1897a7e6055SDimitry Andric addVCallToSet(Call, Guid, TypeTestAssumeVCalls,
1907a7e6055SDimitry Andric TypeTestAssumeConstVCalls);
1917a7e6055SDimitry Andric
1927a7e6055SDimitry Andric break;
1937a7e6055SDimitry Andric }
1947a7e6055SDimitry Andric
1957a7e6055SDimitry Andric case Intrinsic::type_checked_load: {
1967a7e6055SDimitry Andric auto *TypeMDVal = cast<MetadataAsValue>(CI->getArgOperand(2));
1977a7e6055SDimitry Andric auto *TypeId = dyn_cast<MDString>(TypeMDVal->getMetadata());
1987a7e6055SDimitry Andric if (!TypeId)
1997a7e6055SDimitry Andric break;
2007a7e6055SDimitry Andric GlobalValue::GUID Guid = GlobalValue::getGUID(TypeId->getString());
2017a7e6055SDimitry Andric
2027a7e6055SDimitry Andric SmallVector<DevirtCallSite, 4> DevirtCalls;
2037a7e6055SDimitry Andric SmallVector<Instruction *, 4> LoadedPtrs;
2047a7e6055SDimitry Andric SmallVector<Instruction *, 4> Preds;
2057a7e6055SDimitry Andric bool HasNonCallUses = false;
2067a7e6055SDimitry Andric findDevirtualizableCallsForTypeCheckedLoad(DevirtCalls, LoadedPtrs, Preds,
207*b5893f02SDimitry Andric HasNonCallUses, CI, DT);
2087a7e6055SDimitry Andric // Any non-call uses of the result of llvm.type.checked.load will
2097a7e6055SDimitry Andric // prevent us from optimizing away the llvm.type.test.
2107a7e6055SDimitry Andric if (HasNonCallUses)
2117a7e6055SDimitry Andric TypeTests.insert(Guid);
2127a7e6055SDimitry Andric for (auto &Call : DevirtCalls)
2137a7e6055SDimitry Andric addVCallToSet(Call, Guid, TypeCheckedLoadVCalls,
2147a7e6055SDimitry Andric TypeCheckedLoadConstVCalls);
2157a7e6055SDimitry Andric
2167a7e6055SDimitry Andric break;
2177a7e6055SDimitry Andric }
2187a7e6055SDimitry Andric default:
2197a7e6055SDimitry Andric break;
2207a7e6055SDimitry Andric }
2217a7e6055SDimitry Andric }
2227a7e6055SDimitry Andric
isNonVolatileLoad(const Instruction * I)223*b5893f02SDimitry Andric static bool isNonVolatileLoad(const Instruction *I) {
224*b5893f02SDimitry Andric if (const auto *LI = dyn_cast<LoadInst>(I))
225*b5893f02SDimitry Andric return !LI->isVolatile();
226*b5893f02SDimitry Andric
227*b5893f02SDimitry Andric return false;
228*b5893f02SDimitry Andric }
229*b5893f02SDimitry Andric
computeFunctionSummary(ModuleSummaryIndex & Index,const Module & M,const Function & F,BlockFrequencyInfo * BFI,ProfileSummaryInfo * PSI,DominatorTree & DT,bool HasLocalsInUsedOrAsm,DenseSet<GlobalValue::GUID> & CantBePromoted,bool IsThinLTO)230*b5893f02SDimitry Andric static void computeFunctionSummary(ModuleSummaryIndex &Index, const Module &M,
231d88c1a5aSDimitry Andric const Function &F, BlockFrequencyInfo *BFI,
232*b5893f02SDimitry Andric ProfileSummaryInfo *PSI, DominatorTree &DT,
233*b5893f02SDimitry Andric bool HasLocalsInUsedOrAsm,
234*b5893f02SDimitry Andric DenseSet<GlobalValue::GUID> &CantBePromoted,
235*b5893f02SDimitry Andric bool IsThinLTO) {
236d88c1a5aSDimitry Andric // Summary not currently supported for anonymous functions, they should
237d88c1a5aSDimitry Andric // have been named.
238d88c1a5aSDimitry Andric assert(F.hasName());
2393ca95b02SDimitry Andric
2403ca95b02SDimitry Andric unsigned NumInsts = 0;
2413ca95b02SDimitry Andric // Map from callee ValueId to profile count. Used to accumulate profile
2423ca95b02SDimitry Andric // counts for all static calls to a given callee.
243d88c1a5aSDimitry Andric MapVector<ValueInfo, CalleeInfo> CallGraphEdges;
244d88c1a5aSDimitry Andric SetVector<ValueInfo> RefEdges;
245d88c1a5aSDimitry Andric SetVector<GlobalValue::GUID> TypeTests;
2467a7e6055SDimitry Andric SetVector<FunctionSummary::VFuncId> TypeTestAssumeVCalls,
2477a7e6055SDimitry Andric TypeCheckedLoadVCalls;
2487a7e6055SDimitry Andric SetVector<FunctionSummary::ConstVCall> TypeTestAssumeConstVCalls,
2497a7e6055SDimitry Andric TypeCheckedLoadConstVCalls;
2503ca95b02SDimitry Andric ICallPromotionAnalysis ICallAnalysis;
2512cab237bSDimitry Andric SmallPtrSet<const User *, 8> Visited;
2522cab237bSDimitry Andric
2532cab237bSDimitry Andric // Add personality function, prefix data and prologue data to function's ref
2542cab237bSDimitry Andric // list.
2552cab237bSDimitry Andric findRefEdges(Index, &F, RefEdges, Visited);
256*b5893f02SDimitry Andric std::vector<const Instruction *> NonVolatileLoads;
2573ca95b02SDimitry Andric
258d88c1a5aSDimitry Andric bool HasInlineAsmMaybeReferencingInternal = false;
2593ca95b02SDimitry Andric for (const BasicBlock &BB : F)
2603ca95b02SDimitry Andric for (const Instruction &I : BB) {
261d88c1a5aSDimitry Andric if (isa<DbgInfoIntrinsic>(I))
262d88c1a5aSDimitry Andric continue;
2633ca95b02SDimitry Andric ++NumInsts;
264*b5893f02SDimitry Andric if (isNonVolatileLoad(&I)) {
265*b5893f02SDimitry Andric // Postpone processing of non-volatile load instructions
266*b5893f02SDimitry Andric // See comments below
267*b5893f02SDimitry Andric Visited.insert(&I);
268*b5893f02SDimitry Andric NonVolatileLoads.push_back(&I);
269*b5893f02SDimitry Andric continue;
270*b5893f02SDimitry Andric }
2710f5676f4SDimitry Andric findRefEdges(Index, &I, RefEdges, Visited);
272d88c1a5aSDimitry Andric auto CS = ImmutableCallSite(&I);
273d88c1a5aSDimitry Andric if (!CS)
274d88c1a5aSDimitry Andric continue;
2753ca95b02SDimitry Andric
276d88c1a5aSDimitry Andric const auto *CI = dyn_cast<CallInst>(&I);
277d88c1a5aSDimitry Andric // Since we don't know exactly which local values are referenced in inline
278d88c1a5aSDimitry Andric // assembly, conservatively mark the function as possibly referencing
279d88c1a5aSDimitry Andric // a local value from inline assembly to ensure we don't export a
280d88c1a5aSDimitry Andric // reference (which would require renaming and promotion of the
281d88c1a5aSDimitry Andric // referenced value).
2822cab237bSDimitry Andric if (HasLocalsInUsedOrAsm && CI && CI->isInlineAsm())
283d88c1a5aSDimitry Andric HasInlineAsmMaybeReferencingInternal = true;
284d88c1a5aSDimitry Andric
285d88c1a5aSDimitry Andric auto *CalledValue = CS.getCalledValue();
2863ca95b02SDimitry Andric auto *CalledFunction = CS.getCalledFunction();
2872cab237bSDimitry Andric if (CalledValue && !CalledFunction) {
2882cab237bSDimitry Andric CalledValue = CalledValue->stripPointerCastsNoFollowAliases();
2892cab237bSDimitry Andric // Stripping pointer casts can reveal a called function.
2902cab237bSDimitry Andric CalledFunction = dyn_cast<Function>(CalledValue);
2912cab237bSDimitry Andric }
292d88c1a5aSDimitry Andric // Check if this is an alias to a function. If so, get the
293d88c1a5aSDimitry Andric // called aliasee for the checks below.
294d88c1a5aSDimitry Andric if (auto *GA = dyn_cast<GlobalAlias>(CalledValue)) {
295d88c1a5aSDimitry Andric assert(!CalledFunction && "Expected null called function in callsite for alias");
296d88c1a5aSDimitry Andric CalledFunction = dyn_cast<Function>(GA->getBaseObject());
2973ca95b02SDimitry Andric }
298d88c1a5aSDimitry Andric // Check if this is a direct call to a known function or a known
299d88c1a5aSDimitry Andric // intrinsic, or an indirect call with profile data.
300d88c1a5aSDimitry Andric if (CalledFunction) {
3017a7e6055SDimitry Andric if (CI && CalledFunction->isIntrinsic()) {
3027a7e6055SDimitry Andric addIntrinsicToSummary(
3037a7e6055SDimitry Andric CI, TypeTests, TypeTestAssumeVCalls, TypeCheckedLoadVCalls,
304*b5893f02SDimitry Andric TypeTestAssumeConstVCalls, TypeCheckedLoadConstVCalls, DT);
305d88c1a5aSDimitry Andric continue;
306d88c1a5aSDimitry Andric }
307d88c1a5aSDimitry Andric // We should have named any anonymous globals
308d88c1a5aSDimitry Andric assert(CalledFunction->hasName());
3095517e702SDimitry Andric auto ScaledCount = PSI->getProfileCount(&I, BFI);
310d88c1a5aSDimitry Andric auto Hotness = ScaledCount ? getHotness(ScaledCount.getValue(), PSI)
311d88c1a5aSDimitry Andric : CalleeInfo::HotnessType::Unknown;
3124ba319b5SDimitry Andric if (ForceSummaryEdgesCold != FunctionSummary::FSHT_None)
3134ba319b5SDimitry Andric Hotness = CalleeInfo::HotnessType::Cold;
314d88c1a5aSDimitry Andric
315d88c1a5aSDimitry Andric // Use the original CalledValue, in case it was an alias. We want
316d88c1a5aSDimitry Andric // to record the call edge to the alias in that case. Eventually
317d88c1a5aSDimitry Andric // an alias summary will be created to associate the alias and
318d88c1a5aSDimitry Andric // aliasee.
3194ba319b5SDimitry Andric auto &ValueInfo = CallGraphEdges[Index.getOrInsertValueInfo(
3204ba319b5SDimitry Andric cast<GlobalValue>(CalledValue))];
3214ba319b5SDimitry Andric ValueInfo.updateHotness(Hotness);
3224ba319b5SDimitry Andric // Add the relative block frequency to CalleeInfo if there is no profile
3234ba319b5SDimitry Andric // information.
3244ba319b5SDimitry Andric if (BFI != nullptr && Hotness == CalleeInfo::HotnessType::Unknown) {
3254ba319b5SDimitry Andric uint64_t BBFreq = BFI->getBlockFreq(&BB).getFrequency();
3264ba319b5SDimitry Andric uint64_t EntryFreq = BFI->getEntryFreq();
3274ba319b5SDimitry Andric ValueInfo.updateRelBlockFreq(BBFreq, EntryFreq);
3284ba319b5SDimitry Andric }
3293ca95b02SDimitry Andric } else {
330d88c1a5aSDimitry Andric // Skip inline assembly calls.
331d88c1a5aSDimitry Andric if (CI && CI->isInlineAsm())
332d88c1a5aSDimitry Andric continue;
333d88c1a5aSDimitry Andric // Skip direct calls.
3342cab237bSDimitry Andric if (!CalledValue || isa<Constant>(CalledValue))
335d88c1a5aSDimitry Andric continue;
336d88c1a5aSDimitry Andric
3374ba319b5SDimitry Andric // Check if the instruction has a callees metadata. If so, add callees
3384ba319b5SDimitry Andric // to CallGraphEdges to reflect the references from the metadata, and
3394ba319b5SDimitry Andric // to enable importing for subsequent indirect call promotion and
3404ba319b5SDimitry Andric // inlining.
3414ba319b5SDimitry Andric if (auto *MD = I.getMetadata(LLVMContext::MD_callees)) {
3424ba319b5SDimitry Andric for (auto &Op : MD->operands()) {
3434ba319b5SDimitry Andric Function *Callee = mdconst::extract_or_null<Function>(Op);
3444ba319b5SDimitry Andric if (Callee)
3454ba319b5SDimitry Andric CallGraphEdges[Index.getOrInsertValueInfo(Callee)];
3464ba319b5SDimitry Andric }
3474ba319b5SDimitry Andric }
3484ba319b5SDimitry Andric
3493ca95b02SDimitry Andric uint32_t NumVals, NumCandidates;
3503ca95b02SDimitry Andric uint64_t TotalCount;
3513ca95b02SDimitry Andric auto CandidateProfileData =
3523ca95b02SDimitry Andric ICallAnalysis.getPromotionCandidatesForInstruction(
3533ca95b02SDimitry Andric &I, NumVals, TotalCount, NumCandidates);
3543ca95b02SDimitry Andric for (auto &Candidate : CandidateProfileData)
3550f5676f4SDimitry Andric CallGraphEdges[Index.getOrInsertValueInfo(Candidate.Value)]
3560f5676f4SDimitry Andric .updateHotness(getHotness(Candidate.Count, PSI));
3573ca95b02SDimitry Andric }
3583ca95b02SDimitry Andric }
3593ca95b02SDimitry Andric
360*b5893f02SDimitry Andric // By now we processed all instructions in a function, except
361*b5893f02SDimitry Andric // non-volatile loads. All new refs we add in a loop below
362*b5893f02SDimitry Andric // are obviously constant. All constant refs are grouped in the
363*b5893f02SDimitry Andric // end of RefEdges vector, so we can use a single integer value
364*b5893f02SDimitry Andric // to identify them.
365*b5893f02SDimitry Andric unsigned RefCnt = RefEdges.size();
366*b5893f02SDimitry Andric for (const Instruction *I : NonVolatileLoads) {
367*b5893f02SDimitry Andric Visited.erase(I);
368*b5893f02SDimitry Andric findRefEdges(Index, I, RefEdges, Visited);
369*b5893f02SDimitry Andric }
370*b5893f02SDimitry Andric std::vector<ValueInfo> Refs = RefEdges.takeVector();
371*b5893f02SDimitry Andric // Regular LTO module doesn't participate in ThinLTO import,
372*b5893f02SDimitry Andric // so no reference from it can be readonly, since this would
373*b5893f02SDimitry Andric // require importing variable as local copy
374*b5893f02SDimitry Andric if (IsThinLTO)
375*b5893f02SDimitry Andric for (; RefCnt < Refs.size(); ++RefCnt)
376*b5893f02SDimitry Andric Refs[RefCnt].setReadOnly();
377*b5893f02SDimitry Andric
3787a7e6055SDimitry Andric // Explicit add hot edges to enforce importing for designated GUIDs for
3797a7e6055SDimitry Andric // sample PGO, to enable the same inlines as the profiled optimized binary.
3807a7e6055SDimitry Andric for (auto &I : F.getImportGUIDs())
3810f5676f4SDimitry Andric CallGraphEdges[Index.getOrInsertValueInfo(I)].updateHotness(
3824ba319b5SDimitry Andric ForceSummaryEdgesCold == FunctionSummary::FSHT_All
3834ba319b5SDimitry Andric ? CalleeInfo::HotnessType::Cold
3844ba319b5SDimitry Andric : CalleeInfo::HotnessType::Critical);
3857a7e6055SDimitry Andric
38695ec533aSDimitry Andric bool NonRenamableLocal = isNonRenamableLocal(F);
38795ec533aSDimitry Andric bool NotEligibleForImport =
388*b5893f02SDimitry Andric NonRenamableLocal || HasInlineAsmMaybeReferencingInternal;
38995ec533aSDimitry Andric GlobalValueSummary::GVFlags Flags(F.getLinkage(), NotEligibleForImport,
3902cab237bSDimitry Andric /* Live = */ false, F.isDSOLocal());
3912cab237bSDimitry Andric FunctionSummary::FFlags FunFlags{
3922cab237bSDimitry Andric F.hasFnAttribute(Attribute::ReadNone),
3932cab237bSDimitry Andric F.hasFnAttribute(Attribute::ReadOnly),
394*b5893f02SDimitry Andric F.hasFnAttribute(Attribute::NoRecurse), F.returnDoesNotAlias(),
395*b5893f02SDimitry Andric // FIXME: refactor this to use the same code that inliner is using.
396*b5893f02SDimitry Andric // Don't try to import functions with noinline attribute.
397*b5893f02SDimitry Andric F.getAttributes().hasFnAttribute(Attribute::NoInline)};
398d88c1a5aSDimitry Andric auto FuncSummary = llvm::make_unique<FunctionSummary>(
399*b5893f02SDimitry Andric Flags, NumInsts, FunFlags, /*EntryCount=*/0, std::move(Refs),
4002cab237bSDimitry Andric CallGraphEdges.takeVector(), TypeTests.takeVector(),
4012cab237bSDimitry Andric TypeTestAssumeVCalls.takeVector(), TypeCheckedLoadVCalls.takeVector(),
4027a7e6055SDimitry Andric TypeTestAssumeConstVCalls.takeVector(),
4037a7e6055SDimitry Andric TypeCheckedLoadConstVCalls.takeVector());
40495ec533aSDimitry Andric if (NonRenamableLocal)
40595ec533aSDimitry Andric CantBePromoted.insert(F.getGUID());
4064ba319b5SDimitry Andric Index.addGlobalValueSummary(F, std::move(FuncSummary));
4073ca95b02SDimitry Andric }
4083ca95b02SDimitry Andric
40995ec533aSDimitry Andric static void
computeVariableSummary(ModuleSummaryIndex & Index,const GlobalVariable & V,DenseSet<GlobalValue::GUID> & CantBePromoted)41095ec533aSDimitry Andric computeVariableSummary(ModuleSummaryIndex &Index, const GlobalVariable &V,
41195ec533aSDimitry Andric DenseSet<GlobalValue::GUID> &CantBePromoted) {
412d88c1a5aSDimitry Andric SetVector<ValueInfo> RefEdges;
4133ca95b02SDimitry Andric SmallPtrSet<const User *, 8> Visited;
4144ba319b5SDimitry Andric bool HasBlockAddress = findRefEdges(Index, &V, RefEdges, Visited);
41595ec533aSDimitry Andric bool NonRenamableLocal = isNonRenamableLocal(V);
41695ec533aSDimitry Andric GlobalValueSummary::GVFlags Flags(V.getLinkage(), NonRenamableLocal,
4172cab237bSDimitry Andric /* Live = */ false, V.isDSOLocal());
418*b5893f02SDimitry Andric
419*b5893f02SDimitry Andric // Don't mark variables we won't be able to internalize as read-only.
420*b5893f02SDimitry Andric GlobalVarSummary::GVarFlags VarFlags(
421*b5893f02SDimitry Andric !V.hasComdat() && !V.hasAppendingLinkage() && !V.isInterposable() &&
422*b5893f02SDimitry Andric !V.hasAvailableExternallyLinkage() && !V.hasDLLExportStorageClass());
423*b5893f02SDimitry Andric auto GVarSummary = llvm::make_unique<GlobalVarSummary>(Flags, VarFlags,
424*b5893f02SDimitry Andric RefEdges.takeVector());
42595ec533aSDimitry Andric if (NonRenamableLocal)
42695ec533aSDimitry Andric CantBePromoted.insert(V.getGUID());
4274ba319b5SDimitry Andric if (HasBlockAddress)
4284ba319b5SDimitry Andric GVarSummary->setNotEligibleToImport();
4294ba319b5SDimitry Andric Index.addGlobalValueSummary(V, std::move(GVarSummary));
4303ca95b02SDimitry Andric }
4313ca95b02SDimitry Andric
43295ec533aSDimitry Andric static void
computeAliasSummary(ModuleSummaryIndex & Index,const GlobalAlias & A,DenseSet<GlobalValue::GUID> & CantBePromoted)43395ec533aSDimitry Andric computeAliasSummary(ModuleSummaryIndex &Index, const GlobalAlias &A,
43495ec533aSDimitry Andric DenseSet<GlobalValue::GUID> &CantBePromoted) {
43595ec533aSDimitry Andric bool NonRenamableLocal = isNonRenamableLocal(A);
43695ec533aSDimitry Andric GlobalValueSummary::GVFlags Flags(A.getLinkage(), NonRenamableLocal,
4372cab237bSDimitry Andric /* Live = */ false, A.isDSOLocal());
4382cab237bSDimitry Andric auto AS = llvm::make_unique<AliasSummary>(Flags);
439d88c1a5aSDimitry Andric auto *Aliasee = A.getBaseObject();
440d88c1a5aSDimitry Andric auto *AliaseeSummary = Index.getGlobalValueSummary(*Aliasee);
441d88c1a5aSDimitry Andric assert(AliaseeSummary && "Alias expects aliasee summary to be parsed");
442d88c1a5aSDimitry Andric AS->setAliasee(AliaseeSummary);
44395ec533aSDimitry Andric if (NonRenamableLocal)
44495ec533aSDimitry Andric CantBePromoted.insert(A.getGUID());
4454ba319b5SDimitry Andric Index.addGlobalValueSummary(A, std::move(AS));
446d88c1a5aSDimitry Andric }
447d88c1a5aSDimitry Andric
44895ec533aSDimitry Andric // Set LiveRoot flag on entries matching the given value name.
setLiveRoot(ModuleSummaryIndex & Index,StringRef Name)44995ec533aSDimitry Andric static void setLiveRoot(ModuleSummaryIndex &Index, StringRef Name) {
4500f5676f4SDimitry Andric if (ValueInfo VI = Index.getValueInfo(GlobalValue::getGUID(Name)))
4510f5676f4SDimitry Andric for (auto &Summary : VI.getSummaryList())
4526d97bb29SDimitry Andric Summary->setLive(true);
45395ec533aSDimitry Andric }
45495ec533aSDimitry Andric
buildModuleSummaryIndex(const Module & M,std::function<BlockFrequencyInfo * (const Function & F)> GetBFICallback,ProfileSummaryInfo * PSI)455d88c1a5aSDimitry Andric ModuleSummaryIndex llvm::buildModuleSummaryIndex(
456d88c1a5aSDimitry Andric const Module &M,
457d88c1a5aSDimitry Andric std::function<BlockFrequencyInfo *(const Function &F)> GetBFICallback,
458d88c1a5aSDimitry Andric ProfileSummaryInfo *PSI) {
4595517e702SDimitry Andric assert(PSI);
460*b5893f02SDimitry Andric bool EnableSplitLTOUnit = false;
461*b5893f02SDimitry Andric if (auto *MD = mdconst::extract_or_null<ConstantInt>(
462*b5893f02SDimitry Andric M.getModuleFlag("EnableSplitLTOUnit")))
463*b5893f02SDimitry Andric EnableSplitLTOUnit = MD->getZExtValue();
464*b5893f02SDimitry Andric ModuleSummaryIndex Index(/*HaveGVs=*/true, EnableSplitLTOUnit);
465d88c1a5aSDimitry Andric
466d88c1a5aSDimitry Andric // Identify the local values in the llvm.used and llvm.compiler.used sets,
467d88c1a5aSDimitry Andric // which should not be exported as they would then require renaming and
468d88c1a5aSDimitry Andric // promotion, but we may have opaque uses e.g. in inline asm. We collect them
469d88c1a5aSDimitry Andric // here because we use this information to mark functions containing inline
470d88c1a5aSDimitry Andric // assembly calls as not importable.
471d88c1a5aSDimitry Andric SmallPtrSet<GlobalValue *, 8> LocalsUsed;
472d88c1a5aSDimitry Andric SmallPtrSet<GlobalValue *, 8> Used;
473d88c1a5aSDimitry Andric // First collect those in the llvm.used set.
474d88c1a5aSDimitry Andric collectUsedGlobalVariables(M, Used, /*CompilerUsed*/ false);
475d88c1a5aSDimitry Andric // Next collect those in the llvm.compiler.used set.
476d88c1a5aSDimitry Andric collectUsedGlobalVariables(M, Used, /*CompilerUsed*/ true);
47795ec533aSDimitry Andric DenseSet<GlobalValue::GUID> CantBePromoted;
478d88c1a5aSDimitry Andric for (auto *V : Used) {
47995ec533aSDimitry Andric if (V->hasLocalLinkage()) {
480d88c1a5aSDimitry Andric LocalsUsed.insert(V);
48195ec533aSDimitry Andric CantBePromoted.insert(V->getGUID());
48295ec533aSDimitry Andric }
483d88c1a5aSDimitry Andric }
4843ca95b02SDimitry Andric
4852cab237bSDimitry Andric bool HasLocalInlineAsmSymbol = false;
4862cab237bSDimitry Andric if (!M.getModuleInlineAsm().empty()) {
4872cab237bSDimitry Andric // Collect the local values defined by module level asm, and set up
4882cab237bSDimitry Andric // summaries for these symbols so that they can be marked as NoRename,
4892cab237bSDimitry Andric // to prevent export of any use of them in regular IR that would require
4902cab237bSDimitry Andric // renaming within the module level asm. Note we don't need to create a
4912cab237bSDimitry Andric // summary for weak or global defs, as they don't need to be flagged as
4922cab237bSDimitry Andric // NoRename, and defs in module level asm can't be imported anyway.
4932cab237bSDimitry Andric // Also, any values used but not defined within module level asm should
4942cab237bSDimitry Andric // be listed on the llvm.used or llvm.compiler.used global and marked as
4952cab237bSDimitry Andric // referenced from there.
4962cab237bSDimitry Andric ModuleSymbolTable::CollectAsmSymbols(
4972cab237bSDimitry Andric M, [&](StringRef Name, object::BasicSymbolRef::Flags Flags) {
4982cab237bSDimitry Andric // Symbols not marked as Weak or Global are local definitions.
4992cab237bSDimitry Andric if (Flags & (object::BasicSymbolRef::SF_Weak |
5002cab237bSDimitry Andric object::BasicSymbolRef::SF_Global))
5012cab237bSDimitry Andric return;
5022cab237bSDimitry Andric HasLocalInlineAsmSymbol = true;
5032cab237bSDimitry Andric GlobalValue *GV = M.getNamedValue(Name);
5042cab237bSDimitry Andric if (!GV)
5052cab237bSDimitry Andric return;
5062cab237bSDimitry Andric assert(GV->isDeclaration() && "Def in module asm already has definition");
5072cab237bSDimitry Andric GlobalValueSummary::GVFlags GVFlags(GlobalValue::InternalLinkage,
5082cab237bSDimitry Andric /* NotEligibleToImport = */ true,
5092cab237bSDimitry Andric /* Live = */ true,
5102cab237bSDimitry Andric /* Local */ GV->isDSOLocal());
5114ba319b5SDimitry Andric CantBePromoted.insert(GV->getGUID());
5122cab237bSDimitry Andric // Create the appropriate summary type.
5132cab237bSDimitry Andric if (Function *F = dyn_cast<Function>(GV)) {
5142cab237bSDimitry Andric std::unique_ptr<FunctionSummary> Summary =
5152cab237bSDimitry Andric llvm::make_unique<FunctionSummary>(
516*b5893f02SDimitry Andric GVFlags, /*InstCount=*/0,
5172cab237bSDimitry Andric FunctionSummary::FFlags{
5182cab237bSDimitry Andric F->hasFnAttribute(Attribute::ReadNone),
5192cab237bSDimitry Andric F->hasFnAttribute(Attribute::ReadOnly),
5202cab237bSDimitry Andric F->hasFnAttribute(Attribute::NoRecurse),
521*b5893f02SDimitry Andric F->returnDoesNotAlias(),
522*b5893f02SDimitry Andric /* NoInline = */ false},
523*b5893f02SDimitry Andric /*EntryCount=*/0, ArrayRef<ValueInfo>{},
524*b5893f02SDimitry Andric ArrayRef<FunctionSummary::EdgeTy>{},
5252cab237bSDimitry Andric ArrayRef<GlobalValue::GUID>{},
5262cab237bSDimitry Andric ArrayRef<FunctionSummary::VFuncId>{},
5272cab237bSDimitry Andric ArrayRef<FunctionSummary::VFuncId>{},
5282cab237bSDimitry Andric ArrayRef<FunctionSummary::ConstVCall>{},
5292cab237bSDimitry Andric ArrayRef<FunctionSummary::ConstVCall>{});
5304ba319b5SDimitry Andric Index.addGlobalValueSummary(*GV, std::move(Summary));
5312cab237bSDimitry Andric } else {
5322cab237bSDimitry Andric std::unique_ptr<GlobalVarSummary> Summary =
533*b5893f02SDimitry Andric llvm::make_unique<GlobalVarSummary>(
534*b5893f02SDimitry Andric GVFlags, GlobalVarSummary::GVarFlags(),
5352cab237bSDimitry Andric ArrayRef<ValueInfo>{});
5364ba319b5SDimitry Andric Index.addGlobalValueSummary(*GV, std::move(Summary));
5372cab237bSDimitry Andric }
5382cab237bSDimitry Andric });
5392cab237bSDimitry Andric }
5402cab237bSDimitry Andric
541*b5893f02SDimitry Andric bool IsThinLTO = true;
542*b5893f02SDimitry Andric if (auto *MD =
543*b5893f02SDimitry Andric mdconst::extract_or_null<ConstantInt>(M.getModuleFlag("ThinLTO")))
544*b5893f02SDimitry Andric IsThinLTO = MD->getZExtValue();
545*b5893f02SDimitry Andric
5463ca95b02SDimitry Andric // Compute summaries for all functions defined in module, and save in the
5473ca95b02SDimitry Andric // index.
548d88c1a5aSDimitry Andric for (auto &F : M) {
5493ca95b02SDimitry Andric if (F.isDeclaration())
5503ca95b02SDimitry Andric continue;
5513ca95b02SDimitry Andric
552*b5893f02SDimitry Andric DominatorTree DT(const_cast<Function &>(F));
5533ca95b02SDimitry Andric BlockFrequencyInfo *BFI = nullptr;
5543ca95b02SDimitry Andric std::unique_ptr<BlockFrequencyInfo> BFIPtr;
555d88c1a5aSDimitry Andric if (GetBFICallback)
556d88c1a5aSDimitry Andric BFI = GetBFICallback(F);
557da09e106SDimitry Andric else if (F.hasProfileData()) {
558*b5893f02SDimitry Andric LoopInfo LI{DT};
5593ca95b02SDimitry Andric BranchProbabilityInfo BPI{F, LI};
5603ca95b02SDimitry Andric BFIPtr = llvm::make_unique<BlockFrequencyInfo>(F, BPI, LI);
5613ca95b02SDimitry Andric BFI = BFIPtr.get();
5623ca95b02SDimitry Andric }
5633ca95b02SDimitry Andric
564*b5893f02SDimitry Andric computeFunctionSummary(Index, M, F, BFI, PSI, DT,
5652cab237bSDimitry Andric !LocalsUsed.empty() || HasLocalInlineAsmSymbol,
566*b5893f02SDimitry Andric CantBePromoted, IsThinLTO);
5673ca95b02SDimitry Andric }
5683ca95b02SDimitry Andric
5693ca95b02SDimitry Andric // Compute summaries for all variables defined in module, and save in the
5703ca95b02SDimitry Andric // index.
571d88c1a5aSDimitry Andric for (const GlobalVariable &G : M.globals()) {
5723ca95b02SDimitry Andric if (G.isDeclaration())
5733ca95b02SDimitry Andric continue;
57495ec533aSDimitry Andric computeVariableSummary(Index, G, CantBePromoted);
5753ca95b02SDimitry Andric }
576d88c1a5aSDimitry Andric
577d88c1a5aSDimitry Andric // Compute summaries for all aliases defined in module, and save in the
578d88c1a5aSDimitry Andric // index.
579d88c1a5aSDimitry Andric for (const GlobalAlias &A : M.aliases())
58095ec533aSDimitry Andric computeAliasSummary(Index, A, CantBePromoted);
581d88c1a5aSDimitry Andric
582d88c1a5aSDimitry Andric for (auto *V : LocalsUsed) {
583d88c1a5aSDimitry Andric auto *Summary = Index.getGlobalValueSummary(*V);
584d88c1a5aSDimitry Andric assert(Summary && "Missing summary for global value");
58595ec533aSDimitry Andric Summary->setNotEligibleToImport();
586d88c1a5aSDimitry Andric }
587d88c1a5aSDimitry Andric
58895ec533aSDimitry Andric // The linker doesn't know about these LLVM produced values, so we need
58995ec533aSDimitry Andric // to flag them as live in the index to ensure index-based dead value
59095ec533aSDimitry Andric // analysis treats them as live roots of the analysis.
59195ec533aSDimitry Andric setLiveRoot(Index, "llvm.used");
59295ec533aSDimitry Andric setLiveRoot(Index, "llvm.compiler.used");
59395ec533aSDimitry Andric setLiveRoot(Index, "llvm.global_ctors");
59495ec533aSDimitry Andric setLiveRoot(Index, "llvm.global_dtors");
59595ec533aSDimitry Andric setLiveRoot(Index, "llvm.global.annotations");
59695ec533aSDimitry Andric
59795ec533aSDimitry Andric for (auto &GlobalList : Index) {
5980f5676f4SDimitry Andric // Ignore entries for references that are undefined in the current module.
5990f5676f4SDimitry Andric if (GlobalList.second.SummaryList.empty())
6000f5676f4SDimitry Andric continue;
6010f5676f4SDimitry Andric
6020f5676f4SDimitry Andric assert(GlobalList.second.SummaryList.size() == 1 &&
60395ec533aSDimitry Andric "Expected module's index to have one summary per GUID");
6040f5676f4SDimitry Andric auto &Summary = GlobalList.second.SummaryList[0];
605db17bf38SDimitry Andric if (!IsThinLTO) {
606db17bf38SDimitry Andric Summary->setNotEligibleToImport();
607db17bf38SDimitry Andric continue;
608db17bf38SDimitry Andric }
609db17bf38SDimitry Andric
61095ec533aSDimitry Andric bool AllRefsCanBeExternallyReferenced =
61195ec533aSDimitry Andric llvm::all_of(Summary->refs(), [&](const ValueInfo &VI) {
6120f5676f4SDimitry Andric return !CantBePromoted.count(VI.getGUID());
61395ec533aSDimitry Andric });
61495ec533aSDimitry Andric if (!AllRefsCanBeExternallyReferenced) {
61595ec533aSDimitry Andric Summary->setNotEligibleToImport();
61695ec533aSDimitry Andric continue;
61795ec533aSDimitry Andric }
61895ec533aSDimitry Andric
61995ec533aSDimitry Andric if (auto *FuncSummary = dyn_cast<FunctionSummary>(Summary.get())) {
62095ec533aSDimitry Andric bool AllCallsCanBeExternallyReferenced = llvm::all_of(
62195ec533aSDimitry Andric FuncSummary->calls(), [&](const FunctionSummary::EdgeTy &Edge) {
6220f5676f4SDimitry Andric return !CantBePromoted.count(Edge.first.getGUID());
62395ec533aSDimitry Andric });
62495ec533aSDimitry Andric if (!AllCallsCanBeExternallyReferenced)
62595ec533aSDimitry Andric Summary->setNotEligibleToImport();
62695ec533aSDimitry Andric }
62795ec533aSDimitry Andric }
62895ec533aSDimitry Andric
629d88c1a5aSDimitry Andric return Index;
630d88c1a5aSDimitry Andric }
631d88c1a5aSDimitry Andric
632d88c1a5aSDimitry Andric AnalysisKey ModuleSummaryIndexAnalysis::Key;
633d88c1a5aSDimitry Andric
634d88c1a5aSDimitry Andric ModuleSummaryIndex
run(Module & M,ModuleAnalysisManager & AM)635d88c1a5aSDimitry Andric ModuleSummaryIndexAnalysis::run(Module &M, ModuleAnalysisManager &AM) {
636d88c1a5aSDimitry Andric ProfileSummaryInfo &PSI = AM.getResult<ProfileSummaryAnalysis>(M);
637d88c1a5aSDimitry Andric auto &FAM = AM.getResult<FunctionAnalysisManagerModuleProxy>(M).getManager();
638d88c1a5aSDimitry Andric return buildModuleSummaryIndex(
639d88c1a5aSDimitry Andric M,
640d88c1a5aSDimitry Andric [&FAM](const Function &F) {
641d88c1a5aSDimitry Andric return &FAM.getResult<BlockFrequencyAnalysis>(
642d88c1a5aSDimitry Andric *const_cast<Function *>(&F));
643d88c1a5aSDimitry Andric },
644d88c1a5aSDimitry Andric &PSI);
6453ca95b02SDimitry Andric }
6463ca95b02SDimitry Andric
6473ca95b02SDimitry Andric char ModuleSummaryIndexWrapperPass::ID = 0;
6482cab237bSDimitry Andric
6493ca95b02SDimitry Andric INITIALIZE_PASS_BEGIN(ModuleSummaryIndexWrapperPass, "module-summary-analysis",
6503ca95b02SDimitry Andric "Module Summary Analysis", false, true)
INITIALIZE_PASS_DEPENDENCY(BlockFrequencyInfoWrapperPass)6513ca95b02SDimitry Andric INITIALIZE_PASS_DEPENDENCY(BlockFrequencyInfoWrapperPass)
65294c53d40SDimitry Andric INITIALIZE_PASS_DEPENDENCY(ProfileSummaryInfoWrapperPass)
6533ca95b02SDimitry Andric INITIALIZE_PASS_END(ModuleSummaryIndexWrapperPass, "module-summary-analysis",
6543ca95b02SDimitry Andric "Module Summary Analysis", false, true)
6553ca95b02SDimitry Andric
6563ca95b02SDimitry Andric ModulePass *llvm::createModuleSummaryIndexWrapperPass() {
6573ca95b02SDimitry Andric return new ModuleSummaryIndexWrapperPass();
6583ca95b02SDimitry Andric }
6593ca95b02SDimitry Andric
ModuleSummaryIndexWrapperPass()6603ca95b02SDimitry Andric ModuleSummaryIndexWrapperPass::ModuleSummaryIndexWrapperPass()
6613ca95b02SDimitry Andric : ModulePass(ID) {
6623ca95b02SDimitry Andric initializeModuleSummaryIndexWrapperPassPass(*PassRegistry::getPassRegistry());
6633ca95b02SDimitry Andric }
6643ca95b02SDimitry Andric
runOnModule(Module & M)6653ca95b02SDimitry Andric bool ModuleSummaryIndexWrapperPass::runOnModule(Module &M) {
666*b5893f02SDimitry Andric auto *PSI = &getAnalysis<ProfileSummaryInfoWrapperPass>().getPSI();
6674ba319b5SDimitry Andric Index.emplace(buildModuleSummaryIndex(
668d88c1a5aSDimitry Andric M,
669d88c1a5aSDimitry Andric [this](const Function &F) {
6703ca95b02SDimitry Andric return &(this->getAnalysis<BlockFrequencyInfoWrapperPass>(
6713ca95b02SDimitry Andric *const_cast<Function *>(&F))
6723ca95b02SDimitry Andric .getBFI());
673d88c1a5aSDimitry Andric },
674*b5893f02SDimitry Andric PSI));
6753ca95b02SDimitry Andric return false;
6763ca95b02SDimitry Andric }
6773ca95b02SDimitry Andric
doFinalization(Module & M)6783ca95b02SDimitry Andric bool ModuleSummaryIndexWrapperPass::doFinalization(Module &M) {
679d88c1a5aSDimitry Andric Index.reset();
6803ca95b02SDimitry Andric return false;
6813ca95b02SDimitry Andric }
6823ca95b02SDimitry Andric
getAnalysisUsage(AnalysisUsage & AU) const6833ca95b02SDimitry Andric void ModuleSummaryIndexWrapperPass::getAnalysisUsage(AnalysisUsage &AU) const {
6843ca95b02SDimitry Andric AU.setPreservesAll();
6853ca95b02SDimitry Andric AU.addRequired<BlockFrequencyInfoWrapperPass>();
686d88c1a5aSDimitry Andric AU.addRequired<ProfileSummaryInfoWrapperPass>();
6873ca95b02SDimitry Andric }
688