mirror of
https://github.com/Mercury-Language/mercury.git
synced 2025-12-15 05:44:58 +00:00
Estimated hours taken: 1200
Aditi compilation.
compiler/options.m:
The documentation for these is commented out because the Aditi
system is not currently useful to the general public.
--aditi: enable Aditi compilation.
--dump-rl: write the intermediate RL to `<module>.rl_dump'.
--dump-rl-bytecode: write a text version of the bytecodes
to `<module>.rla'
--aditi-only: don't produce a `.c' file.
--filenames-from-stdin: accept a list of filenames to compile
from stdin. This is used by the query shell.
--optimize-rl, --optimize-rl-cse, --optimize-rl-invariants,
--optimize-rl-index, --detect-rl-streams:
Options to control RL optimization passes.
--aditi-user:
Default owner of any Aditi procedures,
defaults to $USER or "guest".
--generate-schemas:
write schemas for base relations to `<module>'.base_schema
and schemas for derived relations to `<module>'.derived_schema.
This is used by the query shell.
compiler/handle_options.m:
Handle the default for --aditi-user.
compiler/hlds_pred.m:
compiler/prog_data.m:
compiler/prog_io_pragma.m:
compiler/make_hlds.m:
Add some Aditi pragma declarations - `aditi', `supp_magic', `context',
`naive', `psn' (predicate semi-naive), `aditi_memo', `aditi_no_memo',
`base_relation', `owner' and `index'.
Separate out code to parse a predicate name and arity.
compiler/hlds_pred.m:
Add predicates to identify Aditi procedures.
Added markers `generate_inline' and `aditi_interface', which
are used internally for Aditi code generation.
Add an `owner' field to pred_infos, which is used for database
security checks.
Add a field to pred_infos to hold the list of indexes for a base
relation.
compiler/make_hlds.m:
Some pragmas must be exported if the corresponding predicates
are exported, check this.
Make sure stratification of Aditi procedures is checked.
Predicates with a mode declaration but no type declaration
are no longer assumed to be local.
Set the `do_aditi_compilation' field of the module_info if there
are any local Aditi procedures or base relations.
Check that `--aditi' is set if Aditi compilation is required.
compiler/post_typecheck.m:
Check that every Aditi predicate has an `aditi__state' argument,
which is used to ensure sequencing of updates and that Aditi
procedures are only called within transactions.
compiler/dnf.m:
Changed the definition of disjunctive normal form slightly
so that a call followed by some atomic goals not including
any database calls is considered atomic. magic.m can handle
this kind of goal, and it results in more efficient RL code.
compiler/hlds_module.m:
compiler/dependency_graph.m:
Added dependency_graph__get_scc_entry_points which finds
the procedures in an SCC which could be called from outside.
Added a new field to the dependency_info, the
aditi_dependency_ordering. This contains all Aditi SCCs of
the original program, with multiple SCCs merged where
possible to improve the effectiveness of differential evaluation
and the low level RL optimizations.
compiler/hlds_module.m:
Add a field to record whether there are any local Aditi procedures
in the current module.
Added versions of module_info_pred_proc_info and
module_info_set_pred_proc_info which take a pred_proc_id,
not a separate pred_id and proc_id.
compiler/polymorphism.m:
compiler/lambda.m:
Make sure that predicates created for closures in Aditi procedures
have the correct markers.
compiler/goal_util.m:
Added goal_util__switch_to_disjunction,
goal_util__case_to_disjunct (factored out from simplify.m)
and goal_util__if_then_else_to_disjunction. These are
require because supplementary magic sets can't handle
if-then-elses or switches.
compiler/type_util.m:
Added type_is_aditi_state/1.
compiler/mode_util.m:
Added partition_args/5 which partitions a list of arguments
into inputs and others.
compiler/inlining.m:
Don't inline memoed procedures.
Don't inline Aditi procedures into non-Aditi procedures.
compiler/intermod.m:
Handle Aditi markers.
Clean up handling of markers which should not appear in `.opt' files.
compiler/simplify.m:
Export a slightly different interface for use by magic.m.
Remove explicit quantifications where possible.
Merge multiple nested quantifications.
Don't report infinite recursion warnings for Aditi procedures.
compiler/prog_out.m:
Generalised the code to output a module list to write any list.
compiler/code_gen.m:
compiler/arg_info.m:
Don't process Aditi procedures.
compiler/mercury_compile.m:
Call magic.m and rl_gen.m.
Don't perform the low-level annotation passes on Aditi procedures.
Remove calls to constraint.m - sometime soon a rewritten version
will be called directly from deforestation.
compiler/passes_aux.m:
Add predicates to process only non-Aditi procedures.
compiler/llds.m:
compiler/llds_out.m:
Added new `code_addr' enum members, do_{det,semidet,nondet}_aditi_call,
which are defined in extras/aditi/aditi.m.
compiler/call_gen.m:
Handle generation of do_*_aditi_call.
compiler/llds_out.m:
Write the RL code for the module as a constant char array
in the `.c' file.
compiler/term_errors.m:
compiler/error_util.m:
Move code to describe predicates into error_util.m
Allow the caller to explicitly add line breaks.
Added error_util:list_to_pieces to format a list of
strings.
Reordered some arguments for currying.
compiler/hlds_out.m:
Don't try to print clauses if there are none.
runtime/mercury_init.h:
util/mkinit.c:
scripts/c2init.in:
Added a function `mercury__load_aditi_rl_code()' to the generated
`<module>_init.c' file which throws all the RL code for the program
at the database. This should be called at connection time by
`aditi__connect'.
Added an option `--aditi' which controls the output
`mercury__load_aditi_rl_code()'.
compiler/notes/compiler_design.html:
Document the new files.
Mmakefile:
bindist/Mmakefile:
Don't distribute extras/aditi yet.
New files:
compiler/magic.m:
compiler/magic_util.m:
Supplementary magic sets transformation. Report errors
for constructs that Aditi can't handle.
compiler/context.m:
Supplementary context transformation.
compiler/rl_gen.m:
compiler/rl_relops.m:
Aditi code generation.
compiler/rl_info.m:
Code generator state.
compiler/rl.m:
Intermediate RL representation.
compiler/rl_util:
Predicates to collect information about RL instructions.
compiler/rl_dump.m:
Print out the representation in rl.m.
compiler/rl_opt.m:
Control low-level RL optimizations.
compiler/rl_block.m:
Break a procedure into basic blocks.
compiler/rl_analyse.m:
Generic dataflow analysis for RL procedures.
compiler/rl_liveness.m:
Make sure all relations are initialised before used, clear
references to relations that are no longer required.
compiler/rl_loop.m:
Loop invariant removal.
compiler/rl_block_opt.m:
CSE and instruction merging on basic blocks.
compiler/rl_key.m:
Detect upper/lower bounds for which a goal could succeed.
compiler/rl_sort.m:
Use indexing for joins and projections.
Optimize away unnecessary sorting and indexing.
compiler/rl_stream.m:
Detect relations which don't need to be materialised.
compiler/rl_code.m:
RL bytecode definitions. Automatically generated from the Aditi
header files.
compiler/rl_out.m:
compiler/rl_file.m:
Output the RL bytecodes in binary to <module>.rlo (for use by Aditi)
and in text to <module>.rla (for use by the RL interpreter).
Also output the schema information if --generate-schemas is set.
compiler/rl_exprn.m:
Generate bytecodes for join conditions.
extras/aditi/Mmakefile:
extras/aditi/aditi.m:
Definitions of some Aditi library predicates and the
interfacing and transaction processing code.
845 lines
31 KiB
Mathematica
845 lines
31 KiB
Mathematica
%-----------------------------------------------------------------------------%
|
|
% Copyright (C) 1998 University of Melbourne.
|
|
% This file may only be copied under the terms of the GNU General
|
|
% Public License - see the file COPYING in the Mercury distribution.
|
|
%-----------------------------------------------------------------------------%
|
|
% File: rl_block.m
|
|
% Main author: stayl
|
|
%
|
|
% Find the basic blocks and loops in a list of RL instructions.
|
|
% Produce a flow graph.
|
|
% See the Dragon Book for details.
|
|
%-----------------------------------------------------------------------------%
|
|
:- module rl_block.
|
|
|
|
:- interface.
|
|
|
|
:- import_module rl, hlds_pred, hlds_module, prog_data.
|
|
:- import_module bool, io, int, list, map, relation, set, std_util.
|
|
|
|
:- pred rl_block__create_flow_graph(bool::in, module_info::in,
|
|
rl_proc::in, rl_opt_info::out,
|
|
io__state::di, io__state::uo) is det.
|
|
|
|
% Find all relations which are used by more than one block.
|
|
:- pred rl_block__get_nonlocal_relations(set(relation_id)::out,
|
|
rl_opt_info::in, rl_opt_info::out) is det.
|
|
|
|
% Convert a flow graph back into a list of instructions.
|
|
:- pred rl_block__get_proc(rl_opt_info::in, rl_proc_name::in,
|
|
list(pred_proc_id)::in, rl_proc::out) is det.
|
|
|
|
% If the boolean is `yes' dump the RL code.
|
|
:- pred rl_block__dump_blocks(bool::in, rl_opt_info::in,
|
|
rl_opt_info::out, io__state::di, io__state::uo) is det.
|
|
|
|
%-----------------------------------------------------------------------------%
|
|
:- implementation.
|
|
|
|
:- import_module hlds_module, rl_dump.
|
|
:- import_module queue, require, string.
|
|
|
|
rl_block__create_flow_graph(Debug, ModuleInfo, Proc, Info) -->
|
|
{ rl_block__build_maps(ModuleInfo, Proc, Info1) },
|
|
rl_block__dump_blocks(Debug, Info1, Info2),
|
|
rl_block__dump_flow_graph(Debug, Info2, Info3),
|
|
|
|
{ rl_block__get_dominator_info(Info3, Info4) },
|
|
{ rl_block__find_loops(Info4, Info5) },
|
|
{ rl_opt_info_get_loops(Loops, Info5, Info) },
|
|
rl_block__dump_loops(Debug, Loops).
|
|
|
|
% Separate out the instructions into blocks.
|
|
:- pred rl_block__build_maps(module_info::in, rl_proc::in,
|
|
rl_opt_info::out) is det.
|
|
|
|
rl_block__build_maps(ModuleInfo, Proc, Info) :-
|
|
Proc = rl_proc(_, Inputs, Outputs, Memoed, RelInfo, Instrs, _),
|
|
rl_opt_info_init(ModuleInfo, RelInfo, Inputs, Outputs, Memoed,
|
|
Info0, FirstBlockId),
|
|
|
|
% Some analyses require that the first block not be branched
|
|
% to from anywhere, so we add an empty one here.
|
|
block_info_init(BlockInfo),
|
|
rl_opt_info_add_block(FirstBlockId, block(no, [], no, BlockInfo),
|
|
Info0, Info1),
|
|
rl_opt_info_get_next_block_id(BlockId, Info1, Info2),
|
|
rl_opt_info_add_flow_graph_arc(FirstBlockId, BlockId, Info2, Info3),
|
|
rl_block__build_maps_2([], Instrs, BlockId, no, Info3, Info).
|
|
|
|
:- pred rl_block__build_maps_2(list(rl_instruction)::in,
|
|
list(rl_instruction)::in, block_id::in, maybe(label_id)::in,
|
|
rl_opt_info::in, rl_opt_info::out) is det.
|
|
|
|
rl_block__build_maps_2(RevBlockInstrs, [], BlockId, MaybeLabel) -->
|
|
% Some analyses, e.g. liveness, require that the last block
|
|
% only falls through to the end of the procedure, so we add an
|
|
% extra one even if there are no instructions.
|
|
{ list__reverse(RevBlockInstrs, BlockInstrs) },
|
|
{ block_info_init(BlockInfo) },
|
|
{ Block = block(MaybeLabel, BlockInstrs, no, BlockInfo) },
|
|
rl_opt_info_add_block(BlockId, Block),
|
|
rl_opt_info_set_last_block_id(BlockId).
|
|
|
|
rl_block__build_maps_2(RevBlockInstrs0, [Instr | Instrs],
|
|
BlockId, MaybeLabel0) -->
|
|
( { Instr = label(Label) - _ } ->
|
|
% Assign a new block_id for the label.
|
|
rl_opt_info_add_label(Label, LabelBlockId),
|
|
rl_opt_info_add_flow_graph_arc(BlockId, LabelBlockId),
|
|
{ list__reverse(RevBlockInstrs0, BlockInstrs) },
|
|
{ block_info_init(BlockInfo) },
|
|
{ Block = block(MaybeLabel0, BlockInstrs, no, BlockInfo) },
|
|
rl_opt_info_add_block(BlockId, Block),
|
|
rl_block__build_maps_2([], Instrs, LabelBlockId, yes(Label))
|
|
; { Instr = conditional_goto(_, Label) - _ } ->
|
|
rl_opt_info_add_label(Label, LabelBlockId),
|
|
rl_opt_info_add_flow_graph_arc(BlockId, LabelBlockId),
|
|
|
|
rl_opt_info_get_next_block_id(NextBlockId),
|
|
rl_opt_info_add_flow_graph_arc(BlockId, NextBlockId),
|
|
|
|
{ list__reverse(RevBlockInstrs0, BlockInstrs) },
|
|
{ block_info_init(BlockInfo) },
|
|
{ Block = block(MaybeLabel0, BlockInstrs,
|
|
yes(Instr), BlockInfo) },
|
|
rl_opt_info_add_block(BlockId, Block),
|
|
|
|
rl_block__build_maps_2([], Instrs, NextBlockId, no)
|
|
; { Instr = goto(Label) - _ } ->
|
|
rl_opt_info_add_label(Label, LabelBlockId),
|
|
rl_opt_info_add_flow_graph_arc(BlockId, LabelBlockId),
|
|
|
|
{ list__reverse(RevBlockInstrs0, BlockInstrs) },
|
|
{ block_info_init(BlockInfo) },
|
|
{ Block = block(MaybeLabel0, BlockInstrs,
|
|
yes(Instr), BlockInfo) },
|
|
rl_opt_info_add_block(BlockId, Block),
|
|
|
|
% Avoid creating a dead block in between the
|
|
% goto and the next label.
|
|
( { rl_block__get_next_label(NextLabel, Instrs, Instrs1) } ->
|
|
rl_opt_info_add_label(NextLabel, NextLabelBlockId),
|
|
rl_block__build_maps_2([], Instrs1,
|
|
NextLabelBlockId, yes(NextLabel))
|
|
;
|
|
% There must always be a way to get to the end
|
|
% of the procedure.
|
|
{ error("rl_block__build_maps - goto not followed by a label") }
|
|
)
|
|
; { Instr = comment - _ } ->
|
|
% Strip comments, since they are likely to be fairly
|
|
% meaningless after optimization.
|
|
rl_block__build_maps_2(RevBlockInstrs0,
|
|
Instrs, BlockId, MaybeLabel0)
|
|
;
|
|
rl_block__build_maps_2([Instr | RevBlockInstrs0],
|
|
Instrs, BlockId, MaybeLabel0)
|
|
).
|
|
|
|
% Find the next label after an unconditional goto, removing
|
|
% any instructions in between since they are dead code.
|
|
:- pred rl_block__get_next_label(label_id::out, list(rl_instruction)::in,
|
|
list(rl_instruction)::out) is semidet.
|
|
|
|
rl_block__get_next_label(NextLabel, [Instr | Instrs0], Instrs1) :-
|
|
( Instr = label(NextLabel0) - _ ->
|
|
NextLabel = NextLabel0,
|
|
Instrs1 = Instrs0
|
|
;
|
|
rl_block__get_next_label(NextLabel, Instrs0, Instrs1)
|
|
).
|
|
|
|
%-----------------------------------------------------------------------------%
|
|
%-----------------------------------------------------------------------------%
|
|
|
|
% See dragon book p. 670.
|
|
% A node in the flow graph dominates another node if all paths to
|
|
% the second node from the initial node pass through the first.
|
|
:- pred rl_block__get_dominator_info(rl_opt_info::in, rl_opt_info::out) is det.
|
|
|
|
rl_block__get_dominator_info -->
|
|
rl_opt_info_get_flow_graph(FlowGraph),
|
|
{ relation__domain(FlowGraph, Nodes) },
|
|
{ set__delete(Nodes, 0, NonInitialNodes) },
|
|
{ set__to_sorted_list(NonInitialNodes, NonInitialNodeList) },
|
|
{ map__init(Dominators0) },
|
|
|
|
% The initial node dominates itself.
|
|
rl_opt_info_get_first_block_id(FirstBlockId),
|
|
{ set__singleton_set(InitialNodeDominators, FirstBlockId) },
|
|
{ set_dominating_nodes(Dominators0, FirstBlockId,
|
|
InitialNodeDominators, Dominators1) },
|
|
|
|
% Initially, all non-initial nodes dominate all other
|
|
% non-initial nodes.
|
|
{ Initialise =
|
|
lambda([Node::in, Dom0::in, Dom::out] is det, (
|
|
set_dominating_nodes(Dom0, Node, NonInitialNodes, Dom)
|
|
)) },
|
|
{ list__foldl(Initialise, NonInitialNodeList,
|
|
Dominators1, Dominators2) },
|
|
|
|
{ SinglePass =
|
|
lambda([Dom0::in, Dom::out, Changed::out] is det, (
|
|
list__foldl(rl_block__get_dominator_info_single_pass(FlowGraph),
|
|
NonInitialNodeList, Dom0 - no, Dom - Changed)
|
|
)) },
|
|
{ compute_to_fixpoint(SinglePass, Dominators2, Dominators) },
|
|
rl_opt_info_set_dominator_info(Dominators).
|
|
|
|
:- pred rl_block__get_dominator_info_single_pass(flow_graph::in,
|
|
block_id::in, pair(dominator_info, bool)::in,
|
|
pair(dominator_info, bool)::out) is det.
|
|
|
|
rl_block__get_dominator_info_single_pass(FlowGraph, Node,
|
|
Dominators0 - Changed0, Dominators - Changed) :-
|
|
relation__lookup_element(FlowGraph, Node, NodeKey),
|
|
relation__lookup_to(FlowGraph, NodeKey, Predecessors0),
|
|
set__to_sorted_list(Predecessors0, Predecessors),
|
|
lookup_dominating_nodes(Dominators0, Node, Value0),
|
|
(
|
|
Predecessors = [PredKey | PredKeys],
|
|
relation__lookup_key(FlowGraph, PredKey, Pred),
|
|
lookup_dominating_nodes(Dominators0, Pred,
|
|
DomByPredecessors0),
|
|
IntersectPredecessors =
|
|
lambda([PredecessorKey::in, Inter0::in,
|
|
Inter::out] is det, (
|
|
relation__lookup_key(FlowGraph, PredecessorKey,
|
|
Predecessor),
|
|
lookup_dominating_nodes(Dominators0, Predecessor,
|
|
PredecessorDom),
|
|
set__intersect(Inter0, PredecessorDom, Inter)
|
|
)),
|
|
list__foldl(IntersectPredecessors, PredKeys,
|
|
DomByPredecessors0, DomByPredecessors),
|
|
set__insert(DomByPredecessors, Node, NewValue)
|
|
;
|
|
Predecessors = [],
|
|
set__singleton_set(NewValue, Node)
|
|
),
|
|
set__difference(Value0, NewValue, Diff),
|
|
( set__empty(Diff) ->
|
|
Changed = Changed0
|
|
;
|
|
Changed = yes
|
|
),
|
|
set_dominating_nodes(Dominators0, Node, NewValue, Dominators).
|
|
|
|
%-----------------------------------------------------------------------------%
|
|
|
|
% Find the back edges in the flow graph, then find the loop for
|
|
% each back edge.
|
|
:- pred rl_block__find_loops(rl_opt_info::in, rl_opt_info::out) is det.
|
|
|
|
rl_block__find_loops -->
|
|
rl_opt_info_get_flow_graph(FlowGraph),
|
|
rl_opt_info_get_dominator_info(DominatorInfo),
|
|
{ relation__to_key_assoc_list(FlowGraph, FlowAssocList) },
|
|
% If the edge is a back edge, find the loop that it closes,
|
|
% otherwise fail.
|
|
{ BackEdgeToLoop =
|
|
lambda([GraphEdge::in, Loop::out] is semidet, (
|
|
GraphEdge = CallingKey - CalledKey,
|
|
relation__lookup_key(FlowGraph, CallingKey, CallingNode),
|
|
relation__lookup_key(FlowGraph, CalledKey, CalledNode),
|
|
lookup_dominating_nodes(DominatorInfo, CallingNode,
|
|
CallingNodeDominators),
|
|
set__member(CalledNode, CallingNodeDominators),
|
|
( CallingNode = CalledNode ->
|
|
set__singleton_set(LoopNodes, CallingNode)
|
|
;
|
|
set__list_to_set([CallingNode, CalledNode],
|
|
LoopNodes0),
|
|
queue__init(NodesToProcess0),
|
|
queue__put(NodesToProcess0, CallingNode,
|
|
NodesToProcess1),
|
|
rl_block__get_loop(FlowGraph, DominatorInfo,
|
|
NodesToProcess1, LoopNodes0, LoopNodes)
|
|
),
|
|
Loop = loop(CalledNode, LoopNodes)
|
|
)) },
|
|
{ list__filter_map(BackEdgeToLoop, FlowAssocList, Loops) },
|
|
rl_opt_info_set_loops(Loops).
|
|
|
|
:- pred rl_block__get_loop(flow_graph::in, dominator_info::in,
|
|
queue(block_id)::in, set(block_id)::in, set(block_id)::out) is det.
|
|
|
|
rl_block__get_loop(FlowGraph, DominatorInfo, NodeQueue0,
|
|
LoopNodes0, LoopNodes) :-
|
|
( queue__get(NodeQueue0, Node, NodeQueue1) ->
|
|
relation__lookup_element(FlowGraph, Node, NodeKey),
|
|
relation__lookup_to(FlowGraph, NodeKey, Predecessors),
|
|
set__to_sorted_list(Predecessors, PredecessorList),
|
|
HandlePredecessor =
|
|
lambda([PredecessorKey::in, Info0::in,
|
|
Info::out] is det, (
|
|
Info0 = Nodes0 - Queue0,
|
|
relation__lookup_key(FlowGraph, PredecessorKey,
|
|
Predecessor),
|
|
( set__member(Predecessor, Nodes0) ->
|
|
Nodes = Nodes0,
|
|
Queue = Queue0
|
|
;
|
|
set__insert(Nodes0, Predecessor, Nodes),
|
|
queue__put(Queue0, Predecessor, Queue)
|
|
),
|
|
Info = Nodes - Queue
|
|
)),
|
|
list__foldl(HandlePredecessor, PredecessorList,
|
|
LoopNodes0 - NodeQueue1, LoopNodes1 - NodeQueue2),
|
|
rl_block__get_loop(FlowGraph, DominatorInfo, NodeQueue2,
|
|
LoopNodes1, LoopNodes)
|
|
;
|
|
LoopNodes = LoopNodes0
|
|
).
|
|
|
|
%-----------------------------------------------------------------------------%
|
|
|
|
:- pred compute_to_fixpoint(pred(T, T, bool), T, T).
|
|
:- mode compute_to_fixpoint(pred(in, out, out) is det, in, out) is det.
|
|
|
|
compute_to_fixpoint(Pred, T0, T) :-
|
|
call(Pred, T0, T1, Changed),
|
|
( Changed = yes ->
|
|
compute_to_fixpoint(Pred, T1, T)
|
|
;
|
|
T = T1
|
|
).
|
|
|
|
%-----------------------------------------------------------------------------%
|
|
|
|
rl_block__get_nonlocal_relations(NonLocals) -->
|
|
rl_opt_info_get_rev_block_order(Blocks),
|
|
{ set__init(SingleBlockRels0) },
|
|
rl_opt_info_get_input_relations(InputRels),
|
|
rl_opt_info_get_output_relations(OutputRels),
|
|
rl_opt_info_get_memoed_relations(MemoedRels),
|
|
{ set__insert_list(MemoedRels, InputRels, NonLocals0) },
|
|
{ set__insert_list(NonLocals0, OutputRels, NonLocals1) },
|
|
list__foldl2(rl_block__update_nonlocal_relations, Blocks,
|
|
SingleBlockRels0 - NonLocals1, _ - NonLocals).
|
|
|
|
:- pred rl_block__update_nonlocal_relations(block_id::in,
|
|
pair(set(relation_id))::in, pair(set(relation_id))::out,
|
|
rl_opt_info::in, rl_opt_info::out) is det.
|
|
|
|
rl_block__update_nonlocal_relations(BlockId, Single0 - Multi0, Single - Multi)
|
|
-->
|
|
rl_opt_info_get_block(BlockId, Block),
|
|
{ Block = block(_, Instrs, MaybeBranch, _) },
|
|
{ AddInstrRels =
|
|
lambda([Instr::in, Rels0::in, Rels::out] is det, (
|
|
rl__instr_relations(Instr, Inputs, Outputs),
|
|
set__insert_list(Rels0, Inputs, Rels1),
|
|
set__insert_list(Rels1, Outputs, Rels)
|
|
)) },
|
|
{ set__init(BlockRels0) },
|
|
{ list__foldl(AddInstrRels, Instrs, BlockRels0, BlockRels1) },
|
|
{ MaybeBranch = yes(Branch) ->
|
|
call(AddInstrRels, Branch, BlockRels1, BlockRels)
|
|
;
|
|
BlockRels = BlockRels1
|
|
},
|
|
{ set__intersect(Single0, BlockRels, NewMulti) },
|
|
{ set__difference(BlockRels, Single0, NewSingle0) },
|
|
{ set__difference(NewSingle0, Multi0, NewSingle) },
|
|
{ set__union(Single0, NewSingle, Single) },
|
|
{ set__union(Multi0, NewMulti, Multi) }.
|
|
|
|
%-----------------------------------------------------------------------------%
|
|
%-----------------------------------------------------------------------------%
|
|
|
|
:- interface.
|
|
|
|
:- type rl_opt_info.
|
|
|
|
:- type block_id == int.
|
|
|
|
:- type block
|
|
---> block(
|
|
maybe(label_id), % label starting the block
|
|
list(rl_instruction),
|
|
maybe(rl_instruction), % branch instruction ending the block.
|
|
block_info
|
|
).
|
|
|
|
:- type block_info
|
|
---> block_info(
|
|
set(relation_id), % relations live on entry
|
|
set(relation_id) % relations live on exit
|
|
).
|
|
|
|
:- type block_map == map(block_id, block).
|
|
:- type label_map == map(label_id, block_id).
|
|
|
|
:- type flow_graph == relation(block_id).
|
|
|
|
% Nodes which dominate a given node. A node dominates another
|
|
% node if all paths to the second node from the initial node
|
|
% pass through the first.
|
|
:- type dominator_info == map(block_id, set(block_id)).
|
|
|
|
:- type loop
|
|
---> loop(
|
|
block_id, % entry block
|
|
set(block_id) % all blocks
|
|
).
|
|
|
|
%-----------------------------------------------------------------------------%
|
|
|
|
:- pred rl_opt_info_get_next_block_id_no_update(block_id::out,
|
|
rl_opt_info::in, rl_opt_info::out) is det.
|
|
:- pred rl_opt_info_get_relation_info_map(relation_info_map::out,
|
|
rl_opt_info::in, rl_opt_info::out) is det.
|
|
:- pred rl_opt_info_get_highest_label_id(label_id::out,
|
|
rl_opt_info::in, rl_opt_info::out) is det.
|
|
:- pred rl_opt_info_get_first_block_id(block_id::out,
|
|
rl_opt_info::in, rl_opt_info::out) is det.
|
|
:- pred rl_opt_info_get_block_map(block_map::out,
|
|
rl_opt_info::in, rl_opt_info::out) is det.
|
|
:- pred rl_opt_info_get_module_info(module_info::out,
|
|
rl_opt_info::in, rl_opt_info::out) is det.
|
|
:- pred rl_opt_info_get_label_map(label_map::out,
|
|
rl_opt_info::in, rl_opt_info::out) is det.
|
|
:- pred rl_opt_info_get_flow_graph(flow_graph::out,
|
|
rl_opt_info::in, rl_opt_info::out) is det.
|
|
:- pred rl_opt_info_get_dominator_info(dominator_info::out,
|
|
rl_opt_info::in, rl_opt_info::out) is det.
|
|
:- pred rl_opt_info_get_loops(list(loop)::out,
|
|
rl_opt_info::in, rl_opt_info::out) is det.
|
|
:- pred rl_opt_info_get_rev_block_order(list(block_id)::out,
|
|
rl_opt_info::in, rl_opt_info::out) is det.
|
|
:- pred rl_opt_info_get_last_block_id(block_id::out,
|
|
rl_opt_info::in, rl_opt_info::out) is det.
|
|
:- pred rl_opt_info_get_input_relations(list(relation_id)::out,
|
|
rl_opt_info::in, rl_opt_info::out) is det.
|
|
:- pred rl_opt_info_get_output_relations(list(relation_id)::out,
|
|
rl_opt_info::in, rl_opt_info::out) is det.
|
|
:- pred rl_opt_info_get_memoed_relations(set(relation_id)::out,
|
|
rl_opt_info::in, rl_opt_info::out) is det.
|
|
:- pred rl_opt_info_get_next_relation_id(relation_id::out,
|
|
rl_opt_info::in, rl_opt_info::out) is det.
|
|
|
|
:- pred rl_opt_info_set_relation_info_map(relation_info_map::in,
|
|
rl_opt_info::in, rl_opt_info::out) is det.
|
|
:- pred rl_opt_info_set_highest_label_id(label_id::in,
|
|
rl_opt_info::in, rl_opt_info::out) is det.
|
|
:- pred rl_opt_info_set_first_block_id(block_id::in,
|
|
rl_opt_info::in, rl_opt_info::out) is det.
|
|
:- pred rl_opt_info_set_block_map(block_map::in,
|
|
rl_opt_info::in, rl_opt_info::out) is det.
|
|
:- pred rl_opt_info_set_module_info(module_info::in,
|
|
rl_opt_info::in, rl_opt_info::out) is det.
|
|
:- pred rl_opt_info_set_label_map(label_map::in,
|
|
rl_opt_info::in, rl_opt_info::out) is det.
|
|
:- pred rl_opt_info_set_flow_graph(flow_graph::in,
|
|
rl_opt_info::in, rl_opt_info::out) is det.
|
|
:- pred rl_opt_info_set_dominator_info(dominator_info::in,
|
|
rl_opt_info::in, rl_opt_info::out) is det.
|
|
:- pred rl_opt_info_set_loops(list(loop)::in,
|
|
rl_opt_info::in, rl_opt_info::out) is det.
|
|
:- pred rl_opt_info_set_rev_block_order(list(block_id)::in,
|
|
rl_opt_info::in, rl_opt_info::out) is det.
|
|
:- pred rl_opt_info_set_last_block_id(block_id::in,
|
|
rl_opt_info::in, rl_opt_info::out) is det.
|
|
:- pred rl_opt_info_set_input_relations(list(relation_id)::in,
|
|
rl_opt_info::in, rl_opt_info::out) is det.
|
|
:- pred rl_opt_info_set_output_relations(list(relation_id)::in,
|
|
rl_opt_info::in, rl_opt_info::out) is det.
|
|
:- pred rl_opt_info_set_memoed_relations(set(relation_id)::in,
|
|
rl_opt_info::in, rl_opt_info::out) is det.
|
|
:- pred rl_opt_info_set_next_relation_id(relation_id::in,
|
|
rl_opt_info::in, rl_opt_info::out) is det.
|
|
|
|
:- pred rl_opt_info_get_block(block_id::in, block::out,
|
|
rl_opt_info::in, rl_opt_info::out) is det.
|
|
|
|
:- pred rl_opt_info_set_block(block_id::in, block::in,
|
|
rl_opt_info::in, rl_opt_info::out) is det.
|
|
|
|
:- pred rl_opt_info_get_new_label(label_id::out, block_id::out,
|
|
rl_opt_info::in, rl_opt_info::out) is det.
|
|
|
|
:- pred rl_opt_info_add_flow_graph_arc(block_id::in, block_id::in,
|
|
rl_opt_info::in, rl_opt_info::out) is det.
|
|
|
|
:- pred rl_opt_info_add_block(block_id::in, block::in,
|
|
rl_opt_info::in, rl_opt_info::out) is det.
|
|
|
|
:- pred rl_opt_info_get_relation_info(relation_id::in, relation_info::out,
|
|
rl_opt_info::in, rl_opt_info::out) is det.
|
|
|
|
:- pred rl_opt_info_set_relation_info(relation_id::in, relation_info::in,
|
|
rl_opt_info::in, rl_opt_info::out) is det.
|
|
|
|
:- pred rl_opt_info_add_relation(list(type)::in,
|
|
relation_id::out, rl_opt_info::in, rl_opt_info::out) is det.
|
|
|
|
:- pred block_info_init(block_info::out) is det.
|
|
|
|
%-----------------------------------------------------------------------------%
|
|
|
|
:- implementation.
|
|
|
|
% Information about a procedure to be optimized.
|
|
:- type rl_opt_info
|
|
---> rl_opt_info(
|
|
block_id, % next block id
|
|
relation_info_map,
|
|
label_id, % next label_id
|
|
block_id, % first block_id
|
|
block_map,
|
|
module_info,
|
|
label_map,
|
|
flow_graph,
|
|
dominator_info,
|
|
list(loop),
|
|
list(block_id), % blocks in
|
|
% reverse order
|
|
block_id, % last block_id
|
|
list(relation_id), % inputs
|
|
list(relation_id), % outputs
|
|
set(relation_id), % memoed relations
|
|
relation_id, % next relation_id
|
|
unit
|
|
).
|
|
|
|
rl_opt_info_get_next_block_id_no_update(A, Info, Info) :-
|
|
Info = rl_opt_info(A,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_).
|
|
rl_opt_info_get_relation_info_map(B, Info, Info) :-
|
|
Info = rl_opt_info(_,B,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_).
|
|
rl_opt_info_get_highest_label_id(C, Info, Info) :-
|
|
Info = rl_opt_info(_,_,C,_,_,_,_,_,_,_,_,_,_,_,_,_,_).
|
|
rl_opt_info_get_first_block_id(D, Info, Info) :-
|
|
Info = rl_opt_info(_,_,_,D,_,_,_,_,_,_,_,_,_,_,_,_,_).
|
|
rl_opt_info_get_block_map(E, Info, Info) :-
|
|
Info = rl_opt_info(_,_,_,_,E,_,_,_,_,_,_,_,_,_,_,_,_).
|
|
rl_opt_info_get_module_info(F, Info, Info) :-
|
|
Info = rl_opt_info(_,_,_,_,_,F,_,_,_,_,_,_,_,_,_,_,_).
|
|
rl_opt_info_get_label_map(G, Info, Info) :-
|
|
Info = rl_opt_info(_,_,_,_,_,_,G,_,_,_,_,_,_,_,_,_,_).
|
|
rl_opt_info_get_flow_graph(H, Info, Info) :-
|
|
Info = rl_opt_info(_,_,_,_,_,_,_,H,_,_,_,_,_,_,_,_,_).
|
|
rl_opt_info_get_dominator_info(I, Info, Info) :-
|
|
Info = rl_opt_info(_,_,_,_,_,_,_,_,I,_,_,_,_,_,_,_,_).
|
|
rl_opt_info_get_loops(J, Info, Info) :-
|
|
Info = rl_opt_info(_,_,_,_,_,_,_,_,_,J,_,_,_,_,_,_,_).
|
|
rl_opt_info_get_rev_block_order(K, Info, Info) :-
|
|
Info = rl_opt_info(_,_,_,_,_,_,_,_,_,_,K,_,_,_,_,_,_).
|
|
rl_opt_info_get_last_block_id(L, Info, Info) :-
|
|
Info = rl_opt_info(_,_,_,_,_,_,_,_,_,_,_,L,_,_,_,_,_).
|
|
rl_opt_info_get_input_relations(M, Info, Info) :-
|
|
Info = rl_opt_info(_,_,_,_,_,_,_,_,_,_,_,_,M,_,_,_,_).
|
|
rl_opt_info_get_output_relations(N, Info, Info) :-
|
|
Info = rl_opt_info(_,_,_,_,_,_,_,_,_,_,_,_,_,N,_,_,_).
|
|
rl_opt_info_get_memoed_relations(O, Info, Info) :-
|
|
Info = rl_opt_info(_,_,_,_,_,_,_,_,_,_,_,_,_,_,O,_,_).
|
|
rl_opt_info_get_next_relation_id(P, Info, Info) :-
|
|
Info = rl_opt_info(_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,P,_).
|
|
|
|
rl_opt_info_set_relation_info_map(B, Info0, Info) :-
|
|
Info0 = rl_opt_info(A,_,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q),
|
|
Info = rl_opt_info(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q).
|
|
rl_opt_info_set_highest_label_id(C, Info0, Info) :-
|
|
Info0 = rl_opt_info(A,B,_,D,E,F,G,H,I,J,K,L,M,N,O,P,Q),
|
|
Info = rl_opt_info(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q).
|
|
rl_opt_info_set_first_block_id(D, Info0, Info) :-
|
|
Info0 = rl_opt_info(A,B,C,_,E,F,G,H,I,J,K,L,M,N,O,P,Q),
|
|
Info = rl_opt_info(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q).
|
|
rl_opt_info_set_block_map(E, Info0, Info) :-
|
|
Info0 = rl_opt_info(A,B,C,D,_,F,G,H,I,J,K,L,M,N,O,P,Q),
|
|
Info = rl_opt_info(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q).
|
|
rl_opt_info_set_module_info(F, Info0, Info) :-
|
|
Info0 = rl_opt_info(A,B,C,D,E,_,G,H,I,J,K,L,M,N,O,P,Q),
|
|
Info = rl_opt_info(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q).
|
|
rl_opt_info_set_label_map(G, Info0, Info) :-
|
|
Info0 = rl_opt_info(A,B,C,D,E,F,_,H,I,J,K,L,M,N,O,P,Q),
|
|
Info = rl_opt_info(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q).
|
|
rl_opt_info_set_flow_graph(H, Info0, Info) :-
|
|
Info0 = rl_opt_info(A,B,C,D,E,F,G,_,I,J,K,L,M,N,O,P,Q),
|
|
Info = rl_opt_info(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q).
|
|
rl_opt_info_set_dominator_info(I, Info0, Info) :-
|
|
Info0 = rl_opt_info(A,B,C,D,E,F,G,H,_,J,K,L,M,N,O,P,Q),
|
|
Info = rl_opt_info(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q).
|
|
rl_opt_info_set_loops(J, Info0, Info) :-
|
|
Info0 = rl_opt_info(A,B,C,D,E,F,G,H,I,_,K,L,M,N,O,P,Q),
|
|
Info = rl_opt_info(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q).
|
|
rl_opt_info_set_rev_block_order(K, Info0, Info) :-
|
|
Info0 = rl_opt_info(A,B,C,D,E,F,G,H,I,J,_,L,M,N,O,P,Q),
|
|
Info = rl_opt_info(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q).
|
|
rl_opt_info_set_last_block_id(L, Info0, Info) :-
|
|
Info0 = rl_opt_info(A,B,C,D,E,F,G,H,I,J,K,_,M,N,O,P,Q),
|
|
Info = rl_opt_info(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q).
|
|
rl_opt_info_set_input_relations(M, Info0, Info) :-
|
|
Info0 = rl_opt_info(A,B,C,D,E,F,G,H,I,J,K,L,_,N,O,P,Q),
|
|
Info = rl_opt_info(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q).
|
|
rl_opt_info_set_output_relations(N, Info0, Info) :-
|
|
Info0 = rl_opt_info(A,B,C,D,E,F,G,H,I,J,K,L,M,_,O,P,Q),
|
|
Info = rl_opt_info(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q).
|
|
rl_opt_info_set_memoed_relations(O, Info0, Info) :-
|
|
Info0 = rl_opt_info(A,B,C,D,E,F,G,H,I,J,K,L,M,N,_,P,Q),
|
|
Info = rl_opt_info(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q).
|
|
rl_opt_info_set_next_relation_id(P, Info0, Info) :-
|
|
Info0 = rl_opt_info(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,_,Q),
|
|
Info = rl_opt_info(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q).
|
|
|
|
%-----------------------------------------------------------------------------%
|
|
|
|
:- pred rl_opt_info_init(module_info::in, relation_info_map::in,
|
|
list(relation_id)::in, list(relation_id)::in,
|
|
set(relation_id)::in, rl_opt_info::out, block_id::out) is det.
|
|
|
|
rl_opt_info_init(ModuleInfo, RelationInfoMap, Inputs, Outputs,
|
|
MemoedRels, Info, FirstBlockId) :-
|
|
map__init(BlockMap0),
|
|
map__init(LabelMap0),
|
|
map__init(DominatorInfo0),
|
|
relation__init(FlowGraph0),
|
|
FirstBlockId = 0,
|
|
|
|
map__keys(RelationInfoMap, RelationIds),
|
|
( list__last(RelationIds, HighestRelationId) ->
|
|
NextRelationId is HighestRelationId + 1
|
|
;
|
|
NextRelationId = 0
|
|
),
|
|
|
|
Info = rl_opt_info(FirstBlockId, RelationInfoMap, 0, 0, BlockMap0,
|
|
ModuleInfo, LabelMap0, FlowGraph0, DominatorInfo0, [], [], 0,
|
|
Inputs, Outputs, MemoedRels, NextRelationId, unit).
|
|
|
|
:- pred rl_opt_info_get_next_block_id(block_id::out,
|
|
rl_opt_info::in, rl_opt_info::out) is det.
|
|
|
|
rl_opt_info_get_next_block_id(BlockId1, Info0, Info) :-
|
|
Info0 = rl_opt_info(BlockId,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q),
|
|
BlockId1 is BlockId + 1,
|
|
Info = rl_opt_info(BlockId1,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q).
|
|
|
|
%-----------------------------------------------------------------------------%
|
|
|
|
:- pred lookup_dominating_nodes(dominator_info::in, block_id::in,
|
|
set(block_id)::out) is det.
|
|
|
|
lookup_dominating_nodes(Dominators, BlockId, Nodes) :-
|
|
( map__search(Dominators, BlockId, Nodes1) ->
|
|
Nodes = Nodes1
|
|
;
|
|
set__init(Nodes)
|
|
).
|
|
|
|
:- pred set_dominating_nodes(dominator_info::in, block_id::in,
|
|
set(block_id)::in, dominator_info::out) is det.
|
|
|
|
set_dominating_nodes(Dominators0, BlockId, Nodes, Dominators) :-
|
|
map__set(Dominators0, BlockId, Nodes, Dominators).
|
|
|
|
%-----------------------------------------------------------------------------%
|
|
|
|
:- pred rl_opt_info_add_label(label_id::in, block_id::out,
|
|
rl_opt_info::in, rl_opt_info::out) is det.
|
|
|
|
rl_opt_info_add_label(LabelId, LabelBlockId) -->
|
|
rl_opt_info_get_label_map(LabelMap0),
|
|
( { map__search(LabelMap0, LabelId, LabelBlockId1) } ->
|
|
{ LabelBlockId = LabelBlockId1 }
|
|
;
|
|
rl_opt_info_get_next_block_id(LabelBlockId),
|
|
{ map__det_insert(LabelMap0, LabelId,
|
|
LabelBlockId, LabelMap) },
|
|
rl_opt_info_set_label_map(LabelMap)
|
|
),
|
|
rl_opt_info_get_highest_label_id(TopLabelId0),
|
|
( { LabelId > TopLabelId0 } ->
|
|
rl_opt_info_set_highest_label_id(LabelId)
|
|
;
|
|
[]
|
|
).
|
|
|
|
%-----------------------------------------------------------------------------%
|
|
|
|
rl_opt_info_get_block(BlockId, Block) -->
|
|
rl_opt_info_get_block_map(BlockMap),
|
|
{ map__lookup(BlockMap, BlockId, Block) }.
|
|
|
|
rl_opt_info_set_block(BlockId, Block) -->
|
|
rl_opt_info_get_block_map(BlockMap0),
|
|
{ map__set(BlockMap0, BlockId, Block, BlockMap) },
|
|
rl_opt_info_set_block_map(BlockMap).
|
|
|
|
%-----------------------------------------------------------------------------%
|
|
|
|
rl_opt_info_get_new_label(Label, Block) -->
|
|
rl_opt_info_get_next_block_id(Block),
|
|
rl_opt_info_get_highest_label_id(Label0),
|
|
{ Label is Label0 + 1 },
|
|
rl_opt_info_set_highest_label_id(Label).
|
|
|
|
%-----------------------------------------------------------------------------%
|
|
|
|
rl_opt_info_get_relation_info(RelationId, RelationInfo) -->
|
|
rl_opt_info_get_relation_info_map(RelMap0),
|
|
{ map__lookup(RelMap0, RelationId, RelationInfo) }.
|
|
|
|
rl_opt_info_set_relation_info(RelationId, RelationInfo) -->
|
|
rl_opt_info_get_relation_info_map(RelMap0),
|
|
{ map__set(RelMap0, RelationId, RelationInfo, RelMap) },
|
|
rl_opt_info_set_relation_info_map(RelMap).
|
|
|
|
rl_opt_info_add_relation(Schema, RelationId) -->
|
|
rl_opt_info_get_next_relation_id(RelationId),
|
|
{ NextRelationId is RelationId + 1 },
|
|
rl_opt_info_set_next_relation_id(NextRelationId),
|
|
{ rl__relation_id_to_string(RelationId, RelName) },
|
|
rl_opt_info_get_module_info(ModuleInfo),
|
|
{ rl__default_temporary_state(ModuleInfo, State) },
|
|
{ RelationInfo = relation_info(temporary(State),
|
|
Schema, [], RelName) },
|
|
rl_opt_info_get_relation_info_map(RelMap0),
|
|
{ map__det_insert(RelMap0, RelationId, RelationInfo, RelMap) },
|
|
rl_opt_info_set_relation_info_map(RelMap).
|
|
|
|
%-----------------------------------------------------------------------------%
|
|
|
|
rl_opt_info_add_flow_graph_arc(CallingBlock, CalledBlock) -->
|
|
rl_opt_info_get_flow_graph(FlowGraph0),
|
|
{ relation__add_element(FlowGraph0, CallingBlock,
|
|
CallingBlockKey, FlowGraph1) },
|
|
{ relation__add_element(FlowGraph1, CalledBlock,
|
|
CalledBlockKey, FlowGraph2) },
|
|
{ relation__add(FlowGraph2, CallingBlockKey,
|
|
CalledBlockKey, FlowGraph) },
|
|
rl_opt_info_set_flow_graph(FlowGraph).
|
|
|
|
%-----------------------------------------------------------------------------%
|
|
|
|
rl_opt_info_add_block(BlockId, Block) -->
|
|
rl_opt_info_get_block_map(BlockMap0),
|
|
{ map__det_insert(BlockMap0, BlockId, Block, BlockMap) },
|
|
rl_opt_info_set_block_map(BlockMap),
|
|
rl_opt_info_get_rev_block_order(BlockOrder0),
|
|
rl_opt_info_set_rev_block_order([BlockId | BlockOrder0]).
|
|
|
|
%-----------------------------------------------------------------------------%
|
|
|
|
rl_block__get_proc(Info0, ProcName, MercuryProcs, Proc) :-
|
|
rl_opt_info_get_rev_block_order(RevOrder, Info0, Info1),
|
|
list__reverse(RevOrder, Order),
|
|
rl_opt_info_get_block_map(BlockMap, Info1, Info2),
|
|
GetInstrs =
|
|
lambda([BlockId::in, Instrs::out] is det, (
|
|
map__lookup(BlockMap, BlockId,
|
|
block(MaybeLabel, Instrs0, MaybeBranch, _)),
|
|
( MaybeBranch = yes(Branch) ->
|
|
list__append(Instrs0, [Branch], Instrs1)
|
|
;
|
|
Instrs1 = Instrs0
|
|
),
|
|
( MaybeLabel = yes(Label) ->
|
|
Instrs = [label(Label) - "" | Instrs1]
|
|
;
|
|
Instrs = Instrs1
|
|
)
|
|
)),
|
|
list__map(GetInstrs, Order, InstrLists),
|
|
list__condense(InstrLists, Instructions),
|
|
rl_opt_info_get_input_relations(Inputs, Info2, Info3),
|
|
rl_opt_info_get_output_relations(Outputs, Info3, Info4),
|
|
rl_opt_info_get_memoed_relations(Memoed, Info4, Info5),
|
|
rl_opt_info_get_relation_info_map(RelMap, Info5, _),
|
|
Proc = rl_proc(ProcName, Inputs, Outputs, Memoed,
|
|
RelMap, Instructions, MercuryProcs).
|
|
|
|
%-----------------------------------------------------------------------------%
|
|
|
|
rl_block__dump_blocks(no, Info, Info) --> [].
|
|
rl_block__dump_blocks(yes, Info0, Info) -->
|
|
{ rl_opt_info_get_rev_block_order(RevBlockOrder, Info0, Info1) },
|
|
{ list__reverse(RevBlockOrder, BlockOrder) },
|
|
{ rl_opt_info_get_block_map(BlockMap, Info1, Info2) },
|
|
{ rl_opt_info_get_relation_info_map(RelInfo, Info2, Info3) },
|
|
{ rl_opt_info_get_module_info(ModuleInfo, Info3, Info) },
|
|
list__foldl(rl_block__dump_block(BlockMap, RelInfo, ModuleInfo),
|
|
BlockOrder).
|
|
|
|
:- pred rl_block__dump_block(block_map::in, relation_info_map::in,
|
|
module_info::in, block_id::in, io__state::di, io__state::uo) is det.
|
|
|
|
rl_block__dump_block(BlockMap, RelMap, ModuleInfo, BlockId) -->
|
|
io__format("Block %i:\n", [i(BlockId)]),
|
|
{ map__lookup(BlockMap, BlockId, Block) },
|
|
|
|
{ Block = block(MaybeLabel, Instrs, MaybeBranch, BlockInfo) },
|
|
( { MaybeLabel = yes(Label) } ->
|
|
rl_dump__write_instruction(ModuleInfo,
|
|
RelMap, label(Label) - "")
|
|
;
|
|
[]
|
|
),
|
|
io__write_list(Instrs, "",
|
|
rl_dump__write_instruction(ModuleInfo, RelMap)),
|
|
( { MaybeBranch = yes(Branch) } ->
|
|
rl_dump__write_instruction(ModuleInfo, RelMap, Branch)
|
|
;
|
|
[]
|
|
),
|
|
|
|
{ BlockInfo = block_info(LiveAtStart, LiveAtEnd) },
|
|
io__write_string("Live at start: "),
|
|
io__write(LiveAtStart),
|
|
io__nl,
|
|
io__write_string("Live at end: "),
|
|
io__write(LiveAtEnd),
|
|
io__nl,
|
|
io__nl.
|
|
|
|
:- pred rl_block__dump_flow_graph(bool::in, rl_opt_info::in,
|
|
rl_opt_info::out, io__state::di, io__state::uo) is det.
|
|
|
|
rl_block__dump_flow_graph(no, Info, Info) --> [].
|
|
rl_block__dump_flow_graph(yes, Info0, Info) -->
|
|
{ rl_opt_info_get_flow_graph(Graph, Info0, Info1) },
|
|
{ rl_opt_info_get_rev_block_order(RevOrder, Info1, Info) },
|
|
{ list__reverse(RevOrder, Order) },
|
|
io__write_string("Flow graph:\n"),
|
|
list__foldl(rl_block__dump_flow_graph_2(Graph), Order).
|
|
|
|
:- pred rl_block__dump_flow_graph_2(flow_graph::in, block_id::in,
|
|
io__state::di, io__state::uo) is det.
|
|
|
|
rl_block__dump_flow_graph_2(Graph, Block) -->
|
|
{ relation__lookup_element(Graph, Block, BlockKey) },
|
|
{ relation__lookup_from(Graph, BlockKey, CalledKeys0) },
|
|
{ set__to_sorted_list(CalledKeys0, CalledKeys) },
|
|
{ list__map(relation__lookup_key(Graph), CalledKeys, CalledBlocks) },
|
|
io__write_int(Block),
|
|
io__write_string(": "),
|
|
io__write_list(CalledBlocks, ", ", io__write_int),
|
|
io__nl.
|
|
|
|
:- pred rl_block__dump_loops(bool::in, list(loop)::in,
|
|
io__state::di, io__state::uo) is det.
|
|
|
|
rl_block__dump_loops(no, _) --> [].
|
|
rl_block__dump_loops(yes, Loops) -->
|
|
io__write_list(Loops, "\n", rl_block__dump_loop),
|
|
io__nl.
|
|
|
|
:- pred rl_block__dump_loop(loop::in, io__state::di, io__state::uo) is det.
|
|
|
|
rl_block__dump_loop(loop(Entry, Blocks0)) -->
|
|
io__format("Loop entry: %i. Nodes: [", [i(Entry)]),
|
|
{ set__to_sorted_list(Blocks0, Blocks) },
|
|
io__write_list(Blocks, ", ", io__write_int),
|
|
io__write_string("]\n").
|
|
|
|
%-----------------------------------------------------------------------------%
|
|
|
|
block_info_init(block_info(Rels, Rels)) :-
|
|
set__init(Rels).
|
|
|
|
%-----------------------------------------------------------------------------%
|
|
%-----------------------------------------------------------------------------%
|