LLVM 24.0.0git
BasicBlockPathCloning.cpp
Go to the documentation of this file.
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
36#include "llvm/ADT/StringRef.h"
42#include "llvm/CodeGen/Passes.h"
48
49using namespace llvm;
50
51namespace {
52
53// Clones the given block and assigns the given `CloneID` to its BBID. Copies
54// the instructions into the new block and sets up its successors.
55MachineBasicBlock *CloneMachineBasicBlock(MachineBasicBlock &OrigBB,
56 unsigned CloneID) {
57 auto &MF = *OrigBB.getParent();
58 auto TII = MF.getSubtarget().getInstrInfo();
59 // Create the clone block and set its BBID based on the original block.
60 MachineBasicBlock *CloneBB = MF.CreateMachineBasicBlock(
61 OrigBB.getBasicBlock(), UniqueBBID{OrigBB.getBBID()->BaseID, CloneID});
62 MF.push_back(CloneBB);
63
64 // Copy the instructions.
65 for (auto &I : OrigBB.instrs()) {
66 // Bundled instructions are duplicated together.
67 if (I.isBundledWithPred())
68 continue;
69 TII->duplicate(*CloneBB, CloneBB->end(), I);
70 }
71
72 // Add the successors of the original block as the new block's successors.
73 // We set the predecessor after returning from this call.
74 for (auto SI = OrigBB.succ_begin(), SE = OrigBB.succ_end(); SI != SE; ++SI)
75 CloneBB->copySuccessor(&OrigBB, SI);
76
77 if (auto FT = OrigBB.getFallThrough(/*JumpToFallThrough=*/false)) {
78 // The original block has an implicit fall through.
79 // Insert an explicit unconditional jump from the cloned block to the
80 // fallthrough block. Technically, this is only needed for the last block
81 // of the path, but we do it for all clones for consistency.
82 TII->insertUnconditionalBranch(*CloneBB, FT, CloneBB->findBranchDebugLoc());
83 }
84 return CloneBB;
85}
86
87// Returns if we can legally apply the cloning represented by `ClonePath`.
88// `BBIDToBlock` contains the original basic blocks in function `MF` keyed by
89// their `BBID::BaseID`.
90bool IsValidCloning(const MachineFunction &MF,
92 const SmallVector<unsigned> &ClonePath) {
93 const MachineBasicBlock *PrevBB = nullptr;
94 for (size_t I = 0; I < ClonePath.size(); ++I) {
95 unsigned BBID = ClonePath[I];
96 const MachineBasicBlock *PathBB = BBIDToBlock.lookup(BBID);
97 if (!PathBB) {
98 WithColor::warning() << "no block with id " << BBID << " in function "
99 << MF.getName() << "\n";
100 return false;
101 }
102
103 if (PrevBB) {
104 if (!PrevBB->isSuccessor(PathBB)) {
106 << "block #" << BBID << " is not a successor of block #"
107 << PrevBB->getBBID()->BaseID << " in function " << MF.getName()
108 << "\n";
109 return false;
110 }
111
112 for (auto &MI : *PathBB) {
113 // Avoid cloning when the block contains non-duplicable instructions.
114 // CFI instructions are marked as non-duplicable only because of Darwin,
115 // so we exclude them from this check.
116 if (MI.isNotDuplicable() && !MI.isCFIInstruction()) {
118 << "block #" << BBID
119 << " has non-duplicable instructions in function " << MF.getName()
120 << "\n";
121 return false;
122 }
123 }
124 if (PathBB->isMachineBlockAddressTaken()) {
125 // Avoid cloning blocks which have their address taken since we can't
126 // rewire branches to those blocks as easily.
128 << "block #" << BBID
129 << " has its machine block address taken in function "
130 << MF.getName() << "\n";
131 return false;
132 }
133 if (PathBB->isInlineAsmBrIndirectTarget()) {
134 // Similarly for branches to the block within an asm goto.
136 << "block #" << BBID
137 << " is a branch target of an 'asm goto' in function "
138 << MF.getName() << "\n";
139 return false;
140 }
141 }
142
143 if (I != ClonePath.size() - 1 && !PathBB->empty() &&
144 PathBB->back().isIndirectBranch()) {
146 << "block #" << BBID
147 << " has indirect branch and appears as the non-tail block of a "
148 "path in function "
149 << MF.getName() << "\n";
150 return false;
151 }
152 PrevBB = PathBB;
153 }
154 return true;
155}
156
157// Applies all clonings specified in `ClonePaths` to `MF`. Returns true
158// if any clonings have been applied.
159bool ApplyCloning(MachineFunction &MF,
160 const SmallVector<SmallVector<unsigned>> &ClonePaths) {
161 if (ClonePaths.empty())
162 return false;
163 bool AnyPathsCloned = false;
164 // Map from the final BB IDs to the `MachineBasicBlock`s.
166 for (auto &BB : MF)
167 BBIDToBlock.try_emplace(BB.getBBID()->BaseID, &BB);
168
169 DenseMap<unsigned, unsigned> NClonesForBBID;
170 auto TII = MF.getSubtarget().getInstrInfo();
171 for (const auto &ClonePath : ClonePaths) {
172 if (!IsValidCloning(MF, BBIDToBlock, ClonePath)) {
173 // We still need to increment the number of clones so we can map
174 // to the cluster info correctly.
175 for (unsigned BBID : ClonePath)
176 ++NClonesForBBID[BBID];
177 continue;
178 }
179 MachineBasicBlock *PrevBB = nullptr;
180 for (unsigned BBID : ClonePath) {
181 MachineBasicBlock *OrigBB = BBIDToBlock.at(BBID);
182 if (PrevBB == nullptr) {
183 // The first block in the path is not cloned. We only need to make it
184 // branch to the next cloned block in the path. Here, we make its
185 // fallthrough explicit so we can change it later.
186 if (auto FT = OrigBB->getFallThrough(/*JumpToFallThrough=*/false)) {
187 TII->insertUnconditionalBranch(*OrigBB, FT,
188 OrigBB->findBranchDebugLoc());
189 }
190 PrevBB = OrigBB;
191 continue;
192 }
193 MachineBasicBlock *CloneBB =
194 CloneMachineBasicBlock(*OrigBB, ++NClonesForBBID[BBID]);
195
196 // Set up the previous block in the path to jump to the clone. This also
197 // transfers the successor/predecessor relationship of PrevBB and OrigBB
198 // to that of PrevBB and CloneBB.
199 PrevBB->ReplaceUsesOfBlockWith(OrigBB, CloneBB);
200
201 // Copy the livein set.
202 for (auto &LiveIn : OrigBB->liveins())
203 CloneBB->addLiveIn(LiveIn);
204
205 PrevBB = CloneBB;
206 }
207 AnyPathsCloned = true;
208 }
209 return AnyPathsCloned;
210}
211
212class BasicBlockPathCloning : public MachineFunctionPass {
213public:
214 static char ID;
215
216 BasicBlockSectionsProfileReaderWrapperPass *BBSectionsProfileReader = nullptr;
217
218 BasicBlockPathCloning() : MachineFunctionPass(ID) {}
219
220 StringRef getPassName() const override { return "Basic Block Path Cloning"; }
221
222 void getAnalysisUsage(AnalysisUsage &AU) const override;
223
224 /// Identify basic blocks that need separate sections and prepare to emit them
225 /// accordingly.
226 bool runOnMachineFunction(MachineFunction &MF) override;
227};
228
229} // namespace
230
231char BasicBlockPathCloning::ID = 0;
233 BasicBlockPathCloning, "bb-path-cloning",
234 "Applies path clonings for the -basic-block-sections=list option", false,
235 false)
238 BasicBlockPathCloning, "bb-path-cloning",
239 "Applies path clonings for the -basic-block-sections=list option", false,
240 false)
241
242bool BasicBlockPathCloning::runOnMachineFunction(MachineFunction &MF) {
243 assert(MF.getTarget().getBBSectionsType() == BasicBlockSection::List &&
244 "BB Sections list not enabled!");
246 return false;
247
248 return ApplyCloning(MF,
249 getAnalysis<BasicBlockSectionsProfileReaderWrapperPass>()
250 .getClonePathsForFunction(MF.getName()));
251}
252
253void BasicBlockPathCloning::getAnalysisUsage(AnalysisUsage &AU) const {
254 AU.addRequired<BasicBlockSectionsProfileReaderWrapperPass>();
255 AU.addPreserved<MachineBlockHashInfo>();
257}
258
259MachineFunctionPass *llvm::createBasicBlockPathCloningPass() {
260 return new BasicBlockPathCloning();
261}
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
const HexagonInstrInfo * TII
IRTranslator LLVM IR MI
#define I(x, y, z)
Definition MD5.cpp:57
#define INITIALIZE_PASS_DEPENDENCY(depName)
Definition PassSupport.h:42
#define INITIALIZE_PASS_END(passName, arg, name, cfg, analysis)
Definition PassSupport.h:44
#define INITIALIZE_PASS_BEGIN(passName, arg, name, cfg, analysis)
Definition PassSupport.h:39
This file defines the SmallVector class.
Represent the analysis usage information of a pass.
AnalysisUsage & addRequired()
AnalysisUsage & addPreserved()
Add the specified Pass class to the set of analyses preserved by this pass.
ValueT & at(const_arg_type_t< KeyT > Val)
Return the entry for the specified key, or abort if no such entry exists.
Definition DenseMap.h:811
ValueT lookup(const_arg_type_t< KeyT > Val) const
Return the entry for the specified key, or a default constructed value if no such entry exists.
Definition DenseMap.h:793
std::pair< iterator, bool > try_emplace(KeyT &&Key, Ts &&...Args)
Definition DenseMap.h:856
LLVM_ABI MachineBasicBlock * getFallThrough(bool JumpToFallThrough=true)
Return the fallthrough block if the block can implicitly transfer control to the block after it by fa...
iterator_range< livein_iterator > liveins() const
void push_back(MachineInstr *MI)
std::optional< UniqueBBID > getBBID() const
const BasicBlock * getBasicBlock() const
Return the LLVM basic block that this instance corresponded to originally.
LLVM_ABI void copySuccessor(const MachineBasicBlock *Orig, succ_iterator I)
Copy a successor (and any probability info) from original block to this block's.
LLVM_ABI void ReplaceUsesOfBlockWith(MachineBasicBlock *Old, MachineBasicBlock *New)
Given a machine basic block that branched to 'Old', change the code and CFG so that it branches to 'N...
void addLiveIn(MCRegister PhysReg, LaneBitmask LaneMask=LaneBitmask::getAll())
Adds the specified register as a live in.
const MachineFunction * getParent() const
Return the MachineFunction containing this basic block.
LLVM_ABI DebugLoc findBranchDebugLoc()
Find and return the merged DebugLoc of the branch instructions of the block.
LLVM_ABI bool isSuccessor(const MachineBasicBlock *MBB) const
Return true if the specified MBB is a successor of this block.
MachineFunctionPass - This class adapts the FunctionPass interface to allow convenient creation of pa...
void getAnalysisUsage(AnalysisUsage &AU) const override
getAnalysisUsage - Subclasses that override getAnalysisUsage must call this.
StringRef getName() const
getName - Return the name of the corresponding LLVM function.
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
static LLVM_ABI raw_ostream & warning()
Convenience method for printing "warning: " to stderr.
Definition WithColor.cpp:86
This is an optimization pass for GlobalISel generic memory operations.
LLVM_ABI bool hasInstrProfHashMismatch(MachineFunction &MF)
This checks if the source of this function has drifted since this binary was profiled previously.
LLVM_ABI MachineFunctionPass * createBasicBlockPathCloningPass()