xref: /aosp_15_r20/external/google-benchmark/docs/AssemblyTests.md (revision dbb99499c3810fa1611fa2242a2fc446be01a57c)
1*dbb99499SAndroid Build Coastguard Worker# Assembly Tests
2*dbb99499SAndroid Build Coastguard Worker
3*dbb99499SAndroid Build Coastguard WorkerThe Benchmark library provides a number of functions whose primary
4*dbb99499SAndroid Build Coastguard Workerpurpose in to affect assembly generation, including `DoNotOptimize`
5*dbb99499SAndroid Build Coastguard Workerand `ClobberMemory`. In addition there are other functions,
6*dbb99499SAndroid Build Coastguard Workersuch as `KeepRunning`, for which generating good assembly is paramount.
7*dbb99499SAndroid Build Coastguard Worker
8*dbb99499SAndroid Build Coastguard WorkerFor these functions it's important to have tests that verify the
9*dbb99499SAndroid Build Coastguard Workercorrectness and quality of the implementation. This requires testing
10*dbb99499SAndroid Build Coastguard Workerthe code generated by the compiler.
11*dbb99499SAndroid Build Coastguard Worker
12*dbb99499SAndroid Build Coastguard WorkerThis document describes how the Benchmark library tests compiler output,
13*dbb99499SAndroid Build Coastguard Workeras well as how to properly write new tests.
14*dbb99499SAndroid Build Coastguard Worker
15*dbb99499SAndroid Build Coastguard Worker
16*dbb99499SAndroid Build Coastguard Worker## Anatomy of a Test
17*dbb99499SAndroid Build Coastguard Worker
18*dbb99499SAndroid Build Coastguard WorkerWriting a test has two steps:
19*dbb99499SAndroid Build Coastguard Worker
20*dbb99499SAndroid Build Coastguard Worker* Write the code you want to generate assembly for.
21*dbb99499SAndroid Build Coastguard Worker* Add `// CHECK` lines to match against the verified assembly.
22*dbb99499SAndroid Build Coastguard Worker
23*dbb99499SAndroid Build Coastguard WorkerExample:
24*dbb99499SAndroid Build Coastguard Worker```c++
25*dbb99499SAndroid Build Coastguard Worker
26*dbb99499SAndroid Build Coastguard Worker// CHECK-LABEL: test_add:
27*dbb99499SAndroid Build Coastguard Workerextern "C" int test_add() {
28*dbb99499SAndroid Build Coastguard Worker    extern int ExternInt;
29*dbb99499SAndroid Build Coastguard Worker    return ExternInt + 1;
30*dbb99499SAndroid Build Coastguard Worker
31*dbb99499SAndroid Build Coastguard Worker    // CHECK: movl ExternInt(%rip), %eax
32*dbb99499SAndroid Build Coastguard Worker    // CHECK: addl %eax
33*dbb99499SAndroid Build Coastguard Worker    // CHECK: ret
34*dbb99499SAndroid Build Coastguard Worker}
35*dbb99499SAndroid Build Coastguard Worker
36*dbb99499SAndroid Build Coastguard Worker```
37*dbb99499SAndroid Build Coastguard Worker
38*dbb99499SAndroid Build Coastguard Worker#### LLVM Filecheck
39*dbb99499SAndroid Build Coastguard Worker
40*dbb99499SAndroid Build Coastguard Worker[LLVM's Filecheck](https://llvm.org/docs/CommandGuide/FileCheck.html)
41*dbb99499SAndroid Build Coastguard Workeris used to test the generated assembly against the `// CHECK` lines
42*dbb99499SAndroid Build Coastguard Workerspecified in the tests source file. Please see the documentation
43*dbb99499SAndroid Build Coastguard Workerlinked above for information on how to write `CHECK` directives.
44*dbb99499SAndroid Build Coastguard Worker
45*dbb99499SAndroid Build Coastguard Worker#### Tips and Tricks:
46*dbb99499SAndroid Build Coastguard Worker
47*dbb99499SAndroid Build Coastguard Worker* Tests should match the minimal amount of output required to establish
48*dbb99499SAndroid Build Coastguard Workercorrectness. `CHECK` directives don't have to match on the exact next line
49*dbb99499SAndroid Build Coastguard Workerafter the previous match, so tests should omit checks for unimportant
50*dbb99499SAndroid Build Coastguard Workerbits of assembly. ([`CHECK-NEXT`](https://llvm.org/docs/CommandGuide/FileCheck.html#the-check-next-directive)
51*dbb99499SAndroid Build Coastguard Workercan be used to ensure a match occurs exactly after the previous match).
52*dbb99499SAndroid Build Coastguard Worker
53*dbb99499SAndroid Build Coastguard Worker* The tests are compiled with `-O3 -g0`. So we're only testing the
54*dbb99499SAndroid Build Coastguard Workeroptimized output.
55*dbb99499SAndroid Build Coastguard Worker
56*dbb99499SAndroid Build Coastguard Worker* The assembly output is further cleaned up using `tools/strip_asm.py`.
57*dbb99499SAndroid Build Coastguard WorkerThis removes comments, assembler directives, and unused labels before
58*dbb99499SAndroid Build Coastguard Workerthe test is run.
59*dbb99499SAndroid Build Coastguard Worker
60*dbb99499SAndroid Build Coastguard Worker* The generated and stripped assembly file for a test is output under
61*dbb99499SAndroid Build Coastguard Worker`<build-directory>/test/<test-name>.s`
62*dbb99499SAndroid Build Coastguard Worker
63*dbb99499SAndroid Build Coastguard Worker* Filecheck supports using [`CHECK` prefixes](https://llvm.org/docs/CommandGuide/FileCheck.html#cmdoption-check-prefixes)
64*dbb99499SAndroid Build Coastguard Workerto specify lines that should only match in certain situations.
65*dbb99499SAndroid Build Coastguard WorkerThe Benchmark tests use `CHECK-CLANG` and `CHECK-GNU` for lines that
66*dbb99499SAndroid Build Coastguard Workerare only expected to match Clang or GCC's output respectively. Normal
67*dbb99499SAndroid Build Coastguard Worker`CHECK` lines match against all compilers. (Note: `CHECK-NOT` and
68*dbb99499SAndroid Build Coastguard Worker`CHECK-LABEL` are NOT prefixes. They are versions of non-prefixed
69*dbb99499SAndroid Build Coastguard Worker`CHECK` lines)
70*dbb99499SAndroid Build Coastguard Worker
71*dbb99499SAndroid Build Coastguard Worker* Use `extern "C"` to disable name mangling for specific functions. This
72*dbb99499SAndroid Build Coastguard Workermakes them easier to name in the `CHECK` lines.
73*dbb99499SAndroid Build Coastguard Worker
74*dbb99499SAndroid Build Coastguard Worker
75*dbb99499SAndroid Build Coastguard Worker## Problems Writing Portable Tests
76*dbb99499SAndroid Build Coastguard Worker
77*dbb99499SAndroid Build Coastguard WorkerWriting tests which check the code generated by a compiler are
78*dbb99499SAndroid Build Coastguard Workerinherently non-portable. Different compilers and even different compiler
79*dbb99499SAndroid Build Coastguard Workerversions may generate entirely different code. The Benchmark tests
80*dbb99499SAndroid Build Coastguard Workermust tolerate this.
81*dbb99499SAndroid Build Coastguard Worker
82*dbb99499SAndroid Build Coastguard WorkerLLVM Filecheck provides a number of mechanisms to help write
83*dbb99499SAndroid Build Coastguard Worker"more portable" tests; including [matching using regular expressions](https://llvm.org/docs/CommandGuide/FileCheck.html#filecheck-pattern-matching-syntax),
84*dbb99499SAndroid Build Coastguard Workerallowing the creation of [named variables](https://llvm.org/docs/CommandGuide/FileCheck.html#filecheck-variables)
85*dbb99499SAndroid Build Coastguard Workerfor later matching, and [checking non-sequential matches](https://llvm.org/docs/CommandGuide/FileCheck.html#the-check-dag-directive).
86*dbb99499SAndroid Build Coastguard Worker
87*dbb99499SAndroid Build Coastguard Worker#### Capturing Variables
88*dbb99499SAndroid Build Coastguard Worker
89*dbb99499SAndroid Build Coastguard WorkerFor example, say GCC stores a variable in a register but Clang stores
90*dbb99499SAndroid Build Coastguard Workerit in memory. To write a test that tolerates both cases we "capture"
91*dbb99499SAndroid Build Coastguard Workerthe destination of the store, and then use the captured expression
92*dbb99499SAndroid Build Coastguard Workerto write the remainder of the test.
93*dbb99499SAndroid Build Coastguard Worker
94*dbb99499SAndroid Build Coastguard Worker```c++
95*dbb99499SAndroid Build Coastguard Worker// CHECK-LABEL: test_div_no_op_into_shr:
96*dbb99499SAndroid Build Coastguard Workerextern "C" void test_div_no_op_into_shr(int value) {
97*dbb99499SAndroid Build Coastguard Worker    int divisor = 2;
98*dbb99499SAndroid Build Coastguard Worker    benchmark::DoNotOptimize(divisor); // hide the value from the optimizer
99*dbb99499SAndroid Build Coastguard Worker    return value / divisor;
100*dbb99499SAndroid Build Coastguard Worker
101*dbb99499SAndroid Build Coastguard Worker    // CHECK: movl $2, [[DEST:.*]]
102*dbb99499SAndroid Build Coastguard Worker    // CHECK: idivl [[DEST]]
103*dbb99499SAndroid Build Coastguard Worker    // CHECK: ret
104*dbb99499SAndroid Build Coastguard Worker}
105*dbb99499SAndroid Build Coastguard Worker```
106*dbb99499SAndroid Build Coastguard Worker
107*dbb99499SAndroid Build Coastguard Worker#### Using Regular Expressions to Match Differing Output
108*dbb99499SAndroid Build Coastguard Worker
109*dbb99499SAndroid Build Coastguard WorkerOften tests require testing assembly lines which may subtly differ
110*dbb99499SAndroid Build Coastguard Workerbetween compilers or compiler versions. A common example of this
111*dbb99499SAndroid Build Coastguard Workeris matching stack frame addresses. In this case regular expressions
112*dbb99499SAndroid Build Coastguard Workercan be used to match the differing bits of output. For example:
113*dbb99499SAndroid Build Coastguard Worker
114*dbb99499SAndroid Build Coastguard Worker<!-- {% raw %} -->
115*dbb99499SAndroid Build Coastguard Worker```c++
116*dbb99499SAndroid Build Coastguard Workerint ExternInt;
117*dbb99499SAndroid Build Coastguard Workerstruct Point { int x, y, z; };
118*dbb99499SAndroid Build Coastguard Worker
119*dbb99499SAndroid Build Coastguard Worker// CHECK-LABEL: test_store_point:
120*dbb99499SAndroid Build Coastguard Workerextern "C" void test_store_point() {
121*dbb99499SAndroid Build Coastguard Worker    Point p{ExternInt, ExternInt, ExternInt};
122*dbb99499SAndroid Build Coastguard Worker    benchmark::DoNotOptimize(p);
123*dbb99499SAndroid Build Coastguard Worker
124*dbb99499SAndroid Build Coastguard Worker    // CHECK: movl ExternInt(%rip), %eax
125*dbb99499SAndroid Build Coastguard Worker    // CHECK: movl %eax, -{{[0-9]+}}(%rsp)
126*dbb99499SAndroid Build Coastguard Worker    // CHECK: movl %eax, -{{[0-9]+}}(%rsp)
127*dbb99499SAndroid Build Coastguard Worker    // CHECK: movl %eax, -{{[0-9]+}}(%rsp)
128*dbb99499SAndroid Build Coastguard Worker    // CHECK: ret
129*dbb99499SAndroid Build Coastguard Worker}
130*dbb99499SAndroid Build Coastguard Worker```
131*dbb99499SAndroid Build Coastguard Worker<!-- {% endraw %} -->
132*dbb99499SAndroid Build Coastguard Worker
133*dbb99499SAndroid Build Coastguard Worker## Current Requirements and Limitations
134*dbb99499SAndroid Build Coastguard Worker
135*dbb99499SAndroid Build Coastguard WorkerThe tests require Filecheck to be installed along the `PATH` of the
136*dbb99499SAndroid Build Coastguard Workerbuild machine. Otherwise the tests will be disabled.
137*dbb99499SAndroid Build Coastguard Worker
138*dbb99499SAndroid Build Coastguard WorkerAdditionally, as mentioned in the previous section, codegen tests are
139*dbb99499SAndroid Build Coastguard Workerinherently non-portable. Currently the tests are limited to:
140*dbb99499SAndroid Build Coastguard Worker
141*dbb99499SAndroid Build Coastguard Worker* x86_64 targets.
142*dbb99499SAndroid Build Coastguard Worker* Compiled with GCC or Clang
143*dbb99499SAndroid Build Coastguard Worker
144*dbb99499SAndroid Build Coastguard WorkerFurther work could be done, at least on a limited basis, to extend the
145*dbb99499SAndroid Build Coastguard Workertests to other architectures and compilers (using `CHECK` prefixes).
146*dbb99499SAndroid Build Coastguard Worker
147*dbb99499SAndroid Build Coastguard WorkerFurthermore, the tests fail for builds which specify additional flags
148*dbb99499SAndroid Build Coastguard Workerthat modify code generation, including `--coverage` or `-fsanitize=`.
149*dbb99499SAndroid Build Coastguard Worker
150