mirror of
https://github.com/Mercury-Language/mercury.git
synced 2025-12-17 23:05:21 +00:00
Estimated hours taken: 40
Support line numbers in the debugger. You now get contexts (filename:lineno
pairs) printed in several circumstances, and you can put breakpoints on
contexts, when they correspond to trace events or to calls. The latter are
implemented as breakpoints on the label layouts of the return sites.
This required extending the debugging RTTI, so that associated with each
module there is now a new data structure listing the source file names that
contribute labels with layout structures to the code of the module. For each
such source file, this table gives a list of all such labels arising from
that file. The table entry for a label gives the line number within the file,
and the pointer to the label layout structure.
compiler/llds.m:
Add a context field to the call instruction.
compiler/continuation_info.m:
Instead of the old division of continuation info about labels into
trace ports and everything else, divide them into trace ports, resume
points and return sites. Record contexts with trace ports, and record
contexts and called procedure information with return sites.
compiler/code_info.m:
Conform to the changes in continuation_info.m.
compiler/options.m:
Add a new option that allows us to disable the generation of line
number information for size benchmarking (it has no other use).
compiler/stack_layout.m:
Generate the new components of the RTTI, unless the option says not to.
compiler/code_gen.m:
compiler/pragma_c_gen.m:
compiler/trace.m:
Include contexts in the information we gather for the layouts
associated with the events we generate.
compiler/call_gen.m:
Include contexts in the call LLDS instructions, for association
with the return site's label layout structure (which is done after
code generation is finished).
compiler/handle_options.m:
Delete the code that tests or sets the deleted options.
compiler/mercury_compile.m:
Delete the code that tests the deleted options.
compiler/basic_block.m:
compiler/dupelim.m:
compiler/frameopt.m:
compiler/livemap.m:
compiler/llds_common.m:
compiler/llds_out.m:
compiler/middle_rec.m:
compiler/opt_debug.m:
compiler/opt_util.m:
compiler/value_number.m:
compiler/vn_*.m:
Trivial changes to conform to the changes to llds.m.
compiler/jumpopt.m:
Do not optimize away jumps to labels with layout structures.
The jumps we are particularly concerned about now are the jumps
that return from procedure calls. Previously, it was okay to redirect
returns from several calls so that all go to the same label, since
the live variable information associated with the labels could be
merged. However, we now also associate line numbers with calls, and
these cannot be usefully merged.
compiler/optimize.m:
Pass the information required by jumpopt to it.
doc/user_guide.texi:
Document that you can now break at line numbers.
Document the new "context" command, and the -d or --detailed option
of the stack command and the commands that set ancestor levels.
runtime/mercury_stack_layout.h:
Extend the module layout structure definition with the new tables.
Remove the conditional facility for including label numbers in label
layout structures. It hasn't been used in a long time, and neither
Tyson or me expect to use it to debug either gc or the debugger itself,
so it has no uses left; the line numbers have superseded it.
runtime/mercury_stack_trace.[ch]:
Extend the code to print stack traces to also optionally print
contexts.
Add some utility predicates currently used by the debugger that could
also be use for debugging gc or for more detailed stack traces.
trace/mercury_trace_internal.c:
Implement the "break <context>" command, the "context" command, and
the -d or --detailed option of the stack command and the commands
that set ancestor levels.
Conditionally define a conditionally used variable.
trace/mercury_trace_external.c:
Minor changes to keep up with the changes to stack traces.
Delete an unused variable.
trace/mercury_trace_spy.[ch]:
Check for breakpoints on contexts.
trace/mercury_trace_tables.[ch]:
Add functions to search the RTTI data structures for labels
corresponding to a given context.
trace/mercury_trace_vars.[ch]:
Remember the context of the current environment.
tests/debugger/queen.{inp,exp}:
Test the new capabilities of the debugger.
tests/debugger/*.{inp,exp}:
Update the expected output of the debugger to account for contexts.
In some cases, modify the input script to put contexts where they don't
overflow lines.
1384 lines
39 KiB
Mathematica
1384 lines
39 KiB
Mathematica
%-----------------------------------------------------------------------------%
|
|
% Copyright (C) 1995-1999 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 builtin_ops, 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_prevfr(Vn), [vn_prevfr(Vn)]).
|
|
vn_util__find_specials(vn_redoip(Vn), [vn_redoip(Vn)]).
|
|
vn_util__find_specials(vn_redofr(Vn), [vn_redofr(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_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, ArgTypes, StatDyn, Label, Msg),
|
|
vn_util__vnrval_to_vn(vn_create(Tag, Args, ArgTypes,
|
|
StatDyn, 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
|
|
|
|
% XXX we should check for overflow
|
|
|
|
% XXX some of this code should be shared with const_prop.m
|
|
|
|
:- 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 = unchecked_right_shift(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 = unchecked_left_shift(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 = 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 = redofr(Rval1) ->
|
|
vn_util__rval_to_vn(Rval1, Vn1, VnTables0, VnTables),
|
|
Vnlval = vn_redofr(Vn1)
|
|
; Lval = succip(Rval1) ->
|
|
vn_util__rval_to_vn(Rval1, Vn1, VnTables0, VnTables),
|
|
Vnlval = vn_succip(Vn1)
|
|
; Lval = succfr(Rval1) ->
|
|
vn_util__rval_to_vn(Rval1, Vn1, VnTables0, VnTables),
|
|
Vnlval = vn_succfr(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(prevfr(_), no).
|
|
vn_util__no_access_lval_to_vnlval(redoip(_), no).
|
|
vn_util__no_access_lval_to_vnlval(redofr(_), no).
|
|
vn_util__no_access_lval_to_vnlval(succip(_), 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_redofr(_), no).
|
|
vn_util__no_access_vnlval_to_lval(vn_redoip(_), no).
|
|
vn_util__no_access_vnlval_to_lval(vn_prevfr(_), no).
|
|
vn_util__no_access_vnlval_to_lval(vn_succip(_), no).
|
|
vn_util__no_access_vnlval_to_lval(vn_succfr(_), 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_prevfr(Vn), [Vn]).
|
|
vn_util__vnlval_access_vns(vn_redoip(Vn), [Vn]).
|
|
vn_util__vnlval_access_vns(vn_redofr(Vn), [Vn]).
|
|
vn_util__vnlval_access_vns(vn_succip(Vn), [Vn]).
|
|
vn_util__vnlval_access_vns(vn_succfr(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_prevfr(_), 1).
|
|
vn_util__classify_loc_cost(vn_redoip(_), 1).
|
|
vn_util__classify_loc_cost(vn_redofr(_), 1).
|
|
vn_util__classify_loc_cost(vn_succip(_), 1).
|
|
vn_util__classify_loc_cost(vn_succfr(_), 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).
|
|
|
|
%-----------------------------------------------------------------------------%
|
|
%-----------------------------------------------------------------------------%
|