aboutsummaryrefslogtreecommitdiffstats
path: root/lib/hipe/amd64/hipe_amd64_ra_sse2_postconditions.erl
diff options
context:
space:
mode:
authorErlang/OTP <[email protected]>2009-11-20 14:54:40 +0000
committerErlang/OTP <[email protected]>2009-11-20 14:54:40 +0000
commit84adefa331c4159d432d22840663c38f155cd4c1 (patch)
treebff9a9c66adda4df2106dfd0e5c053ab182a12bd /lib/hipe/amd64/hipe_amd64_ra_sse2_postconditions.erl
downloadotp-84adefa331c4159d432d22840663c38f155cd4c1.tar.gz
otp-84adefa331c4159d432d22840663c38f155cd4c1.tar.bz2
otp-84adefa331c4159d432d22840663c38f155cd4c1.zip
The R13B03 release.OTP_R13B03
Diffstat (limited to 'lib/hipe/amd64/hipe_amd64_ra_sse2_postconditions.erl')
-rw-r--r--lib/hipe/amd64/hipe_amd64_ra_sse2_postconditions.erl188
1 files changed, 188 insertions, 0 deletions
diff --git a/lib/hipe/amd64/hipe_amd64_ra_sse2_postconditions.erl b/lib/hipe/amd64/hipe_amd64_ra_sse2_postconditions.erl
new file mode 100644
index 0000000000..9ed3d01a56
--- /dev/null
+++ b/lib/hipe/amd64/hipe_amd64_ra_sse2_postconditions.erl
@@ -0,0 +1,188 @@
+%% -*- erlang-indent-level: 2 -*-
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2004-2009. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+%% the License for the specific language governing rights and limitations
+%% under the License.
+%%
+%% %CopyrightEnd%
+%%
+
+-module(hipe_amd64_ra_sse2_postconditions).
+
+-export([check_and_rewrite/2]).
+
+-include("../x86/hipe_x86.hrl").
+-define(HIPE_INSTRUMENT_COMPILER, true).
+-include("../main/hipe.hrl").
+-define(count_temp(T), ?cons_counter(counter_mfa_mem_temps, T)).
+
+
+check_and_rewrite(AMD64Defun, Coloring) ->
+ %%io:format("Converting\n"),
+ TempMap = hipe_temp_map:cols2tuple(Coloring,hipe_amd64_specific_sse2),
+ %%io:format("Rewriting\n"),
+ #defun{code=Code0} = AMD64Defun,
+ {Code1, DidSpill} = do_insns(Code0, TempMap, [], false),
+ {AMD64Defun#defun{code=Code1, var_range={0, hipe_gensym:get_var(x86)}},
+ DidSpill}.
+
+do_insns([I|Insns], TempMap, Accum, DidSpill0) ->
+ {NewIs, DidSpill1} = do_insn(I, TempMap),
+ do_insns(Insns, TempMap, lists:reverse(NewIs, Accum), DidSpill0 or DidSpill1);
+do_insns([], _TempMap, Accum, DidSpill) ->
+ {lists:reverse(Accum), DidSpill}.
+
+do_insn(I, TempMap) -> % Insn -> {Insn list, DidSpill}
+ case I of
+ #fmove{} ->
+ do_fmove(I, TempMap);
+ #fp_unop{} ->
+ do_fp_unop(I, TempMap);
+ #fp_binop{} ->
+ do_fp_binop(I, TempMap);
+ _ ->
+ %% All non sse2 ops
+ {[I], false}
+ end.
+
+%%% Fix an fp_binop.
+do_fp_binop(I, TempMap) ->
+ #fp_binop{src=Src,dst=Dst} = I,
+ case is_mem_opnd(Dst, TempMap) of
+ true ->
+ Tmp = clone(Dst),
+ {[#fmove{src=Dst, dst=Tmp},
+ I#fp_binop{src=Src,dst=Tmp},
+ #fmove{src=Tmp,dst=Dst}],
+ true};
+ false ->
+ {[I], false}
+ end.
+
+do_fp_unop(I, TempMap) ->
+ #fp_unop{arg=Arg} = I,
+ case is_mem_opnd(Arg, TempMap) of
+ true ->
+ Tmp = clone(Arg),
+ {[#fmove{src=Arg, dst=Tmp},
+ I#fp_unop{arg=Tmp},
+ #fmove{src=Tmp,dst=Arg}],
+ true};
+ false ->
+ {[I], false}
+ end.
+
+%%% Fix an fmove op.
+do_fmove(I, TempMap) ->
+ #fmove{src=Src,dst=Dst} = I,
+ case is_mem_opnd(Dst, TempMap) and is_mem_opnd(Src, TempMap) of
+ true ->
+ Tmp = clone(Src),
+ {[#fmove{src=Src, dst=Tmp},I#fmove{src=Tmp,dst=Dst}],
+ true};
+ false ->
+ {[I], false}
+ end.
+
+%%% Check if an operand denotes a memory cell (mem or pseudo).
+
+is_mem_opnd(Opnd, TempMap) ->
+ R =
+ case Opnd of
+ #x86_mem{} -> true;
+ #x86_temp{} ->
+ Reg = hipe_x86:temp_reg(Opnd),
+ case hipe_x86:temp_is_allocatable(Opnd) of
+ true ->
+ case tuple_size(TempMap) > Reg of
+ true ->
+ case
+ hipe_temp_map:is_spilled(Reg, TempMap) of
+ true ->
+ ?count_temp(Reg),
+ true;
+ false -> false
+ end;
+ _ -> false
+ end;
+ false -> true
+ end;
+ _ -> false
+ end,
+ %% io:format("Op ~w mem: ~w\n",[Opnd,R]),
+ R.
+
+%%% Check if an operand is a spilled Temp.
+
+%%src_is_spilled(Src, TempMap) ->
+%% case hipe_x86:is_temp(Src) of
+%% true ->
+%% Reg = hipe_x86:temp_reg(Src),
+%% case hipe_x86:temp_is_allocatable(Src) of
+%% true ->
+%% case tuple_size(TempMap) > Reg of
+%% true ->
+%% case hipe_temp_map:is_spilled(Reg, TempMap) of
+%% true ->
+%% ?count_temp(Reg),
+%% true;
+%% false ->
+%% false
+%% end;
+%% false ->
+%% false
+%% end;
+%% false -> true
+%% end;
+%% false -> false
+%% end.
+
+%% is_spilled(Temp, TempMap) ->
+%% case hipe_x86:temp_is_allocatable(Temp) of
+%% true ->
+%% Reg = hipe_x86:temp_reg(Temp),
+%% case tuple_size(TempMap) > Reg of
+%% true ->
+%% case hipe_temp_map:is_spilled(Reg, TempMap) of
+%% true ->
+%% ?count_temp(Reg),
+%% true;
+%% false ->
+%% false
+%% end;
+%% false ->
+%% false
+%% end;
+%% false -> true
+%% end.
+
+%%% Make Reg a clone of Dst (attach Dst's type to Reg).
+
+clone(Dst) ->
+ Type =
+ case Dst of
+ #x86_mem{} -> hipe_x86:mem_type(Dst);
+ #x86_temp{} -> hipe_x86:temp_type(Dst)
+ end,
+ hipe_x86:mk_new_temp(Type).
+
+%%% Make a certain reg into a clone of Dst
+
+%% clone2(Dst, Reg) ->
+%% Type =
+%% case Dst of
+%% #x86_mem{} -> hipe_x86:mem_type(Dst);
+%% #x86_temp{} -> hipe_x86:temp_type(Dst)
+%% end,
+%% hipe_x86:mk_temp(Reg,Type).