aboutsummaryrefslogtreecommitdiff
path: root/contrib/llvm-project/llvm/lib/CodeGen/BranchRelaxation.cpp
diff options
context:
space:
mode:
authorDimitry Andric <dim@FreeBSD.org>2022-03-20 11:40:34 +0000
committerDimitry Andric <dim@FreeBSD.org>2022-05-14 11:43:05 +0000
commit349cc55c9796c4596a5b9904cd3281af295f878f (patch)
tree410c5a785075730a35f1272ca6a7adf72222ad03 /contrib/llvm-project/llvm/lib/CodeGen/BranchRelaxation.cpp
parentcb2ae6163174b90e999326ecec3699ee093a5d43 (diff)
parentc0981da47d5696fe36474fcf86b4ce03ae3ff818 (diff)
Diffstat (limited to 'contrib/llvm-project/llvm/lib/CodeGen/BranchRelaxation.cpp')
-rw-r--r--contrib/llvm-project/llvm/lib/CodeGen/BranchRelaxation.cpp42
1 files changed, 40 insertions, 2 deletions
diff --git a/contrib/llvm-project/llvm/lib/CodeGen/BranchRelaxation.cpp b/contrib/llvm-project/llvm/lib/CodeGen/BranchRelaxation.cpp
index 366c303614d6..50825ccf9bac 100644
--- a/contrib/llvm-project/llvm/lib/CodeGen/BranchRelaxation.cpp
+++ b/contrib/llvm-project/llvm/lib/CodeGen/BranchRelaxation.cpp
@@ -463,10 +463,48 @@ bool BranchRelaxation::fixupUnconditionalBranch(MachineInstr &MI) {
DebugLoc DL = MI.getDebugLoc();
MI.eraseFromParent();
- BlockInfo[BranchBB->getNumber()].Size += TII->insertIndirectBranch(
- *BranchBB, *DestBB, DL, DestOffset - SrcOffset, RS.get());
+ // Create the optional restore block and, initially, place it at the end of
+ // function. That block will be placed later if it's used; otherwise, it will
+ // be erased.
+ MachineBasicBlock *RestoreBB = createNewBlockAfter(MF->back());
+
+ TII->insertIndirectBranch(*BranchBB, *DestBB, *RestoreBB, DL,
+ DestOffset - SrcOffset, RS.get());
+
+ BlockInfo[BranchBB->getNumber()].Size = computeBlockSize(*BranchBB);
adjustBlockOffsets(*MBB);
+
+ // If RestoreBB is required, try to place just before DestBB.
+ if (!RestoreBB->empty()) {
+ // TODO: For multiple far branches to the same destination, there are
+ // chances that some restore blocks could be shared if they clobber the
+ // same registers and share the same restore sequence. So far, those
+ // restore blocks are just duplicated for each far branch.
+ assert(!DestBB->isEntryBlock());
+ MachineBasicBlock *PrevBB = &*std::prev(DestBB->getIterator());
+ if (auto *FT = PrevBB->getFallThrough()) {
+ assert(FT == DestBB);
+ TII->insertUnconditionalBranch(*PrevBB, FT, DebugLoc());
+ // Recalculate the block size.
+ BlockInfo[PrevBB->getNumber()].Size = computeBlockSize(*PrevBB);
+ }
+ // Now, RestoreBB could be placed directly before DestBB.
+ MF->splice(DestBB->getIterator(), RestoreBB->getIterator());
+ // Update successors and predecessors.
+ RestoreBB->addSuccessor(DestBB);
+ BranchBB->replaceSuccessor(DestBB, RestoreBB);
+ if (TRI->trackLivenessAfterRegAlloc(*MF))
+ computeAndAddLiveIns(LiveRegs, *RestoreBB);
+ // Compute the restore block size.
+ BlockInfo[RestoreBB->getNumber()].Size = computeBlockSize(*RestoreBB);
+ // Update the offset starting from the previous block.
+ adjustBlockOffsets(*PrevBB);
+ } else {
+ // Remove restore block if it's not required.
+ MF->erase(RestoreBB);
+ }
+
return true;
}