| // RUN: %check_clang_tidy %s altera-unroll-loops %t -- -config="{CheckOptions: [{key: "altera-unroll-loops.MaxLoopIterations", value: 50}]}" -header-filter=.* |
| // RUN: %check_clang_tidy -check-suffix=MULT %s altera-unroll-loops %t -- -config="{CheckOptions: [{key: "altera-unroll-loops.MaxLoopIterations", value: 5}]}" -header-filter=.* "--" -DMULT |
| |
| #ifdef MULT |
| // For loops with *= and /= increments. |
| void for_loop_mult_div_increments(int *A) { |
| // *= |
| #pragma unroll |
| for (int i = 2; i <= 32; i *= 2) |
| A[i]++; // OK |
| |
| #pragma unroll |
| for (int i = 2; i <= 64; i *= 2) |
| // 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] |
| A[i]++; // Not OK |
| |
| // /= |
| #pragma unroll |
| for (int i = 32; i >= 2; i /= 2) |
| A[i]++; // OK |
| |
| #pragma unroll |
| for (int i = 64; i >= 2; i /= 2) |
| // 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] |
| A[i]++; // Not OK |
| } |
| #else |
| // Cannot determine loop bounds for while loops. |
| void while_loops(int *A) { |
| // Recommend unrolling loops that aren't already unrolled. |
| int j = 0; |
| while (j < 2000) { |
| // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: kernel performance could be improved by unrolling this loop with a '#pragma unroll' directive [altera-unroll-loops] |
| A[1] += j; |
| j++; |
| } |
| |
| do { |
| // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: kernel performance could be improved by unrolling this loop with a '#pragma unroll' directive [altera-unroll-loops] |
| A[2] += j; |
| j++; |
| } while (j < 2000); |
| |
| // If a while loop is fully unrolled, add a note recommending partial |
| // unrolling. |
| #pragma unroll |
| while (j < 2000) { |
| // 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 |
| A[j]++; |
| } |
| |
| #pragma unroll |
| do { |
| // 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 |
| A[j]++; |
| } while (j < 2000); |
| |
| // While loop is partially unrolled, no action needed. |
| #pragma unroll 4 |
| while (j < 2000) { |
| A[j]++; |
| } |
| |
| #pragma unroll 4 |
| do { |
| A[j]++; |
| } while (j < 2000); |
| } |
| |
| // Range-based for loops. |
| void cxx_for_loops(int *A, int vectorSize) { |
| // Loop with known array size should be unrolled. |
| int a[] = {0, 1, 2, 3, 4, 5}; |
| for (int k : a) { |
| // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: kernel performance could be improved by unrolling this loop with a '#pragma unroll' directive [altera-unroll-loops] |
| A[k]++; |
| } |
| |
| // Loop with known size correctly unrolled. |
| #pragma unroll |
| for (int k : a) { |
| A[k]++; |
| } |
| |
| // Loop with unknown size should be partially unrolled. |
| int b[vectorSize]; |
| #pragma unroll |
| for (int k : b) { |
| // 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] |
| k++; |
| } |
| |
| // Loop with unknown size correctly unrolled. |
| #pragma unroll 5 |
| for (int k : b) { |
| k++; |
| } |
| |
| // Loop with large size should be partially unrolled. |
| int c[51]; |
| #pragma unroll |
| for (int k : c) { |
| // 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] |
| A[k]++; |
| } |
| |
| // Loop with large size correctly unrolled. |
| #pragma unroll 5 |
| for (int k : c) { |
| A[k]++; |
| } |
| } |
| |
| // Simple for loops. |
| void for_loops(int *A, int size) { |
| // Recommend unrolling loops that aren't already unrolled. |
| for (int i = 0; i < 2000; ++i) { |
| // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: kernel performance could be improved by unrolling this loop with a '#pragma unroll' directive [altera-unroll-loops] |
| A[0] += i; |
| } |
| |
| // Loop with known size correctly unrolled. |
| #pragma unroll |
| for (int i = 0; i < 50; ++i) { |
| A[i]++; |
| } |
| |
| // Loop with unknown size should be partially unrolled. |
| #pragma unroll |
| for (int i = 0; i < size; ++i) { |
| // 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] |
| A[i]++; |
| } |
| |
| #pragma unroll |
| for (;;) { |
| // 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] |
| A[0]++; |
| } |
| |
| int i = 0; |
| #pragma unroll |
| for (; i < size; ++i) { |
| // 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] |
| A[i]++; |
| } |
| |
| #pragma unroll |
| for (int i = 0;; ++i) { |
| // 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] |
| A[i]++; |
| } |
| |
| #pragma unroll |
| for (int i = 0; i < size;) { |
| // 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] |
| A[i]++; |
| } |
| |
| #pragma unroll |
| for (int i = size; i < 50; ++i) { |
| // 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] |
| A[i]++; |
| } |
| |
| #pragma unroll |
| for (int i = 0; true; ++i) { |
| // 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] |
| A[i]++; |
| } |
| |
| #pragma unroll |
| for (int i = 0; i == i; ++i) { |
| // 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] |
| A[i]++; |
| } |
| |
| // Loop with unknown size correctly unrolled. |
| #pragma unroll 5 |
| for (int i = 0; i < size; ++i) { |
| A[i]++; |
| } |
| |
| // Loop with large size should be partially unrolled. |
| #pragma unroll |
| for (int i = 0; i < 51; ++i) { |
| // 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] |
| A[i]++; |
| } |
| |
| // Loop with large size correctly unrolled. |
| #pragma unroll 5 |
| for (int i = 0; i < 51; ++i) { |
| A[i]++; |
| } |
| } |
| |
| // For loops with different increments. |
| void for_loop_increments(int *A) { |
| // ++ |
| #pragma unroll |
| for (int i = 0; i < 50; ++i) |
| A[i]++; // OK |
| |
| #pragma unroll |
| for (int i = 0; i < 51; ++i) |
| // 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] |
| A[i]++; // Not OK |
| |
| // -- |
| #pragma unroll |
| for (int i = 50; i > 0; --i) |
| A[i]++; // OK |
| |
| #pragma unroll |
| for (int i = 51; i > 0; --i) |
| // 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] |
| A[i]++; // Not OK |
| |
| // += |
| #pragma unroll |
| for (int i = 0; i < 100; i += 2) |
| A[i]++; // OK |
| |
| #pragma unroll |
| for (int i = 0; i < 101; i += 2) |
| // 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] |
| A[i]++; // Not OK |
| |
| // -= |
| #pragma unroll |
| for (int i = 100; i > 0; i -= 2) |
| A[i]++; // OK |
| |
| #pragma unroll |
| for (int i = 101; i > 0; i -= 2) |
| // 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] |
| A[i]++; // Not OK |
| } |
| |
| // Inner loops should be unrolled. |
| void nested_simple_loops(int *A) { |
| for (int i = 0; i < 1000; ++i) { |
| for (int j = 0; j < 2000; ++j) { |
| // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: kernel performance could be improved by unrolling this loop with a '#pragma unroll' directive [altera-unroll-loops] |
| A[0] += i + j; |
| } |
| } |
| |
| for (int i = 0; i < 1000; ++i) { |
| int j = 0; |
| while (j < 2000) { |
| // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: kernel performance could be improved by unrolling this loop with a '#pragma unroll' directive [altera-unroll-loops] |
| A[1] += i + j; |
| j++; |
| } |
| } |
| |
| for (int i = 0; i < 1000; ++i) { |
| int j = 0; |
| do { |
| // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: kernel performance could be improved by unrolling this loop with a '#pragma unroll' directive [altera-unroll-loops] |
| A[2] += i + j; |
| j++; |
| } while (j < 2000); |
| } |
| |
| int i = 0; |
| while (i < 1000) { |
| for (int j = 0; j < 2000; ++j) { |
| // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: kernel performance could be improved by unrolling this loop with a '#pragma unroll' directive [altera-unroll-loops] |
| A[3] += i + j; |
| } |
| i++; |
| } |
| |
| i = 0; |
| while (i < 1000) { |
| int j = 0; |
| while (j < 2000) { |
| // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: kernel performance could be improved by unrolling this loop with a '#pragma unroll' directive [altera-unroll-loops] |
| A[4] += i + j; |
| j++; |
| } |
| i++; |
| } |
| |
| i = 0; |
| while (i < 1000) { |
| int j = 0; |
| do { |
| // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: kernel performance could be improved by unrolling this loop with a '#pragma unroll' directive [altera-unroll-loops] |
| A[5] += i + j; |
| j++; |
| } while (j < 2000); |
| i++; |
| } |
| |
| i = 0; |
| do { |
| for (int j = 0; j < 2000; ++j) { |
| // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: kernel performance could be improved by unrolling this loop with a '#pragma unroll' directive [altera-unroll-loops] |
| A[6] += i + j; |
| } |
| i++; |
| } while (i < 1000); |
| |
| i = 0; |
| do { |
| int j = 0; |
| while (j < 2000) { |
| // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: kernel performance could be improved by unrolling this loop with a '#pragma unroll' directive [altera-unroll-loops] |
| A[7] += i + j; |
| j++; |
| } |
| i++; |
| } while (i < 1000); |
| |
| i = 0; |
| do { |
| int j = 0; |
| do { |
| // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: kernel performance could be improved by unrolling this loop with a '#pragma unroll' directive [altera-unroll-loops] |
| A[8] += i + j; |
| j++; |
| } while (j < 2000); |
| i++; |
| } while (i < 1000); |
| |
| for (int i = 0; i < 100; ++i) { |
| // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: kernel performance could be improved by unrolling this loop with a '#pragma unroll' directive [altera-unroll-loops] |
| A[i]++; |
| } |
| |
| i = 0; |
| while (i < 100) { |
| // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: kernel performance could be improved by unrolling this loop with a '#pragma unroll' directive [altera-unroll-loops] |
| i++; |
| } |
| |
| i = 0; |
| do { |
| // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: kernel performance could be improved by unrolling this loop with a '#pragma unroll' directive [altera-unroll-loops] |
| i++; |
| } while (i < 100); |
| } |
| |
| // These loops are all correctly unrolled. |
| void unrolled_nested_simple_loops(int *A) { |
| for (int i = 0; i < 1000; ++i) { |
| #pragma unroll |
| for (int j = 0; j < 50; ++j) { |
| A[0] += i + j; |
| } |
| } |
| |
| for (int i = 0; i < 1000; ++i) { |
| int j = 0; |
| #pragma unroll 5 |
| while (j < 50) { |
| A[1] += i + j; |
| j++; |
| } |
| } |
| |
| for (int i = 0; i < 1000; ++i) { |
| int j = 0; |
| #pragma unroll 5 |
| do { |
| A[2] += i + j; |
| j++; |
| } while (j < 50); |
| } |
| |
| int i = 0; |
| while (i < 1000) { |
| #pragma unroll |
| for (int j = 0; j < 50; ++j) { |
| A[3] += i + j; |
| } |
| i++; |
| } |
| |
| i = 0; |
| while (i < 1000) { |
| int j = 0; |
| #pragma unroll 5 |
| while (50 > j) { |
| A[4] += i + j; |
| j++; |
| } |
| i++; |
| } |
| |
| i = 0; |
| while (1000 > i) { |
| int j = 0; |
| #pragma unroll 5 |
| do { |
| A[5] += i + j; |
| j++; |
| } while (j < 50); |
| i++; |
| } |
| |
| i = 0; |
| do { |
| #pragma unroll |
| for (int j = 0; j < 50; ++j) { |
| A[6] += i + j; |
| } |
| i++; |
| } while (i < 1000); |
| |
| i = 0; |
| do { |
| int j = 0; |
| #pragma unroll 5 |
| while (j < 50) { |
| A[7] += i + j; |
| j++; |
| } |
| i++; |
| } while (i < 1000); |
| |
| i = 0; |
| do { |
| int j = 0; |
| #pragma unroll 5 |
| do { |
| A[8] += i + j; |
| j++; |
| } while (j < 50); |
| i++; |
| } while (i < 1000); |
| } |
| |
| // These inner loops are large and should be partially unrolled. |
| void unrolled_nested_simple_loops_large_num_iterations(int *A) { |
| for (int i = 0; i < 1000; ++i) { |
| #pragma unroll |
| for (int j = 0; j < 51; ++j) { |
| // 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] |
| A[0] += i + j; |
| } |
| } |
| |
| int i = 0; |
| while (i < 1000) { |
| #pragma unroll |
| for (int j = 0; j < 51; ++j) { |
| // 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] |
| A[3] += i + j; |
| } |
| i++; |
| } |
| |
| i = 0; |
| do { |
| #pragma unroll |
| for (int j = 0; j < 51; ++j) { |
| // 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] |
| A[6] += i + j; |
| } |
| i++; |
| } while (i < 1000); |
| |
| i = 0; |
| do { |
| int j = 0; |
| #pragma unroll |
| do { |
| // 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 |
| A[8] += i + j; |
| j++; |
| } while (j < 51); |
| i++; |
| } while (i < 1000); |
| |
| i = 0; |
| int a[51]; |
| do { |
| #pragma unroll |
| for (int k : a) { |
| // 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] |
| A[k]++; |
| } |
| } while (i < 1000); |
| } |
| |
| // These loops have unknown bounds and should be partially unrolled. |
| void fully_unrolled_unknown_bounds(int vectorSize) { |
| int someVector[101]; |
| |
| // There is no loop condition |
| #pragma unroll |
| for (;;) { |
| // 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] |
| someVector[0]++; |
| } |
| |
| #pragma unroll |
| for (int i = 0; 1 < 5; ++i) { |
| // 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] |
| someVector[i]++; |
| } |
| |
| // Both sides are value-dependent |
| #pragma unroll |
| for (int i = 0; i < vectorSize; ++i) { |
| // 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] |
| someVector[i]++; |
| } |
| } |
| #endif |
| // There are no fix-its for this check |