aboutsummaryrefslogtreecommitdiffstats
path: root/lib/hipe/x86/hipe_x86_ra_postconditions.erl
diff options
context:
space:
mode:
authorMagnus Lång <[email protected]>2016-06-04 20:10:02 +0200
committerMagnus Lång <[email protected]>2016-08-30 17:19:13 +0200
commit1567585dda8bc604871be06a37aa5d19ad6d28f3 (patch)
tree459dd0611f10364ee930227d63b5693baddd93cc /lib/hipe/x86/hipe_x86_ra_postconditions.erl
parentcca2b0a38dd4cbc3dfef026e0d8c2cba57270935 (diff)
downloadotp-1567585dda8bc604871be06a37aa5d19ad6d28f3.tar.gz
otp-1567585dda8bc604871be06a37aa5d19ad6d28f3.tar.bz2
otp-1567585dda8bc604871be06a37aa5d19ad6d28f3.zip
hipe_x86: Use lea instead of move+add
This is primarily useful for heap allocations, as a two-address 'add' can't be used to both copy the heap pointer to another register, and add the tag.
Diffstat (limited to 'lib/hipe/x86/hipe_x86_ra_postconditions.erl')
-rw-r--r--lib/hipe/x86/hipe_x86_ra_postconditions.erl24
1 files changed, 16 insertions, 8 deletions
diff --git a/lib/hipe/x86/hipe_x86_ra_postconditions.erl b/lib/hipe/x86/hipe_x86_ra_postconditions.erl
index 343d04977d..c73d029b9b 100644
--- a/lib/hipe/x86/hipe_x86_ra_postconditions.erl
+++ b/lib/hipe/x86/hipe_x86_ra_postconditions.erl
@@ -173,14 +173,22 @@ do_jmp_switch(I, TempMap, Strategy) ->
%%% Fix a lea op.
do_lea(I, TempMap, Strategy) ->
- #lea{temp=Temp} = I,
- case is_spilled(Temp, TempMap) of
- false ->
- {[I], false};
- true ->
- NewTmp = spill_temp('untagged', Strategy),
- {[I#lea{temp=NewTmp}, hipe_x86:mk_move(NewTmp, Temp)],
- true}
+ #lea{mem=Mem0,temp=Temp0} = I,
+ {FixMem, Mem, DidSpill1} = fix_mem_operand(Mem0, TempMap, temp1(Strategy)),
+ case Mem of
+ #x86_mem{base=Base, off=#x86_imm{value=0}} ->
+ %% We've decayed into a move due to both operands being memory (there's an
+ %% 'add' in FixMem).
+ {FixMem ++ [hipe_x86:mk_move(Base, Temp0)], DidSpill1};
+ #x86_mem{} ->
+ {StoreTemp, Temp, DidSpill2} =
+ case is_mem_opnd(Temp0, TempMap) of
+ false -> {[], Temp0, false};
+ true ->
+ Temp1 = clone2(Temp0, temp0(Strategy)),
+ {[hipe_x86:mk_move(Temp1, Temp0)], Temp1, true}
+ end,
+ {FixMem ++ [I#lea{mem=Mem,temp=Temp} | StoreTemp], DidSpill1 or DidSpill2}
end.
%%% Fix a move op.