LLVM 23.0.0git
SpeculateAnalyses.cpp
Go to the documentation of this file.
1//===-- SpeculateAnalyses.cpp --*- C++ -*-===//
2//
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
6//
7//===----------------------------------------------------------------------===//
8
10#include "llvm/ADT/ArrayRef.h"
11#include "llvm/ADT/DenseMap.h"
12#include "llvm/ADT/STLExtras.h"
16#include "llvm/Analysis/CFG.h"
17#include "llvm/IR/PassManager.h"
20
21namespace {
22using namespace llvm;
23SmallVector<const BasicBlock *, 8> findBBwithCalls(const Function &F,
24 bool IndirectCall = false) {
26
27 auto findCallInst = [&IndirectCall](const Instruction &I) {
28 if (auto Call = dyn_cast<CallBase>(&I))
30 return Call->isIndirectCall() ? IndirectCall : true;
31 return false;
32 };
33 for (auto &BB : F)
34 if (findCallInst(*BB.getTerminator()) || llvm::any_of(BB, findCallInst))
35 BBs.emplace_back(&BB);
36
37 return BBs;
38}
39} // namespace
40
41// Implementations of Queries shouldn't need to lock the resources
42// such as LLVMContext, each argument (function) has a non-shared LLVMContext
43// Plus, if Queries contain states necessary locking scheme should be provided.
44namespace llvm {
45namespace orc {
46
47// Collect direct calls only
49 DenseSet<StringRef> &CallesNames) {
50 assert(BB != nullptr && "Traversing Null BB to find calls?");
51
52 auto getCalledFunction = [&CallesNames](const CallBase *Call) {
53 auto CalledValue = Call->getCalledOperand()->stripPointerCasts();
54 if (auto DirectCall = dyn_cast<Function>(CalledValue))
55 CallesNames.insert(DirectCall->getName());
56 };
57 for (auto &I : *BB)
58 if (auto CI = dyn_cast<CallInst>(&I))
60
61 if (auto II = dyn_cast<InvokeInst>(BB->getTerminator()))
63}
64
66 return llvm::all_of(F, [](const BasicBlock &BB) {
67 return BB.getSingleSuccessor() != nullptr;
68 });
69}
70
71// BlockFreqQuery Implementations
72
73size_t BlockFreqQuery::numBBToGet(size_t numBB) {
74 // small CFG
75 if (numBB < 4)
76 return numBB;
77 // mid-size CFG
78 else if (numBB < 20)
79 return (numBB / 2);
80 else
81 return (numBB / 2) + (numBB / 4);
82}
83
88
91 PB.registerFunctionAnalyses(FAM);
92
93 auto IBBs = findBBwithCalls(F);
94
95 if (IBBs.empty())
96 return std::nullopt;
97
98 auto &BFI = FAM.getResult<BlockFrequencyAnalysis>(F);
99
100 for (const auto I : IBBs)
101 BBFreqs.push_back({I, BFI.getBlockFreq(I).getFrequency()});
102
103 assert(IBBs.size() == BBFreqs.size() && "BB Count Mismatch");
104
105 llvm::sort(BBFreqs, [](decltype(BBFreqs)::const_reference BBF,
106 decltype(BBFreqs)::const_reference BBS) {
107 return BBF.second > BBS.second ? true : false;
108 });
109
110 // ignoring number of direct calls in a BB
111 auto Topk = numBBToGet(BBFreqs.size());
112
113 for (size_t i = 0; i < Topk; i++)
114 findCalles(BBFreqs[i].first, Calles);
115
116 assert(!Calles.empty() && "Running Analysis on Function with no calls?");
117
118 CallerAndCalles.insert({F.getName(), std::move(Calles)});
119
120 return CallerAndCalles;
121}
122
123// SequenceBBQuery Implementation
124std::size_t SequenceBBQuery::getHottestBlocks(std::size_t TotalBlocks) {
125 if (TotalBlocks == 1)
126 return TotalBlocks;
127 return TotalBlocks / 2;
128}
129
130// FIXME : find good implementation.
132SequenceBBQuery::rearrangeBB(const Function &F, const BlockListTy &BBList) {
133 BlockListTy RearrangedBBSet;
134
135 for (auto &Block : F)
136 if (llvm::is_contained(BBList, &Block))
137 RearrangedBBSet.push_back(&Block);
138
139 assert(RearrangedBBSet.size() == BBList.size() &&
140 "BasicBlock missing while rearranging?");
141 return RearrangedBBSet;
142}
143
144void SequenceBBQuery::traverseToEntryBlock(const BasicBlock *AtBB,
145 const BlockListTy &CallerBlocks,
146 const BackEdgesInfoTy &BackEdgesInfo,
147 const BranchProbabilityInfo *BPI,
148 VisitedBlocksInfoTy &VisitedBlocks) {
149 auto Itr = VisitedBlocks.find(AtBB);
150 if (Itr != VisitedBlocks.end()) { // already visited.
151 if (!Itr->second.Upward)
152 return;
153 Itr->second.Upward = false;
154 } else {
155 // Create hint for newly discoverd blocks.
156 WalkDirection BlockHint;
157 BlockHint.Upward = false;
158 // FIXME: Expensive Check
159 if (llvm::is_contained(CallerBlocks, AtBB))
160 BlockHint.CallerBlock = true;
161 VisitedBlocks.insert(std::make_pair(AtBB, BlockHint));
162 }
163
164 const_pred_iterator PIt = pred_begin(AtBB), EIt = pred_end(AtBB);
165 // Move this check to top, when we have code setup to launch speculative
166 // compiles for function in entry BB, this triggers the speculative compiles
167 // before running the program.
168 if (PIt == EIt) // No Preds.
169 return;
170
171 DenseSet<const BasicBlock *> PredSkipNodes;
172
173 // Since we are checking for predecessor's backedges, this Block
174 // occurs in second position.
175 for (auto &I : BackEdgesInfo)
176 if (I.second == AtBB)
177 PredSkipNodes.insert(I.first);
178
179 // Skip predecessors which source of back-edges.
180 for (; PIt != EIt; ++PIt)
181 // checking EdgeHotness is cheaper
182 if (BPI->isEdgeHot(*PIt, AtBB) && !PredSkipNodes.count(*PIt))
183 traverseToEntryBlock(*PIt, CallerBlocks, BackEdgesInfo, BPI,
185}
186
187void SequenceBBQuery::traverseToExitBlock(const BasicBlock *AtBB,
188 const BlockListTy &CallerBlocks,
189 const BackEdgesInfoTy &BackEdgesInfo,
190 const BranchProbabilityInfo *BPI,
191 VisitedBlocksInfoTy &VisitedBlocks) {
192 auto Itr = VisitedBlocks.find(AtBB);
193 if (Itr != VisitedBlocks.end()) { // already visited.
194 if (!Itr->second.Downward)
195 return;
196 Itr->second.Downward = false;
197 } else {
198 // Create hint for newly discoverd blocks.
199 WalkDirection BlockHint;
200 BlockHint.Downward = false;
201 // FIXME: Expensive Check
202 if (llvm::is_contained(CallerBlocks, AtBB))
203 BlockHint.CallerBlock = true;
204 VisitedBlocks.insert(std::make_pair(AtBB, BlockHint));
205 }
206
207 const_succ_iterator PIt = succ_begin(AtBB), EIt = succ_end(AtBB);
208 if (PIt == EIt) // No succs.
209 return;
210
211 // If there are hot edges, then compute SuccSkipNodes.
212 DenseSet<const BasicBlock *> SuccSkipNodes;
213
214 // Since we are checking for successor's backedges, this Block
215 // occurs in first position.
216 for (auto &I : BackEdgesInfo)
217 if (I.first == AtBB)
218 SuccSkipNodes.insert(I.second);
219
220 for (; PIt != EIt; ++PIt)
221 if (BPI->isEdgeHot(AtBB, *PIt) && !SuccSkipNodes.count(*PIt))
222 traverseToExitBlock(*PIt, CallerBlocks, BackEdgesInfo, BPI,
224}
225
226// Get Block frequencies for blocks and take most frequently executed block,
227// walk towards the entry block from those blocks and discover the basic blocks
228// with call.
230SequenceBBQuery::queryCFG(Function &F, const BlockListTy &CallerBlocks) {
231
232 BlockFreqInfoTy BBFreqs;
234 BackEdgesInfoTy BackEdgesInfo;
235
236 PassBuilder PB;
239
240 auto &BFI = FAM.getResult<BlockFrequencyAnalysis>(F);
241
242 llvm::FindFunctionBackedges(F, BackEdgesInfo);
243
244 for (const auto I : CallerBlocks)
245 BBFreqs.push_back({I, BFI.getBlockFreq(I).getFrequency()});
246
247 llvm::sort(BBFreqs, [](decltype(BBFreqs)::const_reference Bbf,
248 decltype(BBFreqs)::const_reference Bbs) {
249 return Bbf.second > Bbs.second;
250 });
251
253 HotBlocksRef =
254 HotBlocksRef.drop_back(BBFreqs.size() - getHottestBlocks(BBFreqs.size()));
255
256 BranchProbabilityInfo *BPI =
257 FAM.getCachedResult<BranchProbabilityAnalysis>(F);
258
259 // visit NHotBlocks,
260 // traverse upwards to entry
261 // traverse downwards to end.
262
263 for (auto I : HotBlocksRef) {
264 traverseToEntryBlock(I.first, CallerBlocks, BackEdgesInfo, BPI,
266 traverseToExitBlock(I.first, CallerBlocks, BackEdgesInfo, BPI,
268 }
269
270 BlockListTy MinCallerBlocks;
271 for (auto &I : VisitedBlocks)
272 if (I.second.CallerBlock)
273 MinCallerBlocks.push_back(std::move(I.first));
274
275 return rearrangeBB(F, MinCallerBlocks);
276}
277
279 // reduce the number of lists!
281 DenseSet<StringRef> Calles;
282 BlockListTy SequencedBlocks;
283 BlockListTy CallerBlocks;
284
285 CallerBlocks = findBBwithCalls(F);
286 if (CallerBlocks.empty())
287 return std::nullopt;
288
289 if (isStraightLine(F))
290 SequencedBlocks = rearrangeBB(F, CallerBlocks);
291 else
292 SequencedBlocks = queryCFG(F, CallerBlocks);
293
294 for (const auto *BB : SequencedBlocks)
295 findCalles(BB, Calles);
296
297 CallerAndCalles.insert({F.getName(), std::move(Calles)});
298 return CallerAndCalles;
299}
300
301} // namespace orc
302} // namespace llvm
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
SmallPtrSet< const BasicBlock *, 8 > VisitedBlocks
This file defines the DenseMap class.
This header defines various interfaces for pass management in LLVM.
#define F(x, y, z)
Definition MD5.cpp:54
#define I(x, y, z)
Definition MD5.cpp:57
static const Function * getCalledFunction(const Value *V)
uint64_t IntrinsicInst * II
FunctionAnalysisManager FAM
PassBuilder PB(Machine, PassOpts->PTO, std::nullopt, &PIC)
This file contains some templates that are useful if you are working with the STL at all.
This file defines the SmallVector class.
Contains the Analyses and Result Interpretation to select likely functions to Speculatively compile b...
PassT::Result * getCachedResult(IRUnitT &IR) const
Get the cached result of an analysis pass for a given IR unit.
PassT::Result & getResult(IRUnitT &IR, ExtraArgTs... ExtraArgs)
Get the result of an analysis pass for a given IR unit.
LLVM Basic Block Representation.
Definition BasicBlock.h:62
LLVM_ABI const BasicBlock * getSingleSuccessor() const
Return the successor of this block if it has a single successor.
const Instruction * getTerminator() const LLVM_READONLY
Returns the terminator instruction if the block is well formed or null if the block is not well forme...
Definition BasicBlock.h:233
Analysis pass which computes BlockFrequencyInfo.
Analysis providing branch probability information.
LLVM_ABI bool isEdgeHot(const BasicBlock *Src, const BasicBlock *Dst) const
Test if an edge is hot relative to other out-edges of the Src.
Base class for all callable instructions (InvokeInst and CallInst) Holds everything related to callin...
std::pair< iterator, bool > insert(const std::pair< KeyT, ValueT > &KV)
Definition DenseMap.h:241
Implements a dense probed hash-table based set.
Definition DenseSet.h:279
This class provides access to building LLVM's passes.
LLVM_ABI void registerFunctionAnalyses(FunctionAnalysisManager &FAM)
Registers all available function analysis passes.
iterator find(ConstPtrType Ptr) const
iterator end() const
std::pair< iterator, bool > insert(PtrType Ptr)
Inserts Ptr if and only if there is no element in the container equal to Ptr.
reference emplace_back(ArgTypes &&... Args)
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
std::pair< iterator, bool > insert(const ValueT &V)
Definition DenseSet.h:202
size_type count(const_arg_type_t< ValueT > V) const
Return 1 if the specified key is in the set, 0 otherwise.
Definition DenseSet.h:180
LLVM_ABI ResultTy operator()(Function &F)
LLVM_ABI ResultTy operator()(Function &F)
SmallVector< std::pair< const BasicBlock *, uint64_t >, 8 > BlockFreqInfoTy
DenseMap< const BasicBlock *, WalkDirection > VisitedBlocksInfoTy
SmallVector< const BasicBlock *, 8 > BlockListTy
SmallVector< std::pair< const BasicBlock *, const BasicBlock * >, 8 > BackEdgesInfoTy
std::optional< DenseMap< StringRef, DenseSet< StringRef > > > ResultTy
LLVM_ABI bool isStraightLine(const Function &F)
LLVM_ABI void findCalles(const BasicBlock *, DenseSet< StringRef > &)
CallInst * Call
Interfaces for registering analysis passes, producing common pass manager configurations,...
This is an optimization pass for GlobalISel generic memory operations.
Definition Types.h:26
bool all_of(R &&range, UnaryPredicate P)
Provide wrappers to std::all_of which take ranges instead of having to pass begin/end explicitly.
Definition STLExtras.h:1739
auto pred_end(const MachineBasicBlock *BB)
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
Definition Casting.h:643
PredIterator< const BasicBlock, Value::const_user_iterator > const_pred_iterator
Definition CFG.h:106
bool any_of(R &&range, UnaryPredicate P)
Provide wrappers to std::any_of which take ranges instead of having to pass begin/end explicitly.
Definition STLExtras.h:1746
void sort(IteratorTy Start, IteratorTy End)
Definition STLExtras.h:1636
bool isa(const From &Val)
isa<X> - Return true if the parameter to the template is an instance of one of the template type argu...
Definition Casting.h:547
RNSuccIterator< NodeRef, BlockT, RegionT > succ_begin(NodeRef Node)
RNSuccIterator< NodeRef, BlockT, RegionT > succ_end(NodeRef Node)
ArrayRef(const T &OneElt) -> ArrayRef< T >
auto pred_begin(const MachineBasicBlock *BB)
bool is_contained(R &&Range, const E &Element)
Returns true if Element is found in Range.
Definition STLExtras.h:1947
Instruction::const_succ_iterator const_succ_iterator
Definition CFG.h:139
AnalysisManager< Function > FunctionAnalysisManager
Convenience typedef for the Function analysis manager.
LLVM_ABI void FindFunctionBackedges(const Function &F, SmallVectorImpl< std::pair< const BasicBlock *, const BasicBlock * > > &Result)
Analyze the specified function to find all of the loop backedges in the function and return them.
Definition CFG.cpp:35