xref: /freebsd-src/contrib/llvm-project/llvm/lib/Analysis/ModuleSummaryAnalysis.cpp (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
10b57cec5SDimitry Andric //===- ModuleSummaryAnalysis.cpp - Module summary index builder -----------===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric //
90b57cec5SDimitry Andric // This pass builds a ModuleSummaryIndex object for the module, to be written
100b57cec5SDimitry Andric // to bitcode or LLVM assembly.
110b57cec5SDimitry Andric //
120b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
130b57cec5SDimitry Andric 
140b57cec5SDimitry Andric #include "llvm/Analysis/ModuleSummaryAnalysis.h"
150b57cec5SDimitry Andric #include "llvm/ADT/ArrayRef.h"
160b57cec5SDimitry Andric #include "llvm/ADT/DenseSet.h"
170b57cec5SDimitry Andric #include "llvm/ADT/MapVector.h"
180b57cec5SDimitry Andric #include "llvm/ADT/STLExtras.h"
190b57cec5SDimitry Andric #include "llvm/ADT/SetVector.h"
200b57cec5SDimitry Andric #include "llvm/ADT/SmallPtrSet.h"
210b57cec5SDimitry Andric #include "llvm/ADT/SmallVector.h"
220b57cec5SDimitry Andric #include "llvm/ADT/StringRef.h"
230b57cec5SDimitry Andric #include "llvm/Analysis/BlockFrequencyInfo.h"
240b57cec5SDimitry Andric #include "llvm/Analysis/BranchProbabilityInfo.h"
25*0fca6ea1SDimitry Andric #include "llvm/Analysis/ConstantFolding.h"
260b57cec5SDimitry Andric #include "llvm/Analysis/IndirectCallPromotionAnalysis.h"
270b57cec5SDimitry Andric #include "llvm/Analysis/LoopInfo.h"
28bdd1243dSDimitry Andric #include "llvm/Analysis/MemoryProfileInfo.h"
290b57cec5SDimitry Andric #include "llvm/Analysis/ProfileSummaryInfo.h"
305ffd83dbSDimitry Andric #include "llvm/Analysis/StackSafetyAnalysis.h"
310b57cec5SDimitry Andric #include "llvm/Analysis/TypeMetadataUtils.h"
320b57cec5SDimitry Andric #include "llvm/IR/Attributes.h"
330b57cec5SDimitry Andric #include "llvm/IR/BasicBlock.h"
340b57cec5SDimitry Andric #include "llvm/IR/Constant.h"
350b57cec5SDimitry Andric #include "llvm/IR/Constants.h"
360b57cec5SDimitry Andric #include "llvm/IR/Dominators.h"
370b57cec5SDimitry Andric #include "llvm/IR/Function.h"
380b57cec5SDimitry Andric #include "llvm/IR/GlobalAlias.h"
390b57cec5SDimitry Andric #include "llvm/IR/GlobalValue.h"
400b57cec5SDimitry Andric #include "llvm/IR/GlobalVariable.h"
410b57cec5SDimitry Andric #include "llvm/IR/Instructions.h"
420b57cec5SDimitry Andric #include "llvm/IR/IntrinsicInst.h"
430b57cec5SDimitry Andric #include "llvm/IR/Metadata.h"
440b57cec5SDimitry Andric #include "llvm/IR/Module.h"
450b57cec5SDimitry Andric #include "llvm/IR/ModuleSummaryIndex.h"
460b57cec5SDimitry Andric #include "llvm/IR/Use.h"
470b57cec5SDimitry Andric #include "llvm/IR/User.h"
48480093f4SDimitry Andric #include "llvm/InitializePasses.h"
490b57cec5SDimitry Andric #include "llvm/Object/ModuleSymbolTable.h"
500b57cec5SDimitry Andric #include "llvm/Object/SymbolicFile.h"
510b57cec5SDimitry Andric #include "llvm/Pass.h"
520b57cec5SDimitry Andric #include "llvm/Support/Casting.h"
530b57cec5SDimitry Andric #include "llvm/Support/CommandLine.h"
54fe6060f1SDimitry Andric #include "llvm/Support/FileSystem.h"
550b57cec5SDimitry Andric #include <algorithm>
560b57cec5SDimitry Andric #include <cassert>
570b57cec5SDimitry Andric #include <cstdint>
580b57cec5SDimitry Andric #include <vector>
590b57cec5SDimitry Andric 
600b57cec5SDimitry Andric using namespace llvm;
61bdd1243dSDimitry Andric using namespace llvm::memprof;
620b57cec5SDimitry Andric 
630b57cec5SDimitry Andric #define DEBUG_TYPE "module-summary-analysis"
640b57cec5SDimitry Andric 
650b57cec5SDimitry Andric // Option to force edges cold which will block importing when the
660b57cec5SDimitry Andric // -import-cold-multiplier is set to 0. Useful for debugging.
67bdd1243dSDimitry Andric namespace llvm {
680b57cec5SDimitry Andric FunctionSummary::ForceSummaryHotnessType ForceSummaryEdgesCold =
690b57cec5SDimitry Andric     FunctionSummary::FSHT_None;
70bdd1243dSDimitry Andric } // namespace llvm
71bdd1243dSDimitry Andric 
72bdd1243dSDimitry Andric static cl::opt<FunctionSummary::ForceSummaryHotnessType, true> FSEC(
730b57cec5SDimitry Andric     "force-summary-edges-cold", cl::Hidden, cl::location(ForceSummaryEdgesCold),
740b57cec5SDimitry Andric     cl::desc("Force all edges in the function summary to cold"),
750b57cec5SDimitry Andric     cl::values(clEnumValN(FunctionSummary::FSHT_None, "none", "None."),
760b57cec5SDimitry Andric                clEnumValN(FunctionSummary::FSHT_AllNonCritical,
770b57cec5SDimitry Andric                           "all-non-critical", "All non-critical edges."),
780b57cec5SDimitry Andric                clEnumValN(FunctionSummary::FSHT_All, "all", "All edges.")));
790b57cec5SDimitry Andric 
80bdd1243dSDimitry Andric static cl::opt<std::string> ModuleSummaryDotFile(
81bdd1243dSDimitry Andric     "module-summary-dot-file", cl::Hidden, cl::value_desc("filename"),
82bdd1243dSDimitry Andric     cl::desc("File to emit dot graph of new summary into"));
830b57cec5SDimitry Andric 
8406c3fb27SDimitry Andric extern cl::opt<bool> ScalePartialSampleProfileWorkingSetSize;
8506c3fb27SDimitry Andric 
86*0fca6ea1SDimitry Andric extern cl::opt<unsigned> MaxNumVTableAnnotations;
87*0fca6ea1SDimitry Andric 
88*0fca6ea1SDimitry Andric extern cl::opt<bool> MemProfReportHintedSizes;
89*0fca6ea1SDimitry Andric 
900b57cec5SDimitry Andric // Walk through the operands of a given User via worklist iteration and populate
910b57cec5SDimitry Andric // the set of GlobalValue references encountered. Invoked either on an
920b57cec5SDimitry Andric // Instruction or a GlobalVariable (which walks its initializer).
930b57cec5SDimitry Andric // Return true if any of the operands contains blockaddress. This is important
940b57cec5SDimitry Andric // to know when computing summary for global var, because if global variable
950b57cec5SDimitry Andric // references basic block address we can't import it separately from function
960b57cec5SDimitry Andric // containing that basic block. For simplicity we currently don't import such
970b57cec5SDimitry Andric // global vars at all. When importing function we aren't interested if any
980b57cec5SDimitry Andric // instruction in it takes an address of any basic block, because instruction
990b57cec5SDimitry Andric // can only take an address of basic block located in the same function.
100*0fca6ea1SDimitry Andric // Set `RefLocalLinkageIFunc` to true if the analyzed value references a
101*0fca6ea1SDimitry Andric // local-linkage ifunc.
1020b57cec5SDimitry Andric static bool findRefEdges(ModuleSummaryIndex &Index, const User *CurUser,
1035f757f3fSDimitry Andric                          SetVector<ValueInfo, std::vector<ValueInfo>> &RefEdges,
104*0fca6ea1SDimitry Andric                          SmallPtrSet<const User *, 8> &Visited,
105*0fca6ea1SDimitry Andric                          bool &RefLocalLinkageIFunc) {
1060b57cec5SDimitry Andric   bool HasBlockAddress = false;
1070b57cec5SDimitry Andric   SmallVector<const User *, 32> Worklist;
108fe6060f1SDimitry Andric   if (Visited.insert(CurUser).second)
1090b57cec5SDimitry Andric     Worklist.push_back(CurUser);
1100b57cec5SDimitry Andric 
1110b57cec5SDimitry Andric   while (!Worklist.empty()) {
1120b57cec5SDimitry Andric     const User *U = Worklist.pop_back_val();
1135ffd83dbSDimitry Andric     const auto *CB = dyn_cast<CallBase>(U);
1140b57cec5SDimitry Andric 
1150b57cec5SDimitry Andric     for (const auto &OI : U->operands()) {
1160b57cec5SDimitry Andric       const User *Operand = dyn_cast<User>(OI);
1170b57cec5SDimitry Andric       if (!Operand)
1180b57cec5SDimitry Andric         continue;
1190b57cec5SDimitry Andric       if (isa<BlockAddress>(Operand)) {
1200b57cec5SDimitry Andric         HasBlockAddress = true;
1210b57cec5SDimitry Andric         continue;
1220b57cec5SDimitry Andric       }
1230b57cec5SDimitry Andric       if (auto *GV = dyn_cast<GlobalValue>(Operand)) {
1240b57cec5SDimitry Andric         // We have a reference to a global value. This should be added to
1250b57cec5SDimitry Andric         // the reference set unless it is a callee. Callees are handled
1260b57cec5SDimitry Andric         // specially by WriteFunction and are added to a separate list.
127*0fca6ea1SDimitry Andric         if (!(CB && CB->isCallee(&OI))) {
128*0fca6ea1SDimitry Andric           // If an ifunc has local linkage, do not add it into ref edges, and
129*0fca6ea1SDimitry Andric           // sets `RefLocalLinkageIFunc` to true. The referencer is not eligible
130*0fca6ea1SDimitry Andric           // for import. An ifunc doesn't have summary and ThinLTO cannot
131*0fca6ea1SDimitry Andric           // promote it; importing the referencer may cause linkage errors.
132*0fca6ea1SDimitry Andric           if (auto *GI = dyn_cast_if_present<GlobalIFunc>(GV);
133*0fca6ea1SDimitry Andric               GI && GI->hasLocalLinkage()) {
134*0fca6ea1SDimitry Andric             RefLocalLinkageIFunc = true;
135*0fca6ea1SDimitry Andric             continue;
136*0fca6ea1SDimitry Andric           }
1370b57cec5SDimitry Andric           RefEdges.insert(Index.getOrInsertValueInfo(GV));
138*0fca6ea1SDimitry Andric         }
1390b57cec5SDimitry Andric         continue;
1400b57cec5SDimitry Andric       }
141fe6060f1SDimitry Andric       if (Visited.insert(Operand).second)
1420b57cec5SDimitry Andric         Worklist.push_back(Operand);
1430b57cec5SDimitry Andric     }
1440b57cec5SDimitry Andric   }
145*0fca6ea1SDimitry Andric 
146*0fca6ea1SDimitry Andric   const Instruction *I = dyn_cast<Instruction>(CurUser);
147*0fca6ea1SDimitry Andric   if (I) {
148*0fca6ea1SDimitry Andric     uint64_t TotalCount = 0;
149*0fca6ea1SDimitry Andric     // MaxNumVTableAnnotations is the maximum number of vtables annotated on
150*0fca6ea1SDimitry Andric     // the instruction.
151*0fca6ea1SDimitry Andric     auto ValueDataArray = getValueProfDataFromInst(
152*0fca6ea1SDimitry Andric         *I, IPVK_VTableTarget, MaxNumVTableAnnotations, TotalCount);
153*0fca6ea1SDimitry Andric 
154*0fca6ea1SDimitry Andric     for (const auto &V : ValueDataArray)
155*0fca6ea1SDimitry Andric       RefEdges.insert(Index.getOrInsertValueInfo(/* VTableGUID = */
156*0fca6ea1SDimitry Andric                                                  V.Value));
157*0fca6ea1SDimitry Andric   }
1580b57cec5SDimitry Andric   return HasBlockAddress;
1590b57cec5SDimitry Andric }
1600b57cec5SDimitry Andric 
1610b57cec5SDimitry Andric static CalleeInfo::HotnessType getHotness(uint64_t ProfileCount,
1620b57cec5SDimitry Andric                                           ProfileSummaryInfo *PSI) {
1630b57cec5SDimitry Andric   if (!PSI)
1640b57cec5SDimitry Andric     return CalleeInfo::HotnessType::Unknown;
1650b57cec5SDimitry Andric   if (PSI->isHotCount(ProfileCount))
1660b57cec5SDimitry Andric     return CalleeInfo::HotnessType::Hot;
1670b57cec5SDimitry Andric   if (PSI->isColdCount(ProfileCount))
1680b57cec5SDimitry Andric     return CalleeInfo::HotnessType::Cold;
1690b57cec5SDimitry Andric   return CalleeInfo::HotnessType::None;
1700b57cec5SDimitry Andric }
1710b57cec5SDimitry Andric 
1720b57cec5SDimitry Andric static bool isNonRenamableLocal(const GlobalValue &GV) {
1730b57cec5SDimitry Andric   return GV.hasSection() && GV.hasLocalLinkage();
1740b57cec5SDimitry Andric }
1750b57cec5SDimitry Andric 
1760b57cec5SDimitry Andric /// Determine whether this call has all constant integer arguments (excluding
1770b57cec5SDimitry Andric /// "this") and summarize it to VCalls or ConstVCalls as appropriate.
1785f757f3fSDimitry Andric static void addVCallToSet(
1795f757f3fSDimitry Andric     DevirtCallSite Call, GlobalValue::GUID Guid,
1805f757f3fSDimitry Andric     SetVector<FunctionSummary::VFuncId, std::vector<FunctionSummary::VFuncId>>
1815f757f3fSDimitry Andric         &VCalls,
1825f757f3fSDimitry Andric     SetVector<FunctionSummary::ConstVCall,
1835f757f3fSDimitry Andric               std::vector<FunctionSummary::ConstVCall>> &ConstVCalls) {
1840b57cec5SDimitry Andric   std::vector<uint64_t> Args;
1850b57cec5SDimitry Andric   // Start from the second argument to skip the "this" pointer.
186e8d8bef9SDimitry Andric   for (auto &Arg : drop_begin(Call.CB.args())) {
1870b57cec5SDimitry Andric     auto *CI = dyn_cast<ConstantInt>(Arg);
1880b57cec5SDimitry Andric     if (!CI || CI->getBitWidth() > 64) {
1890b57cec5SDimitry Andric       VCalls.insert({Guid, Call.Offset});
1900b57cec5SDimitry Andric       return;
1910b57cec5SDimitry Andric     }
1920b57cec5SDimitry Andric     Args.push_back(CI->getZExtValue());
1930b57cec5SDimitry Andric   }
1940b57cec5SDimitry Andric   ConstVCalls.insert({{Guid, Call.Offset}, std::move(Args)});
1950b57cec5SDimitry Andric }
1960b57cec5SDimitry Andric 
1970b57cec5SDimitry Andric /// If this intrinsic call requires that we add information to the function
1980b57cec5SDimitry Andric /// summary, do so via the non-constant reference arguments.
1990b57cec5SDimitry Andric static void addIntrinsicToSummary(
2005f757f3fSDimitry Andric     const CallInst *CI,
2015f757f3fSDimitry Andric     SetVector<GlobalValue::GUID, std::vector<GlobalValue::GUID>> &TypeTests,
2025f757f3fSDimitry Andric     SetVector<FunctionSummary::VFuncId, std::vector<FunctionSummary::VFuncId>>
2035f757f3fSDimitry Andric         &TypeTestAssumeVCalls,
2045f757f3fSDimitry Andric     SetVector<FunctionSummary::VFuncId, std::vector<FunctionSummary::VFuncId>>
2055f757f3fSDimitry Andric         &TypeCheckedLoadVCalls,
2065f757f3fSDimitry Andric     SetVector<FunctionSummary::ConstVCall,
2075f757f3fSDimitry Andric               std::vector<FunctionSummary::ConstVCall>>
2085f757f3fSDimitry Andric         &TypeTestAssumeConstVCalls,
2095f757f3fSDimitry Andric     SetVector<FunctionSummary::ConstVCall,
2105f757f3fSDimitry Andric               std::vector<FunctionSummary::ConstVCall>>
2115f757f3fSDimitry Andric         &TypeCheckedLoadConstVCalls,
2120b57cec5SDimitry Andric     DominatorTree &DT) {
2130b57cec5SDimitry Andric   switch (CI->getCalledFunction()->getIntrinsicID()) {
214972a253aSDimitry Andric   case Intrinsic::type_test:
215972a253aSDimitry Andric   case Intrinsic::public_type_test: {
2160b57cec5SDimitry Andric     auto *TypeMDVal = cast<MetadataAsValue>(CI->getArgOperand(1));
2170b57cec5SDimitry Andric     auto *TypeId = dyn_cast<MDString>(TypeMDVal->getMetadata());
2180b57cec5SDimitry Andric     if (!TypeId)
2190b57cec5SDimitry Andric       break;
2200b57cec5SDimitry Andric     GlobalValue::GUID Guid = GlobalValue::getGUID(TypeId->getString());
2210b57cec5SDimitry Andric 
2220b57cec5SDimitry Andric     // Produce a summary from type.test intrinsics. We only summarize type.test
2230b57cec5SDimitry Andric     // intrinsics that are used other than by an llvm.assume intrinsic.
2240b57cec5SDimitry Andric     // Intrinsics that are assumed are relevant only to the devirtualization
2250b57cec5SDimitry Andric     // pass, not the type test lowering pass.
2260b57cec5SDimitry Andric     bool HasNonAssumeUses = llvm::any_of(CI->uses(), [](const Use &CIU) {
227fe6060f1SDimitry Andric       return !isa<AssumeInst>(CIU.getUser());
2280b57cec5SDimitry Andric     });
2290b57cec5SDimitry Andric     if (HasNonAssumeUses)
2300b57cec5SDimitry Andric       TypeTests.insert(Guid);
2310b57cec5SDimitry Andric 
2320b57cec5SDimitry Andric     SmallVector<DevirtCallSite, 4> DevirtCalls;
2330b57cec5SDimitry Andric     SmallVector<CallInst *, 4> Assumes;
2340b57cec5SDimitry Andric     findDevirtualizableCallsForTypeTest(DevirtCalls, Assumes, CI, DT);
2350b57cec5SDimitry Andric     for (auto &Call : DevirtCalls)
2360b57cec5SDimitry Andric       addVCallToSet(Call, Guid, TypeTestAssumeVCalls,
2370b57cec5SDimitry Andric                     TypeTestAssumeConstVCalls);
2380b57cec5SDimitry Andric 
2390b57cec5SDimitry Andric     break;
2400b57cec5SDimitry Andric   }
2410b57cec5SDimitry Andric 
24206c3fb27SDimitry Andric   case Intrinsic::type_checked_load_relative:
2430b57cec5SDimitry Andric   case Intrinsic::type_checked_load: {
2440b57cec5SDimitry Andric     auto *TypeMDVal = cast<MetadataAsValue>(CI->getArgOperand(2));
2450b57cec5SDimitry Andric     auto *TypeId = dyn_cast<MDString>(TypeMDVal->getMetadata());
2460b57cec5SDimitry Andric     if (!TypeId)
2470b57cec5SDimitry Andric       break;
2480b57cec5SDimitry Andric     GlobalValue::GUID Guid = GlobalValue::getGUID(TypeId->getString());
2490b57cec5SDimitry Andric 
2500b57cec5SDimitry Andric     SmallVector<DevirtCallSite, 4> DevirtCalls;
2510b57cec5SDimitry Andric     SmallVector<Instruction *, 4> LoadedPtrs;
2520b57cec5SDimitry Andric     SmallVector<Instruction *, 4> Preds;
2530b57cec5SDimitry Andric     bool HasNonCallUses = false;
2540b57cec5SDimitry Andric     findDevirtualizableCallsForTypeCheckedLoad(DevirtCalls, LoadedPtrs, Preds,
2550b57cec5SDimitry Andric                                                HasNonCallUses, CI, DT);
2560b57cec5SDimitry Andric     // Any non-call uses of the result of llvm.type.checked.load will
2570b57cec5SDimitry Andric     // prevent us from optimizing away the llvm.type.test.
2580b57cec5SDimitry Andric     if (HasNonCallUses)
2590b57cec5SDimitry Andric       TypeTests.insert(Guid);
2600b57cec5SDimitry Andric     for (auto &Call : DevirtCalls)
2610b57cec5SDimitry Andric       addVCallToSet(Call, Guid, TypeCheckedLoadVCalls,
2620b57cec5SDimitry Andric                     TypeCheckedLoadConstVCalls);
2630b57cec5SDimitry Andric 
2640b57cec5SDimitry Andric     break;
2650b57cec5SDimitry Andric   }
2660b57cec5SDimitry Andric   default:
2670b57cec5SDimitry Andric     break;
2680b57cec5SDimitry Andric   }
2690b57cec5SDimitry Andric }
2700b57cec5SDimitry Andric 
2710b57cec5SDimitry Andric static bool isNonVolatileLoad(const Instruction *I) {
2720b57cec5SDimitry Andric   if (const auto *LI = dyn_cast<LoadInst>(I))
2730b57cec5SDimitry Andric     return !LI->isVolatile();
2740b57cec5SDimitry Andric 
2750b57cec5SDimitry Andric   return false;
2760b57cec5SDimitry Andric }
2770b57cec5SDimitry Andric 
2780b57cec5SDimitry Andric static bool isNonVolatileStore(const Instruction *I) {
2790b57cec5SDimitry Andric   if (const auto *SI = dyn_cast<StoreInst>(I))
2800b57cec5SDimitry Andric     return !SI->isVolatile();
2810b57cec5SDimitry Andric 
2820b57cec5SDimitry Andric   return false;
2830b57cec5SDimitry Andric }
2840b57cec5SDimitry Andric 
2850eae32dcSDimitry Andric // Returns true if the function definition must be unreachable.
2860eae32dcSDimitry Andric //
2870eae32dcSDimitry Andric // Note if this helper function returns true, `F` is guaranteed
2880eae32dcSDimitry Andric // to be unreachable; if it returns false, `F` might still
2890eae32dcSDimitry Andric // be unreachable but not covered by this helper function.
2900eae32dcSDimitry Andric static bool mustBeUnreachableFunction(const Function &F) {
2910eae32dcSDimitry Andric   // A function must be unreachable if its entry block ends with an
2920eae32dcSDimitry Andric   // 'unreachable'.
2930eae32dcSDimitry Andric   assert(!F.isDeclaration());
2940eae32dcSDimitry Andric   return isa<UnreachableInst>(F.getEntryBlock().getTerminator());
2950eae32dcSDimitry Andric }
2960eae32dcSDimitry Andric 
2975ffd83dbSDimitry Andric static void computeFunctionSummary(
2985ffd83dbSDimitry Andric     ModuleSummaryIndex &Index, const Module &M, const Function &F,
2995ffd83dbSDimitry Andric     BlockFrequencyInfo *BFI, ProfileSummaryInfo *PSI, DominatorTree &DT,
3005ffd83dbSDimitry Andric     bool HasLocalsInUsedOrAsm, DenseSet<GlobalValue::GUID> &CantBePromoted,
3015ffd83dbSDimitry Andric     bool IsThinLTO,
3025ffd83dbSDimitry Andric     std::function<const StackSafetyInfo *(const Function &F)> GetSSICallback) {
3030b57cec5SDimitry Andric   // Summary not currently supported for anonymous functions, they should
3040b57cec5SDimitry Andric   // have been named.
3050b57cec5SDimitry Andric   assert(F.hasName());
3060b57cec5SDimitry Andric 
3070b57cec5SDimitry Andric   unsigned NumInsts = 0;
3080b57cec5SDimitry Andric   // Map from callee ValueId to profile count. Used to accumulate profile
3090b57cec5SDimitry Andric   // counts for all static calls to a given callee.
31006c3fb27SDimitry Andric   MapVector<ValueInfo, CalleeInfo, DenseMap<ValueInfo, unsigned>,
31106c3fb27SDimitry Andric             std::vector<std::pair<ValueInfo, CalleeInfo>>>
31206c3fb27SDimitry Andric       CallGraphEdges;
3135f757f3fSDimitry Andric   SetVector<ValueInfo, std::vector<ValueInfo>> RefEdges, LoadRefEdges,
3145f757f3fSDimitry Andric       StoreRefEdges;
3155f757f3fSDimitry Andric   SetVector<GlobalValue::GUID, std::vector<GlobalValue::GUID>> TypeTests;
3165f757f3fSDimitry Andric   SetVector<FunctionSummary::VFuncId, std::vector<FunctionSummary::VFuncId>>
3175f757f3fSDimitry Andric       TypeTestAssumeVCalls, TypeCheckedLoadVCalls;
3185f757f3fSDimitry Andric   SetVector<FunctionSummary::ConstVCall,
3195f757f3fSDimitry Andric             std::vector<FunctionSummary::ConstVCall>>
3205f757f3fSDimitry Andric       TypeTestAssumeConstVCalls, TypeCheckedLoadConstVCalls;
3210b57cec5SDimitry Andric   ICallPromotionAnalysis ICallAnalysis;
3220b57cec5SDimitry Andric   SmallPtrSet<const User *, 8> Visited;
3230b57cec5SDimitry Andric 
3240b57cec5SDimitry Andric   // Add personality function, prefix data and prologue data to function's ref
3250b57cec5SDimitry Andric   // list.
326*0fca6ea1SDimitry Andric   bool HasLocalIFuncCallOrRef = false;
327*0fca6ea1SDimitry Andric   findRefEdges(Index, &F, RefEdges, Visited, HasLocalIFuncCallOrRef);
3280b57cec5SDimitry Andric   std::vector<const Instruction *> NonVolatileLoads;
3290b57cec5SDimitry Andric   std::vector<const Instruction *> NonVolatileStores;
3300b57cec5SDimitry Andric 
331bdd1243dSDimitry Andric   std::vector<CallsiteInfo> Callsites;
332bdd1243dSDimitry Andric   std::vector<AllocInfo> Allocs;
333bdd1243dSDimitry Andric 
33406c3fb27SDimitry Andric #ifndef NDEBUG
33506c3fb27SDimitry Andric   DenseSet<const CallBase *> CallsThatMayHaveMemprofSummary;
33606c3fb27SDimitry Andric #endif
33706c3fb27SDimitry Andric 
3380b57cec5SDimitry Andric   bool HasInlineAsmMaybeReferencingInternal = false;
339349cc55cSDimitry Andric   bool HasIndirBranchToBlockAddress = false;
340349cc55cSDimitry Andric   bool HasUnknownCall = false;
341349cc55cSDimitry Andric   bool MayThrow = false;
342349cc55cSDimitry Andric   for (const BasicBlock &BB : F) {
343349cc55cSDimitry Andric     // We don't allow inlining of function with indirect branch to blockaddress.
344349cc55cSDimitry Andric     // If the blockaddress escapes the function, e.g., via a global variable,
345349cc55cSDimitry Andric     // inlining may lead to an invalid cross-function reference. So we shouldn't
346349cc55cSDimitry Andric     // import such function either.
347349cc55cSDimitry Andric     if (BB.hasAddressTaken()) {
348349cc55cSDimitry Andric       for (User *U : BlockAddress::get(const_cast<BasicBlock *>(&BB))->users())
349349cc55cSDimitry Andric         if (!isa<CallBrInst>(*U)) {
350349cc55cSDimitry Andric           HasIndirBranchToBlockAddress = true;
351349cc55cSDimitry Andric           break;
352349cc55cSDimitry Andric         }
353349cc55cSDimitry Andric     }
354349cc55cSDimitry Andric 
3550b57cec5SDimitry Andric     for (const Instruction &I : BB) {
356349cc55cSDimitry Andric       if (I.isDebugOrPseudoInst())
3570b57cec5SDimitry Andric         continue;
3580b57cec5SDimitry Andric       ++NumInsts;
359349cc55cSDimitry Andric 
3600b57cec5SDimitry Andric       // Regular LTO module doesn't participate in ThinLTO import,
3610b57cec5SDimitry Andric       // so no reference from it can be read/writeonly, since this
3620b57cec5SDimitry Andric       // would require importing variable as local copy
3630b57cec5SDimitry Andric       if (IsThinLTO) {
3640b57cec5SDimitry Andric         if (isNonVolatileLoad(&I)) {
3650b57cec5SDimitry Andric           // Postpone processing of non-volatile load instructions
3660b57cec5SDimitry Andric           // See comments below
3670b57cec5SDimitry Andric           Visited.insert(&I);
3680b57cec5SDimitry Andric           NonVolatileLoads.push_back(&I);
3690b57cec5SDimitry Andric           continue;
3700b57cec5SDimitry Andric         } else if (isNonVolatileStore(&I)) {
3710b57cec5SDimitry Andric           Visited.insert(&I);
3720b57cec5SDimitry Andric           NonVolatileStores.push_back(&I);
3730b57cec5SDimitry Andric           // All references from second operand of store (destination address)
3740b57cec5SDimitry Andric           // can be considered write-only if they're not referenced by any
3750b57cec5SDimitry Andric           // non-store instruction. References from first operand of store
3760b57cec5SDimitry Andric           // (stored value) can't be treated either as read- or as write-only
3770b57cec5SDimitry Andric           // so we add them to RefEdges as we do with all other instructions
3780b57cec5SDimitry Andric           // except non-volatile load.
3790b57cec5SDimitry Andric           Value *Stored = I.getOperand(0);
3800b57cec5SDimitry Andric           if (auto *GV = dyn_cast<GlobalValue>(Stored))
3810b57cec5SDimitry Andric             // findRefEdges will try to examine GV operands, so instead
3820b57cec5SDimitry Andric             // of calling it we should add GV to RefEdges directly.
3830b57cec5SDimitry Andric             RefEdges.insert(Index.getOrInsertValueInfo(GV));
3840b57cec5SDimitry Andric           else if (auto *U = dyn_cast<User>(Stored))
385*0fca6ea1SDimitry Andric             findRefEdges(Index, U, RefEdges, Visited, HasLocalIFuncCallOrRef);
3860b57cec5SDimitry Andric           continue;
3870b57cec5SDimitry Andric         }
3880b57cec5SDimitry Andric       }
389*0fca6ea1SDimitry Andric       findRefEdges(Index, &I, RefEdges, Visited, HasLocalIFuncCallOrRef);
3905ffd83dbSDimitry Andric       const auto *CB = dyn_cast<CallBase>(&I);
391349cc55cSDimitry Andric       if (!CB) {
392349cc55cSDimitry Andric         if (I.mayThrow())
393349cc55cSDimitry Andric           MayThrow = true;
3940b57cec5SDimitry Andric         continue;
395349cc55cSDimitry Andric       }
3960b57cec5SDimitry Andric 
3970b57cec5SDimitry Andric       const auto *CI = dyn_cast<CallInst>(&I);
3980b57cec5SDimitry Andric       // Since we don't know exactly which local values are referenced in inline
3990b57cec5SDimitry Andric       // assembly, conservatively mark the function as possibly referencing
4000b57cec5SDimitry Andric       // a local value from inline assembly to ensure we don't export a
4010b57cec5SDimitry Andric       // reference (which would require renaming and promotion of the
4020b57cec5SDimitry Andric       // referenced value).
4030b57cec5SDimitry Andric       if (HasLocalsInUsedOrAsm && CI && CI->isInlineAsm())
4040b57cec5SDimitry Andric         HasInlineAsmMaybeReferencingInternal = true;
4050b57cec5SDimitry Andric 
4065ffd83dbSDimitry Andric       auto *CalledValue = CB->getCalledOperand();
4075ffd83dbSDimitry Andric       auto *CalledFunction = CB->getCalledFunction();
4080b57cec5SDimitry Andric       if (CalledValue && !CalledFunction) {
4098bcb0991SDimitry Andric         CalledValue = CalledValue->stripPointerCasts();
4100b57cec5SDimitry Andric         // Stripping pointer casts can reveal a called function.
4110b57cec5SDimitry Andric         CalledFunction = dyn_cast<Function>(CalledValue);
4120b57cec5SDimitry Andric       }
4130b57cec5SDimitry Andric       // Check if this is an alias to a function. If so, get the
4140b57cec5SDimitry Andric       // called aliasee for the checks below.
4150b57cec5SDimitry Andric       if (auto *GA = dyn_cast<GlobalAlias>(CalledValue)) {
4160b57cec5SDimitry Andric         assert(!CalledFunction && "Expected null called function in callsite for alias");
417349cc55cSDimitry Andric         CalledFunction = dyn_cast<Function>(GA->getAliaseeObject());
4180b57cec5SDimitry Andric       }
4190b57cec5SDimitry Andric       // Check if this is a direct call to a known function or a known
4200b57cec5SDimitry Andric       // intrinsic, or an indirect call with profile data.
4210b57cec5SDimitry Andric       if (CalledFunction) {
4220b57cec5SDimitry Andric         if (CI && CalledFunction->isIntrinsic()) {
4230b57cec5SDimitry Andric           addIntrinsicToSummary(
4240b57cec5SDimitry Andric               CI, TypeTests, TypeTestAssumeVCalls, TypeCheckedLoadVCalls,
4250b57cec5SDimitry Andric               TypeTestAssumeConstVCalls, TypeCheckedLoadConstVCalls, DT);
4260b57cec5SDimitry Andric           continue;
4270b57cec5SDimitry Andric         }
4280b57cec5SDimitry Andric         // We should have named any anonymous globals
4290b57cec5SDimitry Andric         assert(CalledFunction->hasName());
4305ffd83dbSDimitry Andric         auto ScaledCount = PSI->getProfileCount(*CB, BFI);
43181ad6265SDimitry Andric         auto Hotness = ScaledCount ? getHotness(*ScaledCount, PSI)
4320b57cec5SDimitry Andric                                    : CalleeInfo::HotnessType::Unknown;
4330b57cec5SDimitry Andric         if (ForceSummaryEdgesCold != FunctionSummary::FSHT_None)
4340b57cec5SDimitry Andric           Hotness = CalleeInfo::HotnessType::Cold;
4350b57cec5SDimitry Andric 
4360b57cec5SDimitry Andric         // Use the original CalledValue, in case it was an alias. We want
4370b57cec5SDimitry Andric         // to record the call edge to the alias in that case. Eventually
4380b57cec5SDimitry Andric         // an alias summary will be created to associate the alias and
4390b57cec5SDimitry Andric         // aliasee.
4400b57cec5SDimitry Andric         auto &ValueInfo = CallGraphEdges[Index.getOrInsertValueInfo(
4410b57cec5SDimitry Andric             cast<GlobalValue>(CalledValue))];
4420b57cec5SDimitry Andric         ValueInfo.updateHotness(Hotness);
4435f757f3fSDimitry Andric         if (CB->isTailCall())
4445f757f3fSDimitry Andric           ValueInfo.setHasTailCall(true);
4450b57cec5SDimitry Andric         // Add the relative block frequency to CalleeInfo if there is no profile
4460b57cec5SDimitry Andric         // information.
4470b57cec5SDimitry Andric         if (BFI != nullptr && Hotness == CalleeInfo::HotnessType::Unknown) {
4480b57cec5SDimitry Andric           uint64_t BBFreq = BFI->getBlockFreq(&BB).getFrequency();
4495f757f3fSDimitry Andric           uint64_t EntryFreq = BFI->getEntryFreq().getFrequency();
4500b57cec5SDimitry Andric           ValueInfo.updateRelBlockFreq(BBFreq, EntryFreq);
4510b57cec5SDimitry Andric         }
4520b57cec5SDimitry Andric       } else {
453349cc55cSDimitry Andric         HasUnknownCall = true;
4545f757f3fSDimitry Andric         // If F is imported, a local linkage ifunc (e.g. target_clones on a
4555f757f3fSDimitry Andric         // static function) called by F will be cloned. Since summaries don't
4565f757f3fSDimitry Andric         // track ifunc, we do not know implementation functions referenced by
4575f757f3fSDimitry Andric         // the ifunc resolver need to be promoted in the exporter, and we will
4585f757f3fSDimitry Andric         // get linker errors due to cloned declarations for implementation
4595f757f3fSDimitry Andric         // functions. As a simple fix, just mark F as not eligible for import.
4605f757f3fSDimitry Andric         // Non-local ifunc is not cloned and does not have the issue.
4615f757f3fSDimitry Andric         if (auto *GI = dyn_cast_if_present<GlobalIFunc>(CalledValue))
4625f757f3fSDimitry Andric           if (GI->hasLocalLinkage())
463*0fca6ea1SDimitry Andric             HasLocalIFuncCallOrRef = true;
4640b57cec5SDimitry Andric         // Skip inline assembly calls.
4650b57cec5SDimitry Andric         if (CI && CI->isInlineAsm())
4660b57cec5SDimitry Andric           continue;
4670b57cec5SDimitry Andric         // Skip direct calls.
4680b57cec5SDimitry Andric         if (!CalledValue || isa<Constant>(CalledValue))
4690b57cec5SDimitry Andric           continue;
4700b57cec5SDimitry Andric 
4710b57cec5SDimitry Andric         // Check if the instruction has a callees metadata. If so, add callees
4720b57cec5SDimitry Andric         // to CallGraphEdges to reflect the references from the metadata, and
4730b57cec5SDimitry Andric         // to enable importing for subsequent indirect call promotion and
4740b57cec5SDimitry Andric         // inlining.
4750b57cec5SDimitry Andric         if (auto *MD = I.getMetadata(LLVMContext::MD_callees)) {
476fcaf7f86SDimitry Andric           for (const auto &Op : MD->operands()) {
4770b57cec5SDimitry Andric             Function *Callee = mdconst::extract_or_null<Function>(Op);
4780b57cec5SDimitry Andric             if (Callee)
4790b57cec5SDimitry Andric               CallGraphEdges[Index.getOrInsertValueInfo(Callee)];
4800b57cec5SDimitry Andric           }
4810b57cec5SDimitry Andric         }
4820b57cec5SDimitry Andric 
483*0fca6ea1SDimitry Andric         uint32_t NumCandidates;
4840b57cec5SDimitry Andric         uint64_t TotalCount;
4850b57cec5SDimitry Andric         auto CandidateProfileData =
486*0fca6ea1SDimitry Andric             ICallAnalysis.getPromotionCandidatesForInstruction(&I, TotalCount,
487*0fca6ea1SDimitry Andric                                                                NumCandidates);
488fcaf7f86SDimitry Andric         for (const auto &Candidate : CandidateProfileData)
4890b57cec5SDimitry Andric           CallGraphEdges[Index.getOrInsertValueInfo(Candidate.Value)]
4900b57cec5SDimitry Andric               .updateHotness(getHotness(Candidate.Count, PSI));
4910b57cec5SDimitry Andric       }
492bdd1243dSDimitry Andric 
49306c3fb27SDimitry Andric       // Summarize memprof related metadata. This is only needed for ThinLTO.
49406c3fb27SDimitry Andric       if (!IsThinLTO)
49506c3fb27SDimitry Andric         continue;
49606c3fb27SDimitry Andric 
497bdd1243dSDimitry Andric       // TODO: Skip indirect calls for now. Need to handle these better, likely
498bdd1243dSDimitry Andric       // by creating multiple Callsites, one per target, then speculatively
499bdd1243dSDimitry Andric       // devirtualize while applying clone info in the ThinLTO backends. This
500bdd1243dSDimitry Andric       // will also be important because we will have a different set of clone
501bdd1243dSDimitry Andric       // versions per target. This handling needs to match that in the ThinLTO
502bdd1243dSDimitry Andric       // backend so we handle things consistently for matching of callsite
503bdd1243dSDimitry Andric       // summaries to instructions.
504bdd1243dSDimitry Andric       if (!CalledFunction)
505bdd1243dSDimitry Andric         continue;
506bdd1243dSDimitry Andric 
50706c3fb27SDimitry Andric       // Ensure we keep this analysis in sync with the handling in the ThinLTO
50806c3fb27SDimitry Andric       // backend (see MemProfContextDisambiguation::applyImport). Save this call
50906c3fb27SDimitry Andric       // so that we can skip it in checking the reverse case later.
51006c3fb27SDimitry Andric       assert(mayHaveMemprofSummary(CB));
51106c3fb27SDimitry Andric #ifndef NDEBUG
51206c3fb27SDimitry Andric       CallsThatMayHaveMemprofSummary.insert(CB);
51306c3fb27SDimitry Andric #endif
51406c3fb27SDimitry Andric 
515bdd1243dSDimitry Andric       // Compute the list of stack ids first (so we can trim them from the stack
516bdd1243dSDimitry Andric       // ids on any MIBs).
517bdd1243dSDimitry Andric       CallStack<MDNode, MDNode::op_iterator> InstCallsite(
518bdd1243dSDimitry Andric           I.getMetadata(LLVMContext::MD_callsite));
519bdd1243dSDimitry Andric       auto *MemProfMD = I.getMetadata(LLVMContext::MD_memprof);
520bdd1243dSDimitry Andric       if (MemProfMD) {
521bdd1243dSDimitry Andric         std::vector<MIBInfo> MIBs;
522*0fca6ea1SDimitry Andric         std::vector<uint64_t> TotalSizes;
523bdd1243dSDimitry Andric         for (auto &MDOp : MemProfMD->operands()) {
524bdd1243dSDimitry Andric           auto *MIBMD = cast<const MDNode>(MDOp);
525bdd1243dSDimitry Andric           MDNode *StackNode = getMIBStackNode(MIBMD);
526bdd1243dSDimitry Andric           assert(StackNode);
527bdd1243dSDimitry Andric           SmallVector<unsigned> StackIdIndices;
528bdd1243dSDimitry Andric           CallStack<MDNode, MDNode::op_iterator> StackContext(StackNode);
529bdd1243dSDimitry Andric           // Collapse out any on the allocation call (inlining).
530bdd1243dSDimitry Andric           for (auto ContextIter =
531bdd1243dSDimitry Andric                    StackContext.beginAfterSharedPrefix(InstCallsite);
532bdd1243dSDimitry Andric                ContextIter != StackContext.end(); ++ContextIter) {
533bdd1243dSDimitry Andric             unsigned StackIdIdx = Index.addOrGetStackIdIndex(*ContextIter);
534bdd1243dSDimitry Andric             // If this is a direct recursion, simply skip the duplicate
535bdd1243dSDimitry Andric             // entries. If this is mutual recursion, handling is left to
536bdd1243dSDimitry Andric             // the LTO link analysis client.
537bdd1243dSDimitry Andric             if (StackIdIndices.empty() || StackIdIndices.back() != StackIdIdx)
538bdd1243dSDimitry Andric               StackIdIndices.push_back(StackIdIdx);
539bdd1243dSDimitry Andric           }
540bdd1243dSDimitry Andric           MIBs.push_back(
541bdd1243dSDimitry Andric               MIBInfo(getMIBAllocType(MIBMD), std::move(StackIdIndices)));
542*0fca6ea1SDimitry Andric           if (MemProfReportHintedSizes) {
543*0fca6ea1SDimitry Andric             auto TotalSize = getMIBTotalSize(MIBMD);
544*0fca6ea1SDimitry Andric             assert(TotalSize);
545*0fca6ea1SDimitry Andric             TotalSizes.push_back(TotalSize);
546*0fca6ea1SDimitry Andric           }
547bdd1243dSDimitry Andric         }
548bdd1243dSDimitry Andric         Allocs.push_back(AllocInfo(std::move(MIBs)));
549*0fca6ea1SDimitry Andric         if (MemProfReportHintedSizes) {
550*0fca6ea1SDimitry Andric           assert(Allocs.back().MIBs.size() == TotalSizes.size());
551*0fca6ea1SDimitry Andric           Allocs.back().TotalSizes = std::move(TotalSizes);
552*0fca6ea1SDimitry Andric         }
553bdd1243dSDimitry Andric       } else if (!InstCallsite.empty()) {
554bdd1243dSDimitry Andric         SmallVector<unsigned> StackIdIndices;
555bdd1243dSDimitry Andric         for (auto StackId : InstCallsite)
556bdd1243dSDimitry Andric           StackIdIndices.push_back(Index.addOrGetStackIdIndex(StackId));
557bdd1243dSDimitry Andric         // Use the original CalledValue, in case it was an alias. We want
558bdd1243dSDimitry Andric         // to record the call edge to the alias in that case. Eventually
559bdd1243dSDimitry Andric         // an alias summary will be created to associate the alias and
560bdd1243dSDimitry Andric         // aliasee.
561bdd1243dSDimitry Andric         auto CalleeValueInfo =
562bdd1243dSDimitry Andric             Index.getOrInsertValueInfo(cast<GlobalValue>(CalledValue));
563bdd1243dSDimitry Andric         Callsites.push_back({CalleeValueInfo, StackIdIndices});
564bdd1243dSDimitry Andric       }
5650b57cec5SDimitry Andric     }
566349cc55cSDimitry Andric   }
56706c3fb27SDimitry Andric 
56806c3fb27SDimitry Andric   if (PSI->hasPartialSampleProfile() && ScalePartialSampleProfileWorkingSetSize)
5695ffd83dbSDimitry Andric     Index.addBlockCount(F.size());
5700b57cec5SDimitry Andric 
5710b57cec5SDimitry Andric   std::vector<ValueInfo> Refs;
5720b57cec5SDimitry Andric   if (IsThinLTO) {
5730b57cec5SDimitry Andric     auto AddRefEdges = [&](const std::vector<const Instruction *> &Instrs,
5745f757f3fSDimitry Andric                            SetVector<ValueInfo, std::vector<ValueInfo>> &Edges,
5750b57cec5SDimitry Andric                            SmallPtrSet<const User *, 8> &Cache) {
5760b57cec5SDimitry Andric       for (const auto *I : Instrs) {
5770b57cec5SDimitry Andric         Cache.erase(I);
578*0fca6ea1SDimitry Andric         findRefEdges(Index, I, Edges, Cache, HasLocalIFuncCallOrRef);
5790b57cec5SDimitry Andric       }
5800b57cec5SDimitry Andric     };
5810b57cec5SDimitry Andric 
5820b57cec5SDimitry Andric     // By now we processed all instructions in a function, except
5830b57cec5SDimitry Andric     // non-volatile loads and non-volatile value stores. Let's find
5840b57cec5SDimitry Andric     // ref edges for both of instruction sets
5850b57cec5SDimitry Andric     AddRefEdges(NonVolatileLoads, LoadRefEdges, Visited);
5860b57cec5SDimitry Andric     // We can add some values to the Visited set when processing load
5870b57cec5SDimitry Andric     // instructions which are also used by stores in NonVolatileStores.
5880b57cec5SDimitry Andric     // For example this can happen if we have following code:
5890b57cec5SDimitry Andric     //
5900b57cec5SDimitry Andric     // store %Derived* @foo, %Derived** bitcast (%Base** @bar to %Derived**)
5910b57cec5SDimitry Andric     // %42 = load %Derived*, %Derived** bitcast (%Base** @bar to %Derived**)
5920b57cec5SDimitry Andric     //
5930b57cec5SDimitry Andric     // After processing loads we'll add bitcast to the Visited set, and if
5940b57cec5SDimitry Andric     // we use the same set while processing stores, we'll never see store
5950b57cec5SDimitry Andric     // to @bar and @bar will be mistakenly treated as readonly.
5960b57cec5SDimitry Andric     SmallPtrSet<const llvm::User *, 8> StoreCache;
5970b57cec5SDimitry Andric     AddRefEdges(NonVolatileStores, StoreRefEdges, StoreCache);
5980b57cec5SDimitry Andric 
5990b57cec5SDimitry Andric     // If both load and store instruction reference the same variable
6000b57cec5SDimitry Andric     // we won't be able to optimize it. Add all such reference edges
6010b57cec5SDimitry Andric     // to RefEdges set.
602fcaf7f86SDimitry Andric     for (const auto &VI : StoreRefEdges)
6030b57cec5SDimitry Andric       if (LoadRefEdges.remove(VI))
6040b57cec5SDimitry Andric         RefEdges.insert(VI);
6050b57cec5SDimitry Andric 
6060b57cec5SDimitry Andric     unsigned RefCnt = RefEdges.size();
6070b57cec5SDimitry Andric     // All new reference edges inserted in two loops below are either
6080b57cec5SDimitry Andric     // read or write only. They will be grouped in the end of RefEdges
6090b57cec5SDimitry Andric     // vector, so we can use a single integer value to identify them.
610fcaf7f86SDimitry Andric     for (const auto &VI : LoadRefEdges)
6110b57cec5SDimitry Andric       RefEdges.insert(VI);
6120b57cec5SDimitry Andric 
6130b57cec5SDimitry Andric     unsigned FirstWORef = RefEdges.size();
614fcaf7f86SDimitry Andric     for (const auto &VI : StoreRefEdges)
6150b57cec5SDimitry Andric       RefEdges.insert(VI);
6160b57cec5SDimitry Andric 
6170b57cec5SDimitry Andric     Refs = RefEdges.takeVector();
6180b57cec5SDimitry Andric     for (; RefCnt < FirstWORef; ++RefCnt)
6190b57cec5SDimitry Andric       Refs[RefCnt].setReadOnly();
6200b57cec5SDimitry Andric 
6210b57cec5SDimitry Andric     for (; RefCnt < Refs.size(); ++RefCnt)
6220b57cec5SDimitry Andric       Refs[RefCnt].setWriteOnly();
6230b57cec5SDimitry Andric   } else {
6240b57cec5SDimitry Andric     Refs = RefEdges.takeVector();
6250b57cec5SDimitry Andric   }
6260b57cec5SDimitry Andric   // Explicit add hot edges to enforce importing for designated GUIDs for
6270b57cec5SDimitry Andric   // sample PGO, to enable the same inlines as the profiled optimized binary.
6280b57cec5SDimitry Andric   for (auto &I : F.getImportGUIDs())
6290b57cec5SDimitry Andric     CallGraphEdges[Index.getOrInsertValueInfo(I)].updateHotness(
6300b57cec5SDimitry Andric         ForceSummaryEdgesCold == FunctionSummary::FSHT_All
6310b57cec5SDimitry Andric             ? CalleeInfo::HotnessType::Cold
6320b57cec5SDimitry Andric             : CalleeInfo::HotnessType::Critical);
6330b57cec5SDimitry Andric 
63406c3fb27SDimitry Andric #ifndef NDEBUG
63506c3fb27SDimitry Andric   // Make sure that all calls we decided could not have memprof summaries get a
63606c3fb27SDimitry Andric   // false value for mayHaveMemprofSummary, to ensure that this handling remains
63706c3fb27SDimitry Andric   // in sync with the ThinLTO backend handling.
63806c3fb27SDimitry Andric   if (IsThinLTO) {
63906c3fb27SDimitry Andric     for (const BasicBlock &BB : F) {
64006c3fb27SDimitry Andric       for (const Instruction &I : BB) {
64106c3fb27SDimitry Andric         const auto *CB = dyn_cast<CallBase>(&I);
64206c3fb27SDimitry Andric         if (!CB)
64306c3fb27SDimitry Andric           continue;
64406c3fb27SDimitry Andric         // We already checked these above.
64506c3fb27SDimitry Andric         if (CallsThatMayHaveMemprofSummary.count(CB))
64606c3fb27SDimitry Andric           continue;
64706c3fb27SDimitry Andric         assert(!mayHaveMemprofSummary(CB));
64806c3fb27SDimitry Andric       }
64906c3fb27SDimitry Andric     }
65006c3fb27SDimitry Andric   }
65106c3fb27SDimitry Andric #endif
65206c3fb27SDimitry Andric 
6530b57cec5SDimitry Andric   bool NonRenamableLocal = isNonRenamableLocal(F);
654*0fca6ea1SDimitry Andric   bool NotEligibleForImport =
655*0fca6ea1SDimitry Andric       NonRenamableLocal || HasInlineAsmMaybeReferencingInternal ||
656*0fca6ea1SDimitry Andric       HasIndirBranchToBlockAddress || HasLocalIFuncCallOrRef;
657fe6060f1SDimitry Andric   GlobalValueSummary::GVFlags Flags(
658fe6060f1SDimitry Andric       F.getLinkage(), F.getVisibility(), NotEligibleForImport,
659*0fca6ea1SDimitry Andric       /* Live = */ false, F.isDSOLocal(), F.canBeOmittedFromSymbolTable(),
660*0fca6ea1SDimitry Andric       GlobalValueSummary::ImportKind::Definition);
6610b57cec5SDimitry Andric   FunctionSummary::FFlags FunFlags{
662bdd1243dSDimitry Andric       F.doesNotAccessMemory(), F.onlyReadsMemory() && !F.doesNotAccessMemory(),
6630b57cec5SDimitry Andric       F.hasFnAttribute(Attribute::NoRecurse), F.returnDoesNotAlias(),
6640b57cec5SDimitry Andric       // FIXME: refactor this to use the same code that inliner is using.
6650b57cec5SDimitry Andric       // Don't try to import functions with noinline attribute.
666349cc55cSDimitry Andric       F.getAttributes().hasFnAttr(Attribute::NoInline),
667349cc55cSDimitry Andric       F.hasFnAttribute(Attribute::AlwaysInline),
6680eae32dcSDimitry Andric       F.hasFnAttribute(Attribute::NoUnwind), MayThrow, HasUnknownCall,
6690eae32dcSDimitry Andric       mustBeUnreachableFunction(F)};
6705ffd83dbSDimitry Andric   std::vector<FunctionSummary::ParamAccess> ParamAccesses;
6715ffd83dbSDimitry Andric   if (auto *SSI = GetSSICallback(F))
672e8d8bef9SDimitry Andric     ParamAccesses = SSI->getParamAccesses(Index);
6738bcb0991SDimitry Andric   auto FuncSummary = std::make_unique<FunctionSummary>(
6740b57cec5SDimitry Andric       Flags, NumInsts, FunFlags, /*EntryCount=*/0, std::move(Refs),
6750b57cec5SDimitry Andric       CallGraphEdges.takeVector(), TypeTests.takeVector(),
6760b57cec5SDimitry Andric       TypeTestAssumeVCalls.takeVector(), TypeCheckedLoadVCalls.takeVector(),
6770b57cec5SDimitry Andric       TypeTestAssumeConstVCalls.takeVector(),
678bdd1243dSDimitry Andric       TypeCheckedLoadConstVCalls.takeVector(), std::move(ParamAccesses),
679bdd1243dSDimitry Andric       std::move(Callsites), std::move(Allocs));
6800b57cec5SDimitry Andric   if (NonRenamableLocal)
6810b57cec5SDimitry Andric     CantBePromoted.insert(F.getGUID());
6820b57cec5SDimitry Andric   Index.addGlobalValueSummary(F, std::move(FuncSummary));
6830b57cec5SDimitry Andric }
6840b57cec5SDimitry Andric 
6850b57cec5SDimitry Andric /// Find function pointers referenced within the given vtable initializer
6860b57cec5SDimitry Andric /// (or subset of an initializer) \p I. The starting offset of \p I within
6870b57cec5SDimitry Andric /// the vtable initializer is \p StartingOffset. Any discovered function
6880b57cec5SDimitry Andric /// pointers are added to \p VTableFuncs along with their cumulative offset
6890b57cec5SDimitry Andric /// within the initializer.
6900b57cec5SDimitry Andric static void findFuncPointers(const Constant *I, uint64_t StartingOffset,
6910b57cec5SDimitry Andric                              const Module &M, ModuleSummaryIndex &Index,
692*0fca6ea1SDimitry Andric                              VTableFuncList &VTableFuncs,
693*0fca6ea1SDimitry Andric                              const GlobalVariable &OrigGV) {
6940b57cec5SDimitry Andric   // First check if this is a function pointer.
6950b57cec5SDimitry Andric   if (I->getType()->isPointerTy()) {
69606c3fb27SDimitry Andric     auto C = I->stripPointerCasts();
69706c3fb27SDimitry Andric     auto A = dyn_cast<GlobalAlias>(C);
69806c3fb27SDimitry Andric     if (isa<Function>(C) || (A && isa<Function>(A->getAliasee()))) {
69906c3fb27SDimitry Andric       auto GV = dyn_cast<GlobalValue>(C);
70006c3fb27SDimitry Andric       assert(GV);
7010b57cec5SDimitry Andric       // We can disregard __cxa_pure_virtual as a possible call target, as
7020b57cec5SDimitry Andric       // calls to pure virtuals are UB.
70306c3fb27SDimitry Andric       if (GV && GV->getName() != "__cxa_pure_virtual")
70406c3fb27SDimitry Andric         VTableFuncs.push_back({Index.getOrInsertValueInfo(GV), StartingOffset});
7050b57cec5SDimitry Andric       return;
7060b57cec5SDimitry Andric     }
70706c3fb27SDimitry Andric   }
7080b57cec5SDimitry Andric 
7090b57cec5SDimitry Andric   // Walk through the elements in the constant struct or array and recursively
7100b57cec5SDimitry Andric   // look for virtual function pointers.
7110b57cec5SDimitry Andric   const DataLayout &DL = M.getDataLayout();
7120b57cec5SDimitry Andric   if (auto *C = dyn_cast<ConstantStruct>(I)) {
7130b57cec5SDimitry Andric     StructType *STy = dyn_cast<StructType>(C->getType());
7140b57cec5SDimitry Andric     assert(STy);
7150b57cec5SDimitry Andric     const StructLayout *SL = DL.getStructLayout(C->getType());
7160b57cec5SDimitry Andric 
717fe6060f1SDimitry Andric     for (auto EI : llvm::enumerate(STy->elements())) {
718fe6060f1SDimitry Andric       auto Offset = SL->getElementOffset(EI.index());
7190b57cec5SDimitry Andric       unsigned Op = SL->getElementContainingOffset(Offset);
7200b57cec5SDimitry Andric       findFuncPointers(cast<Constant>(I->getOperand(Op)),
721*0fca6ea1SDimitry Andric                        StartingOffset + Offset, M, Index, VTableFuncs, OrigGV);
7220b57cec5SDimitry Andric     }
7230b57cec5SDimitry Andric   } else if (auto *C = dyn_cast<ConstantArray>(I)) {
7240b57cec5SDimitry Andric     ArrayType *ATy = C->getType();
7250b57cec5SDimitry Andric     Type *EltTy = ATy->getElementType();
7260b57cec5SDimitry Andric     uint64_t EltSize = DL.getTypeAllocSize(EltTy);
7270b57cec5SDimitry Andric     for (unsigned i = 0, e = ATy->getNumElements(); i != e; ++i) {
7280b57cec5SDimitry Andric       findFuncPointers(cast<Constant>(I->getOperand(i)),
729*0fca6ea1SDimitry Andric                        StartingOffset + i * EltSize, M, Index, VTableFuncs,
730*0fca6ea1SDimitry Andric                        OrigGV);
731*0fca6ea1SDimitry Andric     }
732*0fca6ea1SDimitry Andric   } else if (const auto *CE = dyn_cast<ConstantExpr>(I)) {
733*0fca6ea1SDimitry Andric     // For relative vtables, the next sub-component should be a trunc.
734*0fca6ea1SDimitry Andric     if (CE->getOpcode() != Instruction::Trunc ||
735*0fca6ea1SDimitry Andric         !(CE = dyn_cast<ConstantExpr>(CE->getOperand(0))))
736*0fca6ea1SDimitry Andric       return;
737*0fca6ea1SDimitry Andric 
738*0fca6ea1SDimitry Andric     // If this constant can be reduced to the offset between a function and a
739*0fca6ea1SDimitry Andric     // global, then we know this is a valid virtual function if the RHS is the
740*0fca6ea1SDimitry Andric     // original vtable we're scanning through.
741*0fca6ea1SDimitry Andric     if (CE->getOpcode() == Instruction::Sub) {
742*0fca6ea1SDimitry Andric       GlobalValue *LHS, *RHS;
743*0fca6ea1SDimitry Andric       APSInt LHSOffset, RHSOffset;
744*0fca6ea1SDimitry Andric       if (IsConstantOffsetFromGlobal(CE->getOperand(0), LHS, LHSOffset, DL) &&
745*0fca6ea1SDimitry Andric           IsConstantOffsetFromGlobal(CE->getOperand(1), RHS, RHSOffset, DL) &&
746*0fca6ea1SDimitry Andric           RHS == &OrigGV &&
747*0fca6ea1SDimitry Andric 
748*0fca6ea1SDimitry Andric           // For relative vtables, this component should point to the callable
749*0fca6ea1SDimitry Andric           // function without any offsets.
750*0fca6ea1SDimitry Andric           LHSOffset == 0 &&
751*0fca6ea1SDimitry Andric 
752*0fca6ea1SDimitry Andric           // Also, the RHS should always point to somewhere within the vtable.
753*0fca6ea1SDimitry Andric           RHSOffset <=
754*0fca6ea1SDimitry Andric               static_cast<uint64_t>(DL.getTypeAllocSize(OrigGV.getInitializer()->getType()))) {
755*0fca6ea1SDimitry Andric         findFuncPointers(LHS, StartingOffset, M, Index, VTableFuncs, OrigGV);
756*0fca6ea1SDimitry Andric       }
7570b57cec5SDimitry Andric     }
7580b57cec5SDimitry Andric   }
7590b57cec5SDimitry Andric }
7600b57cec5SDimitry Andric 
7610b57cec5SDimitry Andric // Identify the function pointers referenced by vtable definition \p V.
7620b57cec5SDimitry Andric static void computeVTableFuncs(ModuleSummaryIndex &Index,
7630b57cec5SDimitry Andric                                const GlobalVariable &V, const Module &M,
7640b57cec5SDimitry Andric                                VTableFuncList &VTableFuncs) {
7650b57cec5SDimitry Andric   if (!V.isConstant())
7660b57cec5SDimitry Andric     return;
7670b57cec5SDimitry Andric 
7680b57cec5SDimitry Andric   findFuncPointers(V.getInitializer(), /*StartingOffset=*/0, M, Index,
769*0fca6ea1SDimitry Andric                    VTableFuncs, V);
7700b57cec5SDimitry Andric 
7710b57cec5SDimitry Andric #ifndef NDEBUG
7720b57cec5SDimitry Andric   // Validate that the VTableFuncs list is ordered by offset.
7730b57cec5SDimitry Andric   uint64_t PrevOffset = 0;
7740b57cec5SDimitry Andric   for (auto &P : VTableFuncs) {
7750b57cec5SDimitry Andric     // The findVFuncPointers traversal should have encountered the
7760b57cec5SDimitry Andric     // functions in offset order. We need to use ">=" since PrevOffset
7770b57cec5SDimitry Andric     // starts at 0.
7780b57cec5SDimitry Andric     assert(P.VTableOffset >= PrevOffset);
7790b57cec5SDimitry Andric     PrevOffset = P.VTableOffset;
7800b57cec5SDimitry Andric   }
7810b57cec5SDimitry Andric #endif
7820b57cec5SDimitry Andric }
7830b57cec5SDimitry Andric 
7840b57cec5SDimitry Andric /// Record vtable definition \p V for each type metadata it references.
7850b57cec5SDimitry Andric static void
7860b57cec5SDimitry Andric recordTypeIdCompatibleVtableReferences(ModuleSummaryIndex &Index,
7870b57cec5SDimitry Andric                                        const GlobalVariable &V,
7880b57cec5SDimitry Andric                                        SmallVectorImpl<MDNode *> &Types) {
7890b57cec5SDimitry Andric   for (MDNode *Type : Types) {
7900b57cec5SDimitry Andric     auto TypeID = Type->getOperand(1).get();
7910b57cec5SDimitry Andric 
7920b57cec5SDimitry Andric     uint64_t Offset =
7930b57cec5SDimitry Andric         cast<ConstantInt>(
7940b57cec5SDimitry Andric             cast<ConstantAsMetadata>(Type->getOperand(0))->getValue())
7950b57cec5SDimitry Andric             ->getZExtValue();
7960b57cec5SDimitry Andric 
7970b57cec5SDimitry Andric     if (auto *TypeId = dyn_cast<MDString>(TypeID))
7980b57cec5SDimitry Andric       Index.getOrInsertTypeIdCompatibleVtableSummary(TypeId->getString())
7990b57cec5SDimitry Andric           .push_back({Offset, Index.getOrInsertValueInfo(&V)});
8000b57cec5SDimitry Andric   }
8010b57cec5SDimitry Andric }
8020b57cec5SDimitry Andric 
8030b57cec5SDimitry Andric static void computeVariableSummary(ModuleSummaryIndex &Index,
8040b57cec5SDimitry Andric                                    const GlobalVariable &V,
8050b57cec5SDimitry Andric                                    DenseSet<GlobalValue::GUID> &CantBePromoted,
8060b57cec5SDimitry Andric                                    const Module &M,
8070b57cec5SDimitry Andric                                    SmallVectorImpl<MDNode *> &Types) {
8085f757f3fSDimitry Andric   SetVector<ValueInfo, std::vector<ValueInfo>> RefEdges;
8090b57cec5SDimitry Andric   SmallPtrSet<const User *, 8> Visited;
810*0fca6ea1SDimitry Andric   bool RefLocalIFunc = false;
811*0fca6ea1SDimitry Andric   bool HasBlockAddress =
812*0fca6ea1SDimitry Andric       findRefEdges(Index, &V, RefEdges, Visited, RefLocalIFunc);
813*0fca6ea1SDimitry Andric   const bool NotEligibleForImport = (HasBlockAddress || RefLocalIFunc);
8140b57cec5SDimitry Andric   bool NonRenamableLocal = isNonRenamableLocal(V);
815fe6060f1SDimitry Andric   GlobalValueSummary::GVFlags Flags(
816fe6060f1SDimitry Andric       V.getLinkage(), V.getVisibility(), NonRenamableLocal,
817*0fca6ea1SDimitry Andric       /* Live = */ false, V.isDSOLocal(), V.canBeOmittedFromSymbolTable(),
818*0fca6ea1SDimitry Andric       GlobalValueSummary::Definition);
8190b57cec5SDimitry Andric 
8200b57cec5SDimitry Andric   VTableFuncList VTableFuncs;
8210b57cec5SDimitry Andric   // If splitting is not enabled, then we compute the summary information
8220b57cec5SDimitry Andric   // necessary for index-based whole program devirtualization.
8230b57cec5SDimitry Andric   if (!Index.enableSplitLTOUnit()) {
8240b57cec5SDimitry Andric     Types.clear();
8250b57cec5SDimitry Andric     V.getMetadata(LLVMContext::MD_type, Types);
8260b57cec5SDimitry Andric     if (!Types.empty()) {
8270b57cec5SDimitry Andric       // Identify the function pointers referenced by this vtable definition.
8280b57cec5SDimitry Andric       computeVTableFuncs(Index, V, M, VTableFuncs);
8290b57cec5SDimitry Andric 
8300b57cec5SDimitry Andric       // Record this vtable definition for each type metadata it references.
8310b57cec5SDimitry Andric       recordTypeIdCompatibleVtableReferences(Index, V, Types);
8320b57cec5SDimitry Andric     }
8330b57cec5SDimitry Andric   }
8340b57cec5SDimitry Andric 
8350b57cec5SDimitry Andric   // Don't mark variables we won't be able to internalize as read/write-only.
8360b57cec5SDimitry Andric   bool CanBeInternalized =
8370b57cec5SDimitry Andric       !V.hasComdat() && !V.hasAppendingLinkage() && !V.isInterposable() &&
8380b57cec5SDimitry Andric       !V.hasAvailableExternallyLinkage() && !V.hasDLLExportStorageClass();
8395ffd83dbSDimitry Andric   bool Constant = V.isConstant();
8405ffd83dbSDimitry Andric   GlobalVarSummary::GVarFlags VarFlags(CanBeInternalized,
8415ffd83dbSDimitry Andric                                        Constant ? false : CanBeInternalized,
8425ffd83dbSDimitry Andric                                        Constant, V.getVCallVisibility());
8438bcb0991SDimitry Andric   auto GVarSummary = std::make_unique<GlobalVarSummary>(Flags, VarFlags,
8440b57cec5SDimitry Andric                                                          RefEdges.takeVector());
8450b57cec5SDimitry Andric   if (NonRenamableLocal)
8460b57cec5SDimitry Andric     CantBePromoted.insert(V.getGUID());
847*0fca6ea1SDimitry Andric   if (NotEligibleForImport)
8480b57cec5SDimitry Andric     GVarSummary->setNotEligibleToImport();
8490b57cec5SDimitry Andric   if (!VTableFuncs.empty())
8500b57cec5SDimitry Andric     GVarSummary->setVTableFuncs(VTableFuncs);
8510b57cec5SDimitry Andric   Index.addGlobalValueSummary(V, std::move(GVarSummary));
8520b57cec5SDimitry Andric }
8530b57cec5SDimitry Andric 
854fcaf7f86SDimitry Andric static void computeAliasSummary(ModuleSummaryIndex &Index, const GlobalAlias &A,
8550b57cec5SDimitry Andric                                 DenseSet<GlobalValue::GUID> &CantBePromoted) {
856fcaf7f86SDimitry Andric   // Skip summary for indirect function aliases as summary for aliasee will not
857fcaf7f86SDimitry Andric   // be emitted.
858fcaf7f86SDimitry Andric   const GlobalObject *Aliasee = A.getAliaseeObject();
859fcaf7f86SDimitry Andric   if (isa<GlobalIFunc>(Aliasee))
860fcaf7f86SDimitry Andric     return;
8610b57cec5SDimitry Andric   bool NonRenamableLocal = isNonRenamableLocal(A);
862fe6060f1SDimitry Andric   GlobalValueSummary::GVFlags Flags(
863fe6060f1SDimitry Andric       A.getLinkage(), A.getVisibility(), NonRenamableLocal,
864*0fca6ea1SDimitry Andric       /* Live = */ false, A.isDSOLocal(), A.canBeOmittedFromSymbolTable(),
865*0fca6ea1SDimitry Andric       GlobalValueSummary::Definition);
8668bcb0991SDimitry Andric   auto AS = std::make_unique<AliasSummary>(Flags);
8670b57cec5SDimitry Andric   auto AliaseeVI = Index.getValueInfo(Aliasee->getGUID());
8680b57cec5SDimitry Andric   assert(AliaseeVI && "Alias expects aliasee summary to be available");
8690b57cec5SDimitry Andric   assert(AliaseeVI.getSummaryList().size() == 1 &&
8700b57cec5SDimitry Andric          "Expected a single entry per aliasee in per-module index");
8710b57cec5SDimitry Andric   AS->setAliasee(AliaseeVI, AliaseeVI.getSummaryList()[0].get());
8720b57cec5SDimitry Andric   if (NonRenamableLocal)
8730b57cec5SDimitry Andric     CantBePromoted.insert(A.getGUID());
8740b57cec5SDimitry Andric   Index.addGlobalValueSummary(A, std::move(AS));
8750b57cec5SDimitry Andric }
8760b57cec5SDimitry Andric 
8770b57cec5SDimitry Andric // Set LiveRoot flag on entries matching the given value name.
8780b57cec5SDimitry Andric static void setLiveRoot(ModuleSummaryIndex &Index, StringRef Name) {
8790b57cec5SDimitry Andric   if (ValueInfo VI = Index.getValueInfo(GlobalValue::getGUID(Name)))
880fcaf7f86SDimitry Andric     for (const auto &Summary : VI.getSummaryList())
8810b57cec5SDimitry Andric       Summary->setLive(true);
8820b57cec5SDimitry Andric }
8830b57cec5SDimitry Andric 
8840b57cec5SDimitry Andric ModuleSummaryIndex llvm::buildModuleSummaryIndex(
8850b57cec5SDimitry Andric     const Module &M,
8860b57cec5SDimitry Andric     std::function<BlockFrequencyInfo *(const Function &F)> GetBFICallback,
8875ffd83dbSDimitry Andric     ProfileSummaryInfo *PSI,
8885ffd83dbSDimitry Andric     std::function<const StackSafetyInfo *(const Function &F)> GetSSICallback) {
8890b57cec5SDimitry Andric   assert(PSI);
8900b57cec5SDimitry Andric   bool EnableSplitLTOUnit = false;
89106c3fb27SDimitry Andric   bool UnifiedLTO = false;
8920b57cec5SDimitry Andric   if (auto *MD = mdconst::extract_or_null<ConstantInt>(
8930b57cec5SDimitry Andric           M.getModuleFlag("EnableSplitLTOUnit")))
8940b57cec5SDimitry Andric     EnableSplitLTOUnit = MD->getZExtValue();
89506c3fb27SDimitry Andric   if (auto *MD =
89606c3fb27SDimitry Andric           mdconst::extract_or_null<ConstantInt>(M.getModuleFlag("UnifiedLTO")))
89706c3fb27SDimitry Andric     UnifiedLTO = MD->getZExtValue();
89806c3fb27SDimitry Andric   ModuleSummaryIndex Index(/*HaveGVs=*/true, EnableSplitLTOUnit, UnifiedLTO);
8990b57cec5SDimitry Andric 
9000b57cec5SDimitry Andric   // Identify the local values in the llvm.used and llvm.compiler.used sets,
9010b57cec5SDimitry Andric   // which should not be exported as they would then require renaming and
9020b57cec5SDimitry Andric   // promotion, but we may have opaque uses e.g. in inline asm. We collect them
9030b57cec5SDimitry Andric   // here because we use this information to mark functions containing inline
9040b57cec5SDimitry Andric   // assembly calls as not importable.
905fe6060f1SDimitry Andric   SmallPtrSet<GlobalValue *, 4> LocalsUsed;
906fe6060f1SDimitry Andric   SmallVector<GlobalValue *, 4> Used;
9070b57cec5SDimitry Andric   // First collect those in the llvm.used set.
908fe6060f1SDimitry Andric   collectUsedGlobalVariables(M, Used, /*CompilerUsed=*/false);
9090b57cec5SDimitry Andric   // Next collect those in the llvm.compiler.used set.
910fe6060f1SDimitry Andric   collectUsedGlobalVariables(M, Used, /*CompilerUsed=*/true);
9110b57cec5SDimitry Andric   DenseSet<GlobalValue::GUID> CantBePromoted;
9120b57cec5SDimitry Andric   for (auto *V : Used) {
9130b57cec5SDimitry Andric     if (V->hasLocalLinkage()) {
9140b57cec5SDimitry Andric       LocalsUsed.insert(V);
9150b57cec5SDimitry Andric       CantBePromoted.insert(V->getGUID());
9160b57cec5SDimitry Andric     }
9170b57cec5SDimitry Andric   }
9180b57cec5SDimitry Andric 
9190b57cec5SDimitry Andric   bool HasLocalInlineAsmSymbol = false;
9200b57cec5SDimitry Andric   if (!M.getModuleInlineAsm().empty()) {
9210b57cec5SDimitry Andric     // Collect the local values defined by module level asm, and set up
9220b57cec5SDimitry Andric     // summaries for these symbols so that they can be marked as NoRename,
9230b57cec5SDimitry Andric     // to prevent export of any use of them in regular IR that would require
9240b57cec5SDimitry Andric     // renaming within the module level asm. Note we don't need to create a
9250b57cec5SDimitry Andric     // summary for weak or global defs, as they don't need to be flagged as
9260b57cec5SDimitry Andric     // NoRename, and defs in module level asm can't be imported anyway.
9270b57cec5SDimitry Andric     // Also, any values used but not defined within module level asm should
9280b57cec5SDimitry Andric     // be listed on the llvm.used or llvm.compiler.used global and marked as
9290b57cec5SDimitry Andric     // referenced from there.
9300b57cec5SDimitry Andric     ModuleSymbolTable::CollectAsmSymbols(
9310b57cec5SDimitry Andric         M, [&](StringRef Name, object::BasicSymbolRef::Flags Flags) {
9320b57cec5SDimitry Andric           // Symbols not marked as Weak or Global are local definitions.
9330b57cec5SDimitry Andric           if (Flags & (object::BasicSymbolRef::SF_Weak |
9340b57cec5SDimitry Andric                        object::BasicSymbolRef::SF_Global))
9350b57cec5SDimitry Andric             return;
9360b57cec5SDimitry Andric           HasLocalInlineAsmSymbol = true;
9370b57cec5SDimitry Andric           GlobalValue *GV = M.getNamedValue(Name);
9380b57cec5SDimitry Andric           if (!GV)
9390b57cec5SDimitry Andric             return;
9400b57cec5SDimitry Andric           assert(GV->isDeclaration() && "Def in module asm already has definition");
941fe6060f1SDimitry Andric           GlobalValueSummary::GVFlags GVFlags(
942fe6060f1SDimitry Andric               GlobalValue::InternalLinkage, GlobalValue::DefaultVisibility,
9430b57cec5SDimitry Andric               /* NotEligibleToImport = */ true,
9440b57cec5SDimitry Andric               /* Live = */ true,
945*0fca6ea1SDimitry Andric               /* Local */ GV->isDSOLocal(), GV->canBeOmittedFromSymbolTable(),
946*0fca6ea1SDimitry Andric               GlobalValueSummary::Definition);
9470b57cec5SDimitry Andric           CantBePromoted.insert(GV->getGUID());
9480b57cec5SDimitry Andric           // Create the appropriate summary type.
9490b57cec5SDimitry Andric           if (Function *F = dyn_cast<Function>(GV)) {
9500b57cec5SDimitry Andric             std::unique_ptr<FunctionSummary> Summary =
9518bcb0991SDimitry Andric                 std::make_unique<FunctionSummary>(
9520b57cec5SDimitry Andric                     GVFlags, /*InstCount=*/0,
9530b57cec5SDimitry Andric                     FunctionSummary::FFlags{
9540b57cec5SDimitry Andric                         F->hasFnAttribute(Attribute::ReadNone),
9550b57cec5SDimitry Andric                         F->hasFnAttribute(Attribute::ReadOnly),
9560b57cec5SDimitry Andric                         F->hasFnAttribute(Attribute::NoRecurse),
9570b57cec5SDimitry Andric                         F->returnDoesNotAlias(),
958480093f4SDimitry Andric                         /* NoInline = */ false,
959349cc55cSDimitry Andric                         F->hasFnAttribute(Attribute::AlwaysInline),
960349cc55cSDimitry Andric                         F->hasFnAttribute(Attribute::NoUnwind),
961349cc55cSDimitry Andric                         /* MayThrow */ true,
9620eae32dcSDimitry Andric                         /* HasUnknownCall */ true,
9630eae32dcSDimitry Andric                         /* MustBeUnreachable */ false},
9640b57cec5SDimitry Andric                     /*EntryCount=*/0, ArrayRef<ValueInfo>{},
9650b57cec5SDimitry Andric                     ArrayRef<FunctionSummary::EdgeTy>{},
9660b57cec5SDimitry Andric                     ArrayRef<GlobalValue::GUID>{},
9670b57cec5SDimitry Andric                     ArrayRef<FunctionSummary::VFuncId>{},
9680b57cec5SDimitry Andric                     ArrayRef<FunctionSummary::VFuncId>{},
9690b57cec5SDimitry Andric                     ArrayRef<FunctionSummary::ConstVCall>{},
9705ffd83dbSDimitry Andric                     ArrayRef<FunctionSummary::ConstVCall>{},
971bdd1243dSDimitry Andric                     ArrayRef<FunctionSummary::ParamAccess>{},
972bdd1243dSDimitry Andric                     ArrayRef<CallsiteInfo>{}, ArrayRef<AllocInfo>{});
9730b57cec5SDimitry Andric             Index.addGlobalValueSummary(*GV, std::move(Summary));
9740b57cec5SDimitry Andric           } else {
9750b57cec5SDimitry Andric             std::unique_ptr<GlobalVarSummary> Summary =
9768bcb0991SDimitry Andric                 std::make_unique<GlobalVarSummary>(
9775ffd83dbSDimitry Andric                     GVFlags,
9785ffd83dbSDimitry Andric                     GlobalVarSummary::GVarFlags(
9795ffd83dbSDimitry Andric                         false, false, cast<GlobalVariable>(GV)->isConstant(),
9805ffd83dbSDimitry Andric                         GlobalObject::VCallVisibilityPublic),
9810b57cec5SDimitry Andric                     ArrayRef<ValueInfo>{});
9820b57cec5SDimitry Andric             Index.addGlobalValueSummary(*GV, std::move(Summary));
9830b57cec5SDimitry Andric           }
9840b57cec5SDimitry Andric         });
9850b57cec5SDimitry Andric   }
9860b57cec5SDimitry Andric 
9870b57cec5SDimitry Andric   bool IsThinLTO = true;
9880b57cec5SDimitry Andric   if (auto *MD =
9890b57cec5SDimitry Andric           mdconst::extract_or_null<ConstantInt>(M.getModuleFlag("ThinLTO")))
9900b57cec5SDimitry Andric     IsThinLTO = MD->getZExtValue();
9910b57cec5SDimitry Andric 
9920b57cec5SDimitry Andric   // Compute summaries for all functions defined in module, and save in the
9930b57cec5SDimitry Andric   // index.
994fcaf7f86SDimitry Andric   for (const auto &F : M) {
9950b57cec5SDimitry Andric     if (F.isDeclaration())
9960b57cec5SDimitry Andric       continue;
9970b57cec5SDimitry Andric 
9980b57cec5SDimitry Andric     DominatorTree DT(const_cast<Function &>(F));
9990b57cec5SDimitry Andric     BlockFrequencyInfo *BFI = nullptr;
10000b57cec5SDimitry Andric     std::unique_ptr<BlockFrequencyInfo> BFIPtr;
10010b57cec5SDimitry Andric     if (GetBFICallback)
10020b57cec5SDimitry Andric       BFI = GetBFICallback(F);
10030b57cec5SDimitry Andric     else if (F.hasProfileData()) {
10040b57cec5SDimitry Andric       LoopInfo LI{DT};
10050b57cec5SDimitry Andric       BranchProbabilityInfo BPI{F, LI};
10068bcb0991SDimitry Andric       BFIPtr = std::make_unique<BlockFrequencyInfo>(F, BPI, LI);
10070b57cec5SDimitry Andric       BFI = BFIPtr.get();
10080b57cec5SDimitry Andric     }
10090b57cec5SDimitry Andric 
10100b57cec5SDimitry Andric     computeFunctionSummary(Index, M, F, BFI, PSI, DT,
10110b57cec5SDimitry Andric                            !LocalsUsed.empty() || HasLocalInlineAsmSymbol,
10125ffd83dbSDimitry Andric                            CantBePromoted, IsThinLTO, GetSSICallback);
10130b57cec5SDimitry Andric   }
10140b57cec5SDimitry Andric 
10150b57cec5SDimitry Andric   // Compute summaries for all variables defined in module, and save in the
10160b57cec5SDimitry Andric   // index.
10170b57cec5SDimitry Andric   SmallVector<MDNode *, 2> Types;
10180b57cec5SDimitry Andric   for (const GlobalVariable &G : M.globals()) {
10190b57cec5SDimitry Andric     if (G.isDeclaration())
10200b57cec5SDimitry Andric       continue;
10210b57cec5SDimitry Andric     computeVariableSummary(Index, G, CantBePromoted, M, Types);
10220b57cec5SDimitry Andric   }
10230b57cec5SDimitry Andric 
10240b57cec5SDimitry Andric   // Compute summaries for all aliases defined in module, and save in the
10250b57cec5SDimitry Andric   // index.
10260b57cec5SDimitry Andric   for (const GlobalAlias &A : M.aliases())
10270b57cec5SDimitry Andric     computeAliasSummary(Index, A, CantBePromoted);
10280b57cec5SDimitry Andric 
1029fcaf7f86SDimitry Andric   // Iterate through ifuncs, set their resolvers all alive.
1030fcaf7f86SDimitry Andric   for (const GlobalIFunc &I : M.ifuncs()) {
1031fcaf7f86SDimitry Andric     I.applyAlongResolverPath([&Index](const GlobalValue &GV) {
1032fcaf7f86SDimitry Andric       Index.getGlobalValueSummary(GV)->setLive(true);
1033fcaf7f86SDimitry Andric     });
1034fcaf7f86SDimitry Andric   }
1035fcaf7f86SDimitry Andric 
10360b57cec5SDimitry Andric   for (auto *V : LocalsUsed) {
10370b57cec5SDimitry Andric     auto *Summary = Index.getGlobalValueSummary(*V);
10380b57cec5SDimitry Andric     assert(Summary && "Missing summary for global value");
10390b57cec5SDimitry Andric     Summary->setNotEligibleToImport();
10400b57cec5SDimitry Andric   }
10410b57cec5SDimitry Andric 
10420b57cec5SDimitry Andric   // The linker doesn't know about these LLVM produced values, so we need
10430b57cec5SDimitry Andric   // to flag them as live in the index to ensure index-based dead value
10440b57cec5SDimitry Andric   // analysis treats them as live roots of the analysis.
10450b57cec5SDimitry Andric   setLiveRoot(Index, "llvm.used");
10460b57cec5SDimitry Andric   setLiveRoot(Index, "llvm.compiler.used");
10470b57cec5SDimitry Andric   setLiveRoot(Index, "llvm.global_ctors");
10480b57cec5SDimitry Andric   setLiveRoot(Index, "llvm.global_dtors");
10490b57cec5SDimitry Andric   setLiveRoot(Index, "llvm.global.annotations");
10500b57cec5SDimitry Andric 
10510b57cec5SDimitry Andric   for (auto &GlobalList : Index) {
10520b57cec5SDimitry Andric     // Ignore entries for references that are undefined in the current module.
10530b57cec5SDimitry Andric     if (GlobalList.second.SummaryList.empty())
10540b57cec5SDimitry Andric       continue;
10550b57cec5SDimitry Andric 
10560b57cec5SDimitry Andric     assert(GlobalList.second.SummaryList.size() == 1 &&
10570b57cec5SDimitry Andric            "Expected module's index to have one summary per GUID");
10580b57cec5SDimitry Andric     auto &Summary = GlobalList.second.SummaryList[0];
10590b57cec5SDimitry Andric     if (!IsThinLTO) {
10600b57cec5SDimitry Andric       Summary->setNotEligibleToImport();
10610b57cec5SDimitry Andric       continue;
10620b57cec5SDimitry Andric     }
10630b57cec5SDimitry Andric 
10640b57cec5SDimitry Andric     bool AllRefsCanBeExternallyReferenced =
10650b57cec5SDimitry Andric         llvm::all_of(Summary->refs(), [&](const ValueInfo &VI) {
10660b57cec5SDimitry Andric           return !CantBePromoted.count(VI.getGUID());
10670b57cec5SDimitry Andric         });
10680b57cec5SDimitry Andric     if (!AllRefsCanBeExternallyReferenced) {
10690b57cec5SDimitry Andric       Summary->setNotEligibleToImport();
10700b57cec5SDimitry Andric       continue;
10710b57cec5SDimitry Andric     }
10720b57cec5SDimitry Andric 
10730b57cec5SDimitry Andric     if (auto *FuncSummary = dyn_cast<FunctionSummary>(Summary.get())) {
10740b57cec5SDimitry Andric       bool AllCallsCanBeExternallyReferenced = llvm::all_of(
10750b57cec5SDimitry Andric           FuncSummary->calls(), [&](const FunctionSummary::EdgeTy &Edge) {
10760b57cec5SDimitry Andric             return !CantBePromoted.count(Edge.first.getGUID());
10770b57cec5SDimitry Andric           });
10780b57cec5SDimitry Andric       if (!AllCallsCanBeExternallyReferenced)
10790b57cec5SDimitry Andric         Summary->setNotEligibleToImport();
10800b57cec5SDimitry Andric     }
10810b57cec5SDimitry Andric   }
10820b57cec5SDimitry Andric 
10830b57cec5SDimitry Andric   if (!ModuleSummaryDotFile.empty()) {
10840b57cec5SDimitry Andric     std::error_code EC;
1085*0fca6ea1SDimitry Andric     raw_fd_ostream OSDot(ModuleSummaryDotFile, EC, sys::fs::OpenFlags::OF_Text);
10860b57cec5SDimitry Andric     if (EC)
10870b57cec5SDimitry Andric       report_fatal_error(Twine("Failed to open dot file ") +
10880b57cec5SDimitry Andric                          ModuleSummaryDotFile + ": " + EC.message() + "\n");
1089480093f4SDimitry Andric     Index.exportToDot(OSDot, {});
10900b57cec5SDimitry Andric   }
10910b57cec5SDimitry Andric 
10920b57cec5SDimitry Andric   return Index;
10930b57cec5SDimitry Andric }
10940b57cec5SDimitry Andric 
10950b57cec5SDimitry Andric AnalysisKey ModuleSummaryIndexAnalysis::Key;
10960b57cec5SDimitry Andric 
10970b57cec5SDimitry Andric ModuleSummaryIndex
10980b57cec5SDimitry Andric ModuleSummaryIndexAnalysis::run(Module &M, ModuleAnalysisManager &AM) {
10990b57cec5SDimitry Andric   ProfileSummaryInfo &PSI = AM.getResult<ProfileSummaryAnalysis>(M);
11000b57cec5SDimitry Andric   auto &FAM = AM.getResult<FunctionAnalysisManagerModuleProxy>(M).getManager();
11015ffd83dbSDimitry Andric   bool NeedSSI = needsParamAccessSummary(M);
11020b57cec5SDimitry Andric   return buildModuleSummaryIndex(
11030b57cec5SDimitry Andric       M,
11040b57cec5SDimitry Andric       [&FAM](const Function &F) {
11050b57cec5SDimitry Andric         return &FAM.getResult<BlockFrequencyAnalysis>(
11060b57cec5SDimitry Andric             *const_cast<Function *>(&F));
11070b57cec5SDimitry Andric       },
11085ffd83dbSDimitry Andric       &PSI,
11095ffd83dbSDimitry Andric       [&FAM, NeedSSI](const Function &F) -> const StackSafetyInfo * {
11105ffd83dbSDimitry Andric         return NeedSSI ? &FAM.getResult<StackSafetyAnalysis>(
11115ffd83dbSDimitry Andric                              const_cast<Function &>(F))
11125ffd83dbSDimitry Andric                        : nullptr;
11135ffd83dbSDimitry Andric       });
11140b57cec5SDimitry Andric }
11150b57cec5SDimitry Andric 
11160b57cec5SDimitry Andric char ModuleSummaryIndexWrapperPass::ID = 0;
11170b57cec5SDimitry Andric 
11180b57cec5SDimitry Andric INITIALIZE_PASS_BEGIN(ModuleSummaryIndexWrapperPass, "module-summary-analysis",
11190b57cec5SDimitry Andric                       "Module Summary Analysis", false, true)
11200b57cec5SDimitry Andric INITIALIZE_PASS_DEPENDENCY(BlockFrequencyInfoWrapperPass)
11210b57cec5SDimitry Andric INITIALIZE_PASS_DEPENDENCY(ProfileSummaryInfoWrapperPass)
11225ffd83dbSDimitry Andric INITIALIZE_PASS_DEPENDENCY(StackSafetyInfoWrapperPass)
11230b57cec5SDimitry Andric INITIALIZE_PASS_END(ModuleSummaryIndexWrapperPass, "module-summary-analysis",
11240b57cec5SDimitry Andric                     "Module Summary Analysis", false, true)
11250b57cec5SDimitry Andric 
11260b57cec5SDimitry Andric ModulePass *llvm::createModuleSummaryIndexWrapperPass() {
11270b57cec5SDimitry Andric   return new ModuleSummaryIndexWrapperPass();
11280b57cec5SDimitry Andric }
11290b57cec5SDimitry Andric 
11300b57cec5SDimitry Andric ModuleSummaryIndexWrapperPass::ModuleSummaryIndexWrapperPass()
11310b57cec5SDimitry Andric     : ModulePass(ID) {
11320b57cec5SDimitry Andric   initializeModuleSummaryIndexWrapperPassPass(*PassRegistry::getPassRegistry());
11330b57cec5SDimitry Andric }
11340b57cec5SDimitry Andric 
11350b57cec5SDimitry Andric bool ModuleSummaryIndexWrapperPass::runOnModule(Module &M) {
11360b57cec5SDimitry Andric   auto *PSI = &getAnalysis<ProfileSummaryInfoWrapperPass>().getPSI();
11375ffd83dbSDimitry Andric   bool NeedSSI = needsParamAccessSummary(M);
11380b57cec5SDimitry Andric   Index.emplace(buildModuleSummaryIndex(
11390b57cec5SDimitry Andric       M,
11400b57cec5SDimitry Andric       [this](const Function &F) {
11410b57cec5SDimitry Andric         return &(this->getAnalysis<BlockFrequencyInfoWrapperPass>(
11420b57cec5SDimitry Andric                          *const_cast<Function *>(&F))
11430b57cec5SDimitry Andric                      .getBFI());
11440b57cec5SDimitry Andric       },
11455ffd83dbSDimitry Andric       PSI,
11465ffd83dbSDimitry Andric       [&](const Function &F) -> const StackSafetyInfo * {
11475ffd83dbSDimitry Andric         return NeedSSI ? &getAnalysis<StackSafetyInfoWrapperPass>(
11485ffd83dbSDimitry Andric                               const_cast<Function &>(F))
11495ffd83dbSDimitry Andric                               .getResult()
11505ffd83dbSDimitry Andric                        : nullptr;
11515ffd83dbSDimitry Andric       }));
11520b57cec5SDimitry Andric   return false;
11530b57cec5SDimitry Andric }
11540b57cec5SDimitry Andric 
11550b57cec5SDimitry Andric bool ModuleSummaryIndexWrapperPass::doFinalization(Module &M) {
11560b57cec5SDimitry Andric   Index.reset();
11570b57cec5SDimitry Andric   return false;
11580b57cec5SDimitry Andric }
11590b57cec5SDimitry Andric 
11600b57cec5SDimitry Andric void ModuleSummaryIndexWrapperPass::getAnalysisUsage(AnalysisUsage &AU) const {
11610b57cec5SDimitry Andric   AU.setPreservesAll();
11620b57cec5SDimitry Andric   AU.addRequired<BlockFrequencyInfoWrapperPass>();
11630b57cec5SDimitry Andric   AU.addRequired<ProfileSummaryInfoWrapperPass>();
11645ffd83dbSDimitry Andric   AU.addRequired<StackSafetyInfoWrapperPass>();
11650b57cec5SDimitry Andric }
11665ffd83dbSDimitry Andric 
11675ffd83dbSDimitry Andric char ImmutableModuleSummaryIndexWrapperPass::ID = 0;
11685ffd83dbSDimitry Andric 
11695ffd83dbSDimitry Andric ImmutableModuleSummaryIndexWrapperPass::ImmutableModuleSummaryIndexWrapperPass(
11705ffd83dbSDimitry Andric     const ModuleSummaryIndex *Index)
11715ffd83dbSDimitry Andric     : ImmutablePass(ID), Index(Index) {
11725ffd83dbSDimitry Andric   initializeImmutableModuleSummaryIndexWrapperPassPass(
11735ffd83dbSDimitry Andric       *PassRegistry::getPassRegistry());
11745ffd83dbSDimitry Andric }
11755ffd83dbSDimitry Andric 
11765ffd83dbSDimitry Andric void ImmutableModuleSummaryIndexWrapperPass::getAnalysisUsage(
11775ffd83dbSDimitry Andric     AnalysisUsage &AU) const {
11785ffd83dbSDimitry Andric   AU.setPreservesAll();
11795ffd83dbSDimitry Andric }
11805ffd83dbSDimitry Andric 
11815ffd83dbSDimitry Andric ImmutablePass *llvm::createImmutableModuleSummaryIndexWrapperPass(
11825ffd83dbSDimitry Andric     const ModuleSummaryIndex *Index) {
11835ffd83dbSDimitry Andric   return new ImmutableModuleSummaryIndexWrapperPass(Index);
11845ffd83dbSDimitry Andric }
11855ffd83dbSDimitry Andric 
11865ffd83dbSDimitry Andric INITIALIZE_PASS(ImmutableModuleSummaryIndexWrapperPass, "module-summary-info",
11875ffd83dbSDimitry Andric                 "Module summary info", false, true)
118806c3fb27SDimitry Andric 
118906c3fb27SDimitry Andric bool llvm::mayHaveMemprofSummary(const CallBase *CB) {
119006c3fb27SDimitry Andric   if (!CB)
119106c3fb27SDimitry Andric     return false;
119206c3fb27SDimitry Andric   if (CB->isDebugOrPseudoInst())
119306c3fb27SDimitry Andric     return false;
119406c3fb27SDimitry Andric   auto *CI = dyn_cast<CallInst>(CB);
119506c3fb27SDimitry Andric   auto *CalledValue = CB->getCalledOperand();
119606c3fb27SDimitry Andric   auto *CalledFunction = CB->getCalledFunction();
119706c3fb27SDimitry Andric   if (CalledValue && !CalledFunction) {
119806c3fb27SDimitry Andric     CalledValue = CalledValue->stripPointerCasts();
119906c3fb27SDimitry Andric     // Stripping pointer casts can reveal a called function.
120006c3fb27SDimitry Andric     CalledFunction = dyn_cast<Function>(CalledValue);
120106c3fb27SDimitry Andric   }
120206c3fb27SDimitry Andric   // Check if this is an alias to a function. If so, get the
120306c3fb27SDimitry Andric   // called aliasee for the checks below.
120406c3fb27SDimitry Andric   if (auto *GA = dyn_cast<GlobalAlias>(CalledValue)) {
120506c3fb27SDimitry Andric     assert(!CalledFunction &&
120606c3fb27SDimitry Andric            "Expected null called function in callsite for alias");
120706c3fb27SDimitry Andric     CalledFunction = dyn_cast<Function>(GA->getAliaseeObject());
120806c3fb27SDimitry Andric   }
120906c3fb27SDimitry Andric   // Check if this is a direct call to a known function or a known
121006c3fb27SDimitry Andric   // intrinsic, or an indirect call with profile data.
121106c3fb27SDimitry Andric   if (CalledFunction) {
121206c3fb27SDimitry Andric     if (CI && CalledFunction->isIntrinsic())
121306c3fb27SDimitry Andric       return false;
121406c3fb27SDimitry Andric   } else {
121506c3fb27SDimitry Andric     // TODO: For now skip indirect calls. See comments in
121606c3fb27SDimitry Andric     // computeFunctionSummary for what is needed to handle this.
121706c3fb27SDimitry Andric     return false;
121806c3fb27SDimitry Andric   }
121906c3fb27SDimitry Andric   return true;
122006c3fb27SDimitry Andric }
1221