aboutsummaryrefslogtreecommitdiffstats
path: root/erts/emulator
diff options
context:
space:
mode:
authorBjörn Gustavsson <[email protected]>2019-03-15 07:47:39 +0100
committerBjörn Gustavsson <[email protected]>2019-03-19 16:02:00 +0100
commitffa22bf1013c7dfeeb7bbf846983dfe39deb7e52 (patch)
tree8f8001b603c275f73f67550ab4bee977bd0422da /erts/emulator
parentf55bb58c78ca3f82e89d0571b7b9541b983d2333 (diff)
downloadotp-ffa22bf1013c7dfeeb7bbf846983dfe39deb7e52.tar.gz
otp-ffa22bf1013c7dfeeb7bbf846983dfe39deb7e52.tar.bz2
otp-ffa22bf1013c7dfeeb7bbf846983dfe39deb7e52.zip
Optimize some common uses of '+' and '-'
Diffstat (limited to 'erts/emulator')
-rw-r--r--erts/emulator/beam/beam_load.c18
-rw-r--r--erts/emulator/beam/ops.tab12
2 files changed, 28 insertions, 2 deletions
diff --git a/erts/emulator/beam/beam_load.c b/erts/emulator/beam/beam_load.c
index 5961b7d743..c2a54c85ce 100644
--- a/erts/emulator/beam/beam_load.c
+++ b/erts/emulator/beam/beam_load.c
@@ -3679,6 +3679,24 @@ gen_increment_from_minus(LoaderState* stp, GenOpArg Reg,
return op;
}
+static GenOp*
+gen_plus_from_minus(LoaderState* stp, GenOpArg Fail, GenOpArg Live,
+ GenOpArg Src, GenOpArg Integer, GenOpArg Dst)
+{
+ GenOp* op;
+
+ NEW_GENOP(stp, op);
+ GENOP_NAME_ARITY(op, gen_plus, 5);
+ op->next = NULL;
+ op->a[0] = Fail;
+ op->a[1] = Live;
+ op->a[2] = Src;
+ op->a[3].type = TAG_i;
+ op->a[3].val = -Integer.val;
+ op->a[4] = Dst;
+ return op;
+}
+
/*
* Test whether the negation of the given number is small.
*/
diff --git a/erts/emulator/beam/ops.tab b/erts/emulator/beam/ops.tab
index d60e6d6b53..649d861c80 100644
--- a/erts/emulator/beam/ops.tab
+++ b/erts/emulator/beam/ops.tab
@@ -1613,6 +1613,11 @@ gen_minus p Live Reg=d Int=i Dst | negation_is_small(Int) => \
# Arithmetic instructions.
#
+# It is OK to swap arguments for '+' in a guard. It is also
+# OK to turn minus into plus in a guard.
+gen_plus Fail=f Live S1=c S2 Dst => i_plus S2 S1 Fail Dst
+gen_minus Fail=f Live S1 S2=i Dst => gen_plus_from_minus(Fail, Live, S1, S2, Dst)
+
gen_plus Fail Live S1 S2 Dst => i_plus S1 S2 Fail Dst
gen_minus Fail Live S1 S2 Dst => i_minus S1 S2 Fail Dst
@@ -1646,10 +1651,13 @@ gc_bif1 Fail Live u$bif:erlang:bnot/1 Src Dst=d => i_int_bnot Fail Src Dst
i_increment rxy W d
-i_plus x xy j? d
-i_plus s s j? d
+# Handle unoptimized code.
+i_plus S1=c S2=c Fail Dst => move S1 x | i_plus x S2 Fail Dst
+
+i_plus xy xyc j? d
i_minus x x j? d
+i_minus c x j? d
i_minus s s j? d
i_times j? s s d