aboutsummaryrefslogtreecommitdiffstats
path: root/lib/hipe/regalloc
diff options
context:
space:
mode:
authorMagnus Lång <[email protected]>2016-09-05 14:55:01 +0200
committerMagnus Lång <[email protected]>2016-09-05 19:17:50 +0200
commitea710644b198f7800f0daf2de0d152cf8e3e9bb3 (patch)
tree46842f5dab3fcdbb4055d11ee55c28506eeac7fc /lib/hipe/regalloc
parent1039c0196a7e643c63ce71b2c6daa2b78b3aa832 (diff)
downloadotp-ea710644b198f7800f0daf2de0d152cf8e3e9bb3.tar.gz
otp-ea710644b198f7800f0daf2de0d152cf8e3e9bb3.tar.bz2
otp-ea710644b198f7800f0daf2de0d152cf8e3e9bb3.zip
hipe: Refactor ra callbacks to accept context arg
This allows us to pass around the context data that hipe_regalloc_prepass needs cleanly, without using process dictionary or parameterised modules (like it was previous to this change).
Diffstat (limited to 'lib/hipe/regalloc')
-rw-r--r--lib/hipe/regalloc/hipe_amd64_specific_sse2.erl148
-rw-r--r--lib/hipe/regalloc/hipe_arm_specific.erl126
-rw-r--r--lib/hipe/regalloc/hipe_coalescing_regalloc.erl49
-rw-r--r--lib/hipe/regalloc/hipe_graph_coloring_regalloc.erl62
-rw-r--r--lib/hipe/regalloc/hipe_ig.erl108
-rw-r--r--lib/hipe/regalloc/hipe_ls_regalloc.erl83
-rw-r--r--lib/hipe/regalloc/hipe_optimistic_regalloc.erl136
-rw-r--r--lib/hipe/regalloc/hipe_ppc_specific.erl126
-rw-r--r--lib/hipe/regalloc/hipe_ppc_specific_fp.erl120
-rw-r--r--lib/hipe/regalloc/hipe_reg_worklists.erl31
-rw-r--r--lib/hipe/regalloc/hipe_regalloc_loop.erl48
-rw-r--r--lib/hipe/regalloc/hipe_regalloc_prepass.erl325
-rw-r--r--lib/hipe/regalloc/hipe_sparc_specific.erl126
-rw-r--r--lib/hipe/regalloc/hipe_sparc_specific_fp.erl120
-rw-r--r--lib/hipe/regalloc/hipe_temp_map.erl28
-rw-r--r--lib/hipe/regalloc/hipe_x86_specific.erl132
-rw-r--r--lib/hipe/regalloc/hipe_x86_specific_x87.erl100
17 files changed, 1008 insertions, 860 deletions
diff --git a/lib/hipe/regalloc/hipe_amd64_specific_sse2.erl b/lib/hipe/regalloc/hipe_amd64_specific_sse2.erl
index dec7c1734d..890df1b81a 100644
--- a/lib/hipe/regalloc/hipe_amd64_specific_sse2.erl
+++ b/lib/hipe/regalloc/hipe_amd64_specific_sse2.erl
@@ -21,47 +21,47 @@
-module(hipe_amd64_specific_sse2).
--export([number_of_temporaries/1]).
+-export([number_of_temporaries/2]).
% The following exports are used as M:F(...) calls from other modules;
%% e.g. hipe_amd64_ra_ls.
--export([analyze/1,
- bb/2,
- args/1,
- labels/1,
- livein/2,
- liveout/2,
- uses/1,
- defines/1,
- defines_all_alloc/1,
- def_use/1,
- is_arg/1, %% used by hipe_ls_regalloc
- is_move/1,
- is_fixed/1, %% used by hipe_graph_coloring_regalloc
- is_global/1,
- is_precoloured/1,
- reg_nr/1,
- non_alloc/1,
- allocatable/0,
+-export([analyze/2,
+ bb/3,
+ args/2,
+ labels/2,
+ livein/3,
+ liveout/3,
+ uses/2,
+ defines/2,
+ defines_all_alloc/2,
+ def_use/2,
+ is_arg/2, %% used by hipe_ls_regalloc
+ is_move/2,
+ is_fixed/2, %% used by hipe_graph_coloring_regalloc
+ is_global/2,
+ is_precoloured/2,
+ reg_nr/2,
+ non_alloc/2,
allocatable/1,
- temp0/0,
- physical_name/1,
- all_precoloured/0,
- new_spill_index/1, %% used by hipe_ls_regalloc
- var_range/1,
- breadthorder/1,
- postorder/1,
- reverse_postorder/1]).
+ allocatable/2,
+ temp0/1,
+ physical_name/2,
+ all_precoloured/1,
+ new_spill_index/2, %% used by hipe_ls_regalloc
+ var_range/2,
+ breadthorder/2,
+ postorder/2,
+ reverse_postorder/2]).
%% callbacks for hipe_regalloc_loop
--export([check_and_rewrite/2,
- check_and_rewrite/3]).
+-export([check_and_rewrite/3,
+ check_and_rewrite/4]).
%% callbacks for hipe_regalloc_prepass
--export([new_reg_nr/0,
- update_reg_nr/2,
- update_bb/3,
- subst_temps/2]).
+-export([new_reg_nr/1,
+ update_reg_nr/3,
+ update_bb/4,
+ subst_temps/3]).
%%----------------------------------------------------------------------------
@@ -69,99 +69,99 @@
%%----------------------------------------------------------------------------
-check_and_rewrite(CFG, Coloring) ->
+check_and_rewrite(CFG, Coloring, no_context) ->
hipe_amd64_ra_sse2_postconditions:check_and_rewrite(CFG, Coloring).
-check_and_rewrite(CFG, Coloring, Strategy) ->
+check_and_rewrite(CFG, Coloring, Strategy, no_context) ->
hipe_amd64_ra_sse2_postconditions:check_and_rewrite(
CFG, Coloring, Strategy).
-reverse_postorder(CFG) ->
+reverse_postorder(CFG, _) ->
hipe_x86_cfg:reverse_postorder(CFG).
-breadthorder(CFG) ->
+breadthorder(CFG, _) ->
hipe_x86_cfg:breadthorder(CFG).
-postorder(CFG) ->
+postorder(CFG, _) ->
hipe_x86_cfg:postorder(CFG).
-is_global(Reg) ->
+is_global(Reg, _) ->
hipe_amd64_registers:sse2_temp0() =:= Reg.
-is_fixed(_Reg) ->
+is_fixed(_Reg, _) ->
false.
-is_arg(_Reg) ->
+is_arg(_Reg, _) ->
false.
--spec args(#cfg{}) -> [].
-args(_CFG) ->
+-spec args(#cfg{}, no_context) -> [].
+args(_CFG, _) ->
[].
-non_alloc(_) ->
+non_alloc(_, _) ->
[].
%% Liveness stuff
-analyze(CFG) ->
+analyze(CFG, _) ->
hipe_amd64_liveness:analyze(CFG).
-livein(Liveness, L) ->
+livein(Liveness, L, _) ->
[X || X <- hipe_amd64_liveness:livein(Liveness, L),
hipe_x86:temp_is_allocatable(X),
hipe_x86:temp_type(X) =:= 'double'].
-liveout(BB_in_out_liveness, Label) ->
+liveout(BB_in_out_liveness, Label, _) ->
[X || X <- hipe_amd64_liveness:liveout(BB_in_out_liveness, Label),
hipe_x86:temp_is_allocatable(X),
hipe_x86:temp_type(X) =:= 'double'].
%% Registers stuff
-allocatable() ->
- allocatable('normal').
+allocatable(Ctx) ->
+ allocatable('normal', Ctx).
-allocatable('normal') ->
+allocatable('normal', _) ->
hipe_amd64_registers:allocatable_sse2();
-allocatable('linearscan') ->
+allocatable('linearscan', _) ->
hipe_amd64_registers:allocatable_sse2() --
[hipe_amd64_registers:sse2_temp0()].
-temp0() ->
+temp0(_) ->
hipe_amd64_registers:sse2_temp0().
-all_precoloured() ->
- allocatable().
+all_precoloured(Ctx) ->
+ allocatable(Ctx).
-is_precoloured(Reg) ->
- lists:member(Reg,all_precoloured()).
+is_precoloured(Reg, Ctx) ->
+ lists:member(Reg,all_precoloured(Ctx)).
-physical_name(Reg) ->
+physical_name(Reg, _) ->
Reg.
%% CFG stuff
-labels(CFG) ->
+labels(CFG, _) ->
hipe_x86_cfg:labels(CFG).
-var_range(_CFG) ->
+var_range(_CFG, _) ->
hipe_gensym:var_range(x86).
--spec number_of_temporaries(#cfg{}) -> non_neg_integer().
-number_of_temporaries(_CFG) ->
+-spec number_of_temporaries(#cfg{}, no_context) -> non_neg_integer().
+number_of_temporaries(_CFG, _) ->
Highest_temporary = hipe_gensym:get_var(x86),
%% Since we can have temps from 0 to Max adjust by +1.
Highest_temporary + 1.
-bb(CFG, L) ->
+bb(CFG, L, _) ->
hipe_x86_cfg:bb(CFG, L).
-update_bb(CFG,L,BB) ->
+update_bb(CFG,L,BB,_) ->
hipe_x86_cfg:bb_add(CFG,L,BB).
%% AMD64 stuff
-def_use(Instruction) ->
+def_use(Instruction, _) ->
{[X || X <- hipe_amd64_defuse:insn_def(Instruction),
hipe_x86:temp_is_allocatable(X),
hipe_x86:temp_type(X) =:= 'double'],
@@ -170,19 +170,19 @@ def_use(Instruction) ->
hipe_x86:temp_type(X) =:= 'double']
}.
-uses(I) ->
+uses(I, _) ->
[X || X <- hipe_amd64_defuse:insn_use(I),
hipe_x86:temp_is_allocatable(X),
hipe_x86:temp_type(X) =:= 'double'].
-defines(I) ->
+defines(I, _) ->
[X || X <- hipe_amd64_defuse:insn_def(I),
hipe_x86:temp_is_allocatable(X),
hipe_x86:temp_type(X) =:= 'double'].
-defines_all_alloc(I) -> hipe_amd64_defuse:insn_defs_all(I).
+defines_all_alloc(I, _) -> hipe_amd64_defuse:insn_defs_all(I).
-is_move(Instruction) ->
+is_move(Instruction, _) ->
case hipe_x86:is_fmove(Instruction) of
true ->
Src = hipe_x86:fmove_src(Instruction),
@@ -192,16 +192,16 @@ is_move(Instruction) ->
false -> false
end.
-reg_nr(Reg) ->
+reg_nr(Reg, _) ->
hipe_x86:temp_reg(Reg).
-new_reg_nr() ->
+new_reg_nr(_) ->
hipe_gensym:get_next_var(x86).
-update_reg_nr(Nr, _Temp) ->
+update_reg_nr(Nr, _Temp, _) ->
hipe_x86:mk_temp(Nr, 'double').
-subst_temps(SubstFun, Instr) ->
+subst_temps(SubstFun, Instr, _) ->
hipe_amd64_subst:insn_temps(
fun(Op) ->
case hipe_x86:temp_is_allocatable(Op)
@@ -212,6 +212,6 @@ subst_temps(SubstFun, Instr) ->
end
end, Instr).
--spec new_spill_index(non_neg_integer()) -> pos_integer().
-new_spill_index(SpillIndex) when is_integer(SpillIndex) ->
+-spec new_spill_index(non_neg_integer(), no_context) -> pos_integer().
+new_spill_index(SpillIndex, _) when is_integer(SpillIndex) ->
SpillIndex + 1.
diff --git a/lib/hipe/regalloc/hipe_arm_specific.erl b/lib/hipe/regalloc/hipe_arm_specific.erl
index 251f1f7361..06ab17b0e9 100644
--- a/lib/hipe/regalloc/hipe_arm_specific.erl
+++ b/lib/hipe/regalloc/hipe_arm_specific.erl
@@ -22,123 +22,123 @@
-module(hipe_arm_specific).
%% for hipe_coalescing_regalloc:
--export([number_of_temporaries/1
- ,analyze/1
- ,labels/1
- ,all_precoloured/0
- ,bb/2
- ,liveout/2
- ,reg_nr/1
- ,def_use/1
- ,is_move/1
- ,is_precoloured/1
- ,var_range/1
- ,allocatable/0
- ,non_alloc/1
- ,physical_name/1
- ,reverse_postorder/1
- ,livein/2
- ,uses/1
- ,defines/1
- ,defines_all_alloc/1
+-export([number_of_temporaries/2
+ ,analyze/2
+ ,labels/2
+ ,all_precoloured/1
+ ,bb/3
+ ,liveout/3
+ ,reg_nr/2
+ ,def_use/2
+ ,is_move/2
+ ,is_precoloured/2
+ ,var_range/2
+ ,allocatable/1
+ ,non_alloc/2
+ ,physical_name/2
+ ,reverse_postorder/2
+ ,livein/3
+ ,uses/2
+ ,defines/2
+ ,defines_all_alloc/2
]).
%% for hipe_graph_coloring_regalloc:
--export([is_fixed/1]).
+-export([is_fixed/2]).
%% for hipe_ls_regalloc:
--export([args/1, is_arg/1, is_global/1, new_spill_index/1]).
--export([breadthorder/1, postorder/1]).
+-export([args/2, is_arg/2, is_global/2, new_spill_index/2]).
+-export([breadthorder/2, postorder/2]).
%% callbacks for hipe_regalloc_loop
--export([check_and_rewrite/2]).
+-export([check_and_rewrite/3]).
%% callbacks for hipe_regalloc_prepass
--export([new_reg_nr/0,
- update_reg_nr/2,
- update_bb/3,
- subst_temps/2]).
+-export([new_reg_nr/1,
+ update_reg_nr/3,
+ update_bb/4,
+ subst_temps/3]).
-check_and_rewrite(CFG, Coloring) ->
+check_and_rewrite(CFG, Coloring, no_context) ->
hipe_arm_ra_postconditions:check_and_rewrite(CFG, Coloring, 'normal').
-reverse_postorder(CFG) ->
+reverse_postorder(CFG, _) ->
hipe_arm_cfg:reverse_postorder(CFG).
-non_alloc(CFG) ->
- non_alloc(hipe_arm_registers:nr_args(), hipe_arm_cfg:params(CFG)).
+non_alloc(CFG, no_context) ->
+ non_alloc_1(hipe_arm_registers:nr_args(), hipe_arm_cfg:params(CFG)).
%% same as hipe_arm_frame:fix_formals/2
-non_alloc(0, Rest) -> Rest;
-non_alloc(N, [_|Rest]) -> non_alloc(N-1, Rest);
-non_alloc(_, []) -> [].
+non_alloc_1(0, Rest) -> Rest;
+non_alloc_1(N, [_|Rest]) -> non_alloc_1(N-1, Rest);
+non_alloc_1(_, []) -> [].
%% Liveness stuff
-analyze(CFG) ->
+analyze(CFG, _) ->
hipe_arm_liveness_gpr:analyse(CFG).
-livein(Liveness,L) ->
+livein(Liveness,L,_) ->
[X || X <- hipe_arm_liveness_gpr:livein(Liveness,L),
hipe_arm:temp_is_allocatable(X)].
-liveout(BB_in_out_liveness,Label) ->
+liveout(BB_in_out_liveness,Label,_) ->
[X || X <- hipe_arm_liveness_gpr:liveout(BB_in_out_liveness,Label),
hipe_arm:temp_is_allocatable(X)].
%% Registers stuff
-allocatable() ->
+allocatable(no_context) ->
hipe_arm_registers:allocatable_gpr().
-all_precoloured() ->
+all_precoloured(no_context) ->
hipe_arm_registers:all_precoloured().
-is_precoloured(Reg) ->
+is_precoloured(Reg, _) ->
hipe_arm_registers:is_precoloured_gpr(Reg).
-is_fixed(R) ->
+is_fixed(R, _) ->
hipe_arm_registers:is_fixed(R).
-physical_name(Reg) ->
+physical_name(Reg, _) ->
Reg.
%% CFG stuff
-labels(CFG) ->
+labels(CFG, _) ->
hipe_arm_cfg:labels(CFG).
-var_range(_CFG) ->
+var_range(_CFG, _) ->
hipe_gensym:var_range(arm).
-number_of_temporaries(_CFG) ->
+number_of_temporaries(_CFG, _) ->
Highest_temporary = hipe_gensym:get_var(arm),
%% Since we can have temps from 0 to Max adjust by +1.
Highest_temporary + 1.
-bb(CFG,L) ->
+bb(CFG,L,_) ->
hipe_arm_cfg:bb(CFG,L).
-update_bb(CFG,L,BB) ->
+update_bb(CFG,L,BB,_) ->
hipe_arm_cfg:bb_add(CFG,L,BB).
%% ARM stuff
-def_use(Instruction) ->
- {defines(Instruction), uses(Instruction)}.
+def_use(Instruction, Ctx) ->
+ {defines(Instruction, Ctx), uses(Instruction, Ctx)}.
-uses(I) ->
+uses(I, _) ->
[X || X <- hipe_arm_defuse:insn_use_gpr(I),
hipe_arm:temp_is_allocatable(X)].
-defines(I) ->
+defines(I, _) ->
[X || X <- hipe_arm_defuse:insn_def_gpr(I),
hipe_arm:temp_is_allocatable(X)].
-defines_all_alloc(I) ->
+defines_all_alloc(I, _) ->
hipe_arm_defuse:insn_defs_all_gpr(I).
-is_move(Instruction) ->
+is_move(Instruction, _) ->
case hipe_arm:is_pseudo_move(Instruction) of
true ->
Dst = hipe_arm:pseudo_move_dst(Instruction),
@@ -151,16 +151,16 @@ is_move(Instruction) ->
false -> false
end.
-reg_nr(Reg) ->
+reg_nr(Reg, _) ->
hipe_arm:temp_reg(Reg).
-new_reg_nr() ->
+new_reg_nr(_) ->
hipe_gensym:get_next_var(arm).
-update_reg_nr(Nr, Temp) ->
+update_reg_nr(Nr, Temp, _) ->
hipe_arm:mk_temp(Nr, hipe_arm:temp_type(Temp)).
-subst_temps(SubstFun, Instr) ->
+subst_temps(SubstFun, Instr, _) ->
hipe_arm_subst:insn_temps(
fun(Op) ->
case hipe_arm:temp_is_allocatable(Op) of
@@ -171,23 +171,23 @@ subst_temps(SubstFun, Instr) ->
%%% Linear Scan stuff
-new_spill_index(SpillIndex) when is_integer(SpillIndex) ->
+new_spill_index(SpillIndex, _) when is_integer(SpillIndex) ->
SpillIndex+1.
-breadthorder(CFG) ->
+breadthorder(CFG, _) ->
hipe_arm_cfg:breadthorder(CFG).
-postorder(CFG) ->
+postorder(CFG, _) ->
hipe_arm_cfg:postorder(CFG).
-is_global(R) ->
+is_global(R, _) ->
R =:= hipe_arm_registers:temp1() orelse
R =:= hipe_arm_registers:temp2() orelse
R =:= hipe_arm_registers:temp3() orelse
hipe_arm_registers:is_fixed(R).
-is_arg(R) ->
+is_arg(R, _) ->
hipe_arm_registers:is_arg(R).
-args(CFG) ->
+args(CFG, _) ->
hipe_arm_registers:args(hipe_arm_cfg:arity(CFG)).
diff --git a/lib/hipe/regalloc/hipe_coalescing_regalloc.erl b/lib/hipe/regalloc/hipe_coalescing_regalloc.erl
index 5f4bd4e524..00bfbaa1b6 100644
--- a/lib/hipe/regalloc/hipe_coalescing_regalloc.erl
+++ b/lib/hipe/regalloc/hipe_coalescing_regalloc.erl
@@ -30,7 +30,7 @@
%%-----------------------------------------------------------------------
-module(hipe_coalescing_regalloc).
--export([regalloc/6]).
+-export([regalloc/7]).
%%-ifndef(DEBUG).
%%-define(DEBUG,true).
@@ -54,16 +54,18 @@
%% SpillIndex2 -- A new spill index
%%-----------------------------------------------------------------------
-regalloc(CFG, Liveness, SpillIndex, SpillLimit, Target, _Options) ->
+regalloc(CFG, Liveness, SpillIndex, SpillLimit, TargetMod, TargetContext,
+ _Options) ->
+ Target = {TargetMod, TargetContext},
%% Build interference graph
?debug_msg("Build IG\n", []),
- IG = hipe_ig:build(CFG, Liveness, Target),
+ IG = hipe_ig:build(CFG, Liveness, TargetMod, TargetContext),
%% io:format("IG: ~p\n", [IG]),
?debug_msg("Init\n", []),
- Num_Temps = Target:number_of_temporaries(CFG),
+ Num_Temps = TargetMod:number_of_temporaries(CFG,TargetContext),
?debug_msg("Coalescing RA: num_temps = ~p~n", [Num_Temps]),
- Allocatable = Target:allocatable(),
+ Allocatable = TargetMod:allocatable(TargetContext),
K = length(Allocatable),
All_colors = colset_from_list(Allocatable),
@@ -72,7 +74,8 @@ regalloc(CFG, Liveness, SpillIndex, SpillLimit, Target, _Options) ->
Move_sets = hipe_moves:new(IG),
?debug_msg("Build Worklist\n", []),
- Worklists = hipe_reg_worklists:new(IG, Target, CFG, Move_sets, K, Num_Temps),
+ Worklists = hipe_reg_worklists:new(IG, TargetMod, TargetContext, CFG,
+ Move_sets, K, Num_Temps),
Alias = initAlias(Num_Temps),
?debug_msg("Do coloring\n~p~n", [Worklists]),
@@ -81,10 +84,10 @@ regalloc(CFG, Liveness, SpillIndex, SpillLimit, Target, _Options) ->
%% 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)]),
+ %% io:format("NodeSet: ~w\n NonAlloc ~w\n",[Node_sets,non_alloc(CFG,Target)]),
?debug_msg("Default coloring\n", []),
{Color0,Node_sets1} =
- defaultColoring(Target:all_precoloured(),
+ defaultColoring(TargetMod:all_precoloured(TargetContext),
initColor(Num_Temps), Node_sets, Target),
?debug_msg("Assign colors\n", []),
@@ -380,7 +383,7 @@ assignColors(Stack, NodeSets, Color, Alias, AllColors, Target) ->
false -> % Colour case
Col = colset_smallest(OkColors),
NodeSets1 = hipe_node_sets:add_colored(Node, NodeSets),
- Color1 = setColor(Node, Target:physical_name(Col), Color),
+ Color1 = setColor(Node, physical_name(Col,Target), Color),
assignColors(Stack1, NodeSets1, Color1, Alias, AllColors, Target)
end
end.
@@ -403,7 +406,7 @@ assignColors(Stack, NodeSets, Color, Alias, AllColors, Target) ->
defaultColoring([], Color, NodeSets, _Target) ->
{Color,NodeSets};
defaultColoring([Reg|Regs], Color, NodeSets, Target) ->
- Color1 = setColor(Reg,Target:physical_name(Reg), Color),
+ Color1 = setColor(Reg,physical_name(Reg,Target), Color),
NodeSets1 = hipe_node_sets:add_colored(Reg, NodeSets),
defaultColoring(Regs, Color1, NodeSets1, Target).
@@ -568,7 +571,7 @@ coalesce(Moves, IG, Worklists, Alias, K, Target) ->
?debug_msg("Testing nodes ~p and ~p for coalescing~n",[Dest,Source]),
Alias_src = getAlias(Source, Alias),
Alias_dst = getAlias(Dest, Alias),
- {U,V} = case Target:is_precoloured(Alias_dst) of
+ {U,V} = case is_precoloured(Alias_dst,Target) of
true -> {Alias_dst, Alias_src};
false -> {Alias_src, Alias_dst}
end,
@@ -578,7 +581,7 @@ coalesce(Moves, IG, Worklists, Alias, K, Target) ->
Worklists1 = add_worklist(Worklists, U, K, Moves1, IG, Target),
{Moves1, IG, Worklists1, Alias};
true ->
- case (Target:is_precoloured(V) orelse
+ case (is_precoloured(V,Target) orelse
hipe_ig:nodes_are_adjacent(U, V, IG)) of
true ->
Moves1 = Moves0, % drop constrained move Move
@@ -586,7 +589,7 @@ coalesce(Moves, IG, Worklists, Alias, K, Target) ->
Worklists2 = add_worklist(Worklists1, V, K, Moves1, IG, Target),
{Moves1, IG, Worklists2, Alias};
false ->
- case (case Target:is_precoloured(U) of
+ case (case is_precoloured(U,Target) of
true ->
AdjV = hipe_ig:node_adj_list(V, IG),
all_adjacent_ok(AdjV, U, Worklists, IG, K, Target);
@@ -628,7 +631,7 @@ coalesce(Moves, IG, Worklists, Alias, K, Target) ->
%%----------------------------------------------------------------------
add_worklist(Worklists, U, K, Moves, IG, Target) ->
- case (not(Target:is_precoloured(U))
+ case (not(is_precoloured(U,Target))
andalso not(hipe_moves:move_related(U, Moves))
andalso (hipe_ig:is_trivially_colourable(U, K, IG))) of
true ->
@@ -712,7 +715,7 @@ combine(U, V, IG, Worklists, Moves, Alias, K, Target) ->
combine_edges([], _U, IG, Worklists, Moves, _K, _Target) ->
{IG, Worklists, Moves};
-combine_edges([T|Ts], U, IG, Worklists, Moves, K, Target) ->
+combine_edges([T|Ts], U, IG, Worklists, Moves, K, Target={TgtMod,TgtCtx}) ->
case hipe_reg_worklists:member_stack_or_coalesced(T, Worklists) of
true -> combine_edges(Ts, U, IG, Worklists, Moves, K, Target);
_ ->
@@ -729,7 +732,7 @@ combine_edges([T|Ts], U, IG, Worklists, Moves, K, Target) ->
%% worklist, and that's where decrement_degree() expects to find it.
%% This issue is not covered in the published algorithm.
OldDegree = hipe_ig:get_node_degree(T, IG),
- IG1 = hipe_ig:add_edge(T, U, IG, Target),
+ IG1 = hipe_ig:add_edge(T, U, IG, TgtMod, TgtCtx),
NewDegree = hipe_ig:get_node_degree(T, IG1),
Worklists0 =
if NewDegree =:= K, OldDegree =:= K-1 ->
@@ -768,7 +771,7 @@ combine_edges([T|Ts], U, IG, Worklists, Moves, K, Target) ->
ok(T, R, IG, K, Target) ->
((hipe_ig:is_trivially_colourable(T, K, IG))
- orelse Target:is_precoloured(T)
+ orelse is_precoloured(T,Target)
orelse hipe_ig:nodes_are_adjacent(T, R, IG)).
%%----------------------------------------------------------------------
@@ -1029,3 +1032,15 @@ freezeEm3(_U, V, _M, K, WorkLists, Moves, IG, _Alias) ->
false ->
{WorkLists, Moves1}
end.
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%%
+%% Interface to external functions.
+%%
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+is_precoloured(R, {TgtMod,TgtCtx}) ->
+ TgtMod:is_precoloured(R,TgtCtx).
+
+physical_name(R, {TgtMod,TgtCtx}) ->
+ TgtMod:physical_name(R,TgtCtx).
diff --git a/lib/hipe/regalloc/hipe_graph_coloring_regalloc.erl b/lib/hipe/regalloc/hipe_graph_coloring_regalloc.erl
index 225f06bded..e91734d8be 100644
--- a/lib/hipe/regalloc/hipe_graph_coloring_regalloc.erl
+++ b/lib/hipe/regalloc/hipe_graph_coloring_regalloc.erl
@@ -51,7 +51,7 @@
%%
-module(hipe_graph_coloring_regalloc).
--export([regalloc/6]).
+-export([regalloc/7]).
%%-ifndef(DO_ASSERT).
%%-define(DO_ASSERT, true).
@@ -78,10 +78,12 @@
%% no neighbors have the same register or spill location).
%% @spec regalloc(#cfg{}, liveness(), non_neg_fixnum(), non_neg_fixnum(),
-%% atom(), list()) -> {, non_neg_fixnum()}
+%% module(), tgt_ctx(), list()) -> {, non_neg_fixnum()}
-regalloc(CFG, Live, SpillIndex, SpillLimit, Target, _Options) ->
- PhysRegs = Target:allocatable(),
+regalloc(CFG, Live, SpillIndex, SpillLimit, TargetMod, TargetContext,
+ _Options) ->
+ Target = {TargetMod, TargetContext},
+ PhysRegs = allocatable(Target),
?report2("building IG~n", []),
{IG, Spill} = build_ig(CFG, Live, Target),
@@ -89,7 +91,7 @@ regalloc(CFG, Live, SpillIndex, SpillLimit, Target, _Options) ->
?report3("graph: ~p~nphysical regs: ~p~n", [list_ig(IG), PhysRegs]),
%% These nodes *can't* be allocated to registers.
- NotAllocatable = [Target:reg_nr(X) || X <- Target:non_alloc(CFG)],
+ NotAllocatable = non_alloc(CFG, Target),
%% i.e. Arguments on x86
?report2("Nonalloc ~w~n", [NotAllocatable]),
@@ -98,7 +100,7 @@ regalloc(CFG, Live, SpillIndex, SpillLimit, Target, _Options) ->
ordsets:from_list(PhysRegs),
SpillIndex,
SpillLimit,
- Target:number_of_temporaries(CFG),
+ number_of_temporaries(CFG, Target),
Target, NotAllocatable),
Coloring = [{X, {reg, X}} || X <- NotAllocatable] ++ Cols,
?ASSERT(check_coloring(Coloring, IG, Target)),
@@ -114,8 +116,8 @@ regalloc(CFG, Live, SpillIndex, SpillLimit, Target, _Options) ->
%%
build_ig(CFG, Live, Target) ->
- NumN = Target:number_of_temporaries(CFG), % poss. N-1?
- {IG, Spill} = build_ig_bbs(Target:labels(CFG),
+ NumN = number_of_temporaries(CFG, Target), % poss. N-1?
+ {IG, Spill} = build_ig_bbs(labels(CFG, Target),
CFG,
Live,
empty_ig(NumN),
@@ -220,7 +222,7 @@ color(IG, Spill, PhysRegs, SpillIx, SpillLimit, NumNodes, Target,
?report(" starting with low degree nodes ~p~n",[Low]),
EmptyStk = [],
- Precolored = Target:all_precoloured(),
+ Precolored = all_precoloured(Target),
{Stk, NewSpillIx} =
simplify(Low, NumNodes, Precolored,
IG, Spill, K, SpillIx, EmptyStk,
@@ -401,7 +403,7 @@ spill_costs([{N,Info}|Ns], IG, Vis, Spill, SpillLimit, Target) ->
true ->
spill_costs(Ns,IG,Vis,Spill, SpillLimit, Target);
_ ->
- case Target:is_fixed(N) of
+ case is_fixed(N, Target) of
true ->
spill_costs(Ns, IG, Vis, Spill, SpillLimit, Target);
false ->
@@ -758,18 +760,36 @@ valid_coloring(X, C, [_|Ys]) ->
%% *** INTERFACES TO OTHER MODULES ***
%%
-liveout(CFG, L, Target) ->
- ordsets:from_list(reg_names(Target:liveout(CFG, L), Target)).
+all_precoloured({TgtMod,TgtCtx}) ->
+ TgtMod:all_precoloured(TgtCtx).
-bb(CFG, L, Target) ->
- hipe_bb:code(Target:bb(CFG, L)).
+allocatable({TgtMod,TgtCtx}) ->
+ TgtMod:allocatable(TgtCtx).
-def_use(X, Target) ->
- {ordsets:from_list(reg_names(Target:defines(X), Target)),
- ordsets:from_list(reg_names(Target:uses(X), Target))}.
+is_fixed(Reg, {TgtMod,TgtCtx}) ->
+ TgtMod:is_fixed(Reg, TgtCtx).
-reg_names(Regs, Target) ->
- [Target:reg_nr(X) || X <- Regs].
+labels(CFG, {TgtMod,TgtCtx}) ->
+ TgtMod:labels(CFG, TgtCtx).
+
+liveout(CFG, L, Target={TgtMod,TgtCtx}) ->
+ ordsets:from_list(reg_names(TgtMod:liveout(CFG, L, TgtCtx), Target)).
+
+bb(CFG, L, {TgtMod,TgtCtx}) ->
+ hipe_bb:code(TgtMod:bb(CFG, L, TgtCtx)).
+
+def_use(X, Target={TgtMod,TgtCtx}) ->
+ {ordsets:from_list(reg_names(TgtMod:defines(X,TgtCtx), Target)),
+ ordsets:from_list(reg_names(TgtMod:uses(X,TgtCtx), Target))}.
+
+non_alloc(CFG, Target={TgtMod,TgtCtx}) ->
+ reg_names(TgtMod:non_alloc(CFG, TgtCtx), Target).
+
+number_of_temporaries(CFG, {TgtMod,TgtCtx}) ->
+ TgtMod:number_of_temporaries(CFG, TgtCtx).
+
+reg_names(Regs, {TgtMod,TgtCtx}) ->
+ [TgtMod:reg_nr(X,TgtCtx) || X <- Regs].
%%
%% Precoloring: use this version when a proper implementation of
@@ -789,5 +809,5 @@ precolor0([R|Rs], Cols, Target) ->
{[{R, {reg, physical_name(R, Target)}}|Cs],
set_color(R, physical_name(R, Target), Cols1)}.
-physical_name(X, Target) ->
- Target:physical_name(X).
+physical_name(X, {TgtMod,TgtCtx}) ->
+ TgtMod:physical_name(X, TgtCtx).
diff --git a/lib/hipe/regalloc/hipe_ig.erl b/lib/hipe/regalloc/hipe_ig.erl
index 47f8f6d08d..81eee2e03c 100644
--- a/lib/hipe/regalloc/hipe_ig.erl
+++ b/lib/hipe/regalloc/hipe_ig.erl
@@ -28,7 +28,7 @@
-module(hipe_ig).
--export([build/3,
+-export([build/4,
nodes_are_adjacent/3,
node_spill_cost/2,
node_adj_list/2,
@@ -38,8 +38,8 @@
spill_costs/1,
adj_list/1,
%% adj_set/1,
- add_edge/4,
- remove_edge/4,
+ add_edge/5,
+ remove_edge/5,
%% set_adj_set/2,
%% set_adj_list/2,
%% set_ig_moves/2,
@@ -64,6 +64,9 @@
-include("../flow/cfg.hrl").
-include("hipe_spillcost.hrl").
+-type target_context() :: any().
+-type target() :: {TargetMod :: module(), TargetContext :: target_context()}.
+
%%----------------------------------------------------------------------
-record(igraph, {adj_set, adj_list, ig_moves, degree,
@@ -78,11 +81,11 @@
%% degree, and testing for trivial colourability (degree < K).
%%----------------------------------------------------------------------
-degree_new(No_temporaries, Target) ->
+degree_new(No_temporaries, {TargetMod, TargetCtx}) ->
Degree = hipe_bifs:array(No_temporaries, 0),
- K = length(Target:allocatable()),
+ K = length(TargetMod:allocatable(TargetCtx)),
Inf = K + No_temporaries,
- precoloured_to_inf_degree(Target:all_precoloured(), Inf, Degree).
+ precoloured_to_inf_degree(TargetMod:all_precoloured(TargetCtx), Inf, Degree).
precoloured_to_inf_degree([], _Inf, Degree) -> Degree;
precoloured_to_inf_degree([P|Ps], Inf, Degree) ->
@@ -344,7 +347,7 @@ set_spill_costs(Spill_costs, IG) -> IG#igraph{spill_costs = Spill_costs}.
%% A new interference record
%%----------------------------------------------------------------------
--spec initial_ig(non_neg_integer(), atom()) -> #igraph{}.
+-spec initial_ig(non_neg_integer(), target()) -> #igraph{}.
initial_ig(NumTemps, Target) ->
#igraph{adj_set = adjset_new(NumTemps),
@@ -361,19 +364,21 @@ initial_ig(NumTemps, Target) ->
%% Description: Constructs an interference graph for the specifyed CFG.
%%
%% Parameters:
-%% CFG -- A Control Flow Graph
-%% Target -- The module that contains the target-specific functions
+%% CFG -- A Control Flow Graph
+%% TargetMod -- The module that contains the target-specific functions
+%% TargetCtx -- Context data to pass to TargetMod
%%
%% Returns:
%% An interference graph for the given CFG.
%%----------------------------------------------------------------------
--spec build(#cfg{}, Liveness::_, atom()) -> #igraph{}.
+-spec build(#cfg{}, Liveness::_, module(), target_context()) -> #igraph{}.
-build(CFG, BBs_in_out_liveness, Target) ->
- Labels = Target:labels(CFG),
+build(CFG, BBs_in_out_liveness, TargetMod, TargetCtx) ->
+ Target = {TargetMod, TargetCtx},
+ Labels = TargetMod:labels(CFG, TargetCtx),
%% How many temporaries exist?
- NumTemps = Target:number_of_temporaries(CFG),
+ NumTemps = TargetMod:number_of_temporaries(CFG, TargetCtx),
IG0 = initial_ig(NumTemps, Target),
%%?debug_msg("initial adjset: ~p\n",[element(2, IG0)]),
%%?debug_msg("initial adjset array: ~.16b\n",[element(3, element(2, IG0))]),
@@ -394,7 +399,7 @@ build(CFG, BBs_in_out_liveness, Target) ->
%% CFG -- The Control Flow Graph that we constructs
%% the interference graph from.
%% Target -- The module containing the target-specific
-%% functions
+%% functions, along with its context data
%%
%% Returns:
%% An interference graph for the given CFG.
@@ -403,13 +408,11 @@ build(CFG, BBs_in_out_liveness, Target) ->
analyze_bbs([], _, IG, _, _) -> IG;
analyze_bbs([L|Ls], BBs_in_out_liveness, IG, CFG, Target) ->
% Get basic block associated with label L
- BB = Target:bb(CFG, L),
+ BB = bb(CFG, L, Target),
% Get basic block code
BB_code = hipe_bb:code(BB),
- % Temporaries that are live out from this basic block
- BB_liveout = Target:liveout(BBs_in_out_liveness, L),
- % Only temporary numbers
- BB_liveout_numbers = reg_numbers(BB_liveout, Target),
+ % Temporaries that are live out from this basic block, only numbers
+ BB_liveout_numbers = liveout(BBs_in_out_liveness, L, Target),
% {Liveness, New Interference Graph}
{_, New_ig, Ref} = analyze_bb_instructions(BB_code,
ordsets:from_list(BB_liveout_numbers),
@@ -432,7 +435,8 @@ analyze_bbs([L|Ls], BBs_in_out_liveness, IG, CFG, Target) ->
%% Live -- All temporaries that are live at the time.
%% Live is a set of temporary "numbers only".
%% IG -- The interference graph in it's current state
-%% Target -- The mopdule containing the target-specific functions
+%% Target -- The mopdule containing the target-specific functions,
+%% along with its context data.
%%
%% Returns:
%% Live -- Temporaries that are live at entery of basic block
@@ -448,7 +452,7 @@ analyze_bb_instructions([Instruction|Instructions], Live, IG, Target) ->
{Live0, IG0, Ref} = analyze_bb_instructions(Instructions, Live,
IG, Target),
%% Check for temporaries that are defined and used in instruction
- {Def, Use} = Target:def_use(Instruction),
+ {Def, Use} = def_use(Instruction, Target),
%% Convert to register numbers
Def_numbers = ordsets:from_list(reg_numbers(Def, Target)),
Use_numbers = ordsets:from_list(reg_numbers(Use, Target)),
@@ -500,14 +504,15 @@ analyze_bb_instructions([Instruction|Instructions], Live, IG, Target) ->
%% Def_numbers -- Temporaries that are defined at this instruction
%% Use_numbers -- Temporaries that are used at this instruction
%% IG -- The interference graph in its current state
-%% Target -- The module containing the target-specific functions
+%% Target -- The module containing the target-specific functions, along
+%% with its context data
%% Returns:
%% Live -- An updated live set
%% IG -- An updated interference graph
%%----------------------------------------------------------------------
analyze_move(Instruction, Live, Def_numbers, Use_numbers, IG, Target) ->
- case Target:is_move(Instruction) of
+ case is_move(Instruction,Target) of
true ->
case {Def_numbers, Use_numbers} of
{[Dst], [Src]} ->
@@ -553,8 +558,9 @@ interfere([Define|Defines], Living, IG, Target) ->
%% Live -- Current live set
%% Lives -- Rest of living temporaries.
%% IG -- An interference graph
-%% Target -- The module containing the target-specific functions
-%% Returns:
+%% Target -- The module containing the target-specific functions, along
+%% with its context data.
+%% Returns:
%% An updated interference graph
%%----------------------------------------------------------------------
@@ -622,11 +628,15 @@ get_moves(IG) ->
%% Parameters:
%% U -- A temporary number
%% V -- A temporary number
-%% Target -- The module containing the target-specific functions
+%% TargetMod -- The module containing the target-specific functions.
+%% TargetCtx -- Context data to pass to TargetMod
%% Returns:
%% An updated interference graph.
%%----------------------------------------------------------------------
+add_edge(U, V, IG, TargetMod, TargetCtx) ->
+ add_edge(U, V, IG, {TargetMod, TargetCtx}).
+
add_edge(U, U, IG, _) -> IG;
add_edge(U, V, IG, Target) ->
case nodes_are_adjacent(U, V, IG) of
@@ -651,11 +661,15 @@ add_edge(U, V, IG, Target) ->
%% Parameters:
%% U -- A temporary number
%% V -- A temporary number
-%% Target -- The module containing the target-specific functions
+%% TargetMod -- The module containing the target-specific functions.
+%% TargetCtx -- Context data for TargetMod.
%% Returns:
%% An updated interference graph.
%%----------------------------------------------------------------------
+remove_edge(U, V, IG, TargetMod, TargetCtx) ->
+ remove_edge(U, V, IG, {TargetMod, TargetCtx}).
+
remove_edge(U, U, IG, _) -> IG;
remove_edge(U, V, IG, Target) ->
case nodes_are_adjacent(U, V, IG) of
@@ -682,8 +696,8 @@ remove_edge(U, V, IG, Target) ->
%% precoloured.
%% Adj_list -- An adj_list
%% Degree -- The degree that all nodes currently have
-%% Target -- The module containing the target-specific
-%% functions
+%% Target -- The module containing the target-specific
+%% functions, along with its context data.
%%
%% Returns:
%% Adj_list -- An updated adj_list data structure
@@ -691,7 +705,7 @@ remove_edge(U, V, IG, Target) ->
%%----------------------------------------------------------------------
remove_if_uncolored(Temp, InterfereTemp, Adj_list, Degree, Target) ->
- case Target:is_precoloured(Temp) of
+ case is_precoloured(Temp,Target) of
false ->
New_adj_list = hipe_adj_list:remove_edge(Temp, InterfereTemp, Adj_list),
degree_dec(Temp, Degree),
@@ -713,8 +727,8 @@ remove_if_uncolored(Temp, InterfereTemp, Adj_list, Degree, Target) ->
%% precoloured.
%% Adj_list -- An adj_list
%% Degree -- The degree that all nodes currently have
-%% Target -- The module containing the target-specific
-%% functions
+%% Target -- The module containing the target-specific
+%% functions, along with its context data.
%%
%% Returns:
%% Adj_list -- An updated adj_list data structure
@@ -722,7 +736,7 @@ remove_if_uncolored(Temp, InterfereTemp, Adj_list, Degree, Target) ->
%%----------------------------------------------------------------------
interfere_if_uncolored(Temp, InterfereTemp, Adj_list, Degree, Target) ->
- case Target:is_precoloured(Temp) of
+ case is_precoloured(Temp, Target) of
false ->
New_adj_list = hipe_adj_list:add_edge(Temp, InterfereTemp, Adj_list),
degree_inc(Temp, Degree),
@@ -739,13 +753,14 @@ interfere_if_uncolored(Temp, InterfereTemp, Adj_list, Degree, Target) ->
%%
%% Parameters:
%% TRs -- A list of temporary registers
-%% Target -- The module containing the target-specific functions
+%% Target -- The module containing the target-specific functions, along with
+%% its context data.
%% Returns:
%% A list of register numbers.
%%----------------------------------------------------------------------
-reg_numbers(Regs, Target) ->
- [Target:reg_nr(X) || X <- Regs].
+reg_numbers(Regs, {TgtMod, TgtCtx}) ->
+ [TgtMod:reg_nr(X,TgtCtx) || X <- Regs].
%%---------------------------------------------------------------------
%% Print functions - only used for debugging
@@ -774,3 +789,24 @@ dec_node_degree(Node, IG) ->
is_trivially_colourable(Node, K, IG) ->
degree_is_trivially_colourable(Node, K, degree(IG)).
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%%
+%% Interface to external functions.
+%%
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+bb(CFG, L, {TgtMod,TgtCtx}) ->
+ TgtMod:bb(CFG,L,TgtCtx).
+
+def_use(Instruction, {TgtMod,TgtCtx}) ->
+ TgtMod:def_use(Instruction, TgtCtx).
+
+is_move(Instruction, {TgtMod,TgtCtx}) ->
+ TgtMod:is_move(Instruction, TgtCtx).
+
+is_precoloured(R, {TgtMod,TgtCtx}) ->
+ TgtMod:is_precoloured(R,TgtCtx).
+
+liveout(Liveness,L, Target={TgtMod,TgtCtx}) ->
+ reg_numbers(TgtMod:liveout(Liveness,L,TgtCtx), Target).
diff --git a/lib/hipe/regalloc/hipe_ls_regalloc.erl b/lib/hipe/regalloc/hipe_ls_regalloc.erl
index 8d9cd8f507..0db18f5c62 100644
--- a/lib/hipe/regalloc/hipe_ls_regalloc.erl
+++ b/lib/hipe/regalloc/hipe_ls_regalloc.erl
@@ -56,7 +56,7 @@
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-module(hipe_ls_regalloc).
--export([regalloc/8]).
+-export([regalloc/9]).
%%-define(DEBUG,1).
-define(HIPE_INSTRUMENT_COMPILER, true).
@@ -95,7 +95,9 @@
%% </ol>
%% @end
%%- - - - - - - - - - - - - - - - - - - - - - - -
-regalloc(CFG, Liveness, PhysRegs, Entrypoints, SpillIndex, DontSpill, Options, Target) ->
+regalloc(CFG, Liveness, PhysRegs, Entrypoints, SpillIndex, DontSpill, Options,
+ TargetMod, TargetContext) ->
+ Target = {TargetMod, TargetContext},
?debug_msg("LinearScan: ~w\n", [erlang:statistics(runtime)]),
USIntervals = calculate_intervals(CFG, Liveness,
Entrypoints, Options, Target),
@@ -122,32 +124,33 @@ regalloc(CFG, Liveness, PhysRegs, Entrypoints, SpillIndex, DontSpill, Options, T
%% Liveness: A map of live-in and live-out sets for each Basic-Block.
%% Entrypoints: A set of BB names that have external entrypoints.
%%
-calculate_intervals(CFG,Liveness,_Entrypoints, Options, Target) ->
+calculate_intervals(CFG,Liveness,_Entrypoints, Options,
+ Target={TgtMod,TgtCtx}) ->
%% Add start point for the argument registers.
Args = arg_vars(CFG, Target),
Interval =
- add_def_point(Args, 0, empty_interval(Target:number_of_temporaries(CFG))),
+ add_def_point(Args, 0, empty_interval(number_of_temporaries(CFG, Target))),
%% Interval = add_livepoint(Args, 0, empty_interval()),
Worklist =
case proplists:get_value(ls_order, Options) of
reversepostorder ->
- Target:reverse_postorder(CFG);
+ TgtMod:reverse_postorder(CFG, TgtCtx);
breadth ->
- Target:breadthorder(CFG);
+ TgtMod:breadthorder(CFG, TgtCtx);
postorder ->
- Target:postorder(CFG);
+ TgtMod:postorder(CFG, TgtCtx);
inorder ->
- Target:inorder(CFG);
+ TgtMod:inorder(CFG, TgtCtx);
reverse_inorder ->
- Target:reverse_inorder(CFG);
+ TgtMod:reverse_inorder(CFG, TgtCtx);
preorder ->
- Target:preorder(CFG);
+ TgtMod:preorder(CFG, TgtCtx);
prediction ->
- Target:predictionorder(CFG);
+ TgtMod:predictionorder(CFG, TgtCtx);
random ->
- Target:labels(CFG);
+ TgtMod:labels(CFG, TgtCtx);
_ ->
- Target:reverse_postorder(CFG)
+ TgtMod:reverse_postorder(CFG, TgtCtx)
end,
%% ?inc_counter(bbs_counter, length(Worklist)),
%% ?debug_msg("No BBs ~w\n",[length(Worklist)]),
@@ -287,7 +290,7 @@ allocate([RegInt|RIS], Free, Active, Alloc, SpillIndex, DontSpill, Target) ->
alloc(OtherTemp,NewPhys,NewAlloc),
SpillIndex, DontSpill, Target);
false ->
- NewSpillIndex = Target:new_spill_index(SpillIndex),
+ NewSpillIndex = new_spill_index(SpillIndex, Target),
{NewAlloc2, NewActive4} =
spill(OtherTemp, OtherEnd, OtherStart, NewActive3,
NewAlloc, SpillIndex, DontSpill, Target),
@@ -303,7 +306,7 @@ allocate([RegInt|RIS], Free, Active, Alloc, SpillIndex, DontSpill, Target) ->
case NewFree of
[] ->
%% No physical registers available, we have to spill.
- NewSpillIndex = Target:new_spill_index(SpillIndex),
+ NewSpillIndex = new_spill_index(SpillIndex, Target),
{NewAlloc, NewActive2} =
spill(Temp, endpoint(RegInt), startpoint(RegInt),
Active, Alloc, SpillIndex, DontSpill, Target),
@@ -749,35 +752,41 @@ create_freeregs([]) ->
%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-bb(CFG, L, Target) ->
- Target:bb(CFG,L).
+bb(CFG, L, {TgtMod, TgtCtx}) ->
+ TgtMod:bb(CFG,L,TgtCtx).
-livein(Liveness,L, Target) ->
- regnames(Target:livein(Liveness,L), Target).
+livein(Liveness,L, Target={TgtMod,TgtCtx}) ->
+ regnames(TgtMod:livein(Liveness,L,TgtCtx), Target).
-liveout(Liveness,L, Target) ->
- regnames(Target:liveout(Liveness,L), Target).
+liveout(Liveness,L, Target={TgtMod,TgtCtx}) ->
+ regnames(TgtMod:liveout(Liveness,L,TgtCtx), Target).
-uses(I, Target) ->
- regnames(Target:uses(I), Target).
+uses(I, Target={TgtMod,TgtCtx}) ->
+ regnames(TgtMod:uses(I,TgtCtx), Target).
-defines(I, Target) ->
- regnames(Target:defines(I), Target).
+defines(I, Target={TgtMod,TgtCtx}) ->
+ regnames(TgtMod:defines(I,TgtCtx), Target).
-is_precoloured(R, Target) ->
- Target:is_precoloured(R).
+is_precoloured(R, {TgtMod,TgtCtx}) ->
+ TgtMod:is_precoloured(R,TgtCtx).
-is_global(R, Target) ->
- Target:is_global(R).
+is_global(R, {TgtMod,TgtCtx}) ->
+ TgtMod:is_global(R,TgtCtx).
-physical_name(R, Target) ->
- Target:physical_name(R).
+new_spill_index(SpillIndex, {TgtMod,TgtCtx}) ->
+ TgtMod:new_spill_index(SpillIndex, TgtCtx).
-regnames(Regs, Target) ->
- [Target:reg_nr(X) || X <- Regs].
+number_of_temporaries(CFG, {TgtMod,TgtCtx}) ->
+ TgtMod:number_of_temporaries(CFG, TgtCtx).
-arg_vars(CFG, Target) ->
- Target:args(CFG).
+physical_name(R, {TgtMod,TgtCtx}) ->
+ TgtMod:physical_name(R,TgtCtx).
-is_arg(Reg, Target) ->
- Target:is_arg(Reg).
+regnames(Regs, {TgtMod,TgtCtx}) ->
+ [TgtMod:reg_nr(X,TgtCtx) || X <- Regs].
+
+arg_vars(CFG, {TgtMod,TgtCtx}) ->
+ TgtMod:args(CFG,TgtCtx).
+
+is_arg(Reg, {TgtMod,TgtCtx}) ->
+ TgtMod:is_arg(Reg,TgtCtx).
diff --git a/lib/hipe/regalloc/hipe_optimistic_regalloc.erl b/lib/hipe/regalloc/hipe_optimistic_regalloc.erl
index 43c6424655..031c799a2c 100644
--- a/lib/hipe/regalloc/hipe_optimistic_regalloc.erl
+++ b/lib/hipe/regalloc/hipe_optimistic_regalloc.erl
@@ -29,7 +29,7 @@
%%-----------------------------------------------------------------------
-module(hipe_optimistic_regalloc).
--export([regalloc/6]).
+-export([regalloc/7]).
-ifndef(DEBUG).
%%-define(DEBUG,true).
@@ -74,20 +74,22 @@
%% SpillLimit -- Temporaris with numbers higher than this have
%% infinit spill cost.
%% Consider changing this to a set.
-%% Target -- The module containing the target-specific functions.
+%% TgtMod -- The module containing the target-specific functions.
+%% TgtCtx -- Context data for TgtMod
%%
%% Returns:
%% Coloring -- A coloring for specified CFG
%% SpillIndex2 -- A new spill index
%%-----------------------------------------------------------------------
-ifdef(COMPARE_ITERATED_OPTIMISTIC).
-regalloc(CFG, Liveness, SpillIndex, SpillLimit, Target, _Options) ->
- ?debug_msg("optimistic ~w\n",[Target]),
+regalloc(CFG, Liveness, SpillIndex, SpillLimit, TgtMod, TgtCtx, _Options) ->
+ Target = {TgtMod, TgtCtx},
+ ?debug_msg("optimistic ~w\n",[TgtMod]),
?debug_msg("CFG: ~p\n",[CFG]),
%% Build interference graph
?debug_msg("Build IG\n",[]),
- IG_O = hipe_ig:build(CFG, Liveness, Target),
- IG = hipe_ig:build(CFG, Liveness, Target),
+ IG_O = hipe_ig:build(CFG, Liveness, TgtMod, TgtCtx),
+ IG = hipe_ig:build(CFG, Liveness, TgtMod, TgtCtx),
?debug_msg("adjlist: ~p\n",[hipe_ig:adj_list(IG)]),
?debug_msg("IG:\n",[]),
?print_adjacent(IG),
@@ -98,9 +100,9 @@ regalloc(CFG, Liveness, SpillIndex, SpillLimit, Target, _Options) ->
SavedAdjList = hipe_ig:adj_list(IG),
?debug_msg("Init\n",[]),
- No_temporaries = Target:number_of_temporaries(CFG),
+ No_temporaries = number_of_temporaries(CFG, Target),
?debug_msg("Coalescing RA: num_temps = ~p~n", [No_temporaries]),
- Allocatable = Target:allocatable(),
+ Allocatable = allocatable(Target),
K = length(Allocatable),
All_colors = colset_from_list(Allocatable),
?debug_msg("K: ~w~nAll_colors: ~p\n",[K, All_colors]),
@@ -113,11 +115,13 @@ regalloc(CFG, Liveness, SpillIndex, SpillLimit, Target, _Options) ->
?mov_print_memberships(Move_sets),
?debug_msg("Build Worklist\n",[]),
- Worklists_O = hipe_reg_worklists:new(IG_O, Target, CFG, Move_sets_O, K, No_temporaries),
+ Worklists_O = hipe_reg_worklists:new(IG_O, TgtMod, TgtCtx, CFG, Move_sets_O,
+ K, No_temporaries),
?debug_msg("Worklists:\n ~p\n", [Worklists_O]),
?reg_print_memberships(Worklists_O),
- Worklists = hipe_reg_worklists:new(IG, Target, CFG, K, No_temporaries),
+ Worklists = hipe_reg_worklists:new(IG, TgtMod, TgtCtx, CFG, K,
+ No_temporaries),
?debug_msg("New Worklists:\n ~p\n", [Worklists]),
?reg_print_memberships(Worklists),
@@ -175,10 +179,10 @@ regalloc(CFG, Liveness, SpillIndex, SpillLimit, Target, _Options) ->
?debug_msg("Init node sets\n",[]),
Node_sets = hipe_node_sets:new(),
- %% ?debug_msg("NodeSet: ~w\n NonAlloc ~w\n",[Node_sets,Target:non_alloc(CFG)]),
+ %% ?debug_msg("NodeSet: ~w\n NonAlloc ~w\n",[Node_sets,non_alloc(CFG,Target)]),
?debug_msg("Default coloring\n",[]),
{Color0,Node_sets1} =
- defaultColoring(Target:all_precoloured(),
+ defaultColoring(all_precoloured(Target),
initColor(No_temporaries), Node_sets, Target),
?debug_msg("Color0\n",[]),
?print_colors(No_temporaries, Color0),
@@ -220,12 +224,13 @@ regalloc(CFG, Liveness, SpillIndex, SpillLimit, Target, _Options) ->
sanity_compare(SortedColoring_O, SortedColoring),
{Coloring,SpillIndex2}.
-else.
-regalloc(CFG, Liveness, SpillIndex, SpillLimit, Target, _Options) ->
- ?debug_msg("optimistic ~w\n",[Target]),
+regalloc(CFG, Liveness, SpillIndex, SpillLimit, TgtMod, TgtCtx, _Options) ->
+ Target = {TgtMod, TgtCtx},
+ ?debug_msg("optimistic ~w\n",[TgtMod]),
?debug_msg("CFG: ~p\n",[CFG]),
%% Build interference graph
?debug_msg("Build IG\n",[]),
- IG = hipe_ig:build(CFG, Liveness, Target),
+ IG = hipe_ig:build(CFG, Liveness, TgtMod, TgtCtx),
?debug_msg("adjlist: ~p\n",[hipe_ig:adj_list(IG)]),
?debug_msg("IG:\n",[]),
?print_adjacent(IG),
@@ -236,9 +241,9 @@ regalloc(CFG, Liveness, SpillIndex, SpillLimit, Target, _Options) ->
SavedAdjList = hipe_ig:adj_list(IG),
?debug_msg("Init\n",[]),
- No_temporaries = Target:number_of_temporaries(CFG),
+ No_temporaries = number_of_temporaries(CFG, Target),
?debug_msg("Coalescing RA: num_temps = ~p~n", [No_temporaries]),
- Allocatable = Target:allocatable(),
+ Allocatable = allocatable(Target),
K = length(Allocatable),
All_colors = colset_from_list(Allocatable),
?debug_msg("K: ~w~nAll_colors: ~p\n",[K, All_colors]),
@@ -251,7 +256,8 @@ regalloc(CFG, Liveness, SpillIndex, SpillLimit, Target, _Options) ->
?debug_msg("Build Worklist\n",[]),
- Worklists = hipe_reg_worklists:new(IG, Target, CFG, K, No_temporaries),
+ Worklists = hipe_reg_worklists:new(IG, TgtMod, TgtCtx, CFG, K,
+ No_temporaries),
?debug_msg("New Worklists:\n ~p\n", [Worklists]),
?reg_print_memberships(Worklists),
@@ -293,10 +299,10 @@ regalloc(CFG, Liveness, SpillIndex, SpillLimit, Target, _Options) ->
?debug_msg("Init node sets\n",[]),
Node_sets = hipe_node_sets:new(),
- %% ?debug_msg("NodeSet: ~w\n NonAlloc ~w\n",[Node_sets,Target:non_alloc(CFG)]),
+ %% ?debug_msg("NodeSet: ~w\n NonAlloc ~w\n",[Node_sets,non_alloc(CFG,Target)]),
?debug_msg("Default coloring\n",[]),
{Color0,Node_sets1} =
- defaultColoring(Target:all_precoloured(),
+ defaultColoring(all_precoloured(Target),
initColor(No_temporaries), Node_sets, Target),
?debug_msg("Color0\n",[]),
?print_colors(No_temporaries, Color0),
@@ -835,7 +841,8 @@ sort_stack_split(Pivot, [H|T], Smaller, Bigger) ->
%% 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.
+%% Target -- The module containing the target-specific functions,
+%% along with its context data.
%%
%% Returns:
%% Color -- A mapping from nodes to their respective color.
@@ -875,7 +882,7 @@ assignColors(Worklists, Stack, NodeSets, Color, No_Temporaries,
false -> % Color case
Col = colset_smallest(OkColors),
NodeSets1 = hipe_node_sets:add_colored(Node, NodeSets),
- Color1 = setColor(Node, Target:physical_name(Col), Color),
+ Color1 = setColor(Node, physical_name(Col,Target), Color),
?debug_msg("Color case. Assigning color ~p to node.~n", [Col]),
assignColors(Worklists, Stack1, NodeSets1, Color1, No_Temporaries, SavedAdjList, SavedSpillCosts, IG, Alias, AllColors, Target)
end
@@ -903,7 +910,8 @@ assignColors(Worklists, Stack, NodeSets, Color, No_Temporaries,
%% Alias -- This is a mapping from nodes to nodes. If a node has
%% been coalesced, this mapping shows the alias for that
%% node.
-%% Target -- The module containing the target-specific functions.
+%% Target -- The module containing the target-specific functions,
+%% along with its context data.
%%
%% Returns:
%% Alias -- The restored aliases after the uncoalescing.
@@ -1007,7 +1015,7 @@ colorSplit([], _Col, NodeSets, Color, _Target) ->
colorSplit([Node|Nodes], Col, NodeSets, Color, Target) ->
?debug_msg(" Coloring node ~p with color ~p.~n", [Node, Col]),
NodeSets1 = hipe_node_sets:add_colored(Node, NodeSets),
- Color1 = setColor(Node, Target:physical_name(Col), Color),
+ Color1 = setColor(Node, physical_name(Col,Target), Color),
colorSplit(Nodes, Col, NodeSets1, Color1, Target).
%% Place non-colorable nodes in a split at the bottom of the SelectStack.
@@ -1036,7 +1044,8 @@ enqueueSplit([Node|Nodes], IG, Stack) ->
%% node.
%% AllColors -- This is an ordset containing all the available colors
%%
-%% Target -- The module containing the target-specific functions.
+%% Target -- The module containing the target-specific functions,
+%% along with its context data.
%%
%% Returns:
%% Color -- A mapping from nodes to their respective color.
@@ -1066,7 +1075,7 @@ assignColors_O(Stack,NodeSets,Color,Alias,AllColors,Target) ->
false -> % Colour case
Col = colset_smallest(OkColors),
NodeSets1 = hipe_node_sets:add_colored(Node, NodeSets),
- Color1 = setColor(Node, Target:physical_name(Col), Color),
+ Color1 = setColor(Node, physical_name(Col,Target), Color),
assignColors_O(Stack1, NodeSets1, Color1, Alias, AllColors, Target)
end
end.
@@ -1080,7 +1089,8 @@ assignColors_O(Stack,NodeSets,Color,Alias,AllColors,Target) ->
%% Regs -- The list of registers to be default colored
%% Color -- The color mapping that shall be changed
%% NodeSets -- The node sets that shall be updated
-%% Target -- The module containing the target-specific functions.
+%% Target -- The module containing the target-specific functions,
+%% along with its context data.
%%
%% Returns:
%% NewColor -- The updated color mapping
@@ -1090,7 +1100,7 @@ assignColors_O(Stack,NodeSets,Color,Alias,AllColors,Target) ->
defaultColoring([], Color, NodeSets, _Target) ->
{Color,NodeSets};
defaultColoring([Reg|Regs], Color, NodeSets, Target) ->
- Color1 = setColor(Reg,Target:physical_name(Reg), Color),
+ Color1 = setColor(Reg,physical_name(Reg,Target), Color),
NodeSets1 = hipe_node_sets:add_colored(Reg, NodeSets),
defaultColoring(Regs, Color1, NodeSets1, Target).
@@ -1284,7 +1294,7 @@ coalesce(Moves, IG, Worklists, Alias, K, Target) ->
?debug_msg("Testing nodes ~p and ~p for coalescing~n",[Dest,Source]),
Alias_src = getAlias(Source, Alias),
Alias_dst = getAlias(Dest, Alias),
- {U,V} = case Target:is_precoloured(Alias_dst) of
+ {U,V} = case is_precoloured(Alias_dst, Target) of
true -> {Alias_dst, Alias_src};
false -> {Alias_src, Alias_dst}
end,
@@ -1294,13 +1304,13 @@ coalesce(Moves, IG, Worklists, Alias, K, Target) ->
%% drop coalesced move Move
{Moves0, IG, Alias, Worklists};
_ ->
- case (Target:is_precoloured(V) orelse
+ case (is_precoloured(V, Target) orelse
hipe_ig:nodes_are_adjacent(U, V, IG)) of
true ->
%% drop constrained move Move
{Moves0, IG, Alias, Worklists};
false ->
- case (case Target:is_precoloured(U) of
+ case (case is_precoloured(U, Target) of
true ->
AdjV = hipe_ig:node_adj_list(V, IG),
all_adjacent_ok(AdjV, U, Worklists, IG, K, Target);
@@ -1351,7 +1361,7 @@ coalesce_O(Moves, IG, Worklists, Alias, K, Target) ->
?debug_msg("Testing nodes ~p and ~p for coalescing~n",[Dest,Source]),
Alias_src = getAlias(Source, Alias),
Alias_dst = getAlias(Dest, Alias),
- {U,V} = case Target:is_precoloured(Alias_dst) of
+ {U,V} = case is_precoloured(Alias_dst, Target) of
true -> {Alias_dst, Alias_src};
false -> {Alias_src, Alias_dst}
end,
@@ -1362,7 +1372,7 @@ coalesce_O(Moves, IG, Worklists, Alias, K, Target) ->
Worklists1 = add_worklist(Worklists, U, K, Moves1, IG, Target),
{Moves1, IG, Worklists1, Alias};
_ ->
- case (Target:is_precoloured(V) orelse
+ case (is_precoloured(V, Target) orelse
hipe_ig:nodes_are_adjacent(U, V, IG)) of
true ->
Moves1 = Moves0, % drop constrained move Move
@@ -1370,7 +1380,7 @@ coalesce_O(Moves, IG, Worklists, Alias, K, Target) ->
Worklists2 = add_worklist(Worklists1, V, K, Moves1, IG, Target),
{Moves1, IG, Worklists2, Alias};
false ->
- case (case Target:is_precoloured(U) of
+ case (case is_precoloured(U, Target) of
true ->
AdjV = hipe_ig:node_adj_list(V, IG),
all_adjacent_ok(AdjV, U, Worklists, IG, K, Target);
@@ -1406,7 +1416,8 @@ coalesce_O(Moves, IG, Worklists, Alias, K, Target) ->
%% K -- Number of registers
%% Moves -- Current move information
%% IG -- Interference graph
-%% Target -- The containing the target-specific functions
+%% Target -- The containing the target-specific functions, along with
+%% its context data.
%%
%% Returns:
%% Worklists (updated)
@@ -1414,7 +1425,7 @@ coalesce_O(Moves, IG, Worklists, Alias, K, Target) ->
-ifdef(COMPARE_ITERATED_OPTIMISTIC).
add_worklist(Worklists, U, K, Moves, IG, Target) ->
- case (not(Target:is_precoloured(U))
+ case (not(is_precoloured(U, Target))
andalso not(hipe_moves:move_related(U, Moves))
andalso (hipe_ig:is_trivially_colourable(U, K, IG))) of
true ->
@@ -1525,12 +1536,12 @@ combine(U, V, IG, Alias, Worklists, K, Target) ->
combine_edges([], _U, IG, _Worklists, _K, _Target) ->
IG;
-combine_edges([T|Ts], U, IG, Worklists, K, Target) ->
+combine_edges([T|Ts], U, IG, Worklists, K, Target={TgtMod,TgtCtx}) ->
case hipe_reg_worklists:member_stack_or_coalesced(T, Worklists) of
true -> combine_edges(Ts, U, IG, Worklists, K, Target);
_ ->
- IG1 = hipe_ig:add_edge(T, U, IG, Target),
- IG2 = case Target:is_precoloured(T) of
+ IG1 = hipe_ig:add_edge(T, U, IG, TgtMod, TgtCtx),
+ IG2 = case is_precoloured(T, Target) of
true -> IG1;
false -> hipe_ig:dec_node_degree(T, IG1)
end,
@@ -1560,7 +1571,7 @@ combine_edges([T|Ts], U, IG, Worklists, K, Target) ->
-ifdef(COMPARE_ITERATED_OPTIMISTIC).
combine_edges_O([], _U, IG, Worklists, Moves, _K, _Target) ->
{IG, Worklists, Moves};
-combine_edges_O([T|Ts], U, IG, Worklists, Moves, K, Target) ->
+combine_edges_O([T|Ts], U, IG, Worklists, Moves, K, Target={TgtMod,TgtCtx}) ->
case hipe_reg_worklists:member_stack_or_coalesced(T, Worklists) of
true -> combine_edges_O(Ts, U, IG, Worklists, Moves, K, Target);
_ ->
@@ -1577,7 +1588,7 @@ combine_edges_O([T|Ts], U, IG, Worklists, Moves, K, Target) ->
%% worklist, and that's where decrement_degree() expects to find it.
%% This issue is not covered in the published algorithm.
OldDegree = hipe_ig:get_node_degree(T, IG),
- IG1 = hipe_ig:add_edge(T, U, IG, Target),
+ IG1 = hipe_ig:add_edge(T, U, IG, TgtMod, TgtCtx),
NewDegree = hipe_ig:get_node_degree(T, IG1),
Worklists0 =
if NewDegree =:= K, OldDegree =:= K-1 ->
@@ -1610,7 +1621,8 @@ combine_edges_O([T|Ts], U, IG, Worklists, Moves, K, Target) ->
%% Alias -- The Alias vector before undoing
%% SavedAdj -- Saved adjacency list
%% IG -- Interference graph
-%% Target -- The module containing the target-specific functions.
+%% Target -- The module containing the target-specific functions,
+%% along with its context data.
%%
%% Returns:
%% list of primitive nodes, that is all nodes that were previously
@@ -1677,7 +1689,8 @@ findPrimitiveNodes(Node, N, Alias, PrimitiveNodes) ->
%% N -- Node that should be uncoalesced
%% SavedAdj -- Saved adjacency list
%% IG -- Interference graph
-%% Target -- The module containing the target-specific functions.
+%% Target -- The module containing the target-specific functions, along
+%% with its context data.
%%
%% Returns:
%% updated Interferece graph
@@ -1703,16 +1716,16 @@ fixAdj(N, SavedAdj, IG, Target) ->
removeAdj([], _N, _IG, _Target) ->
true;
-removeAdj([V| New], N, IG, Target) ->
- hipe_ig:remove_edge(V, N, IG, Target),
+removeAdj([V| New], N, IG, Target={TgtMod,TgtCtx}) ->
+ hipe_ig:remove_edge(V, N, IG, TgtMod, TgtCtx),
removeAdj(New, N, IG, Target).
%%restoreAdj([], _N, IG, _Alias, _Target) ->
%% %%?debug_msg("adj_lists__after_restore_o ~n~p~n", [hipe_ig:adj_list(IG)]),
%% IG;
-%%restoreAdj([V| AdjToN], N, IG, Alias, Target) ->
+%%restoreAdj([V| AdjToN], N, IG, Alias, Target={TgtMod,TgtCtx}) ->
%% AliasToV = getAlias(V, Alias),
-%% IG1 = hipe_ig:add_edge(N, AliasToV, IG, Target),
+%% IG1 = hipe_ig:add_edge(N, AliasToV, IG, TgtMod, TgtCtx),
%% restoreAdj(AdjToN, N, IG1, Alias, Target).
%% XXX This is probably a clumsy way of doing it
@@ -1745,7 +1758,8 @@ findNew([A| Adj], Saved, New) ->
%% R -- Other node to test
%% IG -- Interference graph
%% K -- Number of registers
-%% Target -- The module containing the target-specific functions
+%% Target -- The module containing the target-specific functions, along
+%% with its context data.
%%
%% Returns:
%% true iff coalescing is OK
@@ -1753,7 +1767,7 @@ findNew([A| Adj], Saved, New) ->
ok(T, R, IG, K, Target) ->
((hipe_ig:is_trivially_colourable(T, K, IG))
- orelse Target:is_precoloured(T)
+ orelse is_precoloured(T, Target)
orelse hipe_ig:nodes_are_adjacent(T, R, IG)).
%%----------------------------------------------------------------------
@@ -1766,7 +1780,8 @@ ok(T, R, IG, K, Target) ->
%% U -- Node to test for coalescing
%% IG -- Interference graph
%% K -- Number of registers
-%% Target -- The module containing the target-specific functions
+%% Target -- The module containing the target-specific functions, along
+%% with its context data.
%%
%% Returns:
%% true iff coalescing is OK for all nodes in the list
@@ -2043,3 +2058,24 @@ freezeEm3(_U,V,_M,K,WorkLists,Moves,IG,_Alias) ->
{WorkLists,Moves1}
end.
-endif.
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%%
+%% Interface to external functions.
+%%
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+all_precoloured({TgtMod,TgtCtx}) ->
+ TgtMod:all_precoloured(TgtCtx).
+
+allocatable({TgtMod,TgtCtx}) ->
+ TgtMod:allocatable(TgtCtx).
+
+is_precoloured(R, {TgtMod,TgtCtx}) ->
+ TgtMod:is_precoloured(R,TgtCtx).
+
+number_of_temporaries(CFG, {TgtMod,TgtCtx}) ->
+ TgtMod:number_of_temporaries(CFG, TgtCtx).
+
+physical_name(R, {TgtMod,TgtCtx}) ->
+ TgtMod:physical_name(R,TgtCtx).
diff --git a/lib/hipe/regalloc/hipe_ppc_specific.erl b/lib/hipe/regalloc/hipe_ppc_specific.erl
index d046567e79..ed7a26de8c 100644
--- a/lib/hipe/regalloc/hipe_ppc_specific.erl
+++ b/lib/hipe/regalloc/hipe_ppc_specific.erl
@@ -22,123 +22,123 @@
-module(hipe_ppc_specific).
%% for hipe_coalescing_regalloc:
--export([number_of_temporaries/1
- ,analyze/1
- ,labels/1
- ,all_precoloured/0
- ,bb/2
- ,liveout/2
- ,reg_nr/1
- ,def_use/1
- ,is_move/1
- ,is_precoloured/1
- ,var_range/1
- ,allocatable/0
- ,non_alloc/1
- ,physical_name/1
- ,reverse_postorder/1
- ,livein/2
- ,uses/1
- ,defines/1
- ,defines_all_alloc/1
+-export([number_of_temporaries/2
+ ,analyze/2
+ ,labels/2
+ ,all_precoloured/1
+ ,bb/3
+ ,liveout/3
+ ,reg_nr/2
+ ,def_use/2
+ ,is_move/2
+ ,is_precoloured/2
+ ,var_range/2
+ ,allocatable/1
+ ,non_alloc/2
+ ,physical_name/2
+ ,reverse_postorder/2
+ ,livein/3
+ ,uses/2
+ ,defines/2
+ ,defines_all_alloc/2
]).
%% for hipe_graph_coloring_regalloc:
--export([is_fixed/1]).
+-export([is_fixed/2]).
%% for hipe_ls_regalloc:
--export([args/1, is_arg/1, is_global/1, new_spill_index/1]).
--export([breadthorder/1, postorder/1]).
+-export([args/2, is_arg/2, is_global/2, new_spill_index/2]).
+-export([breadthorder/2, postorder/2]).
%% callbacks for hipe_regalloc_loop
--export([check_and_rewrite/2]).
+-export([check_and_rewrite/3]).
%% callbacks for hipe_regalloc_prepass
--export([new_reg_nr/0,
- update_reg_nr/2,
- update_bb/3,
- subst_temps/2]).
+-export([new_reg_nr/1,
+ update_reg_nr/3,
+ update_bb/4,
+ subst_temps/3]).
-check_and_rewrite(CFG, Coloring) ->
+check_and_rewrite(CFG, Coloring, _) ->
hipe_ppc_ra_postconditions:check_and_rewrite(CFG, Coloring, 'normal').
-reverse_postorder(CFG) ->
+reverse_postorder(CFG, _) ->
hipe_ppc_cfg:reverse_postorder(CFG).
-non_alloc(CFG) ->
- non_alloc(hipe_ppc_registers:nr_args(), hipe_ppc_cfg:params(CFG)).
+non_alloc(CFG, no_context) ->
+ non_alloc_1(hipe_ppc_registers:nr_args(), hipe_ppc_cfg:params(CFG)).
%% same as hipe_ppc_frame:fix_formals/2
-non_alloc(0, Rest) -> Rest;
-non_alloc(N, [_|Rest]) -> non_alloc(N-1, Rest);
-non_alloc(_, []) -> [].
+non_alloc_1(0, Rest) -> Rest;
+non_alloc_1(N, [_|Rest]) -> non_alloc_1(N-1, Rest);
+non_alloc_1(_, []) -> [].
%% Liveness stuff
-analyze(CFG) ->
+analyze(CFG, _) ->
hipe_ppc_liveness_gpr:analyse(CFG).
-livein(Liveness,L) ->
+livein(Liveness,L,_) ->
[X || X <- hipe_ppc_liveness_gpr:livein(Liveness,L),
hipe_ppc:temp_is_allocatable(X)].
-liveout(BB_in_out_liveness,Label) ->
+liveout(BB_in_out_liveness,Label,_) ->
[X || X <- hipe_ppc_liveness_gpr:liveout(BB_in_out_liveness,Label),
hipe_ppc:temp_is_allocatable(X)].
%% Registers stuff
-allocatable() ->
+allocatable(no_context) ->
hipe_ppc_registers:allocatable_gpr().
-all_precoloured() ->
+all_precoloured(no_context) ->
hipe_ppc_registers:all_precoloured().
-is_precoloured(Reg) ->
+is_precoloured(Reg, _) ->
hipe_ppc_registers:is_precoloured_gpr(Reg).
-is_fixed(R) ->
+is_fixed(R, _) ->
hipe_ppc_registers:is_fixed(R).
-physical_name(Reg) ->
+physical_name(Reg, _) ->
Reg.
%% CFG stuff
-labels(CFG) ->
+labels(CFG, _) ->
hipe_ppc_cfg:labels(CFG).
-var_range(_CFG) ->
+var_range(_CFG, _) ->
hipe_gensym:var_range(ppc).
-number_of_temporaries(_CFG) ->
+number_of_temporaries(_CFG, _) ->
Highest_temporary = hipe_gensym:get_var(ppc),
%% Since we can have temps from 0 to Max adjust by +1.
Highest_temporary + 1.
-bb(CFG,L) ->
+bb(CFG,L,_) ->
hipe_ppc_cfg:bb(CFG,L).
-update_bb(CFG,L,BB) ->
+update_bb(CFG,L,BB,_) ->
hipe_ppc_cfg:bb_add(CFG,L,BB).
%% PowerPC stuff
-def_use(Instruction) ->
- {defines(Instruction), uses(Instruction)}.
+def_use(Instruction, Ctx) ->
+ {defines(Instruction, Ctx), uses(Instruction, Ctx)}.
-uses(I) ->
+uses(I, _) ->
[X || X <- hipe_ppc_defuse:insn_use_gpr(I),
hipe_ppc:temp_is_allocatable(X)].
-defines(I) ->
+defines(I, _) ->
[X || X <- hipe_ppc_defuse:insn_def_gpr(I),
hipe_ppc:temp_is_allocatable(X)].
-defines_all_alloc(I) ->
+defines_all_alloc(I, _) ->
hipe_ppc_defuse:insn_defs_all_gpr(I).
-is_move(Instruction) ->
+is_move(Instruction, _) ->
case hipe_ppc:is_pseudo_move(Instruction) of
true ->
Dst = hipe_ppc:pseudo_move_dst(Instruction),
@@ -151,16 +151,16 @@ is_move(Instruction) ->
false -> false
end.
-reg_nr(Reg) ->
+reg_nr(Reg, _) ->
hipe_ppc:temp_reg(Reg).
-new_reg_nr() ->
+new_reg_nr(_) ->
hipe_gensym:get_next_var(ppc).
-update_reg_nr(Nr, Temp) ->
+update_reg_nr(Nr, Temp, _) ->
hipe_ppc:mk_temp(Nr, hipe_ppc:temp_type(Temp)).
-subst_temps(SubstFun, Instr) ->
+subst_temps(SubstFun, Instr, _) ->
hipe_ppc_subst:insn_temps(
fun(Op) ->
case hipe_ppc:temp_is_allocatable(Op)
@@ -173,23 +173,23 @@ subst_temps(SubstFun, Instr) ->
%%% Linear Scan stuff
-new_spill_index(SpillIndex) when is_integer(SpillIndex) ->
+new_spill_index(SpillIndex, _) when is_integer(SpillIndex) ->
SpillIndex+1.
-breadthorder(CFG) ->
+breadthorder(CFG, _) ->
hipe_ppc_cfg:breadthorder(CFG).
-postorder(CFG) ->
+postorder(CFG, _) ->
hipe_ppc_cfg:postorder(CFG).
-is_global(R) ->
+is_global(R, _) ->
R =:= hipe_ppc_registers:temp1() orelse
R =:= hipe_ppc_registers:temp2() orelse
R =:= hipe_ppc_registers:temp3() orelse
hipe_ppc_registers:is_fixed(R).
-is_arg(R) ->
+is_arg(R, _) ->
hipe_ppc_registers:is_arg(R).
-args(CFG) ->
+args(CFG, _) ->
hipe_ppc_registers:args(hipe_ppc_cfg:arity(CFG)).
diff --git a/lib/hipe/regalloc/hipe_ppc_specific_fp.erl b/lib/hipe/regalloc/hipe_ppc_specific_fp.erl
index 5ec625daaf..6daa624720 100644
--- a/lib/hipe/regalloc/hipe_ppc_specific_fp.erl
+++ b/lib/hipe/regalloc/hipe_ppc_specific_fp.erl
@@ -22,126 +22,126 @@
-module(hipe_ppc_specific_fp).
%% for hipe_coalescing_regalloc:
--export([number_of_temporaries/1
- ,analyze/1
- ,labels/1
- ,all_precoloured/0
- ,bb/2
- ,liveout/2
- ,reg_nr/1
- ,def_use/1
- ,is_move/1
- ,is_precoloured/1
- ,var_range/1
- ,allocatable/0
- ,non_alloc/1
- ,physical_name/1
- ,reverse_postorder/1
- ,livein/2
- ,uses/1
- ,defines/1
- ,defines_all_alloc/1
+-export([number_of_temporaries/2
+ ,analyze/2
+ ,labels/2
+ ,all_precoloured/1
+ ,bb/3
+ ,liveout/3
+ ,reg_nr/2
+ ,def_use/2
+ ,is_move/2
+ ,is_precoloured/2
+ ,var_range/2
+ ,allocatable/1
+ ,non_alloc/2
+ ,physical_name/2
+ ,reverse_postorder/2
+ ,livein/3
+ ,uses/2
+ ,defines/2
+ ,defines_all_alloc/2
]).
%% for hipe_graph_coloring_regalloc:
--export([is_fixed/1]).
+-export([is_fixed/2]).
%% for hipe_ls_regalloc:
-%%-export([args/1, is_arg/1, is_global, new_spill_index/1]).
-%%-export([breadthorder/1, postorder/1]).
+%%-export([args/2, is_arg/2, is_global, new_spill_index/2]).
+%%-export([breadthorder/2, postorder/2]).
%% callbacks for hipe_regalloc_loop
--export([check_and_rewrite/2]).
+-export([check_and_rewrite/3]).
%% callbacks for hipe_regalloc_prepass
--export([new_reg_nr/0,
- update_reg_nr/2,
- update_bb/3,
- subst_temps/2]).
+-export([new_reg_nr/1,
+ update_reg_nr/3,
+ update_bb/4,
+ subst_temps/3]).
-check_and_rewrite(CFG, Coloring) ->
+check_and_rewrite(CFG, Coloring, _) ->
hipe_ppc_ra_postconditions_fp:check_and_rewrite(CFG, Coloring).
-reverse_postorder(CFG) ->
+reverse_postorder(CFG, _) ->
hipe_ppc_cfg:reverse_postorder(CFG).
-non_alloc(_CFG) ->
+non_alloc(_CFG, _) ->
[].
%% Liveness stuff
-analyze(CFG) ->
+analyze(CFG, _) ->
hipe_ppc_liveness_fpr:analyse(CFG).
-livein(Liveness, L) ->
+livein(Liveness, L, _) ->
hipe_ppc_liveness_fpr:livein(Liveness, L).
-liveout(BB_in_out_liveness, Label) ->
+liveout(BB_in_out_liveness, Label, _) ->
hipe_ppc_liveness_fpr:liveout(BB_in_out_liveness, Label).
%% Registers stuff
-allocatable() ->
+allocatable(no_context) ->
hipe_ppc_registers:allocatable_fpr().
-all_precoloured() ->
- allocatable().
+all_precoloured(Ctx) ->
+ allocatable(Ctx).
-is_precoloured(Reg) ->
+is_precoloured(Reg, _) ->
hipe_ppc_registers:is_precoloured_fpr(Reg).
-is_fixed(_Reg) ->
+is_fixed(_Reg, _) ->
false.
-physical_name(Reg) ->
+physical_name(Reg, _) ->
Reg.
%% CFG stuff
-labels(CFG) ->
+labels(CFG, _) ->
hipe_ppc_cfg:labels(CFG).
-var_range(_CFG) ->
+var_range(_CFG, _) ->
hipe_gensym:var_range(ppc).
-number_of_temporaries(_CFG) ->
+number_of_temporaries(_CFG, _) ->
Highest_temporary = hipe_gensym:get_var(ppc),
%% Since we can have temps from 0 to Max adjust by +1.
Highest_temporary + 1.
-bb(CFG, L) ->
+bb(CFG, L, _) ->
hipe_ppc_cfg:bb(CFG, L).
-update_bb(CFG,L,BB) ->
+update_bb(CFG,L,BB,_) ->
hipe_ppc_cfg:bb_add(CFG,L,BB).
%% PowerPC stuff
-def_use(I) ->
- {defines(I), uses(I)}.
+def_use(I, Ctx) ->
+ {defines(I, Ctx), uses(I, Ctx)}.
-uses(I) ->
+uses(I, _) ->
hipe_ppc_defuse:insn_use_fpr(I).
-defines(I) ->
+defines(I, _) ->
hipe_ppc_defuse:insn_def_fpr(I).
-defines_all_alloc(I) ->
+defines_all_alloc(I, _) ->
hipe_ppc_defuse:insn_defs_all_fpr(I).
-is_move(I) ->
+is_move(I, _) ->
hipe_ppc:is_pseudo_fmove(I).
-reg_nr(Reg) ->
+reg_nr(Reg, _) ->
hipe_ppc:temp_reg(Reg).
-new_reg_nr() ->
+new_reg_nr(_) ->
hipe_gensym:get_next_var(ppc).
-update_reg_nr(Nr, _Temp) ->
+update_reg_nr(Nr, _Temp, _) ->
hipe_ppc:mk_temp(Nr, 'double').
-subst_temps(SubstFun, Instr) ->
+subst_temps(SubstFun, Instr, _) ->
hipe_ppc_subst:insn_temps(
fun(Op) ->
case hipe_ppc:temp_is_allocatable(Op)
@@ -153,21 +153,21 @@ subst_temps(SubstFun, Instr) ->
end, Instr).
-ifdef(notdef).
-new_spill_index(SpillIndex) ->
+new_spill_index(SpillIndex, _) ->
SpillIndex+1.
-breadthorder(CFG) ->
+breadthorder(CFG, _) ->
hipe_ppc_cfg:breadthorder(CFG).
-postorder(CFG) ->
+postorder(CFG, _) ->
hipe_ppc_cfg:postorder(CFG).
-is_global(_R) ->
+is_global(_R, _) ->
false.
-is_arg(_R) ->
+is_arg(_R, _) ->
false.
-args(_CFG) ->
+args(_CFG, _) ->
[].
-endif.
diff --git a/lib/hipe/regalloc/hipe_reg_worklists.erl b/lib/hipe/regalloc/hipe_reg_worklists.erl
index 88585f9f38..00679cf19c 100644
--- a/lib/hipe/regalloc/hipe_reg_worklists.erl
+++ b/lib/hipe/regalloc/hipe_reg_worklists.erl
@@ -30,8 +30,8 @@
-module(hipe_reg_worklists).
-author(['Andreas Wallin', 'Thorild Selén']).
--export([new/5, % only used by optimistic allocator
- new/6,
+-export([new/6, % only used by optimistic allocator
+ new/7,
simplify/1,
spill/1,
freeze/1,
@@ -90,29 +90,32 @@
%%
%%%----------------------------------------------------------------------
-new(IG, Target, CFG, K, No_temporaries) -> % only used by optimistic allocator
+%% only used by optimistic allocator
+new(IG, TargetMod, TargetCtx, CFG, K, No_temporaries) ->
CoalescedTo = hipe_bifs:array(No_temporaries, 'none'),
- init(initial(Target, CFG), K, IG, empty(No_temporaries, CoalescedTo)).
+ init(initial(TargetMod, TargetCtx, CFG), K, IG,
+ empty(No_temporaries, CoalescedTo)).
-new(IG, Target, CFG, Move_sets, K, No_temporaries) ->
- init(initial(Target, CFG), K, IG, Move_sets, empty(No_temporaries, [])).
+new(IG, TargetMod, TargetCtx, CFG, Move_sets, K, No_temporaries) ->
+ init(initial(TargetMod, TargetCtx, CFG), K, IG, Move_sets,
+ empty(No_temporaries, [])).
-initial(Target, CFG) ->
- {Min_temporary, Max_temporary} = Target:var_range(CFG),
- NonAlloc = Target:non_alloc(CFG),
- non_precoloured(Target, Min_temporary, Max_temporary, [])
- -- [Target:reg_nr(X) || X <- NonAlloc].
+initial(TargetMod, TargetCtx, CFG) ->
+ {Min_temporary, Max_temporary} = TargetMod:var_range(CFG, TargetCtx),
+ NonAlloc = TargetMod:non_alloc(CFG, TargetCtx),
+ non_precoloured(TargetMod, TargetCtx, Min_temporary, Max_temporary, [])
+ -- [TargetMod:reg_nr(X, TargetCtx) || X <- NonAlloc].
-non_precoloured(Target, Current, Max_temporary, Initial) ->
+non_precoloured(TargetMod, TargetCtx, Current, Max_temporary, Initial) ->
if Current > Max_temporary ->
Initial;
true ->
NewInitial =
- case Target:is_precoloured(Current) of
+ case TargetMod:is_precoloured(Current, TargetCtx) of
true -> Initial;
false -> [Current|Initial]
end,
- non_precoloured(Target, Current+1, Max_temporary, NewInitial)
+ non_precoloured(TargetMod, TargetCtx, Current+1, Max_temporary, NewInitial)
end.
%% construct an empty initialized worklists data structure
diff --git a/lib/hipe/regalloc/hipe_regalloc_loop.erl b/lib/hipe/regalloc/hipe_regalloc_loop.erl
index 9557461244..3777f90534 100644
--- a/lib/hipe/regalloc/hipe_regalloc_loop.erl
+++ b/lib/hipe/regalloc/hipe_regalloc_loop.erl
@@ -21,42 +21,44 @@
%%% Common wrapper for graph_coloring and coalescing regallocs.
-module(hipe_regalloc_loop).
--export([ra/6, ra_fp/5]).
+-export([ra/7, ra_fp/6]).
%%-define(HIPE_INSTRUMENT_COMPILER, true). %% Turn on instrumentation.
-include("../main/hipe.hrl").
-ra(CFG, Liveness0, SpillIndex, Options, RegAllocMod, TargetMod) ->
+ra(CFG, Liveness0, SpillIndex, Options, RegAllocMod, TargetMod, TargetCtx) ->
{NewCFG, Liveness, Coloring, _NewSpillIndex} =
- ra_common(CFG, Liveness0, SpillIndex, Options, RegAllocMod, TargetMod),
+ ra_common(CFG, Liveness0, SpillIndex, Options, RegAllocMod, TargetMod,
+ TargetCtx),
{NewCFG, Liveness, Coloring}.
-ra_fp(CFG, Liveness, Options, RegAllocMod, TargetMod) ->
- ra_common(CFG, Liveness, 0, Options, RegAllocMod, TargetMod).
+ra_fp(CFG, Liveness, Options, RegAllocMod, TargetMod, TargetCtx) ->
+ ra_common(CFG, Liveness, 0, Options, RegAllocMod, TargetMod, TargetCtx).
-ra_common(CFG0, Liveness0, SpillIndex, Options, RegAllocMod, TargetMod) ->
+ra_common(CFG0, Liveness0, SpillIndex, Options, RegAllocMod, TargetMod,
+ TargetCtx) ->
?inc_counter(ra_calls_counter, 1),
- SpillLimit0 = TargetMod:number_of_temporaries(CFG0),
+ SpillLimit0 = TargetMod:number_of_temporaries(CFG0, TargetCtx),
{Coloring, _, CFG, Liveness} =
call_allocator_initial(CFG0, Liveness0, SpillLimit0, SpillIndex, Options,
- RegAllocMod, TargetMod),
+ RegAllocMod, TargetMod, TargetCtx),
%% The first iteration, the hipe_regalloc_prepass may create new temps, these
%% should not end up above SpillLimit.
- SpillLimit = TargetMod:number_of_temporaries(CFG),
+ SpillLimit = TargetMod:number_of_temporaries(CFG, TargetCtx),
alloc(Coloring, CFG, Liveness, SpillLimit, SpillIndex, Options,
- RegAllocMod, TargetMod).
+ RegAllocMod, TargetMod, TargetCtx).
alloc(Coloring, CFG0, Liveness, SpillLimit, SpillIndex, Options,
- RegAllocMod, TargetMod) ->
+ RegAllocMod, TargetMod, TargetCtx) ->
?inc_counter(ra_iteration_counter, 1),
- {CFG, DidSpill} = TargetMod:check_and_rewrite(CFG0, Coloring),
+ {CFG, DidSpill} = TargetMod:check_and_rewrite(CFG0, Coloring, TargetCtx),
case DidSpill of
false -> %% No new temps, we are done.
?add_spills(Options, _NewSpillIndex),
- TempMap = hipe_temp_map:cols2tuple(Coloring, TargetMod),
+ TempMap = hipe_temp_map:cols2tuple(Coloring, TargetMod, TargetCtx),
{TempMap2, NewSpillIndex2} =
hipe_spillmin:stackalloc(CFG0, Liveness, [], SpillIndex, Options,
- TargetMod, TempMap),
+ TargetMod, TargetCtx, TempMap),
Coloring2 =
hipe_spillmin:mapmerge(hipe_temp_map:to_substlist(TempMap), TempMap2),
%% case proplists:get_bool(verbose_spills, Options) of
@@ -71,30 +73,32 @@ alloc(Coloring, CFG0, Liveness, SpillLimit, SpillIndex, Options,
%% the list of temps not to spill is uninteresting.
{NewColoring, _NewSpillIndex} =
call_allocator(CFG, Liveness, SpillLimit, SpillIndex, Options,
- RegAllocMod, TargetMod),
+ RegAllocMod, TargetMod, TargetCtx),
alloc(NewColoring, CFG, Liveness, SpillLimit, SpillIndex, Options,
- RegAllocMod, TargetMod)
+ RegAllocMod, TargetMod, TargetCtx)
end.
call_allocator_initial(CFG, Liveness, SpillLimit, SpillIndex, Options,
- RegAllocMod, TargetMod) ->
+ RegAllocMod, TargetMod, TargetCtx) ->
case proplists:get_bool(ra_prespill, Options) of
true ->
hipe_regalloc_prepass:regalloc_initial(
- RegAllocMod, CFG, Liveness, SpillIndex, SpillLimit, TargetMod, Options);
+ RegAllocMod, CFG, Liveness, SpillIndex, SpillLimit, TargetMod,
+ TargetCtx, Options);
false ->
{C, SI} = RegAllocMod:regalloc(CFG, Liveness, SpillIndex, SpillLimit,
- TargetMod, Options),
+ TargetMod, TargetCtx, Options),
{C, SI, CFG, Liveness}
end.
call_allocator(CFG, Liveness, SpillLimit, SpillIndex, Options, RegAllocMod,
- TargetMod) ->
+ TargetMod, TargetCtx) ->
case proplists:get_bool(ra_prespill, Options) of
true ->
hipe_regalloc_prepass:regalloc(
- RegAllocMod, CFG, Liveness, SpillIndex, SpillLimit, TargetMod, Options);
+ RegAllocMod, CFG, Liveness, SpillIndex, SpillLimit, TargetMod,
+ TargetCtx, Options);
false ->
RegAllocMod:regalloc(CFG, Liveness, SpillIndex, SpillLimit, TargetMod,
- Options)
+ TargetCtx, Options)
end.
diff --git a/lib/hipe/regalloc/hipe_regalloc_prepass.erl b/lib/hipe/regalloc/hipe_regalloc_prepass.erl
index 75f377fcce..2f1597ffd1 100644
--- a/lib/hipe/regalloc/hipe_regalloc_prepass.erl
+++ b/lib/hipe/regalloc/hipe_regalloc_prepass.erl
@@ -44,7 +44,7 @@
%% hipe_regalloc_loop iteration, skipping directly to rewrite without ever
%% calling RegAllocMod.
-module(hipe_regalloc_prepass).
--export([regalloc/7, regalloc_initial/7]).
+-export([regalloc/8, regalloc_initial/8]).
-ifndef(DEBUG).
-compile(inline).
@@ -64,8 +64,6 @@
-define(TUNE_MIN_SPLIT_BBS, 384).
%% We present a "pseudo-target" to the register allocator we wrap.
-%% Note: all arities are +1 as we're currently using the parameterised module
-%% facility to store context data.
-export([analyze/2,
all_precoloured/1,
allocatable/1,
@@ -89,16 +87,15 @@
var_range/2,
reverse_postorder/2]).
-%% Eww, parameterised module. Can we fix it without having to touch all the
-%% register allocators?
--record(?MODULE,
- {target :: module()
- ,sub :: sub_map() % Translates temp numbers found in CFG and understood by
- % Target to temp numbers passed to RegAllocMod.
- ,inv :: inv_map() % Translates temp numbers passed to RegAllocMod
- % to temp numbers found in CFG and understood by
- % Target
- ,max_phys :: temp() % Exclusive upper bound on physical registers
+-record(prepass_ctx,
+ {target_mod :: module()
+ ,target_ctx :: target_context()
+ ,sub :: sub_map() % Translates temp numbers found in CFG and understood by
+ % Target to temp numbers passed to RegAllocMod.
+ ,inv :: inv_map() % Translates temp numbers passed to RegAllocMod
+ % to temp numbers found in CFG and understood by
+ % Target
+ ,max_phys :: temp() % Exclusive upper bound on physical registers
}).
-record(cfg,
@@ -131,18 +128,19 @@
-type target_reg() :: non_neg_integer().
-type target_liveness() :: any().
-type target_liveset() :: ordsets:ordset(target_reg()).
+-type target_context() :: any().
-type spillno() :: non_neg_integer().
-type temp() :: non_neg_integer().
-type label() :: non_neg_integer().
-spec regalloc(module(), target_cfg(), target_liveness(), spillno(), spillno(),
- module(), proplists:proplist())
+ module(), target_context(), proplists:proplist())
-> {hipe_map(), spillno()}.
-regalloc(RegAllocMod, CFG, Liveness, SpillIndex0, SpillLimit, Target,
- Options) ->
+regalloc(RegAllocMod, CFG, Liveness, SpillIndex0, SpillLimit, TargetMod,
+ TargetCtx, Options) ->
{Coloring, SpillIndex, same} =
- regalloc_1(RegAllocMod, CFG, SpillIndex0, SpillLimit, Target, Options,
- Liveness),
+ regalloc_1(RegAllocMod, CFG, SpillIndex0, SpillLimit, TargetMod,
+ TargetCtx, Options, Liveness),
{Coloring, SpillIndex}.
%% regalloc_initial/7 is allowed to introduce new temporaries, unlike
@@ -152,47 +150,48 @@ regalloc(RegAllocMod, CFG, Liveness, SpillIndex0, SpillLimit, Target,
%% reason that the splitting heuristic is solely based on the number of basic
%% blocks, which does not change during the register allocation loop.
-spec regalloc_initial(module(), target_cfg(), target_liveness(), spillno(),
- spillno(), module(), proplists:proplist())
+ spillno(), module(), target_context(),
+ proplists:proplist())
-> {hipe_map(), spillno(), target_cfg(),
target_liveness()}.
-regalloc_initial(RegAllocMod, CFG0, Liveness0, SpillIndex0, SpillLimit, Target,
- Options) ->
+regalloc_initial(RegAllocMod, CFG0, Liveness0, SpillIndex0, SpillLimit,
+ TargetMod, TargetCtx, Options) ->
{Coloring, SpillIndex, NewCFG} =
- regalloc_1(RegAllocMod, CFG0, SpillIndex0, SpillLimit, Target, Options,
- Liveness0),
+ regalloc_1(RegAllocMod, CFG0, SpillIndex0, SpillLimit, TargetMod, TargetCtx,
+ Options, Liveness0),
{CFG, Liveness} =
case NewCFG of
same -> {CFG0, Liveness0};
- {rewritten, CFG1} -> {CFG1, Target:analyze(CFG1)}
+ {rewritten, CFG1} -> {CFG1, TargetMod:analyze(CFG1, TargetCtx)}
end,
{Coloring, SpillIndex, CFG, Liveness}.
-regalloc_1(RegAllocMod, CFG0, SpillIndex0, SpillLimit, Target, Options,
- Liveness) ->
+regalloc_1(RegAllocMod, CFG0, SpillIndex0, SpillLimit, TargetMod, TargetCtx,
+ Options, Liveness) ->
{ScanBBs, Seen, SpillMap, SpillIndex1} =
- scan_cfg(CFG0, Liveness, SpillIndex0, Target),
+ scan_cfg(CFG0, Liveness, SpillIndex0, TargetMod, TargetCtx),
{PartColoring, SpillIndex, NewCFG} =
case proplists:get_bool(ra_partitioned, Options)
- andalso length(Target:labels(CFG0)) > ?TUNE_MIN_SPLIT_BBS
+ andalso length(TargetMod:labels(CFG0, TargetCtx)) > ?TUNE_MIN_SPLIT_BBS
of
true ->
regalloc_partitioned(SpillMap, SpillIndex1, SpillLimit, ScanBBs,
- CFG0, Target, RegAllocMod, Options);
+ CFG0, TargetMod, TargetCtx, RegAllocMod, Options);
_ ->
regalloc_whole(Seen, SpillMap, SpillIndex1, SpillLimit, ScanBBs,
- CFG0, Target, RegAllocMod, Options)
+ CFG0, TargetMod, TargetCtx, RegAllocMod, Options)
end,
SpillColors = [{T, {spill, S}} || {T, S} <- maps:to_list(SpillMap)],
Coloring = SpillColors ++ PartColoring,
?ASSERT(begin
- AllPrecoloured = Target:all_precoloured(),
+ AllPrecoloured = TargetMod:all_precoloured(TargetCtx),
MaxPhys = lists:max(AllPrecoloured) + 1,
Unused = unused(live_pseudos(Seen, SpillMap, MaxPhys),
- SpillMap, CFG0, Target),
- unused_unused(Unused, CFG0, Target)
+ SpillMap, CFG0, TargetMod, TargetCtx),
+ unused_unused(Unused, CFG0, TargetMod, TargetCtx)
end),
?ASSERT(begin
CFG =
@@ -200,40 +199,43 @@ regalloc_1(RegAllocMod, CFG0, SpillIndex0, SpillLimit, Target, Options,
same -> CFG0;
{rewritten, CFG1} -> CFG1
end,
- check_coloring(Coloring, CFG, Target)
+ check_coloring(Coloring, CFG, TargetMod, TargetCtx)
end), % Sanity-check
?ASSERT(just_as_good_as(RegAllocMod, CFG, Liveness, SpillIndex0, SpillLimit,
- Target, Options, SpillMap, Coloring, Unused)),
+ TargetMod, TargetCtx, Options, SpillMap, Coloring,
+ Unused)),
{Coloring, SpillIndex, NewCFG}.
regalloc_whole(Seen, SpillMap, SpillIndex0, SpillLimit, ScanBBs,
- CFG, Target, RegAllocMod, Options) ->
- AllPrecoloured = Target:all_precoloured(),
+ CFG, TargetMod, TargetCtx, RegAllocMod, Options) ->
+ AllPrecoloured = TargetMod:all_precoloured(TargetCtx),
MaxPhys = lists:max(AllPrecoloured) + 1,
LivePseudos = live_pseudos(Seen, SpillMap, MaxPhys),
{SubMap, InvMap, MaxPhys, MaxR, SubSpillLimit} =
number_and_map(AllPrecoloured, LivePseudos, SpillLimit),
BBs = transform_whole_cfg(ScanBBs, SubMap),
SubMod = #cfg{cfg=CFG, bbs=BBs, max_reg=MaxR},
- SubTarget = #?MODULE{target=Target, max_phys=MaxPhys, inv=InvMap, sub=SubMap},
+ SubContext = #prepass_ctx{target_mod=TargetMod, target_ctx=TargetCtx,
+ max_phys=MaxPhys, inv=InvMap, sub=SubMap},
{SubColoring, SpillIndex} =
- RegAllocMod:regalloc(SubMod, SubMod, SpillIndex0, SubSpillLimit, SubTarget,
- Options),
- ?ASSERT(check_coloring(SubColoring, SubMod, SubTarget)),
+ RegAllocMod:regalloc(SubMod, SubMod, SpillIndex0, SubSpillLimit, ?MODULE,
+ SubContext, Options),
+ ?ASSERT(check_coloring(SubColoring, SubMod, ?MODULE, SubContext)),
{translate_coloring(SubColoring, InvMap), SpillIndex, same}.
regalloc_partitioned(SpillMap, SpillIndex0, SpillLimit, ScanBBs,
- CFG, Target, RegAllocMod, Options) ->
- AllPrecoloured = Target:all_precoloured(),
+ CFG, TargetMod, TargetCtx, RegAllocMod, Options) ->
+ AllPrecoloured = TargetMod:all_precoloured(TargetCtx),
MaxPhys = lists:max(AllPrecoloured) + 1,
- DSets0 = initial_dsets(CFG, Target),
+ DSets0 = initial_dsets(CFG, TargetMod, TargetCtx),
PartBBList = part_cfg(ScanBBs, SpillMap, MaxPhys),
DSets1 = join_whole_blocks(PartBBList, DSets0),
{PartBBsRLList, DSets2} = merge_small_parts(DSets1),
{PartBBs, DSets3} = merge_pointless_splits(PartBBList, ScanBBs, DSets2),
SeenMap = collect_seenmap(PartBBsRLList, PartBBs),
- {RPostMap, _DSets4} = part_order(Target:reverse_postorder(CFG), DSets3),
+ {RPostMap, _DSets4} = part_order(TargetMod:reverse_postorder(CFG, TargetCtx),
+ DSets3),
{Allocations, SpillIndex} =
lists:mapfoldl(
@@ -245,16 +247,17 @@ regalloc_partitioned(SpillMap, SpillIndex0, SpillLimit, ScanBBs,
number_and_map(AllPrecoloured, LivePseudos, SpillLimit),
BBs = transform_cfg(Elems, PartBBs, SubMap),
SubMod = #cfg{cfg=CFG, bbs=BBs, max_reg=MaxR, rpostorder=RPost},
- SubTarget = #?MODULE{target=Target, max_phys=MaxPhys, inv=InvMap,
- sub=SubMap},
+ SubContext = #prepass_ctx{target_mod=TargetMod, target_ctx=TargetCtx,
+ max_phys=MaxPhys, inv=InvMap, sub=SubMap},
{SubColoring, SpillIndex2} =
RegAllocMod:regalloc(SubMod, SubMod, SpillIndex1, SubSpillLimit,
- SubTarget, Options),
- ?ASSERT(check_coloring(SubColoring, SubMod, SubTarget)),
+ ?MODULE, SubContext, Options),
+ ?ASSERT(check_coloring(SubColoring, SubMod, ?MODULE, SubContext)),
{{translate_coloring(SubColoring, InvMap), Elems}, SpillIndex2}
end, SpillIndex0, PartBBsRLList),
{Coloring, NewCFG} =
- combine_allocations(Allocations, MaxPhys, PartBBs, Target, CFG),
+ combine_allocations(Allocations, MaxPhys, PartBBs, TargetMod, TargetCtx,
+ CFG),
{Coloring, SpillIndex, NewCFG}.
-spec number_and_map([target_reg()], target_liveset(), target_reg())
@@ -306,16 +309,18 @@ translate_coloring(SubColoring, InvMap) ->
-type spill_state() :: #spill_state{}.
-type spill_map() :: #{target_reg() => spillno()}.
--spec scan_cfg(target_cfg(), target_liveness(), spillno(), module())
+-spec scan_cfg(target_cfg(), target_liveness(), spillno(), module(),
+ target_context())
-> {scan_bbs()
,seen()
,spill_map()
,spillno()
}.
-scan_cfg(CFG, Liveness, SpillIndex0, Target) ->
+scan_cfg(CFG, Liveness, SpillIndex0, TgtMod, TgtCtx) ->
State0 = #spill_state{map=#{}, ix=SpillIndex0},
{BBs, Seen, #spill_state{map=Spill, ix=SpillIndex}} =
- scan_bbs(Target:labels(CFG), CFG, Liveness, #{}, State0, #{}, Target),
+ scan_bbs(TgtMod:labels(CFG,TgtCtx), CFG, Liveness, #{}, State0, #{}, TgtMod,
+ TgtCtx),
{BBs, Seen, Spill, SpillIndex}.
-type seen() :: #{target_reg() => []}. % set
@@ -323,65 +328,69 @@ scan_cfg(CFG, Liveness, SpillIndex0, Target) ->
-type scan_bbs() :: #{label() => scan_bb()}.
-spec scan_bbs([label()], target_cfg(), target_liveness(), seen(),
- spill_state(), scan_bbs(), module())
+ spill_state(), scan_bbs(), module(), target_context())
-> {scan_bbs(), seen(), spill_state()}.
-scan_bbs([], _CFG, _Liveness, Seen, State, BBs, _Target) ->
+scan_bbs([], _CFG, _Liveness, Seen, State, BBs, _TgtMod, _TgtCtx) ->
{BBs, Seen, State};
-scan_bbs([L|Ls], CFG, Liveness, Seen0, State0, BBs, Target) ->
- Liveout = t_liveout(Liveness, L, Target),
+scan_bbs([L|Ls], CFG, Liveness, Seen0, State0, BBs, TgtMod, TgtCtx) ->
+ Liveout = t_liveout(Liveness, L, TgtMod, TgtCtx),
{Code, Livein, Seen, State} =
- scan_bb(lists:reverse(hipe_bb:code(Target:bb(CFG, L))), Liveout, Seen0,
- State0, [], Target),
+ scan_bb(lists:reverse(hipe_bb:code(TgtMod:bb(CFG, L, TgtCtx))), Liveout,
+ Seen0, State0, [], TgtMod, TgtCtx),
BB = {Code, Livein, Liveout},
- scan_bbs(Ls, CFG, Liveness, Seen, State, BBs#{L=>BB}, Target).
+ scan_bbs(Ls, CFG, Liveness, Seen, State, BBs#{L=>BB}, TgtMod, TgtCtx).
-spec scan_bb([target_instr()], target_liveset(), seen(), spill_state(),
- [instr()], module())
+ [instr()], module(), target_context())
-> {[instr()]
,target_liveset()
,seen()
,spill_state()
}.
-scan_bb([], Live, Seen, State, IAcc, _Target) ->
+scan_bb([], Live, Seen, State, IAcc, _TgtMod, _TgtCtx) ->
{IAcc, Live, Seen, State};
-scan_bb([I|Is], Live0, Seen0, State0, IAcc0, Target) ->
- {TDef, TUse} = Target:def_use(I),
- ?ASSERT(TDef =:= Target:defines(I)),
- ?ASSERT(TUse =:= Target:uses(I)),
- Def = ordsets:from_list(reg_names(TDef, Target)),
- Use = ordsets:from_list(reg_names(TUse, Target)),
+scan_bb([I|Is], Live0, Seen0, State0, IAcc0, TgtMod, TgtCtx) ->
+ {TDef, TUse} = TgtMod:def_use(I,TgtCtx),
+ ?ASSERT(TDef =:= TgtMod:defines(I,TgtCtx)),
+ ?ASSERT(TUse =:= TgtMod:uses(I,TgtCtx)),
+ Def = ordsets:from_list(reg_names(TDef, TgtMod, TgtCtx)),
+ Use = ordsets:from_list(reg_names(TUse, TgtMod, TgtCtx)),
Live = ordsets:union(Use, ToSpill = ordsets:subtract(Live0, Def)),
Seen = add_seen(Def, add_seen(Use, Seen0)),
- NewI = #instr{defuse={Def, Use}, is_move=Target:is_move(I)},
+ NewI = #instr{defuse={Def, Use}, is_move=TgtMod:is_move(I,TgtCtx)},
IAcc = [NewI|IAcc0],
State =
- case Target:defines_all_alloc(I) of
+ case TgtMod:defines_all_alloc(I,TgtCtx) of
false -> State0;
- true -> spill_all(ToSpill, Target, State0)
+ true -> spill_all(ToSpill, TgtMod, TgtCtx, State0)
end,
%% We can drop "no-ops" here; where (if anywhere) is it worth it?
- scan_bb(Is, Live, Seen, State, IAcc, Target).
+ scan_bb(Is, Live, Seen, State, IAcc, TgtMod, TgtCtx).
--spec t_liveout(target_liveness(), label(), module()) -> target_liveset().
-t_liveout(Liveness, L, Target) ->
+-spec t_liveout(target_liveness(), label(), module(), target_context()) ->
+ target_liveset().
+t_liveout(Liveness, L, TgtMod, TgtCtx) ->
%% FIXME: unnecessary sort; liveout is sorted, reg_names(...) should be sorted
%% or consist of a few sorted subsequences (per type)
- ordsets:from_list(reg_names(Target:liveout(Liveness, L), Target)).
+ ordsets:from_list(reg_names(TgtMod:liveout(Liveness, L, TgtCtx), TgtMod,
+ TgtCtx)).
--spec reg_names([target_temp()], module()) -> [target_reg()].
-reg_names(Regs, Target) ->
- [Target:reg_nr(X) || X <- Regs].
+-spec reg_names([target_temp()], module(), target_context()) -> [target_reg()].
+reg_names(Regs, TgtMod, TgtCtx) ->
+ [TgtMod:reg_nr(X,TgtCtx) || X <- Regs].
-spec add_seen([target_reg()], seen()) -> seen().
add_seen([], Seen) -> Seen;
add_seen([R|Rs], Seen) -> add_seen(Rs, Seen#{R=>[]}).
--spec spill_all([target_reg()], module(), spill_state()) -> spill_state().
-spill_all([], _Target, State) -> State;
-spill_all([R|Rs], Target, State=#spill_state{map=Map, ix=Ix}) ->
- case Target:is_precoloured(R) or maps:is_key(R, Map) of
- true -> spill_all(Rs, Target, State);
- false -> spill_all(Rs, Target, State#spill_state{map=Map#{R=>Ix}, ix=Ix+1})
+-spec spill_all([target_reg()], module(), target_context(), spill_state()) ->
+ spill_state().
+spill_all([], _TgtMod, _TgtCtx, State) -> State;
+spill_all([R|Rs], TgtMod, TgtCtx, State=#spill_state{map=Map, ix=Ix}) ->
+ case TgtMod:is_precoloured(R,TgtCtx) or maps:is_key(R, Map) of
+ true -> spill_all(Rs, TgtMod, TgtCtx, State);
+ false -> spill_all(Rs, TgtMod, TgtCtx,
+ State#spill_state{map=Map#{R=>Ix}, ix=Ix+1})
end.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -558,9 +567,9 @@ map_append(Key, Elem, Map) ->
-type bb_dsets() :: dsets(bb_dset_key()).
-type bb_dsets_rllist() :: [{bb_dset_key(), [bb_dset_key()]}].
--spec initial_dsets(target_cfg(), module()) -> bb_dsets().
-initial_dsets(CFG, Target) ->
- Labels = Target:labels(CFG),
+-spec initial_dsets(target_cfg(), module(), target_context()) -> bb_dsets().
+initial_dsets(CFG, TgtMod, TgtCtx) ->
+ Labels = TgtMod:labels(CFG, TgtCtx),
DSets0 = dsets_new(lists:append([[{entry,L},{exit,L}] || L <- Labels])),
Edges = lists:append([[{L, S} || S <- hipe_gen_cfg:succ(CFG, L)]
|| L <- Labels]),
@@ -692,35 +701,36 @@ transform_bb(BB, SubMap) ->
%% there are, we fix them up as they're found.
-spec combine_allocations([{hipe_map(), [bb_dset_key()]}], target_reg(),
- part_bbs(), module(), target_cfg())
+ part_bbs(), module(), target_context(), target_cfg())
-> {hipe_map(), same | {rewritten, target_cfg()}}.
-combine_allocations([{A,_}|As], MaxPhys, PartBBs, Target, CFG) ->
+combine_allocations([{A,_}|As], MaxPhys, PartBBs, TgtMod, TgtCtx, CFG) ->
{Phys, Pseuds} = lists:partition(fun({R,_}) -> R < MaxPhys end, A),
{Seen, _, []} = partition_by_seen(Pseuds, #{}, [], []),
- combine_allocations(As, MaxPhys, PartBBs, Target, Phys, Seen, Pseuds,
+ combine_allocations(As, MaxPhys, PartBBs, TgtMod, TgtCtx, Phys, Seen, Pseuds,
{same, CFG}).
-spec combine_allocations([{hipe_map(), [bb_dset_key()]}], target_reg(),
- part_bbs(), module(), hipe_map(), seen(), hipe_map(),
- {same|rewritten, target_cfg()})
+ part_bbs(), module(), target_context(), hipe_map(),
+ seen(), hipe_map(), {same|rewritten, target_cfg()})
-> {hipe_map(), same | {rewritten, target_cfg()}}.
-combine_allocations([], _MaxPhys, _PartBBs, _Target, Phys, _Seen, Pseuds,
- CFGT) ->
+combine_allocations([], _MaxPhys, _PartBBs, _TgtMod, _TgtCtx, Phys, _Seen,
+ Pseuds, CFGT) ->
{Phys ++ Pseuds, case CFGT of
{same, _} -> same;
{rewritten, _} -> CFGT
end};
-combine_allocations([{A,PartElems}|As], MaxPhys, PartBBs, Target, Phys, Seen0,
- Acc, CFGT={_,CFG0}) ->
+combine_allocations([{A,PartElems}|As], MaxPhys, PartBBs, TgtMod, TgtCtx, Phys,
+ Seen0, Acc, CFGT={_,CFG0}) ->
{Phys, Pseuds0} = lists:partition(fun({R,_}) -> R < MaxPhys end, A),
{Seen, Pseuds, Collisions} = partition_by_seen(Pseuds0, Seen0, [], []),
case Collisions of
- [] -> combine_allocations(As, MaxPhys, PartBBs, Target, Phys, Seen,
+ [] -> combine_allocations(As, MaxPhys, PartBBs, TgtMod, TgtCtx, Phys, Seen,
Pseuds++Acc, CFGT);
_ ->
%% There were collisions; rename all the temp numbers in Collisions
- {CFG, Renamed} = rename(Collisions, PartElems, PartBBs, Target, CFG0),
- combine_allocations(As, MaxPhys, PartBBs, Target, Phys, Seen,
+ {CFG, Renamed} = rename(Collisions, PartElems, PartBBs, TgtMod, TgtCtx,
+ CFG0),
+ combine_allocations(As, MaxPhys, PartBBs, TgtMod, TgtCtx, Phys, Seen,
Pseuds++Renamed++Acc, {rewritten,CFG})
end.
@@ -735,38 +745,40 @@ partition_by_seen([C={R,_}|Cs], Seen, Acc, Colls) ->
#{} -> partition_by_seen(Cs, Seen#{R => []}, [C|Acc], Colls)
end.
--spec rename(hipe_map(), [bb_dset_key()], part_bbs(), module(), target_cfg())
+-spec rename(hipe_map(), [bb_dset_key()], part_bbs(), module(),
+ target_context(), target_cfg())
-> {target_cfg(), hipe_map()}.
-rename(CollisionList, PartElems, PartBBs, Target, CFG0) ->
- {Map, Renamed} = new_names(CollisionList, Target, #{}, []),
+rename(CollisionList, PartElems, PartBBs, TgtMod, TgtCtx, CFG0) ->
+ {Map, Renamed} = new_names(CollisionList, TgtMod, TgtCtx, #{}, []),
Fun = fun(I) ->
- Target:subst_temps(
+ TgtMod:subst_temps(
fun(Temp) ->
- N = Target:reg_nr(Temp),
+ N = TgtMod:reg_nr(Temp, TgtCtx),
case Map of
- #{N := Subst} -> Target:update_reg_nr(Subst, Temp);
+ #{N := Subst} -> TgtMod:update_reg_nr(Subst, Temp, TgtCtx);
#{} -> Temp
end
- end, I)
+ end, I, TgtCtx)
end,
- {rename_1(PartElems, PartBBs, Target, Fun, CFG0), Renamed}.
+ {rename_1(PartElems, PartBBs, TgtMod, TgtCtx, Fun, CFG0), Renamed}.
-type rename_map() :: #{target_reg() => target_reg()}.
-type rename_fun() :: fun((target_instr()) -> target_instr()).
--spec new_names(hipe_map(), module(), rename_map(), hipe_map())
+-spec new_names(hipe_map(), module(), target_context(), rename_map(),
+ hipe_map())
-> {rename_map(), hipe_map()}.
-new_names([], _Target, Map, Renamed) -> {Map, Renamed};
-new_names([{R,C}|As], Target, Map, Renamed) ->
- Subst = Target:new_reg_nr(),
- new_names(As, Target, Map#{R => Subst}, [{Subst, C} | Renamed]).
+new_names([], _TgtMod, _TgtCtx, Map, Renamed) -> {Map, Renamed};
+new_names([{R,C}|As], TgtMod, TgtCtx, Map, Renamed) ->
+ Subst = TgtMod:new_reg_nr(TgtCtx),
+ new_names(As, TgtMod, TgtCtx, Map#{R => Subst}, [{Subst, C} | Renamed]).
%% @doc Maps over all instructions in a partition on the original CFG.
--spec rename_1([bb_dset_key()], part_bbs(), module(), rename_fun(),
- target_cfg()) -> target_cfg().
-rename_1([], _PartBBs, _Target, _Fun, CFG) -> CFG;
-rename_1([{Half,L}|Es], PartBBs, Target, Fun, CFG0) ->
- Code0 = hipe_bb:code(BB = Target:bb(CFG0, L)),
+-spec rename_1([bb_dset_key()], part_bbs(), module(), target_context(),
+ rename_fun(), target_cfg()) -> target_cfg().
+rename_1([], _PartBBs, _TgtMod, _TgtCtx, _Fun, CFG) -> CFG;
+rename_1([{Half,L}|Es], PartBBs, TgtMod, TgtCtx, Fun, CFG0) ->
+ Code0 = hipe_bb:code(BB = TgtMod:bb(CFG0, L, TgtCtx)),
Code = case {Half, maps:get(L, PartBBs)} of
{entry, {single,_}} -> lists:map(Fun, Code0);
{entry, {split,PBBP,_}} ->
@@ -775,8 +787,8 @@ rename_1([{Half,L}|Es], PartBBs, Target, Fun, CFG0) ->
map_end(Fun, part_bb_part_len(PBBP), Code0);
{exit, {single, _}} -> Code0
end,
- CFG = Target:update_bb(CFG0, L, hipe_bb:code_update(BB, Code)),
- rename_1(Es, PartBBs, Target, Fun, CFG).
+ CFG = TgtMod:update_bb(CFG0, L, hipe_bb:code_update(BB, Code), TgtCtx),
+ rename_1(Es, PartBBs, TgtMod, TgtCtx, Fun, CFG).
-spec part_bb_part_len(part_bb_part()) -> non_neg_integer().
part_bb_part_len({Code, _Livein, _Liveout}) -> length(Code).
@@ -829,14 +841,14 @@ smap_get_all_partial([T|Ts], SMap={s,Map}) when is_integer(T) ->
-define(report2(X,Y), ?IF_DEBUG_LEVEL(2,?msg(X, Y),ok)).
-define(report3(X,Y), ?IF_DEBUG_LEVEL(3,?msg(X, Y),ok)).
-check_coloring(Coloring, CFG, Target) ->
+check_coloring(Coloring, CFG, TgtMod, TgtCtx) ->
?report0("checking coloring ~p~n",[Coloring]),
- IG = hipe_ig:build(CFG, Target:analyze(CFG), Target),
+ IG = hipe_ig:build(CFG, TgtMod:analyze(CFG,TgtCtx), TgtMod, TgtCtx),
check_cols(hipe_vectors:list(hipe_ig:adj_list(IG)),
- init_coloring(Coloring, Target)).
+ init_coloring(Coloring, TgtMod, TgtCtx)).
-init_coloring(Xs, Target) ->
- hipe_temp_map:cols2tuple(Xs, Target).
+init_coloring(Xs, TgtMod, TgtCtx) ->
+ hipe_temp_map:cols2tuple(Xs, TgtMod, TgtCtx).
check_color_of(X, Cols) ->
case hipe_temp_map:find(X, Cols) of
@@ -870,8 +882,8 @@ valid_coloring(X, C, [{Y,C}|Ys]) ->
valid_coloring(X, C, [_|Ys]) ->
valid_coloring(X, C, Ys).
-unused_unused(Unused, CFG, Target) ->
- IG = hipe_ig:build(CFG, Target:analyze(CFG), Target),
+unused_unused(Unused, CFG, TgtMod, TgtCtx) ->
+ IG = hipe_ig:build(CFG, TgtMod:analyze(CFG,TgtCtx), TgtMod, TgtCtx),
lists:all(fun(R) -> case hipe_ig:get_node_degree(R, IG) of
0 -> true;
Deg ->
@@ -883,10 +895,11 @@ unused_unused(Unused, CFG, Target) ->
%%%%%%%%%%%%%%%%%%%%
%% Check that no register allocation opportunities were missed due to ?MODULE
%%
-just_as_good_as(RegAllocMod, CFG, Liveness, SpillIndex0, SpillLimit, Target,
- Options, SpillMap, Coloring, Unused) ->
- {CheckColoring, _} = RegAllocMod:regalloc(CFG, Liveness, SpillIndex0,
- SpillLimit, Target, Options),
+just_as_good_as(RegAllocMod, CFG, Liveness, SpillIndex0, SpillLimit, TgtMod,
+ TgtCtx, Options, SpillMap, Coloring, Unused) ->
+ {CheckColoring, _} =
+ RegAllocMod:regalloc(CFG, Liveness, SpillIndex0, SpillLimit, TgtMod, TgtCtx,
+ Options),
Now = lists:sort([{R,Kind} || {R,{Kind,_}} <- Coloring,
not ordsets:is_element(R, Unused)]),
Check = lists:sort([{R,Kind} || {R,{Kind,_}} <- CheckColoring,
@@ -907,7 +920,7 @@ just_as_good_as(RegAllocMod, CFG, Liveness, SpillIndex0, SpillLimit, Target,
"MFA: ~w:~w/~w~n"
"Unused: ~w~n"
"Now:~w~nCorrect:~w~n",
- [Target, RegAllocMod,
+ [TgtMod, RegAllocMod,
M,F,A,
Unused,
Now -- Check, Check -- Now]),
@@ -917,10 +930,10 @@ just_as_good_as(RegAllocMod, CFG, Liveness, SpillIndex0, SpillLimit, Target,
count(C) -> {length([[] || {_, reg} <- C]),
length([[] || {_, spill} <- C])}.
-unused(LivePseudos, SpillMap, CFG, Target) ->
- {TMin, TMax} = Target:var_range(CFG),
+unused(LivePseudos, SpillMap, CFG, TgtMod, TgtCtx) ->
+ {TMin, TMax} = TgtMod:var_range(CFG,TgtCtx),
SpillOSet = ordsets:from_list(maps:keys(SpillMap)),
- PhysOSet = ordsets:from_list(Target:all_precoloured()),
+ PhysOSet = ordsets:from_list(TgtMod:all_precoloured(TgtCtx)),
Used = ordsets:union(LivePseudos, ordsets:union(PhysOSet, SpillOSet)),
ordsets:subtract(lists:seq(TMin, TMax), Used).
@@ -943,8 +956,8 @@ bb(Cfg=#cfg{bbs=BBs}, Ix, _ModRec) ->
#{Ix := #transformed_bb{bb=BB}} -> BB;
_ -> error(badarg, [Cfg, Ix])
end.
-args(Arity, #?MODULE{target=Target, sub=SubM}) ->
- smap_get(Target:args(Arity), SubM).
+args(Arity, #prepass_ctx{target_mod=TgtMod, target_ctx=TgtCtx, sub=SubM}) ->
+ smap_get(TgtMod:args(Arity,TgtCtx), SubM).
labels(#cfg{bbs=BBs}, _ModRec) -> maps:keys(BBs).
livein(#cfg{bbs=BBs}, Lb, _SubMod) ->
#{Lb := #transformed_bb{livein=Livein}} = BBs,
@@ -956,28 +969,38 @@ uses(I, MR) -> element(2, def_use(I, MR)).
defines(I, MR) -> element(1, def_use(I, MR)).
def_use(#instr{defuse=DefUse}, _ModRec) -> DefUse.
is_move(#instr{is_move=IM}, _ModRec) -> IM.
-is_fixed(Reg, #?MODULE{target=Target,inv=InvM}) ->
- Target:is_fixed(imap_get(Reg, InvM)). % XXX: Is this hot?
-is_global(Reg, #?MODULE{target=Target,max_phys=MaxPhys}) when Reg < MaxPhys ->
- Target:is_global(Reg). % assume id-map
-is_precoloured(Reg, #?MODULE{max_phys=MaxPhys}) -> Reg < MaxPhys.
+is_fixed(Reg, #prepass_ctx{target_mod=TgtMod,target_ctx=TgtCtx,inv=InvM}) ->
+ TgtMod:is_fixed(imap_get(Reg, InvM),TgtCtx). % XXX: Is this hot?
+is_global(Reg, #prepass_ctx{target_mod=TgtMod,target_ctx=TgtCtx,
+ max_phys=MaxPhys}) when Reg < MaxPhys ->
+ TgtMod:is_global(Reg,TgtCtx). % assume id-map
+is_precoloured(Reg, #prepass_ctx{max_phys=MaxPhys}) -> Reg < MaxPhys.
reg_nr(Reg, _ModRec) -> Reg. % After mapping (naturally)
-non_alloc(#cfg{cfg=CFG}, #?MODULE{target=Target,sub=SubM}) ->
- smap_get_all_partial(reg_names(Target:non_alloc(CFG), Target), SubM).
+non_alloc(#cfg{cfg=CFG}, #prepass_ctx{target_mod=TgtMod,target_ctx=TgtCtx,
+ sub=SubM}) ->
+ smap_get_all_partial(reg_names(TgtMod:non_alloc(CFG,TgtCtx), TgtMod, TgtCtx),
+ SubM).
number_of_temporaries(#cfg{max_reg=MaxR}, _ModRec) -> MaxR.
-allocatable(#?MODULE{target=Target}) -> Target:allocatable(). % assume id-map
+allocatable(#prepass_ctx{target_mod=TgtMod, target_ctx=TgtCtx}) ->
+ TgtMod:allocatable(TgtCtx). % assume id-map
physical_name(Reg, _ModRec) -> Reg.
-all_precoloured(#?MODULE{target=Target}) -> Target:all_precoloured(). % dito
-var_range(#cfg{cfg=_CFG, max_reg=MaxReg}, #?MODULE{target=_Target}) ->
- ?ASSERT(begin {TgtMin, _} = _Target:var_range(_CFG), TgtMin =:= 0 end),
+all_precoloured(#prepass_ctx{target_mod=TgtMod, target_ctx=TgtCtx}) ->
+ TgtMod:all_precoloured(TgtCtx). % dito
+var_range(#cfg{cfg=_CFG, max_reg=MaxReg},
+ #prepass_ctx{target_mod=_TgtMod, target_ctx=_TgtCtx}) ->
+ ?ASSERT(begin {TgtMin, _} = _TgtMod:var_range(_CFG,_TgtCtx),
+ TgtMin =:= 0
+ end),
{0, MaxReg-1}.
-postorder(#cfg{cfg=CFG,rpostorder=undefined}, #?MODULE{target=Target}) ->
- Target:postorder(CFG);
+postorder(#cfg{cfg=CFG,rpostorder=undefined},
+ #prepass_ctx{target_mod=TgtMod,target_ctx=TgtCtx}) ->
+ TgtMod:postorder(CFG,TgtCtx);
postorder(#cfg{rpostorder=Labels}, _ModRec) when is_list(Labels) ->
lists:reverse(Labels).
-reverse_postorder(#cfg{cfg=CFG,rpostorder=undefined}, #?MODULE{target=Target}) ->
- Target:reverse_postorder(CFG);
+reverse_postorder(#cfg{cfg=CFG,rpostorder=undefined},
+ #prepass_ctx{target_mod=TgtMod,target_ctx=TgtCtx}) ->
+ TgtMod:reverse_postorder(CFG,TgtCtx);
reverse_postorder(#cfg{rpostorder=Labels}, _ModRec) when is_list(Labels) ->
Labels.
diff --git a/lib/hipe/regalloc/hipe_sparc_specific.erl b/lib/hipe/regalloc/hipe_sparc_specific.erl
index 1cbfcd4dc7..4c575c1c83 100644
--- a/lib/hipe/regalloc/hipe_sparc_specific.erl
+++ b/lib/hipe/regalloc/hipe_sparc_specific.erl
@@ -22,123 +22,123 @@
-module(hipe_sparc_specific).
%% for hipe_coalescing_regalloc:
--export([number_of_temporaries/1
- ,analyze/1
- ,labels/1
- ,all_precoloured/0
- ,bb/2
- ,liveout/2
- ,reg_nr/1
- ,def_use/1
- ,is_move/1
- ,is_precoloured/1
- ,var_range/1
- ,allocatable/0
- ,non_alloc/1
- ,physical_name/1
- ,reverse_postorder/1
- ,livein/2
- ,uses/1
- ,defines/1
- ,defines_all_alloc/1
+-export([number_of_temporaries/2
+ ,analyze/2
+ ,labels/2
+ ,all_precoloured/1
+ ,bb/3
+ ,liveout/3
+ ,reg_nr/2
+ ,def_use/2
+ ,is_move/2
+ ,is_precoloured/2
+ ,var_range/2
+ ,allocatable/1
+ ,non_alloc/2
+ ,physical_name/2
+ ,reverse_postorder/2
+ ,livein/3
+ ,uses/2
+ ,defines/2
+ ,defines_all_alloc/2
]).
%% for hipe_graph_coloring_regalloc:
--export([is_fixed/1]).
+-export([is_fixed/2]).
%% for hipe_ls_regalloc:
--export([args/1, is_arg/1, is_global/1, new_spill_index/1]).
--export([breadthorder/1, postorder/1]).
+-export([args/2, is_arg/2, is_global/2, new_spill_index/2]).
+-export([breadthorder/2, postorder/2]).
%% callbacks for hipe_regalloc_loop
--export([check_and_rewrite/2]).
+-export([check_and_rewrite/3]).
%% callbacks for hipe_regalloc_prepass
--export([new_reg_nr/0,
- update_reg_nr/2,
- update_bb/3,
- subst_temps/2]).
+-export([new_reg_nr/1,
+ update_reg_nr/3,
+ update_bb/4,
+ subst_temps/3]).
-check_and_rewrite(CFG, Coloring) ->
+check_and_rewrite(CFG, Coloring, no_context) ->
hipe_sparc_ra_postconditions:check_and_rewrite(CFG, Coloring, 'normal').
-reverse_postorder(CFG) ->
+reverse_postorder(CFG, _) ->
hipe_sparc_cfg:reverse_postorder(CFG).
-non_alloc(CFG) ->
- non_alloc(hipe_sparc_registers:nr_args(), hipe_sparc_cfg:params(CFG)).
+non_alloc(CFG, no_context) ->
+ non_alloc_1(hipe_sparc_registers:nr_args(), hipe_sparc_cfg:params(CFG)).
%% same as hipe_sparc_frame:fix_formals/2
-non_alloc(0, Rest) -> Rest;
-non_alloc(N, [_|Rest]) -> non_alloc(N-1, Rest);
-non_alloc(_, []) -> [].
+non_alloc_1(0, Rest) -> Rest;
+non_alloc_1(N, [_|Rest]) -> non_alloc_1(N-1, Rest);
+non_alloc_1(_, []) -> [].
%% Liveness stuff
-analyze(CFG) ->
+analyze(CFG, _) ->
hipe_sparc_liveness_gpr:analyse(CFG).
-livein(Liveness,L) ->
+livein(Liveness,L,_) ->
[X || X <- hipe_sparc_liveness_gpr:livein(Liveness,L),
hipe_sparc:temp_is_allocatable(X)].
-liveout(BB_in_out_liveness,Label) ->
+liveout(BB_in_out_liveness,Label,_) ->
[X || X <- hipe_sparc_liveness_gpr:liveout(BB_in_out_liveness,Label),
hipe_sparc:temp_is_allocatable(X)].
%% Registers stuff
-allocatable() ->
+allocatable(no_context) ->
hipe_sparc_registers:allocatable_gpr().
-all_precoloured() ->
+all_precoloured(no_context) ->
hipe_sparc_registers:all_precoloured().
-is_precoloured(Reg) ->
+is_precoloured(Reg, _) ->
hipe_sparc_registers:is_precoloured_gpr(Reg).
-is_fixed(R) ->
+is_fixed(R, _) ->
hipe_sparc_registers:is_fixed(R).
-physical_name(Reg) ->
+physical_name(Reg, _) ->
Reg.
%% CFG stuff
-labels(CFG) ->
+labels(CFG, _) ->
hipe_sparc_cfg:labels(CFG).
-var_range(_CFG) ->
+var_range(_CFG, _) ->
hipe_gensym:var_range(sparc).
-number_of_temporaries(_CFG) ->
+number_of_temporaries(_CFG, _) ->
Highest_temporary = hipe_gensym:get_var(sparc),
%% Since we can have temps from 0 to Max adjust by +1.
Highest_temporary + 1.
-bb(CFG,L) ->
+bb(CFG,L,_) ->
hipe_sparc_cfg:bb(CFG,L).
-update_bb(CFG,L,BB) ->
+update_bb(CFG,L,BB,_) ->
hipe_sparc_cfg:bb_add(CFG,L,BB).
%% SPARC stuff
-def_use(Instruction) ->
- {defines(Instruction), uses(Instruction)}.
+def_use(Instruction, Ctx) ->
+ {defines(Instruction, Ctx), uses(Instruction, Ctx)}.
-uses(I) ->
+uses(I, _) ->
[X || X <- hipe_sparc_defuse:insn_use_gpr(I),
hipe_sparc:temp_is_allocatable(X)].
-defines(I) ->
+defines(I, _) ->
[X || X <- hipe_sparc_defuse:insn_def_gpr(I),
hipe_sparc:temp_is_allocatable(X)].
-defines_all_alloc(I) ->
+defines_all_alloc(I, _) ->
hipe_sparc_defuse:insn_defs_all_gpr(I).
-is_move(Instruction) ->
+is_move(Instruction, _) ->
case hipe_sparc:is_pseudo_move(Instruction) of
true ->
Dst = hipe_sparc:pseudo_move_dst(Instruction),
@@ -151,16 +151,16 @@ is_move(Instruction) ->
false -> false
end.
-reg_nr(Reg) ->
+reg_nr(Reg, _) ->
hipe_sparc:temp_reg(Reg).
-new_reg_nr() ->
+new_reg_nr(_) ->
hipe_gensym:get_next_var(sparc).
-update_reg_nr(Nr, Temp) ->
+update_reg_nr(Nr, Temp, _) ->
hipe_sparc:mk_temp(Nr, hipe_sparc:temp_type(Temp)).
-subst_temps(SubstFun, Instr) ->
+subst_temps(SubstFun, Instr, _) ->
hipe_sparc_subst:insn_temps(
fun(Op) ->
case hipe_sparc:temp_is_allocatable(Op)
@@ -173,23 +173,23 @@ subst_temps(SubstFun, Instr) ->
%%% Linear Scan stuff
-new_spill_index(SpillIndex) when is_integer(SpillIndex) ->
+new_spill_index(SpillIndex, _) when is_integer(SpillIndex) ->
SpillIndex+1.
-breadthorder(CFG) ->
+breadthorder(CFG, _) ->
hipe_sparc_cfg:breadthorder(CFG).
-postorder(CFG) ->
+postorder(CFG, _) ->
hipe_sparc_cfg:postorder(CFG).
-is_global(R) ->
+is_global(R, _) ->
R =:= hipe_sparc_registers:temp1() orelse
R =:= hipe_sparc_registers:temp2() orelse
R =:= hipe_sparc_registers:temp3() orelse
hipe_sparc_registers:is_fixed(R).
-is_arg(R) ->
+is_arg(R, _) ->
hipe_sparc_registers:is_arg(R).
-args(CFG) ->
+args(CFG, _) ->
hipe_sparc_registers:args(hipe_sparc_cfg:arity(CFG)).
diff --git a/lib/hipe/regalloc/hipe_sparc_specific_fp.erl b/lib/hipe/regalloc/hipe_sparc_specific_fp.erl
index 040e1346a4..0334142b95 100644
--- a/lib/hipe/regalloc/hipe_sparc_specific_fp.erl
+++ b/lib/hipe/regalloc/hipe_sparc_specific_fp.erl
@@ -22,126 +22,126 @@
-module(hipe_sparc_specific_fp).
%% for hipe_coalescing_regalloc:
--export([number_of_temporaries/1
- ,analyze/1
- ,labels/1
- ,all_precoloured/0
- ,bb/2
- ,liveout/2
- ,reg_nr/1
- ,def_use/1
- ,is_move/1
- ,is_precoloured/1
- ,var_range/1
- ,allocatable/0
- ,non_alloc/1
- ,physical_name/1
- ,reverse_postorder/1
- ,livein/2
- ,uses/1
- ,defines/1
- ,defines_all_alloc/1
+-export([number_of_temporaries/2
+ ,analyze/2
+ ,labels/2
+ ,all_precoloured/1
+ ,bb/3
+ ,liveout/3
+ ,reg_nr/2
+ ,def_use/2
+ ,is_move/2
+ ,is_precoloured/2
+ ,var_range/2
+ ,allocatable/1
+ ,non_alloc/2
+ ,physical_name/2
+ ,reverse_postorder/2
+ ,livein/3
+ ,uses/2
+ ,defines/2
+ ,defines_all_alloc/2
]).
%% for hipe_graph_coloring_regalloc:
--export([is_fixed/1]).
+-export([is_fixed/2]).
%% for hipe_ls_regalloc:
-%%-export([args/1, is_arg/1, is_global, new_spill_index/1]).
-%%-export([breadthorder/1, postorder/1]).
+%%-export([args/2, is_arg/2, is_global, new_spill_index/2]).
+%%-export([breadthorder/2, postorder/2]).
%% callbacks for hipe_regalloc_loop
--export([check_and_rewrite/2]).
+-export([check_and_rewrite/3]).
%% callbacks for hipe_regalloc_prepass
--export([new_reg_nr/0,
- update_reg_nr/2,
- update_bb/3,
- subst_temps/2]).
+-export([new_reg_nr/1,
+ update_reg_nr/3,
+ update_bb/4,
+ subst_temps/3]).
-check_and_rewrite(CFG, Coloring) ->
+check_and_rewrite(CFG, Coloring, no_context) ->
hipe_sparc_ra_postconditions_fp:check_and_rewrite(CFG, Coloring).
-reverse_postorder(CFG) ->
+reverse_postorder(CFG, _) ->
hipe_sparc_cfg:reverse_postorder(CFG).
-non_alloc(_CFG) ->
+non_alloc(_CFG, _) ->
[].
%% Liveness stuff
-analyze(CFG) ->
+analyze(CFG, _) ->
hipe_sparc_liveness_fpr:analyse(CFG).
-livein(Liveness, L) ->
+livein(Liveness, L, _) ->
hipe_sparc_liveness_fpr:livein(Liveness, L).
-liveout(BB_in_out_liveness, Label) ->
+liveout(BB_in_out_liveness, Label, _) ->
hipe_sparc_liveness_fpr:liveout(BB_in_out_liveness, Label).
%% Registers stuff
-allocatable() ->
+allocatable(no_context) ->
hipe_sparc_registers:allocatable_fpr().
-all_precoloured() ->
- allocatable().
+all_precoloured(Ctx) ->
+ allocatable(Ctx).
-is_precoloured(Reg) ->
+is_precoloured(Reg, _) ->
hipe_sparc_registers:is_precoloured_fpr(Reg).
-is_fixed(_Reg) ->
+is_fixed(_Reg, _) ->
false.
-physical_name(Reg) ->
+physical_name(Reg, _) ->
Reg.
%% CFG stuff
-labels(CFG) ->
+labels(CFG, _) ->
hipe_sparc_cfg:labels(CFG).
-var_range(_CFG) ->
+var_range(_CFG, _) ->
hipe_gensym:var_range(sparc).
-number_of_temporaries(_CFG) ->
+number_of_temporaries(_CFG, _) ->
Highest_temporary = hipe_gensym:get_var(sparc),
%% Since we can have temps from 0 to Max adjust by +1.
Highest_temporary + 1.
-bb(CFG, L) ->
+bb(CFG, L, _) ->
hipe_sparc_cfg:bb(CFG, L).
-update_bb(CFG,L,BB) ->
+update_bb(CFG,L,BB,_) ->
hipe_sparc_cfg:bb_add(CFG,L,BB).
%% SPARC stuff
-def_use(I) ->
- {defines(I), uses(I)}.
+def_use(I, Ctx) ->
+ {defines(I,Ctx), uses(I,Ctx)}.
-uses(I) ->
+uses(I, _) ->
hipe_sparc_defuse:insn_use_fpr(I).
-defines(I) ->
+defines(I, _) ->
hipe_sparc_defuse:insn_def_fpr(I).
-defines_all_alloc(I) ->
+defines_all_alloc(I, _) ->
hipe_sparc_defuse:insn_defs_all_fpr(I).
-is_move(I) ->
+is_move(I, _) ->
hipe_sparc:is_pseudo_fmove(I).
-reg_nr(Reg) ->
+reg_nr(Reg, _) ->
hipe_sparc:temp_reg(Reg).
-new_reg_nr() ->
+new_reg_nr(_) ->
hipe_gensym:get_next_var(sparc).
-update_reg_nr(Nr, _Temp) ->
+update_reg_nr(Nr, _Temp, _) ->
hipe_sparc:mk_temp(Nr, 'double').
-subst_temps(SubstFun, Instr) ->
+subst_temps(SubstFun, Instr, _) ->
hipe_sparc_subst:insn_temps(
fun(Op) ->
case hipe_sparc:temp_is_allocatable(Op)
@@ -153,21 +153,21 @@ subst_temps(SubstFun, Instr) ->
end, Instr).
-ifdef(notdef).
-new_spill_index(SpillIndex)->
+new_spill_index(SpillIndex, _)->
SpillIndex+1.
-breadthorder(CFG) ->
+breadthorder(CFG, _) ->
hipe_sparc_cfg:breadthorder(CFG).
-postorder(CFG) ->
+postorder(CFG, _) ->
hipe_sparc_cfg:postorder(CFG).
-is_global(_R) ->
+is_global(_R, _) ->
false.
-is_arg(_R) ->
+is_arg(_R, _) ->
false.
-args(_CFG) ->
+args(_CFG, _) ->
[].
-endif.
diff --git a/lib/hipe/regalloc/hipe_temp_map.erl b/lib/hipe/regalloc/hipe_temp_map.erl
index 171c2fb019..b683d08054 100644
--- a/lib/hipe/regalloc/hipe_temp_map.erl
+++ b/lib/hipe/regalloc/hipe_temp_map.erl
@@ -33,10 +33,12 @@
-module(hipe_temp_map).
--export([cols2tuple/2, find/2, is_spilled/2, to_substlist/1]).
+-export([cols2tuple/3, find/2, is_spilled/2, to_substlist/1]).
-include("../main/hipe.hrl").
+-type target_context() :: any().
+
%%----------------------------------------------------------------------------
%% Convert a list of [{R0, C1}, {R1, C2}, ...] to a temp_map
%% (Currently implemented as a tuple) tuple {C1, C2, ...}.
@@ -47,32 +49,32 @@
%% element 1
%%----------------------------------------------------------------------------
--spec cols2tuple(hipe_map(), atom()) -> hipe_temp_map().
+-spec cols2tuple(hipe_map(), module(), target_context()) -> hipe_temp_map().
-cols2tuple(Map, Target) ->
+cols2tuple(Map, TgtMod, TgtCtx) ->
SortedMap = lists:keysort(1, Map),
- cols2tuple(0, SortedMap, [], Target).
+ cols2tuple(0, SortedMap, [], TgtMod, TgtCtx).
-%% sorted_cols2tuple(Map, Target) ->
+%% sorted_cols2tuple(Map, TgtMod, TgtCtx) ->
%% ?ASSERT(Map =:= lists:keysort(1, Map)),
-%% cols2tuple(0, Map, [], Target).
+%% cols2tuple(0, Map, [], TgtMod, TgtCtx).
%% Build a dense mapping
-cols2tuple(_, [], Vs, _) ->
+cols2tuple(_, [], Vs, _, _) ->
%% Done reverse the list and convert to tuple.
list_to_tuple(lists:reverse(Vs));
-cols2tuple(N, [{R, C}|Ms], Vs, Target) when N =:= R ->
+cols2tuple(N, [{R, C}|Ms], Vs, TgtMod, TgtCtx) when N =:= R ->
%% N makes sure the mapping is dense. N is he next key.
- cols2tuple(N+1, Ms, [C|Vs], Target);
-cols2tuple(N, SourceMapping=[{R,_}|_], Vs, Target) when N < R ->
+ cols2tuple(N+1, Ms, [C|Vs], TgtMod, TgtCtx);
+cols2tuple(N, SourceMapping=[{R,_}|_], Vs, TgtMod, TgtCtx) when N < R ->
%% The source was sparse, make up some placeholders...
Val =
- case Target:is_precoloured(N) of
+ case TgtMod:is_precoloured(N, TgtCtx) of
%% If it is precoloured, we know what to map it to.
true -> {reg, N};
false -> unknown
end,
- cols2tuple(N+1, SourceMapping, [Val|Vs], Target).
+ cols2tuple(N+1, SourceMapping, [Val|Vs], TgtMod, TgtCtx).
%%
%% True if temp Temp is spilled.
@@ -107,7 +109,7 @@ is_spilled(Temp, Map) ->
%% Returns the inf temp Temp is mapped to.
find(Temp, Map) when Temp < tuple_size(Map) -> element(Temp+1, Map);
-find(_, Map) when is_tuple(Map) -> unknown. % consistency with cols2tuple/2
+find(_, Map) when is_tuple(Map) -> unknown. % consistency with cols2tuple/3
%%
diff --git a/lib/hipe/regalloc/hipe_x86_specific.erl b/lib/hipe/regalloc/hipe_x86_specific.erl
index 627aaa19b4..67c45cdca5 100644
--- a/lib/hipe/regalloc/hipe_x86_specific.erl
+++ b/lib/hipe/regalloc/hipe_x86_specific.erl
@@ -37,93 +37,93 @@
-module(?HIPE_X86_SPECIFIC).
--export([number_of_temporaries/1]).
+-export([number_of_temporaries/2]).
%% The following exports are used as M:F(...) calls from other modules;
%% e.g. hipe_x86_ra_ls.
--export([analyze/1,
- bb/2,
- args/1,
- labels/1,
- livein/2,
- liveout/2,
- uses/1,
- defines/1,
- defines_all_alloc/1,
- def_use/1,
- is_arg/1, % used by hipe_ls_regalloc
- is_move/1,
- is_fixed/1, % used by hipe_graph_coloring_regalloc
- is_global/1,
- is_precoloured/1,
- reg_nr/1,
- non_alloc/1,
- allocatable/0,
- physical_name/1,
- all_precoloured/0,
- new_spill_index/1, % used by hipe_ls_regalloc
- var_range/1,
- breadthorder/1,
- postorder/1,
- reverse_postorder/1]).
+-export([analyze/2,
+ bb/3,
+ args/2,
+ labels/2,
+ livein/3,
+ liveout/3,
+ uses/2,
+ defines/2,
+ defines_all_alloc/2,
+ def_use/2,
+ is_arg/2, % used by hipe_ls_regalloc
+ is_move/2,
+ is_fixed/2, % used by hipe_graph_coloring_regalloc
+ is_global/2,
+ is_precoloured/2,
+ reg_nr/2,
+ non_alloc/2,
+ allocatable/1,
+ physical_name/2,
+ all_precoloured/1,
+ new_spill_index/2, % used by hipe_ls_regalloc
+ var_range/2,
+ breadthorder/2,
+ postorder/2,
+ reverse_postorder/2]).
%% callbacks for hipe_regalloc_loop
--export([check_and_rewrite/2]).
+-export([check_and_rewrite/3]).
%% callbacks for hipe_regalloc_prepass
--export([new_reg_nr/0,
- update_reg_nr/2,
- update_bb/3,
- subst_temps/2]).
+-export([new_reg_nr/1,
+ update_reg_nr/3,
+ update_bb/4,
+ subst_temps/3]).
-check_and_rewrite(CFG, Coloring) ->
+check_and_rewrite(CFG, Coloring, _) ->
?HIPE_X86_RA_POSTCONDITIONS:check_and_rewrite(CFG, Coloring, 'normal').
-reverse_postorder(CFG) ->
+reverse_postorder(CFG, _) ->
hipe_x86_cfg:reverse_postorder(CFG).
-breadthorder(CFG) ->
+breadthorder(CFG, _) ->
hipe_x86_cfg:breadthorder(CFG).
-postorder(CFG) ->
+postorder(CFG, _) ->
hipe_x86_cfg:postorder(CFG).
%% Globally defined registers for linear scan
-is_global(R) ->
+is_global(R, _) ->
?HIPE_X86_REGISTERS:temp1() =:= R orelse
?HIPE_X86_REGISTERS:temp0() =:= R orelse
?HIPE_X86_REGISTERS:is_fixed(R).
-is_fixed(R) ->
+is_fixed(R, _) ->
?HIPE_X86_REGISTERS:is_fixed(R).
-is_arg(R) ->
+is_arg(R, _) ->
?HIPE_X86_REGISTERS:is_arg(R).
-args(CFG) ->
+args(CFG, _) ->
?HIPE_X86_REGISTERS:args(hipe_x86_cfg:arity(CFG)).
-non_alloc(CFG) ->
- non_alloc(?HIPE_X86_REGISTERS:nr_args(), hipe_x86_cfg:params(CFG)).
+non_alloc(CFG, _) ->
+ non_alloc_1(?HIPE_X86_REGISTERS:nr_args(), hipe_x86_cfg:params(CFG)).
%% same as hipe_x86_frame:fix_formals/2
-non_alloc(0, Rest) -> Rest;
-non_alloc(N, [_|Rest]) -> non_alloc(N-1, Rest);
-non_alloc(_, []) -> [].
+non_alloc_1(0, Rest) -> Rest;
+non_alloc_1(N, [_|Rest]) -> non_alloc_1(N-1, Rest);
+non_alloc_1(_, []) -> [].
%% Liveness stuff
-analyze(CFG) ->
+analyze(CFG, _) ->
?HIPE_X86_LIVENESS:analyze(CFG).
-livein(Liveness,L) ->
+livein(Liveness,L,_) ->
[X || X <- ?HIPE_X86_LIVENESS:livein(Liveness,L),
hipe_x86:temp_is_allocatable(X),
hipe_x86:temp_reg(X) =/= ?HIPE_X86_REGISTERS:fcalls(),
hipe_x86:temp_reg(X) =/= ?HIPE_X86_REGISTERS:heap_limit(),
hipe_x86:temp_type(X) =/= 'double'].
-liveout(BB_in_out_liveness,Label) ->
+liveout(BB_in_out_liveness,Label,_) ->
[X || X <- ?HIPE_X86_LIVENESS:liveout(BB_in_out_liveness,Label),
hipe_x86:temp_is_allocatable(X),
hipe_x86:temp_reg(X) =/= ?HIPE_X86_REGISTERS:fcalls(),
@@ -132,40 +132,40 @@ liveout(BB_in_out_liveness,Label) ->
%% Registers stuff
-allocatable() ->
+allocatable(_) ->
?HIPE_X86_REGISTERS:allocatable().
-all_precoloured() ->
+all_precoloured(_) ->
?HIPE_X86_REGISTERS:all_precoloured().
-is_precoloured(Reg) ->
+is_precoloured(Reg,_) ->
?HIPE_X86_REGISTERS:is_precoloured(Reg).
-physical_name(Reg) ->
+physical_name(Reg,_) ->
Reg.
%% CFG stuff
-labels(CFG) ->
+labels(CFG,_) ->
hipe_x86_cfg:labels(CFG).
-var_range(_CFG) ->
+var_range(_CFG,_) ->
hipe_gensym:var_range(x86).
-number_of_temporaries(_CFG) ->
+number_of_temporaries(_CFG,_) ->
Highest_temporary = hipe_gensym:get_var(x86),
%% Since we can have temps from 0 to Max adjust by +1.
Highest_temporary + 1.
-bb(CFG,L) ->
+bb(CFG,L,_) ->
hipe_x86_cfg:bb(CFG,L).
-update_bb(CFG,L,BB) ->
+update_bb(CFG,L,BB,_) ->
hipe_x86_cfg:bb_add(CFG,L,BB).
%% X86 stuff
-def_use(Instruction) ->
+def_use(Instruction,_) ->
{[X || X <- ?HIPE_X86_DEFUSE:insn_def(Instruction),
hipe_x86:temp_is_allocatable(X),
hipe_x86:temp_type(X) =/= 'double'],
@@ -174,19 +174,19 @@ def_use(Instruction) ->
hipe_x86:temp_type(X) =/= 'double']
}.
-uses(I) ->
+uses(I,_) ->
[X || X <- ?HIPE_X86_DEFUSE:insn_use(I),
hipe_x86:temp_is_allocatable(X),
hipe_x86:temp_type(X) =/= 'double'].
-defines(I) ->
+defines(I,_) ->
[X || X <- ?HIPE_X86_DEFUSE:insn_def(I),
hipe_x86:temp_is_allocatable(X),
hipe_x86:temp_type(X) =/= 'double'].
-defines_all_alloc(I) -> ?HIPE_X86_DEFUSE:insn_defs_all(I).
+defines_all_alloc(I,_) -> ?HIPE_X86_DEFUSE:insn_defs_all(I).
-is_move(Instruction) ->
+is_move(Instruction,_) ->
case hipe_x86:is_move(Instruction) of
true ->
Src = hipe_x86:move_src(Instruction),
@@ -207,16 +207,16 @@ is_move(Instruction) ->
false -> false
end.
-reg_nr(Reg) ->
+reg_nr(Reg,_) ->
hipe_x86:temp_reg(Reg).
-new_reg_nr() ->
+new_reg_nr(_) ->
hipe_gensym:get_next_var(x86).
-update_reg_nr(Nr, Temp) ->
+update_reg_nr(Nr, Temp, _) ->
hipe_x86:mk_temp(Nr, hipe_x86:temp_type(Temp)).
-subst_temps(SubstFun, Instr) ->
+subst_temps(SubstFun, Instr, _) ->
?HIPE_X86_SUBST:insn_temps(
fun(Op) ->
case hipe_x86:temp_is_allocatable(Op)
@@ -227,5 +227,5 @@ subst_temps(SubstFun, Instr) ->
end
end, Instr).
-new_spill_index(SpillIndex) when is_integer(SpillIndex) ->
+new_spill_index(SpillIndex, _) when is_integer(SpillIndex) ->
SpillIndex+1.
diff --git a/lib/hipe/regalloc/hipe_x86_specific_x87.erl b/lib/hipe/regalloc/hipe_x86_specific_x87.erl
index cd4d02491d..85923f8f44 100644
--- a/lib/hipe/regalloc/hipe_x86_specific_x87.erl
+++ b/lib/hipe/regalloc/hipe_x86_specific_x87.erl
@@ -32,118 +32,118 @@
-endif.
-module(?HIPE_X86_SPECIFIC_X87).
--export([allocatable/1,
- is_precoloured/1,
- %% var_range/1,
- %% def_use/1,
- %% is_fixed/1,
- is_arg/1,
- %% non_alloc/1,
- new_spill_index/1,
- number_of_temporaries/1
+-export([allocatable/2,
+ is_precoloured/2,
+ %% var_range/2,
+ %% def_use/2,
+ %% is_fixed/2,
+ is_arg/2,
+ %% non_alloc/2,
+ new_spill_index/2,
+ number_of_temporaries/2
]).
%% The following exports are used as M:F(...) calls from other modules;
%% e.g. hipe_x86_ra_ls.
--export([analyze/1,
- bb/2,
- args/1,
- labels/1,
- livein/2,
- liveout/2,
- uses/1,
- defines/1,
- defines_all_alloc/1,
- is_global/1,
- reg_nr/1,
- physical_name/1,
- breadthorder/1,
- postorder/1,
- reverse_postorder/1]).
+-export([analyze/2,
+ bb/3,
+ args/2,
+ labels/2,
+ livein/3,
+ liveout/3,
+ uses/2,
+ defines/2,
+ defines_all_alloc/2,
+ is_global/2,
+ reg_nr/2,
+ physical_name/2,
+ breadthorder/2,
+ postorder/2,
+ reverse_postorder/2]).
%% callbacks for hipe_x86_ra_ls
--export([check_and_rewrite/3]).
+-export([check_and_rewrite/4]).
%% Rewrite happens in hipe_x86_ra_finalise:finalise/4
-check_and_rewrite(CFG, _Coloring, 'linearscan') ->
+check_and_rewrite(CFG, _Coloring, 'linearscan', _) ->
{CFG, false}.
-breadthorder(CFG) ->
+breadthorder(CFG, _) ->
hipe_x86_cfg:breadthorder(CFG).
-postorder(CFG) ->
+postorder(CFG, _) ->
hipe_x86_cfg:postorder(CFG).
-reverse_postorder(CFG) ->
+reverse_postorder(CFG, _) ->
hipe_x86_cfg:reverse_postorder(CFG).
-is_global(_) ->
+is_global(_, _) ->
false.
-ifdef(notdef).
-is_fixed(_) ->
+is_fixed(_, _) ->
false.
-endif.
-is_arg(_) ->
+is_arg(_, _) ->
false.
-args(_) ->
+args(_, _) ->
[].
-ifdef(notdef).
-non_alloc(_) ->
+non_alloc(_, _) ->
[].
-endif.
%% Liveness stuff
-analyze(CFG) ->
+analyze(CFG, _) ->
?HIPE_X86_LIVENESS:analyze(CFG).
-livein(Liveness,L) ->
+livein(Liveness,L,_) ->
[X || X <- ?HIPE_X86_LIVENESS:livein(Liveness,L),
hipe_x86:temp_is_allocatable(X),
hipe_x86:temp_type(X) =:= 'double'].
-liveout(BB_in_out_liveness,Label) ->
+liveout(BB_in_out_liveness,Label,_) ->
[X || X <- ?HIPE_X86_LIVENESS:liveout(BB_in_out_liveness,Label),
hipe_x86:temp_is_allocatable(X),
hipe_x86:temp_type(X) =:= 'double'].
%% Registers stuff
-allocatable('linearscan') ->
+allocatable('linearscan', _) ->
?HIPE_X86_REGISTERS:allocatable_x87().
-is_precoloured(Reg) ->
+is_precoloured(Reg, _) ->
?HIPE_X86_REGISTERS:is_precoloured_x87(Reg).
-physical_name(Reg) ->
+physical_name(Reg, _) ->
Reg.
%% CFG stuff
-labels(CFG) ->
+labels(CFG, _) ->
hipe_x86_cfg:labels(CFG).
-ifdef(notdef).
-var_range(_CFG) ->
+var_range(_CFG, _) ->
{Min,Max} = hipe_gensym:var_range(x86),
%% io:format("Var_range: ~w\n",[{Min,Max}]),
{Min,Max}.
-endif.
-number_of_temporaries(_CFG) ->
+number_of_temporaries(_CFG, _) ->
Highest_temporary = hipe_gensym:get_var(x86),
%% Since we can have temps from 0 to Max adjust by +1.
Highest_temporary + 1.
-bb(CFG,L) ->
+bb(CFG,L,_) ->
hipe_x86_cfg:bb(CFG,L).
%% X86 stuff
-ifdef(notdef).
-def_use(Instruction) ->
+def_use(Instruction, _) ->
{[X || X <- ?HIPE_X86_DEFUSE:insn_def(Instruction),
hipe_x86:temp_is_allocatable(X),
temp_is_double(X)],
@@ -153,23 +153,23 @@ def_use(Instruction) ->
}.
-endif.
-uses(I) ->
+uses(I, _) ->
[X || X <- ?HIPE_X86_DEFUSE:insn_use(I),
hipe_x86:temp_is_allocatable(X),
temp_is_double(X)].
-defines(I) ->
+defines(I, _) ->
[X || X <- ?HIPE_X86_DEFUSE:insn_def(I),
hipe_x86:temp_is_allocatable(X),
temp_is_double(X)].
-defines_all_alloc(I) -> hipe_amd64_defuse:insn_defs_all(I).
+defines_all_alloc(I, _) -> hipe_amd64_defuse:insn_defs_all(I).
temp_is_double(Temp) ->
hipe_x86:temp_type(Temp) =:= 'double'.
-reg_nr(Reg) ->
+reg_nr(Reg, _) ->
hipe_x86:temp_reg(Reg).
-new_spill_index(SpillIndex) ->
+new_spill_index(SpillIndex, _) ->
SpillIndex+1.