[PATCH] D85036: [llvm-cov] reset executation count to 0 after wrapped segment

Vedant Kumar via Phabricator via llvm-commits llvm-commits at lists.llvm.org
Tue Aug 18 11:43:18 PDT 2020


vsk added a comment.

In D85036#2224332 <https://reviews.llvm.org/D85036#2224332>, @zequanwu wrote:

> In D85036#2224279 <https://reviews.llvm.org/D85036#2224279>, @vsk wrote:
>
>> In D85036#2222932 <https://reviews.llvm.org/D85036#2222932>, @zequanwu wrote:
>>
>>> In D85036#2222873 <https://reviews.llvm.org/D85036#2222873>, @vsk wrote:
>>>
>>>> Hi @zequanwu, we've started seeing a regression due to this change in swift (https://ci.swift.org/view/swift-master-next/job/oss-swift-incremental-RA-osx-master-next/7818/consoleText, see the bit about 'coverage_smoke.swift'). Here's the failure we see:
>>>>
>>>>              165:  165| 2| throw CustomError.Err // CHECK-COV: {{ *}}[[@LINE]]|{{ *}}2
>>>>   check:167'0            X~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ error: no match found
>>>>   check:167'1                                                                          with "@LINE" equal to "167"
>>>>   check:167'2                                                                   ?      possible intended match
>>>>              166:  166| 2| } catch {
>>>>   check:167'0     ~~~~~~~~~~~~~~~~~~
>>>>              167:  167| 1| if b { // CHECK-COV: {{ *}}[[@LINE]]|{{ *}}2
>>>>   check:167'0     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
>>>>              168:  168| 1| return 1 // CHECK-COV: {{ *}}[[@LINE]]|{{ *}}1
>>>>   check:167'0     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
>>>>              169:  169| 1| }
>>>>
>>>> The issue is that line 167 ("if b {") has an execution count of 1, even though it's actually reached twice. Before this change, the wrapped count from the catch block starting on line 166 would apply on line 167, all the way through the IfStmt condition (giving an execution count of 2). But with this change, seeing as the IfStmt condition doesn't get its own region, the line execution count gets picked up from the "Then" side of the IfStmt.
>>>>
>>>> I'm concerned that this nested statements generated in clang as well as swift. Do you have some idea about how to address this?
>>>>
>>>> I wonder whether we can make use of gap regions to fix the clang bugs you were looking at. I noticed that this fixed an issue in instrprof-comdat.h, but it's possible that that was caused by a bug in clang that has since been fixed (per the note).
>>>
>>> Hi, I don't know how swift generate the regions. Shouldn't IfStmt gets its own regions covering from `if` keyword to thenStmt? Is that intended not to do so in swift?
>>
>> Thanks for taking a look. Clang and Swift both handle IfStmt in the same way, i.e. they both extend the parent region of the IfStmt through the condition. In clang, this is:
>>
>>   void VisitIfStmt(const IfStmt *S) {
>>     extendRegion(S);
>>     if (S->getInit())
>>       Visit(S->getInit());
>>   
>>     // Extend into the condition before we propagate through it below - this is
>>     // needed to handle macros that generate the "if" but not the condition.
>>     extendRegion(S->getCond());
>>     ...
>>
>> I think this behavior is reasonable (it makes sense to say that the condition of an IfStmt is executed exactly as many times as the parent region containing the IfStmt).
>>
>>> My original thought about this is for one line if there is any new line segment which is start of region, we should ignore the wrapped line segment, and the new line segment count should be the accurate one. Do you have dumping result of segments (`-debug-only=coverage-mapping`) so we can take a deeper look?
>>
>> Right, I thought I was on the same page as you about this. After paging a bit more of this in, I think a problem with ignoring the wrapped line segment is that it must have originated from a region that hasn't actually ended. If a line contains a new start-of-region line segment, it may well begin very late (e.g. at the end of the line), in which case it seems appropriate to consider using the count from the parent region (the wrapped count).
>>
>> Here is the swift example in more detail:
>>
>>   func catchError2(_ b: Bool) -> Int {
>>     do {
>>       throw CustomError.Err // CHECK-COV: {{ *}}[[@LINE]]|{{ *}}2
>>     } catch { // <<< Line 165 >>>
>>       if b {                // CHECK-COV: {{ *}}[[@LINE]]|{{ *}}2
>>         return 1            // CHECK-COV: {{ *}}[[@LINE]]|{{ *}}1
>>       }
>>     }
>>     return 0                // CHECK-COV: {{ *}}[[@LINE]]|{{ *}}1
>>   }
>>   let _ = catchError2(true)
>>   let _ = catchError2(false)
>>   ...
>>   Counter in file 0 165:11 -> 169:4, #1
>>   Counter in file 0 166:10 -> 168:6, #2
>>   Counter in file 0 168:6 -> 169:4, (#1 - #2)
>>   ...
>>     163:6 -> 165:4 (count=2)
>>     165:11 -> 169:4 (count=2)
>>     166:10 -> 168:6 (count=1)
>>     168:6 -> 169:4 (count=1)
>>
>> So, the "catch" on line 165 gets count=2. We then go to line 166 with wrapped-count=2. But we end up applying the start-of-region count on line 166, 166:10 -> 168:6 (count=1), which seems off.
>
> Is it because it's missing the code region for condition `b`? In clang, the condition will have a region with count 2. In the dumping result you given, I don't see that.

I think that explains the difference. Thanks for pointing that out!


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D85036/new/

https://reviews.llvm.org/D85036



More information about the llvm-commits mailing list