This is an archive of the discontinued LLVM Phabricator instance.

[Coverage] Take filenames into account when loading function records.
ClosedPublic

Authored by Dor1s on May 4 2018, 2:24 PM.

Details

Summary

Don't skip functions with the same name but from different files.

That change makes it possible to generate code coverage reports from
different binaries compiled from different sources even if there are functions
with non-unique names. Without that change, code coverage for such functions is
missing except of the first function processed.

Diff Detail

Repository
rL LLVM

Event Timeline

Dor1s created this revision.May 4 2018, 2:24 PM
Dor1s added a comment.May 4 2018, 2:25 PM

Please take a look. That doesn't seem to break any tests. If there aren't any concerns, I'll add a test that would pass with this change and would fail without it.

vsk added a comment.May 4 2018, 3:57 PM

No concerns from me, as we appear to deduplicate function records at a lower level (in VersionedCovMapReader).

I'll note that we appear to take this early return a few times while running tests: http://lab.llvm.org:8080/coverage/coverage-reports/llvm/coverage/Users/buildslave/jenkins/workspace/clang-stage2-coverage-R/llvm/lib/ProfileData/Coverage/CoverageMapping.cpp.html#L212

I'd be curious to know which tests trigger the path, and whether they are simply too relaxed?

Dor1s added a comment.May 7 2018, 3:13 PM

Thanks Vedant! The following tests trigger that branch:

LLVM-Unit :: ProfileData/./ProfileDataTests/ParameterizedCovMapTest/CoverageMappingTest.skip_duplicate_function_record/0
LLVM-Unit :: ProfileData/./ProfileDataTests/ParameterizedCovMapTest/CoverageMappingTest.skip_duplicate_function_record/1
LLVM-Unit :: ProfileData/./ProfileDataTests/ParameterizedCovMapTest/CoverageMappingTest.skip_duplicate_function_record/2
LLVM-Unit :: ProfileData/./ProfileDataTests/ParameterizedCovMapTest/CoverageMappingTest.skip_duplicate_function_record/3
LLVM :: tools/llvm-cov/load-multiple-objects.test
LLVM :: tools/llvm-cov/multiple-objects.test
LLVM :: tools/llvm-cov/universal-binary.c

And the first 4 actually fail with my change. Looks like I've tested something wrong previously (I think I did only check-llvm-tools rather then check-llvm), my bad. I'm looking into those tests now to see their purpose.

Dor1s updated this revision to Diff 145566.May 7 2018, 3:22 PM

Added an example of test that would fail without the change and pass with it.

Dor1s added a comment.May 7 2018, 3:24 PM

Well, it doesn't look like skip_duplicate_function_record make a lot of sense...

You're right that other tests might be hardened in order to test that functionality. Please see my update to multiple-objects.test, I think it makes sense. Do you agree?

Dor1s updated this revision to Diff 145568.May 7 2018, 3:31 PM

fix a typo

Dor1s updated this revision to Diff 145571.May 7 2018, 3:36 PM

update skip_duplicate_function_record to reflect a change necessary to fix the issue

Dor1s added a comment.May 7 2018, 3:38 PM

Another option would be to implement loadFunctionRecord in a way that it would pass the updated CoverageMappingTest.cpp test.

vsk added a comment.May 7 2018, 3:40 PM
LLVM-Unit :: ProfileData/./ProfileDataTests/ParameterizedCovMapTest/CoverageMappingTest.skip_duplicate_function_record/0

This test was added in r284251 along with the initial support for loading coverage data from multiple object files. The basic idea behind seems reasonable, as it makes sense to skip records which are exact duplicates. Do you think the duplicate detection could be enhanced by taking filenames and function hashes into account?

Ah, I see your update to the unit test. Yes, I think a version of loadFunctionRecord which satisfies this test would be great.

Dor1s added a comment.May 7 2018, 3:48 PM
In D46478#1090568, @vsk wrote:
LLVM-Unit :: ProfileData/./ProfileDataTests/ParameterizedCovMapTest/CoverageMappingTest.skip_duplicate_function_record/0

This test was added in r284251 along with the initial support for loading coverage data from multiple object files. The basic idea behind seems reasonable, as it makes sense to skip records which are exact duplicates. Do you think the duplicate detection could be enhanced by taking filenames and function hashes into account?

Ah, I see your update to the unit test. Yes, I think a version of loadFunctionRecord which satisfies this test would be great.

Thanks for taking a look. I hope so, but can't figure out a proper way to implement that. Continue looking into that.

vsk added a comment.May 7 2018, 3:50 PM
In D46478#1090568, @vsk wrote:
LLVM-Unit :: ProfileData/./ProfileDataTests/ParameterizedCovMapTest/CoverageMappingTest.skip_duplicate_function_record/0

This test was added in r284251 along with the initial support for loading coverage data from multiple object files. The basic idea behind seems reasonable, as it makes sense to skip records which are exact duplicates. Do you think the duplicate detection could be enhanced by taking filenames and function hashes into account?

Ah, I see your update to the unit test. Yes, I think a version of loadFunctionRecord which satisfies this test would be great.

Thanks for taking a look. I hope so, but can't figure out a proper way to implement that. Continue looking into that.

Maybe you could change the FunctionNames StringSet to some kind of filename-based map.

Dor1s updated this revision to Diff 145700.May 8 2018, 8:54 AM

Added filenames into consideration whether a record should be loaded or skipped

Dor1s added a comment.May 8 2018, 8:57 AM
In D46478#1090589, @vsk wrote:

...
Maybe you could change the FunctionNames StringSet to some kind of filename-based map.

Thanks Vedant, that's a great idea! I haven't realized that FunctionNames isn't used for anything else.

I've updated the change + sophisticated tests a little bit, everything seems to work fine:

$ ninja check-llvm check-clang check-lld check-polly
[139/151] Running polly regression tests
Testing Time: 7.20s
  Expected Passes    : 1018
  Expected Failures  : 24
  Unsupported Tests  : 95
[140/151] Running lld test suite
Testing Time: 2.61s
  Expected Passes    : 1309
  Unsupported Tests  : 330
[143/151] Running the LLVM regression tests
Testing Time: 27.77s
  Expected Passes    : 14856
  Expected Failures  : 49
  Unsupported Tests  : 10501
[150/151] Running the Clang regression tests
llvm-lit: ~/Projects/llvm/llvm/utils/lit/lit/llvm/config.py:334: note: using clang: ~/Projects/llvm/build/bin/clang
Testing Time: 33.98s
  Expected Passes    : 11999
  Expected Failures  : 18
  Unsupported Tests  : 283
Dor1s retitled this revision from [Coverage] Do not skip functions with the same name when loading CoverageMapping. to [Coverage] Take filenames into account when loading function records..May 8 2018, 8:59 AM
Dor1s edited the summary of this revision. (Show Details)
vsk added inline comments.May 8 2018, 10:34 AM
lib/ProfileData/Coverage/CoverageMapping.cpp
224 ↗(On Diff #145700)

Given that this should just be an optimization, it might be cheaper/simpler to use a map from the hash of the record's filenames to a set of stripped function names. This would preserve the proposed behavior where a record which introduces a duplicate symbol in at least one previously-unseen file is still loaded. Wdyt? I imagine something like AlreadyLoaded = !RecordProvenance[hash_combine_range(Record.Filenames)].insert(OrigFuncName).second. Hashing OrigFuncName might decrease the storage requirements even further.

Dor1s updated this revision to Diff 145741.May 8 2018, 11:33 AM

Use hash-based DenseMap for filenames and hash-based DenseSet for function names

Dor1s marked an inline comment as done.May 8 2018, 11:36 AM
Dor1s added inline comments.
lib/ProfileData/Coverage/CoverageMapping.cpp
224 ↗(On Diff #145700)

Thanks for the hints, Vedant! That sounds better to me. Please take a look at the updated CL, what do you think about it?

unittests/ProfileData/CoverageMappingTest.cpp
875 ↗(On Diff #145741)

I've been confused by this behavior at first, but then realized that it's probably right, as this record must be something different than the one previously loaded at line 866

vsk accepted this revision.May 8 2018, 11:37 AM

LGTM, thanks!

include/llvm/ProfileData/Coverage/CoverageMapping.h
36 ↗(On Diff #145741)

Is <map> needed?

This revision is now accepted and ready to land.May 8 2018, 11:37 AM
Dor1s updated this revision to Diff 145757.May 8 2018, 12:27 PM
Dor1s marked 2 inline comments as done.

remove unnecessary header include

include/llvm/ProfileData/Coverage/CoverageMapping.h
36 ↗(On Diff #145741)

Oops, leftover! Removed. Thanks!

Dor1s updated this revision to Diff 145758.May 8 2018, 12:29 PM

remove the header from the proper file

This revision was automatically updated to reflect the committed changes.