13c256fbfSChandler Carruth //===- CodeMetrics.cpp - Code cost measurements ---------------------------===// 23c256fbfSChandler Carruth // 33c256fbfSChandler Carruth // The LLVM Compiler Infrastructure 43c256fbfSChandler Carruth // 53c256fbfSChandler Carruth // This file is distributed under the University of Illinois Open Source 63c256fbfSChandler Carruth // License. See LICENSE.TXT for details. 73c256fbfSChandler Carruth // 83c256fbfSChandler Carruth //===----------------------------------------------------------------------===// 93c256fbfSChandler Carruth // 103c256fbfSChandler Carruth // This file implements code cost measurement utilities. 113c256fbfSChandler Carruth // 123c256fbfSChandler Carruth //===----------------------------------------------------------------------===// 133c256fbfSChandler Carruth 1466b3130cSChandler Carruth #include "llvm/Analysis/AssumptionCache.h" 153c256fbfSChandler Carruth #include "llvm/Analysis/CodeMetrics.h" 1657f03ddaSHal Finkel #include "llvm/Analysis/LoopInfo.h" 17bb9caa92SChandler Carruth #include "llvm/Analysis/TargetTransformInfo.h" 1857f03ddaSHal Finkel #include "llvm/Analysis/ValueTracking.h" 19219b89b9SChandler Carruth #include "llvm/IR/CallSite.h" 209fb823bbSChandler Carruth #include "llvm/IR/DataLayout.h" 219fb823bbSChandler Carruth #include "llvm/IR/Function.h" 229fb823bbSChandler Carruth #include "llvm/IR/IntrinsicInst.h" 2357f03ddaSHal Finkel #include "llvm/Support/Debug.h" 24*799003bfSBenjamin Kramer #include "llvm/Support/raw_ostream.h" 2557f03ddaSHal Finkel 2657f03ddaSHal Finkel #define DEBUG_TYPE "code-metrics" 273c256fbfSChandler Carruth 283c256fbfSChandler Carruth using namespace llvm; 293c256fbfSChandler Carruth 3057f03ddaSHal Finkel static void completeEphemeralValues(SmallVector<const Value *, 16> &WorkSet, 3157f03ddaSHal Finkel SmallPtrSetImpl<const Value*> &EphValues) { 3257f03ddaSHal Finkel SmallPtrSet<const Value *, 32> Visited; 3357f03ddaSHal Finkel 3457f03ddaSHal Finkel // Make sure that all of the items in WorkSet are in our EphValues set. 3557f03ddaSHal Finkel EphValues.insert(WorkSet.begin(), WorkSet.end()); 3657f03ddaSHal Finkel 3757f03ddaSHal Finkel // Note: We don't speculate PHIs here, so we'll miss instruction chains kept 3857f03ddaSHal Finkel // alive only by ephemeral values. 3957f03ddaSHal Finkel 4057f03ddaSHal Finkel while (!WorkSet.empty()) { 418683d2b0SHal Finkel const Value *V = WorkSet.front(); 428683d2b0SHal Finkel WorkSet.erase(WorkSet.begin()); 438683d2b0SHal Finkel 4470573dcdSDavid Blaikie if (!Visited.insert(V).second) 4557f03ddaSHal Finkel continue; 4657f03ddaSHal Finkel 4757f03ddaSHal Finkel // If all uses of this value are ephemeral, then so is this value. 4857f03ddaSHal Finkel bool FoundNEUse = false; 4957f03ddaSHal Finkel for (const User *I : V->users()) 5057f03ddaSHal Finkel if (!EphValues.count(I)) { 5157f03ddaSHal Finkel FoundNEUse = true; 5257f03ddaSHal Finkel break; 5357f03ddaSHal Finkel } 5457f03ddaSHal Finkel 5557f03ddaSHal Finkel if (FoundNEUse) 5657f03ddaSHal Finkel continue; 5757f03ddaSHal Finkel 5857f03ddaSHal Finkel EphValues.insert(V); 5957f03ddaSHal Finkel DEBUG(dbgs() << "Ephemeral Value: " << *V << "\n"); 6057f03ddaSHal Finkel 6157f03ddaSHal Finkel if (const User *U = dyn_cast<User>(V)) 6257f03ddaSHal Finkel for (const Value *J : U->operands()) { 6357f03ddaSHal Finkel if (isSafeToSpeculativelyExecute(J)) 6457f03ddaSHal Finkel WorkSet.push_back(J); 6557f03ddaSHal Finkel } 6657f03ddaSHal Finkel } 6757f03ddaSHal Finkel } 6857f03ddaSHal Finkel 6957f03ddaSHal Finkel // Find all ephemeral values. 7066b3130cSChandler Carruth void CodeMetrics::collectEphemeralValues( 7166b3130cSChandler Carruth const Loop *L, AssumptionCache *AC, 7257f03ddaSHal Finkel SmallPtrSetImpl<const Value *> &EphValues) { 7357f03ddaSHal Finkel SmallVector<const Value *, 16> WorkSet; 7457f03ddaSHal Finkel 7566b3130cSChandler Carruth for (auto &AssumeVH : AC->assumptions()) { 7666b3130cSChandler Carruth if (!AssumeVH) 7766b3130cSChandler Carruth continue; 7866b3130cSChandler Carruth Instruction *I = cast<Instruction>(AssumeVH); 7966b3130cSChandler Carruth 8057f03ddaSHal Finkel // Filter out call sites outside of the loop so we don't to a function's 8157f03ddaSHal Finkel // worth of work for each of its loops (and, in the common case, ephemeral 8257f03ddaSHal Finkel // values in the loop are likely due to @llvm.assume calls in the loop). 8357f03ddaSHal Finkel if (!L->contains(I->getParent())) 8457f03ddaSHal Finkel continue; 8557f03ddaSHal Finkel 8657f03ddaSHal Finkel WorkSet.push_back(I); 8757f03ddaSHal Finkel } 8857f03ddaSHal Finkel 8957f03ddaSHal Finkel completeEphemeralValues(WorkSet, EphValues); 9057f03ddaSHal Finkel } 9157f03ddaSHal Finkel 9266b3130cSChandler Carruth void CodeMetrics::collectEphemeralValues( 9366b3130cSChandler Carruth const Function *F, AssumptionCache *AC, 9457f03ddaSHal Finkel SmallPtrSetImpl<const Value *> &EphValues) { 9557f03ddaSHal Finkel SmallVector<const Value *, 16> WorkSet; 9657f03ddaSHal Finkel 9766b3130cSChandler Carruth for (auto &AssumeVH : AC->assumptions()) { 9866b3130cSChandler Carruth if (!AssumeVH) 9966b3130cSChandler Carruth continue; 10066b3130cSChandler Carruth Instruction *I = cast<Instruction>(AssumeVH); 10166b3130cSChandler Carruth assert(I->getParent()->getParent() == F && 10266b3130cSChandler Carruth "Found assumption for the wrong function!"); 10357f03ddaSHal Finkel WorkSet.push_back(I); 10466b3130cSChandler Carruth } 10557f03ddaSHal Finkel 10657f03ddaSHal Finkel completeEphemeralValues(WorkSet, EphValues); 10757f03ddaSHal Finkel } 10857f03ddaSHal Finkel 1090539c071SChandler Carruth /// analyzeBasicBlock - Fill in the current structure with information gleaned 1100539c071SChandler Carruth /// from the specified block. 1110539c071SChandler Carruth void CodeMetrics::analyzeBasicBlock(const BasicBlock *BB, 11257f03ddaSHal Finkel const TargetTransformInfo &TTI, 11357f03ddaSHal Finkel SmallPtrSetImpl<const Value*> &EphValues) { 1140539c071SChandler Carruth ++NumBlocks; 1150539c071SChandler Carruth unsigned NumInstsBeforeThisBB = NumInsts; 1160539c071SChandler Carruth for (BasicBlock::const_iterator II = BB->begin(), E = BB->end(); 1170539c071SChandler Carruth II != E; ++II) { 11857f03ddaSHal Finkel // Skip ephemeral values. 11957f03ddaSHal Finkel if (EphValues.count(II)) 12057f03ddaSHal Finkel continue; 12157f03ddaSHal Finkel 1220539c071SChandler Carruth // Special handling for calls. 1230539c071SChandler Carruth if (isa<CallInst>(II) || isa<InvokeInst>(II)) { 1243c256fbfSChandler Carruth ImmutableCallSite CS(cast<Instruction>(II)); 1253c256fbfSChandler Carruth 1263c256fbfSChandler Carruth if (const Function *F = CS.getCalledFunction()) { 1273c256fbfSChandler Carruth // If a function is both internal and has a single use, then it is 1283c256fbfSChandler Carruth // extremely likely to get inlined in the future (it was probably 1293c256fbfSChandler Carruth // exposed by an interleaved devirtualization pass). 1303c256fbfSChandler Carruth if (!CS.isNoInline() && F->hasInternalLinkage() && F->hasOneUse()) 1313c256fbfSChandler Carruth ++NumInlineCandidates; 1323c256fbfSChandler Carruth 1333c256fbfSChandler Carruth // If this call is to function itself, then the function is recursive. 1343c256fbfSChandler Carruth // Inlining it into other functions is a bad idea, because this is 1353c256fbfSChandler Carruth // basically just a form of loop peeling, and our metrics aren't useful 1363c256fbfSChandler Carruth // for that case. 1373c256fbfSChandler Carruth if (F == BB->getParent()) 1383c256fbfSChandler Carruth isRecursive = true; 1393c256fbfSChandler Carruth 1400ba8db45SChandler Carruth if (TTI.isLoweredToCall(F)) 1410ba8db45SChandler Carruth ++NumCalls; 1420ba8db45SChandler Carruth } else { 1433c256fbfSChandler Carruth // We don't want inline asm to count as a call - that would prevent loop 1443c256fbfSChandler Carruth // unrolling. The argument setup cost is still real, though. 1453c256fbfSChandler Carruth if (!isa<InlineAsm>(CS.getCalledValue())) 1463c256fbfSChandler Carruth ++NumCalls; 1473c256fbfSChandler Carruth } 1483c256fbfSChandler Carruth } 1493c256fbfSChandler Carruth 1503c256fbfSChandler Carruth if (const AllocaInst *AI = dyn_cast<AllocaInst>(II)) { 1513c256fbfSChandler Carruth if (!AI->isStaticAlloca()) 1523c256fbfSChandler Carruth this->usesDynamicAlloca = true; 1533c256fbfSChandler Carruth } 1543c256fbfSChandler Carruth 1553c256fbfSChandler Carruth if (isa<ExtractElementInst>(II) || II->getType()->isVectorTy()) 1563c256fbfSChandler Carruth ++NumVectorInsts; 1573c256fbfSChandler Carruth 1584f6fb953SJames Molloy if (const CallInst *CI = dyn_cast<CallInst>(II)) 159576ef3c6SEli Bendersky if (CI->cannotDuplicate()) 1604f6fb953SJames Molloy notDuplicatable = true; 1614f6fb953SJames Molloy 1624f6fb953SJames Molloy if (const InvokeInst *InvI = dyn_cast<InvokeInst>(II)) 163576ef3c6SEli Bendersky if (InvI->cannotDuplicate()) 1644f6fb953SJames Molloy notDuplicatable = true; 1654f6fb953SJames Molloy 1660ba8db45SChandler Carruth NumInsts += TTI.getUserCost(&*II); 1673c256fbfSChandler Carruth } 1683c256fbfSChandler Carruth 1693c256fbfSChandler Carruth if (isa<ReturnInst>(BB->getTerminator())) 1703c256fbfSChandler Carruth ++NumRets; 1713c256fbfSChandler Carruth 1723c256fbfSChandler Carruth // We never want to inline functions that contain an indirectbr. This is 1733c256fbfSChandler Carruth // incorrect because all the blockaddress's (in static global initializers 1743c256fbfSChandler Carruth // for example) would be referring to the original function, and this indirect 1753c256fbfSChandler Carruth // jump would jump from the inlined copy of the function into the original 1763c256fbfSChandler Carruth // function which is extremely undefined behavior. 1773c256fbfSChandler Carruth // FIXME: This logic isn't really right; we can safely inline functions 1783c256fbfSChandler Carruth // with indirectbr's as long as no other function or global references the 1793c256fbfSChandler Carruth // blockaddress of a block within the current function. And as a QOI issue, 1803c256fbfSChandler Carruth // if someone is using a blockaddress without an indirectbr, and that 1813c256fbfSChandler Carruth // reference somehow ends up in another function or global, we probably 1823c256fbfSChandler Carruth // don't want to inline this function. 1834f6fb953SJames Molloy notDuplicatable |= isa<IndirectBrInst>(BB->getTerminator()); 1843c256fbfSChandler Carruth 1853c256fbfSChandler Carruth // Remember NumInsts for this BB. 1863c256fbfSChandler Carruth NumBBInsts[BB] = NumInsts - NumInstsBeforeThisBB; 1873c256fbfSChandler Carruth } 188