From 5fe0f4f82c1b43f94da9dd9da4fb6c0a77f3d25e Mon Sep 17 00:00:00 2001 From: Fergus Henderson Date: Tue, 29 Oct 1996 20:10:17 +0000 Subject: [PATCH] A bunch of changes required to fix problems in code generation for Estimated hours taken: 24 A bunch of changes required to fix problems in code generation for model_det and model_semi disjunctions. simplify.m: Don't convert all model_det and model_semi disjunctions into if-then-elses, because that doesn't work if the disjuncts have output variables, which can happen (e.g. with cc_nondet disjunctions) disj_gen.m: Fix a bug in the code generation for semidet disjunctions: don't forget to jump to the end of the disjunction after each disjunct! liveness.m, live_vars.m, store_alloc.m, disj_gen.m: Treat backtracking in model_det and model_semi disjunctions as shallow backtracking rather than deep backtracking. This means that rather than pushing all live variables onto the stack at the start of a model_det/semi disjunction, and using the nondet_lives to keep track of them, we instead treat these disjunctions a bit more like an if-then-else and use the ordinary liveness/deadness to keep track of them. code_aux.m: Change code_aux__pre_goal_update so that it only applies the post-deaths if the goal is atomic. Applying the *post*-deaths to the set of live variables in the *pre*-goal update only makes sense for atomic goals. (I think previously we only ever generated post-deaths for atomic goals, but now we generate them also for goals inside model_det or model_semi disjunctions.) code_gen.pp, middle_rec.m: Pass an is-atomic flag to code_aux__pre_goal_update. hlds_goal.m: Add some comments. goal_util.m: Fix bugs in goal_util__name_apart_goalinfo. It wasn't applying the substitution to all the appropriate fields. code_exprn.m: Improve the error message for one of the internal errors. hlds_out.m: Print the stack slot allocations in the HLDS dump again. --- compiler/code_aux.m | 22 +++-- compiler/code_exprn.m | 5 +- compiler/code_gen.m | 9 +- compiler/disj_gen.m | 18 ++-- compiler/goal_util.m | 19 +++- compiler/hlds_goal.m | 13 ++- compiler/hlds_out.m | 6 +- compiler/live_vars.m | 84 +++++++++--------- compiler/liveness.m | 195 +++++++++++++++++++++++++++-------------- compiler/middle_rec.m | 2 +- compiler/simplify.m | 6 +- compiler/store_alloc.m | 11 ++- 12 files changed, 247 insertions(+), 143 deletions(-) diff --git a/compiler/code_aux.m b/compiler/code_aux.m index 81dc1b546..5d5f00fb1 100644 --- a/compiler/code_aux.m +++ b/compiler/code_aux.m @@ -41,14 +41,15 @@ :- pred code_aux__contains_simple_recursive_call(hlds__goal, code_info, bool). :- mode code_aux__contains_simple_recursive_call(in, in, out) is semidet. - % code_aux__pre_goal_update(GoalInfo, OldCodeInfo, NewCodeInfo) + % code_aux__pre_goal_update(GoalInfo, Atomic, OldCodeInfo, NewCodeInfo) % updates OldCodeInfo to produce NewCodeInfo with the changes % specified by GoalInfo. The components that change are: % - The set of live variables has the predeath set from % GoalInfo removed (by set difference) % - The set of live variable has the prebirth set from GoalInfo % added (set union) - % - The set of live variables has the postdeath set from GoalInfo + % - If (and only if) `Atomic' is yes, then + % the set of live variables has the postdeath set from GoalInfo % removed (by set difference). These variables are removed so % that they do not get saved across calls and positioned where % branched computations join unnecessarily. @@ -58,17 +59,20 @@ % backtracking (and therefore still need to be stored on % the stack) are updated (those in the goal-info replace % the existing set). -:- pred code_aux__pre_goal_update(hlds__goal_info, code_info, code_info). -:- mode code_aux__pre_goal_update(in, in, out) is det. +:- pred code_aux__pre_goal_update(hlds__goal_info, bool, code_info, code_info). +:- mode code_aux__pre_goal_update(in, in, in, out) is det. % code_aux__post_goal_update(GoalInfo, OldCodeInfo, NewCodeInfo) % updates OldCodeInfo to produce NewCodeInfo with the changes described % by GoalInfo. These are: + % - The set of live variables has the postdeath set from GoalInfo + % removed (by set difference). % - The variables that died during the goal are removed from the % exprn_info structure (from the post-death set). % - Variables that became live at the end of the goal (the post- % birth set) are added to the exprn_info structure and to the % set of live variables. + % - The instmap delta is applied to the current instmap. :- pred code_aux__post_goal_update(hlds__goal_info, code_info, code_info). :- mode code_aux__post_goal_update(in, in, out) is det. @@ -207,7 +211,7 @@ code_aux__is_recursive_call(Goal, CodeInfo) :- % Update the code info structure to be consistent % immediately prior to generating a goal -code_aux__pre_goal_update(GoalInfo) --> +code_aux__pre_goal_update(GoalInfo, Atomic) --> { goal_info_nondet_lives(GoalInfo, NondetLives) }, code_info__set_nondet_lives(NondetLives), { goal_info_pre_delta_liveness(GoalInfo, PreDelta) }, @@ -215,8 +219,12 @@ code_aux__pre_goal_update(GoalInfo) --> code_info__update_deadness_info(PreDelta), { PreDelta = _ - PreDeaths }, code_info__make_vars_dead(PreDeaths), - { goal_info_post_delta_liveness(GoalInfo, PostDelta) }, - code_info__update_deadness_info(PostDelta). + ( { Atomic = yes } -> + { goal_info_post_delta_liveness(GoalInfo, PostDelta) }, + code_info__update_deadness_info(PostDelta) + ; + [] + ). % Update the code info structure to be consistent % immediately after generating a goal diff --git a/compiler/code_exprn.m b/compiler/code_exprn.m index d27c8afaa..9b3ce346c 100644 --- a/compiler/code_exprn.m +++ b/compiler/code_exprn.m @@ -1234,10 +1234,9 @@ code_exprn__produce_vars([V | Vs], [V - R | Rest], Code) --> %------------------------------------------------------------------------------% code_exprn__produce_var(Var, Rval, Code) --> - code_exprn__get_vars(Vars0), - { map__lookup(Vars0, Var, Stat0) }, + code_exprn__get_var_status(Var, Stat), ( - { Stat0 = evaled(Rvals) }, + { Stat = evaled(Rvals) }, \+ ( { set__member(RvalX, Rvals) }, { diff --git a/compiler/code_gen.m b/compiler/code_gen.m index f185b0d53..c9818371a 100644 --- a/compiler/code_gen.m +++ b/compiler/code_gen.m @@ -589,7 +589,12 @@ code_gen__generate_forced_goal(Det, Goal, Code) --> code_gen__generate_goal(ContextModel, Goal - GoalInfo, Code) --> % Make any changes to liveness before Goal - code_aux__pre_goal_update(GoalInfo), + { goal_is_atomic(Goal) -> + IsAtomic = yes + ; + IsAtomic = no + }, + code_aux__pre_goal_update(GoalInfo, IsAtomic), code_info__get_instmap(InstMap), ( { InstMap \= unreachable } @@ -1152,7 +1157,7 @@ code_gen__generate_negation(Goal, Code) --> % (special-cased, though it may be) % we need to apply the pre- and post- % updates. - code_aux__pre_goal_update(GoalInfo), + code_aux__pre_goal_update(GoalInfo, yes), code_info__produce_variable(L, Code0, ValA), code_info__produce_variable(R, Code1, ValB), code_aux__post_goal_update(GoalInfo), diff --git a/compiler/disj_gen.m b/compiler/disj_gen.m index 1ac365a7e..75cda88ea 100644 --- a/compiler/disj_gen.m +++ b/compiler/disj_gen.m @@ -74,7 +74,8 @@ disj_gen__generate_det_disj_2([Goal|Goals], EndLabel, Code) --> RestoreAndPopCode), code_gen__generate_forced_goal(GoalModel, Goal, GoalCode), { EndCode = node([label(EndLabel) - "end of det disj"]) }, - { Code = tree(RestoreAndPopCode, tree(GoalCode, EndCode)) } + { Code = tree(RestoreAndPopCode, tree(GoalCode, EndCode)) }, + code_info__remake_with_store_map ; code_info__get_live_variables(VarList), { set__list_to_set(VarList, Vars) }, @@ -96,7 +97,6 @@ disj_gen__generate_det_disj_2([Goal|Goals], EndLabel, Code) --> % we need to use the saved input vars. code_info__slap_code_info(CodeInfo), code_info__restore_failure_cont(RestoreContCode), - code_info__remake_with_call_info, ( { Goals \= [] } -> @@ -123,7 +123,6 @@ disj_gen__generate_semi_disj(Goals, FollowVars, Code) --> :- mode disj_gen__generate_semi_disj_2(in, in, out, in, out) is det. disj_gen__generate_semi_disj_2(Goals, _FollowVars, Code) --> - code_info__generate_nondet_saves(SaveVarsCode), /**** % This heap restore code only works for goals with no output variables. % It wouldn't work for nondet_cc disjuctions in single-solution contexts. @@ -144,8 +143,7 @@ disj_gen__generate_semi_disj_2(Goals, _FollowVars, Code) --> code_info__remake_with_store_map, /* code_info__maybe_restore_hp(RestoreHeap, HPRestoreCode), - { Code = tree(tree(SaveVarsCode, HPSaveCode), - tree(GoalsCode, HPRestoreCode)) }. + { Code = tree(HPSaveCode, tree(GoalsCode, HPRestoreCode)) }. */ code_info__get_globals(Globals), % If we are using constraints, save the current solver state @@ -153,8 +151,7 @@ disj_gen__generate_semi_disj_2(Goals, _FollowVars, Code) --> { globals__lookup_bool_option(Globals, constraints, SaveTicket) }, code_info__maybe_save_ticket(SaveTicket, SaveTicketCode), - { Code = tree(SaveVarsCode, - tree(SaveTicketCode, GoalsCode)) }. + { Code = tree(SaveTicketCode, GoalsCode) }. :- pred disj_gen__generate_semi_cases(list(hlds__goal), label, code_tree, code_info, code_info). @@ -196,12 +193,15 @@ disj_gen__generate_semi_cases([Goal|Goals], EndLabel, GoalsCode) --> % we need to use the saved input vars. code_info__slap_code_info(CodeInfo), code_info__restore_failure_cont(RestoreContCode), - code_info__remake_with_call_info, % generate the rest of the cases. disj_gen__generate_semi_cases(Goals, EndLabel, GoalsCode0), + { SuccCode = node([ + goto(label(EndLabel)) - "Jump to end of semidet disj" + ]) }, { GoalsCode = tree(tree(ModContCode, - tree(RestoreTicketCode, ThisCode)), + tree(RestoreTicketCode, + tree(ThisCode, SuccCode))), tree(RestoreContCode, GoalsCode0)) } ). diff --git a/compiler/goal_util.m b/compiler/goal_util.m index d39249d0b..86d3d5545 100644 --- a/compiler/goal_util.m +++ b/compiler/goal_util.m @@ -352,11 +352,24 @@ goal_util__name_apart_goalinfo(GoalInfo0, Must, Subn, GoalInfo) :- MaybeInstMap0 = reachable(InstMap0) -> goal_util__rename_follow_vars(InstMap0, Must, Subn, InstMap), - MaybeInstMap = reachable(InstMap) + MaybeInstMap = reachable(InstMap), + goal_info_set_instmap_delta(GoalInfo3, MaybeInstMap, GoalInfo4) ; - MaybeInstMap = MaybeInstMap0 + GoalInfo4 = GoalInfo3 ), - goal_info_set_instmap_delta(GoalInfo3, MaybeInstMap, GoalInfo). + + goal_info_nondet_lives(GoalInfo4, NondetLives0), + goal_util__name_apart_set(NondetLives0, Must, Subn, NondetLives), + goal_info_set_nondet_lives(GoalInfo4, NondetLives, GoalInfo5), + + goal_info_cont_lives(GoalInfo5, MaybeContLives0), + ( MaybeContLives0 = yes(ContLives0) -> + goal_util__name_apart_set(ContLives0, Must, Subn, ContLives), + MaybeContLives = yes(ContLives), + goal_info_set_cont_lives(GoalInfo5, MaybeContLives, GoalInfo) + ; + GoalInfo = GoalInfo5 + ). %-----------------------------------------------------------------------------% diff --git a/compiler/hlds_goal.m b/compiler/hlds_goal.m index 56f4bf429..c4ded1943 100644 --- a/compiler/hlds_goal.m +++ b/compiler/hlds_goal.m @@ -334,10 +334,14 @@ :- implementation. + % NB. Don't forget to check goal_util__name_apart_goalinfo + % if this structure is modified. :- type hlds__goal_info ---> goal_info( delta_liveness, % the changes in liveness after goal % (computed by liveness.m) + % NB for atomic goals, the post-deadness + % should be applied _before_ the goal unit, % junk determinism, % the overall determinism of the goal % (computed during determinism analysis) @@ -359,11 +363,10 @@ % For conditions of ite's it is the % set of variables % live after the condition. - % (XXX For disjunctions in det or semidet + % (XXX For disjuncts in model_det or model_semi % disjunctions, it should perhaps be the set of % variables live at the start of the next - % disjunction. But we don't handle them - % yet.) + % disjunct. But we don't handle them yet.) % These are the only kinds of goal that % use this field. % (Computed by store_alloc.m.) @@ -374,7 +377,9 @@ set(var) % The "nondet lives" - % Nondet live variables that may be 'dead' but - % still nondet live. + % still nondet live. In other words, they + % will not be accessed on forwards execution, + % but may be needed on backtracking. % (Computed by liveness.m.) ). diff --git a/compiler/hlds_out.m b/compiler/hlds_out.m index 1d5c4e4b1..5413ac449 100644 --- a/compiler/hlds_out.m +++ b/compiler/hlds_out.m @@ -1514,9 +1514,9 @@ hlds_out__write_proc(Indent, ModuleInfo, PredId, ProcId, ImportStatus, Proc) --> ( { ImportStatus = pseudo_imported, ProcId = 0 } -> [] ; - % { proc_info_call_info(Proc, CallInfo) }, - % hlds_out__write_indent(Indent), - % hlds_out__write_call_info(Indent, CallInfo, VarSet), + { proc_info_call_info(Proc, CallInfo) }, + hlds_out__write_indent(Indent), + hlds_out__write_call_info(Indent, CallInfo, VarSet), hlds_out__write_indent(Indent), { pred_info_get_is_pred_or_func(PredInfo, PredOrFunc) }, hlds_out__write_clause_head(ModuleInfo, PredId, VarSet, diff --git a/compiler/live_vars.m b/compiler/live_vars.m index 3c0c37303..c2f1faf78 100644 --- a/compiler/live_vars.m +++ b/compiler/live_vars.m @@ -42,7 +42,7 @@ detect_live_vars_in_proc(ProcInfo0, ModuleInfo, ProcInfo) :- detect_initial_live_vars(ProcInfo0, ModuleInfo, Liveness0), set__init(LiveSets0), detect_live_vars_in_goal(Goal0, Liveness0, LiveSets0, - CodeModel, ModuleInfo, ProcInfo0, _Liveness, LiveSets), + ModuleInfo, ProcInfo0, _Liveness, LiveSets), graph_colour__group_elements(LiveSets, ColourSets), set__to_sorted_list(ColourSets, ColourList), live_vars__allocate_call_info(ColourList, CodeModel, CallInfo), @@ -57,12 +57,12 @@ detect_live_vars_in_proc(ProcInfo0, ModuleInfo, ProcInfo) :- % delta annotations. :- pred detect_live_vars_in_goal(hlds__goal, - liveness_info, set(set(var)), code_model, module_info, + liveness_info, set(set(var)), module_info, proc_info, liveness_info, set(set(var))). -:- mode detect_live_vars_in_goal(in, in, in, in, in, in, out, out) is det. +:- mode detect_live_vars_in_goal(in, in, in, in, in, out, out) is det. detect_live_vars_in_goal(Goal0 - GoalInfo, Liveness0, - LiveSets0, CodeModel, ModuleInfo, ProcInfo, + LiveSets0, ModuleInfo, ProcInfo, Liveness, LiveSets) :- goal_info_pre_delta_liveness(GoalInfo, PreDelta), PreDelta = PreBirths - PreDeaths, @@ -84,6 +84,7 @@ detect_live_vars_in_goal(Goal0 - GoalInfo, Liveness0, ), goal_info_nondet_lives(GoalInfo, NondetLives), + goal_info_get_code_model(GoalInfo, CodeModel), detect_live_vars_in_goal_2(Goal0, NondetLives, Liveness3, LiveSets0, CodeModel, ModuleInfo, ProcInfo, Liveness4, LiveSets1), @@ -130,52 +131,55 @@ detect_live_vars_in_goal(Goal0 - GoalInfo, Liveness0, :- mode detect_live_vars_in_goal_2(in, in, in, in, in, in, in, out, out) is det. detect_live_vars_in_goal_2(conj(Goals0), _NondetLives, Liveness0, LiveSets0, - CodeModel, ModuleInfo, ProcInfo, Liveness, LiveSets) :- + _CodeModel, ModuleInfo, ProcInfo, Liveness, LiveSets) :- detect_live_vars_in_conj(Goals0, Liveness0, LiveSets0, - CodeModel, ModuleInfo, ProcInfo, Liveness, LiveSets). + ModuleInfo, ProcInfo, Liveness, LiveSets). detect_live_vars_in_goal_2(disj(Goals0, _), NondetLives, Liveness0, LiveSets0, CodeModel, ModuleInfo, ProcInfo, Liveness, LiveSets) :- - + ( CodeModel = model_non -> % All the currently live variables need to be saved - % on the stack at the start of a disjunction, since we + % on the stack at the start of a nondet disjunction, since we % may need them on backtracking. Therefore they need to % be on the stack at the same time, and hence we insert % them as an interference set into LiveSets. - set__union(Liveness0, NondetLives, LiveVars), - set__insert(LiveSets0, LiveVars, LiveSets1), + set__union(Liveness0, NondetLives, LiveVars), + set__insert(LiveSets0, LiveVars, LiveSets1) + ; + LiveSets1 = LiveSets0 + ), detect_live_vars_in_disj(Goals0, Liveness0, LiveSets1, - CodeModel, ModuleInfo, ProcInfo, Liveness, LiveSets). + ModuleInfo, ProcInfo, Liveness, LiveSets). detect_live_vars_in_goal_2(switch(_Var, _Det, Cases0, _), - _NondetLives, Liveness0, LiveSets0, CodeModel, + _NondetLives, Liveness0, LiveSets0, _CodeModel, ModuleInfo, ProcInfo, Liveness, LiveSets) :- detect_live_vars_in_cases(Cases0, Liveness0, LiveSets0, - CodeModel, ModuleInfo, ProcInfo, Liveness, LiveSets). + ModuleInfo, ProcInfo, Liveness, LiveSets). detect_live_vars_in_goal_2(if_then_else(_Vars, Cond0, Then0, Else0, _), - NondetLives, Liveness0, LiveSets0, CodeModel, + NondetLives, Liveness0, LiveSets0, _CodeModel, ModuleInfo, ProcInfo, Liveness, LiveSets) :- set__union(Liveness0, NondetLives, LiveVars), set__insert(LiveSets0, LiveVars, LiveSets0A), detect_live_vars_in_goal(Cond0, Liveness0, LiveSets0A, - CodeModel, ModuleInfo, ProcInfo, Liveness1, LiveSets1), + ModuleInfo, ProcInfo, Liveness1, LiveSets1), detect_live_vars_in_goal(Then0, Liveness1, LiveSets1, - CodeModel, ModuleInfo, ProcInfo, _Liveness2, LiveSets2), + ModuleInfo, ProcInfo, _Liveness2, LiveSets2), detect_live_vars_in_goal(Else0, Liveness0, LiveSets2, - CodeModel, ModuleInfo, ProcInfo, Liveness, LiveSets). + ModuleInfo, ProcInfo, Liveness, LiveSets). detect_live_vars_in_goal_2(not(Goal0), NondetLives, Liveness0, LiveSets0, - CodeModel, ModuleInfo, ProcInfo, Liveness, LiveSets) :- + _CodeModel, ModuleInfo, ProcInfo, Liveness, LiveSets) :- set__union(Liveness0, NondetLives, LiveVars), set__insert(LiveSets0, LiveVars, LiveSets1), detect_live_vars_in_goal(Goal0, Liveness0, LiveSets1, - CodeModel, ModuleInfo, ProcInfo, Liveness, LiveSets). + ModuleInfo, ProcInfo, Liveness, LiveSets). detect_live_vars_in_goal_2(some(_Vs, Goal0), _NondetLives, Liveness0, LiveSets0, - CodeModel, ModuleInfo, ProcInfo, Liveness, LiveSets) :- + _CodeModel, ModuleInfo, ProcInfo, Liveness, LiveSets) :- detect_live_vars_in_goal(Goal0, Liveness0, LiveSets0, - CodeModel, ModuleInfo, ProcInfo, Liveness, LiveSets). + ModuleInfo, ProcInfo, Liveness, LiveSets). detect_live_vars_in_goal_2(higher_order_call(_PredVar, ArgVars, Types, Modes, Det, _Follow), @@ -278,45 +282,45 @@ detect_live_vars_in_goal_2( %-----------------------------------------------------------------------------% :- pred detect_live_vars_in_conj(list(hlds__goal), liveness_info, - set(set(var)), code_model, module_info, proc_info, + set(set(var)), module_info, proc_info, liveness_info, set(set(var))). -:- mode detect_live_vars_in_conj(in, in, in, in, in, in, out, out) is det. +:- mode detect_live_vars_in_conj(in, in, in, in, in, out, out) is det. detect_live_vars_in_conj([], Liveness, LiveVars, - _CodeModel, _ModuleInfo, _ProcInfo, Liveness, LiveVars). + _ModuleInfo, _ProcInfo, Liveness, LiveVars). detect_live_vars_in_conj([Goal0|Goals0], Liveness0, LiveVars0, - CodeModel, ModuleInfo, ProcInfo, Liveness, LiveVars) :- + ModuleInfo, ProcInfo, Liveness, LiveVars) :- ( Goal0 = _ - GoalInfo, goal_info_get_instmap_delta(GoalInfo, unreachable) -> detect_live_vars_in_goal(Goal0, Liveness0, - LiveVars0, CodeModel, ModuleInfo, ProcInfo, + LiveVars0, ModuleInfo, ProcInfo, Liveness, LiveVars) ; detect_live_vars_in_goal(Goal0, Liveness0, - LiveVars0, CodeModel, ModuleInfo, ProcInfo, + LiveVars0, ModuleInfo, ProcInfo, Liveness1, LiveVars1), detect_live_vars_in_conj(Goals0, Liveness1, - LiveVars1, CodeModel, ModuleInfo, ProcInfo, + LiveVars1, ModuleInfo, ProcInfo, Liveness, LiveVars) ). %-----------------------------------------------------------------------------% :- pred detect_live_vars_in_disj(list(hlds__goal), liveness_info, - set(set(var)), code_model, module_info, proc_info, liveness_info, + set(set(var)), module_info, proc_info, liveness_info, set(set(var))). -:- mode detect_live_vars_in_disj(in, in, in, in, in, in, out, out) is det. +:- mode detect_live_vars_in_disj(in, in, in, in, in, out, out) is det. detect_live_vars_in_disj([], Liveness, LiveSets, - _CodeModel, _ModuleInfo, _ProcInfo, Liveness, LiveSets). + _ModuleInfo, _ProcInfo, Liveness, LiveSets). detect_live_vars_in_disj([Goal0|Goals0], Liveness0, LiveSets0, - CodeModel, ModuleInfo, ProcInfo, Liveness, LiveSets) :- + ModuleInfo, ProcInfo, Liveness, LiveSets) :- detect_live_vars_in_goal(Goal0, Liveness0, LiveSets0, - CodeModel,ModuleInfo, ProcInfo, Liveness, LiveSets1), + ModuleInfo, ProcInfo, Liveness, LiveSets1), detect_live_vars_in_disj(Goals0, Liveness0, LiveSets1, - CodeModel, ModuleInfo, ProcInfo, _Liveness2, LiveSets). + ModuleInfo, ProcInfo, _Liveness2, LiveSets). % set__union(Liveness1, Liveness2, Liveness). % This predicate call is unnecessary because the post-deaths and % pre-births sets *should* be taking care of everything. @@ -324,19 +328,19 @@ detect_live_vars_in_disj([Goal0|Goals0], Liveness0, LiveSets0, %-----------------------------------------------------------------------------% :- pred detect_live_vars_in_cases(list(case), liveness_info, - set(set(var)), code_model, module_info, proc_info, + set(set(var)), module_info, proc_info, liveness_info, set(set(var))). -:- mode detect_live_vars_in_cases(in, in, in, in, in, in, out, out) is det. +:- mode detect_live_vars_in_cases(in, in, in, in, in, out, out) is det. detect_live_vars_in_cases([], Liveness, LiveSets, - _CodeModel, _ModuleInfo, _ProcInfo, Liveness, LiveSets). + _ModuleInfo, _ProcInfo, Liveness, LiveSets). detect_live_vars_in_cases([case(_Cons, Goal0)|Goals0], Liveness0, - LiveSets0, CodeModel, ModuleInfo, ProcInfo, + LiveSets0, ModuleInfo, ProcInfo, Liveness, LiveSets) :- detect_live_vars_in_goal(Goal0, Liveness0, LiveSets0, - CodeModel, ModuleInfo, ProcInfo, Liveness, LiveSets1), + ModuleInfo, ProcInfo, Liveness, LiveSets1), detect_live_vars_in_cases(Goals0, Liveness0, LiveSets1, - CodeModel, ModuleInfo, ProcInfo, _Liveness2, LiveSets). + ModuleInfo, ProcInfo, _Liveness2, LiveSets). % set__union(Liveness1, Liveness2, Liveness). % This predicate call is unnecessary because the post-deaths and % pre-births sets *should* be taking care of everything. diff --git a/compiler/liveness.m b/compiler/liveness.m index 017144a4f..defc44277 100644 --- a/compiler/liveness.m +++ b/compiler/liveness.m @@ -88,8 +88,8 @@ detect_liveness_in_goal(Goal0 - GoalInfo0, Liveness0, ModuleInfo, PostDelta = PostDelta0 ; set__init(PreBirths), - detect_liveness_in_goal_2(Goal0, Liveness0, - ModuleInfo, Liveness1, Goal), + detect_liveness_in_goal_2(Goal0, Liveness0, ModuleInfo, + Liveness1, Goal), set__difference(Births, Liveness1, PostBirths), PostDelta = PostBirths - PostDeaths ), @@ -142,7 +142,7 @@ detect_liveness_in_goal_2(disj(Goals0, FV), Liveness0, ModuleInfo, Liveness, disj(Goals, FV)) :- set__init(Union0), detect_liveness_in_disj(Goals0, Liveness0, ModuleInfo, - Union0, Union, Goals), + Union0, Union, Goals), set__union(Liveness0, Union, Liveness). detect_liveness_in_goal_2(not(Goal0), Liveness0, ModuleInfo, @@ -169,8 +169,8 @@ detect_liveness_in_goal_2(if_then_else(Vars, Cond0, Then0, Else0, FV), set__difference(ProducedInElse, ProducedInThen, ResidueThen), set__difference(ProducedInThen, ProducedInElse, ResidueElse), - stuff_liveness_residue_into_goal(Then1, ResidueThen, Then), - stuff_liveness_residue_into_goal(Else1, ResidueElse, Else), + stuff_liveness_residue_after_goal(Then1, ResidueThen, Then), + stuff_liveness_residue_after_goal(Else1, ResidueElse, Else), set__union(LivenessThen, LivenessElse, Liveness). @@ -223,7 +223,7 @@ detect_liveness_in_disj([Goal0|Goals0], Liveness, ModuleInfo, detect_liveness_in_disj(Goals0, Liveness, ModuleInfo, Union1, Union, Goals), set__difference(Union, Liveness1, Residue), - stuff_liveness_residue_into_goal(Goal1, Residue, Goal). + stuff_liveness_residue_after_goal(Goal1, Residue, Goal). %-----------------------------------------------------------------------------% @@ -239,7 +239,7 @@ detect_liveness_in_cases([case(Cons, Goal0)|Goals0], Liveness, ModuleInfo, detect_liveness_in_cases(Goals0, Liveness, ModuleInfo, Union1, Union, Goals), set__difference(Union, Liveness1, Residue), - stuff_liveness_residue_into_goal(Goal1, Residue, Goal). + stuff_liveness_residue_after_goal(Goal1, Residue, Goal). %-----------------------------------------------------------------------------% %-----------------------------------------------------------------------------% @@ -286,8 +286,8 @@ detect_deadness_in_goal(Goal0 - GoalInfo0, Deadness0, ModuleInfo, ProcInfo, Deadness = Deadness_Nonlocals ), set__init(PostDeaths), - detect_deadness_in_goal_2(Goal0, Deadness0, ModuleInfo, - ProcInfo, Deadness1, Goal), + detect_deadness_in_goal_2(Goal0, GoalInfo0, Deadness0, + ModuleInfo, ProcInfo, Deadness1, Goal), set__difference(Deadness, Deadness1, PreDeaths), PreDelta = PreBirths - PreDeaths ), @@ -295,8 +295,8 @@ detect_deadness_in_goal(Goal0 - GoalInfo0, Deadness0, ModuleInfo, ProcInfo, goal_info_set_post_delta_liveness(GoalInfo0, PostDelta, GoalInfo1), goal_info_set_pre_delta_liveness(GoalInfo1, PreDelta, GoalInfo). -:- pred detect_deadness_in_goal(hlds__goal, liveness_info, module_info, - proc_info, hlds__goal). +:- pred detect_deadness_in_goal(hlds__goal, liveness_info, + module_info, proc_info, hlds__goal). :- mode detect_deadness_in_goal(in, in, in, in, out) is det. detect_deadness_in_goal(Goal0, Deadness, ModuleInfo, ProcInfo, Goal) :- @@ -304,28 +304,35 @@ detect_deadness_in_goal(Goal0, Deadness, ModuleInfo, ProcInfo, Goal) :- % Here we process each of the different sorts of goals. -:- pred detect_deadness_in_goal_2(hlds__goal_expr, liveness_info, - module_info, proc_info, liveness_info, hlds__goal_expr). +:- pred detect_deadness_in_goal_2(hlds__goal_expr, hlds__goal_info, + liveness_info, module_info, proc_info, liveness_info, hlds__goal_expr). +:- mode detect_deadness_in_goal_2(in, in, in, in, in, out, out) is det. -:- mode detect_deadness_in_goal_2(in, in, in, in, out, out) is det. -detect_deadness_in_goal_2(conj(Goals0), Deadness0, ModuleInfo, ProcInfo, +detect_deadness_in_goal_2(conj(Goals0), _, Deadness0, ModuleInfo, ProcInfo, Deadness, conj(Goals)) :- detect_deadness_in_conj(Goals0, Deadness0, ModuleInfo, ProcInfo, Goals, Deadness). -detect_deadness_in_goal_2(disj(Goals0, FV), Deadness0, ModuleInfo, ProcInfo, - Deadness, disj(Goals, FV)) :- - set__init(Union0), - detect_deadness_in_disj(Goals0, Deadness0, ModuleInfo, ProcInfo, - Union0, Union, Goals), - set__union(Deadness0, Union, Deadness). +detect_deadness_in_goal_2(disj(Goals0, FV), GoalInfo, Deadness0, ModuleInfo, + ProcInfo, Deadness, disj(Goals, FV)) :- + goal_info_get_code_model(GoalInfo, CodeModel), + ( CodeModel = model_non -> + set__init(Union0), + detect_deadness_in_nondet_disj(Goals0, Deadness0, ModuleInfo, + ProcInfo, Union0, Union, Goals), + set__union(Deadness0, Union, Deadness) + ; + detect_deadness_in_pruned_disj(Goals0, GoalInfo, + Deadness0, ModuleInfo, + ProcInfo, Goals, Deadness) + ). -detect_deadness_in_goal_2(not(Goal0), Deadness0, ModuleInfo, ProcInfo, +detect_deadness_in_goal_2(not(Goal0), _, Deadness0, ModuleInfo, ProcInfo, Deadness, not(Goal)) :- detect_deadness_in_goal(Goal0, Deadness0, ModuleInfo, ProcInfo, Deadness, Goal). -detect_deadness_in_goal_2(if_then_else(Vars, Cond0, Then0, Else0, FV), +detect_deadness_in_goal_2(if_then_else(Vars, Cond0, Then0, Else0, FV), _, Deadness0, ModuleInfo, ProcInfo, Deadness, if_then_else(Vars, Cond, Then, Else, FV)) :- detect_deadness_in_goal(Then0, Deadness0, ModuleInfo, ProcInfo, @@ -336,31 +343,32 @@ detect_deadness_in_goal_2(if_then_else(Vars, Cond0, Then0, Else0, FV), detect_deadness_in_goal(Cond0, DeadnessThenElse, ModuleInfo, ProcInfo, Deadness, Cond), set__difference(DeadnessElse, DeadnessThen, ResidueThen), - stuff_deadness_residue_into_goal(Then1, ResidueThen, Then), + stuff_deadness_residue_before_goal(Then1, ResidueThen, Then), set__difference(DeadnessThen, DeadnessElse, ResidueElse), - stuff_deadness_residue_into_goal(Else1, ResidueElse, Else). + stuff_deadness_residue_before_goal(Else1, ResidueElse, Else). -detect_deadness_in_goal_2(switch(Var, Det, Cases0, FV), Deadness0, ModuleInfo, - ProcInfo, Deadness, switch(Var, Det, Cases, FV)) :- +detect_deadness_in_goal_2(switch(Var, Det, Cases0, FV), _, Deadness0, + ModuleInfo, ProcInfo, Deadness, + switch(Var, Det, Cases, FV)) :- set__init(Union0), detect_deadness_in_cases(Var, Cases0, Deadness0, ModuleInfo, ProcInfo, Union0, Union, Cases), set__union(Deadness0, Union, Deadness). -detect_deadness_in_goal_2(some(Vars, Goal0), Deadness0, ModuleInfo, ProcInfo, - Deadness, some(Vars, Goal)) :- +detect_deadness_in_goal_2(some(Vars, Goal0), _, Deadness0, ModuleInfo, + ProcInfo, Deadness, some(Vars, Goal)) :- detect_deadness_in_goal(Goal0, Deadness0, ModuleInfo, ProcInfo, Deadness, Goal). -detect_deadness_in_goal_2(higher_order_call(A,B,C,D,E,F), Dn, _, _, Dn, +detect_deadness_in_goal_2(higher_order_call(A,B,C,D,E,F), _, Dn, _, _, Dn, higher_order_call(A,B,C,D,E,F)). -detect_deadness_in_goal_2(call(A,B,C,D,E,F,G), Dn, _, _, Dn, +detect_deadness_in_goal_2(call(A,B,C,D,E,F,G), _, Dn, _, _, Dn, call(A,B,C,D,E,F,G)). -detect_deadness_in_goal_2(unify(A,B,C,D,E), Dn, _, _, Dn, unify(A,B,C,D,E)). +detect_deadness_in_goal_2(unify(A,B,C,D,E), _, Dn, _, _, Dn, unify(A,B,C,D,E)). -detect_deadness_in_goal_2(pragma_c_code(A,B,C,D,E,F), Dn, _, _, Dn, +detect_deadness_in_goal_2(pragma_c_code(A,B,C,D,E,F), _, Dn, _, _, Dn, pragma_c_code(A,B,C,D,E,F)). %-----------------------------------------------------------------------------% @@ -388,20 +396,52 @@ detect_deadness_in_conj([Goal0|Goals0], Deadness0, ModuleInfo, ProcInfo, %-----------------------------------------------------------------------------% -:- pred detect_deadness_in_disj(list(hlds__goal), set(var), module_info, - proc_info, set(var), set(var), list(hlds__goal)). -:- mode detect_deadness_in_disj(in, in, in, in, in, out, out) is det. + % for a pruned disj, for simplicity we handle things pretty + % conservatively: we assume that none of the non-local variables + % die until the very end of the disjunction. -detect_deadness_in_disj([], _Deadness, _ModuleInfo, _PInfo, Union, Union, []). -detect_deadness_in_disj([Goal0|Goals0], Deadness, ModuleInfo, ProcInfo, +:- pred detect_deadness_in_pruned_disj(list(hlds__goal), hlds__goal_info, + set(var), module_info, proc_info, list(hlds__goal), set(var)). +:- mode detect_deadness_in_pruned_disj(in, in, in, in, in, out, out) is det. + +detect_deadness_in_pruned_disj(Goals0, GoalInfo, Deadness0, ModuleInfo, + ProcInfo, Goals, Deadness) :- + goal_info_get_nonlocals(GoalInfo, NonLocals), + set__difference(NonLocals, Deadness0, PostDeaths), + set__union(Deadness0, PostDeaths, Deadness), + detect_deadness_in_pruned_disj_2(Goals0, Deadness, PostDeaths, + ModuleInfo, ProcInfo, Goals). + +:- pred detect_deadness_in_pruned_disj_2(list(hlds__goal), set(var), set(var), + module_info, proc_info, list(hlds__goal)). +:- mode detect_deadness_in_pruned_disj_2(in, in, in, in, in, out) is det. + +detect_deadness_in_pruned_disj_2([], _Deadness0, _PostDeaths, + _ModuleInfo, _PInfo, []). +detect_deadness_in_pruned_disj_2([Goal0|Goals0], Deadness0, PostDeaths, + ModuleInfo, ProcInfo, [Goal|Goals]) :- + detect_deadness_in_goal(Goal0, Deadness0, ModuleInfo, ProcInfo, + _Deadness1, Goal1), + stuff_deadness_residue_after_goal(Goal1, PostDeaths, Goal), + detect_deadness_in_pruned_disj_2(Goals0, Deadness0, PostDeaths, + ModuleInfo, ProcInfo, Goals). + +%-----------------------------------------------------------------------------% +:- pred detect_deadness_in_nondet_disj(list(hlds__goal), set(var), module_info, + proc_info, set(var), set(var), list(hlds__goal)). +:- mode detect_deadness_in_nondet_disj(in, in, in, in, in, out, out) is det. + +detect_deadness_in_nondet_disj([], _Deadness, _ModuleInfo, _PInfo, Union, + Union, []). +detect_deadness_in_nondet_disj([Goal0|Goals0], Deadness, ModuleInfo, ProcInfo, Union0, Union, [Goal|Goals]) :- detect_deadness_in_goal(Goal0, Deadness, ModuleInfo, ProcInfo, Deadness1, Goal1), set__union(Union0, Deadness1, Union1), - detect_deadness_in_disj(Goals0, Deadness, ModuleInfo, ProcInfo, + detect_deadness_in_nondet_disj(Goals0, Deadness, ModuleInfo, ProcInfo, Union1, Union, Goals), set__difference(Union, Deadness1, Residue), - stuff_deadness_residue_into_goal(Goal1, Residue, Goal). + stuff_deadness_residue_before_goal(Goal1, Residue, Goal). %-----------------------------------------------------------------------------% @@ -424,7 +464,7 @@ detect_deadness_in_cases(SwitchVar, [case(Cons, Goal0)|Goals0], Deadness0, % it must be put in the pre-death set of that case. set__insert(Union2, SwitchVar, Union), set__difference(Union, Deadness1, Residue), - stuff_deadness_residue_into_goal(Goal1, Residue, Goal). + stuff_deadness_residue_before_goal(Goal1, Residue, Goal). %-----------------------------------------------------------------------------% @@ -497,24 +537,60 @@ detect_initial_deadness_2([V - M|VAs], ModuleInfo, Deadness0, Deadness) :- %-----------------------------------------------------------------------------% %-----------------------------------------------------------------------------% -:- pred stuff_liveness_residue_into_goal(hlds__goal, liveness_info, hlds__goal). -:- mode stuff_liveness_residue_into_goal(in, in, out) is det. +:- pred stuff_liveness_residue_after_goal(hlds__goal, liveness_info, + hlds__goal). +:- mode stuff_liveness_residue_after_goal(in, in, out) is det. -stuff_liveness_residue_into_goal(Goal - GoalInfo0, Residue, Goal - GoalInfo) :- +stuff_liveness_residue_after_goal(Goal - GoalInfo0, Residue, Goal - GoalInfo) :- goal_info_post_delta_liveness(GoalInfo0, Births0 - Deaths), set__union(Births0, Residue, Births), goal_info_set_post_delta_liveness(GoalInfo0, Births - Deaths, GoalInfo). %-----------------------------------------------------------------------------% -:- pred stuff_deadness_residue_into_goal(hlds__goal, liveness_info, hlds__goal). -:- mode stuff_deadness_residue_into_goal(in, in, out) is det. +:- pred stuff_deadness_residue_before_goal(hlds__goal, liveness_info, + hlds__goal). +:- mode stuff_deadness_residue_before_goal(in, in, out) is det. -stuff_deadness_residue_into_goal(Goal - GoalInfo0, Residue, Goal - GoalInfo) :- +stuff_deadness_residue_before_goal(Goal - GoalInfo0, Residue, Goal - GoalInfo) + :- goal_info_pre_delta_liveness(GoalInfo0, Births - Deaths0), set__union(Deaths0, Residue, Deaths), goal_info_set_pre_delta_liveness(GoalInfo0, Births - Deaths, GoalInfo). +%-----------------------------------------------------------------------------% + +:- pred stuff_deadness_residue_after_goal(hlds__goal, liveness_info, + hlds__goal). +:- mode stuff_deadness_residue_after_goal(in, in, out) is det. + +stuff_deadness_residue_after_goal(Goal0 - GoalInfo0, Residue, Goal - GoalInfo) + :- + ( goal_is_atomic(Goal0) -> + % XXX the following code is a bit dodgy... + % For atomic goals, we can't just put the deadness residue + % in the post-delta-liveness, because the code generator + % would then try to apply it prematurely in the pre_goal_update. + % Instead, we create a singleton conjunction, so that we + % can use the post-delta-liveness of the (non-atomic) + % conjunction. This technique is probably a bit fragile, + % since other parts of the compiler aren't very keen on + % singleton disjunctions. + Goal = conj([Goal0 - GoalInfo0]), + set__init(Births), + set__init(Deaths), + goal_info_set_pre_delta_liveness(GoalInfo0, Births - Deaths, + GoalInfo1), + goal_info_set_post_delta_liveness(GoalInfo1, Births - Residue, + GoalInfo) + ; + Goal = Goal0, + goal_info_post_delta_liveness(GoalInfo0, Births - Deaths0), + set__union(Deaths0, Residue, Deaths), + goal_info_set_post_delta_liveness(GoalInfo0, Births - Deaths, + GoalInfo) + ). + %-----------------------------------------------------------------------------% % traverses a goal, annotating it with information about which vars @@ -608,13 +684,13 @@ add_nondet_lives_to_goal_2(if_then_else(Vars, Cond0, Then0, Else0, FV), % but not the Then have to become automagically % live at the end of the Then. set__difference(Extras, Extras2, ElseOnlyExtras), - stuff_liveness_residue_into_goal(Then1, ElseOnlyExtras, Then), + stuff_liveness_residue_after_goal(Then1, ElseOnlyExtras, Then), % things that become nondet live in the Then % but not the Else have to become automagically % live at the end of the Else. set__difference(Extras, Extras3, ThenOnlyExtras), - stuff_liveness_residue_into_goal(Else1, ThenOnlyExtras, Else). + stuff_liveness_residue_after_goal(Else1, ThenOnlyExtras, Else). % Nondet lives cannot escape from a commit % so we have to work if if this quantifier is a commit or not. @@ -695,7 +771,7 @@ add_nondet_lives_to_disj([G0], Liveness0, Extras0, set__union(ExtrasAcc, Extras1, Extras), set__difference(ExtrasAcc, Extras1, OtherGoalExtras), % optimized Extras -> ExtrasAcc - stuff_liveness_residue_into_goal(G1, OtherGoalExtras, G). + stuff_liveness_residue_after_goal(G1, OtherGoalExtras, G). add_nondet_lives_to_disj([G0|Gs0], Liveness0, Extras0, [G|Gs], Liveness, ExtrasAcc0, Extras) :- % make this clause mutually exclusive with the previous one @@ -705,7 +781,7 @@ add_nondet_lives_to_disj([G0|Gs0], Liveness0, Extras0, add_nondet_lives_to_disj(Gs0, Liveness0, Extras0, Gs, _Liveness1, ExtrasAcc, Extras), set__difference(Extras, Extras2, OtherGoalExtras), - stuff_liveness_residue_into_goal(G1, OtherGoalExtras, G). + stuff_liveness_residue_after_goal(G1, OtherGoalExtras, G). :- pred add_nondet_lives_to_switch(list(case), set(var), set(var), list(case), set(var),set(var), set(var)). @@ -722,22 +798,7 @@ add_nondet_lives_to_switch([case(ConsId, G0)|Gs0], Liveness0, Extras0, add_nondet_lives_to_switch(Gs0, Liveness0, Extras0, Gs, _Liveness1, ExtrasAcc, Extras), set__difference(Extras, Extras2, OtherGoalExtras), - stuff_liveness_residue_into_goal(G1, OtherGoalExtras, G). - -%------------------------------------------------------------------------------% - -:- pred add_deadness_to_goal(hlds__goal, set(var), hlds__goal). -:- mode add_deadness_to_goal(in, in, out) is det. - -add_deadness_to_goal(Goal - GoalInfo0, Vars, Goal - GoalInfo) :- - goal_info_nondet_lives(GoalInfo0, NondetLives0), - goal_info_post_delta_liveness(GoalInfo0, PostDelta0), - PostDelta0 = PostBirths - PostDeaths0, - set__union(NondetLives0, Vars, NondetLives), - set__union(PostDeaths0, Vars, PostDeaths), - PostDelta = PostBirths - PostDeaths, - goal_info_set_nondet_lives(GoalInfo0, NondetLives, GoalInfo1), - goal_info_set_post_delta_liveness(GoalInfo1, PostDelta, GoalInfo). + stuff_liveness_residue_after_goal(G1, OtherGoalExtras, G). %-----------------------------------------------------------------------------% %-----------------------------------------------------------------------------% diff --git a/compiler/middle_rec.m b/compiler/middle_rec.m index 68cbbe85c..9b67ca633 100644 --- a/compiler/middle_rec.m +++ b/compiler/middle_rec.m @@ -119,7 +119,7 @@ middle_rec__generate_switch(Var, BaseConsId, Base, Recursive, FollowVars, { code_util__make_local_entry_label(ModuleInfo, PredId, ProcId, no, EntryLabel) }, - code_aux__pre_goal_update(SwitchGoalInfo), + code_aux__pre_goal_update(SwitchGoalInfo, no), unify_gen__generate_tag_test(Var, BaseConsId, BaseLabel, NegTestCode), { tree__flatten(NegTestCode, NegTestListList) }, diff --git a/compiler/simplify.m b/compiler/simplify.m index 777a69f90..8e83e4d5c 100644 --- a/compiler/simplify.m +++ b/compiler/simplify.m @@ -135,7 +135,7 @@ simplify__goal_2(conj(Goals0), GoalInfo0, InstMap0, DetInfo, Goal, Msgs) :- ) ). -simplify__goal_2(disj(Disjuncts0, FV), GoalInfo, InstMap0, DetInfo, +simplify__goal_2(disj(Disjuncts0, FV), _GoalInfo, InstMap0, DetInfo, Goal, Msgs) :- ( Disjuncts0 = [] -> Goal = disj([], FV), @@ -146,6 +146,9 @@ simplify__goal_2(disj(Disjuncts0, FV), GoalInfo, InstMap0, DetInfo, ; simplify__disj(Disjuncts0, InstMap0, DetInfo, Disjuncts, MsgsA), ( + /**** + XXX This optimization is not correct, see comment below + at the definition of fixup_disj goal_info_get_determinism(GoalInfo, Detism), determinism_components(Detism, _CanFail, MaxSoln), MaxSoln \= at_most_many @@ -164,6 +167,7 @@ simplify__goal_2(disj(Disjuncts0, FV), GoalInfo, InstMap0, DetInfo, GoalInfo, FV, InstMap0, DetInfo, Goal, MsgsA, Msgs) ; + ****/ Goal = disj(Disjuncts, FV), Msgs = MsgsA ) diff --git a/compiler/store_alloc.m b/compiler/store_alloc.m index 0010b8f6b..c0615b0b7 100644 --- a/compiler/store_alloc.m +++ b/compiler/store_alloc.m @@ -51,6 +51,7 @@ store_alloc_in_proc(ProcInfo0, ModuleInfo, ProcInfo) :- store_alloc_in_goal(Goal0 - GoalInfo0, Liveness0, ModuleInfo, Goal - GoalInfo0, Liveness) :- + goal_info_get_code_model(GoalInfo0, CodeModel), goal_info_pre_delta_liveness(GoalInfo0, PreDelta), PreDelta = PreBirths - PreDeaths, goal_info_post_delta_liveness(GoalInfo0, PostDelta), @@ -68,14 +69,18 @@ store_alloc_in_goal(Goal0 - GoalInfo0, Liveness0, ModuleInfo, ( Goal1 = disj(Disjuncts, FollowVars) -> - % For disjunctions, we only want to allocate registers + % For nondet disjunctions, we only want to allocate registers % for the variables that are generated by the disjunction % (the outputs). For the inputs, the first disjunct will % use whichever registers they happen to be in, % and for subsequent disjuncts these variables need to be % put in framevars. - set__difference(Liveness, Liveness0, OutputVars), - set__to_sorted_list(OutputVars, LiveVarList), + ( CodeModel = model_non -> + set__difference(Liveness, Liveness0, OutputVars), + set__to_sorted_list(OutputVars, LiveVarList) + ; + set__to_sorted_list(Liveness, LiveVarList) + ), store_alloc_allocate_storage(LiveVarList, 1, FollowVars, StoreMap), Goal = disj(Disjuncts, StoreMap)