1// RUN: %check_clang_tidy %s altera-unroll-loops %t -- -config="{CheckOptions: {altera-unroll-loops.MaxLoopIterations: 50}}" -header-filter=.*
2// RUN: %check_clang_tidy -check-suffix=MULT %s altera-unroll-loops %t -- -config="{CheckOptions: {altera-unroll-loops.MaxLoopIterations: 5}}" -header-filter=.* "--" -DMULT
3
4#ifdef MULT
5// For loops with *= and /= increments.
6void for_loop_mult_div_increments(int *A) {
7// *=
8#pragma unroll
9 for (int i = 2; i <= 32; i *= 2)
10 A[i]++; // OK
11
12#pragma unroll
13 for (int i = 2; i <= 64; i *= 2)
14 // CHECK-MESSAGES-MULT: :[[@LINE-1]]:3: warning: loop likely has a large number of iterations and thus cannot be fully unrolled; to partially unroll this loop, use the '#pragma unroll <num>' directive [altera-unroll-loops]
15 A[i]++; // Not OK
16
17// /=
18#pragma unroll
19 for (int i = 32; i >= 2; i /= 2)
20 A[i]++; // OK
21
22#pragma unroll
23 for (int i = 64; i >= 2; i /= 2)
24 // CHECK-MESSAGES-MULT: :[[@LINE-1]]:3: warning: loop likely has a large number of iterations and thus cannot be fully unrolled; to partially unroll this loop, use the '#pragma unroll <num>' directive [altera-unroll-loops]
25 A[i]++; // Not OK
26}
27#else
28// Cannot determine loop bounds for while loops.
29void while_loops(int *A) {
30 // Recommend unrolling loops that aren't already unrolled.
31 int j = 0;
32 while (j < 2000) {
33 // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: kernel performance could be improved by unrolling this loop with a '#pragma unroll' directive [altera-unroll-loops]
34 A[1] += j;
35 j++;
36 }
37
38 do {
39 // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: kernel performance could be improved by unrolling this loop with a '#pragma unroll' directive [altera-unroll-loops]
40 A[2] += j;
41 j++;
42 } while (j < 2000);
43
44// If a while loop is fully unrolled, add a note recommending partial
45// unrolling.
46#pragma unroll
47 while (j < 2000) {
48 // CHECK-MESSAGES: :[[@LINE-1]]:3: note: full unrolling requested, but loop bounds may not be known; to partially unroll this loop, use the '#pragma unroll <num>' directive
49 A[j]++;
50 }
51
52#pragma unroll
53 do {
54 // CHECK-MESSAGES: :[[@LINE-1]]:3: note: full unrolling requested, but loop bounds may not be known; to partially unroll this loop, use the '#pragma unroll <num>' directive
55 A[j]++;
56 } while (j < 2000);
57
58// While loop is partially unrolled, no action needed.
59#pragma unroll 4
60 while (j < 2000) {
61 A[j]++;
62 }
63
64#pragma unroll 4
65 do {
66 A[j]++;
67 } while (j < 2000);
68}
69
70// Range-based for loops.
71void cxx_for_loops(int *A, int vectorSize) {
72 // Loop with known array size should be unrolled.
73 int a[] = {0, 1, 2, 3, 4, 5};
74 for (int k : a) {
75 // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: kernel performance could be improved by unrolling this loop with a '#pragma unroll' directive [altera-unroll-loops]
76 A[k]++;
77 }
78
79// Loop with known size correctly unrolled.
80#pragma unroll
81 for (int k : a) {
82 A[k]++;
83 }
84
85 // Loop with unknown size should be partially unrolled.
86 int b[vectorSize];
87#pragma unroll
88 for (int k : b) {
89 // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: full unrolling requested, but loop bounds are not known; to partially unroll this loop, use the '#pragma unroll <num>' directive [altera-unroll-loops]
90 k++;
91 }
92
93// Loop with unknown size correctly unrolled.
94#pragma unroll 5
95 for (int k : b) {
96 k++;
97 }
98
99 // Loop with large size should be partially unrolled.
100 int c[51];
101#pragma unroll
102 for (int k : c) {
103 // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: loop likely has a large number of iterations and thus cannot be fully unrolled; to partially unroll this loop, use the '#pragma unroll <num>' directive [altera-unroll-loops]
104 A[k]++;
105 }
106
107// Loop with large size correctly unrolled.
108#pragma unroll 5
109 for (int k : c) {
110 A[k]++;
111 }
112}
113
114// Simple for loops.
115void for_loops(int *A, int size) {
116 // Recommend unrolling loops that aren't already unrolled.
117 for (int i = 0; i < 2000; ++i) {
118 // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: kernel performance could be improved by unrolling this loop with a '#pragma unroll' directive [altera-unroll-loops]
119 A[0] += i;
120 }
121
122// Loop with known size correctly unrolled.
123#pragma unroll
124 for (int i = 0; i < 50; ++i) {
125 A[i]++;
126 }
127
128// Loop with unknown size should be partially unrolled.
129#pragma unroll
130 for (int i = 0; i < size; ++i) {
131 // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: full unrolling requested, but loop bounds are not known; to partially unroll this loop, use the '#pragma unroll <num>' directive [altera-unroll-loops]
132 A[i]++;
133 }
134
135#pragma unroll
136 for (;;) {
137 // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: full unrolling requested, but loop bounds are not known; to partially unroll this loop, use the '#pragma unroll <num>' directive [altera-unroll-loops]
138 A[0]++;
139 }
140
141 int i = 0;
142#pragma unroll
143 for (; i < size; ++i) {
144 // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: full unrolling requested, but loop bounds are not known; to partially unroll this loop, use the '#pragma unroll <num>' directive [altera-unroll-loops]
145 A[i]++;
146 }
147
148#pragma unroll
149 for (int i = 0;; ++i) {
150 // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: full unrolling requested, but loop bounds are not known; to partially unroll this loop, use the '#pragma unroll <num>' directive [altera-unroll-loops]
151 A[i]++;
152 }
153
154#pragma unroll
155 for (int i = 0; i < size;) {
156 // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: full unrolling requested, but loop bounds are not known; to partially unroll this loop, use the '#pragma unroll <num>' directive [altera-unroll-loops]
157 A[i]++;
158 }
159
160#pragma unroll
161 for (int i = size; i < 50; ++i) {
162 // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: full unrolling requested, but loop bounds are not known; to partially unroll this loop, use the '#pragma unroll <num>' directive [altera-unroll-loops]
163 A[i]++;
164 }
165
166#pragma unroll
167 for (int i = 0; true; ++i) {
168 // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: full unrolling requested, but loop bounds are not known; to partially unroll this loop, use the '#pragma unroll <num>' directive [altera-unroll-loops]
169 A[i]++;
170 }
171
172#pragma unroll
173 for (int i = 0; i == i; ++i) {
174 // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: full unrolling requested, but loop bounds are not known; to partially unroll this loop, use the '#pragma unroll <num>' directive [altera-unroll-loops]
175 A[i]++;
176 }
177
178// Loop with unknown size correctly unrolled.
179#pragma unroll 5
180 for (int i = 0; i < size; ++i) {
181 A[i]++;
182 }
183
184// Loop with large size should be partially unrolled.
185#pragma unroll
186 for (int i = 0; i < 51; ++i) {
187 // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: loop likely has a large number of iterations and thus cannot be fully unrolled; to partially unroll this loop, use the '#pragma unroll <num>' directive [altera-unroll-loops]
188 A[i]++;
189 }
190
191// Loop with large size correctly unrolled.
192#pragma unroll 5
193 for (int i = 0; i < 51; ++i) {
194 A[i]++;
195 }
196}
197
198// For loops with different increments.
199void for_loop_increments(int *A) {
200// ++
201#pragma unroll
202 for (int i = 0; i < 50; ++i)
203 A[i]++; // OK
204
205#pragma unroll
206 for (int i = 0; i < 51; ++i)
207 // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: loop likely has a large number of iterations and thus cannot be fully unrolled; to partially unroll this loop, use the '#pragma unroll <num>' directive [altera-unroll-loops]
208 A[i]++; // Not OK
209
210// --
211#pragma unroll
212 for (int i = 50; i > 0; --i)
213 A[i]++; // OK
214
215#pragma unroll
216 for (int i = 51; i > 0; --i)
217 // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: loop likely has a large number of iterations and thus cannot be fully unrolled; to partially unroll this loop, use the '#pragma unroll <num>' directive [altera-unroll-loops]
218 A[i]++; // Not OK
219
220// +=
221#pragma unroll
222 for (int i = 0; i < 100; i += 2)
223 A[i]++; // OK
224
225#pragma unroll
226 for (int i = 0; i < 101; i += 2)
227 // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: loop likely has a large number of iterations and thus cannot be fully unrolled; to partially unroll this loop, use the '#pragma unroll <num>' directive [altera-unroll-loops]
228 A[i]++; // Not OK
229
230// -=
231#pragma unroll
232 for (int i = 100; i > 0; i -= 2)
233 A[i]++; // OK
234
235#pragma unroll
236 for (int i = 101; i > 0; i -= 2)
237 // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: loop likely has a large number of iterations and thus cannot be fully unrolled; to partially unroll this loop, use the '#pragma unroll <num>' directive [altera-unroll-loops]
238 A[i]++; // Not OK
239}
240
241// Inner loops should be unrolled.
242void nested_simple_loops(int *A) {
243 for (int i = 0; i < 1000; ++i) {
244 for (int j = 0; j < 2000; ++j) {
245 // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: kernel performance could be improved by unrolling this loop with a '#pragma unroll' directive [altera-unroll-loops]
246 A[0] += i + j;
247 }
248 }
249
250 for (int i = 0; i < 1000; ++i) {
251 int j = 0;
252 while (j < 2000) {
253 // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: kernel performance could be improved by unrolling this loop with a '#pragma unroll' directive [altera-unroll-loops]
254 A[1] += i + j;
255 j++;
256 }
257 }
258
259 for (int i = 0; i < 1000; ++i) {
260 int j = 0;
261 do {
262 // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: kernel performance could be improved by unrolling this loop with a '#pragma unroll' directive [altera-unroll-loops]
263 A[2] += i + j;
264 j++;
265 } while (j < 2000);
266 }
267
268 int i = 0;
269 while (i < 1000) {
270 for (int j = 0; j < 2000; ++j) {
271 // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: kernel performance could be improved by unrolling this loop with a '#pragma unroll' directive [altera-unroll-loops]
272 A[3] += i + j;
273 }
274 i++;
275 }
276
277 i = 0;
278 while (i < 1000) {
279 int j = 0;
280 while (j < 2000) {
281 // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: kernel performance could be improved by unrolling this loop with a '#pragma unroll' directive [altera-unroll-loops]
282 A[4] += i + j;
283 j++;
284 }
285 i++;
286 }
287
288 i = 0;
289 while (i < 1000) {
290 int j = 0;
291 do {
292 // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: kernel performance could be improved by unrolling this loop with a '#pragma unroll' directive [altera-unroll-loops]
293 A[5] += i + j;
294 j++;
295 } while (j < 2000);
296 i++;
297 }
298
299 i = 0;
300 do {
301 for (int j = 0; j < 2000; ++j) {
302 // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: kernel performance could be improved by unrolling this loop with a '#pragma unroll' directive [altera-unroll-loops]
303 A[6] += i + j;
304 }
305 i++;
306 } while (i < 1000);
307
308 i = 0;
309 do {
310 int j = 0;
311 while (j < 2000) {
312 // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: kernel performance could be improved by unrolling this loop with a '#pragma unroll' directive [altera-unroll-loops]
313 A[7] += i + j;
314 j++;
315 }
316 i++;
317 } while (i < 1000);
318
319 i = 0;
320 do {
321 int j = 0;
322 do {
323 // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: kernel performance could be improved by unrolling this loop with a '#pragma unroll' directive [altera-unroll-loops]
324 A[8] += i + j;
325 j++;
326 } while (j < 2000);
327 i++;
328 } while (i < 1000);
329
330 for (int i = 0; i < 100; ++i) {
331 // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: kernel performance could be improved by unrolling this loop with a '#pragma unroll' directive [altera-unroll-loops]
332 A[i]++;
333 }
334
335 i = 0;
336 while (i < 100) {
337 // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: kernel performance could be improved by unrolling this loop with a '#pragma unroll' directive [altera-unroll-loops]
338 i++;
339 }
340
341 i = 0;
342 do {
343 // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: kernel performance could be improved by unrolling this loop with a '#pragma unroll' directive [altera-unroll-loops]
344 i++;
345 } while (i < 100);
346}
347
348// These loops are all correctly unrolled.
349void unrolled_nested_simple_loops(int *A) {
350 for (int i = 0; i < 1000; ++i) {
351#pragma unroll
352 for (int j = 0; j < 50; ++j) {
353 A[0] += i + j;
354 }
355 }
356
357 for (int i = 0; i < 1000; ++i) {
358 int j = 0;
359#pragma unroll 5
360 while (j < 50) {
361 A[1] += i + j;
362 j++;
363 }
364 }
365
366 for (int i = 0; i < 1000; ++i) {
367 int j = 0;
368#pragma unroll 5
369 do {
370 A[2] += i + j;
371 j++;
372 } while (j < 50);
373 }
374
375 int i = 0;
376 while (i < 1000) {
377#pragma unroll
378 for (int j = 0; j < 50; ++j) {
379 A[3] += i + j;
380 }
381 i++;
382 }
383
384 i = 0;
385 while (i < 1000) {
386 int j = 0;
387#pragma unroll 5
388 while (50 > j) {
389 A[4] += i + j;
390 j++;
391 }
392 i++;
393 }
394
395 i = 0;
396 while (1000 > i) {
397 int j = 0;
398#pragma unroll 5
399 do {
400 A[5] += i + j;
401 j++;
402 } while (j < 50);
403 i++;
404 }
405
406 i = 0;
407 do {
408#pragma unroll
409 for (int j = 0; j < 50; ++j) {
410 A[6] += i + j;
411 }
412 i++;
413 } while (i < 1000);
414
415 i = 0;
416 do {
417 int j = 0;
418#pragma unroll 5
419 while (j < 50) {
420 A[7] += i + j;
421 j++;
422 }
423 i++;
424 } while (i < 1000);
425
426 i = 0;
427 do {
428 int j = 0;
429#pragma unroll 5
430 do {
431 A[8] += i + j;
432 j++;
433 } while (j < 50);
434 i++;
435 } while (i < 1000);
436}
437
438// These inner loops are large and should be partially unrolled.
439void unrolled_nested_simple_loops_large_num_iterations(int *A) {
440 for (int i = 0; i < 1000; ++i) {
441#pragma unroll
442 for (int j = 0; j < 51; ++j) {
443 // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: loop likely has a large number of iterations and thus cannot be fully unrolled; to partially unroll this loop, use the '#pragma unroll <num>' directive [altera-unroll-loops]
444 A[0] += i + j;
445 }
446 }
447
448 int i = 0;
449 while (i < 1000) {
450#pragma unroll
451 for (int j = 0; j < 51; ++j) {
452 // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: loop likely has a large number of iterations and thus cannot be fully unrolled; to partially unroll this loop, use the '#pragma unroll <num>' directive [altera-unroll-loops]
453 A[3] += i + j;
454 }
455 i++;
456 }
457
458 i = 0;
459 do {
460#pragma unroll
461 for (int j = 0; j < 51; ++j) {
462 // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: loop likely has a large number of iterations and thus cannot be fully unrolled; to partially unroll this loop, use the '#pragma unroll <num>' directive [altera-unroll-loops]
463 A[6] += i + j;
464 }
465 i++;
466 } while (i < 1000);
467
468 i = 0;
469 do {
470 int j = 0;
471#pragma unroll
472 do {
473 // CHECK-MESSAGES: :[[@LINE-1]]:5: note: full unrolling requested, but loop bounds may not be known; to partially unroll this loop, use the '#pragma unroll <num>' directive
474 A[8] += i + j;
475 j++;
476 } while (j < 51);
477 i++;
478 } while (i < 1000);
479
480 i = 0;
481 int a[51];
482 do {
483#pragma unroll
484 for (int k : a) {
485 // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: loop likely has a large number of iterations and thus cannot be fully unrolled; to partially unroll this loop, use the '#pragma unroll <num>' directive [altera-unroll-loops]
486 A[k]++;
487 }
488 } while (i < 1000);
489}
490
491// These loops have unknown bounds and should be partially unrolled.
492void fully_unrolled_unknown_bounds(int vectorSize) {
493 int someVector[101];
494
495// There is no loop condition
496#pragma unroll
497 for (;;) {
498 // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: full unrolling requested, but loop bounds are not known; to partially unroll this loop, use the '#pragma unroll <num>' directive [altera-unroll-loops]
499 someVector[0]++;
500 }
501
502#pragma unroll
503 for (int i = 0; 1 < 5; ++i) {
504 // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: full unrolling requested, but loop bounds are not known; to partially unroll this loop, use the '#pragma unroll <num>' directive [altera-unroll-loops]
505 someVector[i]++;
506 }
507
508// Both sides are value-dependent
509#pragma unroll
510 for (int i = 0; i < vectorSize; ++i) {
511 // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: full unrolling requested, but loop bounds are not known; to partially unroll this loop, use the '#pragma unroll <num>' directive [altera-unroll-loops]
512 someVector[i]++;
513 }
514}
515#endif
516// There are no fix-its for this check
517

source code of clang-tools-extra/test/clang-tidy/checkers/altera/unroll-loops.cpp