xref: /freebsd/contrib/llvm-project/llvm/lib/CodeGen/BasicBlockPathCloning.cpp (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
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.
CloneMachineBasicBlock(MachineBasicBlock & OrigBB,unsigned CloneID)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`.
IsValidCloning(const MachineFunction & MF,const DenseMap<unsigned,MachineBasicBlock * > & BBIDToBlock,const SmallVector<unsigned> & ClonePath)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.
ApplyCloning(MachineFunction & MF,const SmallVector<SmallVector<unsigned>> & ClonePaths)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 
BasicBlockPathCloning()211   BasicBlockPathCloning() : MachineFunctionPass(ID) {
212     initializeBasicBlockPathCloningPass(*PassRegistry::getPassRegistry());
213   }
214 
getPassName() const215   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)
INITIALIZE_PASS_DEPENDENCY(BasicBlockSectionsProfileReaderWrapperPass)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 
getAnalysisUsage(AnalysisUsage & AU) const248 void BasicBlockPathCloning::getAnalysisUsage(AnalysisUsage &AU) const {
249   AU.setPreservesAll();
250   AU.addRequired<BasicBlockSectionsProfileReaderWrapperPass>();
251   MachineFunctionPass::getAnalysisUsage(AU);
252 }
253 
createBasicBlockPathCloningPass()254 MachineFunctionPass *llvm::createBasicBlockPathCloningPass() {
255   return new BasicBlockPathCloning();
256 }
257