diff options
author | Björn Gustavsson <[email protected]> | 2015-12-07 16:12:21 +0100 |
---|---|---|
committer | Björn Gustavsson <[email protected]> | 2016-04-07 15:28:29 +0200 |
commit | e93a66110aa27a5b8228fb46a3459a6de0e626d0 (patch) | |
tree | 856ab34d2bcf08fdbb7a6360534c842f6b5a8f15 | |
parent | c6cabe0b76dda183d209498e1e4e13e3407dcf9b (diff) | |
download | otp-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.c | 6 | ||||
-rwxr-xr-x | erts/emulator/utils/beam_makeops | 55 |
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); |