Skip to content

Commit

Permalink
Simple refactor of hipe_llvm_liveness
Browse files Browse the repository at this point in the history
  • Loading branch information
yiannist committed Apr 11, 2014
1 parent ef8c4a6 commit c4f52a5
Showing 1 changed file with 45 additions and 45 deletions.
90 changes: 45 additions & 45 deletions lib/hipe/llvm/hipe_llvm_liveness.erl
Expand Up @@ -7,27 +7,25 @@
analyze(RtlCfg) -> analyze(RtlCfg) ->
Liveness = hipe_rtl_liveness:analyze(RtlCfg), Liveness = hipe_rtl_liveness:analyze(RtlCfg),
Roots = find_roots(RtlCfg, Liveness), Roots = find_roots(RtlCfg, Liveness),
%% erlang:display(Roots),
NewRtlCfg = mark_dead_roots(RtlCfg, Liveness, Roots), NewRtlCfg = mark_dead_roots(RtlCfg, Liveness, Roots),
{NewRtlCfg, Roots}. {NewRtlCfg, Roots}.


%% @doc Determine which are the GC Roots. Possible roots are all RTL variables %% @doc Determine which are the GC Roots. Possible roots are all RTL variables
%% (rtl_var). However, since function calls are the safe-points, we consider as %% (rtl_var). However, since function calls are the safe-points, we consider as
%% possible GC roots only RTL variables that are live around function calls. %% possible GC roots only RTL variables that are live around function calls.
find_roots(Cfg, Liveness) -> find_roots(CFG, Liveness) ->
Labels = hipe_rtl_cfg:postorder(Cfg), Labels = hipe_rtl_cfg:postorder(CFG),
Roots = find_roots_bb(Labels, Cfg, Liveness, []), find_roots_bb(Labels, CFG, Liveness, []).
lists:usort(lists:flatten(Roots)).


find_roots_bb([], _Cfg, _Liveness, RootAcc) -> find_roots_bb([], _, _, RootAcc) ->
RootAcc; lists:usort(lists:flatten(RootAcc));
find_roots_bb([L|Ls], Cfg, Liveness, RootAcc) -> find_roots_bb([L|Ls], CFG, Liveness, RootAcc) ->
Block = hipe_rtl_cfg:bb(Cfg, L), Block = hipe_rtl_cfg:bb(CFG, L),
BlockCode = hipe_bb:code(Block), BlockCode = hipe_bb:code(Block),
LiveIn = ordsets:from_list(strip(hipe_rtl_liveness:livein(Liveness, L))), LiveIn = ordsets:from_list(strip(hipe_rtl_liveness:livein(Liveness, L))),
LiveOut = ordsets:from_list(strip(hipe_rtl_liveness:liveout(Liveness, L))), LiveOut = ordsets:from_list(strip(hipe_rtl_liveness:liveout(Liveness, L))),
Roots = do_find_roots_bb(BlockCode, L, LiveOut, LiveIn, []), Roots = do_find_roots_bb(BlockCode, L, LiveIn, LiveOut, []),
find_roots_bb(Ls, Cfg, Liveness, Roots ++ RootAcc). find_roots_bb(Ls, CFG, Liveness, [Roots|RootAcc]).


%% For each call inside a BB the GC roots are those RTL variables that are live %% For each call inside a BB the GC roots are those RTL variables that are live
%% before and after the call. %% before and after the call.
Expand All @@ -36,26 +34,26 @@ find_roots_bb([L|Ls], Cfg, Liveness, RootAcc) ->
%% Live After Call: These are the RTL variables that belong to the LiveOut %% Live After Call: These are the RTL variables that belong to the LiveOut
%% list or are used after the call inside the BB (they die inside the BB and so %% list or are used after the call inside the BB (they die inside the BB and so
%% don't belong to the LiveOut list). %% don't belong to the LiveOut list).
do_find_roots_bb([], _Label, _LiveOut, _LiveBefore, RootAcc) -> do_find_roots_bb([], _, _, _, RootAcc) ->
RootAcc; RootAcc;
do_find_roots_bb([I|Is], L, LiveOut, LiveBefore, RootAcc) -> do_find_roots_bb([I|Is], L, LiveIn, LiveOut, RootAcc) ->
case hipe_rtl:is_call(I) of case hipe_rtl:is_call(I) of
true -> true ->
%% Used inside the BB after the call %% Used inside the BB after the call
UsedAfterCall_ = strip(lists:flatten([hipe_rtl:uses(V) || V <- Is])), UsedAfterCall =
UsedAfterCall = ordsets:from_list(UsedAfterCall_), ordsets:from_list(strip(lists:flatten([hipe_rtl:uses(V) || V <- Is]))),
LiveAfter = ordsets:union(UsedAfterCall, LiveOut), LiveAfterCall = ordsets:union(UsedAfterCall, LiveOut),
%% The Actual Roots %% The actual roots
Roots = ordsets:intersection(LiveBefore, LiveAfter), Roots = ordsets:intersection(LiveIn, LiveAfterCall),
%% The result of the instruction %% The result of the instruction
Defines = ordsets:from_list(strip(hipe_rtl:defines(I))), Defined = ordsets:from_list(strip(hipe_rtl:defines(I))),
LiveBefore1 = ordsets:union(LiveBefore, Defines), LiveIn2 = ordsets:union(LiveIn, Defined),
do_find_roots_bb(Is, L, LiveOut, LiveBefore1, [Roots|RootAcc]); do_find_roots_bb(Is, L, LiveIn2, LiveOut, [Roots|RootAcc]);
false -> false ->
%% The result of the instruction %% The result of the instruction
Defines = ordsets:from_list(strip(hipe_rtl:defines(I))), Defined = ordsets:from_list(strip(hipe_rtl:defines(I))),
LiveBefore1 = ordsets:union(LiveBefore, Defines), LiveIn2 = ordsets:union(LiveIn, Defined),
do_find_roots_bb(Is, L, LiveOut, LiveBefore1, RootAcc) do_find_roots_bb(Is, L, LiveIn2, LiveOut, RootAcc)
end. end.


%% @doc This function is responsible for marking when GC Roots, which can only %% @doc This function is responsible for marking when GC Roots, which can only
Expand All @@ -66,41 +64,43 @@ mark_dead_roots(CFG, Liveness, Roots) ->
Labels = hipe_rtl_cfg:postorder(CFG), Labels = hipe_rtl_cfg:postorder(CFG),
mark_dead_bb(Labels, CFG, Liveness, Roots). mark_dead_bb(Labels, CFG, Liveness, Roots).


mark_dead_bb([], Cfg, _Liveness, _Roots) -> mark_dead_bb([], CFG, _, _) ->
Cfg; CFG;
mark_dead_bb([L|Ls], Cfg, Liveness, Roots) -> mark_dead_bb([L|Ls], CFG, Liveness, Roots) ->
Block = hipe_rtl_cfg:bb(Cfg, L), Block = hipe_rtl_cfg:bb(CFG, L),
BlockCode = hipe_bb:code(Block), BlockCode = hipe_bb:code(Block),
LiveIn = ordsets:from_list(strip(hipe_rtl_liveness:livein(Liveness, L))),
LiveOut = ordsets:from_list(strip(hipe_rtl_liveness:liveout(Liveness, L))), LiveOut = ordsets:from_list(strip(hipe_rtl_liveness:liveout(Liveness, L))),
NewBlockCode = do_mark_dead_bb(BlockCode, LiveOut, Roots, []), NewBlockCode = do_mark_dead_bb(BlockCode, LiveOut, Roots, []),
%% Update the CFG %% Update the CFG
NewBB = hipe_bb:code_update(Block, NewBlockCode), NewBB = hipe_bb:code_update(Block, NewBlockCode),
NewCFG = hipe_rtl_cfg:bb_add(Cfg, L, NewBB), NewCFG = hipe_rtl_cfg:bb_add(CFG, L, NewBB),
mark_dead_bb(Ls, NewCFG, Liveness, Roots). mark_dead_bb(Ls, NewCFG, Liveness, Roots).


do_mark_dead_bb([], _LiveOut, _Roots, NewBlockCode) -> do_mark_dead_bb([], _, _, NewBlockCode) ->
lists:reverse(NewBlockCode); lists:reverse(NewBlockCode);
do_mark_dead_bb([I|Is], LiveOut ,Roots, NewBlockCode) -> do_mark_dead_bb([I|Is], LiveOut, Roots, NewBlockCode) ->
Uses = ordsets:from_list(strip(hipe_rtl:uses(I))), Used = ordsets:from_list(strip(hipe_rtl:uses(I))),
%% GC roots that are used in this instruction %% GC roots that are used in this instruction
RootsUsed = ordsets:intersection(Roots, Uses), RootsUsed = ordsets:intersection(Roots, Used),
UsedAfter_ = strip(lists:flatten([hipe_rtl:uses(V) || V <- Is])), UsedAfterInstr =
UsedAfter = ordsets:from_list(UsedAfter_), ordsets:from_list(strip(lists:flatten([hipe_rtl:uses(V) || V <- Is]))),
%% GC roots that are live after this instruction %% GC roots that are live after this instruction
LiveAfter = ordsets:union(LiveOut, UsedAfter), LiveAfterInstr = ordsets:union(LiveOut, UsedAfterInstr),
%% GC roots that their last use is in this instruction %% GC roots that their last use is in this instruction
DeadRoots = ordsets:subtract(RootsUsed, LiveAfter), DeadRoots = ordsets:subtract(RootsUsed, LiveAfterInstr),
%% Re-create the RTL variable from the corresponding Index %% Re-create the RTL variable from the corresponding Index
OldVars = [hipe_rtl:mk_var(V1) || V1 <- DeadRoots], OldVars = [hipe_rtl:mk_var(V) || V <- DeadRoots],
%% Mark the RTL variable as DEAD (last use) %% Mark the RTL variable as 'dead' (last use)
NewVars = [kill_var(V2) || V2 <- OldVars], NewVars = [kill_var(V) || V <- OldVars],
%% Create a list with the substitution of the old vars with the new %% Create a list with the substitution of the old vars with the new
%% ones which are marked with the dead keyword %% ones which are marked with the dead keyword
Subtitution = lists:zip(OldVars, NewVars), Substitution = lists:zip(OldVars, NewVars),
NewI = case Subtitution of NewI =
[] -> I; case Substitution of
_ -> hipe_rtl:subst_uses_llvm(Subtitution, I) [] -> I;
end, _ -> hipe_rtl:subst_uses_llvm(Substitution, I)
end,
do_mark_dead_bb(Is, LiveOut, Roots, [NewI|NewBlockCode]). do_mark_dead_bb(Is, LiveOut, Roots, [NewI|NewBlockCode]).


%% Update the liveness of a var in order to mark that this is the last use. %% Update the liveness of a var in order to mark that this is the last use.
Expand Down

0 comments on commit c4f52a5

Please sign in to comment.