This is an archive of the discontinued LLVM Phabricator instance.

[Coverage] Precise region termination with deferred regions
ClosedPublic

Authored by vsk on Jul 26 2017, 7:07 PM.

Details

Reviewers
arphaman
bogner
Summary

The current coverage implementation doesn't handle region termination
very precisely. Take for example an if statement with a return:

void f() {
  if (true) {
    return; // The `if' body's region is terminated here.
  }
  // This line gets the same coverage as the `if' condition.
}

If the function f is called, the line containing the comment will be
marked as having executed once, which is not correct. (Edit: To clarify,
I meant the second comment.)

The solution here is to create a deferred region after terminating a
region. The deferred region is completed once the start location of the
next statement is known, and is then pushed onto the region stack.
In the cases where it's not possible to complete a deferred region, it
can safely be dropped.

Example output (pre-patch):

Example output (post-patch):

Testing: lit test updates, a stage2 coverage-enabled build of clang

Diff Detail

Event Timeline

vsk created this revision.Jul 26 2017, 7:07 PM
vsk edited the summary of this revision. (Show Details)
arphaman edited edge metadata.Jul 28 2017, 6:11 AM

This is awesome!

I noticed in the sample output that llvm-cov is now forced to print some new region markers because the terminator introduces a new region on the same line, e.g.

|// CHECK-LABEL: _Z10while_loopv:
   88|      1|void while_loop() {
   89|      1|  if (false)
   90|      1|    return; // CHECK: [[@LINE]]:11 -> [[@LINE+2]]:3 = (#0 - #1)
                  ^0    ^1  // Previously, llvm-cov didn't show region markers for this line
   91|      1|

Do you think this can be avoided? Should llvm-cov even try to avoid emitting the region markers? It seems to me that this situation affects just the command-line output of llvm-cov, and region highlighting in HTML won't be impacted by this.

vsk added a comment.EditedJul 28 2017, 10:28 AM

This is awesome!

I noticed in the sample output that llvm-cov is now forced to print some new region markers because the terminator introduces a new region on the same line, e.g.

|// CHECK-LABEL: _Z10while_loopv:
   88|      1|void while_loop() {
   89|      1|  if (false)
   90|      1|    return; // CHECK: [[@LINE]]:11 -> [[@LINE+2]]:3 = (#0 - #1)
                  ^0    ^1  // Previously, llvm-cov didn't show region markers for this line
   91|      1|

Do you think this can be avoided? Should llvm-cov even try to avoid emitting the region markers? It seems to me that this situation affects just the command-line output of llvm-cov, and region highlighting in HTML won't be impacted by this.

Great question! The region highlighting for the html emitter matches exactly with the textual emitter's (edit: *should* match with D36020), so there is an impact. I think we can/should make two general improvements to llvm-cov to address the issue, which would be useful even without this patch. The first (as you brought up) is to stop emitting region markers for segments which start, but do not end, on one line. This fixes an existing annoyance with loops:

for (...; ...; ...) -> { <- This singular curly brace gets a region marker because the body's region starts here. That's a little distracting.

It would also suppress highlighting for deferred regions, removing a visual distraction.

The second improvement would be to to pick better line execution counts. In the sample output that you quoted, you see that the line with the return gets an execution count of 1. What's happening is that llvm-cov picks the maximum execution count from the regions on (or before) the line. The end result is a little weird, because we associate the line execution count with the first region on a line, and we know the "return" is never executed. I have a patch ready to fix this: it corrects a display issue in the existing llvm-cov test suite, and it helps even more with deferred regions enabled (edit: D36014).

arphaman accepted this revision.Aug 1 2017, 9:37 AM

Thanks, it does make sense to update llvm-cov.

LGTM:

lib/CodeGen/CoverageMappingGen.cpp
554

Might be better to use && to avoid extra work.

561

You can use else if here.

This revision is now accepted and ready to land.Aug 1 2017, 9:37 AM
vsk updated this revision to Diff 109142.Aug 1 2017, 10:01 AM
vsk marked 2 inline comments as done.
vsk edited the summary of this revision. (Show Details)

Thanks for the review! I'll hold off on landing this until the llvm-cov changes are in, so that people don't hit the issue where unexpected line execution counts are displayed.

vsk closed this revision.Aug 3 2017, 5:31 PM

Committed in r310010

vsk added a comment.Aug 4 2017, 5:39 PM

Reverted in r310154, because llvm-cov isn't doing a good job of displaying the new regions properly. I'll re-land this after llvm-cov is fixed.