hipe_coalescing_regalloc.erl

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

ERL
1,013
字号
%% -*- erlang-indent-level: 2 -*-%%-----------------------------------------------------------------------%% File    : hipe_coalescing_regalloc.erl%% Authors : Andreas Wallin <d96awa@it.uu.se>%%           Thorild Sel閚 <d95ths@.it.uu.se>%%           Ingemar 舃erg <d95ina@it.uu.se>%% Purpose : Play paintball with registers on a target machine.  We win%%           if they are all colored.  This is an iterated coalescing%%           register allocator.%% Created : 4 Mar 2000%%------------------------------------------------------------------------module(hipe_coalescing_regalloc).-export([regalloc/5]).%%-ifndef(DEBUG).%%-define(DEBUG,true).%%-endif.-include("../main/hipe.hrl").%%-----------------------------------------------------------------------%% Function:    regalloc%%%% Description: Creates a K coloring for a function.%% Parameters:%%   CFG         -- A control flow graph%%   SpillIndex  -- Last index of spill variable%%   SpillLimit  -- Temporaries with numbers higher than this have%%                  infinite spill cost. %%                  Consider changing this to a set.%%   Target      -- The module containing the target-specific functions.%%%% Returns:%%   Coloring    -- A coloring for specified CFG%%   SpillIndex0 -- A new spill index%%-----------------------------------------------------------------------regalloc(CFG, SpillIndex, SpillLimit, Target, _Options) ->  %% Build interference graph  ?debug_msg("Build IG\n",[]),  IG = hipe_ig:build(CFG, Target),  %% io:format("IG: ~p\n",[IG]),  ?debug_msg("Init\n",[]),  No_temporaries = Target:number_of_temporaries(CFG),  ?debug_msg("Coalescing RA: num_temps = ~p~n", [No_temporaries]),  Allocatable = Target:allocatable(),  K = length(Allocatable),  All_colors = colset_from_list(Allocatable),  %% Add registers with their own coloring  ?debug_msg("Moves\n",[]),  Move_sets = hipe_moves:new(IG),  ?debug_msg("Build Worklist\n",[]),  Worklists =     hipe_reg_worklists:new(IG, Target, CFG, Move_sets, K, No_temporaries),  Alias = initAlias(No_temporaries),  ?debug_msg("Do coloring\n~p~n",[Worklists]),  {_IG0, Worklists0, _Moves0, Alias0} =     do_coloring(IG, Worklists, Move_sets, Alias, K, SpillLimit, Target),  %% io:format("SelStk0 ~w\n",[SelStk0]),  ?debug_msg("Init node sets\n",[]),  Node_sets = hipe_node_sets:new(),  %% io:format("NodeSet: ~w\n NonAlloc ~w\n",[Node_sets,Target:non_alloc(CFG)]),  ?debug_msg("Default coloring\n",[]),  {Color0,Node_sets1} =     defaultColoring(Target:all_precoloured(),		    initColor(No_temporaries), Node_sets, Target),  ?debug_msg("Assign colors\n",[]),  {Color1,Node_sets2} =    assignColors(hipe_reg_worklists:stack(Worklists0), Node_sets1, Color0, 		 Alias0, All_colors, Target),  %% io:format("color0:~w\nColor1:~w\nNodes:~w\nNodes2:~w\nNo_temporaries:~w\n",[Color0,Color1,Node_sets,Node_sets2,No_temporaries]),  ?debug_msg("Build mapping ~p\n",[Node_sets2]),  Coloring = build_namelist(Node_sets2,SpillIndex,Alias0,Color1),  ?debug_msg("Coloring ~p\n",[Coloring]),  Coloring.%%----------------------------------------------------------------------%% Function:    do_coloring%%%% Description: Create a coloring. That is, play paintball.%% Parameters:%%   IG          --  An interference graph%%   Worklists   --  Worklists, that is simplify, spill and freeze%%   Moves       --  Moves sets, that is coalesced, constrained %%                   and so on.%%   Alias       --  Tells if two temporaries can have their value%%                   in the same register.%%   K           --  Want to create a K coloring.%%   SpillLimit  --  Try not to spill nodes that are above the spill limit.%%%% Returns:%%   IG          --  Updated interference graph%%   Worklists   --  Updated Worklists structure%%   Moves       --  Updated Moves structure %%   Alias       --  Updates Alias structure%%   %%----------------------------------------------------------------------do_coloring(IG, Worklists, Moves, Alias, K, SpillLimit, Target) ->  Simplify = not(hipe_reg_worklists:is_empty_simplify(Worklists)),  Coalesce = not(hipe_moves:is_empty_worklist(Moves)),  Freeze   = not(hipe_reg_worklists:is_empty_freeze(Worklists)),  Spill    = not(hipe_reg_worklists:is_empty_spill(Worklists)),  if Simplify =:= true ->      {IG0, Worklists0, Moves0} = 	simplify(hipe_reg_worklists:simplify(Worklists),		 IG, 		 Worklists, 		 Moves, 		 K),      do_coloring(IG0, Worklists0, Moves0, Alias,		  K, SpillLimit, Target);     Coalesce =:= true ->      {Moves0, IG0, Worklists0, Alias0} =	coalesce(Moves, IG, Worklists, Alias, K, Target),      do_coloring(IG0, Worklists0, Moves0, Alias0, 		  K, SpillLimit, Target);     Freeze =:= true ->      {Worklists0,Moves0} = 	freeze(K, Worklists, Moves, IG, Alias),      do_coloring(IG, Worklists0, Moves0, Alias, 		  K, SpillLimit, Target);     Spill =:= true ->      {Worklists0, Moves0} = 	selectSpill(Worklists, Moves, IG, K, Alias, SpillLimit),      do_coloring(IG, Worklists0, Moves0, Alias, 		  K, SpillLimit, Target);     true -> % Catchall case      {IG, Worklists, Moves, Alias}    end.%%----------------------------------------------------------------------%% Function:    adjacent%%%% Description: Adjacent nodes that's not coalesced, on the stack or%%               precoloured.%% Parameters:%%   Node        --  Node that you want to adjacents of%%   IG          --  The interference graph%%%%   Returns: %%     A set with nodes/temporaries that are not coalesced, on the %%      stack or precoloured.%%----------------------------------------------------------------------adjacent(Node, IG, Worklists) ->  Adjacent_edges = hipe_ig:node_adj_list(Node, IG),  hipe_reg_worklists:non_stacked_or_coalesced_nodes(Adjacent_edges, Worklists).%%----------------------------------------------------------------------%% Function:    simplify%%%% Description: Simplify graph by removing nodes of low degree. This%%               function simplify all nodes it can at once.%% Parameters:%%   [Node|Nodes]  --  The simplify worklist%%   IG            --  The interference graph%%   Worklists     --  The worklists data-structure%%   Moves         --  The moves data-structure%%   K             --  Produce a K coloring%%%%   Returns: %%     IG          --  An updated interference graph%%     Worklists   --  An updated worklists data-structure%%     Moves       --  An updated moves data-structure%%----------------------------------------------------------------------simplify([], IG, Worklists, Moves, _K) ->   {IG, Worklists, Moves};simplify([Node|Nodes], IG, Worklists, Moves, K) ->  Worklists0 = hipe_reg_worklists:remove_simplify(Node, Worklists),  ?debug_msg("putting ~w on stack~n",[Node]),  Adjacent = adjacent(Node, IG, Worklists0),  Worklists01 = hipe_reg_worklists:push_stack(Node, Adjacent, Worklists0),  {New_ig, Worklists1, New_moves} =    decrement_degree(Adjacent, IG, Worklists01, Moves, K),  simplify(Nodes, New_ig, Worklists1, New_moves, K).%%----------------------------------------------------------------------%% Function:    decrement_degree%%%% Description: Decrement the degree on a number of nodes/temporaries.%% Parameters:%%   [Node|Nodes]  --  Decrement degree on these nodes%%   IG            --  The interference graph%%   Worklists     --  The Worklists data structure%%   Moves         --  The Moves data structure.%%   K             --  We want to create a coloring with K colors%%%%   Returns: %%     IG          --  An updated interference graph (the degrees)%%     Worklists   --  Updated Worklists. Changed if one degree goes%%                     down to K.%%     Moves       --  Updated Moves. Changed if a move related temporary%%                     gets degree K.%%----------------------------------------------------------------------decrement_degree([], IG, Worklists, Moves, _K) ->   {IG, Worklists, Moves};decrement_degree([Node|Nodes], IG, Worklists, Moves, K) ->  PrevDegree = hipe_ig:get_node_degree(Node, IG),  IG0 = hipe_ig:dec_node_degree(Node, IG),  if PrevDegree =:= K ->      AdjList = hipe_ig:node_adj_list(Node, IG0),      %% Ok since Node (a) is still in IG, and (b) cannot be adjacent to itself      Moves00 = enable_moves_active_to_worklist(hipe_moves:node_movelist(Node, Moves),						Moves),      Moves0 = enable_moves(AdjList, Worklists, Moves00),      Worklists0 = hipe_reg_worklists:remove_spill(Node, Worklists),      case hipe_moves:move_related(Node, Moves0) of	true ->	  Worklists1 = hipe_reg_worklists:add_freeze(Node, Worklists0),	  decrement_degree(Nodes, IG0, Worklists1, Moves0, K);	_ ->	  Worklists1 = hipe_reg_worklists:add_simplify(Node, Worklists0),	  decrement_degree(Nodes, IG0, Worklists1, Moves0, K)      end;     true ->      decrement_degree(Nodes, IG0, Worklists, Moves, K)  end.	    %%----------------------------------------------------------------------%% Function:    enable_moves%%%% Description: Make (move-related) nodes that are not yet considered for%%               coalescing, ready for possible coalescing.%%               %% Parameters:%%   [Node|Nodes]   --  A list of move nodes%%   Moves          --  The moves data-structure%%%%   Returns: %%     An updated moves data-structure%%----------------------------------------------------------------------enable_moves([], _Worklists, Moves) -> Moves;enable_moves([Node|Nodes], Worklists, Moves) ->  case hipe_reg_worklists:member_stack_or_coalesced(Node, Worklists) of    true -> enable_moves(Nodes, Worklists, Moves);    _ ->      %% moveList[n] suffices since we're checking for activeMoves membership      Node_moves = hipe_moves:node_movelist(Node, Moves),      New_moves = enable_moves_active_to_worklist(Node_moves, Moves),      enable_moves(Nodes, Worklists, New_moves)  end.%%----------------------------------------------------------------------%% Function:    enable_moves_active_to_worklist%%%% Description: Make (move-related) nodes that are not yet considered for%%              coalescing, ready for possible coalescing.%%               %% Parameters:%%   [Node|Nodes]   --  A list of move nodes%%   Moves          --  The moves data structure%%%%   Returns: %%     An updated moves data structure%%----------------------------------------------------------------------enable_moves_active_to_worklist([], Moves) -> Moves;enable_moves_active_to_worklist([Node|Nodes], Moves) ->  NewMoves =    case hipe_moves:member_active(Node, Moves) of      true ->	hipe_moves:add_worklist(Node, hipe_moves:remove_active(Node, Moves));      _ ->	Moves    end,  enable_moves_active_to_worklist(Nodes, NewMoves).%% Build the namelists, these functions are fast hacks, they use knowledge %% about data representation that they shouldn't know, bad abstraction.build_namelist(NodeSets, Index, Alias, Color) ->  ?debug_msg("Building mapping\n",[]),  ?debug_msg("Vector to list\n",[]),  AliasList = build_alias_list(aliasToList(Alias),			       0,   %% The first temporary has index 0			       []), %% Accumulator  ?debug_msg("Alias list:~p\n",[AliasList]),  ?debug_msg("Coalesced\n",[]),  NL1 = build_coalescedlist(AliasList, Color, Alias, []),  ?debug_msg("Coalesced list:~p\n",[NL1]),  ?debug_msg("Regs\n",[]),  NL2 = build_reglist(hipe_node_sets:colored(NodeSets), Color, NL1),  ?debug_msg("Regs list:~p\n",[NL2]),  ?debug_msg("Spills\n",[]),  build_spillist(hipe_node_sets:spilled(NodeSets), Index, NL2).build_spillist([], Index, List) ->  {List,Index};build_spillist([Node|Nodes], Index, List) ->  ?debug_msg("[~p]: Spill ~p to ~p\n", [?MODULE,Node,Index]),  build_spillist(Nodes, Index+1, [{Node,{spill,Index}}|List]).build_coalescedlist([], _Color, _Alias, List) ->  List;build_coalescedlist([Node|Ns], Color, Alias, List) when is_integer(Node) ->  ?debug_msg("Alias of ~p is ~p~n", [Node, getAlias(Node,Alias)]),  AC = getColor(getAlias(Node, Alias), Color),  build_coalescedlist(Ns, Color, Alias, [{Node,{reg,AC}}|List]).build_reglist([],_Color,List) ->   List;build_reglist([Node|Ns],Color,List) ->  build_reglist(Ns,Color,[{Node,{reg,getColor(Node,Color)}}|List]).build_alias_list([],_I,List) ->  List;build_alias_list([Alias|Aliases],I,List) when is_integer(Alias) ->  build_alias_list(Aliases,I+1,[I|List]);build_alias_list([_Alias|Aliases],I,List) ->  build_alias_list(Aliases,I+1,List).%%----------------------------------------------------------------------%% Function:    assignColors%%%% Description: Tries to assign colors to nodes in a stack.%% Parameters:%%   Stack          --  The SelectStack built by the Select function, %%                      this stack contains tuples in the form {Node,Edges} %%                      where  Node is the Node number and Edges is an ordset %%                      containing the numbers of all the adjacent nodes.%%   NodeSets       --  This is a record containing all the different node %%                      sets that are used in the register allocator.%%   Alias          --  This is a mapping from nodes to nodes, if a node has %%                      been coalesced this mapping shows the alias for that %%                      node.%%   AllColors      --  This is an ordset containing all the available colors%%%%   Target         --  The module containing the target-specific functions.%%

⌨️ 快捷键说明

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