aboutsummaryrefslogtreecommitdiff
path: root/llvm/lib/CodeGen/MachineBasicBlock.cpp
diff options
context:
space:
mode:
authorMatthias Braun <matze@braunis.de>2022-12-08 17:15:41 -0800
committerMatthias Braun <matze@braunis.de>2023-05-10 20:30:52 -0700
commitb8817825b9dcb45f204d3a3a9056f929e12c7a3b (patch)
treeb4a0d01367a2c5d0c2510eb811508f245fad0d9b /llvm/lib/CodeGen/MachineBasicBlock.cpp
parent220e77a83af19b3f6c47472596fdaaef8e305927 (diff)
downloadllvm-b8817825b9dcb45f204d3a3a9056f929e12c7a3b.zip
llvm-b8817825b9dcb45f204d3a3a9056f929e12c7a3b.tar.gz
llvm-b8817825b9dcb45f204d3a3a9056f929e12c7a3b.tar.bz2
Support critical edge splitting for jump tables
Add support for splitting critical edges coming from an indirect jump using a jump table ("switch jumps"). This introduces the `TargetInstrInfo::getJumpTableIndex` callback to allows targets to return an index into `MachineJumpTableInfo` for a given indirect jump. It also updates to `MachineBasicBlock::SplitCriticalEdge` to allow splitting of critical edges by rewriting jump table entries. This is largely based on work done by Zhixuan Huan in D132202. Differential Revision: https://reviews.llvm.org/D140975
Diffstat (limited to 'llvm/lib/CodeGen/MachineBasicBlock.cpp')
-rw-r--r--llvm/lib/CodeGen/MachineBasicBlock.cpp75
1 files changed, 73 insertions, 2 deletions
diff --git a/llvm/lib/CodeGen/MachineBasicBlock.cpp b/llvm/lib/CodeGen/MachineBasicBlock.cpp
index 47a475a..48b2aa4 100644
--- a/llvm/lib/CodeGen/MachineBasicBlock.cpp
+++ b/llvm/lib/CodeGen/MachineBasicBlock.cpp
@@ -18,6 +18,7 @@
#include "llvm/CodeGen/MachineDominators.h"
#include "llvm/CodeGen/MachineFunction.h"
#include "llvm/CodeGen/MachineInstrBuilder.h"
+#include "llvm/CodeGen/MachineJumpTableInfo.h"
#include "llvm/CodeGen/MachineLoopInfo.h"
#include "llvm/CodeGen/MachineRegisterInfo.h"
#include "llvm/CodeGen/SlotIndexes.h"
@@ -664,6 +665,15 @@ void MachineBasicBlock::moveAfter(MachineBasicBlock *NewBefore) {
getParent()->splice(++NewBefore->getIterator(), getIterator());
}
+static int findJumpTableIndex(const MachineBasicBlock &MBB) {
+ MachineBasicBlock::const_iterator TerminatorI = MBB.getFirstTerminator();
+ if (TerminatorI == MBB.end())
+ return -1;
+ const MachineInstr &Terminator = *TerminatorI;
+ const TargetInstrInfo *TII = MBB.getParent()->getSubtarget().getInstrInfo();
+ return TII->getJumpTableIndex(Terminator);
+}
+
void MachineBasicBlock::updateTerminator(
MachineBasicBlock *PreviousLayoutSuccessor) {
LLVM_DEBUG(dbgs() << "Updating terminators on " << printMBBReference(*this)
@@ -1033,6 +1043,50 @@ MachineBasicBlock *MachineBasicBlock::splitAt(MachineInstr &MI,
return SplitBB;
}
+// Returns `true` if there are possibly other users of the jump table at
+// `JumpTableIndex` except for the ones in `IgnoreMBB`.
+static bool jumpTableHasOtherUses(const MachineFunction &MF,
+ const MachineBasicBlock &IgnoreMBB,
+ int JumpTableIndex) {
+ assert(JumpTableIndex >= 0 && "need valid index");
+ const MachineJumpTableInfo &MJTI = *MF.getJumpTableInfo();
+ const MachineJumpTableEntry &MJTE = MJTI.getJumpTables()[JumpTableIndex];
+ // Take any basic block from the table; every user of the jump table must
+ // show up in the predecessor list.
+ const MachineBasicBlock *MBB = nullptr;
+ for (MachineBasicBlock *B : MJTE.MBBs) {
+ if (B != nullptr) {
+ MBB = B;
+ break;
+ }
+ }
+ if (MBB == nullptr)
+ return true; // can't rule out other users if there isn't any block.
+ const TargetInstrInfo &TII = *MF.getSubtarget().getInstrInfo();
+ SmallVector<MachineOperand, 4> Cond;
+ for (MachineBasicBlock *Pred : MBB->predecessors()) {
+ if (Pred == &IgnoreMBB)
+ continue;
+ MachineBasicBlock *DummyT = nullptr;
+ MachineBasicBlock *DummyF = nullptr;
+ Cond.clear();
+ if (!TII.analyzeBranch(*Pred, DummyT, DummyF, Cond,
+ /*AllowModify=*/false)) {
+ // analyzable direct jump
+ continue;
+ }
+ int PredJTI = findJumpTableIndex(*Pred);
+ if (PredJTI >= 0) {
+ if (PredJTI == JumpTableIndex)
+ return true;
+ continue;
+ }
+ // Be conservative for unanalyzable jumps.
+ return true;
+ }
+ return false;
+}
+
MachineBasicBlock *MachineBasicBlock::SplitCriticalEdge(
MachineBasicBlock *Succ, Pass &P,
std::vector<SparseBitVector<>> *LiveInSets) {
@@ -1044,6 +1098,16 @@ MachineBasicBlock *MachineBasicBlock::SplitCriticalEdge(
DebugLoc DL; // FIXME: this is nowhere
MachineBasicBlock *NMBB = MF->CreateMachineBasicBlock();
+
+ // Is there an indirect jump with jump table?
+ bool ChangedIndirectJump = false;
+ int JTI = findJumpTableIndex(*this);
+ if (JTI >= 0) {
+ MachineJumpTableInfo &MJTI = *MF->getJumpTableInfo();
+ MJTI.ReplaceMBBInJumpTable(JTI, Succ, NMBB);
+ ChangedIndirectJump = true;
+ }
+
MF->insert(std::next(MachineFunction::iterator(this)), NMBB);
LLVM_DEBUG(dbgs() << "Splitting critical edge: " << printMBBReference(*this)
<< " -- " << printMBBReference(*NMBB) << " -- "
@@ -1109,7 +1173,9 @@ MachineBasicBlock *MachineBasicBlock::SplitCriticalEdge(
// as the fallthrough successor
if (Succ == PrevFallthrough)
PrevFallthrough = NMBB;
- updateTerminator(PrevFallthrough);
+
+ if (!ChangedIndirectJump)
+ updateTerminator(PrevFallthrough);
if (Indexes) {
SmallVector<MachineInstr*, 4> NewTerminators;
@@ -1284,8 +1350,13 @@ bool MachineBasicBlock::canSplitCriticalEdge(
if (MF->getTarget().requiresStructuredCFG())
return false;
+ // Do we have an Indirect jump with a jumptable that we can rewrite?
+ int JTI = findJumpTableIndex(*this);
+ if (JTI >= 0 && !jumpTableHasOtherUses(*MF, *this, JTI))
+ return true;
+
// We may need to update this's terminator, but we can't do that if
- // analyzeBranch fails. If this uses a jump table, we won't touch it.
+ // analyzeBranch fails.
const TargetInstrInfo *TII = MF->getSubtarget().getInstrInfo();
MachineBasicBlock *TBB = nullptr, *FBB = nullptr;
SmallVector<MachineOperand, 4> Cond;