aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBjörn Gustavsson <[email protected]>2015-12-07 16:12:21 +0100
committerBjörn Gustavsson <[email protected]>2016-04-07 15:28:29 +0200
commite93a66110aa27a5b8228fb46a3459a6de0e626d0 (patch)
tree856ab34d2bcf08fdbb7a6360534c842f6b5a8f15
parentc6cabe0b76dda183d209498e1e4e13e3407dcf9b (diff)
downloadotp-e93a66110aa27a5b8228fb46a3459a6de0e626d0.tar.gz
otp-e93a66110aa27a5b8228fb46a3459a6de0e626d0.tar.bz2
otp-e93a66110aa27a5b8228fb46a3459a6de0e626d0.zip
Introduce a 'rename' instruction
Introduce a 'rename' instruction that can be used to optimize simple renaming with unchanged operands such as: get_tuple_element Reg P Dst => i_get_tuple_element Reg P Dst By allowing it to lower the arity of instruction, transformations such as the following can be handled: trim N Remaining => i_trim N All in all, currently 67 transformations can be optimized in this way, including some commonly used ones.
-rw-r--r--erts/emulator/beam/beam_load.c6
-rwxr-xr-xerts/emulator/utils/beam_makeops55
2 files changed, 61 insertions, 0 deletions
diff --git a/erts/emulator/beam/beam_load.c b/erts/emulator/beam/beam_load.c
index 5d03c98657..ad174664ae 100644
--- a/erts/emulator/beam/beam_load.c
+++ b/erts/emulator/beam/beam_load.c
@@ -5077,6 +5077,12 @@ transform_engine(LoaderState* st)
instr->arity = gen_opc[op].arity;
ap = 0;
break;
+#ifdef TOP_rename
+ case TOP_rename:
+ instr->op = op = *pc++;
+ instr->arity = gen_opc[op].arity;
+ return TE_OK;
+#endif
case TOP_store_type:
i = *pc++;
instr->a[ap].type = i;
diff --git a/erts/emulator/utils/beam_makeops b/erts/emulator/utils/beam_makeops
index 8f99fdb201..3d4213d55d 100755
--- a/erts/emulator/utils/beam_makeops
+++ b/erts/emulator/utils/beam_makeops
@@ -1718,6 +1718,8 @@ sub tr_gen_to {
push(@code, make_op('', 'end'))
unless is_instr($code[$#code], 'call_end');
+ tr_maybe_rename(\@code);
+
#
# Chain together all codes segments having the same first operation.
#
@@ -1743,6 +1745,59 @@ sub tr_gen_to {
push(@{$gen_transform{$key}}, @code),
}
+sub tr_maybe_rename {
+ my($ref) = @_;
+ my $s = 'left';
+ my $a = 0;
+ my $num_args = 0;
+ my $new_instr;
+ my $first;
+ my $i;
+
+ for ($i = 1; $i < @$ref; $i++) {
+ my $instr = $$ref[$i];
+ my($size, $instr_ref, $comment) = @$instr;
+ my($op, @args) = @$instr_ref;
+
+ if ($s eq 'left') {
+ if ($op eq 'set_var_next_arg') {
+ if ($num_args == $a and $args[0] == $a) {
+ $num_args++;
+ }
+ $a++;
+ } elsif ($op eq 'next_arg') {
+ $a++;
+ } elsif ($op eq 'commit') {
+ $a = 0;
+ $first = $i;
+ $s = 'committed';
+ } elsif ($op eq 'next_instr') {
+ return;
+ }
+ } elsif ($s eq 'committed') {
+ if ($op eq 'new_instr') {
+ $new_instr = $args[0];
+ $a = 0;
+ $s = 'right';
+ } else {
+ return;
+ }
+ } elsif ($s eq 'right') {
+ if ($op eq 'store_var_next_arg' && $args[0] == $a) {
+ $a++;
+ } elsif ($op eq 'end' && $a <= $num_args) {
+ my $name = $gen_opname[$new_instr];
+ my $arity = $gen_arity[$new_instr];
+ my $new_op = make_op("$name/$arity", 'rename', $new_instr);
+ splice @$ref, $first, $i-$first+1, ($new_op);
+ return;
+ } else {
+ return;
+ }
+ }
+ }
+}
+
sub tr_code_len {
my($sum) = 0;
my($ref);