aboutsummaryrefslogtreecommitdiffstats
path: root/lib/hipe/sparc/hipe_sparc_ra_postconditions.erl
diff options
context:
space:
mode:
authorMagnus Lång <[email protected]>2017-03-16 15:30:00 +0100
committerMagnus Lång <[email protected]>2017-03-16 20:49:42 +0100
commitc52b2cf226cb3f1bb1b16bee28d47785506adff3 (patch)
treef016829f93e26db7fe7e2329ace868f4b2442510 /lib/hipe/sparc/hipe_sparc_ra_postconditions.erl
parentd1d26f4bf9da3cc5eab4e918df771d67fe9e6bb5 (diff)
downloadotp-c52b2cf226cb3f1bb1b16bee28d47785506adff3.tar.gz
otp-c52b2cf226cb3f1bb1b16bee28d47785506adff3.tar.bz2
otp-c52b2cf226cb3f1bb1b16bee28d47785506adff3.zip
hipe: Add pseudo_spill_f?move instructions
These pseudo instructions are added to all backends and allow spill slot to spill slot move coalescing in a clean way. They have regular move semantics, but contain an additional scratch register to be used if both source and destination are spilled, and can not be move coalesced. Additionally, a register allocator callback Target:is_spill_move(Instr, Context) is added which allows the spill slot allocators to check for these instructions and try to coalesce the spill slots the two temporaries are allocated to.
Diffstat (limited to 'lib/hipe/sparc/hipe_sparc_ra_postconditions.erl')
-rw-r--r--lib/hipe/sparc/hipe_sparc_ra_postconditions.erl24
1 files changed, 16 insertions, 8 deletions
diff --git a/lib/hipe/sparc/hipe_sparc_ra_postconditions.erl b/lib/hipe/sparc/hipe_sparc_ra_postconditions.erl
index 984c97fbd4..d3ecb43ec6 100644
--- a/lib/hipe/sparc/hipe_sparc_ra_postconditions.erl
+++ b/lib/hipe/sparc/hipe_sparc_ra_postconditions.erl
@@ -54,6 +54,7 @@ do_insn(I, TempMap, Strategy) ->
#pseudo_call{} -> do_pseudo_call(I, TempMap, Strategy);
#pseudo_move{} -> do_pseudo_move(I, TempMap, Strategy);
#pseudo_set{} -> do_pseudo_set(I, TempMap, Strategy);
+ #pseudo_spill_move{} -> do_pseudo_spill_move(I, TempMap, Strategy);
#pseudo_tailcall{} -> do_pseudo_tailcall(I, TempMap, Strategy);
#rdy{} -> do_rdy(I, TempMap, Strategy);
#sethi{} -> do_sethi(I, TempMap, Strategy);
@@ -92,14 +93,16 @@ do_pseudo_call(I=#pseudo_call{funv=FunV}, TempMap, Strategy) ->
do_pseudo_move(I=#pseudo_move{src=Src,dst=Dst}, TempMap, Strategy) ->
%% Either Dst or Src (but not both) may be a pseudo temp.
- %% pseudo_move is a special case: in [XXX: not pseudo_tailcall]
- %% all other instructions, all temps must be non-pseudos
- %% after register allocation.
- case temp_is_spilled(Dst, TempMap) of
- true -> % Src must not be a pseudo
- {FixSrc,NewSrc,DidSpill} = fix_src1(Src, TempMap, Strategy),
- NewI = I#pseudo_move{src=NewSrc},
- {FixSrc ++ [NewI], DidSpill};
+ %% pseudo_move and pseudo_spill_move [XXX: not pseudo_tailcall]
+ %% are special cases: in all other instructions, all temps must
+ %% be non-pseudos after register allocation.
+ case temp_is_spilled(Src, TempMap)
+ andalso temp_is_spilled(Dst, TempMap)
+ of
+ true -> % Turn into pseudo_spill_move
+ Temp = clone(Src, temp1(Strategy)),
+ NewI = #pseudo_spill_move{src=Src,temp=Temp,dst=Dst},
+ {[NewI], true};
_ ->
{[I], false}
end.
@@ -109,6 +112,11 @@ do_pseudo_set(I=#pseudo_set{dst=Dst}, TempMap, Strategy) ->
NewI = I#pseudo_set{dst=NewDst},
{[NewI | FixDst], DidSpill}.
+do_pseudo_spill_move(I=#pseudo_spill_move{temp=Temp}, TempMap, _Strategy) ->
+ %% Temp is above the low water mark and must not have been spilled
+ false = temp_is_spilled(Temp, TempMap),
+ {[I], false}.
+
do_pseudo_tailcall(I=#pseudo_tailcall{funv=FunV}, TempMap, Strategy) ->
{FixFunV,NewFunV,DidSpill} = fix_funv(FunV, TempMap, Strategy),
NewI = I#pseudo_tailcall{funv=NewFunV},