1 //===- bolt/Core/BinaryBasicBlock.cpp - Low-level basic block -------------===//
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 //===----------------------------------------------------------------------===//
9 // This file implements the BinaryBasicBlock class.
11 //===----------------------------------------------------------------------===//
13 #include "bolt/Core/BinaryBasicBlock.h"
14 #include "bolt/Core/BinaryContext.h"
15 #include "bolt/Core/BinaryFunction.h"
16 #include "llvm/ADT/SmallPtrSet.h"
17 #include "llvm/MC/MCInst.h"
18 #include "llvm/Support/Errc.h"
20 #define DEBUG_TYPE "bolt"
25 constexpr uint32_t BinaryBasicBlock::INVALID_OFFSET
;
27 bool operator<(const BinaryBasicBlock
&LHS
, const BinaryBasicBlock
&RHS
) {
28 return LHS
.Index
< RHS
.Index
;
31 bool BinaryBasicBlock::hasCFG() const { return getParent()->hasCFG(); }
33 bool BinaryBasicBlock::isEntryPoint() const {
34 return getParent()->isEntryPoint(*this);
37 bool BinaryBasicBlock::hasInstructions() const {
38 return getParent()->hasInstructions();
41 const JumpTable
*BinaryBasicBlock::getJumpTable() const {
42 const MCInst
*Inst
= getLastNonPseudoInstr();
43 const JumpTable
*JT
= Inst
? Function
->getJumpTable(*Inst
) : nullptr;
47 void BinaryBasicBlock::adjustNumPseudos(const MCInst
&Inst
, int Sign
) {
48 BinaryContext
&BC
= Function
->getBinaryContext();
49 if (BC
.MIB
->isPseudo(Inst
))
53 BinaryBasicBlock::iterator
BinaryBasicBlock::getFirstNonPseudo() {
54 const BinaryContext
&BC
= Function
->getBinaryContext();
55 for (auto II
= Instructions
.begin(), E
= Instructions
.end(); II
!= E
; ++II
) {
56 if (!BC
.MIB
->isPseudo(*II
))
62 BinaryBasicBlock::reverse_iterator
BinaryBasicBlock::getLastNonPseudo() {
63 const BinaryContext
&BC
= Function
->getBinaryContext();
64 for (auto RII
= Instructions
.rbegin(), E
= Instructions
.rend(); RII
!= E
;
66 if (!BC
.MIB
->isPseudo(*RII
))
72 bool BinaryBasicBlock::validateSuccessorInvariants() {
73 const MCInst
*Inst
= getLastNonPseudoInstr();
74 const JumpTable
*JT
= Inst
? Function
->getJumpTable(*Inst
) : nullptr;
75 BinaryContext
&BC
= Function
->getBinaryContext();
79 // Note: for now we assume that successors do not reference labels from
80 // any overlapping jump tables. We only look at the entries for the jump
81 // table that is referenced at the last instruction.
82 const auto Range
= JT
->getEntriesForAddress(BC
.MIB
->getJumpTable(*Inst
));
83 const std::vector
<const MCSymbol
*> Entries(
84 std::next(JT
->Entries
.begin(), Range
.first
),
85 std::next(JT
->Entries
.begin(), Range
.second
));
86 std::set
<const MCSymbol
*> UniqueSyms(Entries
.begin(), Entries
.end());
87 for (BinaryBasicBlock
*Succ
: Successors
) {
88 auto Itr
= UniqueSyms
.find(Succ
->getLabel());
89 if (Itr
!= UniqueSyms
.end()) {
90 UniqueSyms
.erase(Itr
);
92 // Work on the assumption that jump table blocks don't
93 // have a conditional successor.
95 errs() << "BOLT-WARNING: Jump table successor " << Succ
->getName()
96 << " not contained in the jump table.\n";
99 // If there are any leftover entries in the jump table, they
100 // must be one of the function end labels.
102 for (const MCSymbol
*Sym
: UniqueSyms
) {
103 Valid
&= (Sym
== Function
->getFunctionEndLabel() ||
104 Sym
== Function
->getFunctionEndLabel(getFragmentNum()));
106 errs() << "BOLT-WARNING: Jump table contains illegal entry: "
107 << Sym
->getName() << "\n";
112 // Unknown control flow.
113 if (Inst
&& BC
.MIB
->isIndirectBranch(*Inst
))
116 const MCSymbol
*TBB
= nullptr;
117 const MCSymbol
*FBB
= nullptr;
118 MCInst
*CondBranch
= nullptr;
119 MCInst
*UncondBranch
= nullptr;
121 if (analyzeBranch(TBB
, FBB
, CondBranch
, UncondBranch
)) {
122 switch (Successors
.size()) {
124 Valid
= !CondBranch
&& !UncondBranch
;
127 const bool HasCondBlock
=
128 CondBranch
&& Function
->getBasicBlockForLabel(
129 BC
.MIB
->getTargetSymbol(*CondBranch
));
130 Valid
= !CondBranch
|| !HasCondBlock
;
134 Valid
= (CondBranch
&&
135 (TBB
== getConditionalSuccessor(true)->getLabel() &&
136 ((!UncondBranch
&& !FBB
) ||
138 FBB
== getConditionalSuccessor(false)->getLabel()))));
144 errs() << "BOLT-WARNING: CFG invalid in " << *getFunction() << " @ "
145 << getName() << "\n";
147 errs() << "Jump Table instruction addr = 0x"
148 << Twine::utohexstr(BC
.MIB
->getJumpTable(*Inst
)) << "\n";
151 getFunction()->dump();
156 BinaryBasicBlock
*BinaryBasicBlock::getSuccessor(const MCSymbol
*Label
) const {
157 if (!Label
&& succ_size() == 1)
158 return *succ_begin();
160 for (BinaryBasicBlock
*BB
: successors())
161 if (BB
->getLabel() == Label
)
167 BinaryBasicBlock
*BinaryBasicBlock::getSuccessor(const MCSymbol
*Label
,
168 BinaryBranchInfo
&BI
) const {
169 auto BIIter
= branch_info_begin();
170 for (BinaryBasicBlock
*BB
: successors()) {
171 if (BB
->getLabel() == Label
) {
181 BinaryBasicBlock
*BinaryBasicBlock::getLandingPad(const MCSymbol
*Label
) const {
182 for (BinaryBasicBlock
*BB
: landing_pads())
183 if (BB
->getLabel() == Label
)
189 int32_t BinaryBasicBlock::getCFIStateAtInstr(const MCInst
*Instr
) const {
191 getFunction()->getState() >= BinaryFunction::State::CFG
&&
192 "can only calculate CFI state when function is in or past the CFG state");
194 const BinaryFunction::CFIInstrMapType
&FDEProgram
=
195 getFunction()->getFDEProgram();
197 // Find the last CFI preceding Instr in this basic block.
198 const MCInst
*LastCFI
= nullptr;
199 bool InstrSeen
= (Instr
== nullptr);
200 for (const MCInst
&Inst
: llvm::reverse(Instructions
)) {
202 InstrSeen
= (&Inst
== Instr
);
205 if (Function
->getBinaryContext().MIB
->isCFI(Inst
)) {
211 assert(InstrSeen
&& "instruction expected in basic block");
213 // CFI state is the same as at basic block entry point.
215 return getCFIState();
217 // Fold all RememberState/RestoreState sequences, such as for:
220 // RememberState (#K)
229 // RestoreState <- LastCFI
231 // we return K - the most efficient state to (re-)generate.
232 int64_t State
= LastCFI
->getOperand(0).getImm();
234 FDEProgram
[State
].getOperation() == MCCFIInstruction::OpRestoreState
) {
237 assert(State
>= 0 && "first CFI cannot be RestoreState");
238 while (Depth
&& State
>= 0) {
239 const MCCFIInstruction
&CFIInstr
= FDEProgram
[State
];
240 if (CFIInstr
.getOperation() == MCCFIInstruction::OpRestoreState
)
242 else if (CFIInstr
.getOperation() == MCCFIInstruction::OpRememberState
)
246 assert(Depth
== 0 && "unbalanced RememberState/RestoreState stack");
248 // Skip any GNU_args_size.
249 while (State
>= 0 && FDEProgram
[State
].getOperation() ==
250 MCCFIInstruction::OpGnuArgsSize
) {
255 assert((State
+ 1 >= 0) && "miscalculated CFI state");
259 void BinaryBasicBlock::addSuccessor(BinaryBasicBlock
*Succ
, uint64_t Count
,
260 uint64_t MispredictedCount
) {
261 Successors
.push_back(Succ
);
262 BranchInfo
.push_back({Count
, MispredictedCount
});
263 Succ
->Predecessors
.push_back(this);
266 void BinaryBasicBlock::replaceSuccessor(BinaryBasicBlock
*Succ
,
267 BinaryBasicBlock
*NewSucc
,
269 uint64_t MispredictedCount
) {
270 Succ
->removePredecessor(this, /*Multiple=*/false);
271 auto I
= succ_begin();
272 auto BI
= BranchInfo
.begin();
273 for (; I
!= succ_end(); ++I
) {
274 assert(BI
!= BranchInfo
.end() && "missing BranchInfo entry");
279 assert(I
!= succ_end() && "no such successor!");
282 *BI
= BinaryBranchInfo
{Count
, MispredictedCount
};
283 NewSucc
->addPredecessor(this);
286 void BinaryBasicBlock::removeAllSuccessors() {
287 SmallPtrSet
<BinaryBasicBlock
*, 2> UniqSuccessors(succ_begin(), succ_end());
288 for (BinaryBasicBlock
*SuccessorBB
: UniqSuccessors
)
289 SuccessorBB
->removePredecessor(this);
294 void BinaryBasicBlock::removeSuccessor(BinaryBasicBlock
*Succ
) {
295 Succ
->removePredecessor(this, /*Multiple=*/false);
296 auto I
= succ_begin();
297 auto BI
= BranchInfo
.begin();
298 for (; I
!= succ_end(); ++I
) {
299 assert(BI
!= BranchInfo
.end() && "missing BranchInfo entry");
304 assert(I
!= succ_end() && "no such successor!");
307 BranchInfo
.erase(BI
);
310 void BinaryBasicBlock::addPredecessor(BinaryBasicBlock
*Pred
) {
311 Predecessors
.push_back(Pred
);
314 void BinaryBasicBlock::removePredecessor(BinaryBasicBlock
*Pred
,
316 // Note: the predecessor could be listed multiple times.
318 for (auto PredI
= Predecessors
.begin(); PredI
!= Predecessors
.end();) {
319 if (*PredI
== Pred
) {
321 PredI
= Predecessors
.erase(PredI
);
328 assert(Erased
&& "Pred is not a predecessor of this block!");
332 void BinaryBasicBlock::removeDuplicateConditionalSuccessor(MCInst
*CondBranch
) {
333 assert(succ_size() == 2 && Successors
[0] == Successors
[1] &&
334 "conditional successors expected");
336 BinaryBasicBlock
*Succ
= Successors
[0];
337 const BinaryBranchInfo CondBI
= BranchInfo
[0];
338 const BinaryBranchInfo UncondBI
= BranchInfo
[1];
340 eraseInstruction(findInstruction(CondBranch
));
345 Successors
.push_back(Succ
);
347 uint64_t Count
= COUNT_NO_PROFILE
;
348 if (CondBI
.Count
!= COUNT_NO_PROFILE
&& UncondBI
.Count
!= COUNT_NO_PROFILE
)
349 Count
= CondBI
.Count
+ UncondBI
.Count
;
350 BranchInfo
.push_back({Count
, 0});
353 void BinaryBasicBlock::updateJumpTableSuccessors() {
354 const JumpTable
*JT
= getJumpTable();
355 assert(JT
&& "Expected jump table instruction.");
357 // Clear existing successors.
358 removeAllSuccessors();
360 // Generate the list of successors in deterministic order without duplicates.
361 SmallVector
<BinaryBasicBlock
*, 16> SuccessorBBs
;
362 for (const MCSymbol
*Label
: JT
->Entries
) {
363 BinaryBasicBlock
*BB
= getFunction()->getBasicBlockForLabel(Label
);
364 // Ignore __builtin_unreachable()
366 assert(Label
== getFunction()->getFunctionEndLabel() &&
367 "JT label should match a block or end of function.");
370 SuccessorBBs
.emplace_back(BB
);
372 llvm::sort(SuccessorBBs
,
373 [](const BinaryBasicBlock
*BB1
, const BinaryBasicBlock
*BB2
) {
374 return BB1
->getInputOffset() < BB2
->getInputOffset();
376 SuccessorBBs
.erase(std::unique(SuccessorBBs
.begin(), SuccessorBBs
.end()),
379 for (BinaryBasicBlock
*BB
: SuccessorBBs
)
383 void BinaryBasicBlock::adjustExecutionCount(double Ratio
) {
384 auto adjustedCount
= [&](uint64_t Count
) -> uint64_t {
385 double NewCount
= Count
* Ratio
;
386 if (!NewCount
&& Count
&& (Ratio
> 0.0))
391 setExecutionCount(adjustedCount(getKnownExecutionCount()));
392 for (BinaryBranchInfo
&BI
: branch_info()) {
393 if (BI
.Count
!= COUNT_NO_PROFILE
)
394 BI
.Count
= adjustedCount(BI
.Count
);
395 if (BI
.MispredictedCount
!= COUNT_INFERRED
)
396 BI
.MispredictedCount
= adjustedCount(BI
.MispredictedCount
);
400 bool BinaryBasicBlock::analyzeBranch(const MCSymbol
*&TBB
, const MCSymbol
*&FBB
,
402 MCInst
*&UncondBranch
) {
403 auto &MIB
= Function
->getBinaryContext().MIB
;
404 return MIB
->analyzeBranch(Instructions
.begin(), Instructions
.end(), TBB
, FBB
,
405 CondBranch
, UncondBranch
);
408 bool BinaryBasicBlock::isMacroOpFusionPair(const_iterator I
) const {
409 auto &MIB
= Function
->getBinaryContext().MIB
;
410 ArrayRef
<MCInst
> Insts
= Instructions
;
411 return MIB
->isMacroOpFusionPair(Insts
.slice(I
- begin()));
414 BinaryBasicBlock::const_iterator
415 BinaryBasicBlock::getMacroOpFusionPair() const {
416 if (!Function
->getBinaryContext().isX86())
419 if (getNumNonPseudos() < 2 || succ_size() != 2)
422 auto RI
= getLastNonPseudo();
423 assert(RI
!= rend() && "cannot have an empty block with 2 successors");
425 BinaryContext
&BC
= Function
->getBinaryContext();
427 // Skip instruction if it's an unconditional branch following
428 // a conditional one.
429 if (BC
.MIB
->isUnconditionalBranch(*RI
))
432 if (!BC
.MIB
->isConditionalBranch(*RI
))
435 // Start checking with instruction preceding the conditional branch.
440 auto II
= std::prev(RI
.base()); // convert to a forward iterator
441 if (isMacroOpFusionPair(II
))
447 MCInst
*BinaryBasicBlock::getTerminatorBefore(MCInst
*Pos
) {
448 BinaryContext
&BC
= Function
->getBinaryContext();
450 bool Check
= Pos
? false : true;
451 MCInst
*FirstTerminator
= nullptr;
452 while (Itr
!= rend()) {
459 if (BC
.MIB
->isTerminator(*Itr
))
460 FirstTerminator
= &*Itr
;
463 return FirstTerminator
;
466 bool BinaryBasicBlock::hasTerminatorAfter(MCInst
*Pos
) {
467 BinaryContext
&BC
= Function
->getBinaryContext();
469 while (Itr
!= rend()) {
472 if (BC
.MIB
->isTerminator(*Itr
))
479 bool BinaryBasicBlock::swapConditionalSuccessors() {
480 if (succ_size() != 2)
483 std::swap(Successors
[0], Successors
[1]);
484 std::swap(BranchInfo
[0], BranchInfo
[1]);
488 void BinaryBasicBlock::addBranchInstruction(const BinaryBasicBlock
*Successor
) {
489 assert(isSuccessor(Successor
));
490 BinaryContext
&BC
= Function
->getBinaryContext();
492 std::unique_lock
<llvm::sys::RWMutex
> Lock(BC
.CtxMutex
);
493 BC
.MIB
->createUncondBranch(NewInst
, Successor
->getLabel(), BC
.Ctx
.get());
494 Instructions
.emplace_back(std::move(NewInst
));
497 void BinaryBasicBlock::addTailCallInstruction(const MCSymbol
*Target
) {
498 BinaryContext
&BC
= Function
->getBinaryContext();
500 BC
.MIB
->createTailCall(NewInst
, Target
, BC
.Ctx
.get());
501 Instructions
.emplace_back(std::move(NewInst
));
504 uint32_t BinaryBasicBlock::getNumCalls() const {
506 BinaryContext
&BC
= Function
->getBinaryContext();
507 for (const MCInst
&Instr
: Instructions
) {
508 if (BC
.MIB
->isCall(Instr
))
514 uint32_t BinaryBasicBlock::getNumPseudos() const {
516 BinaryContext
&BC
= Function
->getBinaryContext();
518 for (const MCInst
&Instr
: Instructions
)
519 if (BC
.MIB
->isPseudo(Instr
))
522 if (N
!= NumPseudos
) {
523 errs() << "BOLT-ERROR: instructions for basic block " << getName()
524 << " in function " << *Function
<< ": calculated pseudos " << N
525 << ", set pseudos " << NumPseudos
<< ", size " << size() << '\n';
526 llvm_unreachable("pseudos mismatch");
532 ErrorOr
<std::pair
<double, double>>
533 BinaryBasicBlock::getBranchStats(const BinaryBasicBlock
*Succ
) const {
534 if (Function
->hasValidProfile()) {
535 uint64_t TotalCount
= 0;
536 uint64_t TotalMispreds
= 0;
537 for (const BinaryBranchInfo
&BI
: BranchInfo
) {
538 if (BI
.Count
!= COUNT_NO_PROFILE
) {
539 TotalCount
+= BI
.Count
;
540 TotalMispreds
+= BI
.MispredictedCount
;
544 if (TotalCount
> 0) {
545 auto Itr
= llvm::find(Successors
, Succ
);
546 assert(Itr
!= Successors
.end());
547 const BinaryBranchInfo
&BI
= BranchInfo
[Itr
- Successors
.begin()];
548 if (BI
.Count
&& BI
.Count
!= COUNT_NO_PROFILE
) {
549 if (TotalMispreds
== 0)
551 return std::make_pair(double(BI
.Count
) / TotalCount
,
552 double(BI
.MispredictedCount
) / TotalMispreds
);
556 return make_error_code(llvm::errc::result_out_of_range
);
559 void BinaryBasicBlock::dump() const {
560 BinaryContext
&BC
= Function
->getBinaryContext();
562 outs() << Label
->getName() << ":\n";
563 BC
.printInstructions(outs(), Instructions
.begin(), Instructions
.end(),
564 getOffset(), Function
);
566 for (auto itr
= pred_begin(); itr
!= pred_end(); ++itr
) {
567 outs() << " " << (*itr
)->getName();
569 outs() << "\nsuccs:";
570 for (auto itr
= succ_begin(); itr
!= succ_end(); ++itr
) {
571 outs() << " " << (*itr
)->getName();
576 uint64_t BinaryBasicBlock::estimateSize(const MCCodeEmitter
*Emitter
) const {
577 return Function
->getBinaryContext().computeCodeSize(begin(), end(), Emitter
);
580 BinaryBasicBlock::BinaryBranchInfo
&
581 BinaryBasicBlock::getBranchInfo(const BinaryBasicBlock
&Succ
) {
582 return const_cast<BinaryBranchInfo
&>(
583 static_cast<const BinaryBasicBlock
&>(*this).getBranchInfo(Succ
));
586 const BinaryBasicBlock::BinaryBranchInfo
&
587 BinaryBasicBlock::getBranchInfo(const BinaryBasicBlock
&Succ
) const {
588 const auto Zip
= llvm::zip(successors(), branch_info());
589 const auto Result
= llvm::find_if(
590 Zip
, [&](const auto &Tuple
) { return std::get
<0>(Tuple
) == &Succ
; });
591 assert(Result
!= Zip
.end() && "Cannot find target in successors");
592 return std::get
<1>(*Result
);
595 BinaryBasicBlock
*BinaryBasicBlock::splitAt(iterator II
) {
596 assert(II
!= end() && "expected iterator pointing to instruction");
598 BinaryBasicBlock
*NewBlock
= getFunction()->addBasicBlock();
600 // Adjust successors/predecessors and propagate the execution count.
601 moveAllSuccessorsTo(NewBlock
);
602 addSuccessor(NewBlock
, getExecutionCount(), 0);
604 // Set correct CFI state for the new block.
605 NewBlock
->setCFIState(getCFIStateAtInstr(&*II
));
607 // Move instructions over.
608 adjustNumPseudos(II
, end(), -1);
609 NewBlock
->addInstructions(II
, end());
610 Instructions
.erase(II
, end());