1; RUN: opt -loop-unroll -S %s -verify-loop-info -verify-dom-info -verify-loop-lcssa | FileCheck %s
2
3%struct.spam = type { double, double, double, double, double, double, double }
4
5define void @test2(i32* %arg)  {
6; CHECK-LABEL: void @test2
7; CHECK-NEXT: entry:
8; CHECK-NEXT:   br label %for.header
9
10; CHECK-LABEL: for.header:                                       ; preds = %entry
11; CHECK-NEXT:    store i32 0, i32* %arg, align 4
12; CHECK-NEXT:    br label %for.latch
13
14; CHECK-LABEL: for.latch:                                        ; preds = %for.header
15; CHECK-NEXT:    %ptr.1 = getelementptr inbounds i32, i32* %arg, i64 1
16; CHECK-NEXT:    store i32 0, i32* %ptr.1, align 4
17; CHECK-NEXT:    br label %for.latch.1
18
19; CHECK-LABEL: if.end.loopexit:                                  ; preds = %for.latch.2
20; CHECK-NEXT:    ret void
21
22; CHECK-LABEL: for.latch.1:                                      ; preds = %for.latch
23; CHECK-NEXT:    %ptr.2 = getelementptr inbounds i32, i32* %arg, i64 2
24; CHECK-NEXT:    store i32 0, i32* %ptr.2, align 4
25; CHECK-NEXT:    br label %for.latch.2
26
27; CHECK-LABEL: for.latch.2:                                      ; preds = %for.latch.1
28; CHECK-NEXT:    %ptr.3 = getelementptr inbounds i32, i32* %arg, i64 3
29; CHECK-NEXT:    store i32 0, i32* %ptr.3, align 4
30; CHECK-NEXT:    br i1 true, label %if.end.loopexit, label %for.latch.3
31
32; CHECK-LABEL: for.latch.3:                                      ; preds = %for.latch.2
33; CHECK-NEXT:    unreachable
34
35entry:
36  br label %for.header
37
38for.header:                              ; preds = %for.latch, %entry
39  %indvars.iv800 = phi i64 [ 0, %entry ], [ %indvars.iv.next801, %for.latch ]
40  %ptr = getelementptr inbounds i32, i32* %arg, i64 %indvars.iv800
41  store i32 0, i32* %ptr, align 4
42  %indvars.iv.next801 = add nuw nsw i64 %indvars.iv800, 1
43  %exitcond802 = icmp eq i64 %indvars.iv.next801, 4
44  br i1 %exitcond802, label %if.end.loopexit, label %for.latch
45
46for.latch: ; preds = %for.header
47  br label %for.header
48
49if.end.loopexit:                                  ; preds = %for.header
50  ret void
51}
52
53define double @test_with_lcssa(double %arg1, double* %arg2) {
54; CHECK-LABEL: define double @test_with_lcssa(
55; CHECK-LABEL: entry:
56; CHECK-NEXT:    br label %loop.header
57
58; CHECK-LABEL: loop.header:                                      ; preds = %entry
59; CHECK-NEXT:    %res = fsub double %arg1, 3.000000e+00
60; CHECK-NEXT:    br label %loop.latch
61
62; CHECK-LABEL: loop.latch:                                       ; preds = %loop.header
63; CHECK-NEXT:    %ptr = getelementptr inbounds double, double* %arg2, i64 1
64; CHECK-NEXT:    %lv = load double, double* %ptr, align 8
65; CHECK-NEXT:    %res.1 = fsub double %lv, %res
66; CHECK-NEXT:    br i1 true, label %loop.exit, label %loop.latch.1
67
68; CHECK-LABEL: loop.exit:                                        ; preds = %loop.latch
69; CHECK-NEXT:    %res.lcssa = phi double [ %res.1, %loop.latch ]
70; CHECK-NEXT:    ret double %res.lcssa
71
72; CHECK-LABEL: loop.latch.1:                                     ; preds = %loop.latch
73; CHECK-NEXT:    %ptr.1 = getelementptr inbounds double, double* %arg2, i64 2
74; CHECK-NEXT:    unreachable
75
76entry:
77  br label %loop.header
78
79loop.header:                                            ; preds = %entry, %loop.latch
80  %iv = phi i64 [ 0, %entry ], [ %iv.next, %loop.latch ]
81  %d1 = phi double [ %arg1, %entry ], [ %lv, %loop.latch ]
82  %d2 = phi double [ 3.0, %entry ], [ %res, %loop.latch ]
83  %res = fsub double %d1, %d2
84  %iv.next = add nuw nsw i64 %iv, 1
85  %cond = icmp eq i64 %iv.next, 2
86  br i1 %cond, label %loop.exit, label %loop.latch
87
88loop.latch:                                            ; preds = %bb366
89  %ptr = getelementptr inbounds double, double* %arg2, i64 %iv.next
90  %lv = load double, double* %ptr, align 8
91  br label %loop.header
92
93loop.exit:                                            ; preds = %bb366
94  %res.lcssa = phi double [ %res, %loop.header ]
95  ret double %res.lcssa
96}
97
98; We unroll the outer loop and need to preserve LI for the inner loop.
99define void @test_with_nested_loop(i32* %arg)  {
100; CHECK-LABEL: void @test_with_nested_loop
101; CHECK-LABEL: entry:
102; CHECK-NEXT:    br label %outer.header
103
104; CHECK-DAG: outer.header:                                     ; preds = %entry
105; CHECK-NEXT:    br label %inner.body.preheader
106
107; CHECK-DAG: inner.body.preheader:                             ; preds = %outer.header
108; CHECK-NEXT:    br label %inner.body
109
110; CHECK-LABEL: inner.body:                                       ; preds = %inner.body.preheader, %inner.body
111; CHECK-NEXT:    %j.iv = phi i64 [ %j.iv.next, %inner.body ], [ 0, %inner.body.preheader ]
112; CHECK-NEXT:    %ptr = getelementptr inbounds i32, i32* %arg, i64 %j.iv
113; CHECK-NEXT:    store i32 0, i32* %ptr, align 4
114; CHECK-NEXT:    %j.iv.next = add nuw nsw i64 %j.iv, 1
115; CHECK-NEXT:    %inner.cond = icmp eq i64 %j.iv.next, 40000
116; CHECK-NEXT:    br i1 %inner.cond, label %outer.latch, label %inner.body
117
118; CHECK-LABEL: outer.latch:                                      ; preds = %inner.body
119; CHECK-NEXT:    br label %inner.body.preheader.1
120
121; CHECK-LABEL: exit:                                             ; preds = %outer.latch.1
122; CHECK-NEXT:    ret void
123
124; CHECK-LABEL: inner.body.preheader.1:                           ; preds = %outer.latch
125; CHECK-NEXT:    br label %inner.body.1
126
127; CHECK-LABEL: inner.body.1:                                     ; preds = %inner.body.1, %inner.body.preheader.1
128; CHECK-NEXT:    %j.iv.1 = phi i64 [ %j.iv.next.1, %inner.body.1 ], [ 0, %inner.body.preheader.1 ]
129; CHECK-NEXT:    %idx.1 = add i64 1, %j.iv.1
130; CHECK-NEXT:    %ptr.1 = getelementptr inbounds i32, i32* %arg, i64 %idx.1
131; CHECK-NEXT:    store i32 0, i32* %ptr.1, align 4
132; CHECK-NEXT:    %j.iv.next.1 = add nuw nsw i64 %j.iv.1, 1
133; CHECK-NEXT:    %inner.cond.1 = icmp eq i64 %j.iv.next.1, 40000
134; CHECK-NEXT:    br i1 %inner.cond.1, label %outer.latch.1, label %inner.body.1
135
136; CHECK-LABEL: outer.latch.1:                                    ; preds = %inner.body.1
137; CHECK-NEXT:    br i1 true, label %exit, label %inner.body.preheader.2
138
139; CHECK-LABEL: inner.body.preheader.2:                           ; preds = %outer.latch.1
140; CHECK-NEXT:    br label %inner.body.2
141
142; CHECK-LABEL: inner.body.2:                                     ; preds = %inner.body.2, %inner.body.preheader.2
143; CHECK-NEXT:    %j.iv.2 = phi i64 [ %j.iv.next.2, %inner.body.2 ], [ 0, %inner.body.preheader.2 ]
144; CHECK-NEXT:    %idx.2 = add i64 2, %j.iv.2
145; CHECK-NEXT:    %ptr.2 = getelementptr inbounds i32, i32* %arg, i64 %idx.2
146; CHECK-NEXT:    store i32 0, i32* %ptr.2, align 4
147; CHECK-NEXT:    %j.iv.next.2 = add nuw nsw i64 %j.iv.2, 1
148; CHECK-NEXT:    %inner.cond.2 = icmp eq i64 %j.iv.next.2, 40000
149; CHECK-NEXT:    br i1 %inner.cond.2, label %outer.latch.2, label %inner.body.2
150
151; CHECK-LABEL: outer.latch.2:                                    ; preds = %inner.body.2
152; CHECK-NEXT:    unreachable
153;
154entry:
155  br label %outer.header
156
157outer.header:                              ; preds = %outer.latch, %entry
158  %outer.iv = phi i64 [ 0, %entry ], [ %outer.iv.next, %outer.latch ]
159  %outer.iv.next = add nuw nsw i64 %outer.iv, 1
160  %outer.cond = icmp eq i64 %outer.iv, 2
161  br i1 %outer.cond, label %exit, label %inner.body
162
163inner.body:
164  %j.iv = phi i64 [ 0, %outer.header ], [ %j.iv.next, %inner.body ]
165  %idx = add i64 %outer.iv, %j.iv
166  %ptr = getelementptr inbounds i32, i32* %arg, i64 %idx
167  store i32 0, i32* %ptr, align 4
168  %j.iv.next = add nuw nsw i64 %j.iv, 1
169  %inner.cond = icmp eq i64 %j.iv.next, 40000
170  br i1 %inner.cond, label %outer.latch, label %inner.body
171
172outer.latch: ; preds = %inner.body
173  br label %outer.header
174
175exit:                                  ; preds = %outer.header
176  ret void
177}
178
179; We unroll the inner loop and need to preserve LI for the outer loop.
180define void @test_with_nested_loop_unroll_inner(i32* %arg)  {
181; CHECK-LABEL: define void @test_with_nested_loop_unroll_inner(
182; CHECK-LABEL: entry:
183; CHECK-NEXT:   br label %outer.header
184
185; CHECK-LABEL: outer.header:                                     ; preds = %inner.body, %entry
186; CHECK-NEXT:   %outer.iv = phi i64 [ 0, %entry ], [ %outer.iv.next, %inner.body ]
187; CHECK-NEXT:   %outer.iv.next = add nuw nsw i64 %outer.iv, 1
188; CHECK-NEXT:   %outer.cond = icmp eq i64 %outer.iv, 40000
189; CHECK-NEXT:   br i1 %outer.cond, label %exit, label %inner.body.preheader
190
191; CHECK-LABEL: inner.body.preheader:                             ; preds = %outer.header
192; CHECK-NEXT:   br label %inner.body
193
194; CHECK-LABEL: inner.body:                                       ; preds = %inner.body.preheader
195; CHECK-NEXT:   %ptr = getelementptr inbounds i32, i32* %arg, i64 %outer.iv
196; CHECK-NEXT:   store i32 0, i32* %ptr, align 4
197; CHECK-NEXT:   %idx.1 = add i64 %outer.iv, 1
198; CHECK-NEXT:   %ptr.1 = getelementptr inbounds i32, i32* %arg, i64 %idx.1
199; CHECK-NEXT:   store i32 0, i32* %ptr.1, align 4
200; CHECK-NEXT:   br label %outer.header
201
202; CHECK-LABEL: exit:                                             ; preds = %outer.header
203; CHECK-NEXT:  ret void
204;
205entry:
206  br label %outer.header
207
208outer.header:                              ; preds = %outer.latch, %entry
209  %outer.iv = phi i64 [ 0, %entry ], [ %outer.iv.next, %outer.latch ]
210  %outer.iv.next = add nuw nsw i64 %outer.iv, 1
211  %outer.cond = icmp eq i64 %outer.iv, 40000
212  br i1 %outer.cond, label %exit, label %inner.body
213
214inner.body:
215  %j.iv = phi i64 [ 0, %outer.header ], [ %j.iv.next, %inner.body ]
216  %idx = add i64 %outer.iv, %j.iv
217  %ptr = getelementptr inbounds i32, i32* %arg, i64 %idx
218  store i32 0, i32* %ptr, align 4
219  %j.iv.next = add nuw nsw i64 %j.iv, 1
220  %inner.cond = icmp eq i64 %j.iv.next, 2
221  br i1 %inner.cond, label %outer.latch, label %inner.body
222
223outer.latch: ; preds = %inner.body
224  br label %outer.header
225
226exit:                                  ; preds = %outer.header
227  ret void
228}
229
230
231
232; Check that we do not crash for headers with non-branch instructions, e.g.
233; switch. We do not unroll in those cases.
234define void @test_switchinst_in_header() {
235; CHECK-LABEL: define void @test_switchinst_in_header() {
236; CHECK-LABEL: entry:
237; CHECK-NEXT:    br label %while.header
238
239; CHECK-LABEL: while.header:                                     ; preds = %while.latch, %entry
240; CHECK-NEXT:    switch i32 undef, label %exit [
241; CHECK-NEXT:      i32 11, label %while.body1
242; CHECK-NEXT:      i32 5, label %while.body2
243; CHECK-NEXT:    ]
244
245; CHECK-LABEL: while.body1:                                      ; preds = %while.header
246; CHECK-NEXT:    unreachable
247
248; CHECK-LABEL: while.body2:                                      ; preds = %while.header
249; CHECK-NEXT:    br label %while.latch
250
251; CHECK-LABEL: while.latch:                                      ; preds = %while.body2
252; CHECK-NEXT:    br label %while.header
253
254; CHECK-LABEL: exit:                                             ; preds = %while.header
255; CHECK-NEXT:    ret void
256;
257entry:
258  br label %while.header
259
260while.header:                               ; preds = %while.latch, %entry
261  switch i32 undef, label %exit [
262    i32 11, label %while.body1
263    i32 5, label %while.body2
264  ]
265
266while.body1:                                ; preds = %while.header
267  unreachable
268
269while.body2:                                ; preds = %while.header
270  br label %while.latch
271
272while.latch:   								; preds = %while.body2
273  br label %while.header
274
275exit:                        			    ; preds = %while.header
276  ret void
277}
278