hipe_sparc_finalize.erl

来自「OTP是开放电信平台的简称」· ERL 代码 · 共 247 行

ERL
247
字号
%%% -*- erlang-indent-level: 2 -*-%%%----------------------------------------------------------------------%%% File    : hipe_sparc_finalize.erl%%% Author  : Christoffer Vikstr鰉 <chvi3471@student.uu.se>%%% Purpose : %%% Created : 16 Feb 2004 by Christoffer Vikstr鰉 <chvi3471@student.uu.se>%%%-----------------------------------------------------------------------module(hipe_sparc_finalize).-export([finalize/2]).-include("hipe_sparc.hrl").finalize(CFG,Options) ->  OptCFG = case proplists:get_bool(sparc_peephole,Options) of	     true  -> hipe_sparc_cfg:remove_trivial_bbs(CFG);	     false -> CFG	   end,  LinearCode = hipe_sparc:sparc_code(hipe_sparc_cfg:linearize(OptCFG)),  OptLinearCode = hipe_sparc_peephole:peep(LinearCode),  OptLinearCode2 = fill_delay(OptLinearCode, Options),  {OptCFG, lists:flatten(OptLinearCode2)}.%% opt(Code) ->%%     lists:reverse(opt(Code,[])).%% opt([G,L|Code], Acc) ->%%   case hipe_sparc:is_goto(G) of%%       true ->%% 	  case hipe_sparc:is_label(L) of%% 	      true ->%% 		  case hipe_sparc:goto_label(G) =:= hipe_sparc:label_name(L) of%% 		      true ->%% 			  opt(Code,[L|Acc]);%% 		      false ->%% 			  opt(Code,[L,G|Acc])%% 		  end;%% 	      false ->%% 		  opt([L|Code], [G|Acc])%% 	  end;%%       false ->%% 	  opt([L|Code], [G|Acc])%%   end;%% opt([I],Acc) ->%%     [I|Acc];%% opt([],Acc) ->%%     Acc.%% %%%% %% %% %%%% peephole([]) ->%%   [];%% peephole([I|Is]) ->%%    case I of%%      #move{} ->%%        case hipe_sparc:move_src(I) =:= hipe_sparc:move_dest(I) of%% 	 true ->%% 	   peephole(Is);%% 	 false ->%% 	   [I | peephole(Is)]%%        end;%%       _ ->%%        [I | peephole(Is)]%%    end.%%%% Code is a list of instructions. %%fill_delay(Code, Options) ->  Codes =  split_at_branch(Code),  case proplists:get_bool(fill_delayslot,Options) of    true  -> [fill_delay0(Is) || Is <- Codes];    false -> [nofill_delay(Is) || Is <- Codes]  end.nofill_delay(Code) ->  [Code | [hipe_sparc:nop_create()]].%%%% Code is a list of instructions where a branch/jump %%fill_delay0(Code) ->  case catch find_delay(Code) of    no_branch ->      Code;    {NewCode, _, _, _} ->      [NewCode | [hipe_sparc:nop_create()]];    {NewCode, Delay} ->      [NewCode | [Delay]]  end.%%%% Extracts a delay instruction from a list %%find_delay([Jmp]) ->  case hipe_sparc:has_delayslot(Jmp) of    true ->      {[Jmp],        ordsets:from_list(hipe_sparc:uses(Jmp)),        ordsets:from_list(hipe_sparc:defines(Jmp)),       []};    false ->      throw(no_branch)  end;find_delay([I|Is]) ->  case find_delay(Is) of    {NewIs, Uses, Defs, Loads} ->      IUses = ordsets:from_list(hipe_sparc:uses(I)),      IDefs = ordsets:from_list(hipe_sparc:defines(I)),      NewUses = ordsets:union(Uses, IUses),      NewDefs = ordsets:union(Defs, IDefs),      IsStore = hipe_sparc:is_store(I),      NewLoads = case hipe_sparc:is_load(I) of 		   true -> [I|Loads];		   false -> Loads		 end,      case is_delay_instr(I) of	true ->	  %% Make sure the instruction isn't defining a reg that is 	  %% used later or uses a reg that is defined later or	  %% defines a reg that is defined later	  X = {ordsets:intersection(Uses, IDefs), 	       ordsets:intersection(Defs, IUses),	       ordsets:intersection(Defs, IDefs)},	  case X of	    {[], [], []} ->  %% No register conflicts	      case {IsStore,Loads} of		{_,[]} -> % No following loads		  {NewIs, I}; % found a delay instr.		{false,_} -> % This is not a store		  {NewIs, I}; % found a delay instr.		_ -> %% A store with following loads.		  %% XXX: TODO check whether the store 		  %%      and the load REALY conflicts.		  %%      (Stack and Heap does not conflict)		  {[I|NewIs], NewUses, NewDefs, NewLoads} %% Search more	      end;	    _ -> %% Register conflicts.	      {[I|NewIs], NewUses, NewDefs, NewLoads}	  end;	false ->	  {[I|NewIs], NewUses, NewDefs, NewLoads}      end;    {NewIs, Delay} ->      {[I|NewIs], Delay}  end.%%%% true if I is an instruction that can be moved to a delay slot%%is_delay_instr(I) ->  case I of    #label{} -> false;    #comment{} -> false;    #load_address{} -> false;    #load_atom{} -> false;    #load_word_index{} -> false;    #fop{} -> false;    %%         in the delayslot can slow down code...    %%         ... but it can also speed up code.    %%         the impact is about 10 - 20 % on small bms    %%         on the average you loose 1-2 % by not putting    %%         loads in delayslots    %% #load{} -> false;    _ -> true  end.%%%% Split a list of instructions to a list of lists of instructions%% where each sublist ends with a branch.%%split_at_branch([]) ->   [];split_at_branch([I|Rest]) ->  case Rest of    [L|_] ->      case hipe_sparc:is_label(L) of	true -> 	  Lname = hipe_sparc:label_name(L),	  split(I,Lname,Rest);	false ->	  split(I,[],Rest)      end;    _ ->      split(I,[],Rest)  end.split(I,Lname,Is)->  case I of    #b{} ->       case hipe_sparc:b_false_label(I) of	Lname ->	  [[hipe_sparc:b_false_label_update(I,[])] |	   split_at_branch(Is)];	FL ->	  [[hipe_sparc:b_false_label_update(I,[])], 	   [hipe_sparc:goto_create(FL)]|	   split_at_branch(Is)]      end;%%  #br{} -> %%       case hipe_sparc:br_false_label(I) of%% 	Lname ->%% 	  [[hipe_sparc:br_false_label_update(I,[])] |%% 	   split_at_branch(Is)];%% 	FL ->%% 	  [[hipe_sparc:br_false_label_update(I,[])], %% 	   [hipe_sparc:goto_create(FL)]|%% 	   split_at_branch(Is)]%%       end;    #goto{} ->       [[I] | split_at_branch(Is)];    #jmp{} ->       [[I] | split_at_branch(Is)];    #jmp_link{} ->       [[I] | split_at_branch(Is)];    #call_link{} ->%%      [[I] | split_at_branch(Is)];      case hipe_sparc:call_link_continuation(I) of	[] -> %%	  NL = hipe_sparc:label_create_new(),%%	  NLname = hipe_sparc:label_name(NL),	 [[I] | split_at_branch(Is)];%%	  [[hipe_sparc:goto_create(NLname)]|%%	   split_at_branch([NL|Is])]];	Lname -> 	  [[hipe_sparc:call_link_continuation_update(I,[])] |	   split_at_branch(Is)];	CCL ->	  [[hipe_sparc:call_link_continuation_update(I,[])],	   [hipe_sparc:goto_create(CCL)]|	   split_at_branch(Is)]      end;    #label{} ->      [[I] | split_at_branch(Is)];    _ ->       [Same|Lists] = split_at_branch(Is),      [[I|Same]|Lists]  end.

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?