forked from OSchip/llvm-project
[SimplifyCFG] Teach merge conditional stores to handle cases where the PostBB has more than 2 predecessors by inserting a new block for the store.
Summary: Currently merge conditional stores can't handle cases where PostBB (the block we need to move the store to) has more than 2 predecessors. This patch removes that restriction by creating a new block with only the 2 predecessors we care about and an unconditional branch to the original block. This provides a place to put the store. Reviewers: efriedma, jmolloy, ABataev Reviewed By: efriedma Subscribers: llvm-commits Differential Revision: https://reviews.llvm.org/D39760 llvm-svn: 329142
This commit is contained in:
parent
8427e94b54
commit
7d3aba6687
|
@ -2982,6 +2982,21 @@ static bool mergeConditionalStoreToAddress(BasicBlock *PTB, BasicBlock *PFB,
|
|||
if (&*I != PStore && I->mayReadOrWriteMemory())
|
||||
return false;
|
||||
|
||||
// If PostBB has more than two predecessors, we need to split it so we can
|
||||
// sink the store.
|
||||
if (std::next(pred_begin(PostBB), 2) != pred_end(PostBB)) {
|
||||
// We know that QFB's only successor is PostBB. And QFB has a single
|
||||
// predecessor. If QTB exists, then its only successor is also PostBB.
|
||||
// If QTB does not exist, then QFB's only predecessor has a conditional
|
||||
// branch to QFB and PostBB.
|
||||
BasicBlock *TruePred = QTB ? QTB : QFB->getSinglePredecessor();
|
||||
BasicBlock *NewBB = SplitBlockPredecessors(PostBB, { QFB, TruePred},
|
||||
"condstore.split");
|
||||
if (!NewBB)
|
||||
return false;
|
||||
PostBB = NewBB;
|
||||
}
|
||||
|
||||
// OK, we're going to sink the stores to PostBB. The store has to be
|
||||
// conditional though, so first create the predicate.
|
||||
Value *PCond = cast<BranchInst>(PFB->getSinglePredecessor()->getTerminator())
|
||||
|
@ -3117,7 +3132,7 @@ static bool mergeConditionalStores(BranchInst *PBI, BranchInst *QBI,
|
|||
if ((PTB && !HasOnePredAndOneSucc(PTB, PBI->getParent(), QBI->getParent())) ||
|
||||
(QTB && !HasOnePredAndOneSucc(QTB, QBI->getParent(), PostBB)))
|
||||
return false;
|
||||
if (!PostBB->hasNUses(2) || !QBI->getParent()->hasNUses(2))
|
||||
if (!QBI->getParent()->hasNUses(2))
|
||||
return false;
|
||||
|
||||
// OK, this is a sequence of two diamonds or triangles.
|
||||
|
|
|
@ -369,3 +369,42 @@ end:
|
|||
%z4 = phi i32 [ %z3, %no2 ], [ 3, %yes2 ]
|
||||
ret i32 %z4
|
||||
}
|
||||
|
||||
; This test has an outer if over the two triangles. This requires creating a new BB to hold the store.
|
||||
define void @test_outer_if(i32* %p, i32 %a, i32 %b, i32 %c) {
|
||||
; CHECK-LABEL: @test_outer_if(
|
||||
; CHECK-NEXT: entry:
|
||||
; CHECK-NEXT: [[X3:%.*]] = icmp eq i32 [[C:%.*]], 0
|
||||
; CHECK-NEXT: br i1 [[X3]], label [[END:%.*]], label [[CONTINUE:%.*]]
|
||||
; CHECK: continue:
|
||||
; CHECK-NEXT: [[X1:%.*]] = icmp ne i32 [[A:%.*]], 0
|
||||
; CHECK-NEXT: [[X2:%.*]] = icmp eq i32 [[B:%.*]], 0
|
||||
; CHECK-NEXT: [[TMP0:%.*]] = xor i1 [[X2]], true
|
||||
; CHECK-NEXT: [[TMP1:%.*]] = or i1 [[X1]], [[TMP0]]
|
||||
; CHECK-NEXT: br i1 [[TMP1]], label [[TMP2:%.*]], label [[END]]
|
||||
; CHECK: [[NOT_X2:%.*]] = xor i1 [[X2]], true
|
||||
; CHECK-NEXT: [[SPEC_SELECT:%.*]] = zext i1 [[NOT_X2]] to i32
|
||||
; CHECK-NEXT: store i32 [[SPEC_SELECT]], i32* [[P:%.*]], align 4
|
||||
; CHECK-NEXT: br label [[END]]
|
||||
; CHECK: end:
|
||||
; CHECK-NEXT: ret void
|
||||
;
|
||||
entry:
|
||||
%x3 = icmp eq i32 %c, 0
|
||||
br i1 %x3, label %end, label %continue
|
||||
continue:
|
||||
%x1 = icmp eq i32 %a, 0
|
||||
br i1 %x1, label %fallthrough, label %yes1
|
||||
yes1:
|
||||
store i32 0, i32* %p
|
||||
br label %fallthrough
|
||||
fallthrough:
|
||||
%x2 = icmp eq i32 %b, 0
|
||||
br i1 %x2, label %end, label %yes2
|
||||
yes2:
|
||||
store i32 1, i32* %p
|
||||
br label %end
|
||||
end:
|
||||
ret void
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue