aboutsummaryrefslogtreecommitdiffstats
path: root/lib/hipe/x86/hipe_rtl_to_x86.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_rtl_to_x86.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_rtl_to_x86.erl')
-rw-r--r--lib/hipe/x86/hipe_rtl_to_x86.erl18
1 files changed, 17 insertions, 1 deletions
diff --git a/lib/hipe/x86/hipe_rtl_to_x86.erl b/lib/hipe/x86/hipe_rtl_to_x86.erl
index 79028b0652..4c8c98551c 100644
--- a/lib/hipe/x86/hipe_rtl_to_x86.erl
+++ b/lib/hipe/x86/hipe_rtl_to_x86.erl
@@ -85,7 +85,7 @@ conv_insn(I, Map, Data) ->
true ->
conv_shift(Dst, Src1, BinOp, Src2);
false ->
- conv_alu(Dst, Src1, BinOp, Src2, [])
+ conv_alu_nocc(Dst, Src1, BinOp, Src2, [])
end,
{FixSrc1++FixSrc2++I2, Map2, Data};
#alub{} ->
@@ -250,6 +250,22 @@ conv_insn(I, Map, Data) ->
%%% Finalise the conversion of a 3-address ALU operation, taking
%%% care to not introduce more temps and moves than necessary.
+conv_alu_nocc(Dst, Src1, 'add', Src2, Tail) ->
+ case (not same_opnd(Dst, Src1)) andalso (not same_opnd(Dst, Src2))
+ andalso (hipe_x86:is_temp(Src1) orelse hipe_x86:is_temp(Src2))
+ of
+ false -> conv_alu(Dst, Src1, 'add', Src2, Tail);
+ true -> % Use LEA
+ Type = typeof_dst(Dst),
+ Mem = case hipe_x86:is_temp(Src1) of
+ true -> hipe_x86:mk_mem(Src1, Src2, Type);
+ false -> hipe_x86:mk_mem(Src2, Src1, Type)
+ end,
+ [hipe_x86:mk_lea(Mem, Dst) | Tail]
+ end;
+conv_alu_nocc(Dst, Src1, BinOp, Src2, Tail) ->
+ conv_alu(Dst, Src1, BinOp, Src2, Tail).
+
conv_alu(Dst, Src1, 'imul', Src2, Tail) ->
mk_imul(Src1, Src2, Dst, Tail);
conv_alu(Dst, Src1, BinOp, Src2, Tail) ->