1
0
mirror of https://github.com/RPCS3/llvm-mirror.git synced 2024-11-26 04:32:44 +01:00

MachineBasicBlock::updateTerminator now requires an explicit layout successor.

Previously, it tried to infer the correct destination block from the
successor list, but this is a rather tricky propspect, given the
existence of successors that occur mid-block, such as invoke, and
potentially in the future, callbr/INLINEASM_BR. (INLINEASM_BR, in
particular would be problematic, because its successor blocks are not
distinct from "normal" successors, as EHPads are.)

Instead, require the caller to pass in the expected fallthrough
successor explicitly. In most callers, the correct block is
immediately clear. But, in MachineBlockPlacement, we do need to record
the original ordering, before starting to reorder blocks.

Unfortunately, the goal of decoupling the behavior of end-of-block
jumps from the successor list has not been fully accomplished in this
patch, as there is currently no other way to determine whether a block
is intended to fall-through, or end as unreachable. Further work is
needed there.

Differential Revision: https://reviews.llvm.org/D79605
This commit is contained in:
James Y Knight 2020-02-19 10:41:28 -05:00
parent 1bcdec3cb9
commit f92fad214d
11 changed files with 101 additions and 74 deletions

View File

@ -514,11 +514,13 @@ public:
return getSectionID() == MBB->getSectionID(); return getSectionID() == MBB->getSectionID();
} }
/// Update the terminator instructions in block to account for changes to the /// Update the terminator instructions in block to account for changes to
/// layout. If the block previously used a fallthrough, it may now need a /// block layout which may have been made. PreviousLayoutSuccessor should be
/// branch, and if it previously used branching it may now be able to use a /// set to the block which may have been used as fallthrough before the block
/// fallthrough. /// layout was modified. If the block previously fell through to that block,
void updateTerminator(); /// it may now need a branch. If it previously branched to another block, it
/// may now be able to fallthrough to the current layout successor.
void updateTerminator(MachineBasicBlock *PreviousLayoutSuccessor);
// Machine-CFG mutators // Machine-CFG mutators

View File

@ -180,7 +180,7 @@ static void updateBranches(
MachineBasicBlock *TBB = nullptr, *FBB = nullptr; // For analyzeBranch. MachineBasicBlock *TBB = nullptr, *FBB = nullptr; // For analyzeBranch.
if (TII->analyzeBranch(MBB, TBB, FBB, Cond)) if (TII->analyzeBranch(MBB, TBB, FBB, Cond))
continue; continue;
MBB.updateTerminator(); MBB.updateTerminator(FTMBB);
} }
} }

View File

@ -245,8 +245,7 @@ MachineBasicBlock *BranchRelaxation::splitBlockBeforeInstr(MachineInstr &MI,
// Cleanup potential unconditional branch to successor block. // Cleanup potential unconditional branch to successor block.
// Note that updateTerminator may change the size of the blocks. // Note that updateTerminator may change the size of the blocks.
NewBB->updateTerminator(); OrigBB->updateTerminator(NewBB);
OrigBB->updateTerminator();
// Figure out how large the OrigBB is. As the first half of the original // Figure out how large the OrigBB is. As the first half of the original
// block, it cannot contain a tablejump. The size includes // block, it cannot contain a tablejump. The size includes

View File

@ -559,7 +559,11 @@ void MachineBasicBlock::moveAfter(MachineBasicBlock *NewBefore) {
getParent()->splice(++NewBefore->getIterator(), getIterator()); getParent()->splice(++NewBefore->getIterator(), getIterator());
} }
void MachineBasicBlock::updateTerminator() { void MachineBasicBlock::updateTerminator(
MachineBasicBlock *PreviousLayoutSuccessor) {
LLVM_DEBUG(dbgs() << "Updating terminators on " << printMBBReference(*this)
<< "\n");
const TargetInstrInfo *TII = getParent()->getSubtarget().getInstrInfo(); const TargetInstrInfo *TII = getParent()->getSubtarget().getInstrInfo();
// A block with no successors has no concerns with fall-through edges. // A block with no successors has no concerns with fall-through edges.
if (this->succ_empty()) if (this->succ_empty())
@ -578,25 +582,21 @@ void MachineBasicBlock::updateTerminator() {
if (isLayoutSuccessor(TBB)) if (isLayoutSuccessor(TBB))
TII->removeBranch(*this); TII->removeBranch(*this);
} else { } else {
// The block has an unconditional fallthrough. If its successor is not its // The block has an unconditional fallthrough, or the end of the block is
// layout successor, insert a branch. First we have to locate the only // unreachable.
// non-landing-pad successor, as that is the fallthrough block.
for (succ_iterator SI = succ_begin(), SE = succ_end(); SI != SE; ++SI) {
if ((*SI)->isEHPad())
continue;
assert(!TBB && "Found more than one non-landing-pad successor!");
TBB = *SI;
}
// If there is no non-landing-pad successor, the block has no fall-through // Unfortunately, whether the end of the block is unreachable is not
// edges to be concerned with. // immediately obvious; we must fall back to checking the successor list,
if (!TBB) // and assuming that if the passed in block is in the succesor list and
// not an EHPad, it must be the intended target.
if (!PreviousLayoutSuccessor || !isSuccessor(PreviousLayoutSuccessor) ||
PreviousLayoutSuccessor->isEHPad())
return; return;
// Finally update the unconditional successor to be reached via a branch // If the unconditional successor block is not the current layout
// if it would not be reached by fallthrough. // successor, insert a branch to jump to it.
if (!isLayoutSuccessor(TBB)) if (!isLayoutSuccessor(PreviousLayoutSuccessor))
TII->insertBranch(*this, TBB, nullptr, Cond, DL); TII->insertBranch(*this, PreviousLayoutSuccessor, nullptr, Cond, DL);
} }
return; return;
} }
@ -617,38 +617,20 @@ void MachineBasicBlock::updateTerminator() {
return; return;
} }
// Walk through the successors and find the successor which is not a landing // We now know we're going to fallthrough to PreviousLayoutSuccessor.
// pad and is not the conditional branch destination (in TBB) as the assert(PreviousLayoutSuccessor);
// fallthrough successor. assert(!PreviousLayoutSuccessor->isEHPad());
MachineBasicBlock *FallthroughBB = nullptr; assert(isSuccessor(PreviousLayoutSuccessor));
for (succ_iterator SI = succ_begin(), SE = succ_end(); SI != SE; ++SI) {
if ((*SI)->isEHPad() || *SI == TBB)
continue;
assert(!FallthroughBB && "Found more than one fallthrough successor.");
FallthroughBB = *SI;
}
if (!FallthroughBB) { if (PreviousLayoutSuccessor == TBB) {
if (canFallThrough()) { // We had a fallthrough to the same basic block as the conditional jump
// We fallthrough to the same basic block as the conditional jump targets. // targets. Remove the conditional jump, leaving an unconditional
// Remove the conditional jump, leaving unconditional fallthrough. // fallthrough or an unconditional jump.
// FIXME: This does not seem like a reasonable pattern to support, but it
// has been seen in the wild coming out of degenerate ARM test cases.
TII->removeBranch(*this);
// Finally update the unconditional successor to be reached via a branch if
// it would not be reached by fallthrough.
if (!isLayoutSuccessor(TBB))
TII->insertBranch(*this, TBB, nullptr, Cond, DL);
return;
}
// We enter here iff exactly one successor is TBB which cannot fallthrough
// and the rest successors if any are EHPads. In this case, we need to
// change the conditional branch into unconditional branch.
TII->removeBranch(*this); TII->removeBranch(*this);
Cond.clear(); if (!isLayoutSuccessor(TBB)) {
TII->insertBranch(*this, TBB, nullptr, Cond, DL); Cond.clear();
TII->insertBranch(*this, TBB, nullptr, Cond, DL);
}
return; return;
} }
@ -657,14 +639,14 @@ void MachineBasicBlock::updateTerminator() {
if (TII->reverseBranchCondition(Cond)) { if (TII->reverseBranchCondition(Cond)) {
// We can't reverse the condition, add an unconditional branch. // We can't reverse the condition, add an unconditional branch.
Cond.clear(); Cond.clear();
TII->insertBranch(*this, FallthroughBB, nullptr, Cond, DL); TII->insertBranch(*this, PreviousLayoutSuccessor, nullptr, Cond, DL);
return; return;
} }
TII->removeBranch(*this); TII->removeBranch(*this);
TII->insertBranch(*this, FallthroughBB, nullptr, Cond, DL); TII->insertBranch(*this, PreviousLayoutSuccessor, nullptr, Cond, DL);
} else if (!isLayoutSuccessor(FallthroughBB)) { } else if (!isLayoutSuccessor(PreviousLayoutSuccessor)) {
TII->removeBranch(*this); TII->removeBranch(*this);
TII->insertBranch(*this, TBB, FallthroughBB, Cond, DL); TII->insertBranch(*this, TBB, PreviousLayoutSuccessor, Cond, DL);
} }
} }
@ -908,6 +890,7 @@ MachineBasicBlock *MachineBasicBlock::SplitCriticalEdge(
return nullptr; return nullptr;
MachineFunction *MF = getParent(); MachineFunction *MF = getParent();
MachineBasicBlock *PrevFallthrough = getNextNode();
DebugLoc DL; // FIXME: this is nowhere DebugLoc DL; // FIXME: this is nowhere
MachineBasicBlock *NMBB = MF->CreateMachineBasicBlock(); MachineBasicBlock *NMBB = MF->CreateMachineBasicBlock();
@ -978,7 +961,11 @@ MachineBasicBlock *MachineBasicBlock::SplitCriticalEdge(
Terminators.push_back(&*I); Terminators.push_back(&*I);
} }
updateTerminator(); // Since we replaced all uses of Succ with NMBB, that should also be treated
// as the fallthrough successor
if (Succ == PrevFallthrough)
PrevFallthrough = NMBB;
updateTerminator(PrevFallthrough);
if (Indexes) { if (Indexes) {
SmallVector<MachineInstr*, 4> NewTerminators; SmallVector<MachineInstr*, 4> NewTerminators;

View File

@ -2703,6 +2703,20 @@ void MachineBlockPlacement::buildCFGChains() {
assert(!BadFunc && "Detected problems with the block placement."); assert(!BadFunc && "Detected problems with the block placement.");
}); });
// Remember original layout ordering, so we can update terminators after
// reordering to point to the original layout successor.
SmallVector<MachineBasicBlock *, 4> OriginalLayoutSuccessors(
F->getNumBlockIDs());
{
MachineBasicBlock *LastMBB = nullptr;
for (auto &MBB : *F) {
if (LastMBB != nullptr)
OriginalLayoutSuccessors[LastMBB->getNumber()] = &MBB;
LastMBB = &MBB;
}
OriginalLayoutSuccessors[F->back().getNumber()] = nullptr;
}
// Splice the blocks into place. // Splice the blocks into place.
MachineFunction::iterator InsertPos = F->begin(); MachineFunction::iterator InsertPos = F->begin();
LLVM_DEBUG(dbgs() << "[MBP] Function: " << F->getName() << "\n"); LLVM_DEBUG(dbgs() << "[MBP] Function: " << F->getName() << "\n");
@ -2760,15 +2774,18 @@ void MachineBlockPlacement::buildCFGChains() {
// TBB = FBB = nullptr; // TBB = FBB = nullptr;
// } // }
// } // }
if (!TII->analyzeBranch(*PrevBB, TBB, FBB, Cond)) if (!TII->analyzeBranch(*PrevBB, TBB, FBB, Cond)) {
PrevBB->updateTerminator(); PrevBB->updateTerminator(OriginalLayoutSuccessors[PrevBB->getNumber()]);
}
} }
// Fixup the last block. // Fixup the last block.
Cond.clear(); Cond.clear();
MachineBasicBlock *TBB = nullptr, *FBB = nullptr; // For analyzeBranch. MachineBasicBlock *TBB = nullptr, *FBB = nullptr; // For analyzeBranch.
if (!TII->analyzeBranch(F->back(), TBB, FBB, Cond)) if (!TII->analyzeBranch(F->back(), TBB, FBB, Cond)) {
F->back().updateTerminator(); MachineBasicBlock *PrevBB = &F->back();
PrevBB->updateTerminator(OriginalLayoutSuccessors[PrevBB->getNumber()]);
}
BlockWorkList.clear(); BlockWorkList.clear();
EHPadWorkList.clear(); EHPadWorkList.clear();
@ -2802,7 +2819,6 @@ void MachineBlockPlacement::optimizeBranches() {
DebugLoc dl; // FIXME: this is nowhere DebugLoc dl; // FIXME: this is nowhere
TII->removeBranch(*ChainBB); TII->removeBranch(*ChainBB);
TII->insertBranch(*ChainBB, FBB, TBB, Cond, dl); TII->insertBranch(*ChainBB, FBB, TBB, Cond, dl);
ChainBB->updateTerminator();
} }
} }
} }

View File

@ -813,6 +813,8 @@ bool TailDuplicator::tailDuplicate(bool IsSimple, MachineBasicBlock *TailBB,
LLVM_DEBUG(dbgs() << "\n*** Tail-duplicating " << printMBBReference(*TailBB) LLVM_DEBUG(dbgs() << "\n*** Tail-duplicating " << printMBBReference(*TailBB)
<< '\n'); << '\n');
bool ShouldUpdateTerminators = TailBB->canFallThrough();
DenseSet<unsigned> UsedByPhi; DenseSet<unsigned> UsedByPhi;
getRegsUsedByPHIs(*TailBB, &UsedByPhi); getRegsUsedByPHIs(*TailBB, &UsedByPhi);
@ -885,6 +887,10 @@ bool TailDuplicator::tailDuplicate(bool IsSimple, MachineBasicBlock *TailBB,
for (MachineBasicBlock *Succ : TailBB->successors()) for (MachineBasicBlock *Succ : TailBB->successors())
PredBB->addSuccessor(Succ, MBPI->getEdgeProbability(TailBB, Succ)); PredBB->addSuccessor(Succ, MBPI->getEdgeProbability(TailBB, Succ));
// Update branches in pred to jump to tail's layout successor if needed.
if (ShouldUpdateTerminators)
PredBB->updateTerminator(TailBB->getNextNode());
Changed = true; Changed = true;
++NumTailDups; ++NumTailDups;
} }
@ -943,6 +949,11 @@ bool TailDuplicator::tailDuplicate(bool IsSimple, MachineBasicBlock *TailBB,
PrevBB->removeSuccessor(PrevBB->succ_begin()); PrevBB->removeSuccessor(PrevBB->succ_begin());
assert(PrevBB->succ_empty()); assert(PrevBB->succ_empty());
PrevBB->transferSuccessors(TailBB); PrevBB->transferSuccessors(TailBB);
// Update branches in PrevBB based on Tail's layout successor.
if (ShouldUpdateTerminators)
PrevBB->updateTerminator(TailBB->getNextNode());
TDBBs.push_back(PrevBB); TDBBs.push_back(PrevBB);
Changed = true; Changed = true;
} }

View File

@ -295,8 +295,6 @@ void AArch64ConditionOptimizer::modifyCmp(MachineInstr *CmpMI,
.add(BrMI.getOperand(1)); .add(BrMI.getOperand(1));
BrMI.eraseFromParent(); BrMI.eraseFromParent();
MBB->updateTerminator();
++NumConditionsAdjusted; ++NumConditionsAdjusted;
} }

View File

@ -710,7 +710,7 @@ void SSACCmpConv::convert(SmallVectorImpl<MachineBasicBlock *> &RemovedBlocks) {
.add(CmpMI->getOperand(1)); // Branch target. .add(CmpMI->getOperand(1)); // Branch target.
} }
CmpMI->eraseFromParent(); CmpMI->eraseFromParent();
Head->updateTerminator(); Head->updateTerminator(CmpBB->getNextNode());
RemovedBlocks.push_back(CmpBB); RemovedBlocks.push_back(CmpBB);
CmpBB->eraseFromParent(); CmpBB->eraseFromParent();

View File

@ -2361,6 +2361,7 @@ adjustJTTargetBlockForward(MachineBasicBlock *BB, MachineBasicBlock *JTBB) {
SmallVector<MachineOperand, 4> CondPrior; SmallVector<MachineOperand, 4> CondPrior;
MachineFunction::iterator BBi = BB->getIterator(); MachineFunction::iterator BBi = BB->getIterator();
MachineFunction::iterator OldPrior = std::prev(BBi); MachineFunction::iterator OldPrior = std::prev(BBi);
MachineFunction::iterator OldNext = std::next(BBi);
// If the block terminator isn't analyzable, don't try to move the block // If the block terminator isn't analyzable, don't try to move the block
bool B = TII->analyzeBranch(*BB, TBB, FBB, Cond); bool B = TII->analyzeBranch(*BB, TBB, FBB, Cond);
@ -2371,8 +2372,8 @@ adjustJTTargetBlockForward(MachineBasicBlock *BB, MachineBasicBlock *JTBB) {
if (!B && Cond.empty() && BB != &MF->front() && if (!B && Cond.empty() && BB != &MF->front() &&
!TII->analyzeBranch(*OldPrior, TBB, FBB, CondPrior)) { !TII->analyzeBranch(*OldPrior, TBB, FBB, CondPrior)) {
BB->moveAfter(JTBB); BB->moveAfter(JTBB);
OldPrior->updateTerminator(); OldPrior->updateTerminator(BB);
BB->updateTerminator(); BB->updateTerminator(OldNext != MF->end() ? &*OldNext : nullptr);
// Update numbering to account for the block being moved. // Update numbering to account for the block being moved.
MF->RenumberBlocks(); MF->RenumberBlocks();
++NumJTMoved; ++NumJTMoved;

View File

@ -1017,18 +1017,20 @@ void HexagonEarlyIfConversion::mergeBlocks(MachineBasicBlock *PredB,
PredB->removeSuccessor(SuccB); PredB->removeSuccessor(SuccB);
PredB->splice(PredB->end(), SuccB, SuccB->begin(), SuccB->end()); PredB->splice(PredB->end(), SuccB, SuccB->begin(), SuccB->end());
PredB->transferSuccessorsAndUpdatePHIs(SuccB); PredB->transferSuccessorsAndUpdatePHIs(SuccB);
MachineBasicBlock *OldLayoutSuccessor = SuccB->getNextNode();
removeBlock(SuccB); removeBlock(SuccB);
if (!TermOk) if (!TermOk)
PredB->updateTerminator(); PredB->updateTerminator(OldLayoutSuccessor);
} }
void HexagonEarlyIfConversion::simplifyFlowGraph(const FlowPattern &FP) { void HexagonEarlyIfConversion::simplifyFlowGraph(const FlowPattern &FP) {
MachineBasicBlock *OldLayoutSuccessor = FP.SplitB->getNextNode();
if (FP.TrueB) if (FP.TrueB)
removeBlock(FP.TrueB); removeBlock(FP.TrueB);
if (FP.FalseB) if (FP.FalseB)
removeBlock(FP.FalseB); removeBlock(FP.FalseB);
FP.SplitB->updateTerminator(); FP.SplitB->updateTerminator(OldLayoutSuccessor);
if (FP.SplitB->succ_size() != 1) if (FP.SplitB->succ_size() != 1)
return; return;

View File

@ -159,8 +159,16 @@ static void maybeUpdateTerminator(MachineBasicBlock *MBB) {
} }
assert((AnyBarrier || AllAnalyzable) && assert((AnyBarrier || AllAnalyzable) &&
"analyzeBranch needs to analyze any block with a fallthrough"); "analyzeBranch needs to analyze any block with a fallthrough");
// Find the layout successor from the original block order.
MachineFunction *MF = MBB->getParent();
MachineBasicBlock *OriginalSuccessor =
unsigned(MBB->getNumber() + 1) < MF->getNumBlockIDs()
? MF->getBlockNumbered(MBB->getNumber() + 1)
: nullptr;
if (AllAnalyzable) if (AllAnalyzable)
MBB->updateTerminator(); MBB->updateTerminator(OriginalSuccessor);
} }
namespace { namespace {
@ -247,9 +255,12 @@ struct Entry {
static void sortBlocks(MachineFunction &MF, const MachineLoopInfo &MLI, static void sortBlocks(MachineFunction &MF, const MachineLoopInfo &MLI,
const WebAssemblyExceptionInfo &WEI, const WebAssemblyExceptionInfo &WEI,
const MachineDominatorTree &MDT) { const MachineDominatorTree &MDT) {
// Remember original layout ordering, so we can update terminators after
// reordering to point to the original layout successor.
MF.RenumberBlocks();
// Prepare for a topological sort: Record the number of predecessors each // Prepare for a topological sort: Record the number of predecessors each
// block has, ignoring loop backedges. // block has, ignoring loop backedges.
MF.RenumberBlocks();
SmallVector<unsigned, 16> NumPredsLeft(MF.getNumBlockIDs(), 0); SmallVector<unsigned, 16> NumPredsLeft(MF.getNumBlockIDs(), 0);
for (MachineBasicBlock &MBB : MF) { for (MachineBasicBlock &MBB : MF) {
unsigned N = MBB.pred_size(); unsigned N = MBB.pred_size();