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 // Summary not currently supported for anonymous functions, they must 82 // be renamed. 83 if (!F.hasName()) 84 return; 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 94 SmallPtrSet<const User *, 8> Visited; 95 for (const BasicBlock &BB : F) 96 for (const Instruction &I : BB) { 97 if (isa<DbgInfoIntrinsic>(I)) 98 continue; 99 ++NumInsts; 100 findRefEdges(&I, RefEdges, Visited); 101 auto CS = ImmutableCallSite(&I); 102 if (!CS) 103 continue; 104 auto *CalledFunction = CS.getCalledFunction(); 105 // Check if this is a direct call to a known function. 106 if (CalledFunction) { 107 // Skip nameless and intrinsics. 108 if (!CalledFunction->hasName() || CalledFunction->isIntrinsic()) 109 continue; 110 auto ScaledCount = BFI ? BFI->getBlockProfileCount(&BB) : None; 111 auto *CalleeId = 112 M.getValueSymbolTable().lookup(CalledFunction->getName()); 113 114 auto Hotness = ScaledCount ? getHotness(ScaledCount.getValue(), PSI) 115 : CalleeInfo::HotnessType::Unknown; 116 CallGraphEdges[CalleeId].updateHotness(Hotness); 117 } else { 118 const auto *CI = dyn_cast<CallInst>(&I); 119 // Skip inline assembly calls. 120 if (CI && CI->isInlineAsm()) 121 continue; 122 // Skip direct calls. 123 if (!CS.getCalledValue() || isa<Constant>(CS.getCalledValue())) 124 continue; 125 126 uint32_t NumVals, NumCandidates; 127 uint64_t TotalCount; 128 auto CandidateProfileData = 129 ICallAnalysis.getPromotionCandidatesForInstruction( 130 &I, NumVals, TotalCount, NumCandidates); 131 for (auto &Candidate : CandidateProfileData) 132 IndirectCallEdges[Candidate.Value].updateHotness( 133 getHotness(Candidate.Count, PSI)); 134 } 135 } 136 137 GlobalValueSummary::GVFlags Flags(F); 138 std::unique_ptr<FunctionSummary> FuncSummary = 139 llvm::make_unique<FunctionSummary>(Flags, NumInsts); 140 FuncSummary->addCallGraphEdges(CallGraphEdges); 141 FuncSummary->addCallGraphEdges(IndirectCallEdges); 142 FuncSummary->addRefEdges(RefEdges); 143 Index.addGlobalValueSummary(F.getName(), std::move(FuncSummary)); 144 } 145 146 static void computeVariableSummary(ModuleSummaryIndex &Index, 147 const GlobalVariable &V) { 148 DenseSet<const Value *> RefEdges; 149 SmallPtrSet<const User *, 8> Visited; 150 findRefEdges(&V, RefEdges, Visited); 151 GlobalValueSummary::GVFlags Flags(V); 152 std::unique_ptr<GlobalVarSummary> GVarSummary = 153 llvm::make_unique<GlobalVarSummary>(Flags); 154 GVarSummary->addRefEdges(RefEdges); 155 Index.addGlobalValueSummary(V.getName(), std::move(GVarSummary)); 156 } 157 158 ModuleSummaryIndex llvm::buildModuleSummaryIndex( 159 const Module &M, 160 std::function<BlockFrequencyInfo *(const Function &F)> GetBFICallback, 161 ProfileSummaryInfo *PSI) { 162 ModuleSummaryIndex Index; 163 // Check if the module can be promoted, otherwise just disable importing from 164 // it by not emitting any summary. 165 // FIXME: we could still import *into* it most of the time. 166 if (!moduleCanBeRenamedForThinLTO(M)) 167 return Index; 168 169 // Compute summaries for all functions defined in module, and save in the 170 // index. 171 for (auto &F : M) { 172 if (F.isDeclaration()) 173 continue; 174 175 BlockFrequencyInfo *BFI = nullptr; 176 std::unique_ptr<BlockFrequencyInfo> BFIPtr; 177 if (GetBFICallback) 178 BFI = GetBFICallback(F); 179 else if (F.getEntryCount().hasValue()) { 180 LoopInfo LI{DominatorTree(const_cast<Function &>(F))}; 181 BranchProbabilityInfo BPI{F, LI}; 182 BFIPtr = llvm::make_unique<BlockFrequencyInfo>(F, BPI, LI); 183 BFI = BFIPtr.get(); 184 } 185 186 computeFunctionSummary(Index, M, F, BFI, PSI); 187 } 188 189 // Compute summaries for all variables defined in module, and save in the 190 // index. 191 for (const GlobalVariable &G : M.globals()) { 192 if (G.isDeclaration()) 193 continue; 194 computeVariableSummary(Index, G); 195 } 196 return Index; 197 } 198 199 char ModuleSummaryIndexAnalysis::PassID; 200 201 ModuleSummaryIndex 202 ModuleSummaryIndexAnalysis::run(Module &M, ModuleAnalysisManager &AM) { 203 ProfileSummaryInfo &PSI = AM.getResult<ProfileSummaryAnalysis>(M); 204 auto &FAM = AM.getResult<FunctionAnalysisManagerModuleProxy>(M).getManager(); 205 return buildModuleSummaryIndex( 206 M, 207 [&FAM](const Function &F) { 208 return &FAM.getResult<BlockFrequencyAnalysis>( 209 *const_cast<Function *>(&F)); 210 }, 211 &PSI); 212 } 213 214 char ModuleSummaryIndexWrapperPass::ID = 0; 215 INITIALIZE_PASS_BEGIN(ModuleSummaryIndexWrapperPass, "module-summary-analysis", 216 "Module Summary Analysis", false, true) 217 INITIALIZE_PASS_DEPENDENCY(BlockFrequencyInfoWrapperPass) 218 INITIALIZE_PASS_END(ModuleSummaryIndexWrapperPass, "module-summary-analysis", 219 "Module Summary Analysis", false, true) 220 221 ModulePass *llvm::createModuleSummaryIndexWrapperPass() { 222 return new ModuleSummaryIndexWrapperPass(); 223 } 224 225 ModuleSummaryIndexWrapperPass::ModuleSummaryIndexWrapperPass() 226 : ModulePass(ID) { 227 initializeModuleSummaryIndexWrapperPassPass(*PassRegistry::getPassRegistry()); 228 } 229 230 bool ModuleSummaryIndexWrapperPass::runOnModule(Module &M) { 231 auto &PSI = *getAnalysis<ProfileSummaryInfoWrapperPass>().getPSI(M); 232 Index = buildModuleSummaryIndex( 233 M, 234 [this](const Function &F) { 235 return &(this->getAnalysis<BlockFrequencyInfoWrapperPass>( 236 *const_cast<Function *>(&F)) 237 .getBFI()); 238 }, 239 &PSI); 240 return false; 241 } 242 243 bool ModuleSummaryIndexWrapperPass::doFinalization(Module &M) { 244 Index.reset(); 245 return false; 246 } 247 248 void ModuleSummaryIndexWrapperPass::getAnalysisUsage(AnalysisUsage &AU) const { 249 AU.setPreservesAll(); 250 AU.addRequired<BlockFrequencyInfoWrapperPass>(); 251 AU.addRequired<ProfileSummaryInfoWrapperPass>(); 252 } 253 254 bool llvm::moduleCanBeRenamedForThinLTO(const Module &M) { 255 // We cannot currently promote or rename anything used in inline assembly, 256 // which are not visible to the compiler. Detect a possible case by looking 257 // for a llvm.used local value, in conjunction with an inline assembly call 258 // in the module. Prevent importing of any modules containing these uses by 259 // suppressing generation of the index. This also prevents importing 260 // into this module, which is also necessary to avoid needing to rename 261 // in case of a name clash between a local in this module and an imported 262 // global. 263 // FIXME: If we find we need a finer-grained approach of preventing promotion 264 // and renaming of just the functions using inline assembly we will need to: 265 // - Add flag in the function summaries to identify those with inline asm. 266 // - Prevent importing of any functions with flag set. 267 // - Prevent importing of any global function with the same name as a 268 // function in current module that has the flag set. 269 // - For any llvm.used value that is exported and promoted, add a private 270 // alias to the original name in the current module (even if we don't 271 // export the function using those values in inline asm, another function 272 // with a reference could be exported). 273 SmallPtrSet<GlobalValue *, 8> Used; 274 collectUsedGlobalVariables(M, Used, /*CompilerUsed*/ false); 275 bool LocalIsUsed = 276 any_of(Used, [](GlobalValue *V) { return V->hasLocalLinkage(); }); 277 if (!LocalIsUsed) 278 return true; 279 280 // Walk all the instructions in the module and find if one is inline ASM 281 auto HasInlineAsm = any_of(M, [](const Function &F) { 282 return any_of(instructions(F), [](const Instruction &I) { 283 const CallInst *CallI = dyn_cast<CallInst>(&I); 284 if (!CallI) 285 return false; 286 return CallI->isInlineAsm(); 287 }); 288 }); 289 return !HasInlineAsm; 290 } 291