517 lines · cpp
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=.* "--" -DMULT3 4#ifdef MULT5// For loops with *= and /= increments.6void for_loop_mult_div_increments(int *A) {7// *=8#pragma unroll9 for (int i = 2; i <= 32; i *= 2)10 A[i]++; // OK11 12#pragma unroll13 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 OK16 17// /=18#pragma unroll19 for (int i = 32; i >= 2; i /= 2)20 A[i]++; // OK21 22#pragma unroll23 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 OK26}27#else28// 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 partial45// unrolling.46#pragma unroll47 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>' directive49 A[j]++;50 }51 52#pragma unroll53 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>' directive55 A[j]++;56 } while (j < 2000);57 58// While loop is partially unrolled, no action needed.59#pragma unroll 460 while (j < 2000) {61 A[j]++;62 }63 64#pragma unroll 465 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 unroll81 for (int k : a) {82 A[k]++;83 }84 85 // Loop with unknown size should be partially unrolled.86 int b[vectorSize];87#pragma unroll88 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 595 for (int k : b) {96 k++;97 }98 99 // Loop with large size should be partially unrolled.100 int c[51];101#pragma unroll102 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 5109 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 unroll124 for (int i = 0; i < 50; ++i) {125 A[i]++;126 }127 128// Loop with unknown size should be partially unrolled.129#pragma unroll130 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 unroll136 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 unroll143 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 unroll149 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 unroll155 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 unroll161 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 unroll167 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 unroll173 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 5180 for (int i = 0; i < size; ++i) {181 A[i]++;182 }183 184// Loop with large size should be partially unrolled.185#pragma unroll186 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 5193 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 unroll202 for (int i = 0; i < 50; ++i)203 A[i]++; // OK204 205#pragma unroll206 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 OK209 210// --211#pragma unroll212 for (int i = 50; i > 0; --i)213 A[i]++; // OK214 215#pragma unroll216 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 OK219 220// +=221#pragma unroll222 for (int i = 0; i < 100; i += 2)223 A[i]++; // OK224 225#pragma unroll226 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 OK229 230// -=231#pragma unroll232 for (int i = 100; i > 0; i -= 2)233 A[i]++; // OK234 235#pragma unroll236 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 OK239}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 unroll352 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 5360 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 5369 do {370 A[2] += i + j;371 j++;372 } while (j < 50);373 }374 375 int i = 0;376 while (i < 1000) {377#pragma unroll378 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 5388 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 5399 do {400 A[5] += i + j;401 j++;402 } while (j < 50);403 i++;404 }405 406 i = 0;407 do {408#pragma unroll409 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 5419 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 5430 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 unroll442 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 unroll451 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 unroll461 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 unroll472 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>' directive474 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 unroll484 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 condition496#pragma unroll497 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 unroll503 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-dependent509#pragma unroll510 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#endif516// There are no fix-its for this check517