Skip to content

Commit fd6f815

Browse files
committed
[SimplifyCFG] Enable MergeBlockIntoPredecessor with two successors
1 parent 773d357 commit fd6f815

File tree

3 files changed

+93
-1
lines changed

3 files changed

+93
-1
lines changed

llvm/lib/Transforms/Utils/BasicBlockUtils.cpp

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -207,6 +207,10 @@ bool llvm::MergeBlockIntoPredecessor(BasicBlock *BB, DomTreeUpdater *DTU,
207207
if (PredecessorWithTwoSuccessors) {
208208
if (!(PredBB_BI = dyn_cast<BranchInst>(PTI)))
209209
return false;
210+
// Can't merge if any of the instructions has side effects
211+
for (Instruction &candid : *BB)
212+
if (candid.mayHaveSideEffects())
213+
return false;
210214
BranchInst *BB_JmpI = dyn_cast<BranchInst>(BB->getTerminator());
211215
if (!BB_JmpI || !BB_JmpI->isUnconditional())
212216
return false;
@@ -283,6 +287,36 @@ bool llvm::MergeBlockIntoPredecessor(BasicBlock *BB, DomTreeUpdater *DTU,
283287
if (MSSAU)
284288
MSSAU->moveAllAfterMergeBlocks(BB, PredBB, Start);
285289

290+
// PHI nodes that references the Pred shall be replaced with a SelectInst
291+
for (BasicBlock *Succ : successors(PTI)) {
292+
if (Succ == BB)
293+
continue;
294+
for (PHINode &PhiSucc : Succ->phis()) {
295+
if (llvm::is_contained(PhiSucc.blocks(), PredBB)) {
296+
if (PredBB_BI->isConditional()) {
297+
Value *Cond = PredBB_BI->getCondition();
298+
Value *OrigPhi0 = PhiSucc.removeIncomingValue(PredBB, false);
299+
Value *newPhi = OrigPhi0;
300+
301+
if (PhiSucc.getNumOperands() > 0) {
302+
if (llvm::is_contained(PhiSucc.blocks(), BB)) {
303+
Value *OrigPhi1 = PhiSucc.removeIncomingValue(BB, false);
304+
// Swap branch given the conditions
305+
if (PredBB_BI->getSuccessor(0) == Succ) {
306+
newPhi = SelectInst::Create(Cond, OrigPhi0, OrigPhi1, "", PTI->getIterator());
307+
} else {
308+
newPhi = SelectInst::Create(Cond, OrigPhi1, OrigPhi0, "", PTI->getIterator());
309+
}
310+
PhiSucc.addIncoming(newPhi, PredBB);
311+
}
312+
}
313+
314+
PhiSucc.addIncoming(newPhi, PredBB);
315+
}
316+
}
317+
}
318+
}
319+
286320
// Make all PHI nodes that referred to BB now refer to Pred as their
287321
// source...
288322
BB->replaceAllUsesWith(PredBB);

llvm/lib/Transforms/Utils/SimplifyCFG.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8339,7 +8339,7 @@ bool SimplifyCFGOpt::simplifyOnce(BasicBlock *BB) {
83398339
// Merge basic blocks into their predecessor if there is only one distinct
83408340
// pred, and if there is only one distinct successor of the predecessor, and
83418341
// if there are no PHI nodes.
8342-
if (MergeBlockIntoPredecessor(BB, DTU))
8342+
if (MergeBlockIntoPredecessor(BB, DTU, nullptr, nullptr, nullptr, true))
83438343
return true;
83448344

83458345
if (SinkCommon && Options.SinkCommonInsts)
Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --tool ./opt --version 5
2+
; RUN: opt < %s -passes=simplifycfg -S | FileCheck %s
3+
4+
define i1 @_Z7compareRK1SS1_(ptr %a, ptr %b) {
5+
; CHECK-LABEL: @_Z7compareRK1SS1_(
6+
; CHECK-SAME: ptr [[A:%.*]], ptr [[B:%.*]]) {
7+
; CHECK-NEXT: entry:
8+
; CHECK-NEXT: %0 = load i32, ptr %a, align 4, !tbaa !3
9+
; CHECK-NEXT: %1 = load i32, ptr %b, align 4, !tbaa !3
10+
; CHECK-NEXT: %cmp.i = icmp slt i32 %0, %1
11+
; CHECK-NEXT: %cmp.i19 = icmp eq i32 %0, %1
12+
; CHECK-NEXT: %y = getelementptr inbounds nuw i8, ptr %a, i64 4
13+
; CHECK-NEXT: %2 = load i32, ptr %y, align 4, !tbaa !8
14+
; CHECK-NEXT: %y14 = getelementptr inbounds nuw i8, ptr %b, i64 4
15+
; CHECK-NEXT: %3 = load i32, ptr %y14, align 4, !tbaa !8
16+
; CHECK-NEXT: %cmp = icmp slt i32 %2, %3
17+
; CHECK-NEXT: %4 = select i1 %cmp.i19, i1 %cmp, i1 false
18+
; CHECK-NEXT: %5 = select i1 %cmp.i, i1 true, i1 %4
19+
; CHECK-NEXT: br label %lor.end
20+
; CHECK-EMPTY:
21+
; CHECK-NEXT: lor.end: ; preds = %entry
22+
; CHECK-NEXT: ret i1 %5
23+
entry:
24+
%0 = load i32, ptr %a, align 4, !tbaa !3
25+
%1 = load i32, ptr %b, align 4, !tbaa !3
26+
%cmp.i = icmp slt i32 %0, %1
27+
br i1 %cmp.i, label %lor.end, label %lor.rhs
28+
29+
lor.rhs: ; preds = %entry
30+
%cmp.i19 = icmp eq i32 %0, %1
31+
br i1 %cmp.i19, label %land.rhs, label %lor.end
32+
33+
land.rhs: ; preds = %lor.rhs
34+
%y = getelementptr inbounds nuw i8, ptr %a, i64 4
35+
%2 = load i32, ptr %y, align 4, !tbaa !8
36+
%y14 = getelementptr inbounds nuw i8, ptr %b, i64 4
37+
%3 = load i32, ptr %y14, align 4, !tbaa !8
38+
%cmp = icmp slt i32 %2, %3
39+
br label %lor.end
40+
41+
lor.end: ; preds = %lor.rhs, %land.rhs, %entry
42+
%4 = phi i1 [ true, %entry ], [ false, %lor.rhs ], [ %cmp, %land.rhs ]
43+
ret i1 %4
44+
}
45+
46+
!llvm.module.flags = !{!0, !1}
47+
!llvm.ident = !{!2}
48+
49+
!0 = !{i32 1, !"wchar_size", i32 4}
50+
!1 = !{i32 7, !"uwtable", i32 2}
51+
!2 = !{!"clang"}
52+
!3 = !{!4, !5, i64 0}
53+
!4 = !{!"_ZTS1S", !5, i64 0, !5, i64 4}
54+
!5 = !{!"int", !6, i64 0}
55+
!6 = !{!"omnipotent char", !7, i64 0}
56+
!7 = !{!"Simple C++ TBAA"}
57+
!8 = !{!4, !5, i64 4}
58+
!9 = !{!5, !5, i64 0}

0 commit comments

Comments
 (0)