[m-rev.] diff: Minor improvment to coverage profiling.

Paul Bone pbone at csse.unimelb.edu.au
Wed May 16 16:30:18 AEST 2012


Minor coverage profiling improvement.

While writing the background section of my thesis I found a case where
coverage profiling can be trivially and obviously improved.  These
changes make this small improvement.  Even though the improvement is
minor, it seems obvious so I'd rather make it so that I don't have to
avoid describing it in the thesis.

In if-then-else expressions with a condition that has at most one
solution the coverage at the beginning of the else branch can be inferred
from the coverage before the ITE and before the then branch.  We can
avoid creating a coverage point at the beginning of the else branch.

I haven't updated the deep profiling version number since a newer
inference tool will happily read older profiles (which means I don't
have to adjust the feedback tests).  However an older tool may not
auto-parallelise a newer profile.

deep_profiler/coverage.m:
    As above.

compiler/coverage_profiling.m:
    Conform with the updates in deep_profiler/coverage.m

    Fix trailing whitespace.

Index: compiler/coverage_profiling.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/compiler/coverage_profiling.m,v
retrieving revision 1.9
diff -u -r1.9 coverage_profiling.m
--- compiler/coverage_profiling.m	13 Feb 2012 00:11:35 -0000	1.9
+++ compiler/coverage_profiling.m	16 May 2012 06:09:49 -0000
@@ -97,7 +97,7 @@
     --->    coverage_profiling_options(
                 % These fields correspond to coverage profiling options that
                 % may be specified on the command line.
-                
+
                 % Use per ProcDynamic coverage rather than per ProcStatic.
                 cpo_dynamic_coverage        :: coverage_data_type,
 
@@ -186,7 +186,7 @@
     coverage_before_known::in, coverage_before_known::out,
     proc_coverage_info::in, proc_coverage_info::out, bool::out) is det.
 
-coverage_prof_second_pass_goal(Goal0, Goal, 
+coverage_prof_second_pass_goal(Goal0, Goal,
         CoverageBeforeKnown, NextCoverageBeforeKnown, !Info, AddedImpurity) :-
     Goal0 = hlds_goal(GoalExpr0, GoalInfo0),
     Detism = goal_info_get_determinism(GoalInfo0),
@@ -669,12 +669,39 @@
             CoverageKnownBeforeThen0 = coverage_before_known,
             InsertCPThen = no
         ),
-        % Always insert a coverage point for the else branch.
+        CoverageKnownBeforeThen = coverage_before_known,
+
         ElseId = goal_info_get_goal_id(Else0 ^ hlds_goal_info),
         ElsePath = goal_id_to_reverse_path(ContainingGoalMap, ElseId),
-        InsertCPElse = yes(coverage_point_info(ElsePath, cp_type_branch_arm)),
-        CoverageKnownBeforeThen = coverage_before_known,
-        CoverageKnownBeforeElse = coverage_before_known
+        CondDetism = goal_info_get_determinism(Cond ^ hlds_goal_info),
+        determinism_components(CondDetism, _, CondSolns),
+        (
+            CondSolns = at_most_many,
+
+            % Always insert a coverage point for the else branch.
+            InsertCPElse = yes(coverage_point_info(ElsePath,
+                cp_type_branch_arm)),
+            CoverageKnownBeforeElse = coverage_before_known
+        ;
+            ( CondSolns = at_most_zero
+            ; CondSolns = at_most_one
+            ; CondSolns = at_most_many_cc
+            ),
+
+            % Only insert a coverage point if we cannot infer the coverage
+            % from before the ITE and before the then branch.
+            (
+                CoverageBeforeITEKnown = coverage_before_known,
+                CoverageKnownBeforeThen = coverage_before_known
+            ->
+                InsertCPElse = no,
+                CoverageKnownBeforeElse = coverage_before_known
+            ;
+                InsertCPElse = yes(coverage_point_info(ElsePath,
+                    cp_type_branch_arm)),
+                CoverageKnownBeforeElse = coverage_before_known
+            )
+        )
     ;
         % Don't insert any coverage points.
         InsertCPThen = no,
@@ -1214,7 +1241,7 @@
 
     % Returns a string containing the Low Level C code for a coverage point.
     %
-:- pred coverage_point_ll_code(coverage_data_type::in, 
+:- pred coverage_point_ll_code(coverage_data_type::in,
     pragma_foreign_proc_attributes::out, pragma_foreign_code_impl::out) is det.
 
 coverage_point_ll_code(CoverageDataType, ForeignProcAttrs, ForeignCodeImpl) :-
@@ -1239,7 +1266,7 @@
 
 :- func coverage_point_ll_code(coverage_data_type) = string.
 
-coverage_point_ll_code(static_coverage_data) = 
+coverage_point_ll_code(static_coverage_data) =
     % The code of this predicate is duplicated bodily in profiling_builtin.m
     % in the library directory, so any changes here should also be made there.
 "
@@ -1275,7 +1302,7 @@
 #endif /* MR_DEEP_PROFILING_COVERAGE_STATIC */
 ".
 
-coverage_point_ll_code(dynamic_coverage_data) = 
+coverage_point_ll_code(dynamic_coverage_data) =
     % The code of this predicate is duplicated bodily in profiling_builtin.m
     % in the library directory, so any changes here should also be made there.
 "
@@ -1288,7 +1315,7 @@
   #ifdef MR_DEEP_PROFILING_LOWLEVEL_DEBUG
     if (MR_calldebug && MR_lld_print_enabled) {
         MR_print_deep_prof_vars(stdout, ""increment_coverage_point_count"");
-        printf("", CallSiteDynamic: 0x%x, CPIndex: %d\\n"", 
+        printf("", CallSiteDynamic: 0x%x, CPIndex: %d\\n"",
             MR_current_call_site_dynamic, CPIndex);
     }
   #endif
Index: deep_profiler/coverage.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/deep_profiler/coverage.m,v
retrieving revision 1.16
diff -u -r1.16 coverage.m
--- deep_profiler/coverage.m	3 May 2011 04:35:00 -0000	1.16
+++ deep_profiler/coverage.m	16 May 2012 06:09:49 -0000
@@ -635,14 +635,46 @@
         RevThenGoalPath = map.lookup(GoalPathMap, Then ^ goal_annotation),
         get_branch_start_coverage(Info, RevThenGoalPath, BeforeThen)
     ),
-    % XXX It should be possible, if the condition is not at_most_many and does
-    % not throw exceptions, to compute BeforeElse as the difference between the
-    % counts in the initial value of !.Before and AfterCond, if both are known.
-    % check_ite_coverage already knows the relationship.  Using exception
-    % counts on call goals and propagating them through the coverage annotation
-    % algorithms can solve this.
-    RevElseGoalPath = map.lookup(GoalPathMap, Else ^ goal_annotation),
-    get_branch_start_coverage(Info, RevElseGoalPath, BeforeElse),
+
+    CondSolns = detism_get_solutions(CondDetism),
+    (
+        CondSolns = at_most_many_rep,
+        RevElseGoalPath = map.lookup(GoalPathMap, Else ^ goal_annotation),
+        get_branch_start_coverage(Info, RevElseGoalPath, BeforeElse)
+    ;
+        ( CondSolns = at_most_one_rep
+        ; CondSolns = at_most_zero_rep
+        ),
+        % Assumeing that Cond never throws an exception and we know the
+        % coverage before the ite and at the beginning of Then, then the
+        % coverage at the beginning of Else can be inferred.
+        (
+            (
+                BeforeThen = before_known(BeforeThenCount)
+            ;
+                BeforeThen = before_zero,
+                BeforeThenCount = 0
+            ),
+            (
+                (
+                    Before = before_known(BeforeCount)
+                ;
+                    Before = before_zero,
+                    BeforeCount = 0
+                ),
+                BeforeElse = before_coverage(BeforeCount - BeforeThenCount)
+            ;
+                Before = before_unknown,
+                RevElseGoalPath = map.lookup(GoalPathMap,
+                    Else ^ goal_annotation),
+                get_branch_start_coverage(Info, RevElseGoalPath, BeforeElse)
+            )
+        ;
+            BeforeThen = before_unknown,
+            RevElseGoalPath = map.lookup(GoalPathMap, Else ^ goal_annotation),
+            get_branch_start_coverage(Info, RevElseGoalPath, BeforeElse)
+        )
+    ),
 
     trace [compile_time(flag("debug_coverage_propagation")), io(!IO)] (
         io.format("ITE Coverage inferred before then and else branches:\n" ++
Index: mdbcomp/feedback.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/mdbcomp/feedback.m,v
retrieving revision 1.25
diff -u -r1.25 feedback.m
--- mdbcomp/feedback.m	3 May 2011 04:35:01 -0000	1.25
+++ mdbcomp/feedback.m	16 May 2012 06:09:49 -0000
@@ -532,7 +532,7 @@
 
 :- func feedback_version = string.
 
-feedback_version = "18".
+feedback_version = "19".
 
 %-----------------------------------------------------------------------------%
 :- end_module mdbcomp.feedback.
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 490 bytes
Desc: Digital signature
URL: <http://lists.mercurylang.org/archives/reviews/attachments/20120516/c67e25da/attachment.sig>


More information about the reviews mailing list