1; RUN: opt -loop-unroll-and-jam -allow-unroll-and-jam -unroll-runtime < %s -S | FileCheck %s
2; RUN: opt -loop-unroll-and-jam -allow-unroll-and-jam -unroll-runtime -unroll-and-jam-threshold=15 < %s -S | FileCheck %s --check-prefix=CHECK-LOWTHRES
3
4target datalayout = "e-m:e-p:32:32-i64:64-v128:64:128-a:0:32-n32-S64"
5
6; CHECK-LABEL: test1
7; Basic check that these loops are by default UnJ'd
8define void @test1(i32 %I, i32 %J, i32* noalias nocapture %A, i32* noalias nocapture readonly %B) {
9; CHECK: %i.us = phi i32 [ %add8.us.{{[1-9]*}}, %for.latch ], [ 0, %for.outer.preheader.new ]
10; CHECK-LOWTHRES: %i.us = phi i32 [ %add8.us, %for.latch ], [ 0, %for.outer.preheader ]
11entry:
12  %cmp = icmp ne i32 %J, 0
13  %cmp122 = icmp ne i32 %I, 0
14  %or.cond = and i1 %cmp, %cmp122
15  br i1 %or.cond, label %for.outer.preheader, label %for.end
16
17for.outer.preheader:
18  br label %for.outer
19
20for.outer:
21  %i.us = phi i32 [ %add8.us, %for.latch ], [ 0, %for.outer.preheader ]
22  br label %for.inner
23
24for.inner:
25  %j.us = phi i32 [ 0, %for.outer ], [ %inc.us, %for.inner ]
26  %sum1.us = phi i32 [ 0, %for.outer ], [ %add.us, %for.inner ]
27  %arrayidx.us = getelementptr inbounds i32, i32* %B, i32 %j.us
28  %0 = load i32, i32* %arrayidx.us, align 4
29  %add.us = add i32 %0, %sum1.us
30  %inc.us = add nuw i32 %j.us, 1
31  %exitcond = icmp eq i32 %inc.us, %J
32  br i1 %exitcond, label %for.latch, label %for.inner
33
34for.latch:
35  %add.us.lcssa = phi i32 [ %add.us, %for.inner ]
36  %arrayidx6.us = getelementptr inbounds i32, i32* %A, i32 %i.us
37  store i32 %add.us.lcssa, i32* %arrayidx6.us, align 4
38  %add8.us = add nuw i32 %i.us, 1
39  %exitcond25 = icmp eq i32 %add8.us, %I
40  br i1 %exitcond25, label %for.end.loopexit, label %for.outer
41
42for.end.loopexit:
43  br label %for.end
44
45for.end:
46  ret void
47}
48
49
50; CHECK-LABEL: nounroll_and_jam
51; #pragma nounroll_and_jam
52define void @nounroll_and_jam(i32 %I, i32 %J, i32* noalias nocapture %A, i32* noalias nocapture readonly %B) {
53; CHECK: %i.us = phi i32 [ %add8.us, %for.latch ], [ 0, %for.outer.preheader ]
54entry:
55  %cmp = icmp ne i32 %J, 0
56  %cmp122 = icmp ne i32 %I, 0
57  %or.cond = and i1 %cmp, %cmp122
58  br i1 %or.cond, label %for.outer.preheader, label %for.end
59
60for.outer.preheader:
61  br label %for.outer
62
63for.outer:
64  %i.us = phi i32 [ %add8.us, %for.latch ], [ 0, %for.outer.preheader ]
65  br label %for.inner
66
67for.inner:
68  %j.us = phi i32 [ 0, %for.outer ], [ %inc.us, %for.inner ]
69  %sum1.us = phi i32 [ 0, %for.outer ], [ %add.us, %for.inner ]
70  %arrayidx.us = getelementptr inbounds i32, i32* %B, i32 %j.us
71  %0 = load i32, i32* %arrayidx.us, align 4
72  %add.us = add i32 %0, %sum1.us
73  %inc.us = add nuw i32 %j.us, 1
74  %exitcond = icmp eq i32 %inc.us, %J
75  br i1 %exitcond, label %for.latch, label %for.inner
76
77for.latch:
78  %add.us.lcssa = phi i32 [ %add.us, %for.inner ]
79  %arrayidx6.us = getelementptr inbounds i32, i32* %A, i32 %i.us
80  store i32 %add.us.lcssa, i32* %arrayidx6.us, align 4
81  %add8.us = add nuw i32 %i.us, 1
82  %exitcond25 = icmp eq i32 %add8.us, %I
83  br i1 %exitcond25, label %for.end.loopexit, label %for.outer, !llvm.loop !1
84
85for.end.loopexit:
86  br label %for.end
87
88for.end:
89  ret void
90}
91
92
93; CHECK-LABEL: unroll_and_jam_count
94; #pragma unroll_and_jam(8)
95define void @unroll_and_jam_count(i32 %I, i32 %J, i32* noalias nocapture %A, i32* noalias nocapture readonly %B) {
96; CHECK: %i.us = phi i32 [ %add8.us.7, %for.latch ], [ 0, %for.outer.preheader.new ]
97entry:
98  %cmp = icmp ne i32 %J, 0
99  %cmp122 = icmp ne i32 %I, 0
100  %or.cond = and i1 %cmp, %cmp122
101  br i1 %or.cond, label %for.outer.preheader, label %for.end
102
103for.outer.preheader:
104  br label %for.outer
105
106for.outer:
107  %i.us = phi i32 [ %add8.us, %for.latch ], [ 0, %for.outer.preheader ]
108  br label %for.inner
109
110for.inner:
111  %j.us = phi i32 [ 0, %for.outer ], [ %inc.us, %for.inner ]
112  %sum1.us = phi i32 [ 0, %for.outer ], [ %add.us, %for.inner ]
113  %arrayidx.us = getelementptr inbounds i32, i32* %B, i32 %j.us
114  %0 = load i32, i32* %arrayidx.us, align 4
115  %add.us = add i32 %0, %sum1.us
116  %inc.us = add nuw i32 %j.us, 1
117  %exitcond = icmp eq i32 %inc.us, %J
118  br i1 %exitcond, label %for.latch, label %for.inner
119
120for.latch:
121  %add.us.lcssa = phi i32 [ %add.us, %for.inner ]
122  %arrayidx6.us = getelementptr inbounds i32, i32* %A, i32 %i.us
123  store i32 %add.us.lcssa, i32* %arrayidx6.us, align 4
124  %add8.us = add nuw i32 %i.us, 1
125  %exitcond25 = icmp eq i32 %add8.us, %I
126  br i1 %exitcond25, label %for.end.loopexit, label %for.outer, !llvm.loop !3
127
128for.end.loopexit:
129  br label %for.end
130
131for.end:
132  ret void
133}
134
135
136; CHECK-LABEL: unroll_and_jam
137; #pragma unroll_and_jam
138define void @unroll_and_jam(i32 %I, i32 %J, i32* noalias nocapture %A, i32* noalias nocapture readonly %B) {
139; CHECK: %i.us = phi i32 [ %add8.us.{{[1-9]*}}, %for.latch ], [ 0, %for.outer.preheader.new ]
140; CHECK-LOWTHRES: %i.us = phi i32 [ %add8.us.{{[1-9]*}}, %for.latch ], [ 0, %for.outer.preheader.new ]
141entry:
142  %cmp = icmp ne i32 %J, 0
143  %cmp122 = icmp ne i32 %I, 0
144  %or.cond = and i1 %cmp, %cmp122
145  br i1 %or.cond, label %for.outer.preheader, label %for.end
146
147for.outer.preheader:
148  br label %for.outer
149
150for.outer:
151  %i.us = phi i32 [ %add8.us, %for.latch ], [ 0, %for.outer.preheader ]
152  br label %for.inner
153
154for.inner:
155  %j.us = phi i32 [ 0, %for.outer ], [ %inc.us, %for.inner ]
156  %sum1.us = phi i32 [ 0, %for.outer ], [ %add.us, %for.inner ]
157  %arrayidx.us = getelementptr inbounds i32, i32* %B, i32 %j.us
158  %0 = load i32, i32* %arrayidx.us, align 4
159  %add.us = add i32 %0, %sum1.us
160  %inc.us = add nuw i32 %j.us, 1
161  %exitcond = icmp eq i32 %inc.us, %J
162  br i1 %exitcond, label %for.latch, label %for.inner
163
164for.latch:
165  %add.us.lcssa = phi i32 [ %add.us, %for.inner ]
166  %arrayidx6.us = getelementptr inbounds i32, i32* %A, i32 %i.us
167  store i32 %add.us.lcssa, i32* %arrayidx6.us, align 4
168  %add8.us = add nuw i32 %i.us, 1
169  %exitcond25 = icmp eq i32 %add8.us, %I
170  br i1 %exitcond25, label %for.end.loopexit, label %for.outer, !llvm.loop !5
171
172for.end.loopexit:
173  br label %for.end
174
175for.end:
176  ret void
177}
178
179
180; CHECK-LABEL: nounroll
181; #pragma nounroll (which we take to mean disable unroll and jam too)
182define void @nounroll(i32 %I, i32 %J, i32* noalias nocapture %A, i32* noalias nocapture readonly %B) {
183; CHECK: %i.us = phi i32 [ %add8.us, %for.latch ], [ 0, %for.outer.preheader ]
184entry:
185  %cmp = icmp ne i32 %J, 0
186  %cmp122 = icmp ne i32 %I, 0
187  %or.cond = and i1 %cmp, %cmp122
188  br i1 %or.cond, label %for.outer.preheader, label %for.end
189
190for.outer.preheader:
191  br label %for.outer
192
193for.outer:
194  %i.us = phi i32 [ %add8.us, %for.latch ], [ 0, %for.outer.preheader ]
195  br label %for.inner
196
197for.inner:
198  %j.us = phi i32 [ 0, %for.outer ], [ %inc.us, %for.inner ]
199  %sum1.us = phi i32 [ 0, %for.outer ], [ %add.us, %for.inner ]
200  %arrayidx.us = getelementptr inbounds i32, i32* %B, i32 %j.us
201  %0 = load i32, i32* %arrayidx.us, align 4
202  %add.us = add i32 %0, %sum1.us
203  %inc.us = add nuw i32 %j.us, 1
204  %exitcond = icmp eq i32 %inc.us, %J
205  br i1 %exitcond, label %for.latch, label %for.inner
206
207for.latch:
208  %add.us.lcssa = phi i32 [ %add.us, %for.inner ]
209  %arrayidx6.us = getelementptr inbounds i32, i32* %A, i32 %i.us
210  store i32 %add.us.lcssa, i32* %arrayidx6.us, align 4
211  %add8.us = add nuw i32 %i.us, 1
212  %exitcond25 = icmp eq i32 %add8.us, %I
213  br i1 %exitcond25, label %for.end.loopexit, label %for.outer, !llvm.loop !7
214
215for.end.loopexit:
216  br label %for.end
217
218for.end:
219  ret void
220}
221
222
223; CHECK-LABEL: unroll
224; #pragma unroll (which we take to mean disable unroll and jam)
225define void @unroll(i32 %I, i32 %J, i32* noalias nocapture %A, i32* noalias nocapture readonly %B) {
226; CHECK: %i.us = phi i32 [ %add8.us, %for.latch ], [ 0, %for.outer.preheader ]
227entry:
228  %cmp = icmp ne i32 %J, 0
229  %cmp122 = icmp ne i32 %I, 0
230  %or.cond = and i1 %cmp, %cmp122
231  br i1 %or.cond, label %for.outer.preheader, label %for.end
232
233for.outer.preheader:
234  br label %for.outer
235
236for.outer:
237  %i.us = phi i32 [ %add8.us, %for.latch ], [ 0, %for.outer.preheader ]
238  br label %for.inner
239
240for.inner:
241  %j.us = phi i32 [ 0, %for.outer ], [ %inc.us, %for.inner ]
242  %sum1.us = phi i32 [ 0, %for.outer ], [ %add.us, %for.inner ]
243  %arrayidx.us = getelementptr inbounds i32, i32* %B, i32 %j.us
244  %0 = load i32, i32* %arrayidx.us, align 4
245  %add.us = add i32 %0, %sum1.us
246  %inc.us = add nuw i32 %j.us, 1
247  %exitcond = icmp eq i32 %inc.us, %J
248  br i1 %exitcond, label %for.latch, label %for.inner
249
250for.latch:
251  %add.us.lcssa = phi i32 [ %add.us, %for.inner ]
252  %arrayidx6.us = getelementptr inbounds i32, i32* %A, i32 %i.us
253  store i32 %add.us.lcssa, i32* %arrayidx6.us, align 4
254  %add8.us = add nuw i32 %i.us, 1
255  %exitcond25 = icmp eq i32 %add8.us, %I
256  br i1 %exitcond25, label %for.end.loopexit, label %for.outer, !llvm.loop !9
257
258for.end.loopexit:
259  br label %for.end
260
261for.end:
262  ret void
263}
264
265
266; CHECK-LABEL: nounroll_plus_unroll_and_jam
267; #pragma clang loop nounroll, unroll_and_jam (which we take to mean do unroll_and_jam)
268define void @nounroll_plus_unroll_and_jam(i32 %I, i32 %J, i32* noalias nocapture %A, i32* noalias nocapture readonly %B) {
269; CHECK: %i.us = phi i32 [ %add8.us.{{[1-9]*}}, %for.latch ], [ 0, %for.outer.preheader.new ]
270entry:
271  %cmp = icmp ne i32 %J, 0
272  %cmp122 = icmp ne i32 %I, 0
273  %or.cond = and i1 %cmp, %cmp122
274  br i1 %or.cond, label %for.outer.preheader, label %for.end
275
276for.outer.preheader:
277  br label %for.outer
278
279for.outer:
280  %i.us = phi i32 [ %add8.us, %for.latch ], [ 0, %for.outer.preheader ]
281  br label %for.inner
282
283for.inner:
284  %j.us = phi i32 [ 0, %for.outer ], [ %inc.us, %for.inner ]
285  %sum1.us = phi i32 [ 0, %for.outer ], [ %add.us, %for.inner ]
286  %arrayidx.us = getelementptr inbounds i32, i32* %B, i32 %j.us
287  %0 = load i32, i32* %arrayidx.us, align 4
288  %add.us = add i32 %0, %sum1.us
289  %inc.us = add nuw i32 %j.us, 1
290  %exitcond = icmp eq i32 %inc.us, %J
291  br i1 %exitcond, label %for.latch, label %for.inner
292
293for.latch:
294  %add.us.lcssa = phi i32 [ %add.us, %for.inner ]
295  %arrayidx6.us = getelementptr inbounds i32, i32* %A, i32 %i.us
296  store i32 %add.us.lcssa, i32* %arrayidx6.us, align 4
297  %add8.us = add nuw i32 %i.us, 1
298  %exitcond25 = icmp eq i32 %add8.us, %I
299  br i1 %exitcond25, label %for.end.loopexit, label %for.outer, !llvm.loop !11
300
301for.end.loopexit:
302  br label %for.end
303
304for.end:
305  ret void
306}
307
308
309!1 = distinct !{!1, !2}
310!2 = distinct !{!"llvm.loop.unroll_and_jam.disable"}
311!3 = distinct !{!3, !4}
312!4 = distinct !{!"llvm.loop.unroll_and_jam.count", i32 8}
313!5 = distinct !{!5, !6}
314!6 = distinct !{!"llvm.loop.unroll_and_jam.enable"}
315!7 = distinct !{!7, !8}
316!8 = distinct !{!"llvm.loop.unroll.disable"}
317!9 = distinct !{!9, !10}
318!10 = distinct !{!"llvm.loop.unroll.enable"}
319!11 = distinct !{!11, !8, !6}
320