Missing coverage instrumentation with trace-pc-guard option

Hi,

I was trying to get a coverage for sanitizers for my library and then+AKA-I have encountered a problem that some calls to+AKAAXwBf-sanitizer+AF8-coverage+AF8-trace+AF8-pc+AF8-guards are missing in several basic blocks. I made a
reduced reprocase for this (reduced.c in attachments) and built+AKA-it with '-gline-tables-only -O0 -fsanitize+AD0-address+AKA--fsanitize-coverage+AD0-trace-pc-guard' flags:

clang -gline-tables-only -O0 -fsanitize+AD0-address+AKA--fsanitize-coverage+AD0-trace-pc-guard -S reduced.c

extern void clobber1(int +ACo-state+AF8-ptr)+ADs
extern void clobber2(int +ACo-state+AF8-ptr)+ADs
extern void clobber3(int +ACo-state+AF8-ptr)+ADs

int foo(char c, int state, int threshold) +AHs
+AKAAoACg-while (state +ADw threshold) +AHs
+AKAAoACgAKAAoA-switch (state) +AHs
+AKAAoACgAKAAoA-case 1:
+AKAAoACgAKAAoACgAKA-clobber1(+ACY-state)+ADs
+AKAAoACgAKAAoACgAKA-if (c +AD0APQ '+ACo') +AHs
+AKAAoACgAKAAoACgAKAAoACg-state+-+-+ADs
+AKAAoACgAKAAoACgAKAAfQ else if (c +AD0APQ '/') +AHs
+AKAAoACgAKAAoACgAKAAoACg-state--+ADsAoACgAKAAoACgAKAAoACgAKAAoACgAKAAoACgAKAAoACgAKAAoACgAKAAoACgAKAAoACgAKAAoAA8AD0APQA9AD0APQA9AD0APQA9AD0APQA9AD0APQ missing+AKAAXwBf-sanitizer+AF8-cov+AF8-trace+AF8-pc+AF8-guard call
+AKAAoACgAKAAoACgAKAAfQ else +AHs
+AKAAoACgAKAAoACgAKAAoACg-clobber1(+ACY-state)+ADs
+AKAAoACgAKAAoACgAKAAoACg-goto out+ADs
+AKAAoACgAKAAoACgAKAAfQ
+AKAAoACgAKAAoACgAKA-clobber2(+ACY-state)+ADs
+AKAAoACgAKAAoACgAKA-break+ADs
+AKAAoACgAKAAoA-case 2:
+AKAAoACgAKAAoACgAKA-clobber3(+ACY-state)+ADs
+AKAAoACgAKAAoACgAKA-break+ADs
+AKAAoACgAKAAoAB9
+AKAAoACgAH0
out:
+AKAAoACg-return state+ADs
+AH0

int main(int argc, char +ACoAKg-argv) +AHs
+AKAAoACg-return foo(argv+AFs-1+AF0AWw-2+AF0, argc +- 4, 255) +AD4 100+ADs
+AH0

After examination of dumped LLVM IR (-print-after-all) I have found that+AKA-there are no calls of +AF8AXw-sanitizer+AF8-coverage+AF8-trace+AF8-pc+AF8-guard in 'if.then6'+AKA-basic block that corresponds to +ACI-else if (c +AD0APQ '/')+ACI
fall through case:

sw.bb:+AKAAoACgAKAAoACgAKAAoACgAKAAoACgAKAAoACgAKAAoACgAKAAoACgAKAAoACgAKAAoACgAKAAoACgAKAAoACgAKAAoACgAKAAoACgAKAAoACgAKAAoAA7 preds +AD0 +ACU-while.body
+AKAAoACg-call void +AEA-clobber1(i32+ACo +ACU-state.addr), +ACE-dbg +ACE-15
+AKAAoACgACU-3 +AD0 load i8, i8+ACo +ACU-c.addr, align 1, +ACE-dbg +ACE-16
+AKAAoACgACU-conv +AD0 sext i8 +ACU-3 to i32, +ACE-dbg +ACE-16
+AKAAoACgACU-cmp1 +AD0 icmp eq i32 +ACU-conv, 42, +ACE-dbg +ACE-17
+AKAAoACg-br i1 +ACU-cmp1, label +ACU-if.then, label +ACU-if.else, +ACE-dbg +ACE-16

if.then:+AKAAoACgAKAAoACgAKAAoACgAKAAoACgAKAAoACgAKAAoACgAKAAoACgAKAAoACgAKAAoACgAKAAoACgAKAAoACgAKAAoACgAKAAoACgAKAAoACgADs preds +AD0 +ACU-sw.bb
+AKAAoACg-call void +AEAAXwBf-sanitizer+AF8-cov+AF8-trace+AF8-pc+AF8-guard(i32+ACo inttoptr (i64 add (i64+AKA-ptrtoint (+AFs-6 x i32+AF0AKg +AEAAXwBf-sancov+AF8-gen+AF8 to i64), i64 8) to i32+ACo)), +ACE-dbg +ACE-18
+AKAAoACg-call void asm sideeffect +ACIAIg, +ACIAIg(), +ACE-dbg +ACE-18
+AKAAoACgACU-4 +AD0 load i32, i32+ACo +ACU-state.addr, align 4, +ACE-dbg +ACE-18
+AKAAoACgACU-inc +AD0 add nsw i32 +ACU-4, 1, +ACE-dbg +ACE-18
+AKAAoACg-store i32 +ACU-inc, i32+ACo +ACU-state.addr, align 4, +ACE-dbg +ACE-18
+AKAAoACg-br label +ACU-if.end8, +ACE-dbg +ACE-19

if.else:+AKAAoACgAKAAoACgAKAAoACgAKAAoACgAKAAoACgAKAAoACgAKAAoACgAKAAoACgAKAAoACgAKAAoACgAKAAoACgAKAAoACgAKAAoACgAKAAoACgADs preds +AD0 +ACU-sw.bb
+AKAAoACgACU-5 +AD0 load i8, i8+ACo +ACU-c.addr, align 1, +ACE-dbg +ACE-20
+AKAAoACgACU-conv3 +AD0 sext i8 +ACU-5 to i32, +ACE-dbg +ACE-20
+AKAAoACgACU-cmp4 +AD0 icmp eq i32 +ACU-conv3, 47, +ACE-dbg +ACE-21
+AKAAoACg-br i1 +ACU-cmp4, label +ACU-if.then6, label +ACU-if.else7, +ACE-dbg +ACE-20

if.then6:+AKAAoACgAKAAoACgAKAAoACgAKAAoACgAKAAoACgAKAAoACgAKAAoACgAKAAoACgAKAAoACgAKAAoACgAKAAoACgAKAAoACgAKAAoACgAKAAoAA7 preds +AD0AoAAl-if.else+AKAAoACgAKAAoACgAKAAPAA9AD0APQA9AD0APQA9 no +AF8AXw-sanitizer+AF8-cov+AF8-trace+AF8-pc+AF8-guard
+AKAAoACgACU-6 +AD0 load i32, i32+ACo +ACU-state.addr, align 4, +ACE-dbg +ACE-22
+AKAAoACgACU-dec +AD0 add nsw i32 +ACU-6, -1, +ACE-dbg +ACE-22
+AKAAoACg-store i32 +ACU-dec, i32+ACo +ACU-state.addr, align 4, +ACE-dbg +ACE-22
+AKAAoACg-br label +ACU-if.end, +ACE-dbg +ACE-23

if.else7:+AKAAoACgAKAAoACgAKAAoACgAKAAoACgAKAAoACgAKAAoACgAKAAoACgAKAAoACgAKAAoACgAKAAoACgAKAAoACgAKAAoACgAKAAoACgAKAAoAA7 preds +AD0 +ACU-if.else
+AKAAoACg-call void +AEAAXwBf-sanitizer+AF8-cov+AF8-trace+AF8-pc+AF8-guard(i32+ACo inttoptr (i64 add (i64+AKA-ptrtoint (+AFs-6 x i32+AF0AKg +AEAAXwBf-sancov+AF8-gen+AF8 to i64), i64 12) to i32+ACo)), +ACE-dbg +ACE-24
+AKAAoACg-call void asm sideeffect +ACIAIg, +ACIAIg(), +ACE-dbg +ACE-24
+AKAAoACg-call void +AEA-clobber1(i32+ACo +ACU-state.addr), +ACE-dbg +ACE-24
+AKAAoACg-br label +ACU-out, +ACE-dbg +ACE-25

if.end:+AKAAoACgAKAAoACgAKAAoACgAKAAoACgAKAAoACgAKAAoACgAKAAoACgAKAAoACgAKAAoACgAKAAoACgAKAAoACgAKAAoACgAKAAoACgAKAAoACgAKAAOw preds +AD0 +ACU-if.then6
+AKAAoACg-br label +ACU-if.end8

if.end8:+AKAAoACgAKAAoACgAKAAoACgAKAAoACgAKAAoACgAKAAoACgAKAAoACgAKAAoACgAKAAoACgAKAAoACgAKAAoACgAKAAoACgAKAAoACgAKAAoACgADs preds +AD0 +ACU-if.end,+AKAAJQ-if.then
+AKAAoACg-call void +AEA-clobber2(i32+ACo +ACU-state.addr), +ACE-dbg +ACE-26
+AKAAoACg-br label +ACU-sw.epilog, +ACE-dbg +ACE-27

But, if I remove the 'goto out' instruction, then+AKA'+AF8AXw-sanitizer+AF8-cov+AF8-trace+AF8-pc+AF8-guard' call appears in all if clauses as+AKA-expected.

Is this an intended behavior or some kind of a bug? And if it's+AKA-intended, how can I deduce a real coverage from these instrumented points?

Thanks,
Dmitriy

reduced.c (623 Bytes)