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 1457f03ddaSHal Finkel #include "llvm/Analysis/AssumptionTracker.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" 2457f03ddaSHal Finkel 2557f03ddaSHal Finkel #define DEBUG_TYPE "code-metrics" 263c256fbfSChandler Carruth 273c256fbfSChandler Carruth using namespace llvm; 283c256fbfSChandler Carruth 2957f03ddaSHal Finkel static void completeEphemeralValues(SmallVector<const Value *, 16> &WorkSet, 3057f03ddaSHal Finkel SmallPtrSetImpl<const Value*> &EphValues) { 3157f03ddaSHal Finkel SmallPtrSet<const Value *, 32> Visited; 3257f03ddaSHal Finkel 3357f03ddaSHal Finkel // Make sure that all of the items in WorkSet are in our EphValues set. 3457f03ddaSHal Finkel EphValues.insert(WorkSet.begin(), WorkSet.end()); 3557f03ddaSHal Finkel 3657f03ddaSHal Finkel // Note: We don't speculate PHIs here, so we'll miss instruction chains kept 3757f03ddaSHal Finkel // alive only by ephemeral values. 3857f03ddaSHal Finkel 3957f03ddaSHal Finkel while (!WorkSet.empty()) { 408683d2b0SHal Finkel const Value *V = WorkSet.front(); 418683d2b0SHal Finkel WorkSet.erase(WorkSet.begin()); 428683d2b0SHal Finkel 43*70573dcdSDavid Blaikie if (!Visited.insert(V).second) 4457f03ddaSHal Finkel continue; 4557f03ddaSHal Finkel 4657f03ddaSHal Finkel // If all uses of this value are ephemeral, then so is this value. 4757f03ddaSHal Finkel bool FoundNEUse = false; 4857f03ddaSHal Finkel for (const User *I : V->users()) 4957f03ddaSHal Finkel if (!EphValues.count(I)) { 5057f03ddaSHal Finkel FoundNEUse = true; 5157f03ddaSHal Finkel break; 5257f03ddaSHal Finkel } 5357f03ddaSHal Finkel 5457f03ddaSHal Finkel if (FoundNEUse) 5557f03ddaSHal Finkel continue; 5657f03ddaSHal Finkel 5757f03ddaSHal Finkel EphValues.insert(V); 5857f03ddaSHal Finkel DEBUG(dbgs() << "Ephemeral Value: " << *V << "\n"); 5957f03ddaSHal Finkel 6057f03ddaSHal Finkel if (const User *U = dyn_cast<User>(V)) 6157f03ddaSHal Finkel for (const Value *J : U->operands()) { 6257f03ddaSHal Finkel if (isSafeToSpeculativelyExecute(J)) 6357f03ddaSHal Finkel WorkSet.push_back(J); 6457f03ddaSHal Finkel } 6557f03ddaSHal Finkel } 6657f03ddaSHal Finkel } 6757f03ddaSHal Finkel 6857f03ddaSHal Finkel // Find all ephemeral values. 6957f03ddaSHal Finkel void CodeMetrics::collectEphemeralValues(const Loop *L, AssumptionTracker *AT, 7057f03ddaSHal Finkel SmallPtrSetImpl<const Value*> &EphValues) { 7157f03ddaSHal Finkel SmallVector<const Value *, 16> WorkSet; 7257f03ddaSHal Finkel 7357f03ddaSHal Finkel for (auto &I : AT->assumptions(L->getHeader()->getParent())) { 7457f03ddaSHal Finkel // Filter out call sites outside of the loop so we don't to a function's 7557f03ddaSHal Finkel // worth of work for each of its loops (and, in the common case, ephemeral 7657f03ddaSHal Finkel // values in the loop are likely due to @llvm.assume calls in the loop). 7757f03ddaSHal Finkel if (!L->contains(I->getParent())) 7857f03ddaSHal Finkel continue; 7957f03ddaSHal Finkel 8057f03ddaSHal Finkel WorkSet.push_back(I); 8157f03ddaSHal Finkel } 8257f03ddaSHal Finkel 8357f03ddaSHal Finkel completeEphemeralValues(WorkSet, EphValues); 8457f03ddaSHal Finkel } 8557f03ddaSHal Finkel 8657f03ddaSHal Finkel void CodeMetrics::collectEphemeralValues(const Function *F, AssumptionTracker *AT, 8757f03ddaSHal Finkel SmallPtrSetImpl<const Value*> &EphValues) { 8857f03ddaSHal Finkel SmallVector<const Value *, 16> WorkSet; 8957f03ddaSHal Finkel 9057f03ddaSHal Finkel for (auto &I : AT->assumptions(const_cast<Function*>(F))) 9157f03ddaSHal Finkel WorkSet.push_back(I); 9257f03ddaSHal Finkel 9357f03ddaSHal Finkel completeEphemeralValues(WorkSet, EphValues); 9457f03ddaSHal Finkel } 9557f03ddaSHal Finkel 960539c071SChandler Carruth /// analyzeBasicBlock - Fill in the current structure with information gleaned 970539c071SChandler Carruth /// from the specified block. 980539c071SChandler Carruth void CodeMetrics::analyzeBasicBlock(const BasicBlock *BB, 9957f03ddaSHal Finkel const TargetTransformInfo &TTI, 10057f03ddaSHal Finkel SmallPtrSetImpl<const Value*> &EphValues) { 1010539c071SChandler Carruth ++NumBlocks; 1020539c071SChandler Carruth unsigned NumInstsBeforeThisBB = NumInsts; 1030539c071SChandler Carruth for (BasicBlock::const_iterator II = BB->begin(), E = BB->end(); 1040539c071SChandler Carruth II != E; ++II) { 10557f03ddaSHal Finkel // Skip ephemeral values. 10657f03ddaSHal Finkel if (EphValues.count(II)) 10757f03ddaSHal Finkel continue; 10857f03ddaSHal Finkel 1090539c071SChandler Carruth // Special handling for calls. 1100539c071SChandler Carruth if (isa<CallInst>(II) || isa<InvokeInst>(II)) { 1113c256fbfSChandler Carruth ImmutableCallSite CS(cast<Instruction>(II)); 1123c256fbfSChandler Carruth 1133c256fbfSChandler Carruth if (const Function *F = CS.getCalledFunction()) { 1143c256fbfSChandler Carruth // If a function is both internal and has a single use, then it is 1153c256fbfSChandler Carruth // extremely likely to get inlined in the future (it was probably 1163c256fbfSChandler Carruth // exposed by an interleaved devirtualization pass). 1173c256fbfSChandler Carruth if (!CS.isNoInline() && F->hasInternalLinkage() && F->hasOneUse()) 1183c256fbfSChandler Carruth ++NumInlineCandidates; 1193c256fbfSChandler Carruth 1203c256fbfSChandler Carruth // If this call is to function itself, then the function is recursive. 1213c256fbfSChandler Carruth // Inlining it into other functions is a bad idea, because this is 1223c256fbfSChandler Carruth // basically just a form of loop peeling, and our metrics aren't useful 1233c256fbfSChandler Carruth // for that case. 1243c256fbfSChandler Carruth if (F == BB->getParent()) 1253c256fbfSChandler Carruth isRecursive = true; 1263c256fbfSChandler Carruth 1270ba8db45SChandler Carruth if (TTI.isLoweredToCall(F)) 1280ba8db45SChandler Carruth ++NumCalls; 1290ba8db45SChandler Carruth } else { 1303c256fbfSChandler Carruth // We don't want inline asm to count as a call - that would prevent loop 1313c256fbfSChandler Carruth // unrolling. The argument setup cost is still real, though. 1323c256fbfSChandler Carruth if (!isa<InlineAsm>(CS.getCalledValue())) 1333c256fbfSChandler Carruth ++NumCalls; 1343c256fbfSChandler Carruth } 1353c256fbfSChandler Carruth } 1363c256fbfSChandler Carruth 1373c256fbfSChandler Carruth if (const AllocaInst *AI = dyn_cast<AllocaInst>(II)) { 1383c256fbfSChandler Carruth if (!AI->isStaticAlloca()) 1393c256fbfSChandler Carruth this->usesDynamicAlloca = true; 1403c256fbfSChandler Carruth } 1413c256fbfSChandler Carruth 1423c256fbfSChandler Carruth if (isa<ExtractElementInst>(II) || II->getType()->isVectorTy()) 1433c256fbfSChandler Carruth ++NumVectorInsts; 1443c256fbfSChandler Carruth 1454f6fb953SJames Molloy if (const CallInst *CI = dyn_cast<CallInst>(II)) 146576ef3c6SEli Bendersky if (CI->cannotDuplicate()) 1474f6fb953SJames Molloy notDuplicatable = true; 1484f6fb953SJames Molloy 1494f6fb953SJames Molloy if (const InvokeInst *InvI = dyn_cast<InvokeInst>(II)) 150576ef3c6SEli Bendersky if (InvI->cannotDuplicate()) 1514f6fb953SJames Molloy notDuplicatable = true; 1524f6fb953SJames Molloy 1530ba8db45SChandler Carruth NumInsts += TTI.getUserCost(&*II); 1543c256fbfSChandler Carruth } 1553c256fbfSChandler Carruth 1563c256fbfSChandler Carruth if (isa<ReturnInst>(BB->getTerminator())) 1573c256fbfSChandler Carruth ++NumRets; 1583c256fbfSChandler Carruth 1593c256fbfSChandler Carruth // We never want to inline functions that contain an indirectbr. This is 1603c256fbfSChandler Carruth // incorrect because all the blockaddress's (in static global initializers 1613c256fbfSChandler Carruth // for example) would be referring to the original function, and this indirect 1623c256fbfSChandler Carruth // jump would jump from the inlined copy of the function into the original 1633c256fbfSChandler Carruth // function which is extremely undefined behavior. 1643c256fbfSChandler Carruth // FIXME: This logic isn't really right; we can safely inline functions 1653c256fbfSChandler Carruth // with indirectbr's as long as no other function or global references the 1663c256fbfSChandler Carruth // blockaddress of a block within the current function. And as a QOI issue, 1673c256fbfSChandler Carruth // if someone is using a blockaddress without an indirectbr, and that 1683c256fbfSChandler Carruth // reference somehow ends up in another function or global, we probably 1693c256fbfSChandler Carruth // don't want to inline this function. 1704f6fb953SJames Molloy notDuplicatable |= isa<IndirectBrInst>(BB->getTerminator()); 1713c256fbfSChandler Carruth 1723c256fbfSChandler Carruth // Remember NumInsts for this BB. 1733c256fbfSChandler Carruth NumBBInsts[BB] = NumInsts - NumInstsBeforeThisBB; 1743c256fbfSChandler Carruth } 175