mirror of
https://github.com/Mercury-Language/mercury.git
synced 2025-12-14 21:35:49 +00:00
Estimated hours taken: 6 Branches: main This diff changes the LLDS backend to make it easier to read and to maintain, but contains no changes in algorithms whatsoever. compiler/basic_block.m: compiler/dupelim.m: compiler/frameopt.m: compiler/jumpopt.m: compiler/layout_out.m: compiler/livemap.m: compiler/peephole.m: compiler/reassign.m: compiler/rtti_out.m: compiler/use_local_vars.m: Convert these modules to our current coding standards. Use state variable notation when appropriate, reordering arguments as necessary. compiler/llds_out.m: Convert these modules to our current coding standards. Use state variable notation when appropriate, reordering arguments as necessary. Delete predicates which are just specialized forms of foldl, using foldl (or foldl2 etc) directly instead. Factor out some common code. compiler/livemap.m: Convert these modules to our current coding standards. Use state variable notation when appropriate, reordering arguments as necessary. Remove some special case handling that used to be required by the value numbering pass. library/bintree_set.m: Provide a function version of the initialization predicate.
151 lines
4.8 KiB
Mathematica
151 lines
4.8 KiB
Mathematica
%-----------------------------------------------------------------------------%
|
|
% Copyright (C) 1997-2001,2003 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.
|
|
%-----------------------------------------------------------------------------%
|
|
%
|
|
% Main author: zs.
|
|
%
|
|
% This module defines a representation for basic blocks, sequences of
|
|
% instructions with one entry and one exit, and provides predicates
|
|
% that convert a list of instructions into a list of basic blocks
|
|
% and vice versa.
|
|
|
|
%-----------------------------------------------------------------------------%
|
|
|
|
:- module ll_backend__basic_block.
|
|
|
|
:- interface.
|
|
|
|
:- import_module backend_libs__proc_label.
|
|
:- import_module ll_backend__llds.
|
|
|
|
:- import_module list, map, std_util, counter.
|
|
|
|
:- type block_map == map(label, block_info).
|
|
|
|
:- type block_info
|
|
---> block_info(
|
|
label,
|
|
% The label starting the block.
|
|
instruction,
|
|
% The instruction containing the label.
|
|
list(instruction),
|
|
% The code of the block without the initial
|
|
% label.
|
|
list(label),
|
|
% The labels we can jump to
|
|
% (not falling through).
|
|
maybe(label)
|
|
% The label we fall through to
|
|
% (if there is one).
|
|
).
|
|
|
|
:- pred create_basic_blocks(list(instruction)::in, list(instruction)::out,
|
|
proc_label::in, counter::in, counter::out,
|
|
list(label)::out, block_map::out) is det.
|
|
|
|
:- pred flatten_basic_blocks(list(label)::in, block_map::in,
|
|
list(instruction)::out) is det.
|
|
|
|
%-----------------------------------------------------------------------------%
|
|
|
|
:- implementation.
|
|
|
|
:- import_module ll_backend__opt_util.
|
|
:- import_module bool, int, require.
|
|
|
|
create_basic_blocks(Instrs0, Comments, ProcLabel, !C, LabelSeq, BlockMap) :-
|
|
opt_util__get_prologue(Instrs0, LabelInstr, Comments,
|
|
AfterLabelInstrs),
|
|
Instrs1 = [LabelInstr | AfterLabelInstrs],
|
|
build_block_map(Instrs1, LabelSeq, ProcLabel, map__init, BlockMap, !C).
|
|
|
|
% Add labels to the given instruction sequence so that
|
|
% every basic block has labels around it.
|
|
|
|
%-----------------------------------------------------------------------------%
|
|
|
|
:- pred build_block_map(list(instruction)::in, list(label)::out,
|
|
proc_label::in, block_map::in, block_map::out,
|
|
counter::in, counter::out) is det.
|
|
|
|
build_block_map([], [], _, !BlockMap, !C).
|
|
build_block_map([OrigInstr0 | OrigInstrs0], LabelSeq, ProcLabel,
|
|
!BlockMap, !C) :-
|
|
( OrigInstr0 = label(OrigLabel) - _ ->
|
|
Label = OrigLabel,
|
|
LabelInstr = OrigInstr0,
|
|
RestInstrs = OrigInstrs0
|
|
;
|
|
counter__allocate(N, !C),
|
|
Label = local(N, ProcLabel),
|
|
LabelInstr = label(Label) - "",
|
|
RestInstrs = [OrigInstr0 | OrigInstrs0]
|
|
),
|
|
(
|
|
take_until_end_of_block(RestInstrs, BlockInstrs, Instrs1),
|
|
build_block_map(Instrs1, LabelSeq0, ProcLabel, !BlockMap, !C),
|
|
( list__last(BlockInstrs, LastInstr) ->
|
|
LastInstr = LastUinstr - _,
|
|
opt_util__possible_targets(LastUinstr, SideLabels),
|
|
opt_util__can_instr_fall_through(LastUinstr,
|
|
CanFallThrough),
|
|
( CanFallThrough = yes ->
|
|
get_fallthrough_from_seq(LabelSeq0,
|
|
MaybeFallThrough)
|
|
;
|
|
MaybeFallThrough = no
|
|
)
|
|
;
|
|
SideLabels = [],
|
|
get_fallthrough_from_seq(LabelSeq0, MaybeFallThrough)
|
|
),
|
|
BlockInfo = block_info(Label, LabelInstr, BlockInstrs,
|
|
SideLabels, MaybeFallThrough),
|
|
map__det_insert(!.BlockMap, Label, BlockInfo, !:BlockMap),
|
|
LabelSeq = [Label | LabelSeq0]
|
|
).
|
|
|
|
%-----------------------------------------------------------------------------%
|
|
|
|
:- pred take_until_end_of_block(list(instruction)::in,
|
|
list(instruction)::out, list(instruction)::out) is det.
|
|
|
|
take_until_end_of_block([], [], []).
|
|
take_until_end_of_block([Instr0 | Instrs0], BlockInstrs, Rest) :-
|
|
Instr0 = Uinstr0 - _Comment,
|
|
( Uinstr0 = label(_) ->
|
|
BlockInstrs = [],
|
|
Rest = [Instr0 | Instrs0]
|
|
; opt_util__can_instr_branch_away(Uinstr0, yes) ->
|
|
BlockInstrs = [Instr0],
|
|
Rest = Instrs0
|
|
;
|
|
take_until_end_of_block(Instrs0, BlockInstrs1, Rest),
|
|
BlockInstrs = [Instr0 | BlockInstrs1]
|
|
).
|
|
|
|
%-----------------------------------------------------------------------------%
|
|
|
|
:- pred get_fallthrough_from_seq(list(label)::in, maybe(label)::out) is det.
|
|
|
|
get_fallthrough_from_seq(LabelSeq, MaybeFallThrough) :-
|
|
( LabelSeq = [NextLabel | _] ->
|
|
MaybeFallThrough = yes(NextLabel)
|
|
;
|
|
MaybeFallThrough = no
|
|
).
|
|
|
|
%-----------------------------------------------------------------------------%
|
|
|
|
flatten_basic_blocks([], _, []).
|
|
flatten_basic_blocks([Label | Labels], BlockMap, Instrs) :-
|
|
flatten_basic_blocks(Labels, BlockMap, RestInstrs),
|
|
map__lookup(BlockMap, Label, BlockInfo),
|
|
BlockInfo = block_info(_, BlockLabelInstr, BlockInstrs, _, _),
|
|
list__append([BlockLabelInstr | BlockInstrs], RestInstrs, Instrs).
|
|
|
|
%-----------------------------------------------------------------------------%
|
|
%-----------------------------------------------------------------------------%
|