[m-rev.] diff: Prepare for tail recursion in loop-controled code.

Paul Bone pbone at csse.unimelb.edu.au
Wed Oct 19 12:07:56 AEDT 2011


Prepare to enable tail recursion in loop controlled code.

This patch prevents dep_par_conj.m from inserting get_future goals where they
are not necessary.  These goals where preventing tail recursion in examples
such as map_foldl (not the library predicate, but the one in our paper).

This patch also modifies the loop control scope reason, adding an extra field
that says if the spawned off code may use the parent stack or should setup a
new stack frame.

This patch makes it possible for Zoltan to begin contributing the missing parts
in the code generator.  Meanwhile I will work on the runtime system and the
par_loop_control.m code.

compiler/dep_par_conj.m:
    Don't insert calls to get_future if they're not needed.

    They prevent tail recursion from being possible and are not being optimized
    away.

compiler/hlds_goal.m:
    Add a new field to the loop_control scope reason, lc_use_parent_stack.
    This field is used to tell the code generator if it should generate
    references to the parent stack frame or if it should create a new stack
    frame on the child's stack.

compiler/code_gen.m:
compiler/par_conj_gen.m:
    Pass UseParentStack to the generate_loop_control predicate, and place some
    notes in this predicate about how to handle the different values of
    UseParentStack.

compiler/constraint.m:
compiler/det_analysis.m:
compiler/det_report.m:
compiler/erl_code_gen.m:
compiler/goal_util.m:
compiler/hlds_desc.m:
compiler/hlds_out_goal.m:
compiler/interval.m:
compiler/lambda.m:
compiler/make_hlds_warn.m:
compiler/modecheck_goal.m:
compiler/par_loop_control.m:
compiler/polymorphism.m:
compiler/quantification.m:
compiler/saved_vars.m:
compiler/simplify.m:
compiler/stm_expand.m:
compiler/try_expand.m:
compiler/typecheck.m:
compiler/unique_modes.m:
    Conform to changes in hlds_goal.m

compiler/live_vars.m:
    Conform to changes and make a revisit note about stack slot allocation when
    we don't use the parent's stack frame.

compiler/purity.m:
    Conform to changes and remove a revisit note.

Index: compiler/code_gen.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/code_gen.m,v
retrieving revision 1.187
diff -u -p -b -r1.187 code_gen.m
--- compiler/code_gen.m	9 Oct 2011 09:56:19 -0000	1.187
+++ compiler/code_gen.m	19 Oct 2011 00:56:03 -0000
@@ -266,9 +266,9 @@ generate_goal_expr(GoalExpr, GoalInfo, C
         ( Reason = from_ground_term(TermVar, from_ground_term_construct) ->
             unify_gen.generate_ground_term(TermVar, SubGoal, !CI),
             Code = empty
-        ; Reason = loop_control(LCVar, LCSVar) ->
-            par_conj_gen.generate_loop_control(SubGoal, LCVar, LCSVar, Code,
-                !CI)
+        ; Reason = loop_control(LCVar, LCSVar, UseParentStack) ->
+            par_conj_gen.generate_loop_control(SubGoal, LCVar, LCSVar,
+                UseParentStack, Code, !CI)
         ;
             commit_gen.generate_scope(Reason, CodeModel, GoalInfo,
                 ForwardLiveVarsBeforeGoal, SubGoal, Code, !CI)
Index: compiler/constraint.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/constraint.m,v
retrieving revision 1.104
diff -u -p -b -r1.104 constraint.m
--- compiler/constraint.m	13 Sep 2011 06:07:13 -0000	1.104
+++ compiler/constraint.m	19 Oct 2011 00:56:03 -0000
@@ -174,7 +174,7 @@ propagate_conj_sub_goal_2(hlds_goal(Goal
             ; Reason = commit(_)
             ; Reason = barrier(_)
             ; Reason = trace_goal(_, _, _, _, _)
-            ; Reason = loop_control(_, _)
+            ; Reason = loop_control(_, _, _)
             ),
             % We can't safely propagate constraints into one of these scopes.
             % However, we can propagate constraints inside the scope goal.
Index: compiler/dep_par_conj.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/dep_par_conj.m,v
retrieving revision 1.59
diff -u -p -b -r1.59 dep_par_conj.m
--- compiler/dep_par_conj.m	27 Sep 2011 00:49:24 -0000	1.59
+++ compiler/dep_par_conj.m	19 Oct 2011 00:56:03 -0000
@@ -1754,7 +1754,9 @@ specialize_sequences_in_goal(Goal0, Goal
         GoalExpr0 = conj(ConjType, Goals0),
         (
             ConjType = plain_conj,
-            specialize_sequences_in_conj(Goals0, Goals, !SpecInfo),
+            NonLocals = goal_get_nonlocals(Goal0),
+            specialize_sequences_in_conj(Goals0, Goals, NonLocals,
+                !SpecInfo),
             conj_list_to_goal(Goals, GoalInfo0, Goal)
         ;
             ConjType = parallel_conj,
@@ -1808,22 +1810,22 @@ specialize_sequences_in_goal(Goal0, Goal
     ).
 
 :- pred specialize_sequences_in_conj(list(hlds_goal)::in, list(hlds_goal)::out,
-    spec_info::in, spec_info::out) is det.
+    set_of_progvar::in, spec_info::in, spec_info::out) is det.
 
-specialize_sequences_in_conj(Goals0, Goals, !SpecInfo) :-
+specialize_sequences_in_conj(Goals0, Goals, NonLocals, !SpecInfo) :-
     % For each call goal, look backwards for as many wait calls as possible
     % and forward for as many signal calls as possible. To allow us to look
     % backwards, we maintain a stack of the preceding goals.
-    specialize_sequences_in_conj_2([], Goals0, Goals, !SpecInfo).
+    specialize_sequences_in_conj_2([], Goals0, Goals, NonLocals, !SpecInfo).
 
 :- pred specialize_sequences_in_conj_2(list(hlds_goal)::in,
-    list(hlds_goal)::in, list(hlds_goal)::out, spec_info::in, spec_info::out)
-    is det.
+    list(hlds_goal)::in, list(hlds_goal)::out, set_of_progvar::in,
+    spec_info::in, spec_info::out) is det.
 
 specialize_sequences_in_conj_2(RevGoals, [], list.reverse(RevGoals),
-        !SpecInfo).
+        _, !SpecInfo).
 specialize_sequences_in_conj_2(RevGoals0, [Goal0 | Goals0], Goals,
-        !SpecInfo) :-
+        NonLocals, !SpecInfo) :-
     Goal0 = hlds_goal(GoalExpr0, GoalInfo0),
     (
         GoalExpr0 = plain_call(_, _, _, _, _, _),
@@ -1832,12 +1834,13 @@ specialize_sequences_in_conj_2(RevGoals0
     ->
         CallGoal0 = hlds_goal(GoalExpr0, GoalInfo0),  % dumb mode system
         maybe_specialize_call_and_goals(RevGoals0, CallGoal0, Goals0,
-            RevGoals1, Goals1, !SpecInfo),
-        specialize_sequences_in_conj_2(RevGoals1, Goals1, Goals, !SpecInfo)
+            RevGoals1, Goals1, NonLocals, !SpecInfo),
+        specialize_sequences_in_conj_2(RevGoals1, Goals1, Goals,
+            NonLocals, !SpecInfo)
     ;
         specialize_sequences_in_goal(Goal0, Goal, !SpecInfo),
         specialize_sequences_in_conj_2([Goal | RevGoals0], Goals0, Goals,
-            !SpecInfo)
+            NonLocals, !SpecInfo)
     ).
 
 :- pred specialize_sequences_in_goals(list(hlds_goal)::in, list(hlds_goal)::out,
@@ -1869,10 +1872,10 @@ specialize_sequences_in_cases([Case0 | C
 :- pred maybe_specialize_call_and_goals(list(hlds_goal)::in,
     hlds_goal::in(call_goal), list(hlds_goal)::in,
     list(hlds_goal)::out, list(hlds_goal)::out,
-    spec_info::in, spec_info::out) is det.
+    set_of_progvar::in, spec_info::in, spec_info::out) is det.
 
 maybe_specialize_call_and_goals(RevGoals0, Goal0, FwdGoals0,
-        RevGoals, FwdGoals, !SpecInfo) :-
+        RevGoals, FwdGoals, NonLocals, !SpecInfo) :-
     Goal0 = hlds_goal(GoalExpr0, _),
     GoalExpr0 = plain_call(PredId, ProcId, CallVars, _, _, _),
 
@@ -1947,17 +1950,14 @@ maybe_specialize_call_and_goals(RevGoals
                 MaybeGoal = yes(Goal),
 
                 % After the replaced call may be further references to a
-                % signalled or waited variable.  Add `get' goals after the
-                % transformed goal to make sure the variable is bound.  We
-                % assume the get goals will be simplified away if they turn out
-                % to be unnecessary.
-                %
-                % XXX The simplify pass that comes later doesn't always remove
-                % these calls, even if they're unnecessary.
-
+                % signalled or waited variable.  If so, add `get' goals after
+                % the transformed goal to make sure the variable is bound.
+                PushedPairs = PushedSignalPairs ++ PushedWaitPairs,
+                list.filter(should_add_get_goal(NonLocals, RevGoals1),
+                    PushedPairs, PushedPairsNeedGets),
                 VarTypes = !.SpecInfo ^ spec_vartypes,
                 list.map(make_get_goal(!.SpecInfo ^ spec_module_info, VarTypes),
-                    PushedSignalPairs ++ PushedWaitPairs, GetGoals),
+                    PushedPairsNeedGets, GetGoals),
 
                 RevGoals = GetGoals ++ [Goal] ++ UnPushedWaitGoals ++ RevGoals1,
                 FwdGoals = UnPushedSignalGoals ++ FwdGoals1
@@ -2216,6 +2216,34 @@ number_future_args(ArgNo, [Arg | Args], 
     ),
     number_future_args(ArgNo+1, Args, WaitSignalVars, !RevAcc).
 
+    % should_add_get_goal(NonLocals, FwdGoals, FutureVarPair).
+    %
+    % True the variable wrapped in the FutureVarPair is needed by a another
+    % goal, as indicated by NonLocals (of the conjuction) or FwdGoals (the
+    % remaining goals in the conjunction).
+    %
+:- pred should_add_get_goal(set_of_progvar::in, list(hlds_goal)::in,
+    future_var_pair::in) is semidet.
+
+should_add_get_goal(NonLocals, RevGoals, future_var_pair(_, Var)) :-
+    (
+        % If the variable is in the nonlocals set of the entire conjunction
+        % then we need to add a get goal, because that means that a goal
+        % outside the conjunction also uses the variable.
+        set_of_var.contains(NonLocals, Var)
+    ;
+        % If any of the other goals in the conjunction mention the variable
+        % then we should also add a get_future variable call.  We don't need to
+        % check RevGoals, the only reason the variable might be mentioned there
+        % would be because it was previously partially instantiated.  But since
+        % we're adding a get_future call that does not make sense.  I'm
+        % assuming that only free -> ground instantiation state changes are
+        % allowed for these variables.
+        member(Goal, RevGoals),
+        GoalNonLocals = goal_get_nonlocals(Goal),
+        set_of_var.contains(GoalNonLocals, Var)
+    ).
+
 %-----------------------------------------------------------------------------%
 
 :- pred create_new_spec_parallel_pred(list(arg_pos)::in, pred_proc_id::in,
Index: compiler/det_analysis.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/det_analysis.m,v
retrieving revision 1.235
diff -u -p -b -r1.235 det_analysis.m
--- compiler/det_analysis.m	13 Sep 2011 06:07:13 -0000	1.235
+++ compiler/det_analysis.m	19 Oct 2011 00:56:03 -0000
@@ -1779,7 +1779,7 @@ det_infer_scope(Reason, Goal0, Goal, Goa
             RightFailingContexts, MaybePromiseEqvSolutionSets0,
             Detism, GoalFailingContexts, !DetInfo)
     ;
-        Reason = loop_control(_, _),
+        Reason = loop_control(_, _, _),
         det_infer_goal(Goal0, Goal, InstMap0, SolnContext,
             RightFailingContexts, MaybePromiseEqvSolutionSets0,
             Detism, GoalFailingContexts, !DetInfo),
Index: compiler/det_report.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/det_report.m,v
retrieving revision 1.157
diff -u -p -b -r1.157 det_report.m
--- compiler/det_report.m	13 Sep 2011 06:07:13 -0000	1.157
+++ compiler/det_report.m	19 Oct 2011 00:56:03 -0000
@@ -1129,7 +1129,7 @@ reqscope_check_scope(Reason, SubGoal, Sc
             true
         )
     ;
-        Reason = loop_control(_, _),
+        Reason = loop_control(_, _, _),
         SubGoal = hlds_goal(_, SubGoalInfo),
         Detism = goal_info_get_determinism(SubGoalInfo),
         (
Index: compiler/erl_code_gen.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/erl_code_gen.m,v
retrieving revision 1.42
diff -u -p -b -r1.42 erl_code_gen.m
--- compiler/erl_code_gen.m	13 Sep 2011 06:07:13 -0000	1.42
+++ compiler/erl_code_gen.m	19 Oct 2011 00:56:03 -0000
@@ -631,7 +631,7 @@ erl_gen_goal_expr(GoalExpr, CodeModel, D
             erl_gen_commit(SubGoal, CodeModel, Detism, InstMap, Context,
                 MaybeSuccessExpr, Statement, !Info)
         ;
-            Reason = loop_control(_, _),
+            Reason = loop_control(_, _, _),
             unexpected($module, $pred, "loop_control")
         ;
             Reason = require_detism(_),
Index: compiler/goal_util.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/goal_util.m,v
retrieving revision 1.192
diff -u -p -b -r1.192 goal_util.m
--- compiler/goal_util.m	27 Sep 2011 06:22:47 -0000	1.192
+++ compiler/goal_util.m	19 Oct 2011 00:56:03 -0000
@@ -597,7 +597,7 @@ goal_vars_2(Goal, !Set) :-
             Reason = require_complete_switch(Var),
             set_of_var.insert(Var, !Set)
         ;
-            Reason = loop_control(LCVar, LCSVar),
+            Reason = loop_control(LCVar, LCSVar, _),
             set_of_var.insert(LCVar, !Set),
             set_of_var.insert(LCSVar, !Set)
         ;
Index: compiler/hlds_desc.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/hlds_desc.m,v
retrieving revision 1.9
diff -u -p -b -r1.9 hlds_desc.m
--- compiler/hlds_desc.m	13 Sep 2011 06:07:14 -0000	1.9
+++ compiler/hlds_desc.m	19 Oct 2011 00:56:03 -0000
@@ -157,7 +157,7 @@ describe_goal(ModuleInfo, VarSet, Goal) 
             Reason = trace_goal(_, _, _, _, _),
             Desc = "scope trace goal"
         ;
-            Reason = loop_control(_, _),
+            Reason = loop_control(_, _, _),
             Desc = "scope loop control goal"
         )
     ;
Index: compiler/hlds_goal.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/hlds_goal.m,v
retrieving revision 1.233
diff -u -p -b -r1.233 hlds_goal.m
--- compiler/hlds_goal.m	30 Sep 2011 03:43:32 -0000	1.233
+++ compiler/hlds_goal.m	19 Oct 2011 00:56:03 -0000
@@ -538,7 +538,8 @@
 
     ;       loop_control(
                 lc_lc_var           :: prog_var,
-                lc_lcs_var          :: prog_var
+                lc_lcs_var              :: prog_var,
+                lc_use_parent_stack     :: lc_use_parent_stack
             ).
             % The goal inside the scope will be spawned off because the loop
             % control transformation has been applied to this predicate.
@@ -577,6 +578,10 @@
     --->    is_first_disjunct
     ;       is_not_first_disjunct.
 
+:- type lc_use_parent_stack
+    --->    lc_use_parent_stack_frame
+    ;       lc_create_frame_on_child_stack.
+
 %-----------------------------------------------------------------------------%
 %
 % Information for calls
@@ -2581,10 +2586,10 @@ rename_vars_in_goal_expr(Must, Subn, Exp
             rename_var_list(Must, Subn, QuantVars0, QuantVars),
             Reason = trace_goal(Flag, Grade, Env, Vars, QuantVars)
         ;
-            Reason0 = loop_control(LCVar0, LCSVar0),
+            Reason0 = loop_control(LCVar0, LCSVar0, UseParentStack),
             rename_var(Must, Subn, LCVar0, LCVar),
             rename_var(Must, Subn, LCSVar0, LCSVar),
-            Reason = loop_control(LCVar, LCSVar)
+            Reason = loop_control(LCVar, LCSVar, UseParentStack)
         ),
         rename_vars_in_goal(Must, Subn, Goal0, Goal),
         Expr = scope(Reason, Goal)
@@ -2819,10 +2824,10 @@ incremental_rename_vars_in_goal_expr(Sub
             rename_var_list(need_not_rename, Subn, QuantVars0, QuantVars),
             Reason = trace_goal(Flag, Grade, Env, Vars, QuantVars)
         ;
-            Reason0 = loop_control(LCVar0, LCSVar0),
+            Reason0 = loop_control(LCVar0, LCSVar0, UseParentStack),
             rename_var(need_not_rename, Subn, LCVar0, LCVar),
             rename_var(need_not_rename, Subn, LCSVar0, LCSVar),
-            Reason = loop_control(LCVar, LCSVar)
+            Reason = loop_control(LCVar, LCSVar, UseParentStack)
         ),
         incremental_rename_vars_in_goal(Subn, SubnUpdates, Goal0, Goal),
         Expr = scope(Reason, Goal)
Index: compiler/hlds_out_goal.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/hlds_out_goal.m,v
retrieving revision 1.12
diff -u -p -b -r1.12 hlds_out_goal.m
--- compiler/hlds_out_goal.m	17 Oct 2011 04:31:29 -0000	1.12
+++ compiler/hlds_out_goal.m	19 Oct 2011 00:56:03 -0000
@@ -1975,8 +1975,15 @@ write_goal_scope(Info, GoalExpr, ModuleI
         mercury_output_vars(VarSet, AppendVarNums, QuantVars, !IO),
         io.nl(!IO)
     ;
-        Reason = loop_control(LCVar, LCSVar),
-        io.write_string("loop_control_spawn_off(", !IO),
+        Reason = loop_control(LCVar, LCSVar, UseParentStack),
+        (
+            UseParentStack = lc_use_parent_stack_frame,
+            UseParentStackStr = "using_parent_stack_frame"
+        ;
+            UseParentStack = lc_create_frame_on_child_stack,
+            UseParentStackStr = "using_child_stack"
+        ),
+        io.format("loop_control_spawn_off_%s(", [s(UseParentStackStr)], !IO),
         mercury_output_vars(VarSet, AppendVarNums, [LCVar, LCSVar], !IO),
         io.write_string(") (\n", !IO)
     ),
Index: compiler/interval.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/interval.m,v
retrieving revision 1.54
diff -u -p -b -r1.54 interval.m
--- compiler/interval.m	13 Sep 2011 06:07:14 -0000	1.54
+++ compiler/interval.m	19 Oct 2011 00:56:03 -0000
@@ -962,7 +962,7 @@ record_decisions_in_goal(Goal0, Goal, !V
             ; Reason0 = commit(_)
             ; Reason0 = barrier(_)
             ; Reason0 = trace_goal(_, _, _, _, _)
-            ; Reason0 = loop_control(_, _)
+            ; Reason0 = loop_control(_, _, _)
             ),
             Reason = Reason0
         ),
Index: compiler/lambda.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/lambda.m,v
retrieving revision 1.155
diff -u -p -b -r1.155 lambda.m
--- compiler/lambda.m	30 Sep 2011 03:43:32 -0000	1.155
+++ compiler/lambda.m	19 Oct 2011 00:56:03 -0000
@@ -782,7 +782,7 @@ find_used_vars_in_goal(Goal, !VarUses) :
             Reason = from_ground_term(Var, _),
             mark_var_as_used(Var, !VarUses)
         ;
-            Reason = loop_control(LCVar, LCSVar),
+            Reason = loop_control(LCVar, LCSVar, _),
             mark_var_as_used(LCVar, !VarUses),
             mark_var_as_used(LCSVar, !VarUses)
         ;
Index: compiler/live_vars.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/live_vars.m,v
retrieving revision 1.150
diff -u -p -b -r1.150 live_vars.m
--- compiler/live_vars.m	12 Oct 2011 00:38:19 -0000	1.150
+++ compiler/live_vars.m	19 Oct 2011 00:56:03 -0000
@@ -382,13 +382,19 @@ build_live_sets_in_goal_2(GoalExpr0, Goa
 
             % XXX We could treat from_ground_term_deconstruct scopes specially
             % as well.
-        ; Reason = loop_control(LCVar, LCSVar) ->
+        ; Reason = loop_control(LCVar, LCSVar, _) ->
             % We must handle loop control scopes specially, see the comment for
             % parallel conjunctions above.  Like parallel conjunctions, we need
             % stack slots for the NonLocals, but we also need non-overlapping
             % slots for LC and LCS.
             %
 
+            % XXX: When we use a frame on the child's stack rather than the
+            % parent's we may be able to save fewer variables to the stack at
+            % this time.  This is an optimization for later, not doing it now
+            % will make it easier to generate the code in the spawned off
+            % computation (since it can have the same layout as the parent).
+
             NonLocals = goal_info_get_code_gen_nonlocals(GoalInfo0),
             % Include NonLocals as these need to be on the stack to communicate
             % with the spawned off context,
Index: compiler/make_hlds_warn.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/make_hlds_warn.m,v
retrieving revision 1.43
diff -u -p -b -r1.43 make_hlds_warn.m
--- compiler/make_hlds_warn.m	13 Sep 2011 06:46:03 -0000	1.43
+++ compiler/make_hlds_warn.m	19 Oct 2011 00:56:03 -0000
@@ -252,7 +252,7 @@ warn_singletons_in_goal(Goal, QuantVars,
             warn_singletons_goal_vars([TermVar], GoalInfo, NonLocals,
                 QuantVars, !Info)
         ;
-            Reason = loop_control(_, _),
+            Reason = loop_control(_, _, _),
             % These scopes are introduced only by compiler passes
             % that execute after us.
             sorry($module, $pred, "loop_control")
Index: compiler/modecheck_goal.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/modecheck_goal.m,v
retrieving revision 1.14
diff -u -p -b -r1.14 modecheck_goal.m
--- compiler/modecheck_goal.m	13 Sep 2011 06:46:03 -0000	1.14
+++ compiler/modecheck_goal.m	19 Oct 2011 00:56:03 -0000
@@ -529,7 +529,7 @@ goal_large_flat_constructs(Goal) = Large
             ; Reason = commit(_)
             ; Reason = barrier(_)
             ; Reason = trace_goal(_, _, _, _, _)
-            ; Reason = loop_control(_, _)
+            ; Reason = loop_control(_, _, _)
             ),
             LargeFlatConstructs = set_of_var.init
         )
@@ -606,7 +606,7 @@ set_large_flat_constructs_to_ground_in_g
             ; Reason = commit(_)
             ; Reason = barrier(_)
             ; Reason = trace_goal(_, _, _, _, _)
-            ; Reason = loop_control(_, _)
+            ; Reason = loop_control(_, _, _)
             ),
             Goal = Goal0
         )
@@ -811,7 +811,7 @@ modecheck_goal_scope(Reason, SubGoal0, G
             ; Reason = barrier(_)
             )
         ;
-            Reason = loop_control(LCVar, LCSVar),
+            Reason = loop_control(LCVar, LCSVar, _),
             % We check that the variables for the loop control are ground.
             mode_info_get_instmap(!.ModeInfo, InstMap),
             mode_info_get_module_info(!.ModeInfo, ModuleInfo),
Index: compiler/par_conj_gen.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/par_conj_gen.m,v
retrieving revision 1.49
diff -u -p -b -r1.49 par_conj_gen.m
--- compiler/par_conj_gen.m	17 Oct 2011 04:31:30 -0000	1.49
+++ compiler/par_conj_gen.m	19 Oct 2011 00:56:03 -0000
@@ -101,7 +101,8 @@
     code_model::in, llds_code::out, code_info::in, code_info::out) is det.
 
 :- pred generate_loop_control(hlds_goal::in, prog_var::in, prog_var::in,
-    llds_code::out, code_info::in, code_info::out) is det.
+    lc_use_parent_stack::in, llds_code::out, code_info::in, code_info::out)
+    is det.
 
 %---------------------------------------------------------------------------%
 %---------------------------------------------------------------------------%
@@ -328,16 +329,25 @@ MR_threadscope_post_end_par_conj(&MR_sv(
 
 %-----------------------------------------------------------------------------%
 
-generate_loop_control(Goal, LCVar, LCSVar, Code, !CI) :-
+generate_loop_control(Goal, LCVar, LCSVar, UseParentStack, Code, !CI) :-
     % We don't need to save the parent stack pointer, we do not use it in the
     % main context and all the worker contexts will never have some data that
     % we shouldn't clobber there.
     % We also expect the runtime code to setup the parent stack pointer for us.
 
+    (
+        UseParentStack = lc_use_parent_stack_frame,
     get_known_variables(!.CI, KnownVars),
     NonLocals = goal_info_get_nonlocals(Goal ^ hlds_goal_info),
     InputVars = set_of_var.intersect(NonLocals, list_to_set(KnownVars)),
-    save_variables_on_stack(to_sorted_list(InputVars), SaveCode, !CI),
+        save_variables_on_stack(to_sorted_list(InputVars), SaveCode, !CI)
+    ;
+        UseParentStack = lc_create_frame_on_child_stack,
+        % XXX: Allocate a frame on the child's stack.
+        % Copy the variables to the child's stack.
+        % I'll (Paul) provide C macros in the runtime system for these actions.
+        sorry($module, $pred, "unimplemented")
+    ),
 
     % Create the call to spawn_off.
     remember_position(!.CI, PositionBeforeSpawnOff),
@@ -365,13 +375,20 @@ generate_loop_control(Goal, LCVar, LCSVa
     generate_goal(model_det, Goal, GoalCode, !CI),
     % We expect that the join_and_terminate call is already in Goal.
     SpawnedOffCode0 = LabelCode ++ GoalCode,
-    % Note: Zoltan, Peter and I (Paul) have discussed compressing the stack
-    % frame of the spawned off computation.  This would be _instead of_ using
-    % the parent stack pointer.  TODO: Before we can do this we need to
-    % determine in which loop controls we should use the parent's stack frame,
-    % and then perform this selectively.  The primitives in the runtime system
-    % also need to support this.
-    replace_stack_vars_by_parent_sv(SpawnedOffCode0, SpawnedOffCode),
+
+    (
+        UseParentStack = lc_use_parent_stack_frame,
+        replace_stack_vars_by_parent_sv(SpawnedOffCode0, SpawnedOffCode)
+
+% XXX: Comment back in this case after addressing the one above.  The compiler
+% won't let me include this case if the one above is erroneous.
+%    ;
+%        UseParentStack = lc_create_frame_on_child_stack,
+%
+%        % XXX: We could take this opportunity to remove gaps in the stack
+%        % frame as discussed in our meetings.
+%        sorry($module, $pred, "unimplemented")
+    ),
 
     reset_to_position(PositionAfterSpawnOff, !CI),
 
Index: compiler/par_loop_control.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/par_loop_control.m,v
retrieving revision 1.4
diff -u -p -b -r1.4 par_loop_control.m
--- compiler/par_loop_control.m	18 Oct 2011 01:58:01 -0000	1.4
+++ compiler/par_loop_control.m	19 Oct 2011 00:56:03 -0000
@@ -839,7 +839,9 @@ rewrite_nonrecursive_par_conjuncts(Info,
     % Wrap Conjunct in the loop control scope.
     LCVar = Info ^ lci_lc_var,
     ScopeGoalInfo = ConjunctGoalInfo,
-    ScopeGoalExpr = scope(loop_control(LCVar, LCSVar), Conjunct),
+    % XXX: Which stack frame should this use?
+    ScopeGoalExpr = scope(
+        loop_control(LCVar, LCSVar, lc_use_parent_stack_frame), Conjunct),
     ScopeGoal = hlds_goal(ScopeGoalExpr, ScopeGoalInfo),
 
     rewrite_nonrecursive_par_conjuncts(Info, Conjuncts0, TailGoals,
Index: compiler/polymorphism.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/polymorphism.m,v
retrieving revision 1.370
diff -u -p -b -r1.370 polymorphism.m
--- compiler/polymorphism.m	13 Sep 2011 06:07:14 -0000	1.370
+++ compiler/polymorphism.m	19 Oct 2011 00:56:03 -0000
@@ -1166,7 +1166,7 @@ polymorphism_process_goal_expr(GoalExpr0
                 ; Reason0 = require_complete_switch(_)
                 ; Reason0 = commit(_)
                 ; Reason0 = barrier(_)
-                ; Reason0 = loop_control(_, _)
+                ; Reason0 = loop_control(_, _, _)
                 ),
                 polymorphism_process_goal(SubGoal0, SubGoal, !Info),
                 Reason = Reason0
Index: compiler/purity.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/purity.m,v
retrieving revision 1.149
diff -u -p -b -r1.149 purity.m
--- compiler/purity.m	13 Sep 2011 06:07:14 -0000	1.149
+++ compiler/purity.m	19 Oct 2011 00:56:03 -0000
@@ -689,13 +689,10 @@ compute_expr_purity(GoalExpr0, GoalExpr,
             ContainsTrace = contains_trace_goal,
             Reason = Reason0
         ;
-            % XXX: Revisit this after writing the loop control
-            % transformation, the transformation and primitives will affect
-            % purity and it will be easier to consider what to do here
-            % _after_ that code has been written.
-            Reason0 = loop_control(_, _),
-            sorry($module, $pred,
-                "Revisit purity checking of loop control scopes")
+            % Purity checking happens before the introduction of loop control
+            % scopes.
+            Reason0 = loop_control(_, _, _),
+            unexpected($module, $pred, "loop_control")
         ),
         GoalExpr = scope(Reason, SubGoal)
     ;
Index: compiler/quantification.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/quantification.m,v
retrieving revision 1.149
diff -u -p -b -r1.149 quantification.m
--- compiler/quantification.m	2 Oct 2011 07:51:32 -0000	1.149
+++ compiler/quantification.m	19 Oct 2011 00:56:03 -0000
@@ -731,7 +731,7 @@ implicitly_quantify_goal_quant_info_scop
         ; Reason0 = require_complete_switch(_)
         ; Reason0 = commit(_)
         ; Reason0 = barrier(_)
-        ; Reason0 = loop_control(_, _)
+        ; Reason0 = loop_control(_, _, _)
         ),
         Reason = Reason0,
         goal_expr_vars_bitset(NonLocalsToRecompute, GoalExpr0,
@@ -802,7 +802,7 @@ implicitly_quantify_goal_quant_info_scop
             ; Reason0 = commit(_)
             ; Reason0 = barrier(_)
             ; Reason0 = from_ground_term(_, _)
-            ; Reason0 = loop_control(_, _)
+            ; Reason0 = loop_control(_, _, _)
             ),
             % We shouldn't invoke this predicate for these kinds of scopes.
             unexpected($module, $pred, "unexpected scope")
@@ -1910,7 +1910,7 @@ goal_expr_vars_maybe_lambda_2(NonLocalsT
                 % processed SubGoal, since it should appear in SubGoal.
             )
         ;
-            Reason = loop_control(LCVar, LCSVar),
+            Reason = loop_control(LCVar, LCSVar, _),
             goal_vars_both_maybe_lambda(NonLocalsToRecompute, SubGoal,
                 !:Set, !:LambdaSet),
             set_of_var.insert(LCVar, !Set),
@@ -2068,7 +2068,7 @@ goal_expr_vars_maybe_lambda_and_bi_impl_
             % TermVar should have been put into the relevant sets when we
             % processed SubGoal, since it should appear in SubGoal.
         ;
-            Reason = loop_control(LCVar, LCSVar),
+            Reason = loop_control(LCVar, LCSVar, _),
             goal_vars_both_maybe_lambda_and_bi_impl(SubGoal,
                 !:Set, !:LambdaSet),
             set_of_var.insert(LCVar, !Set),
@@ -2220,7 +2220,7 @@ goal_expr_vars_no_lambda_2(NonLocalsToRe
             % _TermVar should have been put into the relevant sets when we
             % processed SubGoal, since it should appear in SubGoal.
         ;
-            Reason = loop_control(LCVar, LCSVar),
+            Reason = loop_control(LCVar, LCSVar, _),
             goal_vars_both_no_lambda(NonLocalsToRecompute, SubGoal, !:Set),
             set_of_var.insert(LCVar, !Set),
             set_of_var.insert(LCSVar, !Set)
Index: compiler/saved_vars.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/saved_vars.m,v
retrieving revision 1.96
diff -u -p -b -r1.96 saved_vars.m
--- compiler/saved_vars.m	27 Sep 2011 00:49:25 -0000	1.96
+++ compiler/saved_vars.m	19 Oct 2011 00:56:03 -0000
@@ -317,7 +317,7 @@ can_push(Var, Goal) = CanPush :-
                 ; Reason = commit(_)
                 ; Reason = barrier(_)
                 ; Reason = trace_goal(_, _, _, _, _)
-                ; Reason = loop_control(_, _)
+                ; Reason = loop_control(_, _, _)
                 ),
                 CanPush = no
             ;
Index: compiler/simplify.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/simplify.m,v
retrieving revision 1.273
diff -u -p -b -r1.273 simplify.m
--- compiler/simplify.m	13 Oct 2011 00:38:20 -0000	1.273
+++ compiler/simplify.m	19 Oct 2011 00:56:03 -0000
@@ -1978,7 +1978,7 @@ simplify_goal_scope(GoalExpr0, GoalExpr,
                 ; FinalReason = exist_quant(_)
                 ; FinalReason = promise_solutions(_, _)
                 ; FinalReason = barrier(not_removable)
-                ; FinalReason = loop_control(_, _)
+                ; FinalReason = loop_control(_, _, _)
                 ),
                 Goal = Goal1,
                 % Replacing calls, constructions or deconstructions outside
@@ -3796,7 +3796,7 @@ goal_contains_trace(hlds_goal(GoalExpr0,
             ; Reason = require_complete_switch(_)
             ; Reason = commit(_)
             ; Reason = barrier(_)
-            ; Reason = loop_control(_, _)
+            ; Reason = loop_control(_, _, _)
             ),
             goal_contains_trace(SubGoal0, SubGoal, ContainsTrace)
         ),
Index: compiler/stm_expand.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/stm_expand.m,v
retrieving revision 1.25
diff -u -p -b -r1.25 stm_expand.m
--- compiler/stm_expand.m	13 Sep 2011 06:07:14 -0000	1.25
+++ compiler/stm_expand.m	19 Oct 2011 00:56:03 -0000
@@ -354,7 +354,7 @@ stm_process_goal(Instmap, Goal0, Goal, !
             ; Reason = commit(_)
             ; Reason = barrier(_)
             ; Reason = trace_goal(_, _, _, _, _)
-            ; Reason = loop_control(_, _)
+            ; Reason = loop_control(_, _, _)
             ),
             stm_process_goal(Instmap, InnerGoal0, InnerGoal, !Info),
             GoalExpr = scope(Reason, InnerGoal),
Index: compiler/try_expand.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/try_expand.m,v
retrieving revision 1.20
diff -u -p -b -r1.20 try_expand.m
--- compiler/try_expand.m	13 Sep 2011 06:07:14 -0000	1.20
+++ compiler/try_expand.m	19 Oct 2011 00:56:03 -0000
@@ -386,7 +386,7 @@ expand_try_goals_in_goal(Instmap, Goal0,
             ; Reason = from_ground_term(_, from_ground_term_deconstruct)
             ; Reason = from_ground_term(_, from_ground_term_other)
             ; Reason = trace_goal(_, _, _, _, _)
-            ; Reason = loop_control(_, _)
+            ; Reason = loop_control(_, _, _)
             ),
             expand_try_goals_in_goal(Instmap, InnerGoal0, InnerGoal, !Info),
             GoalExpr = scope(Reason, InnerGoal),
Index: compiler/typecheck.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/typecheck.m,v
retrieving revision 1.463
diff -u -p -b -r1.463 typecheck.m
--- compiler/typecheck.m	13 Sep 2011 06:07:15 -0000	1.463
+++ compiler/typecheck.m	19 Oct 2011 00:56:03 -0000
@@ -1291,7 +1291,7 @@ typecheck_goal_2(GoalExpr0, GoalExpr, Go
             ;
                 % These variables are introduced by the compiler and may
                 % only have a single, specific type.
-                Reason = loop_control(LCVar, LCSVar),
+                Reason = loop_control(LCVar, LCSVar, _),
                 Vars = [LCVar, LCSVar]
             ),
             ensure_vars_have_a_type(Vars, !Info)
Index: compiler/unique_modes.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/unique_modes.m,v
retrieving revision 1.141
diff -u -p -b -r1.141 unique_modes.m
--- compiler/unique_modes.m	13 Sep 2011 06:07:15 -0000	1.141
+++ compiler/unique_modes.m	19 Oct 2011 00:56:03 -0000
@@ -567,7 +567,7 @@ unique_modes_check_goal_scope(Reason, Su
         ; Reason = require_complete_switch(_)
         ; Reason = commit(_)
         ; Reason = barrier(_)
-        ; Reason = loop_control(_, _)
+        ; Reason = loop_control(_, _, _)
         ),
         mode_checkpoint(enter, "scope", !ModeInfo),
         unique_modes_check_goal(SubGoal0, SubGoal, !ModeInfo),
-------------- 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/20111019/f8e2760d/attachment.sig>


More information about the reviews mailing list