109467b48Spatrick //===- CodeMetrics.cpp - Code cost measurements ---------------------------===//
209467b48Spatrick //
309467b48Spatrick // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
409467b48Spatrick // See https://llvm.org/LICENSE.txt for license information.
509467b48Spatrick // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
609467b48Spatrick //
709467b48Spatrick //===----------------------------------------------------------------------===//
809467b48Spatrick //
909467b48Spatrick // This file implements code cost measurement utilities.
1009467b48Spatrick //
1109467b48Spatrick //===----------------------------------------------------------------------===//
1209467b48Spatrick
1309467b48Spatrick #include "llvm/Analysis/CodeMetrics.h"
14097a140dSpatrick #include "llvm/ADT/SmallPtrSet.h"
1509467b48Spatrick #include "llvm/Analysis/AssumptionCache.h"
1609467b48Spatrick #include "llvm/Analysis/LoopInfo.h"
1709467b48Spatrick #include "llvm/Analysis/TargetTransformInfo.h"
1809467b48Spatrick #include "llvm/IR/Function.h"
1909467b48Spatrick #include "llvm/Support/Debug.h"
2073471bf0Spatrick #include "llvm/Support/InstructionCost.h"
2109467b48Spatrick
2209467b48Spatrick #define DEBUG_TYPE "code-metrics"
2309467b48Spatrick
2409467b48Spatrick using namespace llvm;
2509467b48Spatrick
2609467b48Spatrick static void
appendSpeculatableOperands(const Value * V,SmallPtrSetImpl<const Value * > & Visited,SmallVectorImpl<const Value * > & Worklist)2709467b48Spatrick appendSpeculatableOperands(const Value *V,
2809467b48Spatrick SmallPtrSetImpl<const Value *> &Visited,
2909467b48Spatrick SmallVectorImpl<const Value *> &Worklist) {
3009467b48Spatrick const User *U = dyn_cast<User>(V);
3109467b48Spatrick if (!U)
3209467b48Spatrick return;
3309467b48Spatrick
3409467b48Spatrick for (const Value *Operand : U->operands())
3509467b48Spatrick if (Visited.insert(Operand).second)
36*d415bd75Srobert if (const auto *I = dyn_cast<Instruction>(Operand))
37*d415bd75Srobert if (!I->mayHaveSideEffects() && !I->isTerminator())
38*d415bd75Srobert Worklist.push_back(I);
3909467b48Spatrick }
4009467b48Spatrick
completeEphemeralValues(SmallPtrSetImpl<const Value * > & Visited,SmallVectorImpl<const Value * > & Worklist,SmallPtrSetImpl<const Value * > & EphValues)4109467b48Spatrick static void completeEphemeralValues(SmallPtrSetImpl<const Value *> &Visited,
4209467b48Spatrick SmallVectorImpl<const Value *> &Worklist,
4309467b48Spatrick SmallPtrSetImpl<const Value *> &EphValues) {
4409467b48Spatrick // Note: We don't speculate PHIs here, so we'll miss instruction chains kept
4509467b48Spatrick // alive only by ephemeral values.
4609467b48Spatrick
4709467b48Spatrick // Walk the worklist using an index but without caching the size so we can
4809467b48Spatrick // append more entries as we process the worklist. This forms a queue without
4909467b48Spatrick // quadratic behavior by just leaving processed nodes at the head of the
5009467b48Spatrick // worklist forever.
5109467b48Spatrick for (int i = 0; i < (int)Worklist.size(); ++i) {
5209467b48Spatrick const Value *V = Worklist[i];
5309467b48Spatrick
5409467b48Spatrick assert(Visited.count(V) &&
5509467b48Spatrick "Failed to add a worklist entry to our visited set!");
5609467b48Spatrick
5709467b48Spatrick // If all uses of this value are ephemeral, then so is this value.
5809467b48Spatrick if (!all_of(V->users(), [&](const User *U) { return EphValues.count(U); }))
5909467b48Spatrick continue;
6009467b48Spatrick
6109467b48Spatrick EphValues.insert(V);
6209467b48Spatrick LLVM_DEBUG(dbgs() << "Ephemeral Value: " << *V << "\n");
6309467b48Spatrick
6409467b48Spatrick // Append any more operands to consider.
6509467b48Spatrick appendSpeculatableOperands(V, Visited, Worklist);
6609467b48Spatrick }
6709467b48Spatrick }
6809467b48Spatrick
6909467b48Spatrick // Find all ephemeral values.
collectEphemeralValues(const Loop * L,AssumptionCache * AC,SmallPtrSetImpl<const Value * > & EphValues)7009467b48Spatrick void CodeMetrics::collectEphemeralValues(
7109467b48Spatrick const Loop *L, AssumptionCache *AC,
7209467b48Spatrick SmallPtrSetImpl<const Value *> &EphValues) {
7309467b48Spatrick SmallPtrSet<const Value *, 32> Visited;
7409467b48Spatrick SmallVector<const Value *, 16> Worklist;
7509467b48Spatrick
7609467b48Spatrick for (auto &AssumeVH : AC->assumptions()) {
7709467b48Spatrick if (!AssumeVH)
7809467b48Spatrick continue;
7909467b48Spatrick Instruction *I = cast<Instruction>(AssumeVH);
8009467b48Spatrick
8109467b48Spatrick // Filter out call sites outside of the loop so we don't do a function's
8209467b48Spatrick // worth of work for each of its loops (and, in the common case, ephemeral
8309467b48Spatrick // values in the loop are likely due to @llvm.assume calls in the loop).
8409467b48Spatrick if (!L->contains(I->getParent()))
8509467b48Spatrick continue;
8609467b48Spatrick
8709467b48Spatrick if (EphValues.insert(I).second)
8809467b48Spatrick appendSpeculatableOperands(I, Visited, Worklist);
8909467b48Spatrick }
9009467b48Spatrick
9109467b48Spatrick completeEphemeralValues(Visited, Worklist, EphValues);
9209467b48Spatrick }
9309467b48Spatrick
collectEphemeralValues(const Function * F,AssumptionCache * AC,SmallPtrSetImpl<const Value * > & EphValues)9409467b48Spatrick void CodeMetrics::collectEphemeralValues(
9509467b48Spatrick const Function *F, AssumptionCache *AC,
9609467b48Spatrick SmallPtrSetImpl<const Value *> &EphValues) {
9709467b48Spatrick SmallPtrSet<const Value *, 32> Visited;
9809467b48Spatrick SmallVector<const Value *, 16> Worklist;
9909467b48Spatrick
10009467b48Spatrick for (auto &AssumeVH : AC->assumptions()) {
10109467b48Spatrick if (!AssumeVH)
10209467b48Spatrick continue;
10309467b48Spatrick Instruction *I = cast<Instruction>(AssumeVH);
10409467b48Spatrick assert(I->getParent()->getParent() == F &&
10509467b48Spatrick "Found assumption for the wrong function!");
10609467b48Spatrick
10709467b48Spatrick if (EphValues.insert(I).second)
10809467b48Spatrick appendSpeculatableOperands(I, Visited, Worklist);
10909467b48Spatrick }
11009467b48Spatrick
11109467b48Spatrick completeEphemeralValues(Visited, Worklist, EphValues);
11209467b48Spatrick }
11309467b48Spatrick
11409467b48Spatrick /// Fill in the current structure with information gleaned from the specified
11509467b48Spatrick /// block.
analyzeBasicBlock(const BasicBlock * BB,const TargetTransformInfo & TTI,const SmallPtrSetImpl<const Value * > & EphValues,bool PrepareForLTO)11673471bf0Spatrick void CodeMetrics::analyzeBasicBlock(
11773471bf0Spatrick const BasicBlock *BB, const TargetTransformInfo &TTI,
11873471bf0Spatrick const SmallPtrSetImpl<const Value *> &EphValues, bool PrepareForLTO) {
11909467b48Spatrick ++NumBlocks;
12073471bf0Spatrick InstructionCost NumInstsBeforeThisBB = NumInsts;
12109467b48Spatrick for (const Instruction &I : *BB) {
12209467b48Spatrick // Skip ephemeral values.
12309467b48Spatrick if (EphValues.count(&I))
12409467b48Spatrick continue;
12509467b48Spatrick
12609467b48Spatrick // Special handling for calls.
12709467b48Spatrick if (const auto *Call = dyn_cast<CallBase>(&I)) {
12809467b48Spatrick if (const Function *F = Call->getCalledFunction()) {
12973471bf0Spatrick bool IsLoweredToCall = TTI.isLoweredToCall(F);
13009467b48Spatrick // If a function is both internal and has a single use, then it is
13109467b48Spatrick // extremely likely to get inlined in the future (it was probably
13209467b48Spatrick // exposed by an interleaved devirtualization pass).
13373471bf0Spatrick // When preparing for LTO, liberally consider calls as inline
13473471bf0Spatrick // candidates.
13573471bf0Spatrick if (!Call->isNoInline() && IsLoweredToCall &&
136*d415bd75Srobert ((F->hasInternalLinkage() && F->hasOneLiveUse()) ||
137*d415bd75Srobert PrepareForLTO)) {
13809467b48Spatrick ++NumInlineCandidates;
13973471bf0Spatrick }
14009467b48Spatrick
14109467b48Spatrick // If this call is to function itself, then the function is recursive.
14209467b48Spatrick // Inlining it into other functions is a bad idea, because this is
14309467b48Spatrick // basically just a form of loop peeling, and our metrics aren't useful
14409467b48Spatrick // for that case.
14509467b48Spatrick if (F == BB->getParent())
14609467b48Spatrick isRecursive = true;
14709467b48Spatrick
14873471bf0Spatrick if (IsLoweredToCall)
14909467b48Spatrick ++NumCalls;
15009467b48Spatrick } else {
15109467b48Spatrick // We don't want inline asm to count as a call - that would prevent loop
15209467b48Spatrick // unrolling. The argument setup cost is still real, though.
15309467b48Spatrick if (!Call->isInlineAsm())
15409467b48Spatrick ++NumCalls;
15509467b48Spatrick }
15609467b48Spatrick }
15709467b48Spatrick
15809467b48Spatrick if (const AllocaInst *AI = dyn_cast<AllocaInst>(&I)) {
15909467b48Spatrick if (!AI->isStaticAlloca())
16009467b48Spatrick this->usesDynamicAlloca = true;
16109467b48Spatrick }
16209467b48Spatrick
16309467b48Spatrick if (isa<ExtractElementInst>(I) || I.getType()->isVectorTy())
16409467b48Spatrick ++NumVectorInsts;
16509467b48Spatrick
16609467b48Spatrick if (I.getType()->isTokenTy() && I.isUsedOutsideOfBlock(BB))
16709467b48Spatrick notDuplicatable = true;
16809467b48Spatrick
16909467b48Spatrick if (const CallInst *CI = dyn_cast<CallInst>(&I)) {
17009467b48Spatrick if (CI->cannotDuplicate())
17109467b48Spatrick notDuplicatable = true;
17209467b48Spatrick if (CI->isConvergent())
17309467b48Spatrick convergent = true;
17409467b48Spatrick }
17509467b48Spatrick
17609467b48Spatrick if (const InvokeInst *InvI = dyn_cast<InvokeInst>(&I))
17709467b48Spatrick if (InvI->cannotDuplicate())
17809467b48Spatrick notDuplicatable = true;
17909467b48Spatrick
180*d415bd75Srobert NumInsts += TTI.getInstructionCost(&I, TargetTransformInfo::TCK_CodeSize);
18109467b48Spatrick }
18209467b48Spatrick
18309467b48Spatrick if (isa<ReturnInst>(BB->getTerminator()))
18409467b48Spatrick ++NumRets;
18509467b48Spatrick
18609467b48Spatrick // We never want to inline functions that contain an indirectbr. This is
18709467b48Spatrick // incorrect because all the blockaddress's (in static global initializers
18809467b48Spatrick // for example) would be referring to the original function, and this indirect
18909467b48Spatrick // jump would jump from the inlined copy of the function into the original
19009467b48Spatrick // function which is extremely undefined behavior.
19109467b48Spatrick // FIXME: This logic isn't really right; we can safely inline functions
19209467b48Spatrick // with indirectbr's as long as no other function or global references the
19309467b48Spatrick // blockaddress of a block within the current function. And as a QOI issue,
19409467b48Spatrick // if someone is using a blockaddress without an indirectbr, and that
19509467b48Spatrick // reference somehow ends up in another function or global, we probably
19609467b48Spatrick // don't want to inline this function.
19709467b48Spatrick notDuplicatable |= isa<IndirectBrInst>(BB->getTerminator());
19809467b48Spatrick
19909467b48Spatrick // Remember NumInsts for this BB.
200*d415bd75Srobert InstructionCost NumInstsThisBB = NumInsts - NumInstsBeforeThisBB;
201*d415bd75Srobert NumBBInsts[BB] = NumInstsThisBB;
20209467b48Spatrick }
203