mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2025-01-31 20:51:52 +01:00
move single basic blocks that are neither fallen into nor fall out of into
a place more useful. In particular, if we can put them in a place where code will be able to fall into it, do so. Otherwise, put it in a place it can fall through into a successor. Otherwise, if preventing a fallthrough, move to the end of the function, out of the way. This deletes several hundred unconditional branches from spass. llvm-svn: 31149
This commit is contained in:
parent
e38c95d2a3
commit
533b205309
@ -46,7 +46,7 @@ namespace {
|
||||
|
||||
// Branch optzn.
|
||||
bool OptimizeBranches(MachineFunction &MF);
|
||||
void OptimizeBlock(MachineFunction::iterator MBB);
|
||||
void OptimizeBlock(MachineBasicBlock *MBB);
|
||||
void RemoveDeadBlock(MachineBasicBlock *MBB);
|
||||
};
|
||||
}
|
||||
@ -394,17 +394,42 @@ static void ReplaceUsesOfBlockWith(MachineBasicBlock *BB,
|
||||
}
|
||||
}
|
||||
|
||||
/// CanFallThrough - Return true of the specified branch condition can transfer
|
||||
/// control to FallthroughBlock, the block immediately after the branch.
|
||||
static bool CanFallThrough(MachineBasicBlock *TBB,
|
||||
MachineBasicBlock *FBB,
|
||||
const std::vector<MachineOperand> &Cond,
|
||||
MachineFunction::iterator FallthroughBlock) {
|
||||
// If there is no branch, control always falls through.
|
||||
if (TBB == 0) return true;
|
||||
|
||||
// If there is some explicit branch to the fallthrough block, it can obviously
|
||||
// reach, even though the branch should get folded to fall through implicitly.
|
||||
if (MachineFunction::iterator(TBB) == FallthroughBlock ||
|
||||
MachineFunction::iterator(FBB) == FallthroughBlock)
|
||||
return true;
|
||||
|
||||
// If it's an unconditional branch to some block not the fall through, it
|
||||
// doesn't fall through.
|
||||
if (Cond.empty()) return false;
|
||||
|
||||
// Otherwise, if it is conditional and has no explicit false block, it falls
|
||||
// through.
|
||||
return !Cond.empty() && FBB == 0;
|
||||
}
|
||||
|
||||
/// OptimizeBlock - Analyze and optimize control flow related to the specified
|
||||
/// block. This is never called on the entry block.
|
||||
void BranchFolder::OptimizeBlock(MachineFunction::iterator MBB) {
|
||||
void BranchFolder::OptimizeBlock(MachineBasicBlock *MBB) {
|
||||
MachineFunction::iterator FallThrough = MBB;
|
||||
++FallThrough;
|
||||
|
||||
// If this block is empty, make everyone use its fall-through, not the block
|
||||
// explicitly.
|
||||
if (MBB->empty()) {
|
||||
// Dead block? Leave for cleanup later.
|
||||
if (MBB->pred_empty()) return;
|
||||
|
||||
MachineFunction::iterator FallThrough = next(MBB);
|
||||
|
||||
if (FallThrough == MBB->getParent()->end()) {
|
||||
// TODO: Simplify preds to not branch here if possible!
|
||||
} else {
|
||||
@ -426,7 +451,7 @@ void BranchFolder::OptimizeBlock(MachineFunction::iterator MBB) {
|
||||
|
||||
// Check to see if we can simplify the terminator of the block before this
|
||||
// one.
|
||||
MachineBasicBlock &PrevBB = *prior(MBB);
|
||||
MachineBasicBlock &PrevBB = *prior(MachineFunction::iterator(MBB));
|
||||
|
||||
MachineBasicBlock *PriorTBB = 0, *PriorFBB = 0;
|
||||
std::vector<MachineOperand> PriorCond;
|
||||
@ -443,7 +468,7 @@ void BranchFolder::OptimizeBlock(MachineFunction::iterator MBB) {
|
||||
if (PriorTBB && PriorTBB == PriorFBB) {
|
||||
TII->RemoveBranch(PrevBB);
|
||||
PriorCond.clear();
|
||||
if (PriorTBB != &*MBB)
|
||||
if (PriorTBB != MBB)
|
||||
TII->InsertBranch(PrevBB, PriorTBB, 0, PriorCond);
|
||||
MadeChange = true;
|
||||
++NumBranchOpts;
|
||||
@ -452,7 +477,7 @@ void BranchFolder::OptimizeBlock(MachineFunction::iterator MBB) {
|
||||
|
||||
// If the previous branch *only* branches to *this* block (conditional or
|
||||
// not) remove the branch.
|
||||
if (PriorTBB == &*MBB && PriorFBB == 0) {
|
||||
if (PriorTBB == MBB && PriorFBB == 0) {
|
||||
TII->RemoveBranch(PrevBB);
|
||||
MadeChange = true;
|
||||
++NumBranchOpts;
|
||||
@ -461,7 +486,7 @@ void BranchFolder::OptimizeBlock(MachineFunction::iterator MBB) {
|
||||
|
||||
// If the prior block branches somewhere else on the condition and here if
|
||||
// the condition is false, remove the uncond second branch.
|
||||
if (PriorFBB == &*MBB) {
|
||||
if (PriorFBB == MBB) {
|
||||
TII->RemoveBranch(PrevBB);
|
||||
TII->InsertBranch(PrevBB, PriorTBB, 0, PriorCond);
|
||||
MadeChange = true;
|
||||
@ -472,7 +497,7 @@ void BranchFolder::OptimizeBlock(MachineFunction::iterator MBB) {
|
||||
// If the prior block branches here on true and somewhere else on false, and
|
||||
// if the branch condition is reversible, reverse the branch to create a
|
||||
// fall-through.
|
||||
if (PriorTBB == &*MBB) {
|
||||
if (PriorTBB == MBB) {
|
||||
std::vector<MachineOperand> NewPriorCond(PriorCond);
|
||||
if (!TII->ReverseBranchCondition(NewPriorCond)) {
|
||||
TII->RemoveBranch(PrevBB);
|
||||
@ -490,12 +515,13 @@ void BranchFolder::OptimizeBlock(MachineFunction::iterator MBB) {
|
||||
if (!TII->AnalyzeBranch(*MBB, CurTBB, CurFBB, CurCond)) {
|
||||
// If the CFG for the prior block has extra edges, remove them.
|
||||
MadeChange |= CorrectExtraCFGEdges(*MBB, CurTBB, CurFBB,
|
||||
!CurCond.empty(), next(MBB));
|
||||
!CurCond.empty(),
|
||||
++MachineFunction::iterator(MBB));
|
||||
|
||||
// If this branch is the only thing in its block, see if we can forward
|
||||
// other blocks across it.
|
||||
if (CurTBB && CurCond.empty() && CurFBB == 0 &&
|
||||
TII->isBranch(MBB->begin()->getOpcode()) && CurTBB != &*MBB) {
|
||||
TII->isBranch(MBB->begin()->getOpcode()) && CurTBB != MBB) {
|
||||
// This block may contain just an unconditional branch. Because there can
|
||||
// be 'non-branch terminators' in the block, try removing the branch and
|
||||
// then seeing if the block is empty.
|
||||
@ -509,7 +535,7 @@ void BranchFolder::OptimizeBlock(MachineFunction::iterator MBB) {
|
||||
if (MBB->empty() && (!PriorUnAnalyzable || !PrevBB.isSuccessor(MBB))) {
|
||||
// If the prior block falls through into us, turn it into an
|
||||
// explicit branch to us to make updates simpler.
|
||||
if (PrevBB.isSuccessor(MBB) && PriorTBB != &*MBB && PriorFBB != &*MBB) {
|
||||
if (PrevBB.isSuccessor(MBB) && PriorTBB != MBB && PriorFBB != MBB) {
|
||||
if (PriorTBB == 0) {
|
||||
assert(PriorCond.empty() && PriorFBB == 0 && "Bad branch analysis");
|
||||
PriorTBB = MBB;
|
||||
@ -526,7 +552,7 @@ void BranchFolder::OptimizeBlock(MachineFunction::iterator MBB) {
|
||||
bool DidChange = false;
|
||||
bool HasBranchToSelf = false;
|
||||
while (PI != MBB->pred_end()) {
|
||||
if (*PI == &*MBB) {
|
||||
if (*PI == MBB) {
|
||||
// If this block has an uncond branch to itself, leave it.
|
||||
++PI;
|
||||
HasBranchToSelf = true;
|
||||
@ -549,5 +575,62 @@ void BranchFolder::OptimizeBlock(MachineFunction::iterator MBB) {
|
||||
// Add the branch back if the block is more than just an uncond branch.
|
||||
TII->InsertBranch(*MBB, CurTBB, 0, CurCond);
|
||||
}
|
||||
|
||||
// If the prior block doesn't fall through into this block, and if this
|
||||
// block doesn't fall through into some other block, see if we can find a
|
||||
// place to move this block where a fall-through will happen.
|
||||
if (!PriorUnAnalyzable && !CanFallThrough(PriorTBB, PriorFBB,
|
||||
PriorCond, MBB)) {
|
||||
// Now we know that there was no fall-through into this block, check to
|
||||
// see if it has fall-throughs.
|
||||
if (!CanFallThrough(CurTBB, CurFBB, CurCond, FallThrough)) {
|
||||
|
||||
// Check all the predecessors of this block. If one of them has no fall
|
||||
// throughs, move this block right after it.
|
||||
for (MachineBasicBlock::pred_iterator PI = MBB->pred_begin(),
|
||||
E = MBB->pred_end(); PI != E; ++PI) {
|
||||
// Analyze the branch at the end of the pred.
|
||||
MachineBasicBlock *PredBB = *PI;
|
||||
MachineFunction::iterator PredFallthrough = PredBB; ++PredFallthrough;
|
||||
MachineBasicBlock *PredTBB = 0, *PredFBB = 0;
|
||||
std::vector<MachineOperand> PredCond;
|
||||
if (PredBB != MBB &&
|
||||
!TII->AnalyzeBranch(*PredBB, PredTBB, PredFBB, PredCond) &&
|
||||
!CanFallThrough(PredTBB, PredFBB, PredCond, PredFallthrough)) {
|
||||
MBB->moveAfter(PredBB);
|
||||
MadeChange = true;
|
||||
return OptimizeBlock(MBB);
|
||||
}
|
||||
}
|
||||
|
||||
// Check all successors to see if we can move this block before it.
|
||||
for (MachineBasicBlock::succ_iterator SI = MBB->succ_begin(),
|
||||
E = MBB->succ_end(); SI != E; ++SI) {
|
||||
// Analyze the branch at the end of the block before the succ.
|
||||
MachineBasicBlock *SuccBB = *SI;
|
||||
MachineFunction::iterator SuccPrev = SuccBB; --SuccPrev;
|
||||
MachineBasicBlock *SuccPrevTBB = 0, *SuccPrevFBB = 0;
|
||||
std::vector<MachineOperand> SuccPrevCond;
|
||||
if (SuccBB != MBB &&
|
||||
!TII->AnalyzeBranch(*SuccPrev, SuccPrevTBB, SuccPrevFBB,
|
||||
SuccPrevCond) &&
|
||||
!CanFallThrough(SuccPrevTBB, SuccPrevFBB, SuccPrevCond, SuccBB)) {
|
||||
MBB->moveBefore(SuccBB);
|
||||
MadeChange = true;
|
||||
return OptimizeBlock(MBB);
|
||||
}
|
||||
}
|
||||
|
||||
// Okay, there is no really great place to put this block. If, however,
|
||||
// the block before this one would be a fall-through if this block were
|
||||
// removed, move this block to the end of the function.
|
||||
if (FallThrough != MBB->getParent()->end() &&
|
||||
CanFallThrough(PriorTBB, PriorFBB, PriorCond, FallThrough)) {
|
||||
MBB->moveAfter(--MBB->getParent()->end());
|
||||
MadeChange = true;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user