hipe_ultra_prio.erl

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

ERL
292
字号
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%	      PRIORITY HANDLING AND PRIORITY CALCULATION%%%% Handling of ready nodes and priorities.%% Priorities are mainly from the critical path. More priorities are added.%%  * One version is adding priorities just depending on the instr, so%%    for example loads get higher priority than stores, and ordered%%    after reg's and offset for better cache performance.%%  * The other version gives higher priority to a node that adds more new%%    nodes to the ready list. This one is maybe not so effectively%%    implemented, but was added too late for smarter solutions.%% One version is commented away-module(hipe_ultra_prio).-export([init_ready/2,	 init_instr_prio/2,	 %% initial_ready_set/4,	 next_ready/7,	 add_ready_nodes/2,	 insert_node/3	]).-include("../sparc/hipe_sparc.hrl").% At first, only nodes with no predecessors are selected.% - if R is empty, there is an error (unless BB itself is empty)%% Arguments : Size  - size of ready-array%%             Preds - array with number of predecessors for each node%% Returns   : An array with list of ready-nodes for each cycle.init_ready(Size, Preds) ->    P = hipe_vectors:size(Preds),    Ready = hipe_vectors:new(Size, []),    R = initial_ready_set(1, P, Preds, []),    hipe_vectors:set(Ready, 0, R).init_instr_prio(N, DAG) ->    critical_path(N, DAG).%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% Function    : initial_ready_set%% Argument    : M     - current node-index%%               N     - where to stop%%               Preds - array with number of predecessors for each node%%               Ready - list with ready-nodes%% Returns     : Ready - list with ready-nodes%% Description : Finds all nodes with no predecessors and adds them to ready.%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%initial_ready_set(M, N, Preds, Ready) ->    if	M > N ->	    Ready;	true ->	    case hipe_vectors:get(Preds, M-1) of		0 ->		    initial_ready_set(M+1, N, Preds, [M|Ready]);		V when is_integer(V), V > 0 ->		    initial_ready_set(M+1, N, Preds, Ready)	    end    end.%% The following handles the nodes ready to schedule:%% 1. select the ready queue of given cycle%% 2. if queue empty, return none%% 3. otherwise, remove entry with highest priority%%    and return {next,Highest_Prio,NewReady}%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% Function    : next_ready%% Argument    : C     - current cycle%%               Ready - array with ready nodes%%               Prio  - array with cpath-priorities for all nodes%%               Nodes - indexed list [{N, Instr}]%% Returns     : none / {next,Highest_Prio,NewReady}%% Description :  1. select the ready queue of given cycle%%                2. if queue empty, return none%%                3. otherwise, remove entry with highest priority%%                   and return {next,Highest_Prio,NewReady} where Highest_Prio%%                   = Id of instr and NewReady = updated ready-array.%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%next_ready(C, Ready, Prio, Nodes, DAG, Preds, Earl) ->    Curr = hipe_vectors:get(Ready, C-1),    case Curr of	[] -> 	    none;	Instrs ->	    {BestI,RestIs} = 		get_best_instr(Instrs, Prio, Nodes, DAG, Preds, Earl, C),	    {next,BestI,hipe_vectors:set(Ready,C-1,RestIs)}    end.% next_ready(C,Ready,Prio,Nodes) ->%     Curr = hipe_vectors:get(Ready,C-1),%     case Curr of% 	[] ->   % 	    none;% 	Instrs ->% 	    {BestInstr,RestInstrs} = get_best_instr(Instrs, Prio, Nodes),% 	    {next,BestInstr,hipe_vectors:set(Ready,C-1,RestInstrs)}%     end.%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% Function    : get_best_instr%% Argument    : Instrs - list of node-id's%%               Prio   - array with cpath-priorities for the nodes%%               Nodes  - indexed list [{Id, Instr}]%% Returns     : {BestSoFar, Rest} - Id of best instr and the rest of id's%% Description : Returns the id of the instr that is the best choice.%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%get_best_instr([Instr|Instrs], Prio, Nodes, DAG, Preds, Earl, C) ->    get_best_instr(Instrs, [], Instr, Prio, Nodes, DAG, Preds, Earl, C).get_best_instr([], Rest, BestSoFar, _Prio, _Nodes, _DAG, _Preds, _Earl, _C) ->     {BestSoFar, Rest};get_best_instr([Instr|Instrs], PassedInstrs, BestSoFar, Prio, Nodes,	       DAG, Preds, Earl, C) ->    case better(Instr, BestSoFar, Prio, Nodes, DAG, Preds, Earl, C) of        true ->	    get_best_instr(Instrs, [BestSoFar|PassedInstrs],			   Instr, Prio, Nodes, DAG, Preds, Earl, C);	false -> 	    get_best_instr(Instrs, [Instr|PassedInstrs], BestSoFar, Prio, 			   Nodes, DAG, Preds, Earl, C)    end.% get_best_instr([Instr|Instrs], Prio, Nodes) ->%     get_best_instr(Instrs, [], Instr, Prio, Nodes).% get_best_instr([], Rest, BestSoFar, Prio, Nodes) -> {BestSoFar, Rest};% get_best_instr([Instr|Instrs], PassedInstrs, BestSoFar, Prio, Nodes) ->%     case better(Instr, BestSoFar, Prio, Nodes) of%         true ->% 	    get_best_instr(Instrs, [BestSoFar|PassedInstrs], % 			   Instr, Prio, Nodes);% 	false -> % 	    get_best_instr(Instrs, [Instr|PassedInstrs],BestSoFar, Prio, Nodes)%     end.    %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% Function    : better%% Argument    : Instr1 - Id of instr 1%%               Instr2 - Id of instr 2%%               Prio   - array with cpath-priorities for the nodes%%               Nodes  - indexed list [{Id, Instr}]%% Returns     : true if Instr1 has higher priority than Instr2%% Description : Checks if Instr1 is a better choice than Instr2 for scheduling%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%better(Instr1, Instr2, Prio, Nodes, DAG, Preds, Earl, C) ->    better_hlp(priority(Instr1, Prio, Nodes, DAG, Preds, Earl, C), 	       priority(Instr2, Prio, Nodes, DAG, Preds, Earl, C)).better_hlp([], []) -> false;better_hlp([], [_|_]) -> false;better_hlp([_|_], []) -> true;better_hlp([X|Xs], [Y|Ys]) -> (X > Y) or ((X =:= Y) and better_hlp(Xs,Ys)).%%%% Returns the instr corresponding to id%%get_instr(InstrId, [{InstrId,Instr}|_]) -> Instr;get_instr(InstrId, [_|Xs]) -> get_instr(InstrId, Xs).				      %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% Function    : priority%% Argument    : InstrId - Id%%               Prio    - array with cpath-priorities for the nodes%%               Nodes   - indexed list [{Id, Instr}]%% Returns     : PrioList - list of priorities [MostSignificant, LessSign, ...]%% Description : Returns a list of priorities where the first element is the%%               cpath-priority and the rest are added depending on what kind%%               of instr it is. Used to order loads/stores sequentially and%%               there is possibility to add whatever stuff...  %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%priority(InstrId, Prio, Nodes, DAG, Preds, Earl, C) ->    {ReadyNodes,_,_,_} = hipe_schedule:delete_node(C,InstrId,DAG,Preds,Earl),    Instr = get_instr(InstrId, Nodes),    Prio1 = hipe_vectors:get(Prio, InstrId-1),    Prio2 = length(ReadyNodes),    PrioRest =	case Instr of	 #load_atom{} ->	    [3];	 #move{} ->	    [3];	 #load{} ->   	    Src = hipe_sparc:load_src(Instr),  	    Off = hipe_sparc:load_off(Instr),	    case hipe_sparc:is_reg(Off) of		false -> [3, 			  -(hipe_sparc:reg_nr(Src)), 			  -(hipe_sparc:imm_value(Off))];		true -> [1]	    end;	 #store{} -> 	     Src = hipe_sparc:store_dest(Instr),	     Off = hipe_sparc:store_off(Instr),	     case hipe_sparc:is_reg(Off) of		 false -> [2, 			   -(hipe_sparc:reg_nr(Src)), 			   -(hipe_sparc:imm_value(Off))];		 true -> [1]	     end;	 _ -> [0]	end,    [Prio1,Prio2|PrioRest].%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% Function    : add_ready_nodes%% Argument    : Nodes - list of [{Cycle,Id}]%%               Ready - array of ready nodes for all cycles%% Returns     : NewReady - updated ready-array%% Description : Gets a list of instrs and adds them to the ready-array%%               to the corresponding cycle.%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%add_ready_nodes([], Ready) -> Ready;add_ready_nodes([{C,I}|Xs], Ready) ->    add_ready_nodes(Xs, insert_node(C, I, Ready)).insert_node(C, I, Ready) ->    Old = hipe_vectors:get(Ready, C-1),    hipe_vectors:set(Ready, C-1, [I|Old]).%%%% Computes the latency for the "most expensive" way through the graph%% for all nodes.  Returns an array of priorities for all nodes.%%critical_path(N, DAG) ->    critical_path(1, N, DAG, hipe_vectors:new(N, -1)).critical_path(M, N, DAG, Prio) ->    if	M > N ->	    Prio;	true ->	    critical_path(M+1, N, DAG, cpath(M, DAG, Prio))    end.%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% Function    : cpath%% Argument    : M    - current node id%%               DAG  - the dependence graph%%               Prio - array of priorities for all nodes%% Returns     : Prio - updated prio array%% Description : If node has prio -1, it has not been visited%%                - otherwise, compute priority as max of priorities of %%                  successors (+ latency)%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%cpath(M, DAG, Prio) ->    InitPrio = hipe_vectors:get(Prio, M-1),    if	InitPrio =:= -1 ->	    cpath_node(M, DAG, Prio);	true ->	    Prio    end.cpath_node(N, DAG, Prio) ->    SuccL = dag_succ(DAG, N),    {Max, NewPrio} = cpath_succ(SuccL, DAG, Prio),    hipe_vectors:set(NewPrio, N-1, Max).cpath_succ(SuccL, DAG, Prio) ->    cpath_succ(SuccL, DAG, Prio, 0).%% performs an unnecessary lookup of priority of Succ, but that might%% not be such a big dealcpath_succ([], _DAG, Prio, NodePrio) -> {NodePrio,Prio};cpath_succ([{Lat,Succ}|Xs], DAG, Prio, NodePrio) ->    NewPrio = cpath(Succ, DAG, Prio),    NewNodePrio = max(hipe_vectors:get(NewPrio, Succ - 1) + Lat, NodePrio),    cpath_succ(Xs, DAG, NewPrio, NewNodePrio).dag_succ(DAG, N) when is_integer(N) ->    hipe_vectors:get(DAG, N-1).max(X, Y) ->    if	X < Y -> Y;	true -> X    end.

⌨️ 快捷键说明

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