liveness.inc
来自「OTP是开放电信平台的简称」· INC 代码 · 共 313 行
INC
313 行
%% -*- Erlang -*-%% -*- erlang-indent-level: 2 -*-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% LIVENESS ANALYSIS%%%% Exports:%% ~~~~~~~%% analyze(CFG) - returns a liveness analysis of CFG.%% liveout(Liveness, Label) - returns a set of variables that are live at%% exit from basic block named Label.%% livein(Liveness, Label) - returns a set of variables that are live at%% entry to the basic block named Label.%% livein_from_liveout(Instructions, LiveOut) - Given a list of instructions %% and a liveout-set, returns a set of variables live at the %% first instruction.%%-export([analyze/1, livein/2]).-ifdef(LIVEOUT_NEEDED).-export([liveout/2]).-endif.-ifdef(PRETTY_PRINT).-export([pp/1]).-endif.%%-export([livein_from_liveout/2]).-ifdef(DEBUG_LIVENESS).-export([annotate_liveness/2]).-endif.%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% Interface functions that MUST be implemented in the including file%%%% cfg_bb(CFG, L) -> BasicBlock, extract a basic block from a cfg.%% cfg_postorder(CFG) -> [Labels], the labels of the cfg in postorder%% cfg_succ_map(CFG) -> SuccMap, a successor mapping.%% cfg_succ(CFG, L) -> [Labels], %% uses(Instr) ->%% defines(Instr) ->%%%% Plus the following, if basic block annotations are needed%%%% cfg_labels(CFG) ->%% cfg_bb_add(CFG, L, NewBB) ->%% mk_comment(Text) ->%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% The generic liveness analysis%%-ifdef(HIPE_LIVENESS_CALC_LARGEST_LIVESET).analyze(CFG) -> PO = cfg_postorder(CFG), InitLiveness = liveness_init(init(cfg_labels(CFG), CFG)), _Max = case get(hipe_largest_liveset) of undefined -> put(hipe_largest_liveset,0), 0; LL -> LL end, Res = merry_go_around(PO, InitLiveness,0), case get(hipe_largest_liveset) > _Max of true -> io:format("Largest liveset: ~w \n",[get(hipe_largest_liveset)]); _ -> ok end, Res.-else.analyze(CFG) -> PO = cfg_postorder(CFG), InitLiveness = liveness_init(init(PO, CFG)), Res = merry_go_around(PO, InitLiveness,0), Res.-endif.%%%% The fixpoint iteration%%merry_go_around(Labels, Liveness, Count) -> case doit_once(Labels, Liveness, 0) of {NewLiveness, 0} -> %% io:format("Iterations ~w~n",[Count]), NewLiveness; {NewLiveness, _Changed} -> merry_go_around(Labels, NewLiveness,Count+1) end.%%%% One iteration%%-ifdef(HIPE_LIVENESS_CALC_LARGEST_LIVESET).doit_once([], Liveness, Changed) -> {Liveness, Changed};doit_once([L|Ls], Liveness, Changed) -> LiveOut = liveout(Liveness, L), Kill = ordsets:subtract(LiveOut, kill(L, Liveness)), LiveIn = ordsets:union(Kill, gen(L,Liveness)), {NewLiveness, ChangedP} = update_livein(L, LiveIn, Liveness), Le = length(LiveIn), Max = get(hipe_largest_liveset), if Le > Max -> put(hipe_largest_liveset,Le); true -> true end, doit_once(Ls, NewLiveness, Changed+ChangedP).-else.doit_once([], Liveness, Changed) -> {Liveness, Changed};doit_once([L|Ls], Liveness, Changed) -> LiveOut = liveout(Liveness, L), Kill = ordsets:subtract(LiveOut, kill(L, Liveness)), LiveIn = ordsets:union(Kill, gen(L,Liveness)), {NewLiveness, ChangedP} = update_livein(L, LiveIn, Liveness), doit_once(Ls, NewLiveness, Changed+ChangedP).-endif.%% %%%% %% Given a list of instructions and liveout, calculates livein%% %%%% livein_from_liveout(List, LiveOut) when is_list(List)->%% livein_from_liveout_1(lists:reverse(List), gb_sets:from_list(LiveOut));%% livein_from_liveout(Instr, LiveOut) ->%% livein_from_liveout_1([Instr], gb_sets:from_list(LiveOut)).%% %% livein_from_liveout_1([], LiveOut) ->%% gb_sets:to_list(LiveOut);%% livein_from_liveout_1([I|Is], LiveOut) ->%% Def = defines(I),%% Use = uses(I),%% DefSet = gb_sets:from_list(Def),%% UseSet = gb_sets:from_list(Use),%% LiveIn = gb_sets:union(gb_sets:difference(LiveOut, DefSet), UseSet),%% Le = gb_sets:size(LiveIn),%% Max = get(hipe_largest_liveset),%% if Le > Max -> put(hipe_largest_liveset,Le);%% true -> true%% end,%% livein_from_liveout_1(Is, LiveIn).%%%% updates liveness for a basic block%% - returns: {NewLiveness, ChangedP} %% - ChangedP is 0 if the new LiveIn is equal to the old one%% otherwise it's 1.%%update_livein(Label, NewLiveIn, Liveness) -> {GK, LiveIn, Successors} = liveness_lookup(Label, Liveness), NewLiveness = liveness_update(Label, {GK, NewLiveIn, Successors}, Liveness), if LiveIn =:= NewLiveIn -> {NewLiveness, 0}; true -> {NewLiveness, 1} end.%%%% LiveOut for a block is the union of the successors LiveIn%%liveout(Liveness, L) -> Succ = successors(L, Liveness), case Succ of [] -> % special case if no successors liveout_no_succ(); _ -> liveout1(Succ, Liveness) end.liveout1(Labels, Liveness) -> liveout1(Labels, Liveness, ordsets:new()).liveout1([], _Liveness, Live) -> Live;liveout1([L|Ls], Liveness,Live) -> liveout1(Ls, Liveness, ordsets:union(livein(Liveness, L),Live)).successors(L, Liveness) -> {_GK,_LiveIn, Successors} = liveness_lookup(L, Liveness), Successors.livein(Liveness, L) -> {_GK, LiveIn,_Successors} = liveness_lookup(L, Liveness), LiveIn.kill(L, Liveness) -> {{_Gen,Kill},_LiveIn,_Successors} = liveness_lookup(L, Liveness), Kill.gen(L, Liveness) -> {{Gen,_Kill},_LiveIn,_Successors} = liveness_lookup(L, Liveness), Gen.%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% init returns a list of: {Label, {{Gen, Kill}, LiveIn, Successors}}%% - Label is the name of the basic block.%% - Gen is the set of varables that are used by this block.%% - Kill is the set of varables that are defined by this block.%% - LiveIn is the set of variables that are alive at entry to the%% block (initially empty).%% - Successors is a list of the successors to the block.init([], _) -> [];init([L|Ls], CFG) -> BB = cfg_bb(CFG, L), Code = hipe_bb:code(BB), SuccMap = cfg_succ_map(CFG), Succ = cfg_succ(SuccMap, L), Transfer = make_bb_transfer(Code, Succ), [{L, {Transfer, ordsets:new(), Succ}} | init(Ls, CFG)].make_bb_transfer([], _Succ) -> {ordsets:new(), ordsets:new()}; % {Gen, Kill}make_bb_transfer([I|Is], Succ) -> {Gen, Kill} = make_bb_transfer(Is, Succ), InstrGen = ordsets:from_list(uses(I)), InstrKill = ordsets:from_list(defines(I)), Gen1 = ordsets:subtract(Gen, InstrKill), Gen2 = ordsets:union(Gen1, InstrGen), Kill1 = ordsets:union(Kill, InstrKill), Kill2 = ordsets:subtract(Kill1, InstrGen), {Gen2, Kill2}.%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% Annotate each basic block with liveness info%%-ifdef(DEBUG_LIVENESS).annotate_liveness(CFG, Liveness) -> Labels = cfg_labels(CFG), annotate_liveness_bb(Labels, CFG, Liveness).annotate_liveness_bb([], CFG, _Liveness) -> CFG;annotate_liveness_bb([L|Ls], CFG, Liveness) -> BB = cfg_bb(CFG, L), Code0 = hipe_bb:code(BB), LiveIn = strip(livein(Liveness, L)), LiveOut = strip(liveout(Liveness, L)), Code = [mk_comment({live_in, LiveIn}), mk_comment({live_out, LiveOut}) | Code0], NewBB = hipe_bb:code_update(BB, Code), NewCFG = cfg_bb_add(CFG, L, NewBB), annotate_liveness_bb(Ls, NewCFG, Liveness).strip([]) -> [];strip([{_,Y}|Xs]) -> [Y|strip(Xs)].-endif. % DEBUG_LIVENESS%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%liveness_init(List) -> liveness_init(List, gb_trees:empty()).liveness_init([{Lbl, Data}|Left], Acc) -> liveness_init(Left, gb_trees:insert(Lbl, Data, Acc));liveness_init([], Acc) -> Acc. liveness_lookup(Label, Liveness) -> gb_trees:get(Label, Liveness).liveness_update(Label, Val, Liveness) -> gb_trees:update(Label, Val, Liveness).%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% pp/1 pretty prints liveness information for a CFG%%%%-ifdef(PRETTY_PRINT).pp(Cfg) -> Liveness=analyze(Cfg), Labels=cfg_labels(Cfg), ok=print_blocks(Labels, Liveness, Cfg).print_blocks([Lbl|Rest], Liveness, Cfg) -> io:format("~nLivein:", []), pp_liveness_info(livein(Liveness, Lbl)), io:format("Label ~w:~n" , [Lbl]), pp_block(Lbl, Cfg), io:format("Liveout:", []), pp_liveness_info(liveout(Liveness, Lbl)), print_blocks(Rest, Liveness, Cfg);print_blocks([], _Liveness, _Cfg) -> ok.-endif. % PRETTY_PRINT
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?