Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/contrib/llvm-project/llvm/lib/CodeGen/BasicBlockPathCloning.cpp
35232 views
1
//===-- BasicBlockPathCloning.cpp ---=========-----------------------------===//
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
//
9
/// \file
10
/// BasicBlockPathCloning implementation.
11
///
12
/// The purpose of this pass is to clone basic block paths based on information
13
/// provided by the -fbasic-block-sections=list option.
14
/// Please refer to BasicBlockSectionsProfileReader.cpp to see a path cloning
15
/// example.
16
//===----------------------------------------------------------------------===//
17
// This pass clones the machine basic blocks alongs the given paths and sets up
18
// the CFG. It assigns BBIDs to the cloned blocks so that the
19
// `BasicBlockSections` pass can correctly map the cluster information to the
20
// blocks. The cloned block's BBID will have the same BaseID as the original
21
// block, but will get a unique non-zero CloneID (original blocks all have zero
22
// CloneIDs). This pass applies a path cloning if it satisfies the following
23
// conditions:
24
// 1. All BBIDs in the path should be mapped to existing blocks.
25
// 2. Each two consecutive BBIDs in the path must have a successor
26
// relationship in the CFG.
27
// 3. The path should not include a block with indirect branches, except for
28
// the last block.
29
// If a path does not satisfy all three conditions, it will be rejected, but the
30
// CloneIDs for its (supposed to be cloned) blocks will be bypassed to make sure
31
// that the `BasicBlockSections` pass can map cluster info correctly to the
32
// actually-cloned blocks.
33
//===----------------------------------------------------------------------===//
34
35
#include "llvm/ADT/SmallVector.h"
36
#include "llvm/ADT/StringRef.h"
37
#include "llvm/CodeGen/BasicBlockSectionUtils.h"
38
#include "llvm/CodeGen/BasicBlockSectionsProfileReader.h"
39
#include "llvm/CodeGen/MachineFunction.h"
40
#include "llvm/CodeGen/MachineFunctionPass.h"
41
#include "llvm/CodeGen/Passes.h"
42
#include "llvm/CodeGen/TargetInstrInfo.h"
43
#include "llvm/InitializePasses.h"
44
#include "llvm/Support/WithColor.h"
45
#include "llvm/Target/TargetMachine.h"
46
47
using namespace llvm;
48
49
namespace {
50
51
// Clones the given block and assigns the given `CloneID` to its BBID. Copies
52
// the instructions into the new block and sets up its successors.
53
MachineBasicBlock *CloneMachineBasicBlock(MachineBasicBlock &OrigBB,
54
unsigned CloneID) {
55
auto &MF = *OrigBB.getParent();
56
auto TII = MF.getSubtarget().getInstrInfo();
57
// Create the clone block and set its BBID based on the original block.
58
MachineBasicBlock *CloneBB = MF.CreateMachineBasicBlock(
59
OrigBB.getBasicBlock(), UniqueBBID{OrigBB.getBBID()->BaseID, CloneID});
60
MF.push_back(CloneBB);
61
62
// Copy the instructions.
63
for (auto &I : OrigBB.instrs()) {
64
// Bundled instructions are duplicated together.
65
if (I.isBundledWithPred())
66
continue;
67
TII->duplicate(*CloneBB, CloneBB->end(), I);
68
}
69
70
// Add the successors of the original block as the new block's successors.
71
// We set the predecessor after returning from this call.
72
for (auto SI = OrigBB.succ_begin(), SE = OrigBB.succ_end(); SI != SE; ++SI)
73
CloneBB->copySuccessor(&OrigBB, SI);
74
75
if (auto FT = OrigBB.getFallThrough(/*JumpToFallThrough=*/false)) {
76
// The original block has an implicit fall through.
77
// Insert an explicit unconditional jump from the cloned block to the
78
// fallthrough block. Technically, this is only needed for the last block
79
// of the path, but we do it for all clones for consistency.
80
TII->insertUnconditionalBranch(*CloneBB, FT, CloneBB->findBranchDebugLoc());
81
}
82
return CloneBB;
83
}
84
85
// Returns if we can legally apply the cloning represented by `ClonePath`.
86
// `BBIDToBlock` contains the original basic blocks in function `MF` keyed by
87
// their `BBID::BaseID`.
88
bool IsValidCloning(const MachineFunction &MF,
89
const DenseMap<unsigned, MachineBasicBlock *> &BBIDToBlock,
90
const SmallVector<unsigned> &ClonePath) {
91
const MachineBasicBlock *PrevBB = nullptr;
92
for (size_t I = 0; I < ClonePath.size(); ++I) {
93
unsigned BBID = ClonePath[I];
94
const MachineBasicBlock *PathBB = BBIDToBlock.lookup(BBID);
95
if (!PathBB) {
96
WithColor::warning() << "no block with id " << BBID << " in function "
97
<< MF.getName() << "\n";
98
return false;
99
}
100
101
if (PrevBB) {
102
if (!PrevBB->isSuccessor(PathBB)) {
103
WithColor::warning()
104
<< "block #" << BBID << " is not a successor of block #"
105
<< PrevBB->getBBID()->BaseID << " in function " << MF.getName()
106
<< "\n";
107
return false;
108
}
109
110
for (auto &MI : *PathBB) {
111
// Avoid cloning when the block contains non-duplicable instructions.
112
// CFI instructions are marked as non-duplicable only because of Darwin,
113
// so we exclude them from this check.
114
if (MI.isNotDuplicable() && !MI.isCFIInstruction()) {
115
WithColor::warning()
116
<< "block #" << BBID
117
<< " has non-duplicable instructions in function " << MF.getName()
118
<< "\n";
119
return false;
120
}
121
}
122
if (PathBB->isMachineBlockAddressTaken()) {
123
// Avoid cloning blocks which have their address taken since we can't
124
// rewire branches to those blocks as easily (e.g., branches within
125
// inline assembly).
126
WithColor::warning()
127
<< "block #" << BBID
128
<< " has its machine block address taken in function "
129
<< MF.getName() << "\n";
130
return false;
131
}
132
}
133
134
if (I != ClonePath.size() - 1 && !PathBB->empty() &&
135
PathBB->back().isIndirectBranch()) {
136
WithColor::warning()
137
<< "block #" << BBID
138
<< " has indirect branch and appears as the non-tail block of a "
139
"path in function "
140
<< MF.getName() << "\n";
141
return false;
142
}
143
PrevBB = PathBB;
144
}
145
return true;
146
}
147
148
// Applies all clonings specified in `ClonePaths` to `MF`. Returns true
149
// if any clonings have been applied.
150
bool ApplyCloning(MachineFunction &MF,
151
const SmallVector<SmallVector<unsigned>> &ClonePaths) {
152
if (ClonePaths.empty())
153
return false;
154
bool AnyPathsCloned = false;
155
// Map from the final BB IDs to the `MachineBasicBlock`s.
156
DenseMap<unsigned, MachineBasicBlock *> BBIDToBlock;
157
for (auto &BB : MF)
158
BBIDToBlock.try_emplace(BB.getBBID()->BaseID, &BB);
159
160
DenseMap<unsigned, unsigned> NClonesForBBID;
161
auto TII = MF.getSubtarget().getInstrInfo();
162
for (const auto &ClonePath : ClonePaths) {
163
if (!IsValidCloning(MF, BBIDToBlock, ClonePath)) {
164
// We still need to increment the number of clones so we can map
165
// to the cluster info correctly.
166
for (unsigned BBID : ClonePath)
167
++NClonesForBBID[BBID];
168
continue;
169
}
170
MachineBasicBlock *PrevBB = nullptr;
171
for (unsigned BBID : ClonePath) {
172
MachineBasicBlock *OrigBB = BBIDToBlock.at(BBID);
173
if (PrevBB == nullptr) {
174
// The first block in the path is not cloned. We only need to make it
175
// branch to the next cloned block in the path. Here, we make its
176
// fallthrough explicit so we can change it later.
177
if (auto FT = OrigBB->getFallThrough(/*JumpToFallThrough=*/false)) {
178
TII->insertUnconditionalBranch(*OrigBB, FT,
179
OrigBB->findBranchDebugLoc());
180
}
181
PrevBB = OrigBB;
182
continue;
183
}
184
MachineBasicBlock *CloneBB =
185
CloneMachineBasicBlock(*OrigBB, ++NClonesForBBID[BBID]);
186
187
// Set up the previous block in the path to jump to the clone. This also
188
// transfers the successor/predecessor relationship of PrevBB and OrigBB
189
// to that of PrevBB and CloneBB.
190
PrevBB->ReplaceUsesOfBlockWith(OrigBB, CloneBB);
191
192
// Copy the livein set.
193
for (auto &LiveIn : OrigBB->liveins())
194
CloneBB->addLiveIn(LiveIn);
195
196
PrevBB = CloneBB;
197
}
198
AnyPathsCloned = true;
199
}
200
return AnyPathsCloned;
201
}
202
} // end anonymous namespace
203
204
namespace llvm {
205
class BasicBlockPathCloning : public MachineFunctionPass {
206
public:
207
static char ID;
208
209
BasicBlockSectionsProfileReaderWrapperPass *BBSectionsProfileReader = nullptr;
210
211
BasicBlockPathCloning() : MachineFunctionPass(ID) {
212
initializeBasicBlockPathCloningPass(*PassRegistry::getPassRegistry());
213
}
214
215
StringRef getPassName() const override { return "Basic Block Path Cloning"; }
216
217
void getAnalysisUsage(AnalysisUsage &AU) const override;
218
219
/// Identify basic blocks that need separate sections and prepare to emit them
220
/// accordingly.
221
bool runOnMachineFunction(MachineFunction &MF) override;
222
};
223
224
} // namespace llvm
225
226
char BasicBlockPathCloning::ID = 0;
227
INITIALIZE_PASS_BEGIN(
228
BasicBlockPathCloning, "bb-path-cloning",
229
"Applies path clonings for the -basic-block-sections=list option", false,
230
false)
231
INITIALIZE_PASS_DEPENDENCY(BasicBlockSectionsProfileReaderWrapperPass)
232
INITIALIZE_PASS_END(
233
BasicBlockPathCloning, "bb-path-cloning",
234
"Applies path clonings for the -basic-block-sections=list option", false,
235
false)
236
237
bool BasicBlockPathCloning::runOnMachineFunction(MachineFunction &MF) {
238
assert(MF.getTarget().getBBSectionsType() == BasicBlockSection::List &&
239
"BB Sections list not enabled!");
240
if (hasInstrProfHashMismatch(MF))
241
return false;
242
243
return ApplyCloning(MF,
244
getAnalysis<BasicBlockSectionsProfileReaderWrapperPass>()
245
.getClonePathsForFunction(MF.getName()));
246
}
247
248
void BasicBlockPathCloning::getAnalysisUsage(AnalysisUsage &AU) const {
249
AU.setPreservesAll();
250
AU.addRequired<BasicBlockSectionsProfileReaderWrapperPass>();
251
MachineFunctionPass::getAnalysisUsage(AU);
252
}
253
254
MachineFunctionPass *llvm::createBasicBlockPathCloningPass() {
255
return new BasicBlockPathCloning();
256
}
257
258