xref: /llvm-project/bolt/lib/Core/BinaryBasicBlock.cpp (revision ae585be11cfac7bccbb7bb463e44a3d95e477cbd)
1 //===--- BinaryBasicBlock.cpp - Interface for assembly-level basic block --===//
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 //===----------------------------------------------------------------------===//
10 
11 #include "bolt/Core/BinaryBasicBlock.h"
12 #include "bolt/Core/BinaryContext.h"
13 #include "bolt/Core/BinaryFunction.h"
14 #include "llvm/MC/MCAsmLayout.h"
15 #include "llvm/MC/MCInst.h"
16 #include "llvm/Support/Errc.h"
17 
18 #undef  DEBUG_TYPE
19 #define DEBUG_TYPE "bolt"
20 
21 namespace llvm {
22 namespace bolt {
23 
24 constexpr uint32_t BinaryBasicBlock::INVALID_OFFSET;
25 
26 bool operator<(const BinaryBasicBlock &LHS, const BinaryBasicBlock &RHS) {
27   return LHS.Index < RHS.Index;
28 }
29 
30 bool BinaryBasicBlock::hasCFG() const {
31   return getParent()->hasCFG();
32 }
33 
34 bool BinaryBasicBlock::isEntryPoint() const {
35   return getParent()->isEntryPoint(*this);
36 }
37 
38 bool BinaryBasicBlock::hasInstructions() const {
39   return getParent()->hasInstructions();
40 }
41 
42 bool BinaryBasicBlock::hasJumpTable() const {
43   const MCInst *Inst = getLastNonPseudoInstr();
44   const JumpTable *JT = Inst ? Function->getJumpTable(*Inst) : nullptr;
45   return (JT != nullptr);
46 }
47 
48 void BinaryBasicBlock::adjustNumPseudos(const MCInst &Inst, int Sign) {
49   BinaryContext &BC = Function->getBinaryContext();
50   if (BC.MIB->isPseudo(Inst))
51     NumPseudos += Sign;
52 }
53 
54 BinaryBasicBlock::iterator BinaryBasicBlock::getFirstNonPseudo() {
55   const BinaryContext &BC = Function->getBinaryContext();
56   for (auto II = Instructions.begin(), E = Instructions.end(); II != E; ++II) {
57     if (!BC.MIB->isPseudo(*II))
58       return II;
59   }
60   return end();
61 }
62 
63 BinaryBasicBlock::reverse_iterator BinaryBasicBlock::getLastNonPseudo() {
64   const BinaryContext &BC = Function->getBinaryContext();
65   for (auto RII = Instructions.rbegin(), E = Instructions.rend();
66        RII != E; ++RII) {
67     if (!BC.MIB->isPseudo(*RII))
68       return RII;
69   }
70   return rend();
71 }
72 
73 bool BinaryBasicBlock::validateSuccessorInvariants() {
74   const MCInst *Inst = getLastNonPseudoInstr();
75   const JumpTable *JT = Inst ? Function->getJumpTable(*Inst) : nullptr;
76   BinaryContext &BC = Function->getBinaryContext();
77   bool Valid = true;
78 
79   if (JT) {
80     // Note: for now we assume that successors do not reference labels from
81     // any overlapping jump tables.  We only look at the entries for the jump
82     // table that is referenced at the last instruction.
83     const auto Range = JT->getEntriesForAddress(BC.MIB->getJumpTable(*Inst));
84     const std::vector<const MCSymbol *> Entries(
85         std::next(JT->Entries.begin(), Range.first),
86         std::next(JT->Entries.begin(), Range.second));
87     std::set<const MCSymbol *> UniqueSyms(Entries.begin(), Entries.end());
88     for (BinaryBasicBlock *Succ : Successors) {
89       auto Itr = UniqueSyms.find(Succ->getLabel());
90       if (Itr != UniqueSyms.end()) {
91         UniqueSyms.erase(Itr);
92       } else  {
93         // Work on the assumption that jump table blocks don't
94         // have a conditional successor.
95         Valid = false;
96         errs() << "BOLT-WARNING: Jump table successor "
97                << Succ->getName()
98                << " not contained in the jump table.\n";
99       }
100     }
101     // If there are any leftover entries in the jump table, they
102     // must be one of the function end labels.
103     if (Valid) {
104       for (const MCSymbol *Sym : UniqueSyms) {
105         Valid &= (Sym == Function->getFunctionEndLabel() ||
106                   Sym == Function->getFunctionColdEndLabel());
107         if (!Valid) {
108           errs() << "BOLT-WARNING: Jump table contains illegal entry: "
109                  << Sym->getName() << "\n";
110         }
111       }
112     }
113   } else {
114     // Unknown control flow.
115     if (Inst && BC.MIB->isIndirectBranch(*Inst))
116       return true;
117 
118     const MCSymbol *TBB = nullptr;
119     const MCSymbol *FBB = nullptr;
120     MCInst *CondBranch = nullptr;
121     MCInst *UncondBranch = nullptr;
122 
123     if (analyzeBranch(TBB, FBB, CondBranch, UncondBranch)) {
124       switch (Successors.size()) {
125       case 0:
126         Valid = !CondBranch && !UncondBranch;
127         break;
128       case 1: {
129         const bool HasCondBlock = CondBranch &&
130           Function->getBasicBlockForLabel(BC.MIB->getTargetSymbol(*CondBranch));
131         Valid = !CondBranch || !HasCondBlock;
132         break;
133       }
134       case 2:
135         Valid =
136           (CondBranch &&
137            (TBB == getConditionalSuccessor(true)->getLabel() &&
138             ((!UncondBranch && !FBB) ||
139              (UncondBranch &&
140               FBB == getConditionalSuccessor(false)->getLabel()))));
141         break;
142       }
143     }
144   }
145   if (!Valid) {
146     errs() << "BOLT-WARNING: CFG invalid in " << *getFunction() << " @ "
147            << getName() << "\n";
148     if (JT) {
149       errs() << "Jump Table instruction addr = 0x"
150              << Twine::utohexstr(BC.MIB->getJumpTable(*Inst)) << "\n";
151       JT->print(errs());
152     }
153     getFunction()->dump();
154   }
155   return Valid;
156 }
157 
158 BinaryBasicBlock *BinaryBasicBlock::getSuccessor(const MCSymbol *Label) const {
159   if (!Label && succ_size() == 1)
160     return *succ_begin();
161 
162   for (BinaryBasicBlock *BB : successors()) {
163     if (BB->getLabel() == Label)
164       return BB;
165   }
166 
167   return nullptr;
168 }
169 
170 BinaryBasicBlock *
171 BinaryBasicBlock::getSuccessor(const MCSymbol *Label,
172                                BinaryBranchInfo &BI) const {
173   auto BIIter = branch_info_begin();
174   for (BinaryBasicBlock *BB : successors()) {
175     if (BB->getLabel() == Label) {
176       BI = *BIIter;
177       return BB;
178     }
179     ++BIIter;
180   }
181 
182   return nullptr;
183 }
184 
185 BinaryBasicBlock *BinaryBasicBlock::getLandingPad(const MCSymbol *Label) const {
186   for (BinaryBasicBlock *BB : landing_pads()) {
187     if (BB->getLabel() == Label)
188       return BB;
189   }
190 
191   return nullptr;
192 }
193 
194 int32_t BinaryBasicBlock::getCFIStateAtInstr(const MCInst *Instr) const {
195   assert(
196       getFunction()->getState() >= BinaryFunction::State::CFG &&
197       "can only calculate CFI state when function is in or past the CFG state");
198 
199   const std::vector<MCCFIInstruction> &FDEProgram =
200       getFunction()->getFDEProgram();
201 
202   // Find the last CFI preceding Instr in this basic block.
203   const MCInst *LastCFI = nullptr;
204   bool InstrSeen = (Instr == nullptr);
205   for (auto RII = Instructions.rbegin(), E = Instructions.rend();
206        RII != E; ++RII) {
207     if (!InstrSeen) {
208       InstrSeen = (&*RII == Instr);
209       continue;
210     }
211     if (Function->getBinaryContext().MIB->isCFI(*RII)) {
212       LastCFI = &*RII;
213       break;
214     }
215   }
216 
217   assert(InstrSeen && "instruction expected in basic block");
218 
219   // CFI state is the same as at basic block entry point.
220   if (!LastCFI)
221     return getCFIState();
222 
223   // Fold all RememberState/RestoreState sequences, such as for:
224   //
225   //   [ CFI #(K-1) ]
226   //   RememberState (#K)
227   //     ....
228   //   RestoreState
229   //   RememberState
230   //     ....
231   //   RestoreState
232   //   [ GNU_args_size ]
233   //   RememberState
234   //     ....
235   //   RestoreState   <- LastCFI
236   //
237   // we return K - the most efficient state to (re-)generate.
238   int64_t State = LastCFI->getOperand(0).getImm();
239   while (State >= 0 &&
240          FDEProgram[State].getOperation() == MCCFIInstruction::OpRestoreState) {
241     int32_t Depth = 1;
242     --State;
243     assert(State >= 0 && "first CFI cannot be RestoreState");
244     while (Depth && State >= 0) {
245       const MCCFIInstruction &CFIInstr = FDEProgram[State];
246       if (CFIInstr.getOperation() == MCCFIInstruction::OpRestoreState) {
247         ++Depth;
248       } else if (CFIInstr.getOperation() == MCCFIInstruction::OpRememberState) {
249         --Depth;
250       }
251       --State;
252     }
253     assert(Depth == 0 && "unbalanced RememberState/RestoreState stack");
254 
255     // Skip any GNU_args_size.
256     while (State >= 0 &&
257            FDEProgram[State].getOperation() == MCCFIInstruction::OpGnuArgsSize){
258       --State;
259     }
260   }
261 
262   assert((State + 1 >= 0) && "miscalculated CFI state");
263   return State + 1;
264 }
265 
266 void BinaryBasicBlock::addSuccessor(BinaryBasicBlock *Succ,
267                                     uint64_t Count,
268                                     uint64_t MispredictedCount) {
269   Successors.push_back(Succ);
270   BranchInfo.push_back({Count, MispredictedCount});
271   Succ->Predecessors.push_back(this);
272 }
273 
274 void BinaryBasicBlock::replaceSuccessor(BinaryBasicBlock *Succ,
275                                         BinaryBasicBlock *NewSucc,
276                                         uint64_t Count,
277                                         uint64_t MispredictedCount) {
278   Succ->removePredecessor(this, /*Multiple=*/false);
279   auto I = succ_begin();
280   auto BI = BranchInfo.begin();
281   for (; I != succ_end(); ++I) {
282     assert(BI != BranchInfo.end() && "missing BranchInfo entry");
283     if (*I == Succ)
284       break;
285     ++BI;
286   }
287   assert(I != succ_end() && "no such successor!");
288 
289   *I = NewSucc;
290   *BI = BinaryBranchInfo{Count, MispredictedCount};
291   NewSucc->addPredecessor(this);
292 }
293 
294 void BinaryBasicBlock::removeAllSuccessors() {
295   for (BinaryBasicBlock *SuccessorBB : successors()) {
296     SuccessorBB->removePredecessor(this);
297   }
298   Successors.clear();
299   BranchInfo.clear();
300 }
301 
302 void BinaryBasicBlock::removeSuccessor(BinaryBasicBlock *Succ) {
303   Succ->removePredecessor(this, /*Multiple=*/false);
304   auto I = succ_begin();
305   auto BI = BranchInfo.begin();
306   for (; I != succ_end(); ++I) {
307     assert(BI != BranchInfo.end() && "missing BranchInfo entry");
308     if (*I == Succ)
309       break;
310     ++BI;
311   }
312   assert(I != succ_end() && "no such successor!");
313 
314   Successors.erase(I);
315   BranchInfo.erase(BI);
316 }
317 
318 void BinaryBasicBlock::addPredecessor(BinaryBasicBlock *Pred) {
319   Predecessors.push_back(Pred);
320 }
321 
322 void BinaryBasicBlock::removePredecessor(BinaryBasicBlock *Pred,
323                                          bool Multiple) {
324   // Note: the predecessor could be listed multiple times.
325   bool Erased = false;
326   for (auto PredI = Predecessors.begin(); PredI != Predecessors.end(); ) {
327     if (*PredI == Pred) {
328       Erased = true;
329       PredI = Predecessors.erase(PredI);
330       if (!Multiple)
331         return;
332     } else {
333       ++PredI;
334     }
335   }
336   assert(Erased && "Pred is not a predecessor of this block!");
337 }
338 
339 void BinaryBasicBlock::removeDuplicateConditionalSuccessor(MCInst *CondBranch) {
340   assert(succ_size() == 2 && Successors[0] == Successors[1] &&
341          "conditional successors expected");
342 
343   BinaryBasicBlock *Succ = Successors[0];
344   const BinaryBranchInfo CondBI = BranchInfo[0];
345   const BinaryBranchInfo UncondBI = BranchInfo[1];
346 
347   eraseInstruction(findInstruction(CondBranch));
348 
349   Successors.clear();
350   BranchInfo.clear();
351 
352   Successors.push_back(Succ);
353 
354   uint64_t Count = COUNT_NO_PROFILE;
355   if (CondBI.Count != COUNT_NO_PROFILE && UncondBI.Count != COUNT_NO_PROFILE)
356     Count = CondBI.Count + UncondBI.Count;
357   BranchInfo.push_back({Count, 0});
358 }
359 
360 void BinaryBasicBlock::adjustExecutionCount(double Ratio) {
361   auto adjustedCount = [&](uint64_t Count) -> uint64_t {
362     double NewCount = Count * Ratio;
363     if (!NewCount && Count && (Ratio > 0.0))
364       NewCount = 1;
365     return NewCount;
366   };
367 
368   setExecutionCount(adjustedCount(getKnownExecutionCount()));
369   for (BinaryBranchInfo &BI : branch_info()) {
370     if (BI.Count != COUNT_NO_PROFILE)
371       BI.Count = adjustedCount(BI.Count);
372     if (BI.MispredictedCount != COUNT_INFERRED)
373       BI.MispredictedCount = adjustedCount(BI.MispredictedCount);
374   }
375 }
376 
377 bool BinaryBasicBlock::analyzeBranch(const MCSymbol *&TBB,
378                                      const MCSymbol *&FBB,
379                                      MCInst *&CondBranch,
380                                      MCInst *&UncondBranch) {
381   auto &MIB = Function->getBinaryContext().MIB;
382   return MIB->analyzeBranch(Instructions.begin(),
383                             Instructions.end(),
384                             TBB,
385                             FBB,
386                             CondBranch,
387                             UncondBranch);
388 }
389 
390 bool BinaryBasicBlock::isMacroOpFusionPair(const_iterator I) const {
391   auto &MIB = Function->getBinaryContext().MIB;
392   ArrayRef<MCInst> Insts = Instructions;
393   return MIB->isMacroOpFusionPair(Insts.slice(I - begin()));
394 }
395 
396 BinaryBasicBlock::const_iterator
397 BinaryBasicBlock::getMacroOpFusionPair() const {
398   if (!Function->getBinaryContext().isX86())
399     return end();
400 
401   if (getNumNonPseudos() < 2 || succ_size() != 2)
402     return end();
403 
404   auto RI = getLastNonPseudo();
405   assert(RI != rend() && "cannot have an empty block with 2 successors");
406 
407   BinaryContext &BC = Function->getBinaryContext();
408 
409   // Skip instruction if it's an unconditional branch following
410   // a conditional one.
411   if (BC.MIB->isUnconditionalBranch(*RI))
412     ++RI;
413 
414   if (!BC.MIB->isConditionalBranch(*RI))
415     return end();
416 
417   // Start checking with instruction preceding the conditional branch.
418   ++RI;
419   if (RI == rend())
420     return end();
421 
422   auto II = std::prev(RI.base()); // convert to a forward iterator
423   if (isMacroOpFusionPair(II))
424     return II;
425 
426   return end();
427 }
428 
429 MCInst *BinaryBasicBlock::getTerminatorBefore(MCInst *Pos) {
430   BinaryContext &BC = Function->getBinaryContext();
431   auto Itr = rbegin();
432   bool Check = Pos ? false : true;
433   MCInst *FirstTerminator = nullptr;
434   while (Itr != rend()) {
435     if (!Check) {
436       if (&*Itr == Pos)
437         Check = true;
438       ++Itr;
439       continue;
440     }
441     if (BC.MIB->isTerminator(*Itr))
442       FirstTerminator = &*Itr;
443     ++Itr;
444   }
445   return FirstTerminator;
446 }
447 
448 bool BinaryBasicBlock::hasTerminatorAfter(MCInst *Pos) {
449   BinaryContext &BC = Function->getBinaryContext();
450   auto Itr = rbegin();
451   while (Itr != rend()) {
452     if (&*Itr == Pos)
453       return false;
454     if (BC.MIB->isTerminator(*Itr))
455       return true;
456     ++Itr;
457   }
458   return false;
459 }
460 
461 bool BinaryBasicBlock::swapConditionalSuccessors() {
462   if (succ_size() != 2)
463     return false;
464 
465   std::swap(Successors[0], Successors[1]);
466   std::swap(BranchInfo[0], BranchInfo[1]);
467   return true;
468 }
469 
470 void BinaryBasicBlock::addBranchInstruction(const BinaryBasicBlock *Successor) {
471   assert(isSuccessor(Successor));
472   BinaryContext &BC = Function->getBinaryContext();
473   MCInst NewInst;
474   std::unique_lock<std::shared_timed_mutex> Lock(BC.CtxMutex);
475   BC.MIB->createUncondBranch(NewInst, Successor->getLabel(), BC.Ctx.get());
476   Instructions.emplace_back(std::move(NewInst));
477 }
478 
479 void BinaryBasicBlock::addTailCallInstruction(const MCSymbol *Target) {
480   BinaryContext &BC = Function->getBinaryContext();
481   MCInst NewInst;
482   BC.MIB->createTailCall(NewInst, Target, BC.Ctx.get());
483   Instructions.emplace_back(std::move(NewInst));
484 }
485 
486 uint32_t BinaryBasicBlock::getNumCalls() const {
487   uint32_t N = 0;
488   BinaryContext &BC = Function->getBinaryContext();
489   for (const MCInst &Instr : Instructions) {
490     if (BC.MIB->isCall(Instr))
491       ++N;
492   }
493   return N;
494 }
495 
496 uint32_t BinaryBasicBlock::getNumPseudos() const {
497 #ifndef NDEBUG
498   BinaryContext &BC = Function->getBinaryContext();
499   uint32_t N = 0;
500   for (const MCInst &Instr : Instructions) {
501     if (BC.MIB->isPseudo(Instr))
502       ++N;
503   }
504   if (N != NumPseudos) {
505     errs() << "BOLT-ERROR: instructions for basic block " << getName()
506            << " in function " << *Function << ": calculated pseudos "
507            << N << ", set pseudos " << NumPseudos << ", size " << size()
508            << '\n';
509     llvm_unreachable("pseudos mismatch");
510   }
511 #endif
512   return NumPseudos;
513 }
514 
515 ErrorOr<std::pair<double, double>>
516 BinaryBasicBlock::getBranchStats(const BinaryBasicBlock *Succ) const {
517   if (Function->hasValidProfile()) {
518     uint64_t TotalCount = 0;
519     uint64_t TotalMispreds = 0;
520     for (const BinaryBranchInfo &BI : BranchInfo) {
521       if (BI.Count != COUNT_NO_PROFILE) {
522         TotalCount += BI.Count;
523         TotalMispreds += BI.MispredictedCount;
524       }
525     }
526 
527     if (TotalCount > 0) {
528       auto Itr = std::find(Successors.begin(), Successors.end(), Succ);
529       assert(Itr != Successors.end());
530       const BinaryBranchInfo &BI = BranchInfo[Itr - Successors.begin()];
531       if (BI.Count && BI.Count != COUNT_NO_PROFILE) {
532         if (TotalMispreds == 0) TotalMispreds = 1;
533         return std::make_pair(double(BI.Count) / TotalCount,
534                               double(BI.MispredictedCount) / TotalMispreds);
535       }
536     }
537   }
538   return make_error_code(llvm::errc::result_out_of_range);
539 }
540 
541 void BinaryBasicBlock::dump() const {
542   BinaryContext &BC = Function->getBinaryContext();
543   if (Label) outs() << Label->getName() << ":\n";
544   BC.printInstructions(outs(), Instructions.begin(), Instructions.end(),
545                        getOffset());
546   outs() << "preds:";
547   for (auto itr = pred_begin(); itr != pred_end(); ++itr) {
548     outs() << " " << (*itr)->getName();
549   }
550   outs() << "\nsuccs:";
551   for (auto itr = succ_begin(); itr != succ_end(); ++itr) {
552     outs() << " " << (*itr)->getName();
553   }
554   outs() << "\n";
555 }
556 
557 uint64_t BinaryBasicBlock::estimateSize(const MCCodeEmitter *Emitter) const {
558   return Function->getBinaryContext().computeCodeSize(begin(), end(), Emitter);
559 }
560 
561 BinaryBasicBlock::BinaryBranchInfo &
562 BinaryBasicBlock::getBranchInfo(const BinaryBasicBlock &Succ) {
563   auto BI = branch_info_begin();
564   for (BinaryBasicBlock *BB : successors()) {
565     if (&Succ == BB)
566       return *BI;
567     ++BI;
568   }
569 
570   llvm_unreachable("Invalid successor");
571   return *BI;
572 }
573 
574 BinaryBasicBlock::BinaryBranchInfo &
575 BinaryBasicBlock::getBranchInfo(const MCSymbol *Label) {
576   auto BI = branch_info_begin();
577   for (BinaryBasicBlock *BB : successors()) {
578     if (BB->getLabel() == Label)
579       return *BI;
580     ++BI;
581   }
582 
583   llvm_unreachable("Invalid successor");
584   return *BI;
585 }
586 
587 BinaryBasicBlock *BinaryBasicBlock::splitAt(iterator II) {
588   assert(II != end() && "expected iterator pointing to instruction");
589 
590   BinaryBasicBlock *NewBlock = getFunction()->addBasicBlock(0);
591 
592   // Adjust successors/predecessors and propagate the execution count.
593   moveAllSuccessorsTo(NewBlock);
594   addSuccessor(NewBlock, getExecutionCount(), 0);
595 
596   // Set correct CFI state for the new block.
597   NewBlock->setCFIState(getCFIStateAtInstr(&*II));
598 
599   // Move instructions over.
600   adjustNumPseudos(II, end(), -1);
601   NewBlock->addInstructions(II, end());
602   Instructions.erase(II, end());
603 
604   return NewBlock;
605 }
606 
607 void BinaryBasicBlock::updateOutputValues(const MCAsmLayout &Layout) {
608   if (!LocSyms)
609     return;
610 
611   const uint64_t BBAddress = getOutputAddressRange().first;
612   const uint64_t BBOffset = Layout.getSymbolOffset(*getLabel());
613   for (const auto &LocSymKV : *LocSyms) {
614     const uint32_t InputFunctionOffset = LocSymKV.first;
615     const uint32_t OutputOffset = static_cast<uint32_t>(
616         Layout.getSymbolOffset(*LocSymKV.second) - BBOffset);
617     getOffsetTranslationTable().emplace_back(
618         std::make_pair(OutputOffset, InputFunctionOffset));
619 
620     // Update reverse (relative to BAT) address lookup table for function.
621     if (getFunction()->requiresAddressTranslation()) {
622       getFunction()->getInputOffsetToAddressMap().emplace(
623           std::make_pair(InputFunctionOffset, OutputOffset + BBAddress));
624     }
625   }
626   LocSyms.reset(nullptr);
627 }
628 
629 } // namespace bolt
630 } // namespace llvm
631