From 84adefa331c4159d432d22840663c38f155cd4c1 Mon Sep 17 00:00:00 2001 From: Erlang/OTP Date: Fri, 20 Nov 2009 14:54:40 +0000 Subject: The R13B03 release. --- lib/hipe/ppc/hipe_ppc_ra_postconditions_fp.erl | 130 +++++++++++++++++++++++++ 1 file changed, 130 insertions(+) create mode 100644 lib/hipe/ppc/hipe_ppc_ra_postconditions_fp.erl (limited to 'lib/hipe/ppc/hipe_ppc_ra_postconditions_fp.erl') diff --git a/lib/hipe/ppc/hipe_ppc_ra_postconditions_fp.erl b/lib/hipe/ppc/hipe_ppc_ra_postconditions_fp.erl new file mode 100644 index 0000000000..889c5681ac --- /dev/null +++ b/lib/hipe/ppc/hipe_ppc_ra_postconditions_fp.erl @@ -0,0 +1,130 @@ +%% -*- 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_ppc_ra_postconditions_fp). +-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}. + +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) -> + case I of + #lfd{} -> do_lfd(I, TempMap); + #lfdx{} -> do_lfdx(I, TempMap); + #stfd{} -> do_stfd(I, TempMap); + #stfdx{} -> do_stfdx(I, TempMap); + #fp_binary{} -> do_fp_binary(I, TempMap); + #fp_unary{} -> do_fp_unary(I, TempMap); + #pseudo_fmove{} -> do_pseudo_fmove(I, TempMap); + _ -> {[I], false} + end. + +%%% Fix relevant instruction types. + +do_lfd(I=#lfd{dst=Dst}, TempMap) -> + {FixDst, NewDst, DidSpill} = fix_dst(Dst, TempMap), + NewI = I#lfd{dst=NewDst}, + {[NewI | FixDst], DidSpill}. + +do_lfdx(I=#lfdx{dst=Dst}, TempMap) -> + {FixDst, NewDst, DidSpill} = fix_dst(Dst, TempMap), + NewI = I#lfdx{dst=NewDst}, + {[NewI | FixDst], DidSpill}. + +do_stfd(I=#stfd{src=Src}, TempMap) -> + {FixSrc, NewSrc, DidSpill} = fix_src(Src, TempMap), + NewI = I#stfd{src=NewSrc}, + {FixSrc ++ [NewI], DidSpill}. + +do_stfdx(I=#stfdx{src=Src}, TempMap) -> + {FixSrc, NewSrc, DidSpill} = fix_src(Src, TempMap), + NewI = I#stfdx{src=NewSrc}, + {FixSrc ++ [NewI], DidSpill}. + +do_fp_binary(I=#fp_binary{dst=Dst,src1=Src1,src2=Src2}, TempMap) -> + {FixDst,NewDst,DidSpill1} = fix_dst(Dst, TempMap), + {FixSrc1,NewSrc1,DidSpill2} = fix_src(Src1, TempMap), + {FixSrc2,NewSrc2,DidSpill3} = fix_src(Src2, TempMap), + NewI = I#fp_binary{dst=NewDst,src1=NewSrc1,src2=NewSrc2}, + {FixSrc1 ++ FixSrc2 ++ [NewI | FixDst], DidSpill1 or DidSpill2 or DidSpill3}. + +do_fp_unary(I=#fp_unary{dst=Dst,src=Src}, TempMap) -> + {FixDst,NewDst,DidSpill1} = fix_dst(Dst, TempMap), + {FixSrc,NewSrc,DidSpill2} = fix_src(Src, TempMap), + NewI = I#fp_unary{dst=NewDst,src=NewSrc}, + {FixSrc ++ [NewI | FixDst], DidSpill1 or DidSpill2}. + +do_pseudo_fmove(I=#pseudo_fmove{dst=Dst,src=Src}, TempMap) -> + case temp_is_spilled(Dst, TempMap) of + true -> + {FixSrc,NewSrc,DidSpill} = fix_src(Src, TempMap), + NewI = I#pseudo_fmove{src=NewSrc}, + {FixSrc ++ [NewI], DidSpill}; + _ -> + {[I], false} + end. + +%%% Fix Dst and Src operands. + +fix_src(Src, TempMap) -> + case temp_is_spilled(Src, TempMap) of + true -> + NewSrc = clone(Src), + {[hipe_ppc:mk_pseudo_fmove(NewSrc, Src)], NewSrc, true}; + _ -> + {[], Src, false} + end. + +fix_dst(Dst, TempMap) -> + case temp_is_spilled(Dst, TempMap) of + true -> + NewDst = clone(Dst), + {[hipe_ppc:mk_pseudo_fmove(Dst, NewDst)], NewDst, true}; + _ -> + {[], Dst, false} + end. + +%%% Check if an operand is a pseudo-temp. + +temp_is_spilled(Temp, TempMap) -> + case hipe_ppc:temp_is_allocatable(Temp) of + true -> + Reg = hipe_ppc:temp_reg(Temp), + tuple_size(TempMap) > Reg andalso hipe_temp_map:is_spilled(Reg, TempMap); + false -> true + end. + +%%% Create a new temp with the same type as an old one. + +clone(Temp) -> + Type = hipe_ppc:temp_type(Temp), % XXX: always double? + hipe_ppc:mk_new_temp(Type). -- cgit v1.2.3