hipe_icode_split_arith.erl

来自「OTP是开放电信平台的简称」· ERL 代码 · 共 535 行 · 第 1/2 页

ERL
535
字号
%% -*- erlang-indent-level: 2 -*-%%-------------------------------------------------------------------%% File    : hipe_icode_split_arith.erl%% Author  : Tobias Lindahl <tobiasl@csd.uu.se>%% Description : %%%% Created : 12 Nov 2003 by Tobias Lindahl <tobiasl@csd.uu.se>%%--------------------------------------------------------------------module(hipe_icode_split_arith).-export([cfg/3]).-include("hipe_icode.hrl").-define(MIN_RATIO, 0.005).cfg(Cfg, _Fun, Options) ->  Icode = hipe_icode_cfg:cfg_to_linear(Cfg),  case proplists:get_bool(split_arith_unsafe, Options) of    true -> make_split_unsafe(Icode);    _ ->      case preprocess(Icode) of	{do_not_split, _Ratio} -> 	  Cfg;	{split, _Ratio, Icode1} ->	  NewCfg = split(Icode1),	  %%hipe_icode_cfg:pp(NewCfg),	  NewCfg      end  end.check_nofix_const([Arg1|Arg2]) ->  case hipe_icode:is_const(Arg1) of    true ->      %%io:format("ConsTant.....~w",[Arg1]),      Val1 = hipe_tagscheme:fixnum_val(hipe_icode:const_value(Arg1)),      case hipe_tagscheme:is_fixnum(Val1) of	true ->	  check_nofix_const(Arg2);	false -> {no}      end;    false ->      check_nofix_const(Arg2)  end;	  check_nofix_const([]) -> true.check_const([I|Left]) ->  case I of    #call{} ->      case is_arith(I) of	true -> %%io:format("is_arith.....~w",[I]),	  Args = hipe_icode:call_args(I),	  case check_nofix_const(Args) of	    {no} -> {do_not_split};	    _ -> check_const(Left)	  end;	_ -> check_const(Left)      end;    _ -> check_const(Left)  end;check_const([]) -> {yes}.make_split_unsafe(Icode)->  LinearCode = hipe_icode:icode_code(Icode),  NewLinearCode = change_unsafe(LinearCode),  NewIcode = hipe_icode:icode_code_update(Icode, NewLinearCode),  hipe_icode_cfg:linear_to_cfg(NewIcode).change_unsafe([I|Is]) ->  case I of    #call{} ->      case is_arith_extra_unsafe(I) of	true ->	  NewOp = arithop_to_extra_unsafe(hipe_icode:call_fun(I)),	  NewI1 = hipe_icode:call_fun_update(I, NewOp),	  [NewI1|change_unsafe(Is)];	false ->	  [I|change_unsafe(Is)]      end;    _ ->      [I|change_unsafe(Is)]  end;change_unsafe([]) -> [].preprocess(Icode) ->  LinearCode = hipe_icode:icode_code(Icode),  case check_const(LinearCode) of    {do_not_split} -> %%io:format("NO FIXNUM....."),      {do_not_split, 1.9849 }; % Ratio val is ignored    _ ->      {NofArith, NofIns, NewLinearCode} = preprocess_code(LinearCode),      case NofArith / NofIns of	X when X >= ?MIN_RATIO ->	  NewIcode = hipe_icode:icode_code_update(Icode, NewLinearCode),	  {split, X, NewIcode};	Y ->	  {do_not_split, Y}      end  end.preprocess_code([H|Code]) ->  preprocess_code(Code, 0, 0, [H]).preprocess_code([I|Left], NofArith, NofIns,CodeAcc = [PrevI|_])->  case I of    #call{} ->      case is_arith(I) of	true ->	  %% Note that we need to put these instructions in a separate	  %% basic block since we need the ability to fail to these	  %% instructions, but also fail from them. The basic block	  %% merger will take care of unnecessary splits.	  %% If call is an arithmetic operation replace the operation	  %% with the specified replacement operator.  	  NewOp = arithop_to_split(hipe_icode:call_fun(I)),	  NewI = hipe_icode:call_fun_update(I, NewOp),	  case hipe_icode:is_label(PrevI) of	    true ->	      case (Left =:= []) orelse hipe_icode:is_label(hd(Left)) of		true -> 		  preprocess_code(Left, NofArith+1, NofIns+1, [NewI|CodeAcc]);		false ->		  NewLabel = hipe_icode:mk_new_label(),		  NewLabelName = hipe_icode:label_name(NewLabel),		  NewI1 = hipe_icode:call_set_continuation(NewI, NewLabelName),		  preprocess_code(Left, NofArith+1, NofIns+1, 				  [NewLabel, NewI1|CodeAcc])	      end;	    false ->	      RevPreCode =		case hipe_icode:is_branch(PrevI) of		  true ->		    [hipe_icode:mk_new_label()];		  false ->		    NewLabel1 = hipe_icode:mk_new_label(),		    NewLabelName1 = hipe_icode:label_name(NewLabel1),		    [NewLabel1, hipe_icode:mk_goto(NewLabelName1)]		end,	      case (Left =:= []) orelse hipe_icode:is_label(hd(Left)) of		true -> 		  preprocess_code(Left, NofArith+1, NofIns+1, 				  [NewI|RevPreCode] ++ CodeAcc);		false ->		  NewLabel2 = hipe_icode:mk_new_label(),		  NewLabelName2 = hipe_icode:label_name(NewLabel2),		  NewI1 = hipe_icode:call_set_continuation(NewI, NewLabelName2),		  preprocess_code(Left, NofArith+1, NofIns+1, 				  [NewLabel2, NewI1|RevPreCode] ++ CodeAcc)	      end	  end;	false ->	  preprocess_code(Left, NofArith, NofIns + 1, [I|CodeAcc])      end;    #label{} ->      %% Don't count labels as instructions.      preprocess_code(Left, NofArith, NofIns, [I|CodeAcc]);    _ ->      preprocess_code(Left, NofArith, NofIns+1, [I|CodeAcc])  end;preprocess_code([], NofArith, NofIns, CodeAcc) ->  {NofArith, NofIns, lists:reverse(CodeAcc)}.split(Icode) ->  LinearCode = hipe_icode:icode_code(Icode),  %% create a new icode label for each existing icode label  %% create mappings, NewToOld and OldToNew.  %%  AllLabels = lists:foldl(fun(I, Acc) ->			      case hipe_icode:is_label(I) of				true -> [hipe_icode:label_name(I)|Acc];				false -> Acc			      end			  end, [], LinearCode),  {OldToNewMap, NewToOldMap}  = new_label_maps(AllLabels),  %% the call below doubles the number of basic blocks with the new  %% labels instead of the old.  NewLinearCode = map_code(LinearCode, OldToNewMap),  NewIcode = hipe_icode:icode_code_update(Icode, NewLinearCode),  NewCfg = hipe_icode_cfg:linear_to_cfg(NewIcode),  NewCfg2 =     insert_tests(NewCfg, [gb_trees:get(X, OldToNewMap) || X<-AllLabels], 		 NewToOldMap, OldToNewMap),  %%io:format("split(Cfg): Inserting testsL Done\n", []),  NewCfg2.map_code(OldCode, LabelMap) ->  AddedCode = map_code(OldCode, none, LabelMap, []),  OldCode ++ AddedCode.map_code([I|Left], ArithFail, LabelMap, Acc) ->  case I of    #call{} ->      case is_arith(I) of	true ->	  case hipe_icode:defines(I) of	    []->  	      map_code(Left, ArithFail, LabelMap, [redirect(I, LabelMap)|Acc]);	    _ ->	      NewOp = split_to_unsafe(I),	      NewI1 = hipe_icode:call_fun_update(I, NewOp),	      NewI2 = redirect(NewI1, LabelMap),	      NewI3 = hipe_icode:call_set_fail_label(NewI2, ArithFail),	      map_code(Left, ArithFail, LabelMap, [NewI3|Acc])	  end;	false ->	  map_code(Left, ArithFail, LabelMap, [redirect(I, LabelMap)|Acc])      end;    #label{} ->      LabelName = hipe_icode:label_name(I),      NewLabel = hipe_icode:mk_label(gb_trees:get(LabelName, LabelMap)),      map_code(Left, LabelName, LabelMap, [NewLabel|Acc]);    _ ->       map_code(Left, ArithFail, LabelMap, [redirect(I, LabelMap)|Acc])  end;map_code([], _ArithFail, _LabelMap, Acc) ->  lists:reverse(Acc).insert_tests(Cfg, Labels,NewToOldMap, OldToNewMap) ->  InfoMap = infomap_init(Labels),  %%io:format("insert_tests/3: Finding testpoints ...\n", []),  NewInfoMap = find_testpoints(Cfg, Labels, InfoMap),  %%io:format("insert_tests/3: Finding testpoints: Done\n", []),  %%io:format("insert_tests/3: Infomap: ~w\n", [gb_trees:to_list(NewInfoMap)]),  make_tests(Cfg, NewInfoMap, NewToOldMap, OldToNewMap).find_testpoints(Cfg, Labels, InfoMap) ->  case find_testpoints(Labels, InfoMap, Cfg, false) of    {dirty, NewInfoMap} ->       %%io:format("find_testpoints/3: Looping\n", []),      find_testpoints(Cfg, Labels, NewInfoMap);    fixpoint ->      InfoMap   end.find_testpoints([Lbl|Left], InfoMap, Cfg, Dirty) ->  Code = hipe_bb:code(hipe_icode_cfg:bb(Cfg, Lbl)),  InfoOut = join_info(hipe_icode_cfg:succ(Cfg, Lbl), InfoMap),    OldInfoIn = infomap_get_all(Lbl, InfoMap),  NewInfoIn = traverse_code(lists:reverse(Code), InfoOut),  case (gb_sets:is_subset(OldInfoIn, NewInfoIn) andalso 	gb_sets:is_subset(NewInfoIn, OldInfoIn)) of    true ->      find_testpoints(Left, InfoMap, Cfg, Dirty);    false ->      %%io:format("find_testpoints/4: Label: ~w: OldMap ~w\nNewMap: ~w\n",       %%	 [Lbl, gb_sets:to_list(OldInfoIn), gb_sets:to_list(NewInfoIn)]),      NewInfoMap = gb_trees:update(Lbl, NewInfoIn, InfoMap),      find_testpoints(Left, NewInfoMap, Cfg, true)  end;find_testpoints([], InfoMap, _Cfg, Dirty) ->  if Dirty -> {dirty, InfoMap};     true -> fixpoint  end.traverse_code([I|Left], Info) ->  NewInfo = kill_defines(I, Info),  case I of    #call{} ->      case is_unsafe_arith(I) of	true ->	  %% The dst is sure to be a fixnum. Remove the 'killed' mark.	  Dst = hd(hipe_icode:call_dstlist(I)),

⌨️ 快捷键说明

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