diff options
author | Matthias Braun <matze@braunis.de> | 2022-12-08 17:15:41 -0800 |
---|---|---|
committer | Matthias Braun <matze@braunis.de> | 2023-05-10 20:30:52 -0700 |
commit | b8817825b9dcb45f204d3a3a9056f929e12c7a3b (patch) | |
tree | b4a0d01367a2c5d0c2510eb811508f245fad0d9b /llvm/lib/CodeGen/MachineBasicBlock.cpp | |
parent | 220e77a83af19b3f6c47472596fdaaef8e305927 (diff) | |
download | llvm-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.cpp | 75 |
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; |