1; RUN: opt -S -loop-fusion < %s | FileCheck %s
2
3@B = common global [1024 x i32] zeroinitializer, align 16
4
5; CHECK: void @dep_free
6; CHECK-NEXT: bb:
7; CHECK-NEXT: br label %[[LOOP1HEADER:bb[0-9]*]]
8; CHECK: [[LOOP1HEADER]]
9; CHECK: br i1 %{{.*}}, label %[[LOOP1BODY:bb[0-9]*]], label %[[LOOP2PREHEADER:bb[0-9]+]]
10; CHECK: [[LOOP1BODY]]
11; CHECK: br label %[[LOOP1LATCH:bb[0-9]*]]
12; CHECK: [[LOOP1LATCH]]
13; CHECK: br label %[[LOOP2PREHEADER:bb[0-9]+]]
14; CHECK: [[LOOP2PREHEADER]]
15; CHECK: br i1 %{{.*}}, label %[[LOOP2BODY:bb[0-9]*]], label %[[LOOP2EXIT:bb[0-9]*]]
16; CHECK: [[LOOP2BODY]]
17; CHECK: br label %[[LOOP2LATCH:bb[0-9]+]]
18; CHECK: [[LOOP2LATCH]]
19; CHECK: br label %[[LOOP1HEADER]]
20; CHECK: ret void
21define void @dep_free(i32* noalias %arg) {
22bb:
23  br label %bb5
24
25bb5:                                              ; preds = %bb14, %bb
26  %indvars.iv2 = phi i64 [ %indvars.iv.next3, %bb14 ], [ 0, %bb ]
27  %.01 = phi i32 [ 0, %bb ], [ %tmp15, %bb14 ]
28  %exitcond4 = icmp ne i64 %indvars.iv2, 100
29  br i1 %exitcond4, label %bb7, label %bb17
30
31bb7:                                              ; preds = %bb5
32  %tmp = add nsw i32 %.01, -3
33  %tmp8 = add nuw nsw i64 %indvars.iv2, 3
34  %tmp9 = trunc i64 %tmp8 to i32
35  %tmp10 = mul nsw i32 %tmp, %tmp9
36  %tmp11 = trunc i64 %indvars.iv2 to i32
37  %tmp12 = srem i32 %tmp10, %tmp11
38  %tmp13 = getelementptr inbounds i32, i32* %arg, i64 %indvars.iv2
39  store i32 %tmp12, i32* %tmp13, align 4
40  br label %bb14
41
42bb14:                                             ; preds = %bb7
43  %indvars.iv.next3 = add nuw nsw i64 %indvars.iv2, 1
44  %tmp15 = add nuw nsw i32 %.01, 1
45  br label %bb5
46
47bb17:                                             ; preds = %bb27, %bb5
48  %indvars.iv = phi i64 [ %indvars.iv.next, %bb27 ], [ 0, %bb5 ]
49  %.0 = phi i32 [ 0, %bb5 ], [ %tmp28, %bb27 ]
50  %exitcond = icmp ne i64 %indvars.iv, 100
51  br i1 %exitcond, label %bb19, label %bb18
52
53bb18:                                             ; preds = %bb17
54  br label %bb29
55
56bb19:                                             ; preds = %bb17
57  %tmp20 = add nsw i32 %.0, -3
58  %tmp21 = add nuw nsw i64 %indvars.iv, 3
59  %tmp22 = trunc i64 %tmp21 to i32
60  %tmp23 = mul nsw i32 %tmp20, %tmp22
61  %tmp24 = trunc i64 %indvars.iv to i32
62  %tmp25 = srem i32 %tmp23, %tmp24
63  %tmp26 = getelementptr inbounds [1024 x i32], [1024 x i32]* @B, i64 0, i64 %indvars.iv
64  store i32 %tmp25, i32* %tmp26, align 4
65  br label %bb27
66
67bb27:                                             ; preds = %bb19
68  %indvars.iv.next = add nuw nsw i64 %indvars.iv, 1
69  %tmp28 = add nuw nsw i32 %.0, 1
70  br label %bb17
71
72bb29:                                             ; preds = %bb18
73  ret void
74}
75
76; CHECK: void @dep_free_parametric
77; CHECK-NEXT: bb:
78; CHECK-NEXT: br label %[[LOOP1HEADER:bb[0-9]*]]
79; CHECK: [[LOOP1HEADER]]
80; CHECK: br i1 %{{.*}}, label %[[LOOP1BODY:bb[0-9]*]], label %[[LOOP2PREHEADER:bb[0-9]+]]
81; CHECK: [[LOOP1BODY]]
82; CHECK: br label %[[LOOP1LATCH:bb[0-9]*]]
83; CHECK: [[LOOP1LATCH]]
84; CHECK: br label %[[LOOP2PREHEADER:bb[0-9]+]]
85; CHECK: [[LOOP2PREHEADER]]
86; CHECK: br i1 %{{.*}}, label %[[LOOP2BODY:bb[0-9]*]], label %[[LOOP2EXIT:bb[0-9]*]]
87; CHECK: [[LOOP2BODY]]
88; CHECK: br label %[[LOOP2LATCH:bb[0-9]+]]
89; CHECK: [[LOOP2LATCH]]
90; CHECK: br label %[[LOOP1HEADER]]
91; CHECK: ret void
92define void @dep_free_parametric(i32* noalias %arg, i64 %arg2) {
93bb:
94  br label %bb3
95
96bb3:                                              ; preds = %bb12, %bb
97  %.01 = phi i64 [ 0, %bb ], [ %tmp13, %bb12 ]
98  %tmp = icmp slt i64 %.01, %arg2
99  br i1 %tmp, label %bb5, label %bb15
100
101bb5:                                              ; preds = %bb3
102  %tmp6 = add nsw i64 %.01, -3
103  %tmp7 = add nuw nsw i64 %.01, 3
104  %tmp8 = mul nsw i64 %tmp6, %tmp7
105  %tmp9 = srem i64 %tmp8, %.01
106  %tmp10 = trunc i64 %tmp9 to i32
107  %tmp11 = getelementptr inbounds i32, i32* %arg, i64 %.01
108  store i32 %tmp10, i32* %tmp11, align 4
109  br label %bb12
110
111bb12:                                             ; preds = %bb5
112  %tmp13 = add nuw nsw i64 %.01, 1
113  br label %bb3
114
115bb15:                                             ; preds = %bb25, %bb3
116  %.0 = phi i64 [ 0, %bb3 ], [ %tmp26, %bb25 ]
117  %tmp16 = icmp slt i64 %.0, %arg2
118  br i1 %tmp16, label %bb18, label %bb17
119
120bb17:                                             ; preds = %bb15
121  br label %bb27
122
123bb18:                                             ; preds = %bb15
124  %tmp19 = add nsw i64 %.0, -3
125  %tmp20 = add nuw nsw i64 %.0, 3
126  %tmp21 = mul nsw i64 %tmp19, %tmp20
127  %tmp22 = srem i64 %tmp21, %.0
128  %tmp23 = trunc i64 %tmp22 to i32
129  %tmp24 = getelementptr inbounds [1024 x i32], [1024 x i32]* @B, i64 0, i64 %.0
130  store i32 %tmp23, i32* %tmp24, align 4
131  br label %bb25
132
133bb25:                                             ; preds = %bb18
134  %tmp26 = add nuw nsw i64 %.0, 1
135  br label %bb15
136
137bb27:                                             ; preds = %bb17
138  ret void
139}
140
141; CHECK: void @raw_only
142; CHECK-NEXT: bb:
143; CHECK-NEXT: br label %[[LOOP1HEADER:bb[0-9]*]]
144; CHECK: [[LOOP1HEADER]]
145; CHECK: br i1 %{{.*}}, label %[[LOOP1BODY:bb[0-9]*]], label %[[LOOP2PREHEADER:bb[0-9]+]]
146; CHECK: [[LOOP1BODY]]
147; CHECK: br label %[[LOOP1LATCH:bb[0-9]*]]
148; CHECK: [[LOOP1LATCH]]
149; CHECK: br label %[[LOOP2PREHEADER:bb[0-9]+]]
150; CHECK: [[LOOP2PREHEADER]]
151; CHECK: br i1 %{{.*}}, label %[[LOOP2BODY:bb[0-9]*]], label %[[LOOP2EXIT:bb[0-9]*]]
152; CHECK: [[LOOP2BODY]]
153; CHECK: br label %[[LOOP2LATCH:bb[0-9]+]]
154; CHECK: [[LOOP2LATCH]]
155; CHECK: br label %[[LOOP1HEADER]]
156; CHECK: ret void
157define void @raw_only(i32* noalias %arg) {
158bb:
159  br label %bb5
160
161bb5:                                              ; preds = %bb9, %bb
162  %indvars.iv2 = phi i64 [ %indvars.iv.next3, %bb9 ], [ 0, %bb ]
163  %exitcond4 = icmp ne i64 %indvars.iv2, 100
164  br i1 %exitcond4, label %bb7, label %bb11
165
166bb7:                                              ; preds = %bb5
167  %tmp = getelementptr inbounds i32, i32* %arg, i64 %indvars.iv2
168  %tmp8 = trunc i64 %indvars.iv2 to i32
169  store i32 %tmp8, i32* %tmp, align 4
170  br label %bb9
171
172bb9:                                              ; preds = %bb7
173  %indvars.iv.next3 = add nuw nsw i64 %indvars.iv2, 1
174  br label %bb5
175
176bb11:                                             ; preds = %bb18, %bb5
177  %indvars.iv = phi i64 [ %indvars.iv.next, %bb18 ], [ 0, %bb5 ]
178  %exitcond = icmp ne i64 %indvars.iv, 100
179  br i1 %exitcond, label %bb13, label %bb19
180
181bb13:                                             ; preds = %bb11
182  %tmp14 = getelementptr inbounds i32, i32* %arg, i64 %indvars.iv
183  %tmp15 = load i32, i32* %tmp14, align 4
184  %tmp16 = shl nsw i32 %tmp15, 1
185  %tmp17 = getelementptr inbounds [1024 x i32], [1024 x i32]* @B, i64 0, i64 %indvars.iv
186  store i32 %tmp16, i32* %tmp17, align 4
187  br label %bb18
188
189bb18:                                             ; preds = %bb13
190  %indvars.iv.next = add nuw nsw i64 %indvars.iv, 1
191  br label %bb11
192
193bb19:                                             ; preds = %bb11
194  ret void
195}
196
197; CHECK: void @raw_only_parametric
198; CHECK-NEXT: bb:
199; CHECK: br label %[[LOOP1HEADER:bb[0-9]*]]
200; CHECK: [[LOOP1HEADER]]
201; CHECK: br i1 %{{.*}}, label %[[LOOP1BODY:bb[0-9]*]], label %[[LOOP2PREHEADER:bb[0-9]+]]
202; CHECK: [[LOOP1BODY]]
203; CHECK: br label %[[LOOP1LATCH:bb[0-9]*]]
204; CHECK: [[LOOP1LATCH]]
205; CHECK: br label %[[LOOP2PREHEADER:bb[0-9]+]]
206; CHECK: [[LOOP2PREHEADER]]
207; CHECK: br i1 %{{.*}}, label %[[LOOP2BODY:bb[0-9]*]], label %[[LOOP2EXIT:bb[0-9]*]]
208; CHECK: [[LOOP2BODY]]
209; CHECK: br label %[[LOOP2LATCH:bb[0-9]+]]
210; CHECK: [[LOOP2LATCH]]
211; CHECK: br label %[[LOOP1HEADER]]
212; CHECK: ret void
213define void @raw_only_parametric(i32* noalias %arg, i32 %arg4) {
214bb:
215  br label %bb5
216
217bb5:                                              ; preds = %bb11, %bb
218  %indvars.iv2 = phi i64 [ %indvars.iv.next3, %bb11 ], [ 0, %bb ]
219  %tmp = sext i32 %arg4 to i64
220  %tmp6 = icmp slt i64 %indvars.iv2, %tmp
221  br i1 %tmp6, label %bb8, label %bb14
222
223bb8:                                              ; preds = %bb5
224  %tmp9 = getelementptr inbounds i32, i32* %arg, i64 %indvars.iv2
225  %tmp10 = trunc i64 %indvars.iv2 to i32
226  store i32 %tmp10, i32* %tmp9, align 4
227  br label %bb11
228
229bb11:                                             ; preds = %bb8
230  %indvars.iv.next3 = add nuw nsw i64 %indvars.iv2, 1
231  br label %bb5
232
233bb14:                                             ; preds = %bb22, %bb5
234  %indvars.iv = phi i64 [ %indvars.iv.next, %bb22 ], [ 0, %bb5 ]
235  %tmp13 = sext i32 %arg4 to i64
236  %tmp15 = icmp slt i64 %indvars.iv, %tmp13
237  br i1 %tmp15, label %bb17, label %bb23
238
239bb17:                                             ; preds = %bb14
240  %tmp18 = getelementptr inbounds i32, i32* %arg, i64 %indvars.iv
241  %tmp19 = load i32, i32* %tmp18, align 4
242  %tmp20 = shl nsw i32 %tmp19, 1
243  %tmp21 = getelementptr inbounds [1024 x i32], [1024 x i32]* @B, i64 0, i64 %indvars.iv
244  store i32 %tmp20, i32* %tmp21, align 4
245  br label %bb22
246
247bb22:                                             ; preds = %bb17
248  %indvars.iv.next = add nuw nsw i64 %indvars.iv, 1
249  br label %bb14
250
251bb23:                                             ; preds = %bb14
252  ret void
253}
254
255; CHECK: void @forward_dep
256; CHECK-NEXT: bb:
257; CHECK: br label %[[LOOP1HEADER:bb[0-9]*]]
258; CHECK: [[LOOP1HEADER]]
259; CHECK: br i1 %{{.*}}, label %[[LOOP1BODY:bb[0-9]*]], label %[[LOOP2PREHEADER:bb[0-9]+]]
260; CHECK: [[LOOP1BODY]]
261; CHECK: br label %[[LOOP1LATCH:bb[0-9]*]]
262; CHECK: [[LOOP1LATCH]]
263; CHECK: br label %[[LOOP2PREHEADER:bb[0-9]+]]
264; CHECK: [[LOOP2PREHEADER]]
265; CHECK: br i1 %{{.*}}, label %[[LOOP2BODY:bb[0-9]*]], label %[[LOOP2EXIT:bb[0-9]*]]
266; CHECK: [[LOOP2BODY]]
267; CHECK: br label %[[LOOP2LATCH:bb[0-9]+]]
268; CHECK: [[LOOP2LATCH]]
269; CHECK: br label %[[LOOP1HEADER]]
270; CHECK: ret void
271define void @forward_dep(i32* noalias %arg) {
272bb:
273  br label %bb5
274
275bb5:                                              ; preds = %bb14, %bb
276  %indvars.iv2 = phi i64 [ %indvars.iv.next3, %bb14 ], [ 0, %bb ]
277  %.01 = phi i32 [ 0, %bb ], [ %tmp15, %bb14 ]
278  %exitcond4 = icmp ne i64 %indvars.iv2, 100
279  br i1 %exitcond4, label %bb7, label %bb17
280
281bb7:                                              ; preds = %bb5
282  %tmp = add nsw i32 %.01, -3
283  %tmp8 = add nuw nsw i64 %indvars.iv2, 3
284  %tmp9 = trunc i64 %tmp8 to i32
285  %tmp10 = mul nsw i32 %tmp, %tmp9
286  %tmp11 = trunc i64 %indvars.iv2 to i32
287  %tmp12 = srem i32 %tmp10, %tmp11
288  %tmp13 = getelementptr inbounds i32, i32* %arg, i64 %indvars.iv2
289  store i32 %tmp12, i32* %tmp13, align 4
290  br label %bb14
291
292bb14:                                             ; preds = %bb7
293  %indvars.iv.next3 = add nuw nsw i64 %indvars.iv2, 1
294  %tmp15 = add nuw nsw i32 %.01, 1
295  br label %bb5
296
297bb17:                                             ; preds = %bb25, %bb5
298  %indvars.iv = phi i64 [ %indvars.iv.next, %bb25 ], [ 0, %bb5 ]
299  %exitcond = icmp ne i64 %indvars.iv, 100
300  br i1 %exitcond, label %bb19, label %bb26
301
302bb19:                                             ; preds = %bb17
303  %tmp20 = add nsw i64 %indvars.iv, -3
304  %tmp21 = getelementptr inbounds i32, i32* %arg, i64 %tmp20
305  %tmp22 = load i32, i32* %tmp21, align 4
306  %tmp23 = mul nsw i32 %tmp22, 3
307  %tmp24 = getelementptr inbounds i32, i32* %arg, i64 %indvars.iv
308  store i32 %tmp23, i32* %tmp24, align 4
309  br label %bb25
310
311bb25:                                             ; preds = %bb19
312  %indvars.iv.next = add nuw nsw i64 %indvars.iv, 1
313  br label %bb17
314
315bb26:                                             ; preds = %bb17
316  ret void
317}
318