aboutsummaryrefslogtreecommitdiffstats
path: root/lib/hipe/arm
diff options
context:
space:
mode:
Diffstat (limited to 'lib/hipe/arm')
-rw-r--r--lib/hipe/arm/Makefile1
-rw-r--r--lib/hipe/arm/hipe_arm_defuse.erl7
-rw-r--r--lib/hipe/arm/hipe_arm_ra.erl28
-rw-r--r--lib/hipe/arm/hipe_arm_ra_ls.erl29
-rw-r--r--lib/hipe/arm/hipe_arm_ra_naive.erl6
-rw-r--r--lib/hipe/arm/hipe_arm_ra_postconditions.erl2
-rw-r--r--lib/hipe/arm/hipe_arm_registers.erl2
-rw-r--r--lib/hipe/arm/hipe_arm_subst.erl112
8 files changed, 157 insertions, 30 deletions
diff --git a/lib/hipe/arm/Makefile b/lib/hipe/arm/Makefile
index 00b6732afa..ed2eccf428 100644
--- a/lib/hipe/arm/Makefile
+++ b/lib/hipe/arm/Makefile
@@ -61,6 +61,7 @@ MODULES=hipe_arm \
hipe_arm_ra_naive \
hipe_arm_ra_postconditions \
hipe_arm_registers \
+ hipe_arm_subst \
hipe_rtl_to_arm
HRL_FILES=hipe_arm.hrl
diff --git a/lib/hipe/arm/hipe_arm_defuse.erl b/lib/hipe/arm/hipe_arm_defuse.erl
index f57b0e601c..f92cf4f82a 100644
--- a/lib/hipe/arm/hipe_arm_defuse.erl
+++ b/lib/hipe/arm/hipe_arm_defuse.erl
@@ -22,6 +22,7 @@
-module(hipe_arm_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]).
-include("hipe_arm.hrl").
%%%
@@ -55,6 +56,12 @@ insn_def_gpr(I) ->
_ -> []
end.
+insn_defs_all_gpr(I) ->
+ case I of
+ #pseudo_call{} -> true;
+ _ -> false
+ end.
+
call_clobbered_gpr() ->
[hipe_arm:mk_temp(R, T)
|| {R,T} <- hipe_arm_registers:call_clobbered() ++ all_fp_pseudos()].
diff --git a/lib/hipe/arm/hipe_arm_ra.erl b/lib/hipe/arm/hipe_arm_ra.erl
index 5a7884b63c..bfb649326c 100644
--- a/lib/hipe/arm/hipe_arm_ra.erl
+++ b/lib/hipe/arm/hipe_arm_ra.erl
@@ -24,28 +24,31 @@
ra(CFG0, Options) ->
%% hipe_arm_pp:pp(hipe_arm_cfg:linearise(CFG0)),
- {CFG1, Coloring_fp, SpillIndex}
+ {CFG1, _FPLiveness1, Coloring_fp, SpillIndex}
= case proplists:get_bool(inline_fp, Options) of
%% true ->
-%% hipe_regalloc_loop:ra_fp(CFG0, Options,
+%% FPLiveness0 = hipe_arm_specific_fp:analyze(CFG0, no_context),
+%% hipe_regalloc_loop:ra_fp(CFG0, FPLiveness0, Options,
%% hipe_coalescing_regalloc,
-%% hipe_arm_specific_fp);
+%% hipe_arm_specific_fp, no_context);
false ->
- {CFG0,[],0}
+ {CFG0,undefined,[],0}
end,
%% hipe_arm_pp:pp(hipe_arm_cfg:linearise(CFG1)),
- {CFG2, Coloring}
+ GPLiveness1 = hipe_arm_specific:analyze(CFG1, no_context),
+ {CFG2, _GPLiveness2, Coloring}
= case proplists:get_value(regalloc, Options, coalescing) of
coalescing ->
- ra(CFG1, SpillIndex, Options, hipe_coalescing_regalloc);
+ ra(CFG1, GPLiveness1, SpillIndex, Options, hipe_coalescing_regalloc);
optimistic ->
- ra(CFG1, SpillIndex, Options, hipe_optimistic_regalloc);
+ ra(CFG1, GPLiveness1, SpillIndex, Options, hipe_optimistic_regalloc);
graph_color ->
- ra(CFG1, SpillIndex, Options, hipe_graph_coloring_regalloc);
+ ra(CFG1, GPLiveness1, SpillIndex, Options,
+ hipe_graph_coloring_regalloc);
linear_scan ->
- hipe_arm_ra_ls:ra(CFG1, SpillIndex, Options);
+ hipe_arm_ra_ls:ra(CFG1, GPLiveness1, SpillIndex, Options);
naive ->
- hipe_arm_ra_naive:ra(CFG1, Coloring_fp, Options);
+ hipe_arm_ra_naive:ra(CFG1, GPLiveness1, Coloring_fp, Options);
_ ->
exit({unknown_regalloc_compiler_option,
proplists:get_value(regalloc,Options)})
@@ -53,5 +56,6 @@ ra(CFG0, Options) ->
%% hipe_arm_pp:pp(hipe_arm_cfg:linearise(CFG2)),
hipe_arm_ra_finalise:finalise(CFG2, Coloring, Coloring_fp).
-ra(CFG, SpillIndex, Options, RegAllocMod) ->
- hipe_regalloc_loop:ra(CFG, SpillIndex, Options, RegAllocMod, hipe_arm_specific).
+ra(CFG, Liveness, SpillIndex, Options, RegAllocMod) ->
+ hipe_regalloc_loop:ra(CFG, Liveness, SpillIndex, Options, RegAllocMod,
+ hipe_arm_specific, no_context).
diff --git a/lib/hipe/arm/hipe_arm_ra_ls.erl b/lib/hipe/arm/hipe_arm_ra_ls.erl
index f9193ca9e0..0aa888da99 100644
--- a/lib/hipe/arm/hipe_arm_ra_ls.erl
+++ b/lib/hipe/arm/hipe_arm_ra_ls.erl
@@ -21,34 +21,35 @@
%%% Linear Scan register allocator for ARM
-module(hipe_arm_ra_ls).
--export([ra/3]).
+-export([ra/4]).
-ra(CFG, SpillIndex, Options) ->
- SpillLimit = hipe_arm_specific:number_of_temporaries(CFG),
- alloc(CFG, SpillIndex, SpillLimit, Options).
+ra(CFG, Liveness, SpillIndex, Options) ->
+ SpillLimit = hipe_arm_specific:number_of_temporaries(CFG, no_context),
+ alloc(CFG, Liveness, SpillIndex, SpillLimit, Options).
-alloc(CFG, SpillIndex, SpillLimit, Options) ->
- {Coloring, _NewSpillIndex, Liveness} =
+alloc(CFG, Liveness, SpillIndex, SpillLimit, Options) ->
+ {Coloring, _NewSpillIndex} =
regalloc(
- CFG,
+ CFG, Liveness,
hipe_arm_registers:allocatable_gpr()--
[hipe_arm_registers:temp3(),
hipe_arm_registers:temp2(),
hipe_arm_registers:temp1()],
[hipe_arm_cfg:start_label(CFG)],
SpillIndex, SpillLimit, Options,
- hipe_arm_specific),
+ hipe_arm_specific, no_context),
{NewCFG, _DidSpill} =
hipe_arm_ra_postconditions:check_and_rewrite(
CFG, Coloring, 'linearscan'),
- TempMap = hipe_temp_map:cols2tuple(Coloring, hipe_arm_specific),
+ TempMap = hipe_temp_map:cols2tuple(Coloring, hipe_arm_specific, no_context),
{SpillMap, _NewSpillIndex2} =
hipe_spillmin:stackalloc(CFG, Liveness, [], SpillIndex, Options,
- hipe_arm_specific, TempMap),
+ hipe_arm_specific, no_context, TempMap),
Coloring2 =
hipe_spillmin:mapmerge(hipe_temp_map:to_substlist(TempMap), SpillMap),
- {NewCFG, 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/arm/hipe_arm_ra_naive.erl b/lib/hipe/arm/hipe_arm_ra_naive.erl
index 0ea4b04092..395beff292 100644
--- a/lib/hipe/arm/hipe_arm_ra_naive.erl
+++ b/lib/hipe/arm/hipe_arm_ra_naive.erl
@@ -20,11 +20,11 @@
%%
-module(hipe_arm_ra_naive).
--export([ra/3]).
+-export([ra/4]).
-include("hipe_arm.hrl").
-ra(CFG, _Coloring_fp, _Options) -> % -> {CFG, Coloring}
+ra(CFG, Liveness, _Coloring_fp, _Options) -> % -> {CFG, Liveness, Coloring}
{NewCFG,_DidSpill} =
hipe_arm_ra_postconditions:check_and_rewrite2(CFG, [], 'naive'),
- {NewCFG, []}.
+ {NewCFG, Liveness, []}.
diff --git a/lib/hipe/arm/hipe_arm_ra_postconditions.erl b/lib/hipe/arm/hipe_arm_ra_postconditions.erl
index 04365f29b0..412524e2e6 100644
--- a/lib/hipe/arm/hipe_arm_ra_postconditions.erl
+++ b/lib/hipe/arm/hipe_arm_ra_postconditions.erl
@@ -26,7 +26,7 @@
-include("hipe_arm.hrl").
check_and_rewrite(CFG, Coloring, Allocator) ->
- TempMap = hipe_temp_map:cols2tuple(Coloring, hipe_arm_specific),
+ TempMap = hipe_temp_map:cols2tuple(Coloring, hipe_arm_specific, no_context),
check_and_rewrite2(CFG, TempMap, Allocator).
check_and_rewrite2(CFG, TempMap, Allocator) ->
diff --git a/lib/hipe/arm/hipe_arm_registers.erl b/lib/hipe/arm/hipe_arm_registers.erl
index dcf039676b..3ecf2f2fdb 100644
--- a/lib/hipe/arm/hipe_arm_registers.erl
+++ b/lib/hipe/arm/hipe_arm_registers.erl
@@ -180,6 +180,8 @@ is_arg(R) ->
_ -> false
end.
+%% Note: the fact that allocatable_gpr() is a subset of call_clobbered() is
+%% hard-coded in hipe_arm_defuse:insn_defs_all_gpr/1
call_clobbered() -> % does the RA strip the type or not?
[{?R0,tagged},{?R0,untagged},
{?R1,tagged},{?R1,untagged},
diff --git a/lib/hipe/arm/hipe_arm_subst.erl b/lib/hipe/arm/hipe_arm_subst.erl
new file mode 100644
index 0000000000..4d077f3cd6
--- /dev/null
+++ b/lib/hipe/arm/hipe_arm_subst.erl
@@ -0,0 +1,112 @@
+%% -*- 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_arm_subst).
+-export([insn_temps/2]).
+-include("hipe_arm.hrl").
+
+%% These should be moved to hipe_arm and exported
+-type temp() :: #arm_temp{}.
+-type shiftop() :: lsl | lsr | asr | ror.
+-type imm4() :: 0..15.
+-type imm5() :: 0..31.
+-type imm8() :: 0..255.
+-type am1() :: {imm8(),imm4()}
+ | temp()
+ | {temp(), rrx}
+ | {temp(), shiftop(), imm5()}
+ | {temp(), shiftop(), temp()}.
+-type am2() :: #am2{}.
+-type am3() :: #am3{}.
+-type arg() :: temp() | integer().
+-type funv() :: #arm_mfa{} | #arm_prim{} | temp().
+-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) ->
+ AM1 = fun(O) -> am1_temps(T, O) end,
+ AM2 = fun(O) -> am2_temps(T, O) end,
+ AM3 = fun(O) -> am3_temps(T, O) end,
+ Arg = fun(O) -> arg_temps(T, O) end,
+ case I of
+ #alu {dst=D,src=L,am1=R} -> I#alu{dst=T(D),src=T(L),am1=AM1(R)};
+ #cmp {src=L,am1=R} -> I#cmp {src=T(L),am1=AM1(R)};
+ #load {dst=D,am2=S} -> I#load {dst=T(D),am2=AM2(S)};
+ #ldrsb {dst=D,am3=S} -> I#ldrsb {dst=T(D),am3=AM3(S)};
+ #move {dst=D,am1=S} -> I#move {dst=T(D),am1=AM1(S)};
+ #pseudo_move{dst=D,src=S} -> I#pseudo_move {dst=T(D),src=T(S)};
+ #store {src=S,am2=D} -> I#store {src=T(S),am2=AM2(D)};
+ #b_label{} -> I;
+ #comment{} -> I;
+ #label{} -> I;
+ #pseudo_bc{} -> I;
+ #pseudo_blr{} -> I;
+ #pseudo_call{funv=F} -> I#pseudo_call{funv=funv_temps(T, F)};
+ #pseudo_call_prepare{} -> I;
+ #pseudo_li{dst=D} -> I#pseudo_li{dst=T(D)};
+ #pseudo_switch{jtab=J=#arm_temp{},index=Ix=#arm_temp{}} ->
+ I#pseudo_switch{jtab=T(J),index=T(Ix)};
+ #pseudo_tailcall{funv=F,stkargs=Stk} ->
+ I#pseudo_tailcall{funv=funv_temps(T,F),stkargs=lists:map(Arg,Stk)};
+ #pseudo_tailcall_prepare{} -> I;
+ #smull{dstlo=DL,dsthi=DH,src1=L,src2=R} ->
+ I#smull{dstlo=T(DL),dsthi=T(DH),src1=T(L),src2=T(R)}
+ end.
+
+-spec am1_temps(subst_fun(), am1()) -> am1().
+am1_temps(_SubstTemp, T={C,R}) when is_integer(C), is_integer(R) -> T;
+am1_temps(SubstTemp, T=#arm_temp{}) -> SubstTemp(T);
+am1_temps(SubstTemp, {T=#arm_temp{},rrx}) -> {SubstTemp(T),rrx};
+am1_temps(SubstTemp, {A=#arm_temp{},Op,B=#arm_temp{}}) when is_atom(Op) ->
+ {SubstTemp(A),Op,SubstTemp(B)};
+am1_temps(SubstTemp, {T=#arm_temp{},Op,I}) when is_atom(Op), is_integer(I) ->
+ {SubstTemp(T),Op,I}.
+
+-spec am2_temps(subst_fun(), am2()) -> am2().
+am2_temps(SubstTemp, T=#am2{src=A=#arm_temp{},offset=O0}) ->
+ O = case O0 of
+ _ when is_integer(O0) -> O0;
+ #arm_temp{} -> SubstTemp(O0);
+ {B=#arm_temp{},rrx} -> {SubstTemp(B),rrx};
+ {B=#arm_temp{},Op,I} when is_atom(Op), is_integer(I) ->
+ {SubstTemp(B),Op,I}
+ end,
+ T#am2{src=SubstTemp(A),offset=O}.
+
+-spec am3_temps(subst_fun(), am3()) -> am3().
+am3_temps(SubstTemp, T=#am3{src=A=#arm_temp{},offset=O0}) ->
+ O = case O0 of
+ _ when is_integer(O0) -> O0;
+ #arm_temp{} -> SubstTemp(O0)
+ end,
+ T#am3{src=SubstTemp(A),offset=O}.
+
+-spec funv_temps(subst_fun(), funv()) -> funv().
+funv_temps(_SubstTemp, M=#arm_mfa{}) -> M;
+funv_temps(_SubstTemp, P=#arm_prim{}) -> P;
+funv_temps(SubstTemp, T=#arm_temp{}) -> SubstTemp(T).
+
+-spec arg_temps(subst_fun(), arg()) -> arg().
+arg_temps(_SubstTemp, Imm) when is_integer(Imm) -> Imm;
+arg_temps(SubstTemp, T=#arm_temp{}) -> SubstTemp(T).