mirror of
https://github.com/Mercury-Language/mercury.git
synced 2026-04-16 18:03:36 +00:00
Besides defining most of the types representing the smaller parts of
parse trees (parts smaller than items), prog_data.m also has many utility
predicates that operate on values of these types. Carve the three substantial
clusters of predicates out of prog_data.m, and move them into their own
modules, which are each imported by fewer modules than prog_data.m itself.
compiler/vartypes.m:
New module containing the vartypes type and the predicates that operate
on it. The new module has *much* better cohesion than the old prog_data.m.
The vartypes type does not appear in any parse tree; it is used only
in the HLDS. So make vartypes.m part of the hlds.m package, not
parse_tree.m.
Move three predicates that perform renamings and substitutions on vartypes
here from prog_type_subst.m, since the latter is part of the parse_tree.m
package, and thus doesn't have access to hlds.vartypes. Make private
the service predicate that these three moved predicates used to rely on,
since it has no other callers.
compiler/prog_detism.m:
New module containing utility predicates that operate on determinisms
and determinism components.
compiler/prog_rename.m:
New module containing utility predicates that rename variables in
various data structures.
compiler/prog_data.m:
Remove the stuff now in the three new modules.
compiler/prog_type_subst.m:
Remove the three predicates now in vartypes.m.
compiler/mercury_to_mercury.m:
Delete an unneded predicate, which was the only part of this module
that referred to vartypes.
compiler/prog_type.m:
compiler/builtin_lib_types.m:
compiler/type_util.m:
Move some utility predicates that refer to vartypes from prog_type.m
and builtin_lib_types.m (both part of parse_tree.m) to type_util.m
(part of check_hlds.m).
compiler/parse_tree.m:
compiler/hlds.m:
compiler/notes/compiler_design.html:
Mention the new modules.
compiler/accumulator.m:
compiler/add_class.m:
compiler/add_clause.m:
compiler/add_foreign_proc.m:
compiler/add_heap_ops.m:
compiler/add_pragma_type_spec.m:
compiler/add_pred.m:
compiler/add_trail_ops.m:
compiler/arg_info.m:
compiler/bytecode_gen.m:
compiler/call_gen.m:
compiler/clause_to_proc.m:
compiler/closure_analysis.m:
compiler/code_info.m:
compiler/code_loc_dep.m:
compiler/common.m:
compiler/complexity.m:
compiler/const_prop.m:
compiler/constraint.m:
compiler/continuation_info.m:
compiler/coverage_profiling.m:
compiler/cse_detection.m:
compiler/ctgc.datastruct.m:
compiler/ctgc.util.m:
compiler/deep_profiling.m:
compiler/deforest.m:
compiler/delay_construct.m:
compiler/delay_partial_inst.m:
compiler/dep_par_conj.m:
compiler/det_analysis.m:
compiler/det_report.m:
compiler/det_util.m:
compiler/disj_gen.m:
compiler/equiv_type_hlds.m:
compiler/erl_call_gen.m:
compiler/erl_code_gen.m:
compiler/erl_code_util.m:
compiler/exception_analysis.m:
compiler/float_regs.m:
compiler/follow_code.m:
compiler/follow_vars.m:
compiler/format_call.m:
compiler/goal_expr_to_goal.m:
compiler/goal_path.m:
compiler/goal_store.m:
compiler/goal_util.m:
compiler/headvar_names.m:
compiler/hhf.m:
compiler/higher_order.m:
compiler/hlds_clauses.m:
compiler/hlds_goal.m:
compiler/hlds_llds.m:
compiler/hlds_out_goal.m:
compiler/hlds_out_module.m:
compiler/hlds_out_pred.m:
compiler/hlds_pred.m:
compiler/hlds_rtti.m:
compiler/inlining.m:
compiler/inst_util.m:
compiler/instmap.m:
compiler/intermod.m:
compiler/interval.m:
compiler/lambda.m:
compiler/lco.m:
compiler/live_vars.m:
compiler/liveness.m:
compiler/lookup_switch.m:
compiler/make_goal.m:
compiler/mark_tail_calls.m:
compiler/ml_accurate_gc.m:
compiler/ml_code_gen.m:
compiler/ml_code_util.m:
compiler/ml_disj_gen.m:
compiler/ml_gen_info.m:
compiler/ml_lookup_switch.m:
compiler/ml_proc_gen.m:
compiler/ml_unify_gen.m:
compiler/mode_constraints.m:
compiler/mode_info.m:
compiler/mode_util.m:
compiler/modecheck_call.m:
compiler/modecheck_conj.m:
compiler/modecheck_goal.m:
compiler/modecheck_unify.m:
compiler/modecheck_util.m:
compiler/modes.m:
compiler/par_loop_control.m:
compiler/pd_info.m:
compiler/pd_util.m:
compiler/polymorphism.m:
compiler/post_typecheck.m:
compiler/prog_rep.m:
compiler/prop_mode_constraints.m:
compiler/purity.m:
compiler/qual_info.m:
compiler/quantification.m:
compiler/rbmm.points_to_graph.m:
compiler/rbmm.points_to_info.m:
compiler/rbmm.region_liveness_info.m:
compiler/rbmm.region_transformation.m:
compiler/saved_vars.m:
compiler/set_of_var.m:
compiler/simplify_goal_call.m:
compiler/simplify_goal_conj.m:
compiler/simplify_goal_disj.m:
compiler/simplify_goal_ite.m:
compiler/simplify_goal_scope.m:
compiler/simplify_goal_switch.m:
compiler/simplify_goal_unify.m:
compiler/simplify_info.m:
compiler/simplify_proc.m:
compiler/size_prof.m:
compiler/ssdebug.m:
compiler/stack_alloc.m:
compiler/stack_layout.m:
compiler/stack_opt.m:
compiler/stm_expand.m:
compiler/store_alloc.m:
compiler/structure_reuse.analysis.m:
compiler/structure_reuse.direct.choose_reuse.m:
compiler/structure_reuse.direct.detect_garbage.m:
compiler/structure_reuse.indirect.m:
compiler/structure_reuse.lbu.m:
compiler/structure_reuse.lfu.m:
compiler/structure_sharing.analysis.m:
compiler/structure_sharing.domain.m:
compiler/switch_detection.m:
compiler/table_gen.m:
compiler/tabling_analysis.m:
compiler/term_constr_build.m:
compiler/term_constr_initial.m:
compiler/term_constr_util.m:
compiler/term_pass1.m:
compiler/term_traversal.m:
compiler/term_util.m:
compiler/trace_gen.m:
compiler/trailing_analysis.m:
compiler/try_expand.m:
compiler/tupling.m:
compiler/type_assign.m:
compiler/type_constraints.m:
compiler/typecheck.m:
compiler/typecheck_errors.m:
compiler/unify_gen.m:
compiler/unify_proc.m:
compiler/unique_modes.m:
compiler/unneeded_code.m:
compiler/untupling.m:
compiler/unused_args.m:
compiler/var_locn.m:
Conform to the above changes, mostly by importing some of the
three new modules as well as, or instead of, prog_data.m.
285 lines
12 KiB
Mathematica
285 lines
12 KiB
Mathematica
%-----------------------------------------------------------------------------%
|
|
% vim: ft=mercury ts=4 sw=4 et
|
|
%-----------------------------------------------------------------------------%
|
|
% Copyright (C) 2001-2012 The University of Melbourne.
|
|
% This file may only be copied under the terms of the GNU General
|
|
% Public License - see the file COPYING in the Mercury distribution.
|
|
%-----------------------------------------------------------------------------%
|
|
%
|
|
% File: delay_construct.m.
|
|
% Author: zs.
|
|
%
|
|
% This module transforms sequences of goals in procedure bodies. It looks for
|
|
% a unification that constructs a ground term followed by primitive goals, at
|
|
% least one of which can fail, and none of which take the variable
|
|
% representing the cell as their input. Such code sequences cause the cell to
|
|
% be constructed even if the following goal would fail, which is wasteful.
|
|
% This module therefore reorders the sequence, moving the construction
|
|
% unification past all the semidet primitives it can.
|
|
%
|
|
% The reason we don't move the construction past calls or composite goals is
|
|
% that this may require storing the input arguments of the construction on the
|
|
% stack, which may cause a slowdown bigger than the speedup available from not
|
|
% having to construct the cell on some execution paths.
|
|
%
|
|
%-----------------------------------------------------------------------------%
|
|
|
|
:- module transform_hlds.delay_construct.
|
|
:- interface.
|
|
|
|
:- import_module hlds.hlds_module.
|
|
:- import_module hlds.hlds_pred.
|
|
|
|
%-----------------------------------------------------------------------------%
|
|
|
|
:- pred delay_construct_proc(module_info::in, pred_proc_id::in,
|
|
proc_info::in, proc_info::out) is det.
|
|
|
|
%-----------------------------------------------------------------------------%
|
|
%-----------------------------------------------------------------------------%
|
|
|
|
:- implementation.
|
|
|
|
:- import_module check_hlds.inst_match.
|
|
:- import_module hlds.hlds_goal.
|
|
:- import_module hlds.hlds_rtti.
|
|
:- import_module hlds.instmap.
|
|
:- import_module hlds.passes_aux.
|
|
:- import_module hlds.vartypes.
|
|
:- import_module parse_tree.prog_data.
|
|
:- import_module parse_tree.set_of_var.
|
|
|
|
:- import_module bool.
|
|
:- import_module list.
|
|
:- import_module require.
|
|
:- import_module set.
|
|
|
|
%-----------------------------------------------------------------------------%
|
|
|
|
delay_construct_proc(ModuleInfo, proc(PredId, ProcId), !ProcInfo) :-
|
|
trace [io(!IO)] (
|
|
write_proc_progress_message("% Delaying construction unifications in ",
|
|
PredId, ProcId, ModuleInfo, !IO)
|
|
),
|
|
module_info_get_globals(ModuleInfo, Globals),
|
|
module_info_pred_info(ModuleInfo, PredId, PredInfo),
|
|
body_should_use_typeinfo_liveness(PredInfo, Globals, BodyTypeinfoLiveness),
|
|
proc_info_get_vartypes(!.ProcInfo, VarTypes),
|
|
proc_info_get_rtti_varmaps(!.ProcInfo, RttiVarMaps),
|
|
proc_info_get_initial_instmap(!.ProcInfo, ModuleInfo, InstMap0),
|
|
DelayInfo = delay_construct_info(ModuleInfo, BodyTypeinfoLiveness,
|
|
VarTypes, RttiVarMaps),
|
|
proc_info_get_goal(!.ProcInfo, Goal0),
|
|
delay_construct_in_goal(Goal0, InstMap0, DelayInfo, Goal),
|
|
proc_info_set_goal(Goal, !ProcInfo).
|
|
|
|
:- type delay_construct_info
|
|
---> delay_construct_info(
|
|
dci_module_info :: module_info,
|
|
dci_body_typeinfo_liveness :: bool,
|
|
dci_vartypes :: vartypes,
|
|
dci_rtti_varmaps :: rtti_varmaps
|
|
).
|
|
|
|
%-----------------------------------------------------------------------------%
|
|
|
|
:- pred delay_construct_in_goal(hlds_goal::in, instmap::in,
|
|
delay_construct_info::in, hlds_goal::out) is det.
|
|
|
|
delay_construct_in_goal(Goal0, InstMap0, DelayInfo, Goal) :-
|
|
Goal0 = hlds_goal(GoalExpr0, GoalInfo0),
|
|
(
|
|
GoalExpr0 = conj(ConjType, Goals0),
|
|
(
|
|
ConjType = plain_conj,
|
|
Detism = goal_info_get_determinism(GoalInfo0),
|
|
determinism_components(Detism, CanFail, MaxSoln),
|
|
(
|
|
% If the conjunction cannot fail, then its conjuncts cannot
|
|
% fail either, so we have no hope of pushing a construction
|
|
% past a failing goal.
|
|
%
|
|
% If the conjuntion contains goals that can succeed more than
|
|
% once, which is possible if MaxSoln is at_most_many or
|
|
% at_most_many_cc, then moving a construction to the right
|
|
% may increase the number of times the construction is
|
|
% executed. We are therefore careful to make sure
|
|
% delay_construct_in_conj doesn't move constructions
|
|
% across goals that succeed more than once. If the conjunction
|
|
% cannot succeed, i.e. MaxSoln is at_most_zero, there is no
|
|
% point in trying to speed it up.
|
|
|
|
CanFail = can_fail,
|
|
MaxSoln \= at_most_zero
|
|
->
|
|
delay_construct_in_conj(Goals0, InstMap0, DelayInfo, set.init,
|
|
[], Goals1)
|
|
;
|
|
Goals1 = Goals0
|
|
)
|
|
;
|
|
ConjType = parallel_conj,
|
|
Goals1 = Goals0
|
|
),
|
|
delay_construct_in_goals(Goals1, InstMap0, DelayInfo, Goals),
|
|
Goal = hlds_goal(conj(ConjType, Goals), GoalInfo0)
|
|
;
|
|
GoalExpr0 = disj(Goals0),
|
|
delay_construct_in_goals(Goals0, InstMap0, DelayInfo, Goals),
|
|
Goal = hlds_goal(disj(Goals), GoalInfo0)
|
|
;
|
|
GoalExpr0 = negation(NegGoal0),
|
|
delay_construct_in_goal(NegGoal0, InstMap0, DelayInfo, NegGoal),
|
|
Goal = hlds_goal(negation(NegGoal), GoalInfo0)
|
|
;
|
|
GoalExpr0 = switch(Var, CanFail, Cases0),
|
|
delay_construct_in_cases(Cases0, InstMap0, DelayInfo, Cases),
|
|
Goal = hlds_goal(switch(Var, CanFail, Cases), GoalInfo0)
|
|
;
|
|
GoalExpr0 = if_then_else(Vars, Cond0, Then0, Else0),
|
|
Cond0 = hlds_goal(_, CondInfo0),
|
|
CondInstMapDelta = goal_info_get_instmap_delta(CondInfo0),
|
|
instmap.apply_instmap_delta(InstMap0, CondInstMapDelta, InstMapThen),
|
|
delay_construct_in_goal(Cond0, InstMap0, DelayInfo, Cond),
|
|
delay_construct_in_goal(Then0, InstMapThen, DelayInfo, Then),
|
|
delay_construct_in_goal(Else0, InstMap0, DelayInfo, Else),
|
|
Goal = hlds_goal(if_then_else(Vars, Cond, Then, Else), GoalInfo0)
|
|
;
|
|
GoalExpr0 = scope(Reason, SubGoal0),
|
|
(
|
|
Reason = from_ground_term(_, FGT),
|
|
( FGT = from_ground_term_construct
|
|
; FGT = from_ground_term_deconstruct
|
|
)
|
|
->
|
|
Goal = Goal0
|
|
;
|
|
delay_construct_in_goal(SubGoal0, InstMap0, DelayInfo, SubGoal),
|
|
Goal = hlds_goal(scope(Reason, SubGoal), GoalInfo0)
|
|
)
|
|
;
|
|
( GoalExpr0 = generic_call(_, _, _, _, _)
|
|
; GoalExpr0 = plain_call(_, _, _, _, _, _)
|
|
; GoalExpr0 = unify(_, _, _, _, _)
|
|
; GoalExpr0 = call_foreign_proc(_, _, _, _, _, _, _)
|
|
),
|
|
Goal = Goal0
|
|
;
|
|
GoalExpr0 = shorthand(_),
|
|
% These should have been expanded out by now.
|
|
unexpected($module, $pred, "shorthand")
|
|
).
|
|
|
|
%-----------------------------------------------------------------------------%
|
|
|
|
% We maintain a list of delayed construction unifications that construct
|
|
% ground terms, and the set of variables they define.
|
|
%
|
|
% When we find other construction unifications, we add them to the list. It
|
|
% does not matter if they depend on other delayed construction unifications;
|
|
% when we put them back into the conjunction, we do so in the original order.
|
|
%
|
|
% There are several reasons why we may not be able to delay a construction
|
|
% unification past a conjunct. The conjunct may not be a primitive goal, or it
|
|
% may be impure; in either case, we must insert all the delayed construction
|
|
% unifications before it. The conjunct may also require the value of a
|
|
% variable defined by a construction unification. In such cases, we could drop
|
|
% before that goal only the construction unifications that define the
|
|
% variables needed by the conjunct, either directly or indirectly through the
|
|
% values required by some of those construction unifications. However,
|
|
% separating out this set of delayed constructions from the others would
|
|
% require somewhat complex code, and it is not clear that there would be any
|
|
% significant benefit. We therefore insert *all* the delayed constructions
|
|
% before a goal if the goal requires *any* of the variables bound by the
|
|
% constructions.
|
|
%
|
|
% The instmap we pass around is the one that we construct from the original
|
|
% conjunction order. At each point, it reflects the bindings made by the
|
|
% conjuncts so far *plus* the bindings made by the delayed goals.
|
|
|
|
:- pred delay_construct_in_conj(list(hlds_goal)::in, instmap::in,
|
|
delay_construct_info::in, set(prog_var)::in, list(hlds_goal)::in,
|
|
list(hlds_goal)::out) is det.
|
|
|
|
delay_construct_in_conj([], _, _, _, RevDelayedGoals, DelayedGoals) :-
|
|
list.reverse(RevDelayedGoals, DelayedGoals).
|
|
delay_construct_in_conj([Goal0 | Goals0], InstMap0, DelayInfo,
|
|
ConstructedVars0, RevDelayedGoals0, Goals) :-
|
|
Goal0 = hlds_goal(GoalExpr0, GoalInfo0),
|
|
InstMapDelta0 = goal_info_get_instmap_delta(GoalInfo0),
|
|
instmap.apply_instmap_delta(InstMap0, InstMapDelta0, InstMap1),
|
|
(
|
|
GoalExpr0 = unify(_, _, _, Unif, _),
|
|
Unif = construct(Var, _, Args, _, _, _, _),
|
|
Args = [_ | _], % We are constructing a cell, not a constant
|
|
instmap_lookup_var(InstMap0, Var, Inst0),
|
|
inst_is_free(DelayInfo ^ dci_module_info, Inst0),
|
|
instmap_lookup_var(InstMap1, Var, Inst1),
|
|
inst_is_ground(DelayInfo ^ dci_module_info, Inst1)
|
|
->
|
|
set.insert(Var, ConstructedVars0, ConstructedVars1),
|
|
RevDelayedGoals1 = [Goal0 | RevDelayedGoals0],
|
|
delay_construct_in_conj(Goals0, InstMap1, DelayInfo,
|
|
ConstructedVars1, RevDelayedGoals1, Goals)
|
|
;
|
|
Goal0 = hlds_goal(GoalExpr0, GoalInfo0),
|
|
delay_construct_skippable(GoalExpr0, GoalInfo0),
|
|
NonLocals = goal_info_get_nonlocals(GoalInfo0),
|
|
maybe_complete_with_typeinfo_vars(NonLocals,
|
|
DelayInfo ^ dci_body_typeinfo_liveness,
|
|
DelayInfo ^ dci_vartypes,
|
|
DelayInfo ^ dci_rtti_varmaps, CompletedNonLocals),
|
|
set_of_var.intersect(CompletedNonLocals,
|
|
set_to_bitset(ConstructedVars0), Intersection),
|
|
set_of_var.is_empty(Intersection),
|
|
goal_info_get_purity(GoalInfo0) = purity_pure
|
|
->
|
|
delay_construct_in_conj(Goals0, InstMap1, DelayInfo,
|
|
ConstructedVars0, RevDelayedGoals0, Goals1),
|
|
Goals = [Goal0 | Goals1]
|
|
;
|
|
list.reverse(RevDelayedGoals0, DelayedGoals),
|
|
delay_construct_in_conj(Goals0, InstMap1, DelayInfo,
|
|
set.init, [], Goals1),
|
|
list.append(DelayedGoals, [Goal0 | Goals1], Goals)
|
|
).
|
|
|
|
:- pred delay_construct_skippable(hlds_goal_expr::in, hlds_goal_info::in)
|
|
is semidet.
|
|
|
|
delay_construct_skippable(GoalExpr, GoalInfo) :-
|
|
(
|
|
GoalExpr = unify(_, _, _, _, _)
|
|
;
|
|
GoalExpr = plain_call(_, _, _, inline_builtin, _, _)
|
|
),
|
|
Detism = goal_info_get_determinism(GoalInfo),
|
|
determinism_components(Detism, _CanFail, MaxSoln),
|
|
MaxSoln \= at_most_many.
|
|
|
|
%-----------------------------------------------------------------------------%
|
|
|
|
:- pred delay_construct_in_goals(list(hlds_goal)::in, instmap::in,
|
|
delay_construct_info::in, list(hlds_goal)::out) is det.
|
|
|
|
delay_construct_in_goals([], _, _, []).
|
|
delay_construct_in_goals([Goal0 | Goals0], InstMap0, DelayInfo,
|
|
[Goal | Goals]) :-
|
|
delay_construct_in_goal(Goal0, InstMap0, DelayInfo, Goal),
|
|
delay_construct_in_goals(Goals0, InstMap0, DelayInfo, Goals).
|
|
|
|
:- pred delay_construct_in_cases(list(case)::in, instmap::in,
|
|
delay_construct_info::in, list(case)::out) is det.
|
|
|
|
delay_construct_in_cases([], _, _, []).
|
|
delay_construct_in_cases([Case0 | Cases0], InstMap0, DelayInfo,
|
|
[Case | Cases]) :-
|
|
Case0 = case(MainConsId, OtherConsIds, Goal0),
|
|
delay_construct_in_goal(Goal0, InstMap0, DelayInfo, Goal),
|
|
Case = case(MainConsId, OtherConsIds, Goal),
|
|
delay_construct_in_cases(Cases0, InstMap0, DelayInfo, Cases).
|
|
|
|
%-----------------------------------------------------------------------------%
|
|
:- end_module transform_hlds.delay_construct.
|
|
%-----------------------------------------------------------------------------%
|