Files
mercury/compiler/arg_pack.m
Peter Wang 4c2846593a Make it possible to store double-precision `float' constructor arguments in
Branches: main

Make it possible to store double-precision `float' constructor arguments in
unboxed form, in low-level C grades on 32-bit platforms, i.e. `float' (and
equivalent) arguments may occupy two machine words. However, until we implement
float registers, this does more harm than good so it remains disabled.

compiler/llds.m:
	Add a type `cell_arg' to hold information about an argument of a cell
	being constructed.

	Change `heap_ref' so that we can refer to a pointer with an unknown
	tag.

compiler/unify_gen.m:
	Use the `cell_arg' type to simplify code related to generating
	constructions.

	Handle double word arguments in constructions and deconstructions.

	Update enumeration packing code to account for the presence of double
	width arguments and the `cell_arg' type.

	Take double width arguments into account when generating ground terms.

compiler/code_info.m:
	Extend `assign_field_lval_expr_to_var' to work for expressions
	involving multiple field lvals of the same variable.

	Make `assign_cell_to_var' conform to changes.

compiler/code_util.m:
	Add a predicate to calculate the size of a cell given its cell_args.

compiler/var_locn.m:
	Conform to the use of the `cell_arg' type and the presense of double
	width arguments.

	Calculate cell size correctly in places.

	Move sanity checking from `var_locn_assign_field_lval_expr_to_var'
	to `code_info.assign_field_lval_expr_to_var'.

compiler/global_data.m:
	Make `rval_type_as_arg' take into account the width of the argument.

	Conform to changes.

compiler/c_util.m:
	Add a new binop category.  Unlike the existing macro_binop category,
	the arguments of macros in this category cannot all be assumed to be
	of integral types.

compiler/llds_out_data.m:
compiler/llds_out_instr.m:
	Output calls to the macros `MR_float_word_bits', `MR_float_from_dword'
	and `MR_float_from_dword_ptr' which were introduced previously.

	When a `heap_ref' has an unknown tag, make the generated code mask off
	the tag bits.

compiler/lco.m:
	Disable the optimisation when float arguments are present, on the basis
	of whether Mercury floats are wider than a machine word.  The comments
	about when floats are stored in boxed form are out of date.

compiler/arg_pack.m:
	Rename a predicate.

compiler/make_hlds_passes.m:
	Update a comment.

compiler/disj_gen.m:
compiler/exprn_aux.m:
compiler/global_data.m:
compiler/llds_to_x86_64.m:
compiler/lookup_switch.m:
compiler/mlds_to_c.m:
compiler/opt_debug.m:
compiler/opt_util.m:
compiler/stack_layout.m:
compiler/string_switch.m:
	Conform to changes.

runtime/mercury_float.h:
	Add a cast to `MR_float_word_bits' to avoid a gcc error.

tests/hard_coded/Mercury.options:
tests/hard_coded/Mmakefile:
tests/hard_coded/heap_ref_mask_tag.exp:
tests/hard_coded/heap_ref_mask_tag.m:
tests/hard_coded/reuse_double.exp:
tests/hard_coded/reuse_double.m:
	Add test cases.

tests/hard_coded/lookup_disj.exp:
tests/hard_coded/lookup_disj.m:
	Extend existing test case.
2011-09-16 07:03:36 +00:00

181 lines
6.1 KiB
Mathematica

%-----------------------------------------------------------------------------%
% vim: ft=mercury ts=4 sw=4 et
%-----------------------------------------------------------------------------%
% Copyright (C) 2011 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: arg_pack.m.
% Main author: wangp.
%
% Utilities for argument packing.
%
%-----------------------------------------------------------------------------%
:- module backend_libs.arg_pack.
:- interface.
:- import_module parse_tree.
:- import_module parse_tree.prog_data.
:- import_module list.
:- import_module maybe.
%-----------------------------------------------------------------------------%
% Packs an argument list such that consecutive arguments which should share
% the same word are converted to a single argument.
%
% The predicate ShiftCombine takes an argument `A' and shift count `Shift'
% (which may be zero). If it is also given the argument `yes(B)' then it
% should produce the combined value `(A << Shift) \/ B'.
% Otherwise, it should produce the value `(A << Shift)'.
%
:- pred pack_args(pred(T, int, maybe(T), T, Acc1, Acc1, Acc2, Acc2)::in(
pred(in, in, in, out, in, out, in, out) is det), list(arg_width)::in,
list(T)::in, list(T)::out, Acc1::in, Acc1::out, Acc2::in, Acc2::out)
is det.
% Return the number of distinct words that would be required to hold the
% list of arguments.
%
:- func count_distinct_words(list(arg_width)) = int.
% Group elements into sub-lists according to the word boundaries implied by
% the list of argument widths. That is, elements which make up part of the
% same word (or double word) are grouped together in a sub-list.
%
:- pred group_same_word_elements(list(arg_width)::in, list(T)::in,
list(list(T))::out) is det.
%-----------------------------------------------------------------------------%
%-----------------------------------------------------------------------------%
:- implementation.
:- import_module int.
:- import_module require.
%-----------------------------------------------------------------------------%
pack_args(ShiftCombine, ArgWidths, !Args, !Acc1, !Acc2) :-
( list.member(partial_word_first(_), ArgWidths) ->
do_pack_args(ShiftCombine, ArgWidths, !Args, !Acc1, !Acc2)
;
true
).
:- pred do_pack_args(pred(T, int, maybe(T), T, Acc1, Acc1, Acc2, Acc2)::in(
pred(in, in, in, out, in, out, in, out) is det), list(arg_width)::in,
list(T)::in, list(T)::out, Acc1::in, Acc1::out, Acc2::in, Acc2::out)
is det.
do_pack_args(_, [], [], [], !Acc1, !Acc2).
do_pack_args(ShiftCombine, [Width | Widths], [Arg0 | Args0], [Arg | Args],
!Acc1, !Acc2) :-
(
Width = full_word,
Shift = 0
;
Width = double_word,
Shift = 0
;
Width = partial_word_first(_Mask),
Shift = 0
;
Width = partial_word_shifted(Shift, _Mask)
),
( belongs_in_same_word(Width, Widths) ->
do_pack_args(ShiftCombine, Widths, Args0, Args1, !Acc1, !Acc2),
(
Args1 = [SecondArg | Args],
ShiftCombine(Arg0, Shift, yes(SecondArg), Arg, !Acc1, !Acc2)
;
Args1 = [],
unexpected($module, $pred, "mismatched lists")
)
;
ShiftCombine(Arg0, Shift, no, Arg, !Acc1, !Acc2),
do_pack_args(ShiftCombine, Widths, Args0, Args, !Acc1, !Acc2)
).
do_pack_args(_, [], [_ | _], _, !Acc1, !Acc2) :-
unexpected($module, $pred, "mismatched lists").
do_pack_args(_, [_ | _], [], _, !Acc1, !Acc2) :-
unexpected($module, $pred, "mismatched lists").
:- pred belongs_in_same_word(arg_width::in, list(arg_width)::in) is semidet.
belongs_in_same_word(Prev, [Next | _]) :-
( Prev = partial_word_first(_)
; Prev = partial_word_shifted(_, _)
),
Next = partial_word_shifted(_, _).
%-----------------------------------------------------------------------------%
count_distinct_words([]) = 0.
count_distinct_words([H | T]) = Words :-
(
H = full_word,
Words = 1 + count_distinct_words(T)
;
H = double_word,
Words = 2 + count_distinct_words(T)
;
H = partial_word_first(_),
Words = 1 + count_distinct_words(T)
;
H = partial_word_shifted(_, _),
Words = count_distinct_words(T)
).
%-----------------------------------------------------------------------------%
group_same_word_elements([], [], []).
group_same_word_elements([W | Ws], [X | Xs], Xss) :-
(
( W = full_word
; W = double_word
),
group_same_word_elements(Ws, Xs, Xss0),
Xss = [[X] | Xss0]
;
W = partial_word_first(_),
split_at_next_word(Ws, WsTail, Xs, XsHead, XsTail),
group_same_word_elements(WsTail, XsTail, Xss0),
Xss = [[X | XsHead] | Xss0]
;
W = partial_word_shifted(_, _),
unexpected($module, $pred, "partial_word_shifted")
).
group_same_word_elements([], [_ | _], _) :-
unexpected($module, $pred, "mismatched lists").
group_same_word_elements([_ | _], [], []) :-
unexpected($module, $pred, "mismatched lists").
:- pred split_at_next_word(list(arg_width)::in, list(arg_width)::out,
list(T)::in, list(T)::out, list(T)::out) is det.
split_at_next_word([], [], XsTail, [], XsTail).
split_at_next_word([W | Ws], WsTail, [X | Xs], XsHead, XsTail) :-
(
( W = full_word
; W = double_word
; W = partial_word_first(_)
),
WsTail = [W | Ws],
XsHead = [],
XsTail = [X | Xs]
;
W = partial_word_shifted(_, _),
split_at_next_word(Ws, WsTail, Xs, XsHead0, XsTail),
XsHead = [X | XsHead0]
).
split_at_next_word([_ | _], _, [], _, _) :-
unexpected($module, $pred, "mismatched lists").
%-----------------------------------------------------------------------------%
:- end_module backend_libs.arg_pack.
%-----------------------------------------------------------------------------%