llvm-project/clang/test/Analysis/loop-unrolling.cpp

550 lines
12 KiB
C++

// RUN: %clang_analyze_cc1 -analyzer-checker=core,debug.ExprInspection -analyzer-config unroll-loops=true,cfg-loopexit=true -verify -std=c++14 -analyzer-config exploration_strategy=unexplored_first_queue %s
// RUN: %clang_analyze_cc1 -analyzer-checker=core,debug.ExprInspection -analyzer-config unroll-loops=true,cfg-loopexit=true,exploration_strategy=dfs -verify -std=c++14 -DDFS=1 %s
void clang_analyzer_numTimesReached();
void clang_analyzer_warnIfReached();
int getNum();
void foo(int &);
int simple_unroll1() {
int a[9];
int k = 42;
for (int i = 0; i < 9; i++) {
clang_analyzer_numTimesReached(); // expected-warning {{9}}
a[i] = 42;
}
int b = 22 / (k - 42); // expected-warning {{Division by zero}}
return 0;
}
int simple_unroll2() {
int a[9];
int k = 42;
int i;
for (i = 0; i < 9; i++) {
clang_analyzer_numTimesReached(); // expected-warning {{9}}
a[i] = 42;
}
for (int j = 0; j <= 9; ++j) {
clang_analyzer_numTimesReached(); // expected-warning {{10}}
a[j] = 42;
}
int b = 22 / (k - 42); // expected-warning {{Division by zero}}
return 0;
}
int simple_unroll3_unsigned() {
int a[9];
int k = 42;
for (unsigned i = 0; i < 9; i++) {
clang_analyzer_numTimesReached(); // expected-warning {{9}}
a[i] = 42;
}
int b = 22 / (k - 42); // expected-warning {{Division by zero}}
return 0;
}
int simple_unroll4_unsigned() {
int a[9];
int k = 42;
unsigned i;
for (i = (0); i < 9; i++) {
clang_analyzer_numTimesReached(); // expected-warning {{9}}
a[i] = 42;
}
int b = 22 / (k - 42); // expected-warning {{Division by zero}}
return 0;
}
int simple_no_unroll1() {
int a[9];
int k = 42;
for (int i = 0; i < 9; i++) {
clang_analyzer_numTimesReached(); // expected-warning {{4}}
a[i] = 42;
foo(i);
}
int b = 22 / (k - 42); // expected-warning {{Division by zero}}
return 0;
}
int simple_no_unroll2() {
int a[9];
int k = 42;
int i;
for (i = 0; i < 9; i++) {
clang_analyzer_numTimesReached(); // expected-warning {{4}}
a[i] = 42;
i += getNum();
}
int b = 22 / (k - 42); // expected-warning {{Division by zero}}
return 0;
}
int simple_no_unroll3() {
int a[9];
int k = 42;
for (int i = 0; i < 9; i++) {
clang_analyzer_numTimesReached(); // expected-warning {{4}}
a[i] = 42;
(void)&i;
}
int b = 22 / (k - 42); // no-warning
return 0;
}
int simple_no_unroll4() {
int a[9];
int k = 42;
int i;
for (i = 0; i < 9; i++) {
clang_analyzer_numTimesReached(); // expected-warning {{4}}
a[i] = 42;
int &j = i;
}
int b = 22 / (k - 42); // no-warning
return 0;
}
int simple_no_unroll5() {
int a[9];
int k = 42;
int i;
for (i = 0; i < 9; i++) {
clang_analyzer_numTimesReached(); // expected-warning {{4}}
a[i] = 42;
int &j{i};
}
int b = 22 / (k - 42); // no-warning
return 0;
}
int no_unroll_assignment() {
for (int i = 0; i < 9; i++) {
i = i + 1;
clang_analyzer_numTimesReached(); // expected-warning {{4}}
}
return 0;
}
int no_unroll_assignment2() {
for (int i = 0; i < 9; i++) {
i *= 2;
clang_analyzer_numTimesReached(); // expected-warning {{4}}
}
return 0;
}
int no_unroll_assignment3() {
for (int i = 128; i > 0; i--) {
i /= 2;
clang_analyzer_numTimesReached(); // expected-warning {{4}}
}
return 0;
}
int no_unroll_assignment4() {
for (int i = 0; i < 9; i++) {
i -= 2;
clang_analyzer_numTimesReached(); // expected-warning {{4}}
}
return 0;
}
int no_unroll_assignment5() {
for (int i = 0; i < 9; i++) {
i += 1;
clang_analyzer_numTimesReached(); // expected-warning {{4}}
}
return 0;
}
int no_unroll_assignment6() {
for (int i = 128; i > 0; i--) {
i >>= 1;
clang_analyzer_numTimesReached(); // expected-warning {{4}}
}
return 0;
}
int no_unroll_assignment7() {
for (int i = 0; i < 512; i++) {
i <<= 1;
clang_analyzer_numTimesReached(); // expected-warning {{4}}
}
return 0;
}
int no_unroll_assignment8() {
for (int i = 0; i < 9; i++) {
i %= 8;
clang_analyzer_numTimesReached(); // expected-warning {{4}}
}
return 0;
}
int no_unroll_assignment9() {
for (int i = 0; i < 9; i++) {
i &= 31;
clang_analyzer_numTimesReached(); // expected-warning {{4}}
}
return 0;
}
int no_unroll_assignment10() {
for (int i = 0; i < 9; i++) {
i |= 2;
clang_analyzer_numTimesReached(); // expected-warning {{4}}
}
return 0;
}
int no_unroll_assignment11() {
for (int i = 0; i < 9; i++) {
i ^= 2;
clang_analyzer_numTimesReached(); // expected-warning {{4}}
}
return 0;
}
int make_new_branches_loop_cached() {
for (int i = 0; i < 8; i++) {
clang_analyzer_numTimesReached(); // expected-warning {{4}}
if (getNum()) {
(void)i; // Since this Stmt does not change the State the analyzer
// won't make a new execution path but reuse the earlier nodes.
}
}
clang_analyzer_warnIfReached(); // no-warning
return 0;
}
int make_new_branches_loop_uncached() {
int l = 2;
for (int i = 0; i < 8; i++) {
clang_analyzer_numTimesReached(); // expected-warning {{10}}
if (getNum()) {
++l;
}
}
clang_analyzer_warnIfReached(); // no-warning
return 0;
}
int make_new_branches_loop_uncached2() {
int l = 2;
for (int i = 0; i < 8; i++) {
clang_analyzer_numTimesReached(); // expected-warning {{10}}
if (getNum()) {
++l;
}
(void)&i; // This ensures that the loop won't be unrolled.
}
clang_analyzer_warnIfReached(); // no-warning
return 0;
}
int escape_before_loop_no_unroll1() {
int a[9];
int k = 42;
int i;
int &j = i;
for (i = 0; i < 9; i++) {
clang_analyzer_numTimesReached(); // expected-warning {{4}}
a[i] = 42;
}
int b = 22 / (k - 42); // no-warning
return 0;
}
int escape_before_loop_no_unroll2() {
int a[9];
int k = 42;
int i;
int *p = &i;
for (i = 0; i < 9; i++) {
clang_analyzer_numTimesReached(); // expected-warning {{4}}
a[i] = 42;
}
int b = 22 / (k - 42); // no-warning
return 0;
}
int escape_before_loop_no_unroll3() {
int a[9];
int k = 42;
int i;
foo(i);
for (i = 0; i < 9; i++) {
clang_analyzer_numTimesReached(); // expected-warning {{4}}
a[i] = 42;
}
int b = 22 / (k - 42); // no-warning
return 0;
}
int nested_outer_unrolled() {
int a[9];
int k = 42;
int j = 0;
for (int i = 0; i < 9; i++) {
clang_analyzer_numTimesReached(); // expected-warning {{1}}
for (j = 0; j < 9; ++j) {
clang_analyzer_numTimesReached(); // expected-warning {{4}}
a[j] = 22;
(void)&j; // ensures that the inner loop won't be unrolled
}
a[i] = 42;
}
int b = 22 / (k - 42); // no-warning
return 0;
}
int nested_inner_unrolled() {
int a[9];
int k = 42;
int j = 0;
for (int i = 0; i < getNum(); i++) {
clang_analyzer_numTimesReached(); // expected-warning {{4}}
for (j = 0; j < 8; ++j) {
clang_analyzer_numTimesReached(); // expected-warning {{32}}
a[j] = 22;
}
a[i] = 42;
}
int b = 22 / (k - 42); // expected-warning {{Division by zero}}
return 0;
}
int nested_both_unrolled() {
int a[9];
int k = 42;
int j = 0;
for (int i = 0; i < 7; i++) {
clang_analyzer_numTimesReached(); // expected-warning {{7}}
for (j = 0; j < 6; ++j) {
clang_analyzer_numTimesReached(); // expected-warning {{42}}
a[j] = 22;
}
a[i] = 42;
}
int b = 22 / (k - 42); // expected-warning {{Division by zero}}
return 0;
}
int simple_known_bound_loop() {
for (int i = 2; i < 12; i++) {
// This function is inlined in nested_inlined_unroll1()
clang_analyzer_numTimesReached(); // expected-warning {{90}}
}
return 0;
}
int simple_unknown_bound_loop() {
for (int i = 2; i < getNum(); i++) {
#ifdef DFS
clang_analyzer_numTimesReached(); // expected-warning {{16}}
#else
clang_analyzer_numTimesReached(); // expected-warning {{8}}
#endif
}
return 0;
}
int nested_inlined_unroll1() {
int k;
for (int i = 0; i < 9; i++) {
clang_analyzer_numTimesReached(); // expected-warning {{9}}
k = simple_known_bound_loop(); // no reevaluation without inlining
}
int a = 22 / k; // expected-warning {{Division by zero}}
return 0;
}
int nested_inlined_no_unroll1() {
int k;
for (int i = 0; i < 9; i++) {
#ifdef DFS
clang_analyzer_numTimesReached(); // expected-warning {{18}}
#else
clang_analyzer_numTimesReached(); // expected-warning {{14}}
#endif
k = simple_unknown_bound_loop(); // reevaluation without inlining, splits the state as well
}
int a = 22 / k; // no-warning
return 0;
}
int recursion_unroll1(bool b) {
int k = 2;
for (int i = 0; i < 5; i++) {
clang_analyzer_numTimesReached(); // expected-warning {{13}}
if (i == 0 && b) // Splits the state in the first iteration but the recursion
// call will be unrolled anyway since the condition is known there.
recursion_unroll1(false);
clang_analyzer_numTimesReached(); // expected-warning {{14}}
}
int a = 22 / k; // no-warning
return 0;
}
int recursion_unroll2(bool b) {
int k = 0;
for (int i = 0; i < 5; i++) {
clang_analyzer_numTimesReached(); // expected-warning {{9}}
if (i == 0 && b)
recursion_unroll2(false);
clang_analyzer_numTimesReached(); // expected-warning {{9}}
}
int a = 22 / k; // expected-warning {{Division by zero}}
return 0;
}
int recursion_unroll3(bool b) {
int k = 2;
for (int i = 0; i < 5; i++) {
clang_analyzer_numTimesReached(); // expected-warning {{10}}
if (i == 4 && b) {
recursion_unroll3(false);
break;
}
clang_analyzer_numTimesReached(); // expected-warning {{10}}
}
int a = 22 / k;
return 0;
}
int recursion_unroll4(bool b) {
int k = 2;
for (int i = 0; i < 5; i++) {
clang_analyzer_numTimesReached(); // expected-warning {{13}}
if (i == 0 && b) {
recursion_unroll4(false);
continue;
}
clang_analyzer_numTimesReached(); // expected-warning {{13}}
}
int a = 22 / k;
return 0;
}
int loop_exit_while_empty_loop_stack() {
if (getNum())
for (int i = 1; i < 8; i++)
;
return 0;
}
int num_steps_on_limit() {
for (int i = 0; i < 128; i++) {
clang_analyzer_numTimesReached(); // expected-warning {{128}}
}
clang_analyzer_numTimesReached(); // expected-warning {{1}}
return 0;
}
int num_steps_over_limit1() {
for (int i = 0; i < 129; i++) {
clang_analyzer_numTimesReached(); // expected-warning {{4}}
}
return 0;
}
int num_steps_on_limit2() {
for (int i = 0; i < 2; i++) {
for (int j = 0; j < 64; j++) {
clang_analyzer_numTimesReached(); // expected-warning {{128}}
}
}
return 0;
}
int num_steps_over_limit2() {
for (int i = 0; i < 2; i++) {
clang_analyzer_numTimesReached(); // expected-warning {{1}}
for (int j = 0; j <= 64; j++) {
clang_analyzer_numTimesReached(); // expected-warning {{4}}
}
}
return 0;
}
int num_steps_on_limit3() {
for (int i = 0; i < getNum(); i++) {
clang_analyzer_numTimesReached(); // expected-warning {{4}}
for (int j = 0; j < 32; j++) {
clang_analyzer_numTimesReached(); // expected-warning {{128}}
}
}
return 0;
}
int num_steps_over_limit3() {
for (int i = 0; i < getNum(); i++) {
clang_analyzer_numTimesReached(); // expected-warning {{1}}
for (int j = 0; j < 33; j++) {
clang_analyzer_numTimesReached(); // expected-warning {{4}}
}
}
return 0;
}
void pr34943() {
for (int i = 0; i < 6L; ++i) {
clang_analyzer_numTimesReached(); // expected-warning {{6}}
}
}
void parm_by_value_as_loop_counter(int i) {
for (i = 0; i < 10; ++i) {
clang_analyzer_numTimesReached(); // expected-warning {{10}}
}
}
void parm_by_ref_as_loop_counter(int &i) {
for (i = 0; i < 10; ++i) {
clang_analyzer_numTimesReached(); // expected-warning {{4}}
}
}
void capture_by_value_as_loop_counter() {
int out = 0;
auto l = [i = out]() mutable {
for (i = 0; i < 10; ++i) {
clang_analyzer_numTimesReached(); // expected-warning {{10}}
}
};
}
void capture_by_ref_as_loop_counter() {
int out = 0;
auto l = [&i = out]() {
for (i = 0; i < 10; ++i) {
clang_analyzer_numTimesReached(); // expected-warning {{4}}
}
};
}
void capture_implicitly_by_value_as_loop_counter() {
int i = 0;
auto l = [=]() mutable {
for (i = 0; i < 10; ++i) {
clang_analyzer_numTimesReached(); // expected-warning {{10}}
}
};
}
void capture_implicitly_by_ref_as_loop_counter() {
int i = 0;
auto l = [&]() mutable {
for (i = 0; i < 10; ++i) {
clang_analyzer_numTimesReached(); // expected-warning {{4}}
}
};
}