diff options
author | Magnus Lång <[email protected]> | 2016-06-04 20:10:02 +0200 |
---|---|---|
committer | Magnus Lång <[email protected]> | 2016-08-30 17:19:13 +0200 |
commit | 1567585dda8bc604871be06a37aa5d19ad6d28f3 (patch) | |
tree | 459dd0611f10364ee930227d63b5693baddd93cc /lib/hipe/x86/hipe_rtl_to_x86.erl | |
parent | cca2b0a38dd4cbc3dfef026e0d8c2cba57270935 (diff) | |
download | otp-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.erl | 18 |
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) -> |