aboutsummaryrefslogtreecommitdiffstats
path: root/lib/hipe
diff options
context:
space:
mode:
authorMagnus Lång <[email protected]>2016-10-02 13:23:52 +0200
committerMagnus Lång <[email protected]>2016-11-16 17:20:32 +0100
commitfda8d7909594d434c01fdc9610127d09d1499a43 (patch)
tree458b7ad7d08e8bfbe836810df877470415ceddbb /lib/hipe
parent921638f8b22479473482bdcaa25f8031ac85e7e8 (diff)
downloadotp-fda8d7909594d434c01fdc9610127d09d1499a43.tar.gz
otp-fda8d7909594d434c01fdc9610127d09d1499a43.tar.bz2
otp-fda8d7909594d434c01fdc9610127d09d1499a43.zip
hipe_tagscheme: Improve fixnum add on x86
With the introduction of immediate adds encoded as 'LEA' on x86, it is now possible to do a fixnum add in two instructions and one branch by commuting the addition and reusing the result register as a temporary, which makes the 'alub' a 2-address add, saving a move instruction.
Diffstat (limited to 'lib/hipe')
-rw-r--r--lib/hipe/rtl/hipe_tagscheme.erl15
1 files changed, 10 insertions, 5 deletions
diff --git a/lib/hipe/rtl/hipe_tagscheme.erl b/lib/hipe/rtl/hipe_tagscheme.erl
index 8d9514ae82..305aacb571 100644
--- a/lib/hipe/rtl/hipe_tagscheme.erl
+++ b/lib/hipe/rtl/hipe_tagscheme.erl
@@ -510,21 +510,26 @@ unsafe_fixnum_sub(Arg1, Arg2, Res) ->
%%% (16X+tag)+((16Y+tag)-tag) = 16X+tag+16Y = 16(X+Y)+tag
%%% (16X+tag)-((16Y+tag)-tag) = 16X+tag-16Y = 16(X-Y)+tag
fixnum_addsub(AluOp, Arg1, Arg2, Res, OtherLab) ->
- Tmp = hipe_rtl:mk_new_reg_gcsafe(),
+ NoOverflowLab = hipe_rtl:mk_new_label(),
%% XXX: Consider moving this test to the users of fixnum_addsub.
case Arg1 =/= Res andalso Arg2 =/= Res of
true ->
%% Args differ from res.
- NoOverflowLab = hipe_rtl:mk_new_label(),
- [hipe_rtl:mk_alu(Tmp, Arg2, sub, hipe_rtl:mk_imm(?TAG_IMMED1_SMALL)),
- hipe_rtl:mk_alub(Res, Arg1, AluOp, Tmp, not_overflow,
+ %% Commute add to save a move on x86
+ {UntagFirst, Lhs, Rhs} =
+ case AluOp of
+ 'add' -> {Arg1, Res, Arg2};
+ 'sub' -> {Arg2, Arg1, Res}
+ end,
+ [hipe_rtl:mk_alu(Res, UntagFirst, sub, hipe_rtl:mk_imm(?TAG_IMMED1_SMALL)),
+ hipe_rtl:mk_alub(Res, Lhs, AluOp, Rhs, not_overflow,
hipe_rtl:label_name(NoOverflowLab),
hipe_rtl:label_name(OtherLab), 0.99),
NoOverflowLab];
false ->
%% At least one of the arguments is the same as Res.
+ Tmp = hipe_rtl:mk_new_reg_gcsafe(),
Tmp2 = hipe_rtl:mk_new_var(), % XXX: shouldn't this var be a reg?
- NoOverflowLab = hipe_rtl:mk_new_label(),
[hipe_rtl:mk_alu(Tmp, Arg2, sub, hipe_rtl:mk_imm(?TAG_IMMED1_SMALL)),
hipe_rtl:mk_alub(Tmp2, Arg1, AluOp, Tmp, not_overflow,
hipe_rtl:label_name(NoOverflowLab),