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