[m-rev.] for review: parallel liveness and code generation
Peter Wang
wangp at students.cs.mu.oz.au
Wed Aug 16 15:46:04 AEST 2006
(Pending much bootchecking.)
For review by Zoltan. In particular I'd like to know `remap_instr' is not
updating some instructions that require updating (to refer to combined static
cell information), or if some instructions don't need updating.
Estimated hours taken: 20
Branches: main
Add options to perform code generation and liveness detection for the low-level
backend using parallel threads. These are enabled with `--parallel-code-gen'
and `--parallel-liveness' options respectively, for compilers built in grades
supporting multiple engines, and running with multiple engines enabled.
Currently we only attempt to use two threads.
compiler/global_data.m:
Use a new type `type_num' instead of `int' everywhere for common cell
type numbers.
Add a function `bump_type_num_counter' which takes a global_data
structure and returns a global_data with the common cell type number
counter incremented by some amount. This is to allow multiple threads
to add new types to their own copies of the global_data structure
without type numbers clashing when we try to merge them later.
Add a predicate `merge_global_datas' which takes two global_datas and
merges their static cell information.
Add a predicate `remap_static_cell_references' which updates code using
the second global_data structure (passed to merge_global_datas) to
refer to static cells in the combined global_data structure.
compiler/layout_out.m:
compiler/llds.m:
compiler/llds_out.m:
compiler/opt_debug.m:
Conform to the type change of common cell type numbers.
compiler/options.m:
doc/user_guide.texi:
Add `--parallel-liveness' and `--parallel-code-gen' options.
The documentation is commented out for now.
compiler/handle_options.m:
Make the `--parallel-liveness' and `--parallel-code-gen' options imply
`--no-trad-passes'.
compiler/liveness.m:
Add parallel liveness detection support.
The sequential liveness detection code took I/O states in order to
output debugging information; make it take values of a typeclass
`debug_liveness_io' instead, and make io.state an instance of the
typeclass. In the parallel case we pass dummy values that don't try to
output debugging information.
compiler/mercury_compile.m:
Run parallel liveness detection if it is enabled and liveness debugging
is not enabled (see above).
compiler/proc_gen.m:
Add parallel code generation support. Run it if selected by the user
and `--very-verbose' is not enabled (as that would require I/O).
runtime/mercury_context.c:
Clear the detstack and nondetstack of a MR_Context structure when it is
destroyed (put back on the free list) to speed up conservative garbage
collection, and to unnecessary retention of memory.
Index: compiler/global_data.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/global_data.m,v
retrieving revision 1.21
diff -u -r1.21 global_data.m
--- compiler/global_data.m 31 Jul 2006 08:31:38 -0000 1.21
+++ compiler/global_data.m 9 Aug 2006 05:22:41 -0000
@@ -100,6 +100,33 @@
:- pred rval_type_as_arg(rval::in, exprn_opts::in, llds_type::out) is det.
%-----------------------------------------------------------------------------%
+
+:- type static_cell_remap_info.
+
+ % bump_type_num_counter(GlobalData, Increment)
+ %
+ % Return a copy of GlobalData with a type counter incremented by Increment.
+ %
+:- func bump_type_num_counter(global_data, int) = global_data.
+
+ % merge_global_datas(GlobalDataA, GlobalDataB, GlobalData, Remap)
+ %
+ % Merge two global data structures, where static cell information from
+ % GlobalDataA takes precedence over GlobalDataB. The type numbers of the
+ % two global_data structures must be distinct. Remap contains the
+ % information necessary for remap_static_cell_references/3.
+ %
+:- pred merge_global_datas(global_data::in, global_data::in, global_data::out,
+ static_cell_remap_info::out) is det.
+
+ % Update instructions in a C procedure that reference the static cells
+ % from the GlobalDataB that was passed to merge_global_datas/4, to
+ % reference the static cells of the merged global_data structure.
+ %
+:- pred remap_static_cell_references(static_cell_remap_info::in,
+ c_procedure::in, c_procedure::out) is det.
+
+%-----------------------------------------------------------------------------%
%-----------------------------------------------------------------------------%
:- implementation.
@@ -116,6 +143,8 @@
:- import_module pair.
:- import_module require.
:- import_module set.
+:- import_module svbimap.
+:- import_module svmap.
%-----------------------------------------------------------------------------%
@@ -242,17 +271,17 @@
:- type static_cell_info
---> static_cell_info(
- sub_info :: static_cell_sub_info,
- type_counter :: counter, % next type number
+ sub_info :: static_cell_sub_info,
+ type_counter :: counter, % next type number
% Maps types to type numbers and vice versa.
- cell_type_num_map :: bimap(common_cell_type, int),
+ cell_type_num_map :: bimap(common_cell_type, type_num),
% Maps the cell type number to the information we have
% for all scalar cells of that type.
- scalar_cell_group_map :: map(int, scalar_cell_group),
+ scalar_cell_group_map :: map(type_num, scalar_cell_group),
- vector_cell_group_map :: map(int, vector_cell_group)
+ vector_cell_group_map :: map(type_num, vector_cell_group)
).
init_static_cell_info(BaseName, UnboxFloat, CommonData) = Info0 :-
@@ -299,7 +328,8 @@
)
;
TypeNumCounter0 = !.Info ^ type_counter,
- counter.allocate(TypeNum, TypeNumCounter0, TypeNumCounter),
+ counter.allocate(TypeNum0, TypeNumCounter0, TypeNumCounter),
+ TypeNum = type_num(TypeNum0),
!:Info = !.Info ^ type_counter := TypeNumCounter,
bimap.det_insert(TypeNumMap0, CellType, TypeNum, TypeNumMap),
@@ -428,7 +458,8 @@
)
;
TypeNumCounter0 = !.Info ^ type_counter,
- counter.allocate(TypeNum, TypeNumCounter0, TypeNumCounter),
+ counter.allocate(TypeNum0, TypeNumCounter0, TypeNumCounter),
+ TypeNum = type_num(TypeNum0),
!:Info = !.Info ^ type_counter := TypeNumCounter,
bimap.det_insert(TypeNumMap0, CellType, TypeNum, TypeNumMap),
@@ -472,7 +503,7 @@
list.reverse(RevVectorDatas, VectorDatas).
:- pred add_scalar_static_cell_for_type(module_name::in,
- bimap(common_cell_type, int)::in, int::in, scalar_cell_group::in,
+ bimap(common_cell_type, type_num)::in, type_num::in, scalar_cell_group::in,
list(scalar_common_data_array)::in, list(scalar_common_data_array)::out)
is det.
@@ -485,7 +516,7 @@
!:Arrays = [Array | !.Arrays].
:- pred add_all_vector_static_cells_for_type(module_name::in,
- bimap(common_cell_type, int)::in, int::in, vector_cell_group::in,
+ bimap(common_cell_type, type_num)::in, type_num::in, vector_cell_group::in,
list(vector_common_data_array)::in, list(vector_common_data_array)::out)
is det.
@@ -495,7 +526,7 @@
map.foldl(add_one_vector_static_cell(ModuleName, TypeNum, CellType),
CellGroup ^ vector_cell_map, !Arrays).
-:- pred add_one_vector_static_cell(module_name::in, int::in,
+:- pred add_one_vector_static_cell(module_name::in, type_num::in,
common_cell_type::in, int::in, vector_contents::in,
list(vector_common_data_array)::in, list(vector_common_data_array)::out)
is det.
@@ -591,6 +622,474 @@
natural_type(UnboxFloat, Rval, Type).
%-----------------------------------------------------------------------------%
+%-----------------------------------------------------------------------------%
+
+:- type static_cell_remap_info
+ ---> static_cell_remap_info(
+ cell_type_num_remap,
+ map(type_num, scalar_cell_group_remap)
+ % A map from the _old_ type number, to the mapping of old
+ % data_names to new_data names.
+ ).
+
+:- type cell_type_num_remap == map(type_num, type_num).
+ % Mapping of old to new type numbers.
+
+:- type scalar_cell_group_remap == map(data_name, data_name).
+ % Mapping of old to new data_names.
+
+bump_type_num_counter(GlobalData0, Increment) = GlobalData :-
+ Counter0 = GlobalData0 ^ static_cell_info ^ type_counter,
+ counter.allocate(N, Counter0, _),
+ Counter = counter.init(N + Increment),
+ GlobalData = GlobalData0 ^ static_cell_info ^ type_counter := Counter.
+
+merge_global_datas(GlobalDataA, GlobalDataB, GlobalData, Remap) :-
+ GlobalDataA = global_data(ProcVarMapA, ProcLayoutMapA, ClosureLayoutsA,
+ StaticCellInfoA),
+ GlobalDataB = global_data(ProcVarMapB, ProcLayoutMapB, ClosureLayoutsB,
+ StaticCellInfoB),
+ GlobalData = global_data(ProcVarMap, ProcLayoutMap, ClosureLayouts,
+ StaticCellInfo),
+ ProcVarMap = map.merge(ProcVarMapA, ProcVarMapB),
+ ProcLayoutMap = map.merge(ProcLayoutMapA, ProcLayoutMapB),
+ ClosureLayouts = ClosureLayoutsA ++ ClosureLayoutsB,
+ merge_static_cell_infos(StaticCellInfoA, StaticCellInfoB, StaticCellInfo,
+ Remap).
+
+:- pred merge_static_cell_infos(static_cell_info::in, static_cell_info::in,
+ static_cell_info::out, static_cell_remap_info::out) is det.
+
+merge_static_cell_infos(SCIa, SCIb, SCI, Remap) :-
+ SCIa = static_cell_info(SubInfoA, TypeCounterA,
+ CellTypeNumMapA, ScalarCellGroupMapA, VectorCellGroupMapA),
+ SCIb = static_cell_info(SubInfoB, _TypeCounterB,
+ CellTypeNumMapB, ScalarCellGroupMapB, VectorCellGroupMapB),
+ expect(unify(SubInfoA, SubInfoB), this_file, "merge_static_cell_info"),
+
+ % Merge cell type number maps.
+ bimap.foldl3(merge_cell_type_num_maps, CellTypeNumMapB,
+ TypeCounterA, TypeCounter, CellTypeNumMapA, CellTypeNumMap,
+ map.init, CellTypeNumMapRemap),
+
+ % Merge the scalar and vector cell group maps.
+ merge_scalar_cell_group_maps(CellTypeNumMapRemap,
+ ScalarCellGroupMapA, ScalarCellGroupMapB,
+ ScalarCellGroupMap, ScalarCellGroupRemap),
+ merge_vector_cell_group_maps(CellTypeNumMapRemap,
+ VectorCellGroupMapA, VectorCellGroupMapB,
+ VectorCellGroupMap),
+
+ Remap = static_cell_remap_info(CellTypeNumMapRemap, ScalarCellGroupRemap),
+
+ % Remap the information in the static_cell_info info itself.
+ SCI0 = static_cell_info(SubInfoA, TypeCounter,
+ CellTypeNumMap, ScalarCellGroupMap, VectorCellGroupMap),
+ SCI = remap_static_cell_info(Remap, SCI0).
+
+:- pred merge_cell_type_num_maps(common_cell_type::in, type_num::in,
+ counter::in, counter::out, bimap(common_cell_type, type_num)::in,
+ bimap(common_cell_type, type_num)::out,
+ cell_type_num_remap::in, cell_type_num_remap::out) is det.
+
+merge_cell_type_num_maps(CellType, BTypeNum,
+ !TypeCounter, !CellTypeNumMap, !TypeNumRemap) :-
+ (if bimap.search(!.CellTypeNumMap, CellType, ATypeNum) then
+ % A type also in GlobalDataA.
+ svmap.det_insert(BTypeNum, ATypeNum, !TypeNumRemap)
+ else
+ % A type not in GlobalDataA.
+ counter.allocate(N, !TypeCounter),
+ NewTypeNum = type_num(N),
+ svmap.det_insert(BTypeNum, NewTypeNum, !TypeNumRemap),
+ svbimap.det_insert(CellType, NewTypeNum, !CellTypeNumMap)
+ ).
+
+:- pred merge_scalar_cell_group_maps(cell_type_num_remap::in,
+ map(type_num, scalar_cell_group)::in, map(type_num, scalar_cell_group)::in,
+ map(type_num, scalar_cell_group)::out,
+ map(type_num, scalar_cell_group_remap)::out) is det.
+
+merge_scalar_cell_group_maps(TypeNumRemap,
+ ScalarCellGroupMapA, ScalarCellGroupMapB,
+ ScalarCellGroupMap, ScalarCellGroupRemap) :-
+ map.foldl2(merge_scalar_cell_group_maps_2(TypeNumRemap),
+ ScalarCellGroupMapB,
+ ScalarCellGroupMapA, ScalarCellGroupMap,
+ map.init, ScalarCellGroupRemap).
+
+:- pred merge_scalar_cell_group_maps_2(cell_type_num_remap::in,
+ type_num::in, scalar_cell_group::in,
+ map(type_num, scalar_cell_group)::in,
+ map(type_num, scalar_cell_group)::out,
+ map(type_num, scalar_cell_group_remap)::in,
+ map(type_num, scalar_cell_group_remap)::out) is det.
+
+merge_scalar_cell_group_maps_2(TypeNumRemap, BTypeNum, BScalarCellGroup,
+ !ScalarCellGroupMap, !Remap) :-
+ map.lookup(TypeNumRemap, BTypeNum, TypeNum),
+ (if
+ ScalarCellGroupPrime = !.ScalarCellGroupMap ^ elem(TypeNum)
+ then
+ ScalarCellGroup0 = ScalarCellGroupPrime
+ else
+ % Could do this more efficiently.
+ ScalarCellGroup0 = scalar_cell_group(counter.init(0), bimap.init, [])
+ ),
+ merge_scalar_cell_groups(TypeNum, ScalarCellGroup0, BScalarCellGroup,
+ ScalarCellGroup, ScalarCellGroupRemap),
+ svmap.set(TypeNum, ScalarCellGroup, !ScalarCellGroupMap),
+ svmap.det_insert(BTypeNum, ScalarCellGroupRemap, !Remap).
+
+:- pred merge_scalar_cell_groups(type_num::in,
+ scalar_cell_group::in, scalar_cell_group::in, scalar_cell_group::out,
+ scalar_cell_group_remap::out) is det.
+
+merge_scalar_cell_groups(TypeNum, GroupA, GroupB, GroupAB, GroupRemap) :-
+ GroupA = scalar_cell_group(_CounterA, GroupMembersA, RevArrayA),
+ GroupB = scalar_cell_group(_CounterB, GroupMembersB, RevArrayB),
+ GroupAB = scalar_cell_group(CounterAB, GroupMembersAB, RevArrayAB),
+
+ CounterAB = counter.init(length(RevArrayAB)),
+
+ ArrayA = reverse(RevArrayA),
+ ArrayB = reverse(RevArrayB),
+ ArrayAB = ArrayA ++ delete_elems(ArrayB, ArrayA),
+ RevArrayAB = reverse(ArrayAB),
+
+ bimap.foldl2(merge_scalar_cell_groups_2(TypeNum, ArrayB, ArrayAB),
+ GroupMembersB,
+ GroupMembersA, GroupMembersAB, map.init, GroupRemap).
+
+:- pred merge_scalar_cell_groups_2(type_num::in,
+ list(common_cell_value)::in, list(common_cell_value)::in,
+ list(rval)::in, data_name::in,
+ bimap(list(rval), data_name)::in, bimap(list(rval), data_name)::out,
+ scalar_cell_group_remap::in, scalar_cell_group_remap::out) is det.
+
+merge_scalar_cell_groups_2(TypeNum, ArrayB, ArrayAB,
+ Rvals, BDataName, !GroupMembers, !GroupRemap) :-
+ (if
+ bimap.search(!.GroupMembers, Rvals, DataName)
+ then
+ % Seen this list of rvals before in the group.
+ svmap.det_insert(BDataName, DataName, !GroupRemap)
+ else
+ % Not seen this list of rvals before in the group.
+ (
+ BDataName = scalar_common_ref(_, BCellNum),
+ % Look up what value this cell number referred to in the B array.
+ % Find the cell number of the same value in the combined A+B array.
+ CommonCellValue = list.det_index0(ArrayB, BCellNum),
+ CellNum = nth_member_lookup0(ArrayAB, CommonCellValue),
+ % Add the new data name.
+ DataName = scalar_common_ref(TypeNum, CellNum),
+ svbimap.det_insert(Rvals, DataName, !GroupMembers),
+ svmap.det_insert(BDataName, DataName, !GroupRemap)
+ ;
+ ( BDataName = vector_common_ref(_, _)
+ ; BDataName = proc_tabling_ref(_, _)
+ ),
+ unexpected(this_file, "merge_scalar_cell_groups_2")
+ )
+ ).
+
+:- pred merge_vector_cell_group_maps(cell_type_num_remap::in,
+ map(type_num, vector_cell_group)::in, map(type_num, vector_cell_group)::in,
+ map(type_num, vector_cell_group)::out) is det.
+
+merge_vector_cell_group_maps(TypeNumRemap, VectorCellGroupMapA,
+ VectorCellGroupMapB, VectorCellGroupMap) :-
+ map.foldl(merge_vector_cell_group_maps_2(TypeNumRemap),
+ VectorCellGroupMapB,
+ VectorCellGroupMapA, VectorCellGroupMap).
+
+:- pred merge_vector_cell_group_maps_2(cell_type_num_remap::in,
+ type_num::in, vector_cell_group::in, map(type_num, vector_cell_group)::in,
+ map(type_num, vector_cell_group)::out) is det.
+
+merge_vector_cell_group_maps_2(TypeNumRemap, OldTypeNum, VectorCellGroup,
+ !VectorCellGroupMap) :-
+ NewTypeNum = TypeNumRemap ^ det_elem(OldTypeNum),
+ svmap.det_insert(NewTypeNum, VectorCellGroup, !VectorCellGroupMap).
+
+:- func nth_member_lookup0(list(T), T) = int.
+
+nth_member_lookup0(List, Elem) = Pos-1 :-
+ list.nth_member_lookup(List, Elem, Pos).
+
+%-----------------------------------------------------------------------------%
+
+ % The scalar cell group and vector cell group contents themselves
+ % need to be updated to use the merged cell information.
+ %
+:- func remap_static_cell_info(static_cell_remap_info,
+ static_cell_info) = static_cell_info.
+
+remap_static_cell_info(Remap, SCI0) = SCI :-
+ ScalarMap = map.map_values(remap_scalar_cell_group(Remap),
+ SCI0 ^ scalar_cell_group_map),
+ VectorMap = map.map_values(remap_vector_cell_group(Remap),
+ SCI0 ^ vector_cell_group_map),
+ SCI = (SCI0 ^ scalar_cell_group_map := ScalarMap)
+ ^ vector_cell_group_map := VectorMap.
+
+:- func remap_scalar_cell_group(static_cell_remap_info,
+ type_num, scalar_cell_group) = scalar_cell_group.
+
+remap_scalar_cell_group(Remap, _, ScalarCellGroup0) = ScalarCellGroup :-
+ Array0 = ScalarCellGroup0 ^ scalar_cell_rev_array,
+ Array = list.map(remap_common_cell_value(Remap), Array0),
+ ScalarCellGroup = ScalarCellGroup0 ^ scalar_cell_rev_array := Array.
+
+:- func remap_vector_cell_group(static_cell_remap_info,
+ type_num, vector_cell_group) = vector_cell_group.
+
+remap_vector_cell_group(Remap, _, VectorCellGroup0) = VectorCellGroup :-
+ VectorCellGroup0 = vector_cell_group(Counter, Map0),
+ VectorCellGroup = vector_cell_group(Counter, Map),
+ Map = map.map_values(remap_vector_contents(Remap), Map0).
+
+:- func remap_vector_contents(static_cell_remap_info,
+ int, vector_contents) = vector_contents.
+
+remap_vector_contents(Remap, _, Contents0) = Contents :-
+ Contents0 = vector_contents(Values0),
+ Contents = vector_contents(Values),
+ Values = list.map(remap_common_cell_value(Remap), Values0).
+
+:- func remap_common_cell_value(static_cell_remap_info,
+ common_cell_value) = common_cell_value.
+
+remap_common_cell_value(Remap, CommonCellValue0) = CommonCellValue :-
+ (
+ CommonCellValue0 = plain_value(RvalsTypes0),
+ CommonCellValue = plain_value(RvalsTypes),
+ RvalsTypes = list.map(remap_plain_value(Remap), RvalsTypes0)
+ ;
+ CommonCellValue0 = grouped_args_value(ArgGroup0),
+ CommonCellValue = grouped_args_value(ArgGroup),
+ ArgGroup = list.map(remap_arg_group_value(Remap), ArgGroup0)
+ ).
+
+:- func remap_plain_value(static_cell_remap_info,
+ pair(rval, llds_type)) = pair(rval, llds_type).
+
+remap_plain_value(Remap, Rval0 - Type) = Rval - Type :-
+ Rval = remap_rval(Remap, Rval0).
+
+:- func remap_arg_group_value(static_cell_remap_info,
+ common_cell_arg_group) = common_cell_arg_group.
+
+remap_arg_group_value(Remap, GroupedArgs0) = GroupedArgs :-
+ (
+ GroupedArgs0 = common_cell_grouped_args(Type, Fields, Rvals0),
+ GroupedArgs = common_cell_grouped_args(Type, Fields, Rvals),
+ Rvals = list.map(remap_rval(Remap), Rvals0)
+ ;
+ GroupedArgs0 = common_cell_ungrouped_arg(Type, Rvals0),
+ GroupedArgs = common_cell_ungrouped_arg(Type, Rvals),
+ Rvals = remap_rval(Remap, Rvals0)
+ ).
+
+%-----------------------------------------------------------------------------%
+
+remap_static_cell_references(Remap, Procedure0, Procedure) :-
+ Code0 = Procedure0 ^ cproc_code,
+ Code = list.map(remap_instruction(Remap), Code0),
+ Procedure = Procedure0 ^ cproc_code := Code.
+
+:- func remap_instruction(static_cell_remap_info, instruction) = instruction.
+
+remap_instruction(Remap, Instr0 - Comment)
+ = remap_instr(Remap, Instr0) - Comment.
+
+:- func remap_instr(static_cell_remap_info, instr) = instr.
+
+remap_instr(Remap, Instr0) = Instr :-
+ (
+ Instr0 = block(NumIntTemps, NumFloatTemps, Block0),
+ Instr = block(NumIntTemps, NumFloatTemps, Block),
+ Block = list.map(remap_instruction(Remap), Block0)
+ ;
+ Instr0 = assign(Lval, Rval0),
+ Instr = assign(Lval, Rval),
+ Rval = remap_rval(Remap, Rval0)
+ ;
+ Instr0 = if_val(Rval0, CodeAddr),
+ Instr = if_val(Rval, CodeAddr),
+ Rval = remap_rval(Remap, Rval0)
+ ;
+ ( Instr0 = comment(_)
+ ; Instr0 = livevals(_)
+ ; Instr0 = llcall(_, _, _, _, _, _)
+ ; Instr0 = mkframe(_, _)
+ ; Instr0 = label(_)
+ ; Instr0 = goto(_)
+ ; Instr0 = computed_goto(_, _)
+ ; Instr0 = arbitrary_c_code(_, _)
+ ; Instr0 = save_maxfr(_)
+ ; Instr0 = restore_maxfr(_)
+ ; Instr0 = incr_hp(_, _, _, _, _)
+ ; Instr0 = mark_hp(_)
+ ; Instr0 = restore_hp(_)
+ ; Instr0 = free_heap(_)
+ ; Instr0 = store_ticket(_)
+ ; Instr0 = reset_ticket(_, _)
+ ; Instr0 = prune_ticket
+ ; Instr0 = discard_ticket
+ ; Instr0 = mark_ticket_stack(_)
+ ; Instr0 = prune_tickets_to(_)
+ ; Instr0 = incr_sp(_, _)
+ ; Instr0 = decr_sp(_)
+ ; Instr0 = decr_sp_and_return(_)
+ ; Instr0 = pragma_c(_, _, _, _, _, _, _, _, _)
+ ; Instr0 = init_sync_term(_, _)
+ ; Instr0 = fork(_, _, _)
+ ; Instr0 = join_and_terminate(_)
+ ; Instr0 = join_and_continue(_, _)
+ ),
+ Instr = Instr0
+ ).
+
+:- func remap_lval(static_cell_remap_info, lval) = lval.
+
+remap_lval(Remap, Lval0) = Lval :-
+ (
+ Lval0 = field(MaybeTag, Rval0, FieldNum),
+ Lval = field(MaybeTag, Rval, FieldNum),
+ Rval = remap_rval(Remap, Rval0)
+ ;
+ Lval0 = mem_ref(Rval0),
+ Lval = mem_ref(Rval),
+ Rval = remap_rval(Remap, Rval0)
+ ;
+ ( Lval0 = reg(_, _)
+ ; Lval0 = succip
+ ; Lval0 = maxfr
+ ; Lval0 = curfr
+ ; Lval0 = hp
+ ; Lval0 = sp
+ ; Lval0 = temp(_, _)
+ ; Lval0 = stackvar(_)
+ ; Lval0 = framevar(_)
+ ; Lval0 = succip_slot(_)
+ ; Lval0 = redoip_slot(_)
+ ; Lval0 = redofr_slot(_)
+ ; Lval0 = succfr_slot(_)
+ ; Lval0 = prevfr_slot(_)
+ ; Lval0 = global_var_ref(_)
+ ; Lval0 = lvar(_)
+ ),
+ Lval = Lval0
+ ).
+
+:- func remap_rval(static_cell_remap_info, rval) = rval.
+
+remap_rval(Remap, Rval0) = Rval :-
+ (
+ Rval0 = lval(Lval0),
+ Rval = lval(Lval),
+ Lval = remap_lval(Remap, Lval0)
+ ;
+ Rval0 = var(_),
+ Rval = Rval0
+ ;
+ Rval0 = mkword(Tag, Ptr0),
+ Rval = mkword(Tag, Ptr),
+ Ptr = remap_rval(Remap, Ptr0)
+ ;
+ Rval0 = const(Const0),
+ Rval = const(Const),
+ Const = remap_rval_const(Remap, Const0)
+ ;
+ Rval0 = unop(Unop, A0),
+ Rval = unop(Unop, A),
+ A = remap_rval(Remap, A0)
+ ;
+ Rval0 = binop(Binop, A0, B0),
+ Rval = binop(Binop, A, B),
+ A = remap_rval(Remap, A0),
+ B = remap_rval(Remap, B0)
+ ;
+ Rval0 = mem_addr(MemRef0),
+ Rval = mem_addr(MemRef),
+ MemRef = remap_mem_ref(Remap, MemRef0)
+ ).
+
+:- func remap_rval_const(static_cell_remap_info, rval_const) = rval_const.
+
+remap_rval_const(Remap, Const0) = Const :-
+ (
+ Const0 = data_addr_const(Addr0, MaybeOffset),
+ Const = data_addr_const(Addr, MaybeOffset),
+ (
+ Addr0 = data_addr(ModuleName, DataName0),
+ Addr = data_addr(ModuleName, DataName),
+ DataName = remap_data_name(Remap, DataName0)
+ ;
+ Addr0 = rtti_addr(_),
+ Addr = Addr0
+ ;
+ Addr0 = layout_addr(_),
+ Addr = Addr0
+ )
+ ;
+ ( Const0 = true
+ ; Const0 = false
+ ; Const0 = int_const(_)
+ ; Const0 = float_const(_)
+ ; Const0 = string_const(_)
+ ; Const0 = multi_string_const(_, _)
+ ; Const0 = code_addr_const(_)
+ ),
+ Const = Const0
+ ).
+
+:- func remap_data_name(static_cell_remap_info, data_name) = data_name.
+
+remap_data_name(Remap, DataName0) = DataName :-
+ Remap = static_cell_remap_info(TypeNumRemap, ScalarCellGroupRemap),
+ (
+ DataName0 = scalar_common_ref(TypeNum0, _Offset),
+ (if
+ map.contains(TypeNumRemap, TypeNum0)
+ then
+ DataName = ScalarCellGroupRemap ^ det_elem(TypeNum0)
+ ^ det_elem(DataName0)
+ else
+ DataName = DataName0
+ )
+ ;
+ DataName0 = vector_common_ref(TypeNum0, Offset),
+ (if
+ map.search(TypeNumRemap, TypeNum0, TypeNum)
+ then
+ DataName = vector_common_ref(TypeNum, Offset)
+ else
+ DataName = DataName0
+ )
+ ;
+ DataName0 = proc_tabling_ref(_, _),
+ DataName = DataName0
+ ).
+
+:- func remap_mem_ref(static_cell_remap_info, mem_ref) = mem_ref.
+
+remap_mem_ref(Remap, MemRef0) = MemRef :-
+ (
+ MemRef0 = stackvar_ref(_),
+ MemRef = MemRef0
+ ;
+ MemRef0 = framevar_ref(_),
+ MemRef = MemRef0
+ ;
+ MemRef0 = heap_ref(Ptr0, Tag, FieldNum),
+ MemRef = heap_ref(Ptr, Tag, FieldNum),
+ Ptr = remap_rval(Remap, Ptr0)
+ ).
+
+%-----------------------------------------------------------------------------%
:- func this_file = string.
Index: compiler/handle_options.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/handle_options.m,v
retrieving revision 1.270
diff -u -r1.270 handle_options.m
--- compiler/handle_options.m 27 Jul 2006 05:01:05 -0000 1.270
+++ compiler/handle_options.m 9 Aug 2006 07:19:44 -0000
@@ -1383,11 +1383,18 @@
true
),
- % --dump-hlds and --statistics require compilation by phases
+ % --dump-hlds, --statistics, --parallel-liveness and
+ % --parallel-code-gen require compilation by phases
globals.lookup_accumulating_option(!.Globals, dump_hlds, DumpStages),
+ globals.lookup_bool_option(!.Globals, parallel_liveness,
+ ParallelLiveness),
+ globals.lookup_bool_option(!.Globals, parallel_code_gen,
+ ParallelCodeGen),
(
( DumpStages = [_ | _]
; Statistics = yes
+ ; ParallelLiveness = yes
+ ; ParallelCodeGen = yes
)
->
globals.set_option(trad_passes, bool(no), !Globals)
Index: compiler/layout_out.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/layout_out.m,v
retrieving revision 1.69
diff -u -r1.69 layout_out.m
--- compiler/layout_out.m 9 Aug 2006 03:17:14 -0000 1.69
+++ compiler/layout_out.m 9 Aug 2006 03:17:34 -0000
@@ -500,7 +500,7 @@
:- type rval_or_numpair_or_none
---> rval(rval)
- ; num_pair(int, int)
+ ; num_pair(type_num, int)
; none.
:- pred output_rval_or_numpair_or_none(rval_or_numpair_or_none::in,
@@ -509,7 +509,7 @@
output_rval_or_numpair_or_none(rval(Rval), !IO) :-
io.write_string(", ", !IO),
output_rval_as_addr(Rval, !IO).
-output_rval_or_numpair_or_none(num_pair(Num1, Num2), !IO) :-
+output_rval_or_numpair_or_none(num_pair(type_num(Num1), Num2), !IO) :-
io.write_string(", ", !IO),
io.write_int(Num1, !IO),
io.write_string(", ", !IO),
Index: compiler/liveness.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/liveness.m,v
retrieving revision 1.149
diff -u -r1.149 liveness.m
--- compiler/liveness.m 31 Jul 2006 08:31:45 -0000 1.149
+++ compiler/liveness.m 16 Aug 2006 04:56:36 -0000
@@ -166,6 +166,13 @@
:- pred detect_liveness_proc(pred_id::in, proc_id::in, module_info::in,
proc_info::in, proc_info::out, io::di, io::uo) is det.
+ % Add liveness annotations to the goals of nonimported procedures in the
+ % module. Attempt to do so in parallel. Debugging liveness is not
+ % supported in this version.
+ %
+:- pred detect_liveness_preds_parallel(module_info::in, module_info::out)
+ is det.
+
% Return the set of variables live at the start of the procedure.
%
:- pred initial_liveness(proc_info::in, pred_id::in, module_info::in,
@@ -199,6 +206,7 @@
:- import_module assoc_list.
:- import_module bool.
+:- import_module int.
:- import_module list.
:- import_module map.
:- import_module maybe.
@@ -206,11 +214,84 @@
:- import_module string.
:- import_module svset.
:- import_module term.
+:- import_module unit.
:- import_module varset.
%-----------------------------------------------------------------------------%
+:- typeclass debug_liveness_io(T) where [
+ pred maybe_debug_liveness(string::in, int::in, int::in,
+ hlds_goal::in, prog_varset::in, module_info::in,
+ T::di, T::uo) is det
+].
+
+:- instance debug_liveness_io(io) where [
+ pred(maybe_debug_liveness/8) is io_maybe_debug_liveness
+].
+
+:- instance debug_liveness_io(unit) where [
+ maybe_debug_liveness(_, _, _, _, _, _, unit, unit)
+].
+
+%-----------------------------------------------------------------------------%
+
+detect_liveness_preds_parallel(!HLDS) :-
+ module_info_predids(!.HLDS, PredIds),
+ interleave(PredIds, PredIdsA, PredIdsB, 0, Length),
+ (
+ % Rather arbitrary.
+ Length < 1000
+ ->
+ list.foldl(detect_liveness_pred_putback, PredIds, !HLDS)
+ ;
+ ( list.map(detect_liveness_pred(!.HLDS), PredIdsA, PredInfosA)
+ & list.foldl(detect_liveness_pred_putback, PredIdsB, !HLDS)
+ ),
+ list.foldl_corresponding(module_info_set_pred_info,
+ PredIdsA, PredInfosA, !HLDS)
+ ).
+
+:- pred interleave(list(T)::in, list(T)::out, list(T)::out, int::in, int::out)
+ is det.
+
+interleave([], [], [], Length, Length).
+interleave([H|T], [H|As], Bs, Length0, Length) :-
+ interleave(T, Bs, As, Length0+1, Length).
+
+:- pred detect_liveness_pred_putback(pred_id::in,
+ module_info::in, module_info::out) is det.
+
+detect_liveness_pred_putback(PredId, !HLDS) :-
+ detect_liveness_pred(!.HLDS, PredId, PredInfo),
+ module_info_set_pred_info(PredId, PredInfo, !HLDS).
+
+:- pred detect_liveness_pred(module_info::in, pred_id::in, pred_info::out)
+ is det.
+
+detect_liveness_pred(ModuleInfo, PredId, PredInfo) :-
+ module_info_pred_info(ModuleInfo, PredId, PredInfo0),
+ ProcIds = pred_info_non_imported_procids(PredInfo0),
+ list.foldl(detect_liveness_pred_proc(ModuleInfo, PredId), ProcIds,
+ PredInfo0, PredInfo).
+
+:- pred detect_liveness_pred_proc(module_info::in, pred_id::in,
+ proc_id::in, pred_info::in, pred_info::out) is det.
+
+detect_liveness_pred_proc(ModuleInfo, PredId, ProcId, !PredInfo) :-
+ pred_info_proc_info(!.PredInfo, ProcId, ProcInfo0),
+ detect_liveness_proc_2(PredId, ModuleInfo, ProcInfo0, ProcInfo, unit, _),
+ pred_info_set_proc_info(ProcId, ProcInfo, !PredInfo).
+
+%-----------------------------------------------------------------------------%
+
detect_liveness_proc(PredId, _ProcId, ModuleInfo, !ProcInfo, !IO) :-
+ detect_liveness_proc_2(PredId, ModuleInfo, !ProcInfo, !IO).
+
+:- pred detect_liveness_proc_2(pred_id::in, module_info::in,
+ proc_info::in, proc_info::out, IO::di, IO::uo) is det
+ <= debug_liveness_io(IO).
+
+detect_liveness_proc_2(PredId, ModuleInfo, !ProcInfo, !IO) :-
requantify_proc(!ProcInfo),
proc_info_get_goal(!.ProcInfo, Goal0),
@@ -225,18 +306,18 @@
globals.lookup_int_option(Globals, debug_liveness, DebugLiveness),
pred_id_to_int(PredId, PredIdInt),
- maybe_write_progress_message("\nbefore liveness",
+ maybe_debug_liveness("\nbefore liveness",
DebugLiveness, PredIdInt, Goal0, VarSet, ModuleInfo, !IO),
initial_liveness(!.ProcInfo, PredId, ModuleInfo, Liveness0),
detect_liveness_in_goal(Goal0, Goal1, Liveness0, _, LiveInfo),
- maybe_write_progress_message("\nafter liveness",
+ maybe_debug_liveness("\nafter liveness",
DebugLiveness, PredIdInt, Goal1, VarSet, ModuleInfo, !IO),
initial_deadness(!.ProcInfo, LiveInfo, ModuleInfo, Deadness0),
detect_deadness_in_goal(Goal1, Goal2, Deadness0, _, Liveness0, LiveInfo),
- maybe_write_progress_message("\nafter deadness",
+ maybe_debug_liveness("\nafter deadness",
DebugLiveness, PredIdInt, Goal2, VarSet, ModuleInfo, !IO),
(
@@ -247,7 +328,7 @@
DelayDeath = yes
->
delay_death_proc_body(Goal2, Goal3, VarSet, Liveness0),
- maybe_write_progress_message("\nafter delay death",
+ maybe_debug_liveness("\nafter delay death",
DebugLiveness, PredIdInt, Goal3, VarSet, ModuleInfo, !IO)
;
Goal3 = Goal2
@@ -261,16 +342,16 @@
),
detect_resume_points_in_goal(Goal3, Goal, Liveness0, _,
LiveInfo, ResumeVars0),
- maybe_write_progress_message("\nafter resume point",
+ maybe_debug_liveness("\nafter resume point",
DebugLiveness, PredIdInt, Goal, VarSet, ModuleInfo, !IO),
proc_info_set_goal(Goal, !ProcInfo),
proc_info_set_liveness_info(Liveness0, !ProcInfo).
-:- pred maybe_write_progress_message(string::in, int::in, int::in,
+:- pred io_maybe_debug_liveness(string::in, int::in, int::in,
hlds_goal::in, prog_varset::in, module_info::in,
io::di, io::uo) is det.
-maybe_write_progress_message(Message, DebugLiveness, PredIdInt,
+io_maybe_debug_liveness(Message, DebugLiveness, PredIdInt,
Goal, VarSet, ModuleInfo, !IO) :-
( DebugLiveness = PredIdInt ->
io.write_string(Message, !IO),
Index: compiler/llds.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/llds.m,v
retrieving revision 1.335
diff -u -r1.335 llds.m
--- compiler/llds.m 28 Jul 2006 05:08:09 -0000 1.335
+++ compiler/llds.m 3 Aug 2006 06:27:36 -0000
@@ -131,13 +131,16 @@
rval % The field value.
).
+:- type type_num
+ ---> type_num(int).
+
:- type scalar_common_data_array
---> scalar_common_data_array(
scda_module :: module_name,
% The basename of this C file.
scda_rval_types :: common_cell_type,
% The type of the elements of the array.
- scda_type_num :: int,
+ scda_type_num :: type_num,
% The type number.
scda_values :: list(common_cell_value)
% The array elements, starting at offset 0.
@@ -149,7 +152,7 @@
% The basename of this C file.
vcda_rval_types :: common_cell_type,
% The type of the elements of the array.
- vcda_type_num :: int,
+ vcda_type_num :: type_num,
% The type number.
vcda_vector_num :: int,
% The number of this vector, among all the
@@ -899,7 +902,7 @@
; layout_addr(layout_name).
:- type data_name
- ---> scalar_common_ref(int, int)
+ ---> scalar_common_ref(type_num, int)
% We store all standalone (scalar) common cells of the same type
% in an array. A reference to one of these cells contains the
% the type number (which becomes the distinguishing part of the
@@ -907,7 +910,7 @@
% which is stored in the first integer, and the offset within
% this array, which is stored in the second integer.
- ; vector_common_ref(int, int)
+ ; vector_common_ref(type_num, int)
% We store each vector of common cells in its own global variable,
% identified by a sequence number. The first integer is this
% sequence number; the second is the offset in the array.
Index: compiler/llds_out.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/llds_out.m,v
retrieving revision 1.286
diff -u -r1.286 llds_out.m
--- compiler/llds_out.m 31 Jul 2006 08:31:45 -0000 1.286
+++ compiler/llds_out.m 3 Aug 2006 06:27:36 -0000
@@ -133,8 +133,8 @@
% to put these in a new module (maybe llds_out_util).
:- type decl_id
- ---> decl_common_type(int)
- ; decl_scalar_common_array(int)
+ ---> decl_common_type(type_num)
+ ; decl_scalar_common_array(type_num)
; decl_float_label(string)
; decl_code_addr(code_addr)
; decl_data_addr(data_addr)
@@ -1160,7 +1160,7 @@
%-----------------------------------------------------------------------------%
-:- pred output_common_type_defn(int::in, common_cell_type::in,
+:- pred output_common_type_defn(type_num::in, common_cell_type::in,
decl_set::in, decl_set::out, io::di, io::uo) is det.
output_common_type_defn(TypeNum, CellType, !DeclSet, !IO) :-
@@ -4258,22 +4258,23 @@
mercury_var_prefix ++ "_proc" ++ tabling_info_id_str(Id) ++ "__" ++
proc_label_to_c_string(ProcLabel, no).
-:- pred output_common_cell_type_name(int::in, io::di, io::uo) is det.
+:- pred output_common_cell_type_name(type_num::in, io::di, io::uo) is det.
-output_common_cell_type_name(TypeNum, !IO) :-
+output_common_cell_type_name(type_num(TypeNum), !IO) :-
io.write_string(mercury_common_type_prefix, !IO),
io.write_int(TypeNum, !IO).
-:- pred output_common_scalar_cell_array_name(int::in, io::di, io::uo) is det.
+:- pred output_common_scalar_cell_array_name(type_num::in, io::di, io::uo)
+ is det.
-output_common_scalar_cell_array_name(TypeNum, !IO) :-
+output_common_scalar_cell_array_name(type_num(TypeNum), !IO) :-
io.write_string(mercury_scalar_common_array_prefix, !IO),
io.write_int(TypeNum, !IO).
-:- pred output_common_vector_cell_array_name(int::in, int::in, io::di, io::uo)
- is det.
+:- pred output_common_vector_cell_array_name(type_num::in, int::in,
+ io::di, io::uo) is det.
-output_common_vector_cell_array_name(TypeNum, CellNum, !IO) :-
+output_common_vector_cell_array_name(type_num(TypeNum), CellNum, !IO) :-
io.write_string(mercury_vector_common_array_prefix, !IO),
io.write_int(TypeNum, !IO),
io.write_string("_", !IO),
@@ -4805,7 +4806,7 @@
(
Exprn = const(data_addr_const(DataAddr, no)),
DataAddr = data_addr(_, DataName),
- DataName = scalar_common_ref(TypeNum, CellNum)
+ DataName = scalar_common_ref(type_num(TypeNum), CellNum)
->
io.write_string("MR_TAG_COMMON(", !IO),
io.write_int(Tag, !IO),
@@ -4931,7 +4932,7 @@
% very substantial.
(
DataAddr = data_addr(_, DataName),
- DataName = scalar_common_ref(TypeNum, CellNum)
+ DataName = scalar_common_ref(type_num(TypeNum), CellNum)
->
io.write_string("MR_COMMON(", !IO),
io.write_int(TypeNum, !IO),
Index: compiler/mercury_compile.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/mercury_compile.m,v
retrieving revision 1.396
diff -u -r1.396 mercury_compile.m
--- compiler/mercury_compile.m 9 Aug 2006 04:56:35 -0000 1.396
+++ compiler/mercury_compile.m 16 Aug 2006 03:09:33 -0000
@@ -3979,8 +3979,17 @@
compute_liveness(Verbose, Stats, !HLDS, !IO) :-
maybe_write_string(Verbose, "% Computing liveness...\n", !IO),
maybe_flush_output(Verbose, !IO),
- process_all_nonimported_procs(update_proc_io(detect_liveness_proc),
- !HLDS, !IO),
+ globals.io_lookup_bool_option(parallel_liveness, ParallelLiveness, !IO),
+ globals.io_lookup_int_option(debug_liveness, DebugLiveness, !IO),
+ (
+ ParallelLiveness = yes,
+ DebugLiveness = -1
+ ->
+ detect_liveness_preds_parallel(!HLDS)
+ ;
+ process_all_nonimported_procs(update_proc_io(detect_liveness_proc),
+ !HLDS, !IO)
+ ),
maybe_write_string(Verbose, "% done.\n", !IO),
maybe_report_stats(Stats, !IO).
Index: compiler/opt_debug.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/opt_debug.m,v
retrieving revision 1.171
diff -u -r1.171 opt_debug.m
--- compiler/opt_debug.m 28 Jul 2006 05:08:14 -0000 1.171
+++ compiler/opt_debug.m 3 Aug 2006 06:27:37 -0000
@@ -347,10 +347,10 @@
dump_data_addr(layout_addr(LayoutName)) =
"layout_addr(" ++ dump_layout_name(LayoutName) ++ ")".
-dump_data_name(scalar_common_ref(TypeNum, Offset)) =
+dump_data_name(scalar_common_ref(type_num(TypeNum), Offset)) =
"scalar_common_ref(" ++ int_to_string(TypeNum) ++ ", "
++ int_to_string(Offset) ++ ")".
-dump_data_name(vector_common_ref(TypeNum, Offset)) =
+dump_data_name(vector_common_ref(type_num(TypeNum), Offset)) =
"vector_common_ref(" ++ int_to_string(TypeNum) ++ ", "
++ int_to_string(Offset) ++ ")".
dump_data_name(proc_tabling_ref(ProcLabel, Id)) =
Index: compiler/options.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/options.m,v
retrieving revision 1.523
diff -u -r1.523 options.m
--- compiler/options.m 14 Aug 2006 03:31:31 -0000 1.523
+++ compiler/options.m 15 Aug 2006 06:10:30 -0000
@@ -431,6 +431,8 @@
; low_level_debug
; table_debug
; trad_passes
+ ; parallel_liveness
+ ; parallel_code_gen
; polymorphism
; reclaim_heap_on_failure
; reclaim_heap_on_semidet_failure
@@ -1103,6 +1105,8 @@
low_level_debug - bool(no),
table_debug - bool(no),
trad_passes - bool(yes),
+ parallel_liveness - bool(no),
+ parallel_code_gen - bool(no),
polymorphism - bool(yes),
reclaim_heap_on_failure - bool_special,
reclaim_heap_on_semidet_failure - bool(yes),
@@ -1816,6 +1820,8 @@
long_option("table-debug", table_debug).
long_option("polymorphism", polymorphism).
long_option("trad-passes", trad_passes).
+long_option("parallel-liveness", parallel_liveness).
+long_option("parallel-code-gen", parallel_code_gen).
long_option("reclaim-heap-on-failure", reclaim_heap_on_failure).
long_option("reclaim-heap-on-semidet-failure",
reclaim_heap_on_semidet_failure).
@@ -3784,6 +3790,16 @@
"\tThis option tells the compiler",
"\tto complete each phase of code generation on all predicates",
"\tbefore going on the next phase on all predicates.",
+ % "--parallel-liveness",
+ % "Use multiple threads when computing liveness.",
+ % "At the moment this option implies `--no-trad-passes',",
+ % "and requires the compiler to be built in a",
+ % "low-level parallel grade and running with multiple engines.",
+ % "--parallel-code-gen",
+ % "Use multiple threads when generating code.",
+ % "At the moment this option implies `--no-trad-passes',",
+ % "and requires the compiler to be built in a",
+ % "low-level parallel grade and running with multiple engines.",
% "\t--no-polymorphism",
% "\t\tDon't handle polymorphic types.",
% "\t\t(Generates slightly more efficient code, but stops",
Index: compiler/proc_gen.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/proc_gen.m,v
retrieving revision 1.4
diff -u -r1.4 proc_gen.m
--- compiler/proc_gen.m 28 Jul 2006 05:08:14 -0000 1.4
+++ compiler/proc_gen.m 16 Aug 2006 05:04:47 -0000
@@ -117,34 +117,105 @@
generate_code(ModuleInfo0, !GlobalData, Procedures, !IO) :-
% Get a list of all the predicate ids for which we will generate code.
module_info_predids(ModuleInfo0, PredIds),
- % Now generate the code for each predicate.
- generate_pred_list_code(ModuleInfo0, !GlobalData, PredIds,
- Procedures, !IO).
-
- % Translate a list of HLDS predicates to LLDS.
- %
-:- pred generate_pred_list_code(module_info::in,
- global_data::in, global_data::out,
- list(pred_id)::in, list(c_procedure)::out, io::di, io::uo) is det.
-
-generate_pred_list_code(_ModuleInfo, !GlobalData, [], [], !IO).
-generate_pred_list_code(ModuleInfo, !GlobalData, [PredId | PredIds],
- Predicates, !IO) :-
- generate_maybe_pred_code(ModuleInfo, !GlobalData, PredId,
- Predicates0, !IO),
- generate_pred_list_code(ModuleInfo, !GlobalData, PredIds,
- Predicates1, !IO),
- list.append(Predicates0, Predicates1, Predicates).
+ % Check if we want to use parallel code generation.
+ module_info_get_globals(ModuleInfo0, Globals),
+ globals.lookup_bool_option(Globals, parallel_code_gen, ParallelCodeGen),
+ globals.lookup_bool_option(Globals, very_verbose, VeryVerbose),
+ globals.lookup_bool_option(Globals, detailed_statistics, Statistics),
+ (
+ ParallelCodeGen = yes,
+ % Can't do parallel code generation if I/O is required.
+ VeryVerbose = no,
+ Statistics = no
+ ->
+ generate_code_maybe_parallel(ModuleInfo0, PredIds, !GlobalData,
+ Procedures, !IO)
+ ;
+ generate_code_sequential(ModuleInfo0, PredIds, !GlobalData,
+ Procedures, !IO)
+ ).
+
+:- pred generate_code_sequential(module_info::in, list(pred_id)::in,
+ global_data::in, global_data::out, list(c_procedure)::out, io::di, io::uo)
+ is det.
+
+generate_code_sequential(ModuleInfo0, PredIds, !GlobalData, Procedures, !IO) :-
+ list.map_foldl2(generate_maybe_pred_code(ModuleInfo0),
+ PredIds, PredProcedures, !GlobalData, !IO),
+ list.condense(PredProcedures, Procedures).
+
+%-----------------------------------------------------------------------------%
+
+:- pred generate_code_maybe_parallel(module_info::in, list(pred_id)::in,
+ global_data::in, global_data::out, list(c_procedure)::out, io::di, io::uo)
+ is det.
+
+generate_code_maybe_parallel(ModuleInfo0, PredIds, !GlobalData, Procedures,
+ !IO) :-
+ list.length(PredIds, Len),
+ (if Len < min_parallel_preds then
+ generate_code_sequential(ModuleInfo0, PredIds, !GlobalData,
+ Procedures, !IO)
+ else
+ % Split up the list of predicates into pieces for processing in
+ % parallel. Splitting the list in the middle does not work well as the
+ % load will be unbalanced. However, splitting the list differently way
+ % does mean that the generated code will be slightly different, due to
+ % the static data being reordered.
+ list.chunk(PredIds, pred_list_chunk_size, ListOfLists),
+ interleave(ListOfLists, ListsOfPredIdsA, ListsOfPredIdsB),
+ (
+ list.condense(ListsOfPredIdsA, PredIdsA),
+ list.map_foldl(generate_pred_code_par(ModuleInfo0),
+ PredIdsA, PredProceduresA, !.GlobalData, GlobalDataA),
+ list.condense(PredProceduresA, ProceduresA)
+ &
+ list.condense(ListsOfPredIdsB, PredIdsB),
+ GlobalData1 = bump_type_num_counter(!.GlobalData, type_num_skip),
+ list.map_foldl(generate_pred_code_par(ModuleInfo0),
+ PredIdsB, PredProceduresB0, GlobalData1, GlobalDataB),
+ list.condense(PredProceduresB0, ProceduresB0)
+ ),
+ merge_global_datas(GlobalDataA, GlobalDataB, !:GlobalData,
+ StaticCellRemapInfo),
+ list.map(remap_static_cell_references(StaticCellRemapInfo),
+ ProceduresB0, ProceduresB),
+ Procedures = ProceduresA ++ ProceduresB
+ ).
+
+ % These numbers are all rather arbitrary.
+ %
+:- func min_parallel_preds = int.
+min_parallel_preds = 400.
+
+:- func pred_list_chunk_size = int.
+pred_list_chunk_size = 50.
+
+:- func type_num_skip = int.
+type_num_skip = 10000.
+
+:- pred interleave(list(T)::in, list(T)::out, list(T)::out) is det.
+:- pred interleave_2(list(T)::in, list(T)::in, list(T)::out,
+ list(T)::in, list(T)::out) is det.
+
+interleave(L, reverse(As), reverse(Bs)) :-
+ interleave_2(L, [], As, [], Bs).
+
+interleave_2([], !As, !Bs).
+interleave_2([H|T], As0, As, Bs0, Bs) :-
+ interleave_2(T, Bs0, Bs, [H|As0], As).
+
+%-----------------------------------------------------------------------------%
:- pred generate_maybe_pred_code(module_info::in,
- global_data::in, global_data::out, pred_id::in,
- list(c_procedure)::out, io::di, io::uo) is det.
+ pred_id::in, list(c_procedure)::out,
+ global_data::in, global_data::out, io::di, io::uo) is det.
% Note that some of the logic of generate_maybe_pred_code is duplicated
% by mercury_compile.backend_pass_by_preds, so modifications here may
% also need to be repeated there.
%
-generate_maybe_pred_code(ModuleInfo, !GlobalData, PredId, Predicates, !IO) :-
+generate_maybe_pred_code(ModuleInfo, PredId, Predicates, !GlobalData, !IO) :-
module_info_preds(ModuleInfo, PredInfos),
map.lookup(PredInfos, PredId, PredInfo),
ProcIds = pred_info_non_imported_procids(PredInfo),
@@ -170,6 +241,16 @@
PredId, PredInfo, ProcIds, Predicates)
).
+:- pred generate_pred_code_par(module_info::in, pred_id::in,
+ list(c_procedure)::out, global_data::in, global_data::out) is det.
+
+generate_pred_code_par(ModuleInfo, PredId, Predicates, !GlobalData) :-
+ module_info_preds(ModuleInfo, PredInfos),
+ map.lookup(PredInfos, PredId, PredInfo),
+ ProcIds = pred_info_non_imported_procids(PredInfo),
+ generate_pred_code(ModuleInfo, !GlobalData,
+ PredId, PredInfo, ProcIds, Predicates).
+
% Translate a HLDS predicate to LLDS.
%
:- pred generate_pred_code(module_info::in, global_data::in, global_data::out,
Index: doc/user_guide.texi
===================================================================
RCS file: /home/mercury1/repository/mercury/doc/user_guide.texi,v
retrieving revision 1.485
diff -u -r1.485 user_guide.texi
--- doc/user_guide.texi 9 Aug 2006 04:56:36 -0000 1.485
+++ doc/user_guide.texi 15 Aug 2006 06:10:31 -0000
@@ -6740,6 +6740,24 @@
before going on the next phase on all predicates.
@c @sp 1
+ at c @item --parallel-liveness
+ at c @item --no-parallel-liveness
+ at c @item --parallel-liveness
+ at c Use multiple threads when computing liveness.
+ at c At the moment this option implies @samp{--no-trad-passes},
+ at c and requires the compiler to be built in a
+ at c low-level parallel grade and running with multiple engines.
+
+ at c @sp 1
+ at c @item --parallel-code-gen
+ at c @item --no-parallel-code-gen
+ at c @item --parallel-code-gen
+ at c Use multiple threads when generating code.
+ at c At the moment this option implies @samp{--no-trad-passes},
+ at c and requires the compiler to be built in a
+ at c low-level parallel grade and running with multiple engines.
+
+ at c @sp 1
@c @item --no-polymorphism
@c Don't handle polymorphic types.
@c (Generates slightly more efficient code, but stops
Index: runtime/mercury_context.c
===================================================================
RCS file: /home/mercury1/repository/mercury/runtime/mercury_context.c,v
retrieving revision 1.47
diff -u -r1.47 mercury_context.c
--- runtime/mercury_context.c 5 Jul 2006 03:00:43 -0000 1.47
+++ runtime/mercury_context.c 9 Aug 2006 11:59:33 -0000
@@ -237,6 +237,14 @@
void
MR_destroy_context(MR_Context *c)
{
+#if defined(MR_CONSERVATIVE_GC) && !defined(MR_HIGHLEVEL_CODE)
+ /* Clear stacks to prevent retention of data. */
+ MR_clear_zone_for_GC(c->MR_ctxt_detstack_zone,
+ c->MR_ctxt_detstack_zone->MR_zone_min);
+ MR_clear_zone_for_GC(c->MR_ctxt_nondetstack_zone,
+ c->MR_ctxt_nondetstack_zone->MR_zone_min);
+#endif /* defined(MR_CONSERVATIVE_GC) && !defined(MR_HIGHLEVEL_CODE) */
+
MR_LOCK(&free_context_list_lock, "destroy_context");
c->MR_ctxt_next = free_context_list;
free_context_list = c;
--------------------------------------------------------------------------
mercury-reviews mailing list
Post messages to: mercury-reviews at csse.unimelb.edu.au
Administrative Queries: owner-mercury-reviews at csse.unimelb.edu.au
Subscriptions: mercury-reviews-request at csse.unimelb.edu.au
--------------------------------------------------------------------------
More information about the reviews
mailing list