mirror of
https://github.com/Mercury-Language/mercury.git
synced 2025-12-21 00:39:37 +00:00
Estimated hours taken: 50
Add support for nested modules.
- module names may themselves be module-qualified
- modules may contain `:- include_module' declarations
which name sub-modules
- a sub-module has access to all the declarations in the
parent module (including its implementation section).
This support is not yet complete; see the BUGS and LIMITATIONS below.
LIMITATIONS
- source file names must match module names
(just as they did previously)
- mmc doesn't allow path names on the command line any more
(e.g. `mmc --make-int ../library/foo.m').
- import_module declarations must use the fully-qualified module name
- module qualifiers must use the fully-qualified module name
- no support for root-qualified module names
(e.g. `:parent:child' instead of `parent:child').
- modules may not be physically nested (only logical nesting, via
`include_module').
BUGS
- doesn't check that the parent module is imported/used before allowing
import/use of its sub-modules.
- doesn't check that there is an include_module declaration in the
parent for each module claiming to be a child of that parent
- privacy of private modules is not enforced
-------------------
NEWS:
Mention that we support nested modules.
library/ops.m:
library/nc_builtin.nl:
library/sp_builtin.nl:
compiler/mercury_to_mercury.m:
Add `include_module' as a new prefix operator.
Change the associativity of `:' from xfy to yfx
(since this made parsing module qualifiers slightly easier).
compiler/prog_data.m:
Add new `include_module' declaration.
Change the `module_name' and `module_specifier' types
from strings to sym_names, so that module names can
themselves be module qualified.
compiler/modules.m:
Add predicates module_name_to_file_name/2 and
file_name_to_module_name/2.
Lots of changes to handle parent module dependencies,
to create parent interface (`.int0') files, to read them in,
to output correct dependencies information for them to the
`.d' and `.dep' files, etc.
Rewrite a lot of the code to improve the readability
(add comments, use subroutines, better variable names).
Also fix a couple of bugs:
- generate_dependencies was using the transitive implementation
dependencies rather than the transitive interface dependencies
to compute the `.int3' dependencies when writing `.d' files
(this bug was introduced during crs's changes to support
`.trans_opt' files)
- when creating the `.int' file, it was reading in the
interfaces for modules imported in the implementation section,
not just those in the interface section.
This meant that the compiler missed a lot of errors.
library/graph.m:
library/lexer.m:
library/term.m:
library/term_io.m:
library/varset.m:
compiler/*.m:
Add `:- import_module' declarations to the interface needed
by declarations in the interface. (The previous version
of the compiler did not detect these missing interface imports,
due to the above-mentioned bug in modules.m.)
compiler/mercury_compile.m:
compiler/intermod.m:
Change mercury_compile__maybe_grab_optfiles and
intermod__grab_optfiles so that they grab the opt files for
parent modules as well as the ones for imported modules.
compiler/mercury_compile.m:
Minor changes to handle parent module dependencies.
(Also improve the wording of the warning about trans-opt
dependencies.)
compiler/make_hlds.m:
compiler/module_qual.m:
Ignore `:- include_module' declarations.
compiler/module_qual.m:
A couple of small changes to handle nested module names.
compiler/prog_out.m:
compiler/prog_util.m:
Add new predicates string_to_sym_name/3 (prog_util.m) and
sym_name_to_string/{2,3} (prog_out.m).
compiler/*.m:
Replace many occurrences of `string' with `module_name'.
Change code that prints out module names or converts
them to strings or filenames to handle the fact that
module names are now sym_names intead of strings.
Also change a few places (e.g. in intermod.m, hlds_module.m)
where the code assumed that any qualified symbol was
fully-qualified.
compiler/prog_io.m:
compiler/prog_io_goal.m:
Move sym_name_and_args/3, parse_qualified_term/4 and
parse_qualified_term/5 preds from prog_io_goal.m to prog_io.m,
since they are very similar to the parse_symbol_name/2 predicate
already in prog_io.m. Rewrite these predicates, both
to improve maintainability, and to handle the newly
allowed syntax (module-qualified module names).
Rename parse_qualified_term/5 as `parse_implicit_qualified_term'.
compiler/prog_io.m:
Rewrite the handling of `:- module' and `:- end_module'
declarations, so that it can handle nested modules.
Add code to parse `include_module' declarations.
compiler/prog_util.m:
compiler/*.m:
Add new predicates mercury_public_builtin_module/1 and
mercury_private_builtin_module/1 in prog_util.m.
Change most of the hard-coded occurrences of "mercury_builtin"
to call mercury_private_builtin_module/1 or
mercury_public_builtin_module/1 or both.
compiler/llds_out.m:
Add llds_out__sym_name_mangle/2, for mangling module names.
compiler/special_pred.m:
compiler/mode_util.m:
compiler/clause_to_proc.m:
compiler/prog_io_goal.m:
compiler/lambda.m:
compiler/polymorphism.m:
Move the predicates in_mode/1, out_mode/1, and uo_mode/1
from special_pred.m to mode_util.m, and change various
hard-coded definitions to instead call these predicates.
compiler/polymorphism.m:
Ensure that the type names `type_info' and `typeclass_info' are
module-qualified in the generated code. This avoids a problem
where the code generated by polymorphism.m was not considered
type-correct, due to the type `type_info' not matching
`mercury_builtin:type_info'.
compiler/check_typeclass.m:
Simplify the code for check_instance_pred and
get_matching_instance_pred_ids.
compiler/mercury_compile.m:
compiler/modules.m:
Disallow directory names in command-line arguments.
compiler/options.m:
compiler/handle_options.m:
compiler/mercury_compile.m:
compiler/modules.m:
Add a `--make-private-interface' option.
The private interface file `<module>.int0' contains
all the declarations in the module; it is used for
compiling sub-modules.
scripts/Mmake.rules:
scripts/Mmake.vars.in:
Add support for creating `.int0' and `.date0' files
by invoking mmc with `--make-private-interface'.
doc/user_guide.texi:
Document `--make-private-interface' and the `.int0'
and `.date0' file extensions.
doc/reference_manual.texi:
Document nested modules.
util/mdemangle.c:
profiler/demangle.m:
Demangle names with multiple module qualifiers.
tests/general/Mmakefile:
tests/general/string_format_test.m:
tests/general/string_format_test.exp:
tests/general/string__format_test.m:
tests/general/string__format_test.exp:
tests/general/.cvsignore:
Change the `:- module string__format_test' declaration in
`string__format_test.m' to `:- module string_format_test',
because with the original declaration the `__' was taken
as a module qualifier, which lead to an error message.
Hence rename the file accordingly, to avoid the warning
about file name not matching module name.
tests/invalid/Mmakefile:
tests/invalid/missing_interface_import.m:
tests/invalid/missing_interface_import.err_exp:
Regression test to check that the compiler reports
errors for missing `import_module' in the interface section.
tests/invalid/*.err_exp:
tests/warnings/unused_args_test.exp:
tests/warnings/unused_import.exp:
Update the expected diagnostics output for the test cases to
reflect a few minor changes to the warning messages.
tests/hard_coded/Mmakefile:
tests/hard_coded/parent.m:
tests/hard_coded/parent.child.m:
tests/hard_coded/parent.exp:
tests/hard_coded/parent2.m:
tests/hard_coded/parent2.child.m:
tests/hard_coded/parent2.exp:
Two simple tests case for the use of nested modules with
separate compilation.
1372 lines
39 KiB
Mathematica
1372 lines
39 KiB
Mathematica
%-----------------------------------------------------------------------------%
|
|
% Copyright (C) 1995-1998 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.
|
|
%-----------------------------------------------------------------------------%
|
|
|
|
% vn_util.m - utility predicates for value numbering.
|
|
|
|
% Main author: zs.
|
|
|
|
%-----------------------------------------------------------------------------%
|
|
|
|
:- module vn_util.
|
|
|
|
:- interface.
|
|
|
|
:- import_module list, bool, std_util.
|
|
:- import_module llds, vn_type, vn_table.
|
|
|
|
%-----------------------------------------------------------------------------%
|
|
%-----------------------------------------------------------------------------%
|
|
|
|
% Submodule for the forward phase of vn_block__handle_instr
|
|
|
|
:- interface.
|
|
|
|
:- pred vn_util__find_specials(vnlval, list(vnlval)).
|
|
:- mode vn_util__find_specials(in, out) is det.
|
|
|
|
:- pred vn_util__convert_to_vnlval_and_insert(list(lval), vnlvalset, vnlvalset).
|
|
% :- mode vn_util__convert_to_vnlval_and_insert(in, di, uo) is det.
|
|
:- mode vn_util__convert_to_vnlval_and_insert(in, in, out) is det.
|
|
|
|
:- implementation.
|
|
|
|
:- import_module int, float, string, set, map, require.
|
|
|
|
:- import_module opt_util.
|
|
|
|
vn_util__find_specials(vn_reg(_, _), []).
|
|
vn_util__find_specials(vn_temp(_, _), []).
|
|
vn_util__find_specials(vn_stackvar(_), []).
|
|
vn_util__find_specials(vn_framevar(_), []).
|
|
vn_util__find_specials(vn_succip, [vn_succip]).
|
|
vn_util__find_specials(vn_maxfr, [vn_maxfr]).
|
|
vn_util__find_specials(vn_curfr, [vn_curfr]).
|
|
vn_util__find_specials(vn_redoip(Vn), [vn_redoip(Vn)]).
|
|
vn_util__find_specials(vn_succip(Vn), [vn_succip(Vn)]).
|
|
vn_util__find_specials(vn_succfr(Vn), [vn_succfr(Vn)]).
|
|
vn_util__find_specials(vn_prevfr(Vn), [vn_prevfr(Vn)]).
|
|
vn_util__find_specials(vn_hp, [vn_hp]).
|
|
vn_util__find_specials(vn_sp, [vn_sp]).
|
|
vn_util__find_specials(vn_field(_, _, _), []).
|
|
vn_util__find_specials(vn_mem_ref(_), []).
|
|
|
|
vn_util__convert_to_vnlval_and_insert([], Liveset, Liveset).
|
|
vn_util__convert_to_vnlval_and_insert([Lval | Lvals], Liveset0, Liveset) :-
|
|
vn_util__no_access_lval_to_vnlval(Lval, MaybeVnlval),
|
|
(
|
|
MaybeVnlval = yes(Vnlval),
|
|
set__insert(Liveset0, Vnlval, Liveset1)
|
|
;
|
|
MaybeVnlval = no,
|
|
Liveset1 = Liveset0
|
|
),
|
|
vn_util__convert_to_vnlval_and_insert(Lvals, Liveset1, Liveset).
|
|
|
|
%-----------------------------------------------------------------------------%
|
|
%-----------------------------------------------------------------------------%
|
|
|
|
:- interface.
|
|
|
|
% Convert an rval into a vnrval and hence into a vn.
|
|
|
|
:- pred vn_util__rval_to_vn(rval, vn, vn_tables, vn_tables).
|
|
% :- mode vn_util__rval_to_vn(in, out, di, uo) is det.
|
|
:- mode vn_util__rval_to_vn(in, out, in, out) is det.
|
|
|
|
:- pred vn_util__lval_to_vn(lval, vn, vn_tables, vn_tables).
|
|
% :- mode vn_util__lval_to_vn(in, out, di, uo) is det.
|
|
:- mode vn_util__lval_to_vn(in, out, in, out) is det.
|
|
|
|
:- pred vn_util__lval_to_vnlval(lval, vnlval, vn_tables, vn_tables).
|
|
% :- mode vn_util__lval_to_vnlval(in, out, di, uo) is det.
|
|
:- mode vn_util__lval_to_vnlval(in, out, in, out) is det.
|
|
|
|
:- pred vn_util__is_const_expr(vn, bool, vn_tables).
|
|
:- mode vn_util__is_const_expr(in, out, in) is det.
|
|
|
|
% Find out what vns, if any, are needed to access a vnlval.
|
|
|
|
:- pred vn_util__vnlval_access_vns(vnlval, list(vn)).
|
|
:- mode vn_util__vnlval_access_vns(in, out) is det.
|
|
|
|
% Turn an vnlval into an lval if possible.
|
|
|
|
:- pred vn_util__no_access_vnlval_to_lval(vnlval, maybe(lval)).
|
|
:- mode vn_util__no_access_vnlval_to_lval(in, out) is det.
|
|
|
|
% Do the reverse.
|
|
|
|
:- pred vn_util__no_access_lval_to_vnlval(lval, maybe(vnlval)).
|
|
:- mode vn_util__no_access_lval_to_vnlval(in, out) is det.
|
|
|
|
:- pred vn_util__find_sub_vns(vnrval, list(vn)).
|
|
:- mode vn_util__find_sub_vns(in, out) is det.
|
|
|
|
% Find all lvals inside a given rval.
|
|
|
|
:- pred vn_util__find_lvals_in_rval(rval, list(lval)).
|
|
:- mode vn_util__find_lvals_in_rval(in, out) is det.
|
|
|
|
:- pred vn_util__find_lvals_in_rvals(list(rval), list(lval)).
|
|
:- mode vn_util__find_lvals_in_rvals(in, out) is det.
|
|
|
|
% Find out whether a vn is needed in two or more assignments.
|
|
|
|
:- pred vn_util__is_vn_shared(vn, vnrval, list(vn_src), vn_tables).
|
|
:- mode vn_util__is_vn_shared(in, in, in, in) is semidet.
|
|
|
|
% Find out which uses of a vn actually require an assignment.
|
|
|
|
:- pred vn_util__real_uses(list(vn_src), list(vn_src), vn_tables).
|
|
% :- mode vn_util__real_uses(di, uo, in) is semidet.
|
|
:- mode vn_util__real_uses(in, out, in) is semidet.
|
|
|
|
% Choose the cheapest location from a given list of locations.
|
|
% Access time is the only consideration. There are three cost levels:
|
|
% registers and temporaries; stackvars and framevars; fields.
|
|
% Fail only if the input list is empty.
|
|
|
|
:- pred vn_util__choose_cheapest_loc(list(vnlval), vnlval).
|
|
:- mode vn_util__choose_cheapest_loc(in, out) is semidet.
|
|
|
|
:- pred vn_util__classify_loc_cost(vnlval, int).
|
|
:- mode vn_util__classify_loc_cost(in, out) is det.
|
|
|
|
:- implementation.
|
|
|
|
%-----------------------------------------------------------------------------%
|
|
|
|
vn_util__rval_to_vn(Rval, Vn, VnTables0, VnTables) :-
|
|
(
|
|
Rval = lval(Lval),
|
|
vn_util__lval_to_vn(Lval, Vn, VnTables0, VnTables)
|
|
;
|
|
Rval = var(_),
|
|
error("value_number should never get rval: var")
|
|
;
|
|
Rval = create(Tag, Args, Unique, Label, Msg),
|
|
vn_util__vnrval_to_vn(vn_create(Tag, Args, Unique, Label, Msg),
|
|
Vn, VnTables0, VnTables)
|
|
;
|
|
Rval = mkword(Tag, Rval1),
|
|
vn_util__rval_to_vn(Rval1, SubVn, VnTables0, VnTables1),
|
|
vn_util__vnrval_to_vn(vn_mkword(Tag, SubVn), Vn,
|
|
VnTables1, VnTables)
|
|
;
|
|
Rval = const(Const),
|
|
vn_util__vnrval_to_vn(vn_const(Const), Vn,
|
|
VnTables0, VnTables)
|
|
;
|
|
Rval = unop(Unop, Rval1),
|
|
vn_util__rval_to_vn(Rval1, SubVn, VnTables0, VnTables1),
|
|
vn_util__vnrval_to_vn(vn_unop(Unop, SubVn), Vn,
|
|
VnTables1, VnTables)
|
|
;
|
|
Rval = binop(Binop, Rval1, Rval2),
|
|
vn_util__rval_to_vn(Rval1, SubVn1, VnTables0, VnTables1),
|
|
vn_util__rval_to_vn(Rval2, SubVn2, VnTables1, VnTables2),
|
|
vn_util__vnrval_to_vn(vn_binop(Binop, SubVn1, SubVn2), Vn,
|
|
VnTables2, VnTables)
|
|
;
|
|
Rval = mem_addr(MemRef),
|
|
vn_util__mem_ref_to_vn(MemRef, Vn, VnTables0, VnTables)
|
|
).
|
|
|
|
:- pred vn_util__mem_ref_to_vn(mem_ref, vn, vn_tables, vn_tables).
|
|
% :- mode vn_util__mem_ref_to_vn(in, out, di, uo) is det.
|
|
:- mode vn_util__mem_ref_to_vn(in, out, in, out) is det.
|
|
|
|
vn_util__mem_ref_to_vn(MemRef, Vn, VnTables0, VnTables) :-
|
|
(
|
|
MemRef = stackvar_ref(Slot),
|
|
vn_util__vnrval_to_vn(vn_stackvar_addr(Slot), Vn,
|
|
VnTables0, VnTables)
|
|
;
|
|
MemRef = framevar_ref(Slot),
|
|
vn_util__vnrval_to_vn(vn_framevar_addr(Slot), Vn,
|
|
VnTables0, VnTables)
|
|
;
|
|
MemRef = heap_ref(Rval, Tag, Field),
|
|
vn_util__rval_to_vn(Rval, SubVn, VnTables0, VnTables1),
|
|
vn_util__vnrval_to_vn(vn_heap_addr(SubVn, Tag, Field), Vn,
|
|
VnTables1, VnTables)
|
|
).
|
|
|
|
:- pred vn_util__vnrval_to_vn(vnrval, vn, vn_tables, vn_tables).
|
|
% :- mode vn_util__vnrval_to_vn(in, out, di, uo) is det.
|
|
:- mode vn_util__vnrval_to_vn(in, out, in, out) is det.
|
|
|
|
vn_util__vnrval_to_vn(Vnrval, Vn, VnTables0, VnTables) :-
|
|
vn_util__simplify_vnrval(Vnrval, Vnrval1, VnTables0, VnTables1),
|
|
( vn_table__search_assigned_vn(Vnrval1, Vn_prime, VnTables1) ->
|
|
( vn_util__vnrval_may_share_vn(Vnrval1) ->
|
|
Vn = Vn_prime,
|
|
VnTables = VnTables1
|
|
;
|
|
vn_table__record_new_vnrval(Vnrval1, Vn,
|
|
VnTables1, VnTables)
|
|
)
|
|
;
|
|
vn_table__record_first_vnrval(Vnrval1, Vn, VnTables1, VnTables)
|
|
).
|
|
|
|
:- pred vn_util__vnrval_may_share_vn(vnrval).
|
|
:- mode vn_util__vnrval_may_share_vn(in) is semidet.
|
|
|
|
vn_util__vnrval_may_share_vn(Vnrval) :-
|
|
(
|
|
Vnrval = vn_unop(cast_to_unsigned, _)
|
|
->
|
|
fail
|
|
;
|
|
true
|
|
).
|
|
|
|
% Simplify the vnrval by partially evaluating expressions involving
|
|
% constants. To make this simpler, swap the arguments of commutative
|
|
% expressions around to put the constants on the right side.
|
|
|
|
% For the time being we assume ideal integers and reals.
|
|
% Eventually, we will have to introduce a mechanism to allow
|
|
% programmers to prescribe orders of evaluation.
|
|
|
|
% We also assume that the compiler's arithmetic is at least as
|
|
% accurate as the target machine's arithmetic.
|
|
|
|
% The simplification has to be done on vnrvals and not on rvals
|
|
% even though this complicates the code. The reason is that an
|
|
% expression such as r1 + 4 can be simplified if we know that
|
|
% r1 was defined as r2 + 8.
|
|
|
|
% XXX more simplification opportunities exist
|
|
|
|
:- pred vn_util__simplify_vnrval(vnrval, vnrval, vn_tables, vn_tables).
|
|
% :- mode vn_util__simplify_vnrval(in, out, di, uo) is det.
|
|
:- mode vn_util__simplify_vnrval(in, out, in, out) is det.
|
|
|
|
vn_util__simplify_vnrval(Vnrval0, Vnrval, VnTables0, VnTables) :-
|
|
(
|
|
Vnrval0 = vn_binop(Binop, Vn1, Vn2),
|
|
vn_util__simplify_vnrval_binop(Binop, Vn1, Vn2, VnrvalPrime,
|
|
VnTables0, VnTablesPrime)
|
|
->
|
|
Vnrval = VnrvalPrime,
|
|
VnTables = VnTablesPrime
|
|
;
|
|
Vnrval = Vnrval0,
|
|
VnTables = VnTables0
|
|
).
|
|
|
|
:- pred vn_util__simplify_vnrval_binop(binary_op, vn, vn, vnrval,
|
|
vn_tables, vn_tables).
|
|
% :- mode vn_util__simplify_vnrval_binop(in, in, in, out, di, uo) is semidet.
|
|
:- mode vn_util__simplify_vnrval_binop(in, in, in, out, in, out) is semidet.
|
|
|
|
vn_util__simplify_vnrval_binop(Binop, Vn1, Vn2, Vnrval, VnTables0, VnTables) :-
|
|
vn_table__lookup_defn(Vn1, Vnrval1,
|
|
"vn_util__simplify_vnrval_binop", VnTables0),
|
|
vn_table__lookup_defn(Vn2, Vnrval2,
|
|
"vn_util__simplify_vnrval_binop", VnTables0),
|
|
(
|
|
Binop = (+),
|
|
(
|
|
% c1+c2 => c
|
|
Vnrval1 = vn_const(int_const(I1)),
|
|
Vnrval2 = vn_const(int_const(I2))
|
|
->
|
|
I is I1 + I2,
|
|
Vnrval = vn_const(int_const(I)),
|
|
VnTables = VnTables0
|
|
;
|
|
% c1+e21+c22 => e21+c
|
|
Vnrval1 = vn_const(int_const(I1)),
|
|
Vnrval2 = vn_binop((+), Vn21, Vn22),
|
|
vn_table__lookup_defn(Vn22, Vnrval22,
|
|
"vn_util__simplify_vnrval", VnTables0),
|
|
Vnrval22 = vn_const(int_const(I22))
|
|
->
|
|
I is I1 + I22,
|
|
vn_util__vnrval_to_vn(vn_const(int_const(I)), VnConst,
|
|
VnTables0, VnTables),
|
|
Vnrval = vn_binop((+), Vn21, VnConst)
|
|
;
|
|
% c1+e2 => e2+c1
|
|
Vnrval1 = vn_const(int_const(_I1)),
|
|
Vnrval2 = vn_binop((+), _Vn21, _Vn22)
|
|
->
|
|
Vnrval = vn_binop((+), Vn2, Vn1),
|
|
VnTables = VnTables0
|
|
;
|
|
% e11+c12+c2 => e11+c
|
|
Vnrval1 = vn_binop((+), Vn11, Vn12),
|
|
vn_table__lookup_defn(Vn12, Vnrval12,
|
|
"vn_util__simplify_vnrval", VnTables0),
|
|
Vnrval12 = vn_const(int_const(I12)),
|
|
Vnrval2 = vn_const(int_const(I2))
|
|
->
|
|
I is I12 + I2,
|
|
vn_util__vnrval_to_vn(vn_const(int_const(I)),
|
|
VnConst, VnTables0, VnTables),
|
|
Vnrval = vn_binop((+), Vn11, VnConst)
|
|
;
|
|
% e11+c12+e21+c22 => e11+e21+c
|
|
Vnrval1 = vn_binop((+), Vn11, Vn12),
|
|
vn_table__lookup_defn(Vn12, Vnrval12,
|
|
"vn_util__simplify_vnrval", VnTables0),
|
|
Vnrval12 = vn_const(int_const(I12)),
|
|
Vnrval2 = vn_binop((+), Vn21, Vn22),
|
|
vn_table__lookup_defn(Vn22, Vnrval22,
|
|
"vn_util__simplify_vnrval", VnTables0),
|
|
Vnrval22 = vn_const(int_const(I22))
|
|
->
|
|
I is I12 + I22,
|
|
vn_util__vnrval_to_vn(vn_binop((+), Vn11, Vn21), VnExpr,
|
|
VnTables0, VnTables1),
|
|
vn_util__vnrval_to_vn(vn_const(int_const(I)),
|
|
VnConst, VnTables1, VnTables),
|
|
Vnrval = vn_binop((+), VnExpr, VnConst)
|
|
;
|
|
% e11+c12+e2 => e11+e2+c12
|
|
Vnrval1 = vn_binop((+), Vn11, Vn12),
|
|
vn_table__lookup_defn(Vn12, Vnrval12,
|
|
"vn_util__simplify_vnrval", VnTables0),
|
|
Vnrval12 = vn_const(int_const(_I12)),
|
|
Vnrval2 = vn_binop((+), _Vn21, _Vn22)
|
|
->
|
|
vn_util__vnrval_to_vn(vn_binop((+), Vn11, Vn2), VnExpr,
|
|
VnTables0, VnTables),
|
|
Vnrval = vn_binop((+), VnExpr, Vn12)
|
|
;
|
|
% e+0 => e
|
|
Vnrval2 = vn_const(int_const(0))
|
|
->
|
|
Vnrval = Vnrval1,
|
|
VnTables = VnTables0
|
|
;
|
|
fail
|
|
)
|
|
;
|
|
Binop = (float_plus),
|
|
(
|
|
% c1+c2 => c
|
|
Vnrval1 = vn_const(float_const(F1)),
|
|
Vnrval2 = vn_const(float_const(F2))
|
|
->
|
|
F is F1 + F2,
|
|
Vnrval = vn_const(float_const(F)),
|
|
VnTables = VnTables0
|
|
;
|
|
% c1+e21+c22 => e21+c
|
|
Vnrval1 = vn_const(float_const(F1)),
|
|
Vnrval2 = vn_binop((float_plus), Vn21, Vn22),
|
|
vn_table__lookup_defn(Vn22, Vnrval22,
|
|
"vn_util__simplify_vnrval", VnTables0),
|
|
Vnrval22 = vn_const(float_const(F22))
|
|
->
|
|
F is F1 + F22,
|
|
vn_util__vnrval_to_vn(vn_const(float_const(F)), VnConst,
|
|
VnTables0, VnTables),
|
|
Vnrval = vn_binop((float_plus), Vn21, VnConst)
|
|
;
|
|
% c1+e2 => e2+c1
|
|
Vnrval1 = vn_const(float_const(_F1)),
|
|
Vnrval2 = vn_binop((float_plus), _Vn21, _Vn22)
|
|
->
|
|
Vnrval = vn_binop((float_plus), Vn2, Vn1),
|
|
VnTables = VnTables0
|
|
;
|
|
% e11+c12+c2 => e11+c
|
|
Vnrval1 = vn_binop((float_plus), Vn11, Vn12),
|
|
vn_table__lookup_defn(Vn12, Vnrval12,
|
|
"vn_util__simplify_vnrval", VnTables0),
|
|
Vnrval12 = vn_const(float_const(F12)),
|
|
Vnrval2 = vn_const(float_const(F2))
|
|
->
|
|
F is F12 + F2,
|
|
vn_util__vnrval_to_vn(vn_const(float_const(F)),
|
|
VnConst, VnTables0, VnTables),
|
|
Vnrval = vn_binop((float_plus), Vn11, VnConst)
|
|
;
|
|
% e11+c12+e21+c22 => e11+e21+c
|
|
Vnrval1 = vn_binop((float_plus), Vn11, Vn12),
|
|
vn_table__lookup_defn(Vn12, Vnrval12,
|
|
"vn_util__simplify_vnrval", VnTables0),
|
|
Vnrval12 = vn_const(float_const(F12)),
|
|
Vnrval2 = vn_binop((float_plus), Vn21, Vn22),
|
|
vn_table__lookup_defn(Vn22, Vnrval22,
|
|
"vn_util__simplify_vnrval", VnTables0),
|
|
Vnrval22 = vn_const(float_const(F22))
|
|
->
|
|
F is F12 + F22,
|
|
vn_util__vnrval_to_vn(vn_binop((float_plus), Vn11,
|
|
Vn21), VnExpr, VnTables0, VnTables1),
|
|
vn_util__vnrval_to_vn(vn_const(float_const(F)),
|
|
VnConst, VnTables1, VnTables),
|
|
Vnrval = vn_binop((float_plus), VnExpr, VnConst)
|
|
;
|
|
% e11+c12+e2 => e11+e2+c12
|
|
Vnrval1 = vn_binop((float_plus), Vn11, Vn12),
|
|
vn_table__lookup_defn(Vn12, Vnrval12,
|
|
"vn_util__simplify_vnrval", VnTables0),
|
|
Vnrval12 = vn_const(float_const(_F12)),
|
|
Vnrval2 = vn_binop((float_plus), _Vn21, _Vn22)
|
|
->
|
|
vn_util__vnrval_to_vn(vn_binop((float_plus), Vn11,
|
|
Vn2), VnExpr, VnTables0, VnTables),
|
|
Vnrval = vn_binop((float_plus), VnExpr, Vn12)
|
|
;
|
|
% e+0 => e
|
|
Vnrval2 = vn_const(float_const(0.0))
|
|
->
|
|
Vnrval = Vnrval1,
|
|
VnTables = VnTables0
|
|
;
|
|
fail
|
|
)
|
|
;
|
|
Binop = (-),
|
|
(
|
|
% e1-c2 => e1+c
|
|
Vnrval2 = vn_const(int_const(I2))
|
|
->
|
|
NI2 is 0 - I2,
|
|
vn_util__vnrval_to_vn(vn_const(int_const(NI2)), VnConst,
|
|
VnTables0, VnTables1),
|
|
vn_util__simplify_vnrval(vn_binop((+), Vn1, VnConst),
|
|
Vnrval, VnTables1, VnTables)
|
|
;
|
|
% c1-e2 => 0-e2+c1
|
|
Vnrval1 = vn_const(int_const(I1)),
|
|
I1 \= 0
|
|
->
|
|
vn_util__vnrval_to_vn(vn_const(int_const(0)), VnConst0,
|
|
VnTables0, VnTables1),
|
|
vn_util__vnrval_to_vn(vn_binop((-), VnConst0, Vn2),
|
|
VnExpr, VnTables1, VnTables2),
|
|
vn_util__simplify_vnrval(vn_binop((+), VnExpr, Vn1),
|
|
Vnrval, VnTables2, VnTables)
|
|
;
|
|
% e1-e1 => 0
|
|
Vn1 = Vn2
|
|
->
|
|
Vnrval = vn_const(int_const(0)),
|
|
VnTables = VnTables0
|
|
;
|
|
% e-0 => e
|
|
Vnrval2 = vn_const(int_const(0))
|
|
->
|
|
Vnrval = Vnrval1,
|
|
VnTables = VnTables0
|
|
;
|
|
fail
|
|
)
|
|
;
|
|
Binop = (float_minus),
|
|
(
|
|
% e1-c2 => e1+c
|
|
Vnrval2 = vn_const(float_const(F2))
|
|
->
|
|
NF2 is 0.0 - F2,
|
|
vn_util__vnrval_to_vn(vn_const(float_const(NF2)),
|
|
VnConst, VnTables0, VnTables1),
|
|
vn_util__simplify_vnrval(vn_binop((float_plus), Vn1,
|
|
VnConst), Vnrval, VnTables1, VnTables)
|
|
;
|
|
% c1-e2 => 0-e2+c1
|
|
Vnrval1 = vn_const(float_const(F1)),
|
|
F1 \= 0.0
|
|
->
|
|
vn_util__vnrval_to_vn(vn_const(float_const(0.0)),
|
|
VnConst0, VnTables0, VnTables1),
|
|
vn_util__vnrval_to_vn(vn_binop((float_minus), VnConst0,
|
|
Vn2), VnExpr, VnTables1, VnTables2),
|
|
vn_util__simplify_vnrval(vn_binop((float_plus), VnExpr,
|
|
Vn1), Vnrval, VnTables2, VnTables)
|
|
;
|
|
% e1-e1 => 0
|
|
Vn1 = Vn2
|
|
->
|
|
Vnrval = vn_const(int_const(0)),
|
|
VnTables = VnTables0
|
|
;
|
|
% e-0 => e
|
|
Vnrval2 = vn_const(float_const(0.0))
|
|
->
|
|
Vnrval = Vnrval1,
|
|
VnTables = VnTables0
|
|
;
|
|
fail
|
|
)
|
|
;
|
|
Binop = (*),
|
|
(
|
|
% c1*c2 => c
|
|
Vnrval1 = vn_const(int_const(I1)),
|
|
Vnrval2 = vn_const(int_const(I2))
|
|
->
|
|
I is I1 * I2,
|
|
Vnrval = vn_const(int_const(I)),
|
|
VnTables = VnTables0
|
|
;
|
|
% e*1 => e
|
|
Vnrval2 = vn_const(int_const(1))
|
|
->
|
|
Vnrval = Vnrval1,
|
|
VnTables = VnTables0
|
|
;
|
|
% 1*e => e
|
|
Vnrval1 = vn_const(int_const(1))
|
|
->
|
|
Vnrval = Vnrval2,
|
|
VnTables = VnTables0
|
|
;
|
|
fail
|
|
)
|
|
;
|
|
Binop = (float_times),
|
|
(
|
|
% c1*c2 => c
|
|
Vnrval1 = vn_const(float_const(F1)),
|
|
Vnrval2 = vn_const(float_const(F2))
|
|
->
|
|
F is F1 * F2,
|
|
Vnrval = vn_const(float_const(F)),
|
|
VnTables = VnTables0
|
|
;
|
|
% e*1 => e
|
|
Vnrval2 = vn_const(float_const(1.0))
|
|
->
|
|
Vnrval = Vnrval1,
|
|
VnTables = VnTables0
|
|
;
|
|
% 1*e => e
|
|
Vnrval1 = vn_const(float_const(1.0))
|
|
->
|
|
Vnrval = Vnrval2,
|
|
VnTables = VnTables0
|
|
;
|
|
fail
|
|
)
|
|
;
|
|
Binop = (/),
|
|
(
|
|
% c1/c2 => c
|
|
Vnrval1 = vn_const(int_const(I1)),
|
|
Vnrval2 = vn_const(int_const(I2)),
|
|
I2 \= 0
|
|
->
|
|
I is I1 // I2,
|
|
Vnrval = vn_const(int_const(I)),
|
|
VnTables = VnTables0
|
|
;
|
|
% e/1 => e
|
|
Vnrval2 = vn_const(int_const(1))
|
|
->
|
|
Vnrval = Vnrval1,
|
|
VnTables = VnTables0
|
|
;
|
|
fail
|
|
)
|
|
;
|
|
Binop = (float_divide),
|
|
(
|
|
% c1/c2 => c
|
|
Vnrval1 = vn_const(float_const(F1)),
|
|
Vnrval2 = vn_const(float_const(F2)),
|
|
F2 \= 0.0
|
|
->
|
|
F is F1 / F2,
|
|
Vnrval = vn_const(float_const(F)),
|
|
VnTables = VnTables0
|
|
;
|
|
% e/1 => e
|
|
Vnrval2 = vn_const(float_const(1.0))
|
|
->
|
|
Vnrval = Vnrval1,
|
|
VnTables = VnTables0
|
|
;
|
|
fail
|
|
)
|
|
;
|
|
Binop = ('|'),
|
|
(
|
|
% c1\/c2 => c
|
|
Vnrval1 = vn_const(int_const(I1)),
|
|
Vnrval2 = vn_const(int_const(I2))
|
|
->
|
|
I is I1 \/ I2,
|
|
Vnrval = vn_const(int_const(I)),
|
|
VnTables = VnTables0
|
|
;
|
|
% e\/0 => e
|
|
Vnrval2 = vn_const(int_const(0))
|
|
->
|
|
Vnrval = Vnrval1,
|
|
VnTables = VnTables0
|
|
;
|
|
% 0\/e => e
|
|
Vnrval1 = vn_const(int_const(0))
|
|
->
|
|
Vnrval = Vnrval2,
|
|
VnTables = VnTables0
|
|
;
|
|
% e\/e => e
|
|
Vn1 = Vn2
|
|
->
|
|
Vnrval = Vnrval1,
|
|
VnTables = VnTables0
|
|
;
|
|
fail
|
|
)
|
|
;
|
|
Binop = (&),
|
|
(
|
|
% c1/\c2 => c
|
|
Vnrval1 = vn_const(int_const(I1)),
|
|
Vnrval2 = vn_const(int_const(I2))
|
|
->
|
|
I is I1 /\ I2,
|
|
Vnrval = vn_const(int_const(I)),
|
|
VnTables = VnTables0
|
|
;
|
|
% e/\0 => 0
|
|
Vnrval2 = vn_const(int_const(0))
|
|
->
|
|
Vnrval = vn_const(int_const(0)),
|
|
VnTables = VnTables0
|
|
;
|
|
% 0/\e => 0
|
|
Vnrval1 = vn_const(int_const(0))
|
|
->
|
|
Vnrval = vn_const(int_const(0)),
|
|
VnTables = VnTables0
|
|
;
|
|
% e/\e => e
|
|
Vn1 = Vn2
|
|
->
|
|
Vnrval = Vnrval1,
|
|
VnTables = VnTables0
|
|
;
|
|
fail
|
|
)
|
|
;
|
|
Binop = (>>),
|
|
(
|
|
% c1>>c2 => c
|
|
Vnrval1 = vn_const(int_const(I1)),
|
|
Vnrval2 = vn_const(int_const(I2))
|
|
->
|
|
I is I1 >> I2,
|
|
Vnrval = vn_const(int_const(I)),
|
|
VnTables = VnTables0
|
|
;
|
|
% e>>0 => e
|
|
Vnrval2 = vn_const(int_const(0))
|
|
->
|
|
Vnrval = Vnrval1,
|
|
VnTables = VnTables0
|
|
;
|
|
fail
|
|
)
|
|
;
|
|
Binop = (<<),
|
|
(
|
|
% c1<<c2 => c
|
|
Vnrval1 = vn_const(int_const(I1)),
|
|
Vnrval2 = vn_const(int_const(I2))
|
|
->
|
|
I is I1 << I2,
|
|
Vnrval = vn_const(int_const(I)),
|
|
VnTables = VnTables0
|
|
;
|
|
% e<<0 => e
|
|
Vnrval2 = vn_const(int_const(0))
|
|
->
|
|
Vnrval = Vnrval1,
|
|
VnTables = VnTables0
|
|
;
|
|
fail
|
|
)
|
|
;
|
|
Binop = eq,
|
|
(
|
|
% e==e => true
|
|
Vn1 = Vn2
|
|
->
|
|
Vnrval = vn_const(true),
|
|
VnTables = VnTables0
|
|
;
|
|
% otherwise, c1==c2 => false
|
|
% (true case handled above)
|
|
Vnrval1 = vn_const(_C1),
|
|
Vnrval2 = vn_const(_C2)
|
|
->
|
|
Vnrval = vn_const(false),
|
|
VnTables = VnTables0
|
|
;
|
|
% tag(mktag(e))==e => true
|
|
Vnrval1 = vn_unop(tag, WordVn),
|
|
Vnrval2 = vn_unop(mktag, Tag),
|
|
vn_table__lookup_defn(WordVn, WordVnrval,
|
|
"vn_util__simplify_vnrval_binop", VnTables0),
|
|
WordVnrval = vn_mkword(Tag, _)
|
|
->
|
|
Vnrval = vn_const(true),
|
|
VnTables = VnTables0
|
|
;
|
|
fail
|
|
)
|
|
;
|
|
Binop = ne,
|
|
(
|
|
% e!=e => false
|
|
Vn1 = Vn2
|
|
->
|
|
Vnrval = vn_const(false),
|
|
VnTables = VnTables0
|
|
;
|
|
% otherwise, c1!=c2 => true
|
|
% (false case handled above)
|
|
Vnrval1 = vn_const(_C1),
|
|
Vnrval2 = vn_const(_C2)
|
|
->
|
|
Vnrval = vn_const(true),
|
|
VnTables = VnTables0
|
|
;
|
|
% tag(mktag(e))!=e => false
|
|
Vnrval1 = vn_unop(tag, WordVn),
|
|
Vnrval2 = vn_unop(mktag, Tag),
|
|
vn_table__lookup_defn(WordVn, WordVnrval,
|
|
"vn_util__simplify_vnrval_binop", VnTables0),
|
|
WordVnrval = vn_mkword(Tag, _)
|
|
->
|
|
Vnrval = vn_const(false),
|
|
VnTables = VnTables0
|
|
;
|
|
fail
|
|
)
|
|
;
|
|
Binop = (>=),
|
|
vn_util__simplify_int_compare_op(>=, Vn1, Vnrval1, Vn2, Vnrval2,
|
|
true, Vnrval),
|
|
VnTables = VnTables0
|
|
;
|
|
Binop = (<=),
|
|
vn_util__simplify_int_compare_op(=<, Vn1, Vnrval1, Vn2, Vnrval2,
|
|
true, Vnrval),
|
|
VnTables = VnTables0
|
|
;
|
|
Binop = (>),
|
|
vn_util__simplify_int_compare_op(>, Vn1, Vnrval1, Vn2, Vnrval2,
|
|
false, Vnrval),
|
|
VnTables = VnTables0
|
|
;
|
|
Binop = (<),
|
|
vn_util__simplify_int_compare_op(<, Vn1, Vnrval1, Vn2, Vnrval2,
|
|
false, Vnrval),
|
|
VnTables = VnTables0
|
|
;
|
|
Binop = (float_eq),
|
|
vn_util__simplify_float_compare_op(float_eq, Vn1, Vnrval1,
|
|
Vn2, Vnrval2, true, Vnrval),
|
|
VnTables = VnTables0
|
|
;
|
|
Binop = (float_ge),
|
|
vn_util__simplify_float_compare_op(>=, Vn1, Vnrval1,
|
|
Vn2, Vnrval2, true, Vnrval),
|
|
VnTables = VnTables0
|
|
;
|
|
Binop = (float_le),
|
|
vn_util__simplify_float_compare_op(=<, Vn1, Vnrval1,
|
|
Vn2, Vnrval2, true, Vnrval),
|
|
VnTables = VnTables0
|
|
;
|
|
Binop = (float_ne),
|
|
vn_util__simplify_float_compare_op(float_ne, Vn1, Vnrval1,
|
|
Vn2, Vnrval2, false, Vnrval),
|
|
VnTables = VnTables0
|
|
;
|
|
Binop = (float_gt),
|
|
vn_util__simplify_float_compare_op(>=, Vn1, Vnrval1,
|
|
Vn2, Vnrval2, false, Vnrval),
|
|
VnTables = VnTables0
|
|
;
|
|
Binop = (float_lt),
|
|
vn_util__simplify_float_compare_op(=<, Vn1, Vnrval1,
|
|
Vn2, Vnrval2, false, Vnrval),
|
|
VnTables = VnTables0
|
|
;
|
|
Binop = (str_eq),
|
|
vn_util__const_if_equal_vns(Vn1, Vn2, true, Vnrval),
|
|
VnTables = VnTables0
|
|
;
|
|
Binop = (str_ge),
|
|
vn_util__const_if_equal_vns(Vn1, Vn2, true, Vnrval),
|
|
VnTables = VnTables0
|
|
;
|
|
Binop = (str_le),
|
|
vn_util__const_if_equal_vns(Vn1, Vn2, true, Vnrval),
|
|
VnTables = VnTables0
|
|
;
|
|
Binop = (str_ne),
|
|
vn_util__const_if_equal_vns(Vn1, Vn2, false, Vnrval),
|
|
VnTables = VnTables0
|
|
;
|
|
Binop = (str_gt),
|
|
vn_util__const_if_equal_vns(Vn1, Vn2, false, Vnrval),
|
|
VnTables = VnTables0
|
|
;
|
|
Binop = (str_lt),
|
|
vn_util__const_if_equal_vns(Vn1, Vn2, false, Vnrval),
|
|
VnTables = VnTables0
|
|
;
|
|
Binop = (and),
|
|
( Vnrval1 = vn_const(true) ->
|
|
Vnrval = Vnrval2,
|
|
VnTables = VnTables0
|
|
; Vnrval2 = vn_const(true) ->
|
|
Vnrval = Vnrval1,
|
|
VnTables = VnTables0
|
|
; Vnrval1 = vn_const(false) ->
|
|
Vnrval = Vnrval1,
|
|
VnTables = VnTables0
|
|
; Vnrval2 = vn_const(false) ->
|
|
Vnrval = Vnrval2,
|
|
VnTables = VnTables0
|
|
;
|
|
fail
|
|
)
|
|
;
|
|
Binop = (or),
|
|
( Vnrval1 = vn_const(false) ->
|
|
Vnrval = Vnrval2,
|
|
VnTables = VnTables0
|
|
; Vnrval2 = vn_const(false) ->
|
|
Vnrval = Vnrval1,
|
|
VnTables = VnTables0
|
|
; Vnrval1 = vn_const(true) ->
|
|
Vnrval = Vnrval1,
|
|
VnTables = VnTables0
|
|
; Vnrval2 = vn_const(true) ->
|
|
Vnrval = Vnrval2,
|
|
VnTables = VnTables0
|
|
;
|
|
fail
|
|
)
|
|
).
|
|
|
|
:- pred vn_util__simplify_int_compare_op(pred(int, int),
|
|
vn, vnrval, vn, vnrval, rval_const, vnrval).
|
|
:- mode vn_util__simplify_int_compare_op(pred(in, in) is semidet,
|
|
in, in, in, in, in, out) is semidet.
|
|
|
|
vn_util__simplify_int_compare_op(ComparePred, Vn1, Vnrval1, Vn2, Vnrval2,
|
|
ResultIfEqual, Vnrval) :-
|
|
(
|
|
Vnrval1 = vn_const(int_const(C1)),
|
|
Vnrval2 = vn_const(int_const(C2))
|
|
->
|
|
(
|
|
call(ComparePred, C1, C2)
|
|
->
|
|
Vnrval = vn_const(true)
|
|
;
|
|
Vnrval = vn_const(false)
|
|
)
|
|
;
|
|
vn_util__const_if_equal_vns(Vn1, Vn2, ResultIfEqual, Vnrval)
|
|
).
|
|
|
|
:- pred vn_util__simplify_float_compare_op(pred(float, float),
|
|
vn, vnrval, vn, vnrval, rval_const, vnrval).
|
|
:- mode vn_util__simplify_float_compare_op(pred(in, in) is semidet,
|
|
in, in, in, in, in, out) is semidet.
|
|
|
|
vn_util__simplify_float_compare_op(ComparePred, Vn1, Vnrval1, Vn2, Vnrval2,
|
|
ResultIfEqual, Vnrval) :-
|
|
(
|
|
Vnrval1 = vn_const(float_const(C1)),
|
|
Vnrval2 = vn_const(float_const(C2))
|
|
->
|
|
(
|
|
call(ComparePred, C1, C2)
|
|
->
|
|
Vnrval = vn_const(true)
|
|
;
|
|
Vnrval = vn_const(false)
|
|
)
|
|
;
|
|
vn_util__const_if_equal_vns(Vn1, Vn2, ResultIfEqual, Vnrval)
|
|
).
|
|
|
|
:- pred float_eq(float::in, float::in) is semidet.
|
|
float_eq(X, X).
|
|
|
|
:- pred float_ne(float::in, float::in) is semidet.
|
|
float_ne(X, Y) :- X \= Y.
|
|
|
|
:- pred vn_util__const_if_equal_vns(vn, vn, rval_const, vnrval).
|
|
:- mode vn_util__const_if_equal_vns(in, in, in, out) is semidet.
|
|
|
|
vn_util__const_if_equal_vns(Vn1, Vn2, Const, Vnrval) :-
|
|
( Vn1 = Vn2 ->
|
|
Vnrval = vn_const(Const)
|
|
;
|
|
fail
|
|
).
|
|
|
|
vn_util__lval_to_vn(Lval, Vn, VnTables0, VnTables) :-
|
|
vn_util__lval_to_vnlval(Lval, Vnlval, VnTables0, VnTables1),
|
|
( vn_table__search_desired_value(Vnlval, Vn_prime, VnTables1) ->
|
|
Vn = Vn_prime,
|
|
VnTables = VnTables1
|
|
;
|
|
vn_table__record_first_vnlval(Vnlval, Vn, VnTables1, VnTables)
|
|
).
|
|
|
|
vn_util__lval_to_vnlval(Lval, Vnlval, VnTables0, VnTables) :-
|
|
vn_util__no_access_lval_to_vnlval(Lval, MaybeVnlval),
|
|
( MaybeVnlval = yes(VnlvalPrime) ->
|
|
Vnlval = VnlvalPrime,
|
|
VnTables = VnTables0
|
|
; Lval = field(Tag, Rval1, Rval2) ->
|
|
vn_util__rval_to_vn(Rval1, Vn1, VnTables0, VnTables1),
|
|
vn_util__rval_to_vn(Rval2, Vn2, VnTables1, VnTables),
|
|
Vnlval = vn_field(Tag, Vn1, Vn2)
|
|
; Lval = mem_ref(Rval1) ->
|
|
vn_util__rval_to_vn(Rval1, Vn1, VnTables0, VnTables),
|
|
Vnlval = vn_mem_ref(Vn1)
|
|
; Lval = succfr(Rval1) ->
|
|
vn_util__rval_to_vn(Rval1, Vn1, VnTables0, VnTables),
|
|
Vnlval = vn_succfr(Vn1)
|
|
; Lval = prevfr(Rval1) ->
|
|
vn_util__rval_to_vn(Rval1, Vn1, VnTables0, VnTables),
|
|
Vnlval = vn_prevfr(Vn1)
|
|
; Lval = redoip(Rval1) ->
|
|
vn_util__rval_to_vn(Rval1, Vn1, VnTables0, VnTables),
|
|
Vnlval = vn_redoip(Vn1)
|
|
; Lval = succip(Rval1) ->
|
|
vn_util__rval_to_vn(Rval1, Vn1, VnTables0, VnTables),
|
|
Vnlval = vn_succip(Vn1)
|
|
;
|
|
error("unexpected lval in vn_util__lval_to_vnlval")
|
|
).
|
|
|
|
% If you to add to this list to fix a determinism error,
|
|
% check vn_util__lval_to_vnlval above as well.
|
|
% vn_util__lval_to_vnlval should have code to handle every lval
|
|
% that is mapped to "no" by vn_util__no_access_lval_to_vnlval.
|
|
|
|
vn_util__no_access_lval_to_vnlval(reg(T, N), yes(vn_reg(T, N))).
|
|
vn_util__no_access_lval_to_vnlval(temp(T, N), yes(vn_temp(T, N))).
|
|
vn_util__no_access_lval_to_vnlval(stackvar(N), yes(vn_stackvar(N))).
|
|
vn_util__no_access_lval_to_vnlval(framevar(N), yes(vn_framevar(N))).
|
|
vn_util__no_access_lval_to_vnlval(succip, yes(vn_succip)).
|
|
vn_util__no_access_lval_to_vnlval(maxfr, yes(vn_maxfr)).
|
|
vn_util__no_access_lval_to_vnlval(curfr, yes(vn_curfr)).
|
|
vn_util__no_access_lval_to_vnlval(redoip(_), no).
|
|
vn_util__no_access_lval_to_vnlval(succip(_), no).
|
|
vn_util__no_access_lval_to_vnlval(prevfr(_), no).
|
|
vn_util__no_access_lval_to_vnlval(succfr(_), no).
|
|
vn_util__no_access_lval_to_vnlval(hp, yes(vn_hp)).
|
|
vn_util__no_access_lval_to_vnlval(sp, yes(vn_sp)).
|
|
vn_util__no_access_lval_to_vnlval(mem_ref(_), no).
|
|
vn_util__no_access_lval_to_vnlval(field(_, _, _), no).
|
|
vn_util__no_access_lval_to_vnlval(lvar(_Var), _) :-
|
|
error("lvar detected in value_number").
|
|
|
|
vn_util__no_access_vnlval_to_lval(vn_reg(T, N), yes(reg(T, N))).
|
|
vn_util__no_access_vnlval_to_lval(vn_temp(T, N), yes(temp(T, N))).
|
|
vn_util__no_access_vnlval_to_lval(vn_stackvar(N), yes(stackvar(N))).
|
|
vn_util__no_access_vnlval_to_lval(vn_framevar(N), yes(framevar(N))).
|
|
vn_util__no_access_vnlval_to_lval(vn_succip, yes(succip)).
|
|
vn_util__no_access_vnlval_to_lval(vn_maxfr, yes(maxfr)).
|
|
vn_util__no_access_vnlval_to_lval(vn_curfr, yes(curfr)).
|
|
vn_util__no_access_vnlval_to_lval(vn_succfr(_), no).
|
|
vn_util__no_access_vnlval_to_lval(vn_prevfr(_), no).
|
|
vn_util__no_access_vnlval_to_lval(vn_redoip(_), no).
|
|
vn_util__no_access_vnlval_to_lval(vn_succip(_), no).
|
|
vn_util__no_access_vnlval_to_lval(vn_hp, yes(hp)).
|
|
vn_util__no_access_vnlval_to_lval(vn_sp, yes(sp)).
|
|
vn_util__no_access_vnlval_to_lval(vn_field(_, _, _), no).
|
|
vn_util__no_access_vnlval_to_lval(vn_mem_ref(_), no).
|
|
|
|
/* one of these preds should be eliminated XXX */
|
|
vn_util__vnlval_access_vns(vn_reg(_, _), []).
|
|
vn_util__vnlval_access_vns(vn_temp(_, _), []).
|
|
vn_util__vnlval_access_vns(vn_stackvar(_), []).
|
|
vn_util__vnlval_access_vns(vn_framevar(_), []).
|
|
vn_util__vnlval_access_vns(vn_succip, []).
|
|
vn_util__vnlval_access_vns(vn_maxfr, []).
|
|
vn_util__vnlval_access_vns(vn_curfr, []).
|
|
vn_util__vnlval_access_vns(vn_succfr(Vn), [Vn]).
|
|
vn_util__vnlval_access_vns(vn_prevfr(Vn), [Vn]).
|
|
vn_util__vnlval_access_vns(vn_redoip(Vn), [Vn]).
|
|
vn_util__vnlval_access_vns(vn_succip(Vn), [Vn]).
|
|
vn_util__vnlval_access_vns(vn_hp, []).
|
|
vn_util__vnlval_access_vns(vn_sp, []).
|
|
vn_util__vnlval_access_vns(vn_field(_, Vn1, Vn2), [Vn1, Vn2]).
|
|
vn_util__vnlval_access_vns(vn_mem_ref(Vn), [Vn]).
|
|
|
|
vn_util__find_sub_vns(vn_origlval(Vnlval), SubVns) :-
|
|
vn_util__vnlval_access_vns(Vnlval, SubVns).
|
|
vn_util__find_sub_vns(vn_mkword(_, SubVn), [SubVn]).
|
|
vn_util__find_sub_vns(vn_const(_), []).
|
|
vn_util__find_sub_vns(vn_create(_, _, _, _, _), []).
|
|
vn_util__find_sub_vns(vn_unop(_, SubVn), [SubVn]).
|
|
vn_util__find_sub_vns(vn_binop(_, SubVn1, SubVn2), [SubVn1, SubVn2]).
|
|
vn_util__find_sub_vns(vn_stackvar_addr(_), []).
|
|
vn_util__find_sub_vns(vn_framevar_addr(_), []).
|
|
vn_util__find_sub_vns(vn_heap_addr(SubVn, _, _), [SubVn]).
|
|
|
|
vn_util__is_const_expr(Vn, IsConst, VnTables) :-
|
|
vn_table__lookup_defn(Vn, Vnrval, "vn_util__is_const_expr", VnTables),
|
|
(
|
|
Vnrval = vn_origlval(_),
|
|
IsConst = no
|
|
;
|
|
Vnrval = vn_mkword(_, Vn1),
|
|
vn_util__is_const_expr(Vn1, IsConst, VnTables)
|
|
;
|
|
Vnrval = vn_const(_),
|
|
IsConst = yes
|
|
;
|
|
Vnrval = vn_create(_, _, _, _, _),
|
|
IsConst = yes
|
|
;
|
|
Vnrval = vn_unop(_, Vn1),
|
|
vn_util__is_const_expr(Vn1, IsConst, VnTables)
|
|
;
|
|
Vnrval = vn_binop(_, Vn1, Vn2),
|
|
vn_util__is_const_expr(Vn1, IsConst1, VnTables),
|
|
vn_util__is_const_expr(Vn2, IsConst2, VnTables),
|
|
bool__and(IsConst1, IsConst2, IsConst)
|
|
;
|
|
Vnrval = vn_stackvar_addr(_),
|
|
IsConst = no
|
|
;
|
|
Vnrval = vn_framevar_addr(_),
|
|
IsConst = no
|
|
;
|
|
Vnrval = vn_heap_addr(_, _, _),
|
|
IsConst = no
|
|
).
|
|
|
|
vn_util__find_lvals_in_rval(Rval, Lvals) :-
|
|
(
|
|
Rval = lval(Lval),
|
|
opt_util__lval_access_rvals(Lval, Rvals),
|
|
vn_util__find_lvals_in_rvals(Rvals, Lvals1),
|
|
Lvals = [Lval | Lvals1]
|
|
;
|
|
Rval = var(_),
|
|
error("var found in vn_util__find_lvals_in_rval")
|
|
;
|
|
Rval = create(_, _, _, _, _),
|
|
Lvals = []
|
|
;
|
|
Rval = mkword(_, Rval1),
|
|
vn_util__find_lvals_in_rval(Rval1, Lvals)
|
|
;
|
|
Rval = const(_),
|
|
Lvals = []
|
|
;
|
|
Rval = unop(_, Rval1),
|
|
vn_util__find_lvals_in_rval(Rval1, Lvals)
|
|
;
|
|
Rval = binop(_, Rval1, Rval2),
|
|
vn_util__find_lvals_in_rval(Rval1, Lvals1),
|
|
vn_util__find_lvals_in_rval(Rval2, Lvals2),
|
|
list__append(Lvals1, Lvals2, Lvals)
|
|
;
|
|
Rval = mem_addr(MemRef),
|
|
vn_util__find_lvals_in_mem_ref(MemRef, Lvals)
|
|
).
|
|
|
|
vn_util__find_lvals_in_rvals([], []).
|
|
vn_util__find_lvals_in_rvals([Rval | Rvals], Lvals) :-
|
|
vn_util__find_lvals_in_rval(Rval, Lvals1),
|
|
vn_util__find_lvals_in_rvals(Rvals, Lvals2),
|
|
list__append(Lvals1, Lvals2, Lvals).
|
|
|
|
:- pred vn_util__find_lvals_in_mem_ref(mem_ref, list(lval)).
|
|
:- mode vn_util__find_lvals_in_mem_ref(in, out) is det.
|
|
|
|
% XXX
|
|
vn_util__find_lvals_in_mem_ref(stackvar_ref(_), []).
|
|
vn_util__find_lvals_in_mem_ref(framevar_ref(_), []).
|
|
vn_util__find_lvals_in_mem_ref(heap_ref(Rval, _, _), Lvals) :-
|
|
vn_util__find_lvals_in_rval(Rval, Lvals).
|
|
|
|
vn_util__is_vn_shared(Vn, Vnrval, Uses0, VnTables) :-
|
|
vn_util__is_const_expr(Vn, no, VnTables),
|
|
\+ Vnrval = vn_origlval(vn_hp),
|
|
vn_util__real_uses(Uses0, Uses1, VnTables),
|
|
Uses1 = [_,_|_].
|
|
|
|
vn_util__real_uses([], [], _VnTables).
|
|
vn_util__real_uses([Use0 | Uses0], Uses, VnTables) :-
|
|
vn_util__real_uses(Uses0, Uses1, VnTables),
|
|
( list__member(Use0, Uses1) ->
|
|
Uses = Uses1
|
|
; Use0 = src_liveval(Vnlval) ->
|
|
(
|
|
vn_table__search_desired_value(Vnlval, Vn, VnTables),
|
|
vn_table__search_current_value(Vnlval, Vn, VnTables)
|
|
->
|
|
Uses = Uses1
|
|
;
|
|
Uses = [Use0 | Uses1]
|
|
)
|
|
; Use0 = src_access(Vnlval) ->
|
|
(
|
|
vn_table__search_desired_value(Vnlval, Vn, VnTables),
|
|
vn_table__search_current_value(Vnlval, Vn, VnTables),
|
|
( vn_table__search_uses(Vn, AccessUses, VnTables) ->
|
|
(
|
|
vn_util__real_uses(AccessUses, [],
|
|
VnTables)
|
|
;
|
|
vn_table__search_current_locs(Vn, Locs,
|
|
VnTables),
|
|
vn_util__choose_cheapest_loc(Locs, Loc),
|
|
vn_util__classify_loc_cost(Loc, 0)
|
|
)
|
|
;
|
|
true
|
|
)
|
|
->
|
|
Uses = Uses1
|
|
;
|
|
Uses = [Use0 | Uses1]
|
|
)
|
|
;
|
|
Uses = [Use0 | Uses1]
|
|
).
|
|
|
|
vn_util__choose_cheapest_loc(Locs, BestLoc) :-
|
|
vn_util__choose_cheapest_loc_2(Locs, no, no, BestLoc).
|
|
|
|
:- pred vn_util__choose_cheapest_loc_2(list(vnlval), maybe(vnlval), maybe(vnlval),
|
|
vnlval).
|
|
:- mode vn_util__choose_cheapest_loc_2(in, in, in, out) is semidet.
|
|
|
|
vn_util__choose_cheapest_loc_2([Loc | Locs], Stack0, Heap0, BestLoc) :-
|
|
vn_util__classify_loc_cost(Loc, Cost),
|
|
( Cost = 0 ->
|
|
BestLoc = Loc
|
|
; Cost = 1 ->
|
|
vn_util__choose_cheapest_loc_2(Locs, yes(Loc), Heap0, BestLoc)
|
|
;
|
|
vn_util__choose_cheapest_loc_2(Locs, Stack0, yes(Loc), BestLoc)
|
|
).
|
|
vn_util__choose_cheapest_loc_2([], Stack0, Heap0, BestLoc) :-
|
|
( Stack0 = yes(Stack) ->
|
|
BestLoc = Stack
|
|
; Heap0 = yes(Heap) ->
|
|
BestLoc = Heap
|
|
;
|
|
fail
|
|
).
|
|
|
|
vn_util__classify_loc_cost(vn_reg(_, _), 0).
|
|
vn_util__classify_loc_cost(vn_temp(_, _), 0).
|
|
vn_util__classify_loc_cost(vn_stackvar(_), 1).
|
|
vn_util__classify_loc_cost(vn_framevar(_), 1).
|
|
vn_util__classify_loc_cost(vn_succip, 0).
|
|
vn_util__classify_loc_cost(vn_maxfr, 0).
|
|
vn_util__classify_loc_cost(vn_curfr, 0).
|
|
vn_util__classify_loc_cost(vn_succfr(_), 1).
|
|
vn_util__classify_loc_cost(vn_prevfr(_), 1).
|
|
vn_util__classify_loc_cost(vn_redoip(_), 1).
|
|
vn_util__classify_loc_cost(vn_succip(_), 1).
|
|
vn_util__classify_loc_cost(vn_hp, 0).
|
|
vn_util__classify_loc_cost(vn_sp, 0).
|
|
vn_util__classify_loc_cost(vn_field(_, _, _), 2).
|
|
vn_util__classify_loc_cost(vn_mem_ref(_), 2).
|
|
|
|
%-----------------------------------------------------------------------------%
|
|
%-----------------------------------------------------------------------------%
|
|
|
|
:- interface.
|
|
|
|
% Build up a list of the uses of each vn.
|
|
|
|
:- pred vn_util__build_uses(vnlvalset, ctrlmap, vn_tables, vn_tables).
|
|
% :- mode vn_util__build_uses(in, in, di, uo) is det.
|
|
:- mode vn_util__build_uses(in, in, in, out) is det.
|
|
|
|
:- implementation.
|
|
|
|
vn_util__build_uses(Livevals, Ctrlmap, VnTables0, VnTables) :-
|
|
vn_util__build_uses_from_ctrl(0, Ctrlmap, VnTables0, VnTables1),
|
|
set__to_sorted_list(Livevals, Livelist),
|
|
vn_util__build_uses_from_livevals(Livelist, VnTables1, VnTables).
|
|
|
|
:- pred vn_util__build_uses_from_ctrl(int, ctrlmap, vn_tables, vn_tables).
|
|
% :- mode vn_util__build_uses_from_ctrl(in, in, di, uo) is det.
|
|
:- mode vn_util__build_uses_from_ctrl(in, in, in, out) is det.
|
|
|
|
vn_util__build_uses_from_ctrl(Ctrl, Ctrlmap, VnTables0, VnTables) :-
|
|
( map__search(Ctrlmap, Ctrl, VnInstr) ->
|
|
(
|
|
VnInstr = vn_livevals(_),
|
|
VnTables1 = VnTables0
|
|
;
|
|
VnInstr = vn_call(_, _, _, _),
|
|
VnTables1 = VnTables0
|
|
;
|
|
VnInstr = vn_mkframe(_, _, _, _),
|
|
VnTables1 = VnTables0
|
|
;
|
|
VnInstr = vn_label(_),
|
|
VnTables1 = VnTables0
|
|
;
|
|
VnInstr = vn_goto(_),
|
|
VnTables1 = VnTables0
|
|
;
|
|
VnInstr = vn_computed_goto(Vn, _),
|
|
vn_util__record_use(Vn, src_ctrl(Ctrl),
|
|
VnTables0, VnTables1)
|
|
;
|
|
VnInstr = vn_if_val(Vn, _),
|
|
vn_util__record_use(Vn, src_ctrl(Ctrl),
|
|
VnTables0, VnTables1)
|
|
;
|
|
VnInstr = vn_mark_hp(Vnlval),
|
|
vn_util__vnlval_access_vns(Vnlval, Vns),
|
|
vn_util__record_use_list(Vns, src_ctrl(Ctrl),
|
|
VnTables0, VnTables1)
|
|
;
|
|
VnInstr = vn_restore_hp(Vn),
|
|
vn_util__record_use(Vn, src_ctrl(Ctrl),
|
|
VnTables0, VnTables1)
|
|
;
|
|
VnInstr = vn_store_ticket(Vnlval),
|
|
vn_util__vnlval_access_vns(Vnlval, Vns),
|
|
vn_util__record_use_list(Vns, src_ctrl(Ctrl),
|
|
VnTables0, VnTables1)
|
|
;
|
|
VnInstr = vn_reset_ticket(Vn, _Reason),
|
|
vn_util__record_use(Vn, src_ctrl(Ctrl),
|
|
VnTables0, VnTables1)
|
|
;
|
|
VnInstr = vn_discard_ticket,
|
|
VnTables1 = VnTables0
|
|
;
|
|
VnInstr = vn_mark_ticket_stack(Vnlval),
|
|
vn_util__vnlval_access_vns(Vnlval, Vns),
|
|
vn_util__record_use_list(Vns, src_ctrl(Ctrl),
|
|
VnTables0, VnTables1)
|
|
;
|
|
VnInstr = vn_discard_tickets_to(Vn),
|
|
vn_util__record_use(Vn, src_ctrl(Ctrl),
|
|
VnTables0, VnTables1)
|
|
;
|
|
VnInstr = vn_incr_sp(_, _),
|
|
VnTables1 = VnTables0
|
|
;
|
|
VnInstr = vn_decr_sp(_),
|
|
VnTables1 = VnTables0
|
|
),
|
|
NextCtrl is Ctrl + 1,
|
|
vn_util__build_uses_from_ctrl(NextCtrl, Ctrlmap,
|
|
VnTables1, VnTables)
|
|
;
|
|
VnTables = VnTables0
|
|
).
|
|
|
|
% We have to record two kinds of uses. The first is the use of the
|
|
% value number we want to assign to the vnlval. The second is the
|
|
% value numbers needed to access the vnlval at all.
|
|
|
|
:- pred vn_util__build_uses_from_livevals(list(vnlval), vn_tables, vn_tables).
|
|
% :- mode vn_util__build_uses_from_livevals(in, di, uo) is det.
|
|
:- mode vn_util__build_uses_from_livevals(in, in, out) is det.
|
|
|
|
vn_util__build_uses_from_livevals([], VnTables, VnTables).
|
|
vn_util__build_uses_from_livevals([Live | Liveslist], VnTables0, VnTables) :-
|
|
( vn_table__search_desired_value(Live, VnPrime, VnTables0) ->
|
|
Vn = VnPrime,
|
|
VnTables1 = VnTables0
|
|
;
|
|
vn_table__record_first_vnlval(Live, Vn, VnTables0, VnTables1)
|
|
),
|
|
vn_util__record_use(Vn, src_liveval(Live), VnTables1, VnTables2),
|
|
vn_util__record_access([Live], VnTables2, VnTables3),
|
|
vn_util__build_uses_from_livevals(Liveslist, VnTables3, VnTables).
|
|
|
|
:- pred vn_util__record_access(list(vnlval), vn_tables, vn_tables).
|
|
% :- mode vn_util__record_access(in, di, uo) is det.
|
|
:- mode vn_util__record_access(in, in, out) is det.
|
|
|
|
vn_util__record_access([], VnTables, VnTables).
|
|
vn_util__record_access([Vnlval | Vnlvals], VnTables0, VnTables) :-
|
|
vn_util__vnlval_access_vns(Vnlval, SubVns),
|
|
vn_util__record_use_list(SubVns, src_access(Vnlval),
|
|
VnTables0, VnTables1),
|
|
vn_util__record_access(Vnlvals, VnTables1, VnTables).
|
|
|
|
:- pred vn_util__record_use(vn, vn_src, vn_tables, vn_tables).
|
|
% :- mode vn_util__record_use(in, in, di, uo) is det.
|
|
:- mode vn_util__record_use(in, in, in, out) is det.
|
|
|
|
vn_util__record_use(Vn, Src, VnTables0, VnTables) :-
|
|
vn_table__lookup_uses(Vn, OldUses, "vn_util__record_use", VnTables0),
|
|
vn_table__add_new_use(Vn, Src, VnTables0, VnTables1),
|
|
( OldUses = [] ->
|
|
vn_table__lookup_defn(Vn, Vnrval, "vn_util__record_use",
|
|
VnTables1),
|
|
(
|
|
Vnrval = vn_origlval(Vnlval),
|
|
vn_util__record_access([Vnlval], VnTables1, VnTables)
|
|
;
|
|
Vnrval = vn_mkword(_, SubVn),
|
|
vn_util__record_use(SubVn, src_vn(Vn),
|
|
VnTables1, VnTables)
|
|
;
|
|
Vnrval = vn_const(_),
|
|
VnTables = VnTables1
|
|
;
|
|
Vnrval = vn_create(_, _, _, _, _),
|
|
VnTables = VnTables1
|
|
;
|
|
Vnrval = vn_unop(_, SubVn),
|
|
vn_util__record_use(SubVn, src_vn(Vn),
|
|
VnTables1, VnTables)
|
|
;
|
|
Vnrval = vn_binop(_, SubVn1, SubVn2),
|
|
vn_util__record_use(SubVn1, src_vn(Vn),
|
|
VnTables1, VnTables2),
|
|
vn_util__record_use(SubVn2, src_vn(Vn),
|
|
VnTables2, VnTables)
|
|
;
|
|
Vnrval = vn_stackvar_addr(_),
|
|
VnTables = VnTables1
|
|
;
|
|
Vnrval = vn_framevar_addr(_),
|
|
VnTables = VnTables1
|
|
;
|
|
Vnrval = vn_heap_addr(SubVn, _, _),
|
|
vn_util__record_use(SubVn, src_vn(Vn),
|
|
VnTables1, VnTables)
|
|
)
|
|
;
|
|
VnTables = VnTables1
|
|
).
|
|
|
|
:- pred vn_util__record_use_list(list(vn), vn_src, vn_tables, vn_tables).
|
|
% :- mode vn_util__record_use_list(in, in, di, uo) is det.
|
|
:- mode vn_util__record_use_list(in, in, in, out) is det.
|
|
|
|
vn_util__record_use_list([], _Src, VnTables, VnTables).
|
|
vn_util__record_use_list([Vn | Vns], Src, VnTables0, VnTables) :-
|
|
vn_util__record_use(Vn, Src, VnTables0, VnTables1),
|
|
vn_util__record_use_list(Vns, Src, VnTables1, VnTables).
|
|
|
|
%-----------------------------------------------------------------------------%
|
|
%-----------------------------------------------------------------------------%
|