| #include <benchmark/benchmark.h> |
| |
| #ifdef __clang__ |
| #pragma clang diagnostic ignored "-Wreturn-type" |
| #endif |
| |
| extern "C" { |
| |
| extern int ExternInt; |
| extern int ExternInt2; |
| extern int ExternInt3; |
| |
| inline int Add42(int x) { return x + 42; } |
| |
| struct NotTriviallyCopyable { |
| NotTriviallyCopyable(); |
| explicit NotTriviallyCopyable(int x) : value(x) {} |
| NotTriviallyCopyable(NotTriviallyCopyable const&); |
| int value; |
| }; |
| |
| struct Large { |
| int value; |
| int data[2]; |
| }; |
| |
| } |
| // CHECK-LABEL: test_with_rvalue: |
| extern "C" void test_with_rvalue() { |
| benchmark::DoNotOptimize(Add42(0)); |
| // CHECK: movl $42, %eax |
| // CHECK: ret |
| } |
| |
| // CHECK-LABEL: test_with_large_rvalue: |
| extern "C" void test_with_large_rvalue() { |
| benchmark::DoNotOptimize(Large{ExternInt, {ExternInt, ExternInt}}); |
| // CHECK: ExternInt(%rip) |
| // CHECK: movl %eax, -{{[0-9]+}}(%[[REG:[a-z]+]] |
| // CHECK: movl %eax, -{{[0-9]+}}(%[[REG]]) |
| // CHECK: movl %eax, -{{[0-9]+}}(%[[REG]]) |
| // CHECK: ret |
| } |
| |
| // CHECK-LABEL: test_with_non_trivial_rvalue: |
| extern "C" void test_with_non_trivial_rvalue() { |
| benchmark::DoNotOptimize(NotTriviallyCopyable(ExternInt)); |
| // CHECK: mov{{l|q}} ExternInt(%rip) |
| // CHECK: ret |
| } |
| |
| // CHECK-LABEL: test_with_lvalue: |
| extern "C" void test_with_lvalue() { |
| int x = 101; |
| benchmark::DoNotOptimize(x); |
| // CHECK-GNU: movl $101, %eax |
| // CHECK-CLANG: movl $101, -{{[0-9]+}}(%[[REG:[a-z]+]]) |
| // CHECK: ret |
| } |
| |
| // CHECK-LABEL: test_with_large_lvalue: |
| extern "C" void test_with_large_lvalue() { |
| Large L{ExternInt, {ExternInt, ExternInt}}; |
| benchmark::DoNotOptimize(L); |
| // CHECK: ExternInt(%rip) |
| // CHECK: movl %eax, -{{[0-9]+}}(%[[REG:[a-z]+]]) |
| // CHECK: movl %eax, -{{[0-9]+}}(%[[REG]]) |
| // CHECK: movl %eax, -{{[0-9]+}}(%[[REG]]) |
| // CHECK: ret |
| } |
| |
| // CHECK-LABEL: test_with_non_trivial_lvalue: |
| extern "C" void test_with_non_trivial_lvalue() { |
| NotTriviallyCopyable NTC(ExternInt); |
| benchmark::DoNotOptimize(NTC); |
| // CHECK: ExternInt(%rip) |
| // CHECK: movl %eax, -{{[0-9]+}}(%[[REG:[a-z]+]]) |
| // CHECK: ret |
| } |
| |
| // CHECK-LABEL: test_with_const_lvalue: |
| extern "C" void test_with_const_lvalue() { |
| const int x = 123; |
| benchmark::DoNotOptimize(x); |
| // CHECK: movl $123, %eax |
| // CHECK: ret |
| } |
| |
| // CHECK-LABEL: test_with_large_const_lvalue: |
| extern "C" void test_with_large_const_lvalue() { |
| const Large L{ExternInt, {ExternInt, ExternInt}}; |
| benchmark::DoNotOptimize(L); |
| // CHECK: ExternInt(%rip) |
| // CHECK: movl %eax, -{{[0-9]+}}(%[[REG:[a-z]+]]) |
| // CHECK: movl %eax, -{{[0-9]+}}(%[[REG]]) |
| // CHECK: movl %eax, -{{[0-9]+}}(%[[REG]]) |
| // CHECK: ret |
| } |
| |
| // CHECK-LABEL: test_with_non_trivial_const_lvalue: |
| extern "C" void test_with_non_trivial_const_lvalue() { |
| const NotTriviallyCopyable Obj(ExternInt); |
| benchmark::DoNotOptimize(Obj); |
| // CHECK: mov{{q|l}} ExternInt(%rip) |
| // CHECK: ret |
| } |
| |
| // CHECK-LABEL: test_div_by_two: |
| extern "C" int test_div_by_two(int input) { |
| int divisor = 2; |
| benchmark::DoNotOptimize(divisor); |
| return input / divisor; |
| // CHECK: movl $2, [[DEST:.*]] |
| // CHECK: idivl [[DEST]] |
| // CHECK: ret |
| } |
| |
| // CHECK-LABEL: test_inc_integer: |
| extern "C" int test_inc_integer() { |
| int x = 0; |
| for (int i=0; i < 5; ++i) |
| benchmark::DoNotOptimize(++x); |
| // CHECK: movl $1, [[DEST:.*]] |
| // CHECK: {{(addl \$1,|incl)}} [[DEST]] |
| // CHECK: {{(addl \$1,|incl)}} [[DEST]] |
| // CHECK: {{(addl \$1,|incl)}} [[DEST]] |
| // CHECK: {{(addl \$1,|incl)}} [[DEST]] |
| // CHECK-CLANG: movl [[DEST]], %eax |
| // CHECK: ret |
| return x; |
| } |
| |
| // CHECK-LABEL: test_pointer_rvalue |
| extern "C" void test_pointer_rvalue() { |
| // CHECK: movl $42, [[DEST:.*]] |
| // CHECK: leaq [[DEST]], %rax |
| // CHECK-CLANG: movq %rax, -{{[0-9]+}}(%[[REG:[a-z]+]]) |
| // CHECK: ret |
| int x = 42; |
| benchmark::DoNotOptimize(&x); |
| } |
| |
| // CHECK-LABEL: test_pointer_const_lvalue: |
| extern "C" void test_pointer_const_lvalue() { |
| // CHECK: movl $42, [[DEST:.*]] |
| // CHECK: leaq [[DEST]], %rax |
| // CHECK-CLANG: movq %rax, -{{[0-9]+}}(%[[REG:[a-z]+]]) |
| // CHECK: ret |
| int x = 42; |
| int * const xp = &x; |
| benchmark::DoNotOptimize(xp); |
| } |
| |
| // CHECK-LABEL: test_pointer_lvalue: |
| extern "C" void test_pointer_lvalue() { |
| // CHECK: movl $42, [[DEST:.*]] |
| // CHECK: leaq [[DEST]], %rax |
| // CHECK-CLANG: movq %rax, -{{[0-9]+}}(%[[REG:[a-z+]+]]) |
| // CHECK: ret |
| int x = 42; |
| int *xp = &x; |
| benchmark::DoNotOptimize(xp); |
| } |