forked from OSchip/llvm-project
517 lines
16 KiB
C++
517 lines
16 KiB
C++
// 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
|