hipe_ssa_liveness.inc
来自「OTP是开放电信平台的简称」· INC 代码 · 共 298 行
INC
298 行
%% -*- Erlang -*-%% -*- erlang-indent-level: 2 -*-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% GENERIC MODULE TO PERFORM LIVENESS ANALYSIS ON SSA FORM%%%% Exports:%% ~~~~~~~%% analyze(CFG) - returns a liveness analysis of CFG.%% liveout(Liveness, Label) - returns the list of variables that are%% live at exit from basic block named Label.%% livein(Liveness, Label) - returns the list of variables that are%% live on entry to the basic block named Label.%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% Uncomment the following if this is ever needed as an independent module%%-ifdef(LIVENESS_NEEDED).-export([ssa_liveness__analyze/1, ssa_liveness__livein/3]).%% ssa_liveness__liveout/2]).-endif.%% -ifdef(DEBUG_LIVENESS).%% -export([pp_liveness/1]).%% -endif.%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% Interface functions that MUST be implemented in the supporting files%%%% In the CFG file:%% ----------------%% - bb(CFG, L) -> BasicBlock, extract a basic block from a cfg.%% - postorder(CFG) -> [Labels], the labels of the cfg in postorder%% - succ_map(CFG) -> SuccMap, a successor mapping.%% - succ(SuccMap, L) -> [Labels], %% - function(CFG) -> {M,F,A}%%%% In the CODE file:%% ----------------- %% - uses(Instr) ->%% - defines(Instr) ->%% - is_phi(Instr) -> Boolean%% - phi_arglist(Instr) -> [{Pred, Var}]%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% The generic liveness analysis on SSA form%%ssa_liveness__analyze(CFG) -> PO = ?CFG:postorder(CFG), InitLiveness = liveness_init(init(PO, CFG)), merry_go_around(PO, InitLiveness).%%%% The fixpoint iteration%%merry_go_around(Labels, Liveness) -> case doit_once(Labels, Liveness) of {fixpoint, NewLiveness} -> NewLiveness; {value, NewLiveness} -> merry_go_around(Labels, NewLiveness) end.%%%% One iteration%%doit_once(Labels, Liveness) -> doit_once(Labels, Liveness, true).doit_once([], Liveness, FixPoint) -> if FixPoint -> {fixpoint, Liveness}; true -> {value, Liveness} end;doit_once([L|Ls], Liveness, FixPoint) -> LiveOut = join_livein(Liveness, L), NewLiveness = update_liveout(L, LiveOut, Liveness), Kill = set_subtract(LiveOut, kill(L, NewLiveness)), LiveIn = set_union(Kill, gen(L,NewLiveness)), case update_livein(L, LiveIn, NewLiveness) of fixpoint -> doit_once(Ls, NewLiveness, FixPoint); {value, NewLiveness1} -> doit_once(Ls, NewLiveness1, false) end. %%%% updates liveness for a basic block%%update_livein(Label, NewLiveIn, Liveness) -> {GKD, LiveIn, LiveOut, Succ} = liveness_lookup(Label, Liveness), case LiveIn of NewLiveIn -> fixpoint; _ -> {value, liveness_update(Label, {GKD,NewLiveIn,LiveOut,Succ}, Liveness)} end.update_liveout(Label, NewLiveOut, Liveness) -> {GKD, LiveIn, _LiveOut, Succ} = liveness_lookup(Label, Liveness), liveness_update(Label, {GKD,LiveIn,NewLiveOut,Succ}, Liveness).%%%% Join Live in to get the new live out.%%join_livein(Liveness, L) -> Succ = successors(L, Liveness), case Succ of [] -> % special case if no successors gb_sets:from_list(liveout_no_succ()); _ -> join_livein1(L, Succ, Liveness) end.join_livein1(Pred, Labels, Liveness) -> join_livein1(Pred, Labels, Liveness, new_set()).join_livein1(_Pred, [], _Liveness, Live) -> Live;join_livein1(Pred, [L|Ls], Liveness, Live) -> OldLivein = livein_set(Liveness, L, Pred), NewLive = set_union(OldLivein, Live), join_livein1(Pred, Ls, Liveness, NewLive).ssa_liveness__liveout(Liveness, L) -> {_GKD, _LiveIn, LiveOut, Successors} = liveness_lookup(L, Liveness), case Successors of [] -> % special case if no successors liveout_no_succ(); _ -> set_to_list(LiveOut) end. -ifdef(LIVENESS_NEEDED).ssa_liveness__livein(Liveness, L, Pred) -> set_to_list(livein_set(Liveness, L, Pred)).-endif.livein_set(Liveness, L, Pred) -> {{_Gen,_Kill,DirGen}, LiveIn, _LiveOut, _Successors} = liveness_lookup(L, Liveness), case gb_trees:lookup(Pred, DirGen) of none -> LiveIn; {value, LiveInFromPred} -> set_union(LiveInFromPred, LiveIn) end.successors(L, Liveness) -> {_GKD, _LiveIn, _LiveOut, Successors} = liveness_lookup(L, Liveness), Successors.kill(L, Liveness) -> {{_Gen,Kill,_DirGen},_LiveIn,_LiveOut,_Successors} = liveness_lookup(L, Liveness), Kill.gen(L, Liveness) -> {{Gen,_Kill,_DirGen},_LiveIn,_LiveOut,_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), {Gen, Kill} = make_bb_transfer(Code, Succ), DirectedGen = get_directed_gen(Code), [{L, {{Gen, Kill, DirectedGen}, new_set(), new_set(), Succ}} | init(Ls, CFG)].make_bb_transfer([], _Succ) -> {new_set(), new_set()}; % {Gen, Kill}make_bb_transfer([I|Is], Succ) -> {Gen, Kill} = make_bb_transfer(Is, Succ), case ?CODE:is_phi(I) of true -> InstrKill = set_from_list(?CODE:defines(I)), Gen1 = set_subtract(Gen, InstrKill), Kill1 = set_union(Kill, InstrKill), {Gen1, Kill1}; false -> InstrGen = set_from_list(?CODE:uses(I)), InstrKill = set_from_list(?CODE:defines(I)), Gen1 = set_subtract(Gen, InstrKill), Gen2 = set_union(Gen1, InstrGen), Kill1 = set_union(Kill, InstrKill), Kill2 = set_subtract(Kill1, InstrGen), {Gen2, Kill2} end.get_directed_gen([I|Left])-> case ?CODE:is_phi(I) of false -> gb_trees:empty(); true -> Map = get_directed_gen(Left), ArgList = ?CODE:phi_arglist(I), lists:foldl(fun update_directed_gen/2, Map, ArgList) end.update_directed_gen({Pred, Var}, Map)-> case gb_trees:lookup(Pred, Map) of none -> gb_trees:insert(Pred, set_from_list([Var]), Map); {value, Set} -> gb_trees:update(Pred, set_add(Var, Set), Map) end. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% liveness%%liveness_init(List) -> liveness_init1(List, gb_trees:empty()).liveness_init1([{Label, Info}|Left], Map) -> liveness_init1(Left, gb_trees:insert(Label, Info, Map));liveness_init1([], Map) -> Map.liveness_lookup(Label, Map) -> {value, Info} = gb_trees:lookup(Label, Map), Info.liveness_update(Label, NewInfo, Map) -> gb_trees:update(Label, NewInfo, Map).%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% Sets%%new_set() -> gb_sets:empty().set_union(S1, S2) -> gb_sets:union(S1, S2).set_subtract(S1, S2) -> gb_sets:subtract(S1, S2).set_from_list(List) -> gb_sets:from_list(List).set_to_list(Set) -> gb_sets:to_list(Set).set_add(Var, Set) -> gb_sets:add(Var, Set).%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% Pretty printer%%-ifdef(DEBUG_LIVENESS).pp_liveness(Cfg) -> io:format("Liveness for ~p:\n", [?CFG:function(Cfg)]), Liveness = analyze(Cfg), RevPostorder = lists:reverse(?CFG:postorder(Cfg)), SuccMap = ?CFG:succ_map(Cfg), Edges = [{X, Y} || X <- RevPostorder, Y <- ?CFG:succ(SuccMap, X)], pp_liveness_edges(Edges, Liveness).pp_liveness_edges([{From, To}|Left], Liveness)-> LiveIn = livein(Liveness, To, From), io:format("Label ~w -> Label ~w: ~p\n", [From, To, LiveIn]), LiveOut = liveout(Liveness, From), io:format("Total live out from Label ~w: ~p\n", [From, LiveOut]), pp_liveness_edges(Left, Liveness);pp_liveness_edges([], _Liveness) -> ok.-endif.
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?