summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--llvm/lib/Transforms/Utils/SimplifyCFG.cpp17
-rw-r--r--llvm/test/Transforms/SimplifyCFG/merge-cond-stores.ll39
2 files changed, 55 insertions, 1 deletions
diff --git a/llvm/lib/Transforms/Utils/SimplifyCFG.cpp b/llvm/lib/Transforms/Utils/SimplifyCFG.cpp
index 5dc9d2c3b71..389ec419b5c 100644
--- a/llvm/lib/Transforms/Utils/SimplifyCFG.cpp
+++ b/llvm/lib/Transforms/Utils/SimplifyCFG.cpp
@@ -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.
diff --git a/llvm/test/Transforms/SimplifyCFG/merge-cond-stores.ll b/llvm/test/Transforms/SimplifyCFG/merge-cond-stores.ll
index a4bda96e22a..f730ef2aed3 100644
--- a/llvm/test/Transforms/SimplifyCFG/merge-cond-stores.ll
+++ b/llvm/test/Transforms/SimplifyCFG/merge-cond-stores.ll
@@ -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
+}
+
OpenPOWER on IntegriCloud