aboutsummaryrefslogtreecommitdiffstats
path: root/lib/hipe/ppc
diff options
context:
space:
mode:
Diffstat (limited to 'lib/hipe/ppc')
-rw-r--r--lib/hipe/ppc/Makefile1
-rw-r--r--lib/hipe/ppc/hipe_ppc_cfg.erl2
-rw-r--r--lib/hipe/ppc/hipe_ppc_defuse.erl7
-rw-r--r--lib/hipe/ppc/hipe_ppc_frame.erl88
-rw-r--r--lib/hipe/ppc/hipe_ppc_main.erl6
-rw-r--r--lib/hipe/ppc/hipe_ppc_ra.erl38
-rw-r--r--lib/hipe/ppc/hipe_ppc_ra_finalise.erl11
-rw-r--r--lib/hipe/ppc/hipe_ppc_ra_ls.erl36
-rw-r--r--lib/hipe/ppc/hipe_ppc_ra_naive.erl10
-rw-r--r--lib/hipe/ppc/hipe_ppc_ra_postconditions.erl21
-rw-r--r--lib/hipe/ppc/hipe_ppc_ra_postconditions_fp.erl17
-rw-r--r--lib/hipe/ppc/hipe_ppc_registers.erl2
-rw-r--r--lib/hipe/ppc/hipe_ppc_subst.erl82
-rw-r--r--lib/hipe/ppc/hipe_rtl_to_ppc.erl25
14 files changed, 230 insertions, 116 deletions
diff --git a/lib/hipe/ppc/Makefile b/lib/hipe/ppc/Makefile
index 1901dfa671..1ca1d51846 100644
--- a/lib/hipe/ppc/Makefile
+++ b/lib/hipe/ppc/Makefile
@@ -63,6 +63,7 @@ MODULES=hipe_ppc \
hipe_ppc_ra_postconditions \
hipe_ppc_ra_postconditions_fp \
hipe_ppc_registers \
+ hipe_ppc_subst \
hipe_rtl_to_ppc
HRL_FILES=hipe_ppc.hrl
diff --git a/lib/hipe/ppc/hipe_ppc_cfg.erl b/lib/hipe/ppc/hipe_ppc_cfg.erl
index 34d4bf54c5..ee9b4432e0 100644
--- a/lib/hipe/ppc/hipe_ppc_cfg.erl
+++ b/lib/hipe/ppc/hipe_ppc_cfg.erl
@@ -24,6 +24,7 @@
-export([init/1,
labels/1, start_label/1,
succ/2,
+ map_bbs/2, fold_bbs/3,
bb/2, bb_add/3]).
-export([postorder/1]).
-export([linearise/1, params/1, reverse_postorder/1]).
@@ -34,6 +35,7 @@
-define(BREADTH_ORDER,true).
-define(PARAMS_NEEDED,true).
-define(START_LABEL_UPDATE_NEEDED,true).
+-define(MAP_FOLD_NEEDED,true).
-include("hipe_ppc.hrl").
-include("../flow/cfg.hrl").
diff --git a/lib/hipe/ppc/hipe_ppc_defuse.erl b/lib/hipe/ppc/hipe_ppc_defuse.erl
index 77b84dc574..305e88488d 100644
--- a/lib/hipe/ppc/hipe_ppc_defuse.erl
+++ b/lib/hipe/ppc/hipe_ppc_defuse.erl
@@ -22,6 +22,7 @@
-module(hipe_ppc_defuse).
-export([insn_def_all/1, insn_use_all/1]).
-export([insn_def_gpr/1, insn_use_gpr/1]).
+-export([insn_defs_all_gpr/1, insn_defs_all_fpr/1]).
-export([insn_def_fpr/1, insn_use_fpr/1]).
-include("hipe_ppc.hrl").
@@ -52,6 +53,9 @@ insn_def_gpr(I) ->
_ -> []
end.
+insn_defs_all_gpr(#pseudo_call{}) -> true;
+insn_defs_all_gpr(_) -> false.
+
call_clobbered_gpr() ->
[hipe_ppc:mk_temp(R, T)
|| {R,T} <- hipe_ppc_registers:call_clobbered() ++ all_fp_pseudos()].
@@ -116,6 +120,9 @@ insn_def_fpr(I) ->
_ -> []
end.
+insn_defs_all_fpr(#pseudo_call{}) -> true;
+insn_defs_all_fpr(_) -> false.
+
call_clobbered_fpr() ->
[hipe_ppc:mk_temp(R, 'double') || R <- hipe_ppc_registers:allocatable_fpr()].
diff --git a/lib/hipe/ppc/hipe_ppc_frame.erl b/lib/hipe/ppc/hipe_ppc_frame.erl
index ff0450270f..8d37159ad8 100644
--- a/lib/hipe/ppc/hipe_ppc_frame.erl
+++ b/lib/hipe/ppc/hipe_ppc_frame.erl
@@ -24,16 +24,14 @@
-include("hipe_ppc.hrl").
-include("../rtl/hipe_literals.hrl").
-frame(Defun) ->
- Formals = fix_formals(hipe_ppc:defun_formals(Defun)),
- Temps0 = all_temps(hipe_ppc:defun_code(Defun), Formals),
- MinFrame = defun_minframe(Defun),
+frame(CFG) ->
+ Formals = fix_formals(hipe_ppc_cfg:params(CFG)),
+ Temps0 = all_temps(CFG, Formals),
+ MinFrame = defun_minframe(CFG),
Temps = ensure_minframe(MinFrame, Temps0),
- ClobbersLR = clobbers_lr(hipe_ppc:defun_code(Defun)),
- CFG0 = hipe_ppc_cfg:init(Defun),
- Liveness = hipe_ppc_liveness_all:analyse(CFG0),
- CFG1 = do_body(CFG0, Liveness, Formals, Temps, ClobbersLR),
- hipe_ppc_cfg:linearise(CFG1).
+ ClobbersLR = clobbers_lr(CFG),
+ Liveness = hipe_ppc_liveness_all:analyse(CFG),
+ do_body(CFG, Liveness, Formals, Temps, ClobbersLR).
fix_formals(Formals) ->
fix_formals(hipe_ppc_registers:nr_args(), Formals).
@@ -44,27 +42,16 @@ fix_formals(_, []) -> [].
do_body(CFG0, Liveness, Formals, Temps, ClobbersLR) ->
Context = mk_context(Liveness, Formals, Temps, ClobbersLR),
- CFG1 = do_blocks(CFG0, Context),
+ CFG1 = hipe_ppc_cfg:map_bbs(
+ fun(Lbl, BB) -> do_block(Lbl, BB, Context) end, CFG0),
do_prologue(CFG1, Context).
-do_blocks(CFG, Context) ->
- Labels = hipe_ppc_cfg:labels(CFG),
- do_blocks(Labels, CFG, Context).
-
-do_blocks([Label|Labels], CFG, Context) ->
+do_block(Label, Block, Context) ->
Liveness = context_liveness(Context),
LiveOut = hipe_ppc_liveness_all:liveout(Liveness, Label),
- Block = hipe_ppc_cfg:bb(CFG, Label),
Code = hipe_bb:code(Block),
- NewCode = do_block(Code, LiveOut, Context),
- NewBlock = hipe_bb:code_update(Block, NewCode),
- NewCFG = hipe_ppc_cfg:bb_add(CFG, Label, NewBlock),
- do_blocks(Labels, NewCFG, Context);
-do_blocks([], CFG, _) ->
- CFG.
-
-do_block(Insns, LiveOut, Context) ->
- do_block(Insns, LiveOut, Context, context_framesize(Context), []).
+ NewCode = do_block(Code, LiveOut, Context, context_framesize(Context), []),
+ hipe_bb:code_update(Block, NewCode).
do_block([I|Insns], LiveOut, Context, FPoff0, RevCode) ->
{NewIs, FPoff1} = do_insn(I, LiveOut, Context, FPoff0),
@@ -573,29 +560,41 @@ temp_is_pseudo(Temp) ->
%%% Detect if a Defun's body clobbers LR.
%%%
-clobbers_lr([I|Insns]) ->
- case I of
- #pseudo_call{} -> true;
- %% mtspr to lr cannot occur yet
- _ -> clobbers_lr(Insns)
- end;
-clobbers_lr([]) -> false.
+clobbers_lr(CFG) ->
+ any_insn(fun(#pseudo_call{}) -> true;
+ (_) -> false
+ end, CFG).
+
+any_insn(Pred, CFG) ->
+ %% Abuse fold to do an efficient "any"-operation using nonlocal control flow
+ FoundSatisfying = make_ref(),
+ try fold_insns(fun (I, _) ->
+ case Pred(I) of
+ true -> throw(FoundSatisfying);
+ false -> false
+ end
+ end, false, CFG)
+ of _ -> false
+ catch FoundSatisfying -> true
+ end.
%%%
%%% Build the set of all temps used in a Defun's body.
%%%
-all_temps(Code, Formals) ->
- S0 = find_temps(Code, tset_empty()),
+all_temps(CFG, Formals) ->
+ S0 = fold_insns(fun find_temps/2, tset_empty(), CFG),
S1 = tset_del_list(S0, Formals),
tset_filter(S1, fun(T) -> temp_is_pseudo(T) end).
-find_temps([I|Insns], S0) ->
+find_temps(I, S0) ->
S1 = tset_add_list(S0, hipe_ppc_defuse:insn_def_all(I)),
- S2 = tset_add_list(S1, hipe_ppc_defuse:insn_use_all(I)),
- find_temps(Insns, S2);
-find_temps([], S) ->
- S.
+ tset_add_list(S1, hipe_ppc_defuse:insn_use_all(I)).
+
+fold_insns(Fun, InitAcc, CFG) ->
+ hipe_ppc_cfg:fold_bbs(
+ fun(_, BB, Acc0) -> lists:foldl(Fun, Acc0, hipe_bb:code(BB)) end,
+ InitAcc, CFG).
tset_empty() ->
gb_sets:new().
@@ -624,16 +623,11 @@ tset_to_list(S) ->
%%% in the middle of a tailcall.
%%%
-defun_minframe(Defun) ->
- MaxTailArity = body_mta(hipe_ppc:defun_code(Defun), 0),
- MyArity = length(fix_formals(hipe_ppc:defun_formals(Defun))),
+defun_minframe(CFG) ->
+ MaxTailArity = fold_insns(fun insn_mta/2, 0, CFG),
+ MyArity = length(fix_formals(hipe_ppc_cfg:params(CFG))),
erlang:max(MaxTailArity - MyArity, 0).
-body_mta([I|Code], MTA) ->
- body_mta(Code, insn_mta(I, MTA));
-body_mta([], MTA) ->
- MTA.
-
insn_mta(I, MTA) ->
case I of
#pseudo_tailcall{arity=Arity} ->
diff --git a/lib/hipe/ppc/hipe_ppc_main.erl b/lib/hipe/ppc/hipe_ppc_main.erl
index fd5cc2befb..5d1b0d0305 100644
--- a/lib/hipe/ppc/hipe_ppc_main.erl
+++ b/lib/hipe/ppc/hipe_ppc_main.erl
@@ -24,8 +24,10 @@
rtl_to_ppc(MFA, RTL, Options) ->
PPC1 = hipe_rtl_to_ppc:translate(RTL),
- PPC2 = hipe_ppc_ra:ra(PPC1, Options),
- PPC3 = hipe_ppc_frame:frame(PPC2),
+ PPC1CFG = hipe_ppc_cfg:init(PPC1),
+ PPC2CFG = hipe_ppc_ra:ra(PPC1CFG, Options),
+ PPC3CFG = hipe_ppc_frame:frame(PPC2CFG),
+ PPC3 = hipe_ppc_cfg:linearise(PPC3CFG),
PPC4 = hipe_ppc_finalise:finalise(PPC3),
ppc_pp(PPC4, MFA, Options),
{native, powerpc, {unprofiled, PPC4}}.
diff --git a/lib/hipe/ppc/hipe_ppc_ra.erl b/lib/hipe/ppc/hipe_ppc_ra.erl
index 87c776f5d1..f8614db4ef 100644
--- a/lib/hipe/ppc/hipe_ppc_ra.erl
+++ b/lib/hipe/ppc/hipe_ppc_ra.erl
@@ -22,36 +22,40 @@
-module(hipe_ppc_ra).
-export([ra/2]).
-ra(Defun0, Options) ->
- %% hipe_ppc_pp:pp(Defun0),
- {Defun1, Coloring_fp, SpillIndex}
+ra(CFG0, Options) ->
+ %% hipe_ppc_pp:pp(hipe_ppc_cfg:linearise(CFG0)),
+ {CFG1, _FPLiveness1, Coloring_fp, SpillIndex}
= case proplists:get_bool(inline_fp, Options) of
true ->
- hipe_regalloc_loop:ra_fp(Defun0, Options,
+ FPLiveness0 = hipe_ppc_specific_fp:analyze(CFG0, no_context),
+ hipe_regalloc_loop:ra_fp(CFG0, FPLiveness0, Options,
hipe_coalescing_regalloc,
- hipe_ppc_specific_fp);
+ hipe_ppc_specific_fp, no_context);
false ->
- {Defun0,[],0}
+ {CFG0,undefined,[],0}
end,
- %% hipe_ppc_pp:pp(Defun1),
- {Defun2, Coloring}
+ %% hipe_ppc_pp:pp(hipe_ppc_cfg:linearise(CFG1)),
+ GPLiveness1 = hipe_ppc_specific:analyze(CFG1, no_context),
+ {CFG2, _GPLiveness2, Coloring}
= case proplists:get_value(regalloc, Options, coalescing) of
coalescing ->
- ra(Defun1, SpillIndex, Options, hipe_coalescing_regalloc);
+ ra(CFG1, GPLiveness1, SpillIndex, Options, hipe_coalescing_regalloc);
optimistic ->
- ra(Defun1, SpillIndex, Options, hipe_optimistic_regalloc);
+ ra(CFG1, GPLiveness1, SpillIndex, Options, hipe_optimistic_regalloc);
graph_color ->
- ra(Defun1, SpillIndex, Options, hipe_graph_coloring_regalloc);
+ ra(CFG1, GPLiveness1, SpillIndex, Options,
+ hipe_graph_coloring_regalloc);
linear_scan ->
- hipe_ppc_ra_ls:ra(Defun1, SpillIndex, Options);
+ hipe_ppc_ra_ls:ra(CFG1, GPLiveness1, SpillIndex, Options);
naive ->
- hipe_ppc_ra_naive:ra(Defun1, Coloring_fp, Options);
+ hipe_ppc_ra_naive:ra(CFG1, GPLiveness1, Coloring_fp, Options);
_ ->
exit({unknown_regalloc_compiler_option,
proplists:get_value(regalloc,Options)})
end,
- %% hipe_ppc_pp:pp(Defun2),
- hipe_ppc_ra_finalise:finalise(Defun2, Coloring, Coloring_fp).
+ %% hipe_ppc_pp:pp(hipe_ppc_cfg:linearise(CFG2)),
+ hipe_ppc_ra_finalise:finalise(CFG2, Coloring, Coloring_fp).
-ra(Defun, SpillIndex, Options, RegAllocMod) ->
- hipe_regalloc_loop:ra(Defun, SpillIndex, Options, RegAllocMod, hipe_ppc_specific).
+ra(CFG, Liveness, SpillIndex, Options, RegAllocMod) ->
+ hipe_regalloc_loop:ra(CFG, Liveness, SpillIndex, Options, RegAllocMod,
+ hipe_ppc_specific, no_context).
diff --git a/lib/hipe/ppc/hipe_ppc_ra_finalise.erl b/lib/hipe/ppc/hipe_ppc_ra_finalise.erl
index ea163221c2..78f123116e 100644
--- a/lib/hipe/ppc/hipe_ppc_ra_finalise.erl
+++ b/lib/hipe/ppc/hipe_ppc_ra_finalise.erl
@@ -23,13 +23,14 @@
-export([finalise/3]).
-include("hipe_ppc.hrl").
-finalise(Defun, TempMap, FPMap0) ->
- Code = hipe_ppc:defun_code(Defun),
- {_, SpillLimit} = hipe_ppc:defun_var_range(Defun),
+finalise(CFG, TempMap, FPMap0) ->
+ {_, SpillLimit} = hipe_gensym:var_range(ppc),
Map = mk_ra_map(TempMap, SpillLimit),
FPMap1 = mk_ra_map_fp(FPMap0, SpillLimit),
- NewCode = ra_code(Code, Map, FPMap1, []),
- Defun#defun{code=NewCode}.
+ hipe_ppc_cfg:map_bbs(fun(_Lbl, BB) -> ra_bb(BB, Map, FPMap1) end, CFG).
+
+ra_bb(BB, Map, FpMap) ->
+ hipe_bb:code_update(BB, ra_code(hipe_bb:code(BB), Map, FpMap, [])).
ra_code([I|Insns], Map, FPMap, Accum) ->
ra_code(Insns, Map, FPMap, [ra_insn(I, Map, FPMap) | Accum]);
diff --git a/lib/hipe/ppc/hipe_ppc_ra_ls.erl b/lib/hipe/ppc/hipe_ppc_ra_ls.erl
index 6e8304467e..5f331542e8 100644
--- a/lib/hipe/ppc/hipe_ppc_ra_ls.erl
+++ b/lib/hipe/ppc/hipe_ppc_ra_ls.erl
@@ -21,37 +21,35 @@
%%% Linear Scan register allocator for PowerPC
-module(hipe_ppc_ra_ls).
--export([ra/3]).
+-export([ra/4]).
-ra(Defun, SpillIndex, Options) ->
- NewDefun = Defun, %% hipe_${ARCH}_ra_rename:rename(Defun,Options),
- CFG = hipe_ppc_cfg:init(NewDefun),
- SpillLimit = hipe_ppc_specific:number_of_temporaries(CFG),
- alloc(NewDefun, SpillIndex, SpillLimit, Options).
+ra(CFG, Liveness, SpillIndex, Options) ->
+ SpillLimit = hipe_ppc_specific:number_of_temporaries(CFG, no_context),
+ alloc(CFG, Liveness, SpillIndex, SpillLimit, Options).
-alloc(Defun, SpillIndex, SpillLimit, Options) ->
- CFG = hipe_ppc_cfg:init(Defun),
+alloc(CFG, Liveness, SpillIndex, SpillLimit, Options) ->
{Coloring, _NewSpillIndex} =
regalloc(
- CFG,
+ CFG, Liveness,
hipe_ppc_registers:allocatable_gpr()--
[hipe_ppc_registers:temp3(),
hipe_ppc_registers:temp2(),
hipe_ppc_registers:temp1()],
[hipe_ppc_cfg:start_label(CFG)],
SpillIndex, SpillLimit, Options,
- hipe_ppc_specific),
- {NewDefun, _DidSpill} =
+ hipe_ppc_specific, no_context),
+ {NewCFG, _DidSpill} =
hipe_ppc_ra_postconditions:check_and_rewrite(
- Defun, Coloring, 'linearscan'),
- TempMap = hipe_temp_map:cols2tuple(Coloring, hipe_ppc_specific),
+ CFG, Coloring, 'linearscan'),
+ TempMap = hipe_temp_map:cols2tuple(Coloring, hipe_ppc_specific, no_context),
{TempMap2,_NewSpillIndex2} =
- hipe_spillmin:stackalloc(CFG, [], SpillIndex, Options,
- hipe_ppc_specific, TempMap),
+ hipe_spillmin:stackalloc(CFG, Liveness, [], SpillIndex, Options,
+ hipe_ppc_specific, no_context, TempMap),
Coloring2 =
hipe_spillmin:mapmerge(hipe_temp_map:to_substlist(TempMap), TempMap2),
- {NewDefun, Coloring2}.
+ {NewCFG, Liveness, Coloring2}.
-regalloc(CFG, PhysRegs, Entrypoints, SpillIndex, DontSpill, Options, Target) ->
- hipe_ls_regalloc:regalloc(
- CFG, PhysRegs, Entrypoints, SpillIndex, DontSpill, Options, Target).
+regalloc(CFG, Liveness, PhysRegs, Entrypoints, SpillIndex, DontSpill, Options,
+ TgtMod, TgtCtx) ->
+ hipe_ls_regalloc:regalloc(CFG, Liveness, PhysRegs, Entrypoints, SpillIndex,
+ DontSpill, Options, TgtMod, TgtCtx).
diff --git a/lib/hipe/ppc/hipe_ppc_ra_naive.erl b/lib/hipe/ppc/hipe_ppc_ra_naive.erl
index 24995be252..322fb1a171 100644
--- a/lib/hipe/ppc/hipe_ppc_ra_naive.erl
+++ b/lib/hipe/ppc/hipe_ppc_ra_naive.erl
@@ -20,11 +20,11 @@
%%
-module(hipe_ppc_ra_naive).
--export([ra/3]).
+-export([ra/4]).
-include("hipe_ppc.hrl").
-ra(Defun, _Coloring_fp, _Options) -> % -> {Defun, Coloring}
- {NewDefun,_DidSpill} =
- hipe_ppc_ra_postconditions:check_and_rewrite2(Defun, [], 'naive'),
- {NewDefun, []}.
+ra(CFG, Liveness, _Coloring_fp, _Options) -> % -> {CFG, Liveness, Coloring}
+ {NewCFG,_DidSpill} =
+ hipe_ppc_ra_postconditions:check_and_rewrite2(CFG, [], 'naive'),
+ {NewCFG, Liveness, []}.
diff --git a/lib/hipe/ppc/hipe_ppc_ra_postconditions.erl b/lib/hipe/ppc/hipe_ppc_ra_postconditions.erl
index 0b16ec3891..f084a30e63 100644
--- a/lib/hipe/ppc/hipe_ppc_ra_postconditions.erl
+++ b/lib/hipe/ppc/hipe_ppc_ra_postconditions.erl
@@ -25,17 +25,13 @@
-include("hipe_ppc.hrl").
-check_and_rewrite(Defun, Coloring, Allocator) ->
- TempMap = hipe_temp_map:cols2tuple(Coloring, hipe_ppc_specific),
- check_and_rewrite2(Defun, TempMap, Allocator).
+check_and_rewrite(CFG, Coloring, Allocator) ->
+ TempMap = hipe_temp_map:cols2tuple(Coloring, hipe_ppc_specific, no_context),
+ check_and_rewrite2(CFG, TempMap, Allocator).
-check_and_rewrite2(Defun, TempMap, Allocator) ->
+check_and_rewrite2(CFG, TempMap, Allocator) ->
Strategy = strategy(Allocator),
- #defun{code=Code0} = Defun,
- {Code1,DidSpill} = do_insns(Code0, TempMap, Strategy, [], false),
- VarRange = {0, hipe_gensym:get_var(ppc)},
- {Defun#defun{code=Code1, var_range=VarRange},
- DidSpill}.
+ do_bbs(hipe_ppc_cfg:labels(CFG), TempMap, Strategy, CFG, false).
strategy(Allocator) ->
case Allocator of
@@ -44,6 +40,13 @@ strategy(Allocator) ->
'naive' -> 'fixed'
end.
+do_bbs([], _, _, CFG, DidSpill) -> {CFG, DidSpill};
+do_bbs([Lbl|Lbls], TempMap, Strategy, CFG0, DidSpill0) ->
+ Code0 = hipe_bb:code(BB = hipe_ppc_cfg:bb(CFG0, Lbl)),
+ {Code, DidSpill} = do_insns(Code0, TempMap, Strategy, [], DidSpill0),
+ CFG = hipe_ppc_cfg:bb_add(CFG0, Lbl, hipe_bb:code_update(BB, Code)),
+ do_bbs(Lbls, TempMap, Strategy, CFG, DidSpill).
+
do_insns([I|Insns], TempMap, Strategy, Accum, DidSpill0) ->
{NewIs, DidSpill1} = do_insn(I, TempMap, Strategy),
do_insns(Insns, TempMap, Strategy, lists:reverse(NewIs, Accum), DidSpill0 or DidSpill1);
diff --git a/lib/hipe/ppc/hipe_ppc_ra_postconditions_fp.erl b/lib/hipe/ppc/hipe_ppc_ra_postconditions_fp.erl
index 821aa66c11..81064079aa 100644
--- a/lib/hipe/ppc/hipe_ppc_ra_postconditions_fp.erl
+++ b/lib/hipe/ppc/hipe_ppc_ra_postconditions_fp.erl
@@ -23,13 +23,16 @@
-export([check_and_rewrite/2]).
-include("hipe_ppc.hrl").
-check_and_rewrite(Defun, Coloring) ->
- TempMap = hipe_temp_map:cols2tuple(Coloring, hipe_ppc_specific_fp),
- #defun{code=Code0} = Defun,
- {Code1,DidSpill} = do_insns(Code0, TempMap, [], false),
- VarRange = {0, hipe_gensym:get_var(ppc)},
- {Defun#defun{code=Code1, var_range=VarRange},
- DidSpill}.
+check_and_rewrite(CFG, Coloring) ->
+ TempMap = hipe_temp_map:cols2tuple(Coloring, hipe_ppc_specific_fp, no_context),
+ do_bbs(hipe_ppc_cfg:labels(CFG), TempMap, CFG, false).
+
+do_bbs([], _TempMap, CFG, DidSpill) -> {CFG, DidSpill};
+do_bbs([Lbl|Lbls], TempMap, CFG0, DidSpill0) ->
+ Code0 = hipe_bb:code(BB = hipe_ppc_cfg:bb(CFG0, Lbl)),
+ {Code, DidSpill} = do_insns(Code0, TempMap, [], DidSpill0),
+ CFG = hipe_ppc_cfg:bb_add(CFG0, Lbl, hipe_bb:code_update(BB, Code)),
+ do_bbs(Lbls, TempMap, CFG, DidSpill).
do_insns([I|Insns], TempMap, Accum, DidSpill0) ->
{NewIs, DidSpill1} = do_insn(I, TempMap),
diff --git a/lib/hipe/ppc/hipe_ppc_registers.erl b/lib/hipe/ppc/hipe_ppc_registers.erl
index f4781d5ed7..8f6d9779fc 100644
--- a/lib/hipe/ppc/hipe_ppc_registers.erl
+++ b/lib/hipe/ppc/hipe_ppc_registers.erl
@@ -201,6 +201,8 @@ is_arg(R) ->
_ -> false
end.
+%% Note: the fact that allocatable_gpr() is a subset of call_clobbered() is
+%% hard-coded in hipe_ppc_defuse:insn_defs_all_gpr/1
call_clobbered() -> % does the RA strip the type or not?
[{?R0,tagged},{?R0,untagged},
%% R1 is reserved for C
diff --git a/lib/hipe/ppc/hipe_ppc_subst.erl b/lib/hipe/ppc/hipe_ppc_subst.erl
new file mode 100644
index 0000000000..5e43fd6471
--- /dev/null
+++ b/lib/hipe/ppc/hipe_ppc_subst.erl
@@ -0,0 +1,82 @@
+%% -*- erlang-indent-level: 2 -*-
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2016. All Rights Reserved.
+%%
+%% Licensed under the Apache License, Version 2.0 (the "License");
+%% you may not use this file except in compliance with the License.
+%% You may obtain a copy of the License at
+%%
+%% http://www.apache.org/licenses/LICENSE-2.0
+%%
+%% Unless required by applicable law or agreed to in writing, software
+%% distributed under the License is distributed on an "AS IS" BASIS,
+%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+%% See the License for the specific language governing permissions and
+%% limitations under the License.
+%%
+%% %CopyrightEnd%
+%%
+
+-module(hipe_ppc_subst).
+-export([insn_temps/2]).
+-include("hipe_ppc.hrl").
+
+%% These should be moved to hipe_ppc and exported
+-type temp() :: #ppc_temp{}.
+-type oper() :: temp() | #ppc_simm16{} | #ppc_uimm16{}.
+-type arg() :: temp() | integer().
+-type insn() :: tuple(). % for now
+
+-type subst_fun() :: fun((temp()) -> temp()).
+
+%% @doc Maps over the temporaries in an instruction
+-spec insn_temps(subst_fun(), insn()) -> insn().
+insn_temps(T, I) ->
+ A = fun(O) -> arg_temps(T, O) end,
+ O = fun(O) -> oper_temps(T, O) end,
+ case I of
+ #alu{dst=D,src1=L,src2=R} -> I#alu{dst=T(D),src1=T(L),src2=O(R)};
+ #b_label{} -> I;
+ %% #bc{} -> I;
+ #bctr{} -> I;
+ #blr{} -> I;
+ #cmp{src1=L,src2=R} -> I#cmp{src1=T(L),src2=O(R)};
+ #comment{} -> I;
+ #label{} -> I;
+ #load{dst=D,base=B} -> I#load{dst=T(D),base=T(B)};
+ #loadx{dst=D,base1=L,base2=R} -> I#loadx{dst=T(D),base1=T(L),base2=T(R)};
+ #mfspr{dst=D} -> I#mfspr{dst=T(D)};
+ #mtcr{src=S} -> I#mtcr{src=T(S)};
+ #mtspr{src=S} -> I#mtspr{src=T(S)};
+ #pseudo_bc{} -> I;
+ #pseudo_call{func=F} when not is_record(F, ppc_temp) -> I;
+ #pseudo_call_prepare{} -> I;
+ #pseudo_li{dst=D} -> I#pseudo_li{dst=T(D)};
+ #pseudo_move{dst=D,src=S} -> I#pseudo_move{dst=T(D),src=T(S)};
+ #pseudo_tailcall{func=F,stkargs=Stk} when not is_record(F, ppc_temp) ->
+ I#pseudo_tailcall{stkargs=lists:map(A,Stk)};
+ #pseudo_tailcall_prepare{} -> I;
+ #store{src=S,base=B} -> I#store{src=T(S),base=T(B)};
+ #storex{src=S,base1=L,base2=R} ->
+ I#storex{src=T(S),base1=T(L),base2=T(R)};
+ #unary{dst=D,src=S} -> I#unary{dst=T(D),src=T(S)};
+ #lfd{dst=D,base=B} -> I#lfd{dst=T(D),base=T(B)};
+ #lfdx{dst=D,base1=L,base2=R} -> I#lfdx{dst=T(D),base1=T(L),base2=T(R)};
+ #stfd{src=S,base=B} -> I#stfd{src=T(S),base=T(B)};
+ #stfdx{src=S,base1=L,base2=R} -> I#stfdx{src=T(S),base1=T(L),base2=T(R)};
+ #fp_binary{dst=D,src1=L,src2=R} ->
+ I#fp_binary{dst=T(D),src1=T(L),src2=T(R)};
+ #fp_unary{dst=D,src=S} -> I#fp_unary{dst=T(D),src=T(S)};
+ #pseudo_fmove{dst=D,src=S} -> I#pseudo_fmove{dst=T(D),src=T(S)}
+ end.
+
+-spec oper_temps(subst_fun(), oper()) -> oper().
+oper_temps(SubstTemp, T=#ppc_temp{}) -> SubstTemp(T);
+oper_temps(_SubstTemp, I=#ppc_simm16{}) -> I;
+oper_temps(_SubstTemp, I=#ppc_uimm16{}) -> I.
+
+-spec arg_temps(subst_fun(), arg()) -> arg().
+arg_temps(_SubstTemp, Imm) when is_integer(Imm) -> Imm;
+arg_temps(SubstTemp, T=#ppc_temp{}) -> SubstTemp(T).
diff --git a/lib/hipe/ppc/hipe_rtl_to_ppc.erl b/lib/hipe/ppc/hipe_rtl_to_ppc.erl
index a994659616..a01e67a789 100644
--- a/lib/hipe/ppc/hipe_rtl_to_ppc.erl
+++ b/lib/hipe/ppc/hipe_rtl_to_ppc.erl
@@ -1031,7 +1031,7 @@ conv_return(I, Map, Data) ->
{I2, Map0, Data}.
conv_store(I, Map, Data) ->
- {Base1, Map0} = conv_dst(hipe_rtl:store_base(I), Map),
+ {Base1, Map0} = conv_src(hipe_rtl:store_base(I), Map),
{Src, Map1} = conv_src(hipe_rtl:store_src(I), Map0),
{Base2, Map2} = conv_src(hipe_rtl:store_offset(I), Map1),
StoreSize = hipe_rtl:store_size(I),
@@ -1056,13 +1056,28 @@ mk_store(Src, Base1, Base2, StoreSize) ->
end.
mk_store2(Src, Base1, Base2, StOp) ->
- case hipe_ppc:is_temp(Base2) of
+ case hipe_ppc:is_temp(Base1) of
true ->
- mk_store_rr(Src, Base1, Base2, StOp);
+ case hipe_ppc:is_temp(Base2) of
+ true ->
+ mk_store_rr(Src, Base1, Base2, StOp);
+ _ ->
+ mk_store_ri(Src, Base1, Base2, StOp)
+ end;
_ ->
- mk_store_ri(Src, Base1, Base2, StOp)
+ case hipe_ppc:is_temp(Base2) of
+ true ->
+ mk_store_ri(Src, Base2, Base1, StOp);
+ _ ->
+ mk_store_ii(Src, Base1, Base2, StOp)
+ end
end.
-
+
+mk_store_ii(Src, Base, Disp, StOp) ->
+ Tmp = new_untagged_temp(),
+ mk_li(Tmp, Base,
+ mk_store_ri(Src, Tmp, Disp, StOp)).
+
mk_store_ri(Src, Base, Disp, StOp) ->
hipe_ppc:mk_store(StOp, Src, Disp, Base, 'new', []).