1 //===- ModuleSummaryAnalysis.cpp - Module summary index builder -----------===// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 // 10 // This pass builds a ModuleSummaryIndex object for the module, to be written 11 // to bitcode or LLVM assembly. 12 // 13 //===----------------------------------------------------------------------===// 14 15 #include "llvm/Analysis/ModuleSummaryAnalysis.h" 16 #include "llvm/Analysis/BlockFrequencyInfo.h" 17 #include "llvm/Analysis/BlockFrequencyInfoImpl.h" 18 #include "llvm/Analysis/BranchProbabilityInfo.h" 19 #include "llvm/Analysis/IndirectCallPromotionAnalysis.h" 20 #include "llvm/Analysis/LoopInfo.h" 21 #include "llvm/Analysis/ProfileSummaryInfo.h" 22 #include "llvm/IR/CallSite.h" 23 #include "llvm/IR/Dominators.h" 24 #include "llvm/IR/InstIterator.h" 25 #include "llvm/IR/IntrinsicInst.h" 26 #include "llvm/IR/ValueSymbolTable.h" 27 #include "llvm/Pass.h" 28 using namespace llvm; 29 30 #define DEBUG_TYPE "module-summary-analysis" 31 32 // Walk through the operands of a given User via worklist iteration and populate 33 // the set of GlobalValue references encountered. Invoked either on an 34 // Instruction or a GlobalVariable (which walks its initializer). 35 static void findRefEdges(const User *CurUser, DenseSet<const Value *> &RefEdges, 36 SmallPtrSet<const User *, 8> &Visited) { 37 SmallVector<const User *, 32> Worklist; 38 Worklist.push_back(CurUser); 39 40 while (!Worklist.empty()) { 41 const User *U = Worklist.pop_back_val(); 42 43 if (!Visited.insert(U).second) 44 continue; 45 46 ImmutableCallSite CS(U); 47 48 for (const auto &OI : U->operands()) { 49 const User *Operand = dyn_cast<User>(OI); 50 if (!Operand) 51 continue; 52 if (isa<BlockAddress>(Operand)) 53 continue; 54 if (isa<GlobalValue>(Operand)) { 55 // We have a reference to a global value. This should be added to 56 // the reference set unless it is a callee. Callees are handled 57 // specially by WriteFunction and are added to a separate list. 58 if (!(CS && CS.isCallee(&OI))) 59 RefEdges.insert(Operand); 60 continue; 61 } 62 Worklist.push_back(Operand); 63 } 64 } 65 } 66 67 static CalleeInfo::HotnessType getHotness(uint64_t ProfileCount, 68 ProfileSummaryInfo *PSI) { 69 if (!PSI) 70 return CalleeInfo::HotnessType::Unknown; 71 if (PSI->isHotCount(ProfileCount)) 72 return CalleeInfo::HotnessType::Hot; 73 if (PSI->isColdCount(ProfileCount)) 74 return CalleeInfo::HotnessType::Cold; 75 return CalleeInfo::HotnessType::None; 76 } 77 78 static void computeFunctionSummary(ModuleSummaryIndex &Index, const Module &M, 79 const Function &F, BlockFrequencyInfo *BFI, 80 ProfileSummaryInfo *PSI, 81 SmallPtrSetImpl<GlobalValue *> &LocalsUsed) { 82 // Summary not currently supported for anonymous functions, they should 83 // have been named. 84 assert(F.hasName()); 85 86 unsigned NumInsts = 0; 87 // Map from callee ValueId to profile count. Used to accumulate profile 88 // counts for all static calls to a given callee. 89 DenseMap<const Value *, CalleeInfo> CallGraphEdges; 90 DenseMap<GlobalValue::GUID, CalleeInfo> IndirectCallEdges; 91 DenseSet<const Value *> RefEdges; 92 ICallPromotionAnalysis ICallAnalysis; 93 bool HasLocalsInUsed = !LocalsUsed.empty(); 94 95 SmallPtrSet<const User *, 8> Visited; 96 for (const BasicBlock &BB : F) 97 for (const Instruction &I : BB) { 98 if (isa<DbgInfoIntrinsic>(I)) 99 continue; 100 ++NumInsts; 101 findRefEdges(&I, RefEdges, Visited); 102 auto CS = ImmutableCallSite(&I); 103 if (!CS) 104 continue; 105 106 const auto *CI = dyn_cast<CallInst>(&I); 107 // Since we don't know exactly which local values are referenced in inline 108 // assembly, conservatively reference all of them from this function, to 109 // ensure we don't export a reference (which would require renaming and 110 // promotion). 111 if (HasLocalsInUsed && CI && CI->isInlineAsm()) 112 RefEdges.insert(LocalsUsed.begin(), LocalsUsed.end()); 113 114 auto *CalledValue = CS.getCalledValue(); 115 auto *CalledFunction = CS.getCalledFunction(); 116 // Check if this is an alias to a function. If so, get the 117 // called aliasee for the checks below. 118 if (auto *GA = dyn_cast<GlobalAlias>(CalledValue)) { 119 assert(!CalledFunction && "Expected null called function in callsite for alias"); 120 CalledFunction = dyn_cast<Function>(GA->getBaseObject()); 121 } 122 // Check if this is a direct call to a known function. 123 if (CalledFunction) { 124 // Skip intrinsics. 125 if (CalledFunction->isIntrinsic()) 126 continue; 127 // We should have named any anonymous globals 128 assert(CalledFunction->hasName()); 129 auto ScaledCount = BFI ? BFI->getBlockProfileCount(&BB) : None; 130 // Use the original CalledValue, in case it was an alias. We want 131 // to record the call edge to the alias in that case. Eventually 132 // an alias summary will be created to associate the alias and 133 // aliasee. 134 auto *CalleeId = 135 M.getValueSymbolTable().lookup(CalledValue->getName()); 136 137 auto Hotness = ScaledCount ? getHotness(ScaledCount.getValue(), PSI) 138 : CalleeInfo::HotnessType::Unknown; 139 CallGraphEdges[CalleeId].updateHotness(Hotness); 140 } else { 141 // Skip inline assembly calls. 142 if (CI && CI->isInlineAsm()) 143 continue; 144 // Skip direct calls. 145 if (!CS.getCalledValue() || isa<Constant>(CS.getCalledValue())) 146 continue; 147 148 uint32_t NumVals, NumCandidates; 149 uint64_t TotalCount; 150 auto CandidateProfileData = 151 ICallAnalysis.getPromotionCandidatesForInstruction( 152 &I, NumVals, TotalCount, NumCandidates); 153 for (auto &Candidate : CandidateProfileData) 154 IndirectCallEdges[Candidate.Value].updateHotness( 155 getHotness(Candidate.Count, PSI)); 156 } 157 } 158 159 GlobalValueSummary::GVFlags Flags(F); 160 std::unique_ptr<FunctionSummary> FuncSummary = 161 llvm::make_unique<FunctionSummary>(Flags, NumInsts); 162 FuncSummary->addCallGraphEdges(CallGraphEdges); 163 FuncSummary->addCallGraphEdges(IndirectCallEdges); 164 FuncSummary->addRefEdges(RefEdges); 165 Index.addGlobalValueSummary(F.getName(), std::move(FuncSummary)); 166 } 167 168 static void computeVariableSummary(ModuleSummaryIndex &Index, 169 const GlobalVariable &V) { 170 DenseSet<const Value *> RefEdges; 171 SmallPtrSet<const User *, 8> Visited; 172 findRefEdges(&V, RefEdges, Visited); 173 GlobalValueSummary::GVFlags Flags(V); 174 std::unique_ptr<GlobalVarSummary> GVarSummary = 175 llvm::make_unique<GlobalVarSummary>(Flags); 176 GVarSummary->addRefEdges(RefEdges); 177 Index.addGlobalValueSummary(V.getName(), std::move(GVarSummary)); 178 } 179 180 static void computeAliasSummary(ModuleSummaryIndex &Index, 181 const GlobalAlias &A) { 182 GlobalValueSummary::GVFlags Flags(A); 183 std::unique_ptr<AliasSummary> AS = llvm::make_unique<AliasSummary>(Flags); 184 auto *Aliasee = A.getBaseObject(); 185 auto *AliaseeSummary = Index.getGlobalValueSummary(*Aliasee); 186 assert(AliaseeSummary && "Alias expects aliasee summary to be parsed"); 187 AS->setAliasee(AliaseeSummary); 188 Index.addGlobalValueSummary(A.getName(), std::move(AS)); 189 } 190 191 ModuleSummaryIndex llvm::buildModuleSummaryIndex( 192 const Module &M, 193 std::function<BlockFrequencyInfo *(const Function &F)> GetBFICallback, 194 ProfileSummaryInfo *PSI) { 195 ModuleSummaryIndex Index; 196 197 // Identify the local values in the llvm.used set, which should not be 198 // exported as they would then require renaming and promotion, but we 199 // may have opaque uses e.g. in inline asm. 200 SmallPtrSet<GlobalValue *, 8> Used; 201 collectUsedGlobalVariables(M, Used, /*CompilerUsed*/ false); 202 SmallPtrSet<GlobalValue *, 8> LocalsUsed; 203 for (auto *V : Used) { 204 if (V->hasLocalLinkage()) 205 LocalsUsed.insert(V); 206 } 207 208 // Compute summaries for all functions defined in module, and save in the 209 // index. 210 for (auto &F : M) { 211 if (F.isDeclaration()) 212 continue; 213 214 BlockFrequencyInfo *BFI = nullptr; 215 std::unique_ptr<BlockFrequencyInfo> BFIPtr; 216 if (GetBFICallback) 217 BFI = GetBFICallback(F); 218 else if (F.getEntryCount().hasValue()) { 219 LoopInfo LI{DominatorTree(const_cast<Function &>(F))}; 220 BranchProbabilityInfo BPI{F, LI}; 221 BFIPtr = llvm::make_unique<BlockFrequencyInfo>(F, BPI, LI); 222 BFI = BFIPtr.get(); 223 } 224 225 computeFunctionSummary(Index, M, F, BFI, PSI, LocalsUsed); 226 } 227 228 // Compute summaries for all variables defined in module, and save in the 229 // index. 230 for (const GlobalVariable &G : M.globals()) { 231 if (G.isDeclaration()) 232 continue; 233 computeVariableSummary(Index, G); 234 } 235 236 // Compute summaries for all aliases defined in module, and save in the 237 // index. 238 for (const GlobalAlias &A : M.aliases()) 239 computeAliasSummary(Index, A); 240 241 for (auto *V : LocalsUsed) { 242 auto *Summary = Index.getGlobalValueSummary(*V); 243 assert(Summary && "Missing summary for global value"); 244 Summary->setNoRename(); 245 } 246 247 return Index; 248 } 249 250 char ModuleSummaryIndexAnalysis::PassID; 251 252 ModuleSummaryIndex 253 ModuleSummaryIndexAnalysis::run(Module &M, ModuleAnalysisManager &AM) { 254 ProfileSummaryInfo &PSI = AM.getResult<ProfileSummaryAnalysis>(M); 255 auto &FAM = AM.getResult<FunctionAnalysisManagerModuleProxy>(M).getManager(); 256 return buildModuleSummaryIndex( 257 M, 258 [&FAM](const Function &F) { 259 return &FAM.getResult<BlockFrequencyAnalysis>( 260 *const_cast<Function *>(&F)); 261 }, 262 &PSI); 263 } 264 265 char ModuleSummaryIndexWrapperPass::ID = 0; 266 INITIALIZE_PASS_BEGIN(ModuleSummaryIndexWrapperPass, "module-summary-analysis", 267 "Module Summary Analysis", false, true) 268 INITIALIZE_PASS_DEPENDENCY(BlockFrequencyInfoWrapperPass) 269 INITIALIZE_PASS_END(ModuleSummaryIndexWrapperPass, "module-summary-analysis", 270 "Module Summary Analysis", false, true) 271 272 ModulePass *llvm::createModuleSummaryIndexWrapperPass() { 273 return new ModuleSummaryIndexWrapperPass(); 274 } 275 276 ModuleSummaryIndexWrapperPass::ModuleSummaryIndexWrapperPass() 277 : ModulePass(ID) { 278 initializeModuleSummaryIndexWrapperPassPass(*PassRegistry::getPassRegistry()); 279 } 280 281 bool ModuleSummaryIndexWrapperPass::runOnModule(Module &M) { 282 auto &PSI = *getAnalysis<ProfileSummaryInfoWrapperPass>().getPSI(); 283 Index = buildModuleSummaryIndex( 284 M, 285 [this](const Function &F) { 286 return &(this->getAnalysis<BlockFrequencyInfoWrapperPass>( 287 *const_cast<Function *>(&F)) 288 .getBFI()); 289 }, 290 &PSI); 291 return false; 292 } 293 294 bool ModuleSummaryIndexWrapperPass::doFinalization(Module &M) { 295 Index.reset(); 296 return false; 297 } 298 299 void ModuleSummaryIndexWrapperPass::getAnalysisUsage(AnalysisUsage &AU) const { 300 AU.setPreservesAll(); 301 AU.addRequired<BlockFrequencyInfoWrapperPass>(); 302 AU.addRequired<ProfileSummaryInfoWrapperPass>(); 303 } 304