On 03/14/2017 01:33 PM, Richard Biener wrote: > On Tue, 14 Mar 2017, Martin Liška wrote: > >> On 03/14/2017 11:48 AM, Richard Biener wrote: >>> On Tue, 14 Mar 2017, Martin Liška wrote: >>> >>>> On 03/14/2017 11:30 AM, Richard Biener wrote: >>>>> On Tue, 14 Mar 2017, Martin Liška wrote: >>>>> >>>>>> On 03/14/2017 11:13 AM, Richard Biener wrote: >>>>>>> On Tue, 14 Mar 2017, Martin Liška wrote: >>>>>>> >>>>>>>> On 03/14/2017 10:12 AM, Richard Biener wrote: >>>>>>>>> On Tue, 14 Mar 2017, Martin Liška wrote: >>>>>>>>> >>>>>>>>>> On 03/14/2017 09:13 AM, Richard Biener wrote: >>>>>>>>>>> On Tue, 14 Mar 2017, Martin Liška wrote: >>>>>>>>>>> >>>>>>>>>>>> On 03/13/2017 04:16 PM, Richard Biener wrote: >>>>>>>>>>>>> On Mon, 13 Mar 2017, Martin Liška wrote: >>>>>>>>>>>>> >>>>>>>>>>>>>> On 03/13/2017 02:53 PM, Richard Biener wrote: >>>>>>>>>>>>>>> On Mon, 13 Mar 2017, Martin Liška wrote: >>>>>>>>>>>>>>> >>>>>>>>>>>>>>>> On 03/13/2017 02:01 PM, Richard Biener wrote: >>>>>>>>>>>>>>>>> On Mon, 13 Mar 2017, Richard Biener wrote: >>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>> On Fri, 10 Mar 2017, Martin Liška wrote: >>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>> Hello. >>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>> As briefly discussed in the PR, there are BB that do not >>>>>>>>>>>>>>>>>>> correspond to a real >>>>>>>>>>>>>>>>>>> line in source >>>>>>>>>>>>>>>>>>> code. profile.c emits locations for all BBs that have a >>>>>>>>>>>>>>>>>>> gimple statement >>>>>>>>>>>>>>>>>>> belonging to a line. >>>>>>>>>>>>>>>>>>> I hope these should be marked in gcov utility and not added >>>>>>>>>>>>>>>>>>> in --all-block >>>>>>>>>>>>>>>>>>> mode to counts of lines. >>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>> Patch survives make check RUNTESTFLAGS="gcov.exp". >>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>> Thanks for review and feedback. >>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>> Humm, the patch doesn't seem to change the BBs associated >>>>>>>>>>>>>>>>>> with a line >>>>>>>>>>>>>>>>>> but rather somehow changes how we compute counts (the patch >>>>>>>>>>>>>>>>>> lacks a >>>>>>>>>>>>>>>>>> description of how you arrived at it). I expected the >>>>>>>>>>>>>>>>>> line-to-BB >>>>>>>>>>>>>>>>>> assignment process to be changed (whereever that is...). >>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>> Currently, each basic block must belong to a source line. It's >>>>>>>>>>>>>>>> how gcov >>>>>>>>>>>>>>>> iterates all blocks (via lines). >>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>> Ah, ok, looking at where output_location is called on I see >>>>>>>>>>>>>>>>> we do not >>>>>>>>>>>>>>>>> assign any line to that block. But still why does >>>>>>>>>>>>>>>>> line->has_block (arc->src) return true? >>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>> Good objection! Problematic that 4->5 edge really comes from >>>>>>>>>>>>>>>> the same line. >>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>> <bb 4> [0.00%]: >>>>>>>>>>>>>>>> ret_7 = 111; >>>>>>>>>>>>>>>> PROF_edge_counter_10 = __gcov0.UuT[0]; >>>>>>>>>>>>>>>> PROF_edge_counter_11 = PROF_edge_counter_10 + 1; >>>>>>>>>>>>>>>> __gcov0.UuT[0] = PROF_edge_counter_11; >>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>> <bb 5> [0.00%]: >>>>>>>>>>>>>>>> # ret_1 = PHI <ret_5(3), ret_7(4)> >>>>>>>>>>>>>>>> goto <bb 7>; [0.00%] >>>>>>>>>>>>>>> >>>>>>>>>>>>>>> Yes, but that's basically meaningless, unless not all edges >>>>>>>>>>>>>>> come from the >>>>>>>>>>>>>>> same line? I see nowhere where we'd explicitely assign lines to >>>>>>>>>>>>>>> edges so it must be gcov "reconstructing" this somewhere. >>>>>>>>>>>>>> >>>>>>>>>>>>>> That's why I added the another flag. We stream locations for >>>>>>>>>>>>>> basic blocks via >>>>>>>>>>>>>> 'output_location' function. And assignment blocks to lines >>>>>>>>>>>>>> happens here: >>>>>>>>>>>>>> >>>>>>>>>>>>>> static void >>>>>>>>>>>>>> add_line_counts (coverage_t *coverage, function_t *fn) >>>>>>>>>>>>>> { >>>>>>>>>>>>>> ... >>>>>>>>>>>>>> if (!ix || ix + 1 == fn->num_blocks) >>>>>>>>>>>>>> /* Entry or exit block */; >>>>>>>>>>>>>> else if (flag_all_blocks) >>>>>>>>>>>>>> { >>>>>>>>>>>>>> line_t *block_line = line; >>>>>>>>>>>>>> >>>>>>>>>>>>>> if (!block_line) >>>>>>>>>>>>>> block_line = &sources[fn->src].lines[fn->line]; >>>>>>>>>>>>>> >>>>>>>>>>>>>> block->chain = block_line->u.blocks; >>>>>>>>>>>>>> block_line->u.blocks = block; >>>>>>>>>>>>>> } >>>>>>>>>>>>>> >>>>>>>>>>>>>> where line is always changes when we reach a BB that has a >>>>>>>>>>>>>> source line assigned. Thus it's changed >>>>>>>>>>>>>> for BB 4 and that's why BB 5 is added to same line. >>>>>>>>>>>>> >>>>>>>>>>>>> Ah, so this means we should "clear" the current line for BB 5 in >>>>>>>>>>>>> output_location? At least I don't see how your patch may not >>>>>>>>>>>>> regress >>>>>>>>>>>>> some cases where the line wasn't output as an optimization? >>>>>>>>>>>> >>>>>>>>>>>> The new flag on block is kind of clearing that the BB is >>>>>>>>>>>> artificial and in fact does not >>>>>>>>>>>> belong to the line. I didn't want to do a bigger refactoring how >>>>>>>>>>>> blocks are iterated via lines. >>>>>>>>>>>> >>>>>>>>>>>> Can you be please more specific about such a case? >>>>>>>>>>> >>>>>>>>>>> in profile.c I see >>>>>>>>>>> >>>>>>>>>>> if (name_differs || line_differs) >>>>>>>>>>> { >>>>>>>>>>> if (!*offset) >>>>>>>>>>> { >>>>>>>>>>> *offset = gcov_write_tag (GCOV_TAG_LINES); >>>>>>>>>>> gcov_write_unsigned (bb->index); >>>>>>>>>>> name_differs = line_differs=true; >>>>>>>>>>> } >>>>>>>>>>> >>>>>>>>>>> ... >>>>>>>>>>> >>>>>>>>>>> so if line_differs is false we might not output GCOV_TAG_LINES >>>>>>>>>>> either >>>>>>>>>>> because 1) optimization, less stuff output, 2) the block has no >>>>>>>>>>> line. >>>>>>>>>>> Looks like we can't really distinguish those. >>>>>>>>>> >>>>>>>>>> Agree with that. >>>>>>>>>> >>>>>>>>>>> >>>>>>>>>>> Not sure how on the input side we end up associating a BB with >>>>>>>>>>> a line if nothing was output for it though. >>>>>>>>>>> >>>>>>>>>>> That is, with your change don't we need >>>>>>>>>>> >>>>>>>>>>> Index: gcc/profile.c >>>>>>>>>>> =================================================================== >>>>>>>>>>> --- gcc/profile.c (revision 246082) >>>>>>>>>>> +++ gcc/profile.c (working copy) >>>>>>>>>>> @@ -941,8 +941,6 @@ output_location (char const *file_name, >>>>>>>>>>> name_differs = !prev_file_name || filename_cmp (file_name, >>>>>>>>>>> prev_file_name); >>>>>>>>>>> line_differs = prev_line != line; >>>>>>>>>>> >>>>>>>>>>> - if (name_differs || line_differs) >>>>>>>>>>> - { >>>>>>>>>>> if (!*offset) >>>>>>>>>>> { >>>>>>>>>>> *offset = gcov_write_tag (GCOV_TAG_LINES); >>>>>>>>>>> @@ -950,6 +948,9 @@ output_location (char const *file_name, >>>>>>>>>>> name_differs = line_differs=true; >>>>>>>>>>> } >>>>>>>>>>> >>>>>>>>>>> + if (name_differs || line_differs) >>>>>>>>>>> + { >>>>>>>>>>> + >>>>>>>>>>> /* If this is a new source file, then output the >>>>>>>>>>> file's name to the .bb file. */ >>>>>>>>>>> if (name_differs) >>>>>>>>>>> >>>>>>>>>>> to resolve this ambiguity? That is, _always_ emit GCOV_TAG_LINES >>>>>>>>>>> for a BB? So then a BB w/o GCOV_TAG_LINES does _not_ have any >>>>>>>>>>> lines associated. >>>>>>>>>> >>>>>>>>>> That should revolve it. Let me find and example where we do not emit >>>>>>>>>> GCOV_TAG_LINES jsut because there's not difference in lines. >>>>>>>>> >>>>>>>>> sth like >>>>>>>>> >>>>>>>>> a = b < 1 ? (c < 3 ? d : c); >>>>>>>>> >>>>>>>>> or even >>>>>>>>> >>>>>>>>> if (..) { ... } else { ... } >>>>>>>> >>>>>>>> These samples work, however your patch would break situations like: >>>>>>>> >>>>>>>> 1: 10:int main () >>>>>>>> -: 11:{ >>>>>>>> -: 12: int i; >>>>>>>> -: 13: >>>>>>>> 22: 14: for (i = 0; i < 10; i++) /* count(11) */ >>>>>>>> 10: 15: noop (); /* count(10) */ >>>>>>>> >>>>>>>> where 22 is summed as (1+10+11), which kind of makes sense as it >>>>>>>> contains >>>>>>>> of 3 statements. >>>>>>> >>>>>>> 22 is with my patch or without? I think 22 makes no sense. >>>>>>> >>>>>>> Richard. >>>>>> >>>>>> With your patch. >>>>> >>>>> I see. As said, I have zero (well, now some little ;)) knowledge >>>>> about gcov. >>>> >>>> :) I'll continue twiddling with that because even loop-less construct >>>> like: >>>> >>>> 1: 1:int foo(int b, int c, int d) >>>> -: 2:{ >>>> 5: 3: int a = b < 1 ? (c < 3 ? d : c) : a; >>>> 2: 4: return a; >>>> -: 5:} >>>> >>>> gives bogus output with your patch (which I believe does proper thing). >>> >>> Reading into the code (yes, it really seems it's for caching purposes >>> given we walk BBs in "random" order) I also observe >> >> Huh, yeah. Currently line count is a sum of all basic blocks that are emitted >> by profile.c with GCOV_TAG_LINES. That explains why considered loop has >> count == 11: >> >> /tmp/gcov-1.gcno: block >> 2:`/home/marxin/Programming/gcc/gcc/testsuite/gcc.misc-tests/gcov-1.c':10, 14 >> /tmp/gcov-1.gcno: block >> 4:`/home/marxin/Programming/gcc/gcc/testsuite/gcc.misc-tests/gcov-1.c':14 >> >> where blocks 2 and 4 are: >> >> <bb 2> [0.00%]: >> i_3 = 0; >> goto <bb 4>; [0.00%] >> >> ... >> >> <bb 4> [0.00%]: >> # i_1 = PHI <i_3(2), i_7(3)> >> if (i_1 <= 9) >> goto <bb 3>; [0.00%] >> else >> goto <bb 5>; [0.00%] >> >> The same happens to int a = b < 1 ? (c < 3 ? d : c) : a; >> >> /tmp/gcov2.gcno: block 2:`/tmp/gcov2.c':1, 3 >> >> <bb 2> [0.00%]: >> if (b_3(D) <= 0) >> goto <bb 3>; [0.00%] >> else >> goto <bb 7>; [0.00%] >> >> That showed a caching of locations actually magically handles loops and >> ternary operations. >> I'm still wondering how should be defined line count for a multiple >> statements happening >> on the line? Having that we can find a proper solution. > > It should be number of times the line is _entered_, that is, lineno > changed from something != lineno to lineno. Consider > > foo (); goto baz; lab: bar (); // line 1 > baz: > goto lab; > > should increment line 1 when entering to foo () as well as when > entering through goto lab. but both times just once.
Ah, I see, such explanation works for me. However, the test-case you introduced is broken: -: 1:int a = 0; -: 2: 1: 3:void foo() -: 4:{ 1: 5: a = 1; 1: 6:} -: 7: 1: 8:void bar() -: 9:{ 1: 10: a++; 1: 11:} -: 12: 1: 13:int main() -: 14:{ 1: 15: foo (); goto baz; lab: bar (); -: 16: -: 17: baz: 2: 18: if (a == 1) 1: 19: goto lab; -: 20:} Line 15 should be executed twice. Martin > > Richard. > > >> Martin >> >>> >>> for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi)) >>> { >>> gimple *stmt = gsi_stmt (gsi); >>> if (!RESERVED_LOCATION_P (gimple_location (stmt))) >>> output_location (gimple_filename (stmt), gimple_lineno >>> (stmt), >>> &offset, bb); >>> >>> should use expand_location and then look at the spelling location, >>> otherwise we'll get interesting effects with macro expansion? >>> >>> } >>> >>> Richard. >>> >>>> Martin >>>> >>>> >>>>> >>>>> Richard. >>>>> >>>>>> Martin >>>>>> >>>>>>> >>>>>>>> Martin >>>>>>>> >>>>>>>>> >>>>>>>>> >>>>>>>>>> Martin >>>>>>>>>> >>>>>>>>>>> >>>>>>>>>>> Richard. >>>>>>>>>>> >>>>>>>>>>> >>>>>>>>>>>> Hope Nathan will find time to provide review as he's familiar with >>>>>>>>>>>> content of gcov.c. >>>>>>>>>>>> >>>>>>>>>>>> Martin >>>>>>>>>>>> >>>>>>>>>>>>> >>>>>>>>>>>>> OTOH I don't know much about gcov format. >>>>>>>>>>>>> >>>>>>>>>>>>> Richard. >>>>>>>>>>>>> >>>>>>>>>>>>>> Martin >>>>>>>>>>>>>> >>>>>>>>>>>>>>> >>>>>>>>>>>>>>> Richard. >>>>>>>>>>>>>>> >>>>>>>>>>>>>>>> Martin >>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>> Richard. >>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>> >>>>>>>>>>>>>>> >>>>>>>>>>>>>> >>>>>>>>>>>>>> >>>>>>>>>>>>> >>>>>>>>>>>> >>>>>>>>>>>> >>>>>>>>>>> >>>>>>>>>> >>>>>>>>>> >>>>>>>>> >>>>>>>> >>>>>>>> >>>>>>> >>>>>> >>>>>> >>>>> >>>> >>>> >>> >> >> >