1 #include <benchmark/benchmark.h>
2 
3 #ifdef __clang__
4 #pragma clang diagnostic ignored "-Wreturn-type"
5 #endif
6 
7 extern "C" {
8 
9 extern int ExternInt;
10 extern int ExternInt2;
11 extern int ExternInt3;
12 
Add42(int x)13 inline int Add42(int x) { return x + 42; }
14 
15 struct NotTriviallyCopyable {
16   NotTriviallyCopyable();
NotTriviallyCopyableNotTriviallyCopyable17   explicit NotTriviallyCopyable(int x) : value(x) {}
18   NotTriviallyCopyable(NotTriviallyCopyable const&);
19   int value;
20 };
21 
22 struct Large {
23   int value;
24   int data[2];
25 };
26 
27 }
28 // CHECK-LABEL: test_with_rvalue:
test_with_rvalue()29 extern "C" void test_with_rvalue() {
30   benchmark::DoNotOptimize(Add42(0));
31   // CHECK: movl $42, %eax
32   // CHECK: ret
33 }
34 
35 // CHECK-LABEL: test_with_large_rvalue:
test_with_large_rvalue()36 extern "C" void test_with_large_rvalue() {
37   benchmark::DoNotOptimize(Large{ExternInt, {ExternInt, ExternInt}});
38   // CHECK: ExternInt(%rip)
39   // CHECK: movl %eax, -{{[0-9]+}}(%[[REG:[a-z]+]]
40   // CHECK: movl %eax, -{{[0-9]+}}(%[[REG]])
41   // CHECK: movl %eax, -{{[0-9]+}}(%[[REG]])
42   // CHECK: ret
43 }
44 
45 // CHECK-LABEL: test_with_non_trivial_rvalue:
test_with_non_trivial_rvalue()46 extern "C" void test_with_non_trivial_rvalue() {
47   benchmark::DoNotOptimize(NotTriviallyCopyable(ExternInt));
48   // CHECK: mov{{l|q}} ExternInt(%rip)
49   // CHECK: ret
50 }
51 
52 // CHECK-LABEL: test_with_lvalue:
test_with_lvalue()53 extern "C" void test_with_lvalue() {
54   int x = 101;
55   benchmark::DoNotOptimize(x);
56   // CHECK-GNU: movl $101, %eax
57   // CHECK-CLANG: movl $101, -{{[0-9]+}}(%[[REG:[a-z]+]])
58   // CHECK: ret
59 }
60 
61 // CHECK-LABEL: test_with_large_lvalue:
test_with_large_lvalue()62 extern "C" void test_with_large_lvalue() {
63   Large L{ExternInt, {ExternInt, ExternInt}};
64   benchmark::DoNotOptimize(L);
65   // CHECK: ExternInt(%rip)
66   // CHECK: movl %eax, -{{[0-9]+}}(%[[REG:[a-z]+]])
67   // CHECK: movl %eax, -{{[0-9]+}}(%[[REG]])
68   // CHECK: movl %eax, -{{[0-9]+}}(%[[REG]])
69   // CHECK: ret
70 }
71 
72 // CHECK-LABEL: test_with_non_trivial_lvalue:
test_with_non_trivial_lvalue()73 extern "C" void test_with_non_trivial_lvalue() {
74   NotTriviallyCopyable NTC(ExternInt);
75   benchmark::DoNotOptimize(NTC);
76   // CHECK: ExternInt(%rip)
77   // CHECK: movl %eax, -{{[0-9]+}}(%[[REG:[a-z]+]])
78   // CHECK: ret
79 }
80 
81 // CHECK-LABEL: test_with_const_lvalue:
test_with_const_lvalue()82 extern "C" void test_with_const_lvalue() {
83   const int x = 123;
84   benchmark::DoNotOptimize(x);
85   // CHECK: movl $123, %eax
86   // CHECK: ret
87 }
88 
89 // CHECK-LABEL: test_with_large_const_lvalue:
test_with_large_const_lvalue()90 extern "C" void test_with_large_const_lvalue() {
91   const Large L{ExternInt, {ExternInt, ExternInt}};
92   benchmark::DoNotOptimize(L);
93   // CHECK: ExternInt(%rip)
94   // CHECK: movl %eax, -{{[0-9]+}}(%[[REG:[a-z]+]])
95   // CHECK: movl %eax, -{{[0-9]+}}(%[[REG]])
96   // CHECK: movl %eax, -{{[0-9]+}}(%[[REG]])
97   // CHECK: ret
98 }
99 
100 // CHECK-LABEL: test_with_non_trivial_const_lvalue:
test_with_non_trivial_const_lvalue()101 extern "C" void test_with_non_trivial_const_lvalue() {
102   const NotTriviallyCopyable Obj(ExternInt);
103   benchmark::DoNotOptimize(Obj);
104   // CHECK: mov{{q|l}} ExternInt(%rip)
105   // CHECK: ret
106 }
107 
108 // CHECK-LABEL: test_div_by_two:
test_div_by_two(int input)109 extern "C" int test_div_by_two(int input) {
110   int divisor = 2;
111   benchmark::DoNotOptimize(divisor);
112   return input / divisor;
113   // CHECK: movl $2, [[DEST:.*]]
114   // CHECK: idivl [[DEST]]
115   // CHECK: ret
116 }
117 
118 // CHECK-LABEL: test_inc_integer:
test_inc_integer()119 extern "C" int test_inc_integer() {
120   int x = 0;
121   for (int i=0; i < 5; ++i)
122     benchmark::DoNotOptimize(++x);
123   // CHECK: movl $1, [[DEST:.*]]
124   // CHECK: {{(addl \$1,|incl)}} [[DEST]]
125   // CHECK: {{(addl \$1,|incl)}} [[DEST]]
126   // CHECK: {{(addl \$1,|incl)}} [[DEST]]
127   // CHECK: {{(addl \$1,|incl)}} [[DEST]]
128   // CHECK-CLANG: movl [[DEST]], %eax
129   // CHECK: ret
130   return x;
131 }
132 
133 // CHECK-LABEL: test_pointer_rvalue
test_pointer_rvalue()134 extern "C" void test_pointer_rvalue() {
135   // CHECK: movl $42, [[DEST:.*]]
136   // CHECK: leaq [[DEST]], %rax
137   // CHECK-CLANG: movq %rax, -{{[0-9]+}}(%[[REG:[a-z]+]])
138   // CHECK: ret
139   int x = 42;
140   benchmark::DoNotOptimize(&x);
141 }
142 
143 // CHECK-LABEL: test_pointer_const_lvalue:
test_pointer_const_lvalue()144 extern "C" void test_pointer_const_lvalue() {
145   // CHECK: movl $42, [[DEST:.*]]
146   // CHECK: leaq [[DEST]], %rax
147   // CHECK-CLANG: movq %rax, -{{[0-9]+}}(%[[REG:[a-z]+]])
148   // CHECK: ret
149   int x = 42;
150   int * const xp = &x;
151   benchmark::DoNotOptimize(xp);
152 }
153 
154 // CHECK-LABEL: test_pointer_lvalue:
test_pointer_lvalue()155 extern "C" void test_pointer_lvalue() {
156   // CHECK: movl $42, [[DEST:.*]]
157   // CHECK: leaq [[DEST]], %rax
158   // CHECK-CLANG: movq %rax, -{{[0-9]+}}(%[[REG:[a-z+]+]])
159   // CHECK: ret
160   int x = 42;
161   int *xp = &x;
162   benchmark::DoNotOptimize(xp);
163 }
164