Skip to content

Commit e82a536

Browse files
committed
Merging r369886:
------------------------------------------------------------------------ r369886 | bjope | 2019-08-26 11:29:53 +0200 (Mon, 26 Aug 2019) | 23 lines [LoopUnroll] Handle certain PHIs in full unrolling properly Summary: When reconstructing the CFG of the loop after unrolling, LoopUnroll could in some cases remove the phi operands of loop-carried values instead of preserving them, resulting in undef phi values after loop unrolling. When doing this reconstruction, avoid removing incoming phi values for phis in the successor blocks if the successor is the block we are jumping to anyway. Patch-by: ebevhan Reviewers: fhahn, efriedma Reviewed By: fhahn Subscribers: bjope, lebedev.ri, zzheng, dmgreen, llvm-commits Tags: #llvm Differential Revision: https://reviews.llvm.org/D66334 ------------------------------------------------------------------------ llvm-svn: 370182
1 parent 67afb7c commit e82a536

File tree

2 files changed

+112
-3
lines changed

2 files changed

+112
-3
lines changed

llvm/lib/Transforms/Utils/LoopUnroll.cpp

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -711,7 +711,7 @@ LoopUnrollResult llvm::UnrollLoop(Loop *L, UnrollLoopOptions ULO, LoopInfo *LI,
711711

712712
auto setDest = [LoopExit, ContinueOnTrue](BasicBlock *Src, BasicBlock *Dest,
713713
ArrayRef<BasicBlock *> NextBlocks,
714-
BasicBlock *CurrentHeader,
714+
BasicBlock *BlockInLoop,
715715
bool NeedConditional) {
716716
auto *Term = cast<BranchInst>(Src->getTerminator());
717717
if (NeedConditional) {
@@ -723,7 +723,9 @@ LoopUnrollResult llvm::UnrollLoop(Loop *L, UnrollLoopOptions ULO, LoopInfo *LI,
723723
if (Dest != LoopExit) {
724724
BasicBlock *BB = Src;
725725
for (BasicBlock *Succ : successors(BB)) {
726-
if (Succ == CurrentHeader)
726+
// Preserve the incoming value from BB if we are jumping to the block
727+
// in the current loop.
728+
if (Succ == BlockInLoop)
727729
continue;
728730
for (PHINode &Phi : Succ->phis())
729731
Phi.removeIncomingValue(BB, false);
@@ -794,7 +796,7 @@ LoopUnrollResult llvm::UnrollLoop(Loop *L, UnrollLoopOptions ULO, LoopInfo *LI,
794796
// unconditional branch for some iterations.
795797
NeedConditional = false;
796798

797-
setDest(Headers[i], Dest, Headers, Headers[i], NeedConditional);
799+
setDest(Headers[i], Dest, Headers, HeaderSucc[i], NeedConditional);
798800
}
799801

800802
// Set up latches to branch to the new header in the unrolled iterations or
Lines changed: 107 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,107 @@
1+
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2+
; RUN: opt < %s -S -loop-unroll -unroll-allow-partial | FileCheck %s
3+
4+
; The phi which acts as input to func should not be undef. It should
5+
; have its loop-carried value (the load in for.cond) replaced accordingly
6+
; after unrolling the loop.
7+
8+
define i16 @full_unroll(i16* %A) {
9+
; CHECK-LABEL: @full_unroll(
10+
; CHECK-NEXT: entry:
11+
; CHECK-NEXT: br label [[FOR_COND:%.*]]
12+
; CHECK: for.cond:
13+
; CHECK-NEXT: [[TMP2:%.*]] = load i16, i16* [[A:%.*]]
14+
; CHECK-NEXT: br label [[FOR_COND_CLEANUP3:%.*]]
15+
; CHECK: for.cond.cleanup:
16+
; CHECK-NEXT: [[DOTLCSSA10_LCSSA:%.*]] = phi i16 [ [[TMP2_2:%.*]], [[FOR_COND_CLEANUP3_2:%.*]] ]
17+
; CHECK-NEXT: [[TMP3:%.*]] = call i16 @func(i16 [[DOTLCSSA10_LCSSA]])
18+
; CHECK-NEXT: ret i16 0
19+
; CHECK: for.cond.cleanup3:
20+
; CHECK-NEXT: [[PTR_1:%.*]] = getelementptr inbounds i16, i16* [[A]], i64 1
21+
; CHECK-NEXT: [[TMP2_1:%.*]] = load i16, i16* [[PTR_1]]
22+
; CHECK-NEXT: br label [[FOR_COND_CLEANUP3_1:%.*]]
23+
; CHECK: for.cond.cleanup3.1:
24+
; CHECK-NEXT: [[PTR_2:%.*]] = getelementptr inbounds i16, i16* [[A]], i64 2
25+
; CHECK-NEXT: [[TMP2_2]] = load i16, i16* [[PTR_2]]
26+
; CHECK-NEXT: br label [[FOR_COND_CLEANUP3_2]]
27+
; CHECK: for.cond.cleanup3.2:
28+
; CHECK-NEXT: [[PTR_3:%.*]] = getelementptr inbounds i16, i16* [[A]], i64 3
29+
; CHECK-NEXT: [[TMP2_3:%.*]] = load i16, i16* [[PTR_3]]
30+
; CHECK-NEXT: br i1 false, label [[FOR_COND_CLEANUP3_3:%.*]], label [[FOR_COND_CLEANUP:%.*]]
31+
; CHECK: for.cond.cleanup3.3:
32+
; CHECK-NEXT: unreachable
33+
;
34+
entry:
35+
br label %for.cond
36+
37+
for.cond: ; preds = %for.cond.cleanup3, %entry
38+
%.lcssa10 = phi i16 [ 123, %entry ], [ %.lcssa, %for.cond.cleanup3 ]
39+
%i.0 = phi i64 [ 0, %entry ], [ %inc9, %for.cond.cleanup3 ]
40+
%ptr = getelementptr inbounds i16, i16* %A, i64 %i.0
41+
%tmp2 = load i16, i16* %ptr
42+
%cmp = icmp ult i64 %i.0, 3
43+
br i1 %cmp, label %for.cond.cleanup3, label %for.cond.cleanup
44+
45+
for.cond.cleanup: ; preds = %for.cond
46+
%.lcssa10.lcssa = phi i16 [ %.lcssa10, %for.cond ]
47+
%tmp3 = call i16 (i16) @func(i16 %.lcssa10.lcssa)
48+
ret i16 0
49+
50+
for.cond.cleanup3: ; preds = %for.cond
51+
%.lcssa = phi i16 [ %tmp2, %for.cond ]
52+
%inc9 = add i64 %i.0, 1
53+
br label %for.cond
54+
}
55+
56+
define i16 @partial_unroll(i16* %A) {
57+
; CHECK-LABEL: @partial_unroll(
58+
; CHECK-NEXT: entry:
59+
; CHECK-NEXT: br label [[FOR_COND:%.*]]
60+
; CHECK: for.cond:
61+
; CHECK-NEXT: [[I_0:%.*]] = phi i64 [ 0, [[ENTRY:%.*]] ], [ [[INC9_2:%.*]], [[FOR_COND_CLEANUP3_2:%.*]] ]
62+
; CHECK-NEXT: [[PTR:%.*]] = getelementptr inbounds i16, i16* [[A:%.*]], i64 [[I_0]]
63+
; CHECK-NEXT: [[TMP2:%.*]] = load i16, i16* [[PTR]]
64+
; CHECK-NEXT: br label [[FOR_COND_CLEANUP3:%.*]]
65+
; CHECK: for.cond.cleanup:
66+
; CHECK-NEXT: [[DOTLCSSA10_LCSSA:%.*]] = phi i16 [ [[TMP2_1:%.*]], [[FOR_COND_CLEANUP3_1:%.*]] ]
67+
; CHECK-NEXT: [[TMP3:%.*]] = call i16 @func(i16 [[DOTLCSSA10_LCSSA]])
68+
; CHECK-NEXT: ret i16 0
69+
; CHECK: for.cond.cleanup3:
70+
; CHECK-NEXT: [[INC9:%.*]] = add nuw nsw i64 [[I_0]], 1
71+
; CHECK-NEXT: [[PTR_1:%.*]] = getelementptr inbounds i16, i16* [[A]], i64 [[INC9]]
72+
; CHECK-NEXT: [[TMP2_1]] = load i16, i16* [[PTR_1]]
73+
; CHECK-NEXT: br label [[FOR_COND_CLEANUP3_1]]
74+
; CHECK: for.cond.cleanup3.1:
75+
; CHECK-NEXT: [[INC9_1:%.*]] = add nuw nsw i64 [[INC9]], 1
76+
; CHECK-NEXT: [[PTR_2:%.*]] = getelementptr inbounds i16, i16* [[A]], i64 [[INC9_1]]
77+
; CHECK-NEXT: [[TMP2_2:%.*]] = load i16, i16* [[PTR_2]]
78+
; CHECK-NEXT: [[CMP_2:%.*]] = icmp ult i64 [[INC9_1]], 200
79+
; CHECK-NEXT: br i1 [[CMP_2]], label [[FOR_COND_CLEANUP3_2]], label [[FOR_COND_CLEANUP:%.*]]
80+
; CHECK: for.cond.cleanup3.2:
81+
; CHECK-NEXT: [[INC9_2]] = add nuw nsw i64 [[INC9_1]], 1
82+
; CHECK-NEXT: br label [[FOR_COND]]
83+
;
84+
entry:
85+
br label %for.cond
86+
87+
for.cond: ; preds = %for.cond.cleanup3, %entry
88+
%.lcssa10 = phi i16 [ 123, %entry ], [ %.lcssa, %for.cond.cleanup3 ]
89+
%i.0 = phi i64 [ 0, %entry ], [ %inc9, %for.cond.cleanup3 ]
90+
%ptr = getelementptr inbounds i16, i16* %A, i64 %i.0
91+
%tmp2 = load i16, i16* %ptr
92+
%cmp = icmp ult i64 %i.0, 200
93+
br i1 %cmp, label %for.cond.cleanup3, label %for.cond.cleanup
94+
95+
for.cond.cleanup: ; preds = %for.cond
96+
%.lcssa10.lcssa = phi i16 [ %.lcssa10, %for.cond ]
97+
%tmp3 = call i16 (i16) @func(i16 %.lcssa10.lcssa)
98+
ret i16 0
99+
100+
for.cond.cleanup3: ; preds = %for.cond
101+
%.lcssa = phi i16 [ %tmp2, %for.cond ]
102+
%inc9 = add i64 %i.0, 1
103+
br label %for.cond
104+
}
105+
106+
declare i16 @func(i16)
107+

0 commit comments

Comments
 (0)