Fix updateTerminator to be resiliant to degenerate terminators where

both fallthrough and a conditional branch target the same successor.
Gracefully delete the conditional branch and introduce any unconditional
branch needed to reach the actual successor. This fixes memory
corruption in 2009-06-15-RegScavengerAssert.ll and possibly other tests.

Also, while I'm here fix a latent bug I spotted by inspection. I never
applied the same fundamental fix to this fallthrough successor finding
logic that I did to the logic used when there are no conditional
branches. As a consequence it would have selected landing pads had they
be aligned in just the right way here. I don't have a test case as
I spotted this by inspection, and the previous time I found this
required have of TableGen's source code to produce it. =/ I hate backend
bugs. ;]

Thanks to Jim Grosbach for helping me reason through this and reviewing
the fix.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@154867 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Chandler Carruth 2012-04-16 22:03:00 +00:00
parent 68f89a6158
commit f1a60c734c
3 changed files with 31 additions and 9 deletions

View File

@ -392,22 +392,44 @@ void MachineBasicBlock::updateTerminator() {
TII->InsertBranch(*this, TBB, 0, Cond, dl);
}
} else {
// Walk through the successors and find the successor which is not
// a landing pad and is not the conditional branch destination (in TBB)
// as the fallthrough successor.
MachineBasicBlock *FallthroughBB = 0;
for (succ_iterator SI = succ_begin(), SE = succ_end(); SI != SE; ++SI) {
if ((*SI)->isLandingPad() || *SI == TBB)
continue;
assert(!FallthroughBB && "Found more than one fallthrough successor.");
FallthroughBB = *SI;
}
if (!FallthroughBB && canFallThrough()) {
// We fallthrough to the same basic block as the conditional jump
// targets. Remove the conditional jump, leaving unconditional
// fallthrough.
// 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, 0, Cond, dl);
return;
}
// The block has a fallthrough conditional branch.
MachineBasicBlock *MBBA = *succ_begin();
MachineBasicBlock *MBBB = *llvm::next(succ_begin());
if (MBBA == TBB) std::swap(MBBB, MBBA);
if (isLayoutSuccessor(TBB)) {
if (TII->ReverseBranchCondition(Cond)) {
// We can't reverse the condition, add an unconditional branch.
Cond.clear();
TII->InsertBranch(*this, MBBA, 0, Cond, dl);
TII->InsertBranch(*this, FallthroughBB, 0, Cond, dl);
return;
}
TII->RemoveBranch(*this);
TII->InsertBranch(*this, MBBA, 0, Cond, dl);
} else if (!isLayoutSuccessor(MBBA)) {
TII->InsertBranch(*this, FallthroughBB, 0, Cond, dl);
} else if (!isLayoutSuccessor(FallthroughBB)) {
TII->RemoveBranch(*this);
TII->InsertBranch(*this, TBB, MBBA, Cond, dl);
TII->InsertBranch(*this, TBB, FallthroughBB, Cond, dl);
}
}
}

View File

@ -83,7 +83,7 @@ define fastcc void @t2() nounwind {
entry:
; CHECK: t2:
; CHECK: cmp r0, #0
; CHECK: bne
; CHECK: %growMapping.exit
br i1 undef, label %bb.i.i3, label %growMapping.exit
bb.i.i3: ; preds = %entry

View File

@ -1,7 +1,7 @@
; RUN: llc -march=x86-64 < %s | FileCheck %s
; CHECK: orq
; CHECK-NEXT: je
; CHECK-NEXT: .LBB0_1
@_ZN11xercesc_2_513SchemaSymbols21fgURI_SCHEMAFORSCHEMAE = external constant [33 x i16], align 32 ; <[33 x i16]*> [#uses=1]
@_ZN11xercesc_2_56XMLUni16fgNotationStringE = external constant [9 x i16], align 16 ; <[9 x i16]*> [#uses=1]