1 //===-- BasicBlockPathCloning.cpp ---=========-----------------------------===//
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 //===----------------------------------------------------------------------===//
10 /// BasicBlockPathCloning implementation.
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
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
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
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 //===----------------------------------------------------------------------===//
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"
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
,
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
);
62 // Copy the instructions.
63 for (auto &I
: OrigBB
.instrs()) {
64 // Bundled instructions are duplicated together.
65 if (I
.isBundledWithPred())
67 TII
->duplicate(*CloneBB
, CloneBB
->end(), I
);
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
);
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());
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
);
96 WithColor::warning() << "no block with id " << BBID
<< " in function "
97 << MF
.getName() << "\n";
102 if (!PrevBB
->isSuccessor(PathBB
)) {
104 << "block #" << BBID
<< " is not a successor of block #"
105 << PrevBB
->getBBID()->BaseID
<< " in function " << MF
.getName()
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()) {
117 << " has non-duplicable instructions in function " << MF
.getName()
124 if (I
!= ClonePath
.size() - 1 && !PathBB
->empty() &&
125 PathBB
->back().isIndirectBranch()) {
128 << " has indirect branch and appears as the non-tail block of a "
130 << MF
.getName() << "\n";
138 // Applies all clonings specified in `ClonePaths` to `MF`. Returns true
139 // if any clonings have been applied.
140 bool ApplyCloning(MachineFunction
&MF
,
141 const SmallVector
<SmallVector
<unsigned>> &ClonePaths
) {
142 if (ClonePaths
.empty())
144 bool AnyPathsCloned
= false;
145 // Map from the final BB IDs to the `MachineBasicBlock`s.
146 DenseMap
<unsigned, MachineBasicBlock
*> BBIDToBlock
;
148 BBIDToBlock
.try_emplace(BB
.getBBID()->BaseID
, &BB
);
150 DenseMap
<unsigned, unsigned> NClonesForBBID
;
151 auto TII
= MF
.getSubtarget().getInstrInfo();
152 for (const auto &ClonePath
: ClonePaths
) {
153 if (!IsValidCloning(MF
, BBIDToBlock
, ClonePath
)) {
154 // We still need to increment the number of clones so we can map
155 // to the cluster info correctly.
156 for (unsigned BBID
: ClonePath
)
157 ++NClonesForBBID
[BBID
];
160 MachineBasicBlock
*PrevBB
= nullptr;
161 for (unsigned BBID
: ClonePath
) {
162 MachineBasicBlock
*OrigBB
= BBIDToBlock
.at(BBID
);
163 if (PrevBB
== nullptr) {
164 // The first block in the path is not cloned. We only need to make it
165 // branch to the next cloned block in the path. Here, we make its
166 // fallthrough explicit so we can change it later.
167 if (auto FT
= OrigBB
->getFallThrough(/*JumpToFallThrough=*/false)) {
168 TII
->insertUnconditionalBranch(*OrigBB
, FT
,
169 OrigBB
->findBranchDebugLoc());
174 MachineBasicBlock
*CloneBB
=
175 CloneMachineBasicBlock(*OrigBB
, ++NClonesForBBID
[BBID
]);
177 // Set up the previous block in the path to jump to the clone. This also
178 // transfers the successor/predecessor relationship of PrevBB and OrigBB
179 // to that of PrevBB and CloneBB.
180 PrevBB
->ReplaceUsesOfBlockWith(OrigBB
, CloneBB
);
182 // Copy the livein set.
183 for (auto &LiveIn
: OrigBB
->liveins())
184 CloneBB
->addLiveIn(LiveIn
);
188 AnyPathsCloned
= true;
190 return AnyPathsCloned
;
192 } // end anonymous namespace
195 class BasicBlockPathCloning
: public MachineFunctionPass
{
199 BasicBlockSectionsProfileReaderWrapperPass
*BBSectionsProfileReader
= nullptr;
201 BasicBlockPathCloning() : MachineFunctionPass(ID
) {
202 initializeBasicBlockPathCloningPass(*PassRegistry::getPassRegistry());
205 StringRef
getPassName() const override
{ return "Basic Block Path Cloning"; }
207 void getAnalysisUsage(AnalysisUsage
&AU
) const override
;
209 /// Identify basic blocks that need separate sections and prepare to emit them
211 bool runOnMachineFunction(MachineFunction
&MF
) override
;
216 char BasicBlockPathCloning::ID
= 0;
217 INITIALIZE_PASS_BEGIN(
218 BasicBlockPathCloning
, "bb-path-cloning",
219 "Applies path clonings for the -basic-block-sections=list option", false,
221 INITIALIZE_PASS_DEPENDENCY(BasicBlockSectionsProfileReaderWrapperPass
)
223 BasicBlockPathCloning
, "bb-path-cloning",
224 "Applies path clonings for the -basic-block-sections=list option", false,
227 bool BasicBlockPathCloning::runOnMachineFunction(MachineFunction
&MF
) {
228 assert(MF
.getTarget().getBBSectionsType() == BasicBlockSection::List
&&
229 "BB Sections list not enabled!");
230 if (hasInstrProfHashMismatch(MF
))
233 return ApplyCloning(MF
,
234 getAnalysis
<BasicBlockSectionsProfileReaderWrapperPass
>()
235 .getClonePathsForFunction(MF
.getName()));
238 void BasicBlockPathCloning::getAnalysisUsage(AnalysisUsage
&AU
) const {
239 AU
.setPreservesAll();
240 AU
.addRequired
<BasicBlockSectionsProfileReaderWrapperPass
>();
241 MachineFunctionPass::getAnalysisUsage(AU
);
244 MachineFunctionPass
*llvm::createBasicBlockPathCloningPass() {
245 return new BasicBlockPathCloning();