1*9880d681SAndroid Build Coastguard Worker //===- CodeMetrics.cpp - Code cost measurements ---------------------------===//
2*9880d681SAndroid Build Coastguard Worker //
3*9880d681SAndroid Build Coastguard Worker // The LLVM Compiler Infrastructure
4*9880d681SAndroid Build Coastguard Worker //
5*9880d681SAndroid Build Coastguard Worker // This file is distributed under the University of Illinois Open Source
6*9880d681SAndroid Build Coastguard Worker // License. See LICENSE.TXT for details.
7*9880d681SAndroid Build Coastguard Worker //
8*9880d681SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===//
9*9880d681SAndroid Build Coastguard Worker //
10*9880d681SAndroid Build Coastguard Worker // This file implements code cost measurement utilities.
11*9880d681SAndroid Build Coastguard Worker //
12*9880d681SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===//
13*9880d681SAndroid Build Coastguard Worker
14*9880d681SAndroid Build Coastguard Worker #include "llvm/Analysis/AssumptionCache.h"
15*9880d681SAndroid Build Coastguard Worker #include "llvm/Analysis/CodeMetrics.h"
16*9880d681SAndroid Build Coastguard Worker #include "llvm/Analysis/LoopInfo.h"
17*9880d681SAndroid Build Coastguard Worker #include "llvm/Analysis/TargetTransformInfo.h"
18*9880d681SAndroid Build Coastguard Worker #include "llvm/Analysis/ValueTracking.h"
19*9880d681SAndroid Build Coastguard Worker #include "llvm/IR/CallSite.h"
20*9880d681SAndroid Build Coastguard Worker #include "llvm/IR/DataLayout.h"
21*9880d681SAndroid Build Coastguard Worker #include "llvm/IR/Function.h"
22*9880d681SAndroid Build Coastguard Worker #include "llvm/IR/IntrinsicInst.h"
23*9880d681SAndroid Build Coastguard Worker #include "llvm/Support/Debug.h"
24*9880d681SAndroid Build Coastguard Worker #include "llvm/Support/raw_ostream.h"
25*9880d681SAndroid Build Coastguard Worker
26*9880d681SAndroid Build Coastguard Worker #define DEBUG_TYPE "code-metrics"
27*9880d681SAndroid Build Coastguard Worker
28*9880d681SAndroid Build Coastguard Worker using namespace llvm;
29*9880d681SAndroid Build Coastguard Worker
completeEphemeralValues(SmallVector<const Value *,16> & WorkSet,SmallPtrSetImpl<const Value * > & EphValues)30*9880d681SAndroid Build Coastguard Worker static void completeEphemeralValues(SmallVector<const Value *, 16> &WorkSet,
31*9880d681SAndroid Build Coastguard Worker SmallPtrSetImpl<const Value*> &EphValues) {
32*9880d681SAndroid Build Coastguard Worker SmallPtrSet<const Value *, 32> Visited;
33*9880d681SAndroid Build Coastguard Worker
34*9880d681SAndroid Build Coastguard Worker // Make sure that all of the items in WorkSet are in our EphValues set.
35*9880d681SAndroid Build Coastguard Worker EphValues.insert(WorkSet.begin(), WorkSet.end());
36*9880d681SAndroid Build Coastguard Worker
37*9880d681SAndroid Build Coastguard Worker // Note: We don't speculate PHIs here, so we'll miss instruction chains kept
38*9880d681SAndroid Build Coastguard Worker // alive only by ephemeral values.
39*9880d681SAndroid Build Coastguard Worker
40*9880d681SAndroid Build Coastguard Worker while (!WorkSet.empty()) {
41*9880d681SAndroid Build Coastguard Worker const Value *V = WorkSet.front();
42*9880d681SAndroid Build Coastguard Worker WorkSet.erase(WorkSet.begin());
43*9880d681SAndroid Build Coastguard Worker
44*9880d681SAndroid Build Coastguard Worker if (!Visited.insert(V).second)
45*9880d681SAndroid Build Coastguard Worker continue;
46*9880d681SAndroid Build Coastguard Worker
47*9880d681SAndroid Build Coastguard Worker // If all uses of this value are ephemeral, then so is this value.
48*9880d681SAndroid Build Coastguard Worker if (!std::all_of(V->user_begin(), V->user_end(),
49*9880d681SAndroid Build Coastguard Worker [&](const User *U) { return EphValues.count(U); }))
50*9880d681SAndroid Build Coastguard Worker continue;
51*9880d681SAndroid Build Coastguard Worker
52*9880d681SAndroid Build Coastguard Worker EphValues.insert(V);
53*9880d681SAndroid Build Coastguard Worker DEBUG(dbgs() << "Ephemeral Value: " << *V << "\n");
54*9880d681SAndroid Build Coastguard Worker
55*9880d681SAndroid Build Coastguard Worker if (const User *U = dyn_cast<User>(V))
56*9880d681SAndroid Build Coastguard Worker for (const Value *J : U->operands()) {
57*9880d681SAndroid Build Coastguard Worker if (isSafeToSpeculativelyExecute(J))
58*9880d681SAndroid Build Coastguard Worker WorkSet.push_back(J);
59*9880d681SAndroid Build Coastguard Worker }
60*9880d681SAndroid Build Coastguard Worker }
61*9880d681SAndroid Build Coastguard Worker }
62*9880d681SAndroid Build Coastguard Worker
63*9880d681SAndroid Build Coastguard Worker // Find all ephemeral values.
collectEphemeralValues(const Loop * L,AssumptionCache * AC,SmallPtrSetImpl<const Value * > & EphValues)64*9880d681SAndroid Build Coastguard Worker void CodeMetrics::collectEphemeralValues(
65*9880d681SAndroid Build Coastguard Worker const Loop *L, AssumptionCache *AC,
66*9880d681SAndroid Build Coastguard Worker SmallPtrSetImpl<const Value *> &EphValues) {
67*9880d681SAndroid Build Coastguard Worker SmallVector<const Value *, 16> WorkSet;
68*9880d681SAndroid Build Coastguard Worker
69*9880d681SAndroid Build Coastguard Worker for (auto &AssumeVH : AC->assumptions()) {
70*9880d681SAndroid Build Coastguard Worker if (!AssumeVH)
71*9880d681SAndroid Build Coastguard Worker continue;
72*9880d681SAndroid Build Coastguard Worker Instruction *I = cast<Instruction>(AssumeVH);
73*9880d681SAndroid Build Coastguard Worker
74*9880d681SAndroid Build Coastguard Worker // Filter out call sites outside of the loop so we don't to a function's
75*9880d681SAndroid Build Coastguard Worker // worth of work for each of its loops (and, in the common case, ephemeral
76*9880d681SAndroid Build Coastguard Worker // values in the loop are likely due to @llvm.assume calls in the loop).
77*9880d681SAndroid Build Coastguard Worker if (!L->contains(I->getParent()))
78*9880d681SAndroid Build Coastguard Worker continue;
79*9880d681SAndroid Build Coastguard Worker
80*9880d681SAndroid Build Coastguard Worker WorkSet.push_back(I);
81*9880d681SAndroid Build Coastguard Worker }
82*9880d681SAndroid Build Coastguard Worker
83*9880d681SAndroid Build Coastguard Worker completeEphemeralValues(WorkSet, EphValues);
84*9880d681SAndroid Build Coastguard Worker }
85*9880d681SAndroid Build Coastguard Worker
collectEphemeralValues(const Function * F,AssumptionCache * AC,SmallPtrSetImpl<const Value * > & EphValues)86*9880d681SAndroid Build Coastguard Worker void CodeMetrics::collectEphemeralValues(
87*9880d681SAndroid Build Coastguard Worker const Function *F, AssumptionCache *AC,
88*9880d681SAndroid Build Coastguard Worker SmallPtrSetImpl<const Value *> &EphValues) {
89*9880d681SAndroid Build Coastguard Worker SmallVector<const Value *, 16> WorkSet;
90*9880d681SAndroid Build Coastguard Worker
91*9880d681SAndroid Build Coastguard Worker for (auto &AssumeVH : AC->assumptions()) {
92*9880d681SAndroid Build Coastguard Worker if (!AssumeVH)
93*9880d681SAndroid Build Coastguard Worker continue;
94*9880d681SAndroid Build Coastguard Worker Instruction *I = cast<Instruction>(AssumeVH);
95*9880d681SAndroid Build Coastguard Worker assert(I->getParent()->getParent() == F &&
96*9880d681SAndroid Build Coastguard Worker "Found assumption for the wrong function!");
97*9880d681SAndroid Build Coastguard Worker WorkSet.push_back(I);
98*9880d681SAndroid Build Coastguard Worker }
99*9880d681SAndroid Build Coastguard Worker
100*9880d681SAndroid Build Coastguard Worker completeEphemeralValues(WorkSet, EphValues);
101*9880d681SAndroid Build Coastguard Worker }
102*9880d681SAndroid Build Coastguard Worker
103*9880d681SAndroid Build Coastguard Worker /// Fill in the current structure with information gleaned from the specified
104*9880d681SAndroid Build Coastguard Worker /// block.
analyzeBasicBlock(const BasicBlock * BB,const TargetTransformInfo & TTI,SmallPtrSetImpl<const Value * > & EphValues)105*9880d681SAndroid Build Coastguard Worker void CodeMetrics::analyzeBasicBlock(const BasicBlock *BB,
106*9880d681SAndroid Build Coastguard Worker const TargetTransformInfo &TTI,
107*9880d681SAndroid Build Coastguard Worker SmallPtrSetImpl<const Value*> &EphValues) {
108*9880d681SAndroid Build Coastguard Worker ++NumBlocks;
109*9880d681SAndroid Build Coastguard Worker unsigned NumInstsBeforeThisBB = NumInsts;
110*9880d681SAndroid Build Coastguard Worker for (const Instruction &I : *BB) {
111*9880d681SAndroid Build Coastguard Worker // Skip ephemeral values.
112*9880d681SAndroid Build Coastguard Worker if (EphValues.count(&I))
113*9880d681SAndroid Build Coastguard Worker continue;
114*9880d681SAndroid Build Coastguard Worker
115*9880d681SAndroid Build Coastguard Worker // Special handling for calls.
116*9880d681SAndroid Build Coastguard Worker if (isa<CallInst>(I) || isa<InvokeInst>(I)) {
117*9880d681SAndroid Build Coastguard Worker ImmutableCallSite CS(&I);
118*9880d681SAndroid Build Coastguard Worker
119*9880d681SAndroid Build Coastguard Worker if (const Function *F = CS.getCalledFunction()) {
120*9880d681SAndroid Build Coastguard Worker // If a function is both internal and has a single use, then it is
121*9880d681SAndroid Build Coastguard Worker // extremely likely to get inlined in the future (it was probably
122*9880d681SAndroid Build Coastguard Worker // exposed by an interleaved devirtualization pass).
123*9880d681SAndroid Build Coastguard Worker if (!CS.isNoInline() && F->hasInternalLinkage() && F->hasOneUse())
124*9880d681SAndroid Build Coastguard Worker ++NumInlineCandidates;
125*9880d681SAndroid Build Coastguard Worker
126*9880d681SAndroid Build Coastguard Worker // If this call is to function itself, then the function is recursive.
127*9880d681SAndroid Build Coastguard Worker // Inlining it into other functions is a bad idea, because this is
128*9880d681SAndroid Build Coastguard Worker // basically just a form of loop peeling, and our metrics aren't useful
129*9880d681SAndroid Build Coastguard Worker // for that case.
130*9880d681SAndroid Build Coastguard Worker if (F == BB->getParent())
131*9880d681SAndroid Build Coastguard Worker isRecursive = true;
132*9880d681SAndroid Build Coastguard Worker
133*9880d681SAndroid Build Coastguard Worker if (TTI.isLoweredToCall(F))
134*9880d681SAndroid Build Coastguard Worker ++NumCalls;
135*9880d681SAndroid Build Coastguard Worker } else {
136*9880d681SAndroid Build Coastguard Worker // We don't want inline asm to count as a call - that would prevent loop
137*9880d681SAndroid Build Coastguard Worker // unrolling. The argument setup cost is still real, though.
138*9880d681SAndroid Build Coastguard Worker if (!isa<InlineAsm>(CS.getCalledValue()))
139*9880d681SAndroid Build Coastguard Worker ++NumCalls;
140*9880d681SAndroid Build Coastguard Worker }
141*9880d681SAndroid Build Coastguard Worker }
142*9880d681SAndroid Build Coastguard Worker
143*9880d681SAndroid Build Coastguard Worker if (const AllocaInst *AI = dyn_cast<AllocaInst>(&I)) {
144*9880d681SAndroid Build Coastguard Worker if (!AI->isStaticAlloca())
145*9880d681SAndroid Build Coastguard Worker this->usesDynamicAlloca = true;
146*9880d681SAndroid Build Coastguard Worker }
147*9880d681SAndroid Build Coastguard Worker
148*9880d681SAndroid Build Coastguard Worker if (isa<ExtractElementInst>(I) || I.getType()->isVectorTy())
149*9880d681SAndroid Build Coastguard Worker ++NumVectorInsts;
150*9880d681SAndroid Build Coastguard Worker
151*9880d681SAndroid Build Coastguard Worker if (I.getType()->isTokenTy() && I.isUsedOutsideOfBlock(BB))
152*9880d681SAndroid Build Coastguard Worker notDuplicatable = true;
153*9880d681SAndroid Build Coastguard Worker
154*9880d681SAndroid Build Coastguard Worker if (const CallInst *CI = dyn_cast<CallInst>(&I)) {
155*9880d681SAndroid Build Coastguard Worker if (CI->cannotDuplicate())
156*9880d681SAndroid Build Coastguard Worker notDuplicatable = true;
157*9880d681SAndroid Build Coastguard Worker if (CI->isConvergent())
158*9880d681SAndroid Build Coastguard Worker convergent = true;
159*9880d681SAndroid Build Coastguard Worker }
160*9880d681SAndroid Build Coastguard Worker
161*9880d681SAndroid Build Coastguard Worker if (const InvokeInst *InvI = dyn_cast<InvokeInst>(&I))
162*9880d681SAndroid Build Coastguard Worker if (InvI->cannotDuplicate())
163*9880d681SAndroid Build Coastguard Worker notDuplicatable = true;
164*9880d681SAndroid Build Coastguard Worker
165*9880d681SAndroid Build Coastguard Worker NumInsts += TTI.getUserCost(&I);
166*9880d681SAndroid Build Coastguard Worker }
167*9880d681SAndroid Build Coastguard Worker
168*9880d681SAndroid Build Coastguard Worker if (isa<ReturnInst>(BB->getTerminator()))
169*9880d681SAndroid Build Coastguard Worker ++NumRets;
170*9880d681SAndroid Build Coastguard Worker
171*9880d681SAndroid Build Coastguard Worker // We never want to inline functions that contain an indirectbr. This is
172*9880d681SAndroid Build Coastguard Worker // incorrect because all the blockaddress's (in static global initializers
173*9880d681SAndroid Build Coastguard Worker // for example) would be referring to the original function, and this indirect
174*9880d681SAndroid Build Coastguard Worker // jump would jump from the inlined copy of the function into the original
175*9880d681SAndroid Build Coastguard Worker // function which is extremely undefined behavior.
176*9880d681SAndroid Build Coastguard Worker // FIXME: This logic isn't really right; we can safely inline functions
177*9880d681SAndroid Build Coastguard Worker // with indirectbr's as long as no other function or global references the
178*9880d681SAndroid Build Coastguard Worker // blockaddress of a block within the current function. And as a QOI issue,
179*9880d681SAndroid Build Coastguard Worker // if someone is using a blockaddress without an indirectbr, and that
180*9880d681SAndroid Build Coastguard Worker // reference somehow ends up in another function or global, we probably
181*9880d681SAndroid Build Coastguard Worker // don't want to inline this function.
182*9880d681SAndroid Build Coastguard Worker notDuplicatable |= isa<IndirectBrInst>(BB->getTerminator());
183*9880d681SAndroid Build Coastguard Worker
184*9880d681SAndroid Build Coastguard Worker // Remember NumInsts for this BB.
185*9880d681SAndroid Build Coastguard Worker NumBBInsts[BB] = NumInsts - NumInstsBeforeThisBB;
186*9880d681SAndroid Build Coastguard Worker }
187