Skip to content

Commit 7194cc0

Browse files
committed
[FlattenCFG] Flatten CFG with Phi nodes
1 parent 773d357 commit 7194cc0

File tree

2 files changed

+89
-15
lines changed

2 files changed

+89
-15
lines changed

llvm/lib/Transforms/Utils/FlattenCFG.cpp

Lines changed: 36 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -134,10 +134,6 @@ class FlattenCFGOpt {
134134
/// its predecessor. In Case 2, BB (BB3) only has conditional branches
135135
/// as its predecessors.
136136
bool FlattenCFGOpt::FlattenParallelAndOr(BasicBlock *BB, IRBuilder<> &Builder) {
137-
PHINode *PHI = dyn_cast<PHINode>(BB->begin());
138-
if (PHI)
139-
return false; // For simplicity, avoid cases containing PHI nodes.
140-
141137
BasicBlock *LastCondBlock = nullptr;
142138
BasicBlock *FirstCondBlock = nullptr;
143139
BasicBlock *UnCondBlock = nullptr;
@@ -208,8 +204,10 @@ bool FlattenCFGOpt::FlattenParallelAndOr(BasicBlock *BB, IRBuilder<> &Builder) {
208204

209205
if (Idx == -1)
210206
Idx = CIdx;
211-
else if (CIdx != Idx)
212-
return false;
207+
else if (CIdx != Idx) {
208+
// Inverse Branch Condition
209+
InvertBranch(PBI, Builder);
210+
}
213211

214212
// PS is the successor which is not BB. Check successors to identify
215213
// the last conditional branch.
@@ -269,11 +267,6 @@ bool FlattenCFGOpt::FlattenParallelAndOr(BasicBlock *BB, IRBuilder<> &Builder) {
269267
if (!PBI1 || !PBI1->isUnconditional())
270268
return false;
271269

272-
// PS2 should not contain PHI node.
273-
PHI = dyn_cast<PHINode>(PS2->begin());
274-
if (PHI)
275-
return false;
276-
277270
// Do the transformation.
278271
BasicBlock *CB;
279272
BranchInst *PBI = cast<BranchInst>(FirstCondBlock->getTerminator());
@@ -291,17 +284,45 @@ bool FlattenCFGOpt::FlattenParallelAndOr(BasicBlock *BB, IRBuilder<> &Builder) {
291284
// Merge conditions.
292285
Builder.SetInsertPoint(PBI);
293286
Value *NC;
294-
if (Idx == 0)
295-
// Case 2, use parallel or.
296-
NC = Builder.CreateOr(PC, CC);
297-
else
287+
if (UnCondBlock)
298288
// Case 1, use parallel and.
299289
NC = Builder.CreateAnd(PC, CC);
290+
else
291+
// Case 2, use parallel or.
292+
NC = Builder.CreateOr(PC, CC);
293+
294+
// Fixup PHI node if needed
295+
for (BasicBlock *CBS : successors(PBI)) {
296+
for (PHINode &Phi : CBS->phis()) {
297+
Value *origPhi0 = nullptr;
298+
Value *newPhi = nullptr;
299+
if (llvm::is_contained(Phi.blocks(), FirstCondBlock)) {
300+
origPhi0 = Phi.removeIncomingValue(FirstCondBlock, false);
301+
newPhi = origPhi0;
302+
}
303+
if (llvm::is_contained(Phi.blocks(), CB)) {
304+
Value *origPhi1 = Phi.removeIncomingValue(CB, false);
305+
newPhi = origPhi1;
306+
307+
if (origPhi0) {
308+
// Swap branch given the conditions
309+
if (PBI->getSuccessor(0) == CBS) {
310+
newPhi = Builder.CreateSelect(PC, origPhi0, origPhi1);
311+
} else {
312+
newPhi = Builder.CreateSelect(PC, origPhi1, origPhi0);
313+
}
314+
}
315+
}
316+
if (newPhi)
317+
Phi.addIncoming(newPhi, FirstCondBlock);
318+
}
319+
}
300320

301321
PBI->replaceUsesOfWith(CC, NC);
302322
PC = NC;
303323
if (CB == LastCondBlock)
304324
Iteration = false;
325+
305326
// Remove internal conditional branches.
306327
CB->dropAllReferences();
307328
// make CB unreachable and let downstream to delete the block.
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --tool ./opt --version 5
2+
; RUN: opt < %s -passes=flatten-cfg -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 sge i32 %0, %1
11+
; CHECK-NEXT: %cmp.i19 = icmp eq i32 %0, %1
12+
; CHECK-NEXT: %2 = and i1 %cmp.i, %cmp.i19
13+
; CHECK-NEXT: %3 = select i1 %cmp.i, i1 false, i1 true
14+
; CHECK-NEXT: br i1 %2, label %land.rhs, label %lor.end
15+
; CHECK-LABEL: lor.end: ; preds = %land.rhs, %entry
16+
; CHECK-NEXT: %6 = phi i1 [ %cmp, %land.rhs ], [ %3, %entry ]
17+
; CHECK-NEXT: ret i1 %6
18+
entry:
19+
%0 = load i32, ptr %a, align 4, !tbaa !3
20+
%1 = load i32, ptr %b, align 4, !tbaa !3
21+
%cmp.i = icmp slt i32 %0, %1
22+
br i1 %cmp.i, label %lor.end, label %lor.rhs
23+
24+
lor.rhs: ; preds = %entry
25+
%cmp.i19 = icmp eq i32 %0, %1
26+
br i1 %cmp.i19, label %land.rhs, label %lor.end
27+
28+
land.rhs: ; preds = %lor.rhs
29+
%y = getelementptr inbounds nuw i8, ptr %a, i64 4
30+
%2 = load i32, ptr %y, align 4, !tbaa !8
31+
%y14 = getelementptr inbounds nuw i8, ptr %b, i64 4
32+
%3 = load i32, ptr %y14, align 4, !tbaa !8
33+
%cmp = icmp slt i32 %2, %3
34+
br label %lor.end
35+
36+
lor.end: ; preds = %lor.rhs, %land.rhs, %entry
37+
%4 = phi i1 [ true, %entry ], [ false, %lor.rhs ], [ %cmp, %land.rhs ]
38+
ret i1 %4
39+
}
40+
41+
!llvm.module.flags = !{!0, !1}
42+
!llvm.ident = !{!2}
43+
44+
!0 = !{i32 1, !"wchar_size", i32 4}
45+
!1 = !{i32 7, !"uwtable", i32 2}
46+
!2 = !{!"clang"}
47+
!3 = !{!4, !5, i64 0}
48+
!4 = !{!"_ZTS1S", !5, i64 0, !5, i64 4}
49+
!5 = !{!"int", !6, i64 0}
50+
!6 = !{!"omnipotent char", !7, i64 0}
51+
!7 = !{!"Simple C++ TBAA"}
52+
!8 = !{!4, !5, i64 4}
53+
!9 = !{!5, !5, i64 0}

0 commit comments

Comments
 (0)