1; RUN: opt < %s -S -loop-flatten -verify-loop-info -verify-dom-info -verify-scev -verify | FileCheck %s
2
3target datalayout = "e-m:e-p:32:32-i64:64-v128:64:128-a:0:32-n32-S64"
4
5; CHECK-LABEL: test1
6; Simple loop where the IV's is constant
7define i32 @test1(i32 %val, i16* nocapture %A) {
8entry:
9  br label %for.body
10; CHECK: entry:
11; CHECK:   %flatten.tripcount = mul i32 20, 10
12; CHECK:   br label %for.body
13
14for.body:                                         ; preds = %entry, %for.inc6
15  %i.018 = phi i32 [ 0, %entry ], [ %inc7, %for.inc6 ]
16  %mul = mul nuw nsw i32 %i.018, 20
17  br label %for.body3
18; CHECK: for.body:
19; CHECK:   %i.018 = phi i32 [ 0, %entry ], [ %inc7, %for.inc6 ]
20; CHECK:   %mul = mul nuw nsw i32 %i.018, 20
21; CHECK:   br label %for.body3
22
23for.body3:                                        ; preds = %for.body, %for.body3
24  %j.017 = phi i32 [ 0, %for.body ], [ %inc, %for.body3 ]
25  %add = add nuw nsw i32 %j.017, %mul
26  %arrayidx = getelementptr inbounds i16, i16* %A, i32 %add
27  %0 = load i16, i16* %arrayidx, align 2
28  %conv16 = zext i16 %0 to i32
29  %add4 = add i32 %conv16, %val
30  %conv5 = trunc i32 %add4 to i16
31  store i16 %conv5, i16* %arrayidx, align 2
32  %inc = add nuw nsw i32 %j.017, 1
33  %exitcond = icmp ne i32 %inc, 20
34  br i1 %exitcond, label %for.body3, label %for.inc6
35; CHECK: for.body3:
36; CHECK:   %j.017 = phi i32 [ 0, %for.body ]
37; CHECK:   %add = add nuw nsw i32 %j.017, %mul
38; CHECK:   %arrayidx = getelementptr inbounds i16, i16* %A, i32 %i.018
39; CHECK:   %0 = load i16, i16* %arrayidx, align 2
40; CHECK:   %conv16 = zext i16 %0 to i32
41; CHECK:   %add4 = add i32 %conv16, %val
42; CHECK:   %conv5 = trunc i32 %add4 to i16
43; CHECK:   store i16 %conv5, i16* %arrayidx, align 2
44; CHECK:   %inc = add nuw nsw i32 %j.017, 1
45; CHECK:   %exitcond = icmp ne i32 %inc, 20
46; CHECK:   br label %for.inc6
47
48for.inc6:                                         ; preds = %for.body3
49  %inc7 = add nuw nsw i32 %i.018, 1
50  %exitcond19 = icmp ne i32 %inc7, 10
51  br i1 %exitcond19, label %for.body, label %for.end8
52; CHECK: for.inc6:
53; CHECK:   %inc7 = add nuw nsw i32 %i.018, 1
54; CHECK:   %exitcond19 = icmp ne i32 %inc7, %flatten.tripcount
55; CHECK:   br i1 %exitcond19, label %for.body, label %for.end8
56
57for.end8:                                         ; preds = %for.inc6
58  ret i32 10
59}
60
61
62; CHECK-LABEL: test2
63; Same as above but non constant IV (which still cannot overflow)
64define i32 @test2(i8 zeroext %I, i32 %val, i16* nocapture %A) {
65entry:
66  %conv = zext i8 %I to i32
67  %cmp26 = icmp eq i8 %I, 0
68  br i1 %cmp26, label %for.end13, label %for.body.lr.ph.split.us
69
70for.body.lr.ph.split.us:                          ; preds = %entry
71  br label %for.body.us
72; CHECK: for.body.lr.ph.split.us:
73; CHECK:   %flatten.tripcount = mul i32 %conv, %conv
74; CHECK:   br label %for.body.us
75
76for.body.us:                                      ; preds = %for.cond2.for.inc11_crit_edge.us, %for.body.lr.ph.split.us
77  %i.027.us = phi i32 [ 0, %for.body.lr.ph.split.us ], [ %inc12.us, %for.cond2.for.inc11_crit_edge.us ]
78  %mul.us = mul nuw nsw i32 %i.027.us, %conv
79  br label %for.body6.us
80; CHECK: for.body.us:
81; CHECK:   %i.027.us = phi i32 [ 0, %for.body.lr.ph.split.us ], [ %inc12.us, %for.cond2.for.inc11_crit_edge.us ]
82; CHECK:   %mul.us = mul nuw nsw i32 %i.027.us, %conv
83; CHECK:   br label %for.body6.us
84
85for.body6.us:                                     ; preds = %for.body.us, %for.body6.us
86  %j.025.us = phi i32 [ 0, %for.body.us ], [ %inc.us, %for.body6.us ]
87  %add.us = add nuw nsw i32 %j.025.us, %mul.us
88  %arrayidx.us = getelementptr inbounds i16, i16* %A, i32 %add.us
89  %0 = load i16, i16* %arrayidx.us, align 2
90  %conv823.us = zext i16 %0 to i32
91  %add9.us = add i32 %conv823.us, %val
92  %conv10.us = trunc i32 %add9.us to i16
93  store i16 %conv10.us, i16* %arrayidx.us, align 2
94  %inc.us = add nuw nsw i32 %j.025.us, 1
95  %exitcond = icmp ne i32 %inc.us, %conv
96  br i1 %exitcond, label %for.body6.us, label %for.cond2.for.inc11_crit_edge.us
97; CHECK: for.body6.us:
98; CHECK:   %j.025.us = phi i32 [ 0, %for.body.us ]
99; CHECK:   %add.us = add nuw nsw i32 %j.025.us, %mul.us
100; CHECK:   %arrayidx.us = getelementptr inbounds i16, i16* %A, i32 %i.027.us
101; CHECK:   %0 = load i16, i16* %arrayidx.us, align 2
102; CHECK:   %conv823.us = zext i16 %0 to i32
103; CHECK:   %add9.us = add i32 %conv823.us, %val
104; CHECK:   %conv10.us = trunc i32 %add9.us to i16
105; CHECK:   store i16 %conv10.us, i16* %arrayidx.us, align 2
106; CHECK:   %inc.us = add nuw nsw i32 %j.025.us, 1
107; CHECK:   %exitcond = icmp ne i32 %inc.us, %conv
108; CHECK:   br label %for.cond2.for.inc11_crit_edge.us
109
110for.cond2.for.inc11_crit_edge.us:                 ; preds = %for.body6.us
111  %inc12.us = add nuw nsw i32 %i.027.us, 1
112  %exitcond28 = icmp ne i32 %inc12.us, %conv
113  br i1 %exitcond28, label %for.body.us, label %for.end13.loopexit
114; CHECK: for.cond2.for.inc11_crit_edge.us:                 ; preds = %for.body6.us
115; CHECK:   %inc12.us = add nuw nsw i32 %i.027.us, 1
116; CHECK:   %exitcond28 = icmp ne i32 %inc12.us, %flatten.tripcount
117; CHECK:   br i1 %exitcond28, label %for.body.us, label %for.end13.loopexit
118
119for.end13.loopexit:                               ; preds = %for.cond2.for.inc11_crit_edge.us
120  br label %for.end13
121
122for.end13:                                        ; preds = %for.end13.loopexit, %entry
123  %i.0.lcssa = phi i32 [ 0, %entry ], [ %conv, %for.end13.loopexit ]
124  ret i32 %i.0.lcssa
125}
126
127
128; CHECK-LABEL: test3
129; Same as above, uses load to determine it can't overflow
130define i32 @test3(i32 %N, i32 %val, i16* nocapture %A) local_unnamed_addr #0 {
131entry:
132  %cmp21 = icmp eq i32 %N, 0
133  br i1 %cmp21, label %for.end8, label %for.body.lr.ph.split.us
134
135for.body.lr.ph.split.us:                          ; preds = %entry
136  br label %for.body.us
137; CHECK: for.body.lr.ph.split.us:
138; CHECK:   %flatten.tripcount = mul i32 %N, %N
139; CHECK:   br label %for.body.us
140
141for.body.us:                                      ; preds = %for.cond1.for.inc6_crit_edge.us, %for.body.lr.ph.split.us
142  %i.022.us = phi i32 [ 0, %for.body.lr.ph.split.us ], [ %inc7.us, %for.cond1.for.inc6_crit_edge.us ]
143  %mul.us = mul i32 %i.022.us, %N
144  br label %for.body3.us
145; CHECK: for.body.us:
146; CHECK:   %i.022.us = phi i32 [ 0, %for.body.lr.ph.split.us ], [ %inc7.us, %for.cond1.for.inc6_crit_edge.us ]
147; CHECK:   %mul.us = mul i32 %i.022.us, %N
148; CHECK:   br label %for.body3.us
149
150for.body3.us:                                     ; preds = %for.body.us, %for.body3.us
151  %j.020.us = phi i32 [ 0, %for.body.us ], [ %inc.us, %for.body3.us ]
152  %add.us = add i32 %j.020.us, %mul.us
153  %arrayidx.us = getelementptr inbounds i16, i16* %A, i32 %add.us
154  %0 = load i16, i16* %arrayidx.us, align 2
155  %conv18.us = zext i16 %0 to i32
156  %add4.us = add i32 %conv18.us, %val
157  %conv5.us = trunc i32 %add4.us to i16
158  store i16 %conv5.us, i16* %arrayidx.us, align 2
159  %inc.us = add nuw i32 %j.020.us, 1
160  %exitcond = icmp ne i32 %inc.us, %N
161  br i1 %exitcond, label %for.body3.us, label %for.cond1.for.inc6_crit_edge.us
162; CHECK: for.body3.us:
163; CHECK:   %j.020.us = phi i32 [ 0, %for.body.us ]
164; CHECK:   %add.us = add i32 %j.020.us, %mul.us
165; CHECK:   %arrayidx.us = getelementptr inbounds i16, i16* %A, i32 %i.022.us
166; CHECK:   %0 = load i16, i16* %arrayidx.us, align 2
167; CHECK:   %conv18.us = zext i16 %0 to i32
168; CHECK:   %add4.us = add i32 %conv18.us, %val
169; CHECK:   %conv5.us = trunc i32 %add4.us to i16
170; CHECK:   store i16 %conv5.us, i16* %arrayidx.us, align 2
171; CHECK:   %inc.us = add nuw i32 %j.020.us, 1
172; CHECK:   %exitcond = icmp ne i32 %inc.us, %N
173; CHECK:   br label %for.cond1.for.inc6_crit_edge.us
174
175for.cond1.for.inc6_crit_edge.us:                  ; preds = %for.body3.us
176  %inc7.us = add nuw i32 %i.022.us, 1
177  %exitcond23 = icmp ne i32 %inc7.us, %N
178  br i1 %exitcond23, label %for.body.us, label %for.end8.loopexit
179; CHECK: for.cond1.for.inc6_crit_edge.us:
180; CHECK:   %inc7.us = add nuw i32 %i.022.us, 1
181; CHECK:   %exitcond23 = icmp ne i32 %inc7.us, %flatten.tripcount
182; CHECK:   br i1 %exitcond23, label %for.body.us, label %for.end8.loopexit
183
184for.end8.loopexit:                                ; preds = %for.cond1.for.inc6_crit_edge.us
185  br label %for.end8
186
187for.end8:                                         ; preds = %for.end8.loopexit, %entry
188  %i.0.lcssa = phi i32 [ 0, %entry ], [ %N, %for.end8.loopexit ]
189  ret i32 %i.0.lcssa
190}
191
192
193; CHECK-LABEL: test4
194; Multiplication cannot overflow, so we can replace the original loop.
195define void @test4(i16 zeroext %N, i32* nocapture %C, i32* nocapture readonly %A, i32 %scale) {
196entry:
197  %conv = zext i16 %N to i32
198  %cmp30 = icmp eq i16 %N, 0
199  br i1 %cmp30, label %for.cond.cleanup, label %for.body.lr.ph.split.us
200; CHECK: entry:
201; CHECK: %[[LIMIT:.*]] = zext i16 %N to i32
202; CHECK: br i1 %{{.*}} label %for.cond.cleanup, label %for.body.lr.ph.split.us
203
204for.body.lr.ph.split.us:                          ; preds = %entry
205  br label %for.body.us
206; CHECK: for.body.lr.ph.split.us:
207; CHECK: %[[TRIPCOUNT:.*]] = mul i32 %[[LIMIT]], %[[LIMIT]]
208; CHECK: br label %for.body.us
209
210for.body.us:                                      ; preds = %for.cond2.for.cond.cleanup6_crit_edge.us, %for.body.lr.ph.split.us
211  %i.031.us = phi i32 [ 0, %for.body.lr.ph.split.us ], [ %inc15.us, %for.cond2.for.cond.cleanup6_crit_edge.us ]
212  %mul.us = mul nuw nsw i32 %i.031.us, %conv
213  br label %for.body7.us
214; CHECK: for.body.us:
215; CHECK: %[[OUTER_IV:.*]] = phi i32
216; CHECK: br label %for.body7.us
217
218for.body7.us:                                     ; preds = %for.body.us, %for.body7.us
219; CHECK: for.body7.us:
220  %j.029.us = phi i32 [ 0, %for.body.us ], [ %inc.us, %for.body7.us ]
221  %add.us = add nuw nsw i32 %j.029.us, %mul.us
222  %arrayidx.us = getelementptr inbounds i32, i32* %A, i32 %add.us
223; CHECK: getelementptr inbounds i32, i32* %A, i32 %[[OUTER_IV]]
224  %0 = load i32, i32* %arrayidx.us, align 4
225  %mul9.us = mul nsw i32 %0, %scale
226; CHECK: getelementptr inbounds i32, i32* %C, i32 %[[OUTER_IV]]
227  %arrayidx13.us = getelementptr inbounds i32, i32* %C, i32 %add.us
228  store i32 %mul9.us, i32* %arrayidx13.us, align 4
229  %inc.us = add nuw nsw i32 %j.029.us, 1
230  %exitcond = icmp ne i32 %inc.us, %conv
231  br i1 %exitcond, label %for.body7.us, label %for.cond2.for.cond.cleanup6_crit_edge.us
232; CHECK: br label %for.cond2.for.cond.cleanup6_crit_edge.us
233
234for.cond2.for.cond.cleanup6_crit_edge.us:         ; preds = %for.body7.us
235  %inc15.us = add nuw nsw i32 %i.031.us, 1
236  %exitcond32 = icmp ne i32 %inc15.us, %conv
237  br i1 %exitcond32, label %for.body.us, label %for.cond.cleanup.loopexit
238; CHECK: for.cond2.for.cond.cleanup6_crit_edge.us:
239; CHECK: br i1 %exitcond32, label %for.body.us, label %for.cond.cleanup.loopexit
240
241for.cond.cleanup.loopexit:                        ; preds = %for.cond2.for.cond.cleanup6_crit_edge.us
242  br label %for.cond.cleanup
243; CHECK: for.cond.cleanup.loopexit:
244; CHECK: br label %for.cond.cleanup
245
246for.cond.cleanup:                                 ; preds = %for.cond.cleanup.loopexit, %entry
247  ret void
248; CHECK: for.cond.cleanup:
249; CHECK: ret void
250}
251
252
253; CHECK-LABEL: test5
254define i32 @test5(i8 zeroext %I, i16 zeroext %J) {
255entry:
256  %0 = lshr i8 %I, 1
257  %div = zext i8 %0 to i32
258  %cmp30 = icmp eq i8 %0, 0
259  br i1 %cmp30, label %for.cond.cleanup, label %for.body.lr.ph
260
261for.body.lr.ph:                                   ; preds = %entry
262  %1 = lshr i16 %J, 1
263  %div5 = zext i16 %1 to i32
264  %cmp627 = icmp eq i16 %1, 0
265  br i1 %cmp627, label %for.body.lr.ph.split, label %for.body.lr.ph.split.us
266
267for.body.lr.ph.split.us:                          ; preds = %for.body.lr.ph
268  br label %for.body.us
269; CHECK: for.body.lr.ph.split.us:
270; CHECK:   %flatten.tripcount = mul i32 %div5, %div
271; CHECK:   br label %for.body.us
272
273for.body.us:                                      ; preds = %for.cond3.for.cond.cleanup8_crit_edge.us, %for.body.lr.ph.split.us
274  %i.032.us = phi i32 [ 0, %for.body.lr.ph.split.us ], [ %inc13.us, %for.cond3.for.cond.cleanup8_crit_edge.us ]
275  %x.031.us = phi i32 [ 1, %for.body.lr.ph.split.us ], [ %xor.us.lcssa, %for.cond3.for.cond.cleanup8_crit_edge.us ]
276  br label %for.body9.us
277; CHECK: for.body.us:
278; CHECK:   %i.032.us = phi i32 [ 0, %for.body.lr.ph.split.us ], [ %inc13.us, %for.cond3.for.cond.cleanup8_crit_edge.us ]
279; CHECK:   %x.031.us = phi i32 [ 1, %for.body.lr.ph.split.us ], [ %xor.us.lcssa, %for.cond3.for.cond.cleanup8_crit_edge.us ]
280; CHECK:   br label %for.body9.us
281
282for.body9.us:                                     ; preds = %for.body.us, %for.body9.us
283  %j.029.us = phi i32 [ 0, %for.body.us ], [ %inc.us, %for.body9.us ]
284  %x.128.us = phi i32 [ %x.031.us, %for.body.us ], [ %xor.us, %for.body9.us ]
285  %call.us = tail call i32 @func(i32 1)
286  %sub.us = sub nsw i32 %call.us, %x.128.us
287  %xor.us = xor i32 %sub.us, %x.128.us
288  %inc.us = add nuw nsw i32 %j.029.us, 1
289  %cmp6.us = icmp ult i32 %inc.us, %div5
290  br i1 %cmp6.us, label %for.body9.us, label %for.cond3.for.cond.cleanup8_crit_edge.us
291; CHECK: for.body9.us:
292; CHECK:   %j.029.us = phi i32 [ 0, %for.body.us ]
293; CHECK:   %x.128.us = phi i32 [ %x.031.us, %for.body.us ]
294; CHECK:   %call.us = tail call i32 @func(i32 1)
295; CHECK:   %sub.us = sub nsw i32 %call.us, %x.128.us
296; CHECK:   %xor.us = xor i32 %sub.us, %x.128.us
297; CHECK:   %inc.us = add nuw nsw i32 %j.029.us, 1
298; CHECK:   %cmp6.us = icmp ult i32 %inc.us, %div5
299; CHECK:   br label %for.cond3.for.cond.cleanup8_crit_edge.us
300
301for.cond3.for.cond.cleanup8_crit_edge.us:         ; preds = %for.body9.us
302  %xor.us.lcssa = phi i32 [ %xor.us, %for.body9.us ]
303  %inc13.us = add nuw nsw i32 %i.032.us, 1
304  %cmp.us = icmp ult i32 %inc13.us, %div
305  br i1 %cmp.us, label %for.body.us, label %for.cond.cleanup.loopexit
306; CHECK: for.cond3.for.cond.cleanup8_crit_edge.us:
307; CHECK:   %xor.us.lcssa = phi i32 [ %xor.us, %for.body9.us ]
308; CHECK:   %inc13.us = add nuw nsw i32 %i.032.us, 1
309; CHECK:   %cmp.us = icmp ult i32 %inc13.us, %flatten.tripcount
310; CHECK:   br i1 %cmp.us, label %for.body.us, label %for.cond.cleanup.loopexit
311
312for.body.lr.ph.split:                             ; preds = %for.body.lr.ph
313  br label %for.body
314
315for.cond.cleanup.loopexit:                        ; preds = %for.cond3.for.cond.cleanup8_crit_edge.us
316  %xor.us.lcssa.lcssa = phi i32 [ %xor.us.lcssa, %for.cond3.for.cond.cleanup8_crit_edge.us ]
317  br label %for.cond.cleanup
318
319for.cond.cleanup.loopexit34:                      ; preds = %for.body
320  br label %for.cond.cleanup
321
322for.cond.cleanup:                                 ; preds = %for.cond.cleanup.loopexit34, %for.cond.cleanup.loopexit, %entry
323  %x.0.lcssa = phi i32 [ 1, %entry ], [ %xor.us.lcssa.lcssa, %for.cond.cleanup.loopexit ], [ 1, %for.cond.cleanup.loopexit34 ]
324  ret i32 %x.0.lcssa
325
326for.body:                                         ; preds = %for.body.lr.ph.split, %for.body
327  %i.032 = phi i32 [ 0, %for.body.lr.ph.split ], [ %inc13, %for.body ]
328  %inc13 = add nuw nsw i32 %i.032, 1
329  %cmp = icmp ult i32 %inc13, %div
330  br i1 %cmp, label %for.body, label %for.cond.cleanup.loopexit34
331}
332
333
334; CHECK-LABEL: test6
335define i32 @test6(i8 zeroext %I, i16 zeroext %J) {
336entry:
337  %0 = lshr i8 %I, 1
338  %div = zext i8 %0 to i32
339  %cmp30 = icmp eq i8 %0, 0
340  br i1 %cmp30, label %for.cond.cleanup, label %for.body.lr.ph
341
342for.body.lr.ph:                                   ; preds = %entry
343  %1 = lshr i16 %J, 1
344  %div5 = zext i16 %1 to i32
345  %cmp627 = icmp eq i16 %1, 0
346  br i1 %cmp627, label %for.body.lr.ph.split, label %for.body.lr.ph.split.us
347
348for.body.lr.ph.split.us:                          ; preds = %for.body.lr.ph
349  br label %for.body.us
350; CHECK: for.body.lr.ph.split.us:
351; CHECK:   %flatten.tripcount = mul i32 %div5, %div
352; CHECK:   br label %for.body.us
353
354for.body.us:                                      ; preds = %for.cond3.for.cond.cleanup8_crit_edge.us, %for.body.lr.ph.split.us
355  %i.032.us = phi i32 [ 0, %for.body.lr.ph.split.us ], [ %inc13.us, %for.cond3.for.cond.cleanup8_crit_edge.us ]
356  %x.031.us = phi i32 [ 1, %for.body.lr.ph.split.us ], [ %xor.us.lcssa, %for.cond3.for.cond.cleanup8_crit_edge.us ]
357  %mul.us = mul nuw nsw i32 %i.032.us, %div5
358  br label %for.body9.us
359; CHECK: for.body.us:
360; CHECK:   %i.032.us = phi i32 [ 0, %for.body.lr.ph.split.us ], [ %inc13.us, %for.cond3.for.cond.cleanup8_crit_edge.us ]
361; CHECK:   %x.031.us = phi i32 [ 1, %for.body.lr.ph.split.us ], [ %xor.us.lcssa, %for.cond3.for.cond.cleanup8_crit_edge.us ]
362; CHECK:   %mul.us = mul nuw nsw i32 %i.032.us, %div5
363; CHECK:   br label %for.body9.us
364
365for.body9.us:                                     ; preds = %for.body.us, %for.body9.us
366  %j.029.us = phi i32 [ 0, %for.body.us ], [ %inc.us, %for.body9.us ]
367  %x.128.us = phi i32 [ %x.031.us, %for.body.us ], [ %xor.us, %for.body9.us ]
368  %add.us = add nuw nsw i32 %j.029.us, %mul.us
369  %call.us = tail call i32 @func(i32 %add.us)
370  %sub.us = sub nsw i32 %call.us, %x.128.us
371  %xor.us = xor i32 %sub.us, %x.128.us
372  %inc.us = add nuw nsw i32 %j.029.us, 1
373  %cmp6.us = icmp ult i32 %inc.us, %div5
374  br i1 %cmp6.us, label %for.body9.us, label %for.cond3.for.cond.cleanup8_crit_edge.us
375; CHECK: for.body9.us:
376; CHECK:   %j.029.us = phi i32 [ 0, %for.body.us ]
377; CHECK:   %x.128.us = phi i32 [ %x.031.us, %for.body.us ]
378; CHECK:   %add.us = add nuw nsw i32 %j.029.us, %mul.us
379; CHECK:   %call.us = tail call i32 @func(i32 %i.032.us)
380; CHECK:   %sub.us = sub nsw i32 %call.us, %x.128.us
381; CHECK:   %xor.us = xor i32 %sub.us, %x.128.us
382; CHECK:   %inc.us = add nuw nsw i32 %j.029.us, 1
383; CHECK:   %cmp6.us = icmp ult i32 %inc.us, %div5
384; CHECK:   br label %for.cond3.for.cond.cleanup8_crit_edge.us
385
386for.cond3.for.cond.cleanup8_crit_edge.us:         ; preds = %for.body9.us
387  %xor.us.lcssa = phi i32 [ %xor.us, %for.body9.us ]
388  %inc13.us = add nuw nsw i32 %i.032.us, 1
389  %cmp.us = icmp ult i32 %inc13.us, %div
390  br i1 %cmp.us, label %for.body.us, label %for.cond.cleanup.loopexit
391; CHECK: for.cond3.for.cond.cleanup8_crit_edge.us:
392; CHECK:   %xor.us.lcssa = phi i32 [ %xor.us, %for.body9.us ]
393; CHECK:   %inc13.us = add nuw nsw i32 %i.032.us, 1
394; CHECK:   %cmp.us = icmp ult i32 %inc13.us, %flatten.tripcount
395; CHECK:   br i1 %cmp.us, label %for.body.us, label %for.cond.cleanup.loopexit
396
397for.body.lr.ph.split:                             ; preds = %for.body.lr.ph
398  br label %for.body
399
400for.cond.cleanup.loopexit:                        ; preds = %for.cond3.for.cond.cleanup8_crit_edge.us
401  %xor.us.lcssa.lcssa = phi i32 [ %xor.us.lcssa, %for.cond3.for.cond.cleanup8_crit_edge.us ]
402  br label %for.cond.cleanup
403
404for.cond.cleanup.loopexit34:                      ; preds = %for.body
405  br label %for.cond.cleanup
406
407for.cond.cleanup:                                 ; preds = %for.cond.cleanup.loopexit34, %for.cond.cleanup.loopexit, %entry
408  %x.0.lcssa = phi i32 [ 1, %entry ], [ %xor.us.lcssa.lcssa, %for.cond.cleanup.loopexit ], [ 1, %for.cond.cleanup.loopexit34 ]
409  ret i32 %x.0.lcssa
410
411for.body:                                         ; preds = %for.body.lr.ph.split, %for.body
412  %i.032 = phi i32 [ 0, %for.body.lr.ph.split ], [ %inc13, %for.body ]
413  %inc13 = add nuw nsw i32 %i.032, 1
414  %cmp = icmp ult i32 %inc13, %div
415  br i1 %cmp, label %for.body, label %for.cond.cleanup.loopexit34
416}
417
418; CHECK-LABEL: test7
419; Various inner phis and conditions which we can still work with
420define signext i16 @test7(i32 %I, i32 %J, i32* nocapture readonly %C, i16 signext %limit) {
421entry:
422  %cmp43 = icmp eq i32 %J, 0
423  br i1 %cmp43, label %for.end17, label %for.body.lr.ph
424
425for.body.lr.ph:                                   ; preds = %entry
426  %conv = sext i16 %limit to i32
427  br label %for.body.us
428; CHECK: for.body.lr.ph:
429; CHECK:   %conv = sext i16 %limit to i32
430; CHECK:   %flatten.tripcount = mul i32 %J, %J
431; CHECK:   br label %for.body.us
432
433for.body.us:                                      ; preds = %for.cond1.for.inc15_crit_edge.us, %for.body.lr.ph
434  %i.047.us = phi i32 [ 0, %for.body.lr.ph ], [ %inc16.us, %for.cond1.for.inc15_crit_edge.us ]
435  %ret.046.us = phi i16 [ 0, %for.body.lr.ph ], [ %ret.2.us.lcssa, %for.cond1.for.inc15_crit_edge.us ]
436  %prev.045.us = phi i32 [ 0, %for.body.lr.ph ], [ %.lcssa, %for.cond1.for.inc15_crit_edge.us ]
437  %tmp.044.us = phi i32 [ 0, %for.body.lr.ph ], [ %tmp.2.us.lcssa, %for.cond1.for.inc15_crit_edge.us ]
438  %mul.us = mul i32 %i.047.us, %J
439  br label %for.body3.us
440; CHECK: for.body.us:
441; CHECK:   %i.047.us = phi i32 [ 0, %for.body.lr.ph ], [ %inc16.us, %for.cond1.for.inc15_crit_edge.us ]
442; CHECK:   %ret.046.us = phi i16 [ 0, %for.body.lr.ph ], [ %ret.2.us.lcssa, %for.cond1.for.inc15_crit_edge.us ]
443; CHECK:   %prev.045.us = phi i32 [ 0, %for.body.lr.ph ], [ %.lcssa, %for.cond1.for.inc15_crit_edge.us ]
444; CHECK:   %tmp.044.us = phi i32 [ 0, %for.body.lr.ph ], [ %tmp.2.us.lcssa, %for.cond1.for.inc15_crit_edge.us ]
445; CHECK:   %mul.us = mul i32 %i.047.us, %J
446; CHECK:   br label %for.body3.us
447
448for.body3.us:                                     ; preds = %for.body.us, %if.end.us
449  %j.040.us = phi i32 [ 0, %for.body.us ], [ %inc.us, %if.end.us ]
450  %ret.139.us = phi i16 [ %ret.046.us, %for.body.us ], [ %ret.2.us, %if.end.us ]
451  %prev.138.us = phi i32 [ %prev.045.us, %for.body.us ], [ %0, %if.end.us ]
452  %tmp.137.us = phi i32 [ %tmp.044.us, %for.body.us ], [ %tmp.2.us, %if.end.us ]
453  %add.us = add i32 %j.040.us, %mul.us
454  %arrayidx.us = getelementptr inbounds i32, i32* %C, i32 %add.us
455  %0 = load i32, i32* %arrayidx.us, align 4
456  %add4.us = add nsw i32 %0, %tmp.137.us
457  %cmp5.us = icmp sgt i32 %add4.us, %conv
458  br i1 %cmp5.us, label %if.then.us, label %if.else.us
459; CHECK: for.body3.us:
460; CHECK:   %j.040.us = phi i32 [ 0, %for.body.us ]
461; CHECK:   %ret.139.us = phi i16 [ %ret.046.us, %for.body.us ]
462; CHECK:   %prev.138.us = phi i32 [ %prev.045.us, %for.body.us ]
463; CHECK:   %tmp.137.us = phi i32 [ %tmp.044.us, %for.body.us ]
464; CHECK:   %add.us = add i32 %j.040.us, %mul.us
465; CHECK:   %arrayidx.us = getelementptr inbounds i32, i32* %C, i32 %i.047.us
466; CHECK:   %0 = load i32, i32* %arrayidx.us, align 4
467; CHECK:   %add4.us = add nsw i32 %0, %tmp.137.us
468; CHECK:   %cmp5.us = icmp sgt i32 %add4.us, %conv
469; CHECK:   br i1 %cmp5.us, label %if.then.us, label %if.else.us
470
471if.else.us:                                       ; preds = %for.body3.us
472  %cmp10.us = icmp sgt i32 %0, %prev.138.us
473  %cond.us = zext i1 %cmp10.us to i32
474  %conv1235.us = zext i16 %ret.139.us to i32
475  %add13.us = add nuw nsw i32 %cond.us, %conv1235.us
476  br label %if.end.us
477; CHECK: if.else.us:
478; CHECK:   %cmp10.us = icmp sgt i32 %0, %prev.138.us
479; CHECK:   %cond.us = zext i1 %cmp10.us to i32
480; CHECK:   %conv1235.us = zext i16 %ret.139.us to i32
481; CHECK:   %add13.us = add nuw nsw i32 %cond.us, %conv1235.us
482; CHECK:   br label %if.end.us
483
484if.then.us:                                       ; preds = %for.body3.us
485  %conv7.us = sext i16 %ret.139.us to i32
486  %add8.us = add nsw i32 %conv7.us, 10
487  br label %if.end.us
488; CHECK: if.then.us:
489; CHECK:   %conv7.us = sext i16 %ret.139.us to i32
490; CHECK:   %add8.us = add nsw i32 %conv7.us, 10
491; CHECK:   br label %if.end.us
492
493if.end.us:                                        ; preds = %if.then.us, %if.else.us
494  %tmp.2.us = phi i32 [ 0, %if.then.us ], [ %add4.us, %if.else.us ]
495  %ret.2.in.us = phi i32 [ %add8.us, %if.then.us ], [ %add13.us, %if.else.us ]
496  %ret.2.us = trunc i32 %ret.2.in.us to i16
497  %inc.us = add nuw i32 %j.040.us, 1
498  %exitcond = icmp ne i32 %inc.us, %J
499  br i1 %exitcond, label %for.body3.us, label %for.cond1.for.inc15_crit_edge.us
500; CHECK: if.end.us:
501; CHECK:   %tmp.2.us = phi i32 [ 0, %if.then.us ], [ %add4.us, %if.else.us ]
502; CHECK:   %ret.2.in.us = phi i32 [ %add8.us, %if.then.us ], [ %add13.us, %if.else.us ]
503; CHECK:   %ret.2.us = trunc i32 %ret.2.in.us to i16
504; CHECK:   %inc.us = add nuw i32 %j.040.us, 1
505; CHECK:   %exitcond = icmp ne i32 %inc.us, %J
506; CHECK:   br label %for.cond1.for.inc15_crit_edge.us
507
508for.cond1.for.inc15_crit_edge.us:                 ; preds = %if.end.us
509  %tmp.2.us.lcssa = phi i32 [ %tmp.2.us, %if.end.us ]
510  %ret.2.us.lcssa = phi i16 [ %ret.2.us, %if.end.us ]
511  %.lcssa = phi i32 [ %0, %if.end.us ]
512  %inc16.us = add nuw i32 %i.047.us, 1
513  %exitcond49 = icmp ne i32 %inc16.us, %J
514  br i1 %exitcond49, label %for.body.us, label %for.end17.loopexit
515; CHECK: for.cond1.for.inc15_crit_edge.us:
516; CHECK:   %tmp.2.us.lcssa = phi i32 [ %tmp.2.us, %if.end.us ]
517; CHECK:   %ret.2.us.lcssa = phi i16 [ %ret.2.us, %if.end.us ]
518; CHECK:   %.lcssa = phi i32 [ %0, %if.end.us ]
519; CHECK:   %inc16.us = add nuw i32 %i.047.us, 1
520; CHECK:   %exitcond49 = icmp ne i32 %inc16.us, %flatten.tripcount
521; CHECK:   br i1 %exitcond49, label %for.body.us, label %for.end17.loopexit
522
523for.end17.loopexit:                               ; preds = %for.cond1.for.inc15_crit_edge.us
524  %ret.2.us.lcssa.lcssa = phi i16 [ %ret.2.us.lcssa, %for.cond1.for.inc15_crit_edge.us ]
525  br label %for.end17
526
527for.end17:                                        ; preds = %for.end17.loopexit, %entry
528  %ret.0.lcssa = phi i16 [ 0, %entry ], [ %ret.2.us.lcssa.lcssa, %for.end17.loopexit ]
529  ret i16 %ret.0.lcssa
530}
531
532; CHECK-LABEL: test8
533; Same as test1, but with different continue block order
534; (uses icmp eq and loops on false)
535define i32 @test8(i32 %val, i16* nocapture %A) {
536entry:
537  br label %for.body
538; CHECK: entry:
539; CHECK:   %flatten.tripcount = mul i32 20, 10
540; CHECK:   br label %for.body
541
542for.body:                                         ; preds = %entry, %for.inc6
543  %i.018 = phi i32 [ 0, %entry ], [ %inc7, %for.inc6 ]
544  %mul = mul nuw nsw i32 %i.018, 20
545  br label %for.body3
546; CHECK: for.body:
547; CHECK:   %i.018 = phi i32 [ 0, %entry ], [ %inc7, %for.inc6 ]
548; CHECK:   %mul = mul nuw nsw i32 %i.018, 20
549; CHECK:   br label %for.body3
550
551for.body3:                                        ; preds = %for.body, %for.body3
552  %j.017 = phi i32 [ 0, %for.body ], [ %inc, %for.body3 ]
553  %add = add nuw nsw i32 %j.017, %mul
554  %arrayidx = getelementptr inbounds i16, i16* %A, i32 %add
555  %0 = load i16, i16* %arrayidx, align 2
556  %conv16 = zext i16 %0 to i32
557  %add4 = add i32 %conv16, %val
558  %conv5 = trunc i32 %add4 to i16
559  store i16 %conv5, i16* %arrayidx, align 2
560  %inc = add nuw nsw i32 %j.017, 1
561  %exitcond = icmp eq i32 %inc, 20
562  br i1 %exitcond, label %for.inc6, label %for.body3
563; CHECK: for.body3:
564; CHECK:   %j.017 = phi i32 [ 0, %for.body ]
565; CHECK:   %add = add nuw nsw i32 %j.017, %mul
566; CHECK:   %arrayidx = getelementptr inbounds i16, i16* %A, i32 %i.018
567; CHECK:   %0 = load i16, i16* %arrayidx, align 2
568; CHECK:   %conv16 = zext i16 %0 to i32
569; CHECK:   %add4 = add i32 %conv16, %val
570; CHECK:   %conv5 = trunc i32 %add4 to i16
571; CHECK:   store i16 %conv5, i16* %arrayidx, align 2
572; CHECK:   %inc = add nuw nsw i32 %j.017, 1
573; CHECK:   %exitcond = icmp eq i32 %inc, 20
574; CHECK:   br label %for.inc6
575
576for.inc6:                                         ; preds = %for.body3
577  %inc7 = add nuw nsw i32 %i.018, 1
578  %exitcond19 = icmp eq i32 %inc7, 10
579  br i1 %exitcond19, label %for.end8, label %for.body
580; CHECK: for.inc6:
581; CHECK:   %inc7 = add nuw nsw i32 %i.018, 1
582; CHECK:   %exitcond19 = icmp eq i32 %inc7, %flatten.tripcount
583; CHECK:   br i1 %exitcond19, label %for.end8, label %for.body
584
585for.end8:                                         ; preds = %for.inc6
586  ret i32 10
587}
588
589
590declare i32 @func(i32)
591
592