1 ; RUN: opt < %s -loop-unroll -unroll-runtime=true -unroll-runtime-epilog=false -unroll-runtime-multi-exit=true -unroll-count=4 -verify-dom-info -S | FileCheck %s
4 ; The tests below are for verifying dom tree after runtime unrolling
5 ; with multiple exit/exiting blocks.
7 ; We explicitly set the unroll count so that expensiveTripCount computation is allowed.
9 ; mergedexit block has edges from loop exit blocks.
12 ; CHECK-LABEL: headerexit:
13 ; CHECK-NEXT: %addphi = phi i64 [ %add.iv, %header ], [ %add.iv.1, %header.1 ], [ %add.iv.2, %header.2 ], [ %add.iv.3, %header.3 ]
14 ; CHECK-NEXT: br label %mergedexit
15 ; CHECK-LABEL: latchexit:
16 ; CHECK-NEXT: %shftphi = phi i64 [ %shft, %latch ], [ %shft.1, %latch.1 ], [ %shft.2, %latch.2 ], [ %shft.3, %latch.3 ]
17 ; CHECK-NEXT: br label %mergedexit
18 ; CHECK-LABEL: mergedexit:
19 ; CHECK-NEXT: %retval = phi i64 [ %addphi, %headerexit ], [ %shftphi, %latchexit ]
20 ; CHECK-NEXT: ret i64 %retval
24 preheader: ; preds = %bb
25 %trip = zext i32 undef to i64
28 header: ; preds = %latch, %preheader
29 %iv = phi i64 [ 2, %preheader ], [ %add.iv, %latch ]
30 %add.iv = add nuw nsw i64 %iv, 2
31 %cmp1 = icmp ult i64 %add.iv, %trip
32 br i1 %cmp1, label %latch, label %headerexit
34 latch: ; preds = %header
35 %shft = ashr i64 %add.iv, 1
36 %cmp2 = icmp ult i64 %shft, %trip
37 br i1 %cmp2, label %header, label %latchexit
39 headerexit: ; preds = %header
40 %addphi = phi i64 [ %add.iv, %header ]
43 latchexit: ; preds = %latch
44 %shftphi = phi i64 [ %shft, %latch ]
47 mergedexit: ; preds = %latchexit, %headerexit
48 %retval = phi i64 [ %addphi, %headerexit ], [ %shftphi, %latchexit ]
52 ; mergedexit has edges from loop exit blocks and a block outside the loop.
53 define void @test2(i1 %cond, i32 %n) {
54 ; CHECK-LABEL: header.1:
55 ; CHECK-NEXT: %add.iv.1 = add nuw nsw i64 %add.iv, 2
56 ; CHECK: br i1 %cmp1.1, label %latch.1, label %headerexit
57 ; CHECK-LABEL: latch.3:
58 ; CHECK: %cmp2.3 = icmp ult i64 %shft.3, %trip
59 ; CHECK-NEXT: br i1 %cmp2.3, label %header, label %latchexit, !llvm.loop
61 br i1 %cond, label %preheader, label %mergedexit
63 preheader: ; preds = %entry
64 %trip = zext i32 %n to i64
67 header: ; preds = %latch, %preheader
68 %iv = phi i64 [ 2, %preheader ], [ %add.iv, %latch ]
69 %add.iv = add nuw nsw i64 %iv, 2
70 %cmp1 = icmp ult i64 %add.iv, %trip
71 br i1 %cmp1, label %latch, label %headerexit
73 latch: ; preds = %header
74 %shft = ashr i64 %add.iv, 1
75 %cmp2 = icmp ult i64 %shft, %trip
76 br i1 %cmp2, label %header, label %latchexit
78 headerexit: ; preds = %header
81 latchexit: ; preds = %latch
84 mergedexit: ; preds = %latchexit, %headerexit, %entry
89 ; exitsucc is from loop exit block only.
90 define i64 @test3(i32 %n) {
92 ; CHECK-LABEL: headerexit:
93 ; CHECK-NEXT: br label %exitsucc
94 ; CHECK-LABEL: latchexit:
95 ; CHECK-NEXT: %shftphi = phi i64 [ %shft, %latch ], [ %shft.1, %latch.1 ], [ %shft.2, %latch.2 ], [ %shft.3, %latch.3 ]
96 ; CHECK-NEXT: ret i64 %shftphi
97 ; CHECK-LABEL: exitsucc:
98 ; CHECK-NEXT: ret i64 96
102 preheader: ; preds = %bb
103 %trip = zext i32 %n to i64
106 header: ; preds = %latch, %preheader
107 %iv = phi i64 [ 2, %preheader ], [ %add.iv, %latch ]
108 %add.iv = add nuw nsw i64 %iv, 2
109 %cmp1 = icmp ult i64 %add.iv, %trip
110 br i1 %cmp1, label %latch, label %headerexit
112 latch: ; preds = %header
113 %shft = ashr i64 %add.iv, 1
114 %cmp2 = icmp ult i64 %shft, %trip
115 br i1 %cmp2, label %header, label %latchexit
117 headerexit: ; preds = %header
120 latchexit: ; preds = %latch
121 %shftphi = phi i64 [ %shft, %latch ]
124 exitsucc: ; preds = %headerexit
128 ; exit block (%default) has an exiting block and another exit block as predecessors.
129 define void @test4(i16 %c3) {
132 ; CHECK-LABEL: exiting.prol:
133 ; CHECK-NEXT: switch i16 %c3, label %default.loopexit.loopexit1 [
135 ; CHECK-LABEL: exiting:
136 ; CHECK-NEXT: switch i16 %c3, label %default.loopexit.loopexit [
138 ; CHECK-LABEL: default.loopexit.loopexit:
139 ; CHECK-NEXT: br label %default.loopexit
141 ; CHECK-LABEL: default.loopexit.loopexit1:
142 ; CHECK-NEXT: br label %default.loopexit
144 ; CHECK-LABEL: default.loopexit:
145 ; CHECK-NEXT: br label %default
147 %c1 = zext i32 undef to i64
150 header: ; preds = %latch, %preheader
151 %indvars.iv = phi i64 [ 0, %preheader ], [ %indvars.iv.next, %latch ]
154 exiting: ; preds = %header
155 switch i16 %c3, label %default [
156 i16 45, label %otherexit
160 latch: ; preds = %exiting
161 %indvars.iv.next = add nuw nsw i64 %indvars.iv, 1
162 %c2 = icmp ult i64 %indvars.iv.next, %c1
163 br i1 %c2, label %header, label %latchexit
165 latchexit: ; preds = %latch
168 default: ; preds = %otherexit, %exiting
171 otherexit: ; preds = %exiting
175 ; exit block (%exitB) has an exiting block and another exit block as predecessors.
176 ; exiting block comes from inner loop.
177 define void @test5() {
180 ; CHECK-NEXT: br i1 false, label %outerH.prol.preheader, label %outerH.prol.loopexit
182 ; CHECK-LABEL: outerH.prol.preheader:
183 ; CHECK-NEXT: br label %outerH.prol
185 ; CHECK-LABEL: outerH.prol:
186 ; CHECK-NEXT: %tmp4.prol = phi i32 [ %tmp6.prol, %outerLatch.prol ], [ undef, %outerH.prol.preheader ]
187 ; CHECK-NEXT: %prol.iter = phi i32 [ 0, %outerH.prol.preheader ], [ %prol.iter.sub, %outerLatch.prol ]
188 ; CHECK-NEXT: br label %innerH.prol
190 %tmp = icmp sgt i32 undef, 79
191 br i1 %tmp, label %outerLatchExit, label %bb1
196 outerH: ; preds = %outerLatch, %bb1
197 %tmp4 = phi i32 [ %tmp6, %outerLatch ], [ undef, %bb1 ]
200 innerH: ; preds = %innerLatch, %outerH
201 br i1 undef, label %innerexiting, label %otherexitB
203 innerexiting: ; preds = %innerH
204 br i1 undef, label %innerLatch, label %exitB
206 innerLatch: ; preds = %innerexiting
207 %tmp13 = fcmp olt double undef, 2.000000e+00
208 br i1 %tmp13, label %innerH, label %outerLatch
210 outerLatch: ; preds = %innerLatch
211 %tmp6 = add i32 %tmp4, 1
212 %tmp7 = icmp sgt i32 %tmp6, 79
213 br i1 %tmp7, label %outerLatchExit, label %outerH
215 outerLatchExit: ; preds = %outerLatch, %bb
218 exitB: ; preds = %innerexiting, %otherexitB
221 otherexitB: ; preds = %innerH
226 ; Blocks reachable from exits (not_zero44) have the IDom as the block within the loop (Header).
227 ; Update the IDom to the preheader.
228 define void @test6() {
230 ; CHECK-LABEL: header.prol.preheader:
231 ; CHECK-NEXT: br label %header.prol
233 ; CHECK-LABEL: header.prol:
234 ; CHECK-NEXT: %indvars.iv.prol = phi i64 [ undef, %header.prol.preheader ], [ %indvars.iv.next.prol, %latch.prol ]
235 ; CHECK-NEXT: %prol.iter = phi i64 [ 1, %header.prol.preheader ], [ %prol.iter.sub, %latch.prol ]
236 ; CHECK-NEXT: br i1 false, label %latch.prol, label %otherexit.loopexit1
238 ; CHECK-LABEL: header.prol.loopexit.unr-lcssa:
239 ; CHECK-NEXT: %indvars.iv.unr.ph = phi i64 [ %indvars.iv.next.prol, %latch.prol ]
240 ; CHECK-NEXT: br label %header.prol.loopexit
242 ; CHECK-LABEL: header.prol.loopexit:
243 ; CHECK-NEXT: %indvars.iv.unr = phi i64 [ undef, %entry ], [ %indvars.iv.unr.ph, %header.prol.loopexit.unr-lcssa ]
244 ; CHECK-NEXT: br i1 true, label %latchexit, label %entry.new
246 ; CHECK-LABEL: entry.new:
247 ; CHECK-NEXT: br label %header
251 header: ; preds = %latch, %entry
252 %indvars.iv = phi i64 [ undef, %entry ], [ %indvars.iv.next, %latch ]
253 br i1 undef, label %latch, label %otherexit
255 latch: ; preds = %header
256 %indvars.iv.next = add nsw i64 %indvars.iv, 2
257 %0 = icmp slt i64 %indvars.iv.next, 616
258 br i1 %0, label %header, label %latchexit
260 latchexit: ; preds = %latch
261 br label %latchexitsucc
263 otherexit: ; preds = %header
264 br label %otherexitsucc
266 otherexitsucc: ; preds = %otherexit
269 not_zero44: ; preds = %latchexitsucc, %otherexitsucc
272 latchexitsucc: ; preds = %latchexit