1 //===- CodeMetrics.cpp - Code cost measurements ---------------------------===//
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7 //===----------------------------------------------------------------------===//
9 // This file implements code cost measurement utilities.
11 //===----------------------------------------------------------------------===//
13 #include "llvm/Analysis/CodeMetrics.h"
14 #include "llvm/ADT/SmallPtrSet.h"
15 #include "llvm/Analysis/AssumptionCache.h"
16 #include "llvm/Analysis/LoopInfo.h"
17 #include "llvm/Analysis/TargetTransformInfo.h"
18 #include "llvm/IR/Function.h"
19 #include "llvm/IR/IntrinsicInst.h"
20 #include "llvm/Support/Debug.h"
21 #include "llvm/Support/InstructionCost.h"
23 #define DEBUG_TYPE "code-metrics"
28 appendSpeculatableOperands(const Value
*V
,
29 SmallPtrSetImpl
<const Value
*> &Visited
,
30 SmallVectorImpl
<const Value
*> &Worklist
) {
31 const User
*U
= dyn_cast
<User
>(V
);
35 for (const Value
*Operand
: U
->operands())
36 if (Visited
.insert(Operand
).second
)
37 if (const auto *I
= dyn_cast
<Instruction
>(Operand
))
38 if (!I
->mayHaveSideEffects() && !I
->isTerminator())
39 Worklist
.push_back(I
);
42 static void completeEphemeralValues(SmallPtrSetImpl
<const Value
*> &Visited
,
43 SmallVectorImpl
<const Value
*> &Worklist
,
44 SmallPtrSetImpl
<const Value
*> &EphValues
) {
45 // Note: We don't speculate PHIs here, so we'll miss instruction chains kept
46 // alive only by ephemeral values.
48 // Walk the worklist using an index but without caching the size so we can
49 // append more entries as we process the worklist. This forms a queue without
50 // quadratic behavior by just leaving processed nodes at the head of the
52 for (int i
= 0; i
< (int)Worklist
.size(); ++i
) {
53 const Value
*V
= Worklist
[i
];
55 assert(Visited
.count(V
) &&
56 "Failed to add a worklist entry to our visited set!");
58 // If all uses of this value are ephemeral, then so is this value.
59 if (!all_of(V
->users(), [&](const User
*U
) { return EphValues
.count(U
); }))
63 LLVM_DEBUG(dbgs() << "Ephemeral Value: " << *V
<< "\n");
65 // Append any more operands to consider.
66 appendSpeculatableOperands(V
, Visited
, Worklist
);
70 // Find all ephemeral values.
71 void CodeMetrics::collectEphemeralValues(
72 const Loop
*L
, AssumptionCache
*AC
,
73 SmallPtrSetImpl
<const Value
*> &EphValues
) {
74 SmallPtrSet
<const Value
*, 32> Visited
;
75 SmallVector
<const Value
*, 16> Worklist
;
77 for (auto &AssumeVH
: AC
->assumptions()) {
80 Instruction
*I
= cast
<Instruction
>(AssumeVH
);
82 // Filter out call sites outside of the loop so we don't do a function's
83 // worth of work for each of its loops (and, in the common case, ephemeral
84 // values in the loop are likely due to @llvm.assume calls in the loop).
85 if (!L
->contains(I
->getParent()))
88 if (EphValues
.insert(I
).second
)
89 appendSpeculatableOperands(I
, Visited
, Worklist
);
92 completeEphemeralValues(Visited
, Worklist
, EphValues
);
95 void CodeMetrics::collectEphemeralValues(
96 const Function
*F
, AssumptionCache
*AC
,
97 SmallPtrSetImpl
<const Value
*> &EphValues
) {
98 SmallPtrSet
<const Value
*, 32> Visited
;
99 SmallVector
<const Value
*, 16> Worklist
;
101 for (auto &AssumeVH
: AC
->assumptions()) {
104 Instruction
*I
= cast
<Instruction
>(AssumeVH
);
105 assert(I
->getParent()->getParent() == F
&&
106 "Found assumption for the wrong function!");
108 if (EphValues
.insert(I
).second
)
109 appendSpeculatableOperands(I
, Visited
, Worklist
);
112 completeEphemeralValues(Visited
, Worklist
, EphValues
);
115 static bool extendsConvergenceOutsideLoop(const Instruction
&I
, const Loop
*L
) {
118 if (!isa
<ConvergenceControlInst
>(I
))
120 for (const auto *U
: I
.users()) {
121 if (!L
->contains(cast
<Instruction
>(U
)))
127 /// Fill in the current structure with information gleaned from the specified
129 void CodeMetrics::analyzeBasicBlock(
130 const BasicBlock
*BB
, const TargetTransformInfo
&TTI
,
131 const SmallPtrSetImpl
<const Value
*> &EphValues
, bool PrepareForLTO
,
134 InstructionCost NumInstsBeforeThisBB
= NumInsts
;
135 for (const Instruction
&I
: *BB
) {
136 // Skip ephemeral values.
137 if (EphValues
.count(&I
))
140 // Special handling for calls.
141 if (const auto *Call
= dyn_cast
<CallBase
>(&I
)) {
142 if (const Function
*F
= Call
->getCalledFunction()) {
143 bool IsLoweredToCall
= TTI
.isLoweredToCall(F
);
144 // If a function is both internal and has a single use, then it is
145 // extremely likely to get inlined in the future (it was probably
146 // exposed by an interleaved devirtualization pass).
147 // When preparing for LTO, liberally consider calls as inline
149 if (!Call
->isNoInline() && IsLoweredToCall
&&
150 ((F
->hasInternalLinkage() && F
->hasOneLiveUse()) ||
152 ++NumInlineCandidates
;
155 // If this call is to function itself, then the function is recursive.
156 // Inlining it into other functions is a bad idea, because this is
157 // basically just a form of loop peeling, and our metrics aren't useful
159 if (F
== BB
->getParent())
165 // We don't want inline asm to count as a call - that would prevent loop
166 // unrolling. The argument setup cost is still real, though.
167 if (!Call
->isInlineAsm())
172 if (const AllocaInst
*AI
= dyn_cast
<AllocaInst
>(&I
)) {
173 if (!AI
->isStaticAlloca())
174 this->usesDynamicAlloca
= true;
177 if (isa
<ExtractElementInst
>(I
) || I
.getType()->isVectorTy())
180 if (I
.getType()->isTokenTy() && !isa
<ConvergenceControlInst
>(I
) &&
181 I
.isUsedOutsideOfBlock(BB
)) {
182 LLVM_DEBUG(dbgs() << I
183 << "\n Cannot duplicate a token value used outside "
184 "the current block (except convergence control).\n");
185 notDuplicatable
= true;
188 if (const CallBase
*CB
= dyn_cast
<CallBase
>(&I
)) {
189 if (CB
->cannotDuplicate())
190 notDuplicatable
= true;
191 // Compute a meet over the visited blocks for the following partial order:
193 // None -> { Controlled, ExtendedLoop, Uncontrolled}
194 // Controlled -> ExtendedLoop
195 if (Convergence
<= ConvergenceKind::Controlled
&& CB
->isConvergent()) {
196 if (isa
<ConvergenceControlInst
>(CB
) ||
197 CB
->getConvergenceControlToken()) {
198 assert(Convergence
!= ConvergenceKind::Uncontrolled
);
199 LLVM_DEBUG(dbgs() << "Found controlled convergence:\n" << I
<< "\n");
200 if (extendsConvergenceOutsideLoop(I
, L
))
201 Convergence
= ConvergenceKind::ExtendedLoop
;
203 assert(Convergence
!= ConvergenceKind::ExtendedLoop
);
204 Convergence
= ConvergenceKind::Controlled
;
207 assert(Convergence
== ConvergenceKind::None
);
208 Convergence
= ConvergenceKind::Uncontrolled
;
213 NumInsts
+= TTI
.getInstructionCost(&I
, TargetTransformInfo::TCK_CodeSize
);
216 if (isa
<ReturnInst
>(BB
->getTerminator()))
219 // We never want to inline functions that contain an indirectbr. This is
220 // incorrect because all the blockaddress's (in static global initializers
221 // for example) would be referring to the original function, and this indirect
222 // jump would jump from the inlined copy of the function into the original
223 // function which is extremely undefined behavior.
224 // FIXME: This logic isn't really right; we can safely inline functions
225 // with indirectbr's as long as no other function or global references the
226 // blockaddress of a block within the current function. And as a QOI issue,
227 // if someone is using a blockaddress without an indirectbr, and that
228 // reference somehow ends up in another function or global, we probably
229 // don't want to inline this function.
230 notDuplicatable
|= isa
<IndirectBrInst
>(BB
->getTerminator());
232 // Remember NumInsts for this BB.
233 InstructionCost NumInstsThisBB
= NumInsts
- NumInstsBeforeThisBB
;
234 NumBBInsts
[BB
] = NumInstsThisBB
;