Hello,
I have few questions about coverage.
Is there any user-facing documentation for clang’s “-coverage” flag?
The coverage instrumentation seems to happen before asan, and so if asan is also enabled
asan will instrument accesses to @__llvm_gcov_ctr.
This is undesirable and so we’d like to skip these accesses.
Looks like GEP around @__llvm_gcov_ctr have special metadata attached:
%2 = getelementptr inbounds [4 x i64]* @__llvm_gcov_ctr, i64 0, i64 %1
%3 = load i64* %2, align 8
%4 = add i64 %3, 1
store i64 %4, i64* %2, align 8
…
!1 = metadata !{…; [ DW_TAG_compile_unit ] … /home/kcc/tmp/cond.cc] [DW_LANG_C_plus_plus]
Can we rely on having this metadata attached to @__llvm_gcov_ctr?
Should we attach some metadata to the actual accesses as well, or simply find the corresponding GEP?
Finally, does anyone have performance numbers for coverage?
As of today it seems completely thread-hostile since __llvm_gcov_ctr is not thread-local.
A simple stress test shows that coverage slows down by 50x!
% cat ~/tmp/coverage_mt.cc
#include <pthread.h>
__thread int x;
attribute((noinline))
void foo() {
x++;
}
void *Thread(void *) {
for (int i = 0; i < 100000000; i++)
foo();
return 0;
}
int main() {
static const int kNumThreads = 16;
pthread_t t[kNumThreads];
for (int i = 0; i < kNumThreads; i++)
pthread_create(&t[i], 0, Thread, 0);
for (int i = 0; i < kNumThreads; i++)
pthread_join(t[i], 0);
return 0;
}
% clang -O2 ~/tmp/coverage_mt.cc -lpthread ; time ./a.out
TIME: real: 0.284; user: 3.560; system: 0.000
% clang -O2 ~/tmp/coverage_mt.cc -lpthread -coverage ; time ./a.out
TIME: real: 13.327; user: 174.510; system: 0.000
Any principal objections against making __llvm_gcov_ctr thread-local, perhaps under a flag?
If anyone is curious, my intent is to enable running coverage and asan in one process.
Thanks,
–kcc