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. |
6 | void 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. |
29 | void 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. |
71 | void 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. |
115 | void 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. |
199 | void 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. |
242 | void 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. |
349 | void 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. |
439 | void 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. |
492 | void 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 | |