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