Bug 67937 - gcov gives wrong results when negative counts are involved
Summary: gcov gives wrong results when negative counts are involved
Status: ASSIGNED
Alias: None
Product: gcc
Classification: Unclassified
Component: gcov-profile (show other bugs)
Version: unknown
: P3 normal
Target Milestone: ---
Assignee: Jan Hubicka
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2015-10-12 15:51 UTC by Joshua Cranmer
Modified: 2018-02-25 12:05 UTC (History)
3 users (show)

See Also:
Host:
Target:
Build:
Known to work:
Known to fail:
Last reconfirmed: 2016-05-20 00:00:00


Attachments
test-case.gcda (105 bytes, application/octet-stream)
2015-10-12 15:53 UTC, Joshua Cranmer
Details
test-case.gcno (515 bytes, application/octet-stream)
2015-10-12 15:56 UTC, Joshua Cranmer
Details

Note You need to log in before you can comment on or make changes to this bug.
Description Joshua Cranmer 2015-10-12 15:51:30 UTC
This is hard to name correctly, since there's really a bigger bug here, and I'm focusing on the lesser bug because it's easier for me to build a minimized test case.

First the explanation: for whatever reason, sometimes gcov produces counts with negative edges (that's a bug by itself). An minimized example of such a case will be attached to the bug. In this scenario, the graph looks like this:

     1147 +-+ -42
   /----->|B|------\
  +-+     +-+     +-+
/>|A|      V 1189 |D| \
| +-+     +-+     +-+ |
|  \----->|C|------/  |
\     0   +-+ 1189    /
 \-------------------/
          23

(This is a result of an optimized loop, I don't have the corresponding code on hand, sorry :-( ).

In this scenario, the loop detection code finds the following loops:
D -> A -> B -> C -> D: loop count = 23
D -> A -> B -> D: loop count = -42
D -> A -> C -> D: loop count = 0
A -> B -> C -> D -> A: loop count = 42
A -> B -> D -> A: loop count = 0
B -> C -> D -> A -> B: loop count = 0
C -> D -> A -> B -> C: loop count = 0

The last four loops are finding permutations of the three simple loops, which is wrong (of course, the fact that one edge has a count of -42 in the first place is wrong in the first place.
Comment 1 Joshua Cranmer 2015-10-12 15:53:40 UTC
Created attachment 36485 [details]
test-case.gcda

(It's a 4.7 test case, but the file format can still be read with trunk gcov the last I checked. Since the originating issue comes from "compile Firefox", I haven't tried preparing .gcda/.gcno files from newer gcc).
Comment 2 Joshua Cranmer 2015-10-12 15:56:34 UTC
Created attachment 36486 [details]
test-case.gcno

And the corresponding .gcno file.

The testcase was minimized by bisecting the original .gcda/.gcno files by dropping functions and seeing where my attempt to write a new implementation that matched gcov's output failed. The attempt (I did several!) that failed this time was using Boost graph library's hawick_circuits detector, which matched the input incorrectly since this is double-counting loop edges if one of them is negative.
Comment 3 Richard Biener 2015-10-13 09:35:49 UTC
Most interesting would be a C testcase that produces the CFG with the bogus counters ;)
Comment 4 Joshua Cranmer 2015-10-13 14:43:29 UTC
(In reply to Richard Biener from comment #3)
> Most interesting would be a C testcase that produces the CFG with the bogus
> counters ;)

Yeah, I know, but doing the minimization on a 5MLOC program takes time.
Comment 5 Jan Hubicka 2016-05-20 14:40:53 UTC
I will take a look.
Comment 6 Jan Hubicka 2016-05-20 14:43:35 UTC
We can have negative counters on fake edges in case the code uses abnormal edges that we can't instrument correctly.  setjmp/longjmp is one of examples.  If you profile kernel, you will have inconsistencies in profile because of race conditions.