[m-rev.] Fix a bug in loop invariant hoisting.

Ralph Becket rafe at cs.mu.OZ.AU
Fri Apr 8 11:42:55 AEST 2005


Estimated hours taken: 3
Branches: main, release

compiler/loop_inv.m:
	Fix a bug in loop invariant hoisting which broke
	tests/valid/loop_inv_bug.  It was hoisting goals that
	constructed variables used as (partially) unique inputs
	elsewhere (this is not allowed because of potential
	clobbering).  Worse, it was not passing the variables in
	question as invariant arguments.

	I've added a comment making explicit the relationship between
	the InvVars and InvGoals variables that must hold for hoisting
	to be sound.

Index: compiler/loop_inv.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/loop_inv.m,v
retrieving revision 1.19
diff -u -r1.19 loop_inv.m
--- compiler/loop_inv.m	24 Mar 2005 05:34:06 -0000	1.19
+++ compiler/loop_inv.m	8 Apr 2005 01:35:58 -0000
@@ -228,6 +228,13 @@
             %
         InvGoals \= []
 
+            % NOTE!  At this point it is vital that
+            % - none of the InvVars are used as (partially) unique
+            % inputs in any goals;
+            % - all of the InvVars are either head vars or constructed
+            % by one of the InvGoals;
+            % - all non-local vars in InvGoals are also in InvVars.
+
       then
 
             % The set of computed invariant vars is the difference
@@ -543,6 +550,10 @@
     % The list returned will not contain duplicate goals judged
     % to be the same by equivalent_goals/2.
     %
+    % We do not hoist goals with unique outputs that are elsewhere
+    % used as unique inputs since the user may clobber the variable
+    % in question.
+    %
 :- pred inv_goals_vars(module_info::in, prog_vars::in,
         hlds_goals::in, hlds_goals::out, prog_vars::in, prog_vars::out) is det.
 
@@ -563,7 +574,8 @@
 inv_goals_vars_2(MI, UUVs, Goal, IGs0, IGs, IVs0, IVs) :-
     ( if
         not invariant_goal(IGs0, Goal),
-        input_args_are_invariant(MI, UUVs, Goal, IVs0)
+        not has_uniquely_used_arg(UUVs, Goal),
+        input_args_are_invariant(MI, Goal, IVs0)
       then
         IGs = [Goal | IGs0],
         IVs = add_outputs(MI, UUVs, Goal, IVs0)
@@ -572,6 +584,15 @@
         IVs = IVs0
     ).
 
+%-----------------------------------------------------------------------------%
+
+:- pred has_uniquely_used_arg(prog_vars::in, hlds_goal::in) is semidet.
+
+has_uniquely_used_arg(UUVs, _GoalExpr - GoalInfo) :-
+    hlds_goal__goal_info_get_nonlocals(GoalInfo, NonLocals),
+    list__member(UUV, UUVs),
+    set__member(UUV, NonLocals).
+
 %------------------------------------------------------------------------------%
 
 :- pred invariant_goal(hlds_goals::in, hlds_goal::in) is semidet.
@@ -582,18 +603,15 @@
 
 %------------------------------------------------------------------------------%
 
-:- pred input_args_are_invariant(module_info::in, prog_vars::in,
-    hlds_goal::in, prog_vars::in) is semidet.
+:- pred input_args_are_invariant(module_info::in, hlds_goal::in, prog_vars::in)
+        is semidet.
 
-input_args_are_invariant(ModuleInfo, UniquelyUsedVars, Goal, InvVars) :-
+input_args_are_invariant(ModuleInfo, Goal, InvVars) :-
     Inputs = goal_inputs(ModuleInfo, Goal),
     all [V] (
         list__member(V, Inputs)
     =>
-        (
-            list__member(V, InvVars),
-            not list__member(V, UniquelyUsedVars)
-        )
+        list__member(V, InvVars)
     ).
 
 %------------------------------------------------------------------------------%
--------------------------------------------------------------------------
mercury-reviews mailing list
post:  mercury-reviews at cs.mu.oz.au
administrative address: owner-mercury-reviews at cs.mu.oz.au
unsubscribe: Address: mercury-reviews-request at cs.mu.oz.au Message: unsubscribe
subscribe:   Address: mercury-reviews-request at cs.mu.oz.au Message: subscribe
--------------------------------------------------------------------------



More information about the reviews mailing list