Sign Up
Log In
Log In
or
Sign Up
Places
All Projects
Status Monitor
Collapse sidebar
home:Ledest:erlang:26
erlang
1023-Undo-instruction-combination-optimizations...
Overview
Repositories
Revisions
Requests
Users
Attributes
Meta
File 1023-Undo-instruction-combination-optimizations.patch of Package erlang
From f302db9ba2d1e83f8349a1f376cd5c101310ecaa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Gustavsson?= <bjorn@erlang.org> Date: Wed, 10 May 2023 08:18:15 +0200 Subject: [PATCH 3/5] Undo instruction combination optimizations As a refactoring preparing to generate C code, undo some of optimizations that combine instructions in the transform engine. --- erts/emulator/beam/beam_transform_engine.c | 93 ++------------- erts/emulator/utils/beam_makeops | 128 +++++---------------- 2 files changed, 38 insertions(+), 183 deletions(-) diff --git a/erts/emulator/beam/beam_transform_engine.c b/erts/emulator/beam/beam_transform_engine.c index 3ce934a48c..7891c901df 100644 --- a/erts/emulator/beam/beam_transform_engine.c +++ b/erts/emulator/beam/beam_transform_engine.c @@ -83,51 +83,17 @@ erts_transform_engine(LoaderState* st) if (((1 << instr->a[ap].type) & mask) == 0) goto restart; break; -#if defined(TOP_is_type_next_arg) - case TOP_is_type_next_arg: - mask = *pc++; - ASSERT(ap < instr->arity); - ASSERT(instr->a[ap].type < BEAM_NUM_TAGS); - if (((1 << instr->a[ap].type) & mask) == 0) - goto restart; - ap++; - break; -#endif case TOP_pred: i = *pc++; i = erts_beam_eval_predicate((unsigned) i, st, var, rest_args); if (i == 0) goto restart; break; -#if defined(TOP_is_eq) case TOP_is_eq: ASSERT(ap < instr->arity); if (*pc++ != instr->a[ap].val) goto restart; break; -#endif - case TOP_is_type_eq: - mask = *pc++; - - ASSERT(ap < instr->arity); - ASSERT(instr->a[ap].type < BEAM_NUM_TAGS); - if (((1 << instr->a[ap].type) & mask) == 0) - goto restart; - if (*pc++ != instr->a[ap].val) - goto restart; - break; -#if defined(TOP_is_type_eq_next_arg) - case TOP_is_type_eq_next_arg: - mask = *pc++; - ASSERT(ap < instr->arity); - ASSERT(instr->a[ap].type < BEAM_NUM_TAGS); - if (((1 << instr->a[ap].type) & mask) == 0) - goto restart; - if (*pc++ != instr->a[ap].val) - goto restart; - ap++; - break; -#endif #if defined(TOP_is_bif) case TOP_is_bif: { @@ -249,50 +215,12 @@ erts_transform_engine(LoaderState* st) } break; #endif - case TOP_set_var_next_arg: + case TOP_set_var: ASSERT(ap < instr->arity); i = *pc++; ASSERT(i < TE_MAX_VARS); - var[i].type = instr->a[ap].type; - var[i].val = instr->a[ap].val; - ap++; - break; -#if defined(TOP_is_type_set_var_next_arg) - case TOP_is_type_set_var_next_arg: - mask = pc[0]; - i = pc[1]; - ASSERT(i < TE_MAX_VARS); - ASSERT(ap < instr->arity); - ASSERT(instr->a[ap].type < BEAM_NUM_TAGS); - if (((1 << instr->a[ap].type) & mask) == 0) - goto restart; - ASSERT(i < TE_MAX_VARS); var[i] = instr->a[ap]; - ap++; - pc += 2; - break; -#endif -#if defined(TOP_is_type_eq_set_var_next_arg) - case TOP_is_type_eq_set_var_next_arg: - { - Eterm val; - mask = pc[0]; - val = pc[1]; - i = pc[2]; - ASSERT(i < TE_MAX_VARS); - ASSERT(ap < instr->arity); - ASSERT(instr->a[ap].type < BEAM_NUM_TAGS); - if (((1 << instr->a[ap].type) & mask) == 0) - goto restart; - if (val != instr->a[ap].val) - goto restart; - ASSERT(i < TE_MAX_VARS); - var[i] = instr->a[ap]; - ap++; - pc += 3; - } break; -#endif #if defined(TOP_rest_args) case TOP_rest_args: { @@ -331,8 +259,8 @@ erts_transform_engine(LoaderState* st) keep = instr; break; #endif -#if defined(TOP_call_end) - case TOP_call_end: +#if defined(TOP_call) + case TOP_call: { BeamOp** lastp; BeamOp* new_instr; @@ -352,7 +280,7 @@ erts_transform_engine(LoaderState* st) *lastp = keep; instr = new_instr; } - /* FALLTHROUGH */ + break; #endif case TOP_end: st->genop = instr; @@ -382,18 +310,15 @@ erts_transform_engine(LoaderState* st) instr->arity = gen_opc[op].arity; return TE_OK; #endif - case TOP_store_val_next_arg: + case TOP_store_val: instr->a[ap].type = pc[0]; instr->a[ap].val = pc[1]; - ap++; pc += 2; break; - case TOP_store_var_next_arg: + case TOP_store_var: i = *pc++; ASSERT(i < TE_MAX_VARS); - instr->a[ap].type = var[i].type; - instr->a[ap].val = var[i].val; - ap++; + instr->a[ap] = var[i]; break; #if defined(TOP_store_rest_args) case TOP_store_rest_args: @@ -416,6 +341,10 @@ erts_transform_engine(LoaderState* st) case TOP_try_me_else_fail: restart = restart_fail; break; +#if defined(TOP_nop) + case TOP_nop: + break; +#endif case TOP_fail: return TE_FAIL; #if defined(TOP_skip_unless) diff --git a/erts/emulator/utils/beam_makeops b/erts/emulator/utils/beam_makeops index c7ea032026..57f9d0fe49 100755 --- a/erts/emulator/utils/beam_makeops +++ b/erts/emulator/utils/beam_makeops @@ -2835,13 +2835,7 @@ sub tr_gen_from { $types .= "$_ "; $type_mask |= $type_bit{$_}; } - if ($cond ne 'is_eq') { - push(@code, make_op($types, 'is_type', $type_mask)); - } else { - $cond = ''; - push(@code, make_op("$types== $val", 'is_type_eq', - $type_mask, $val)); - } + push(@code, make_op($types, 'is_type', $type_mask)); } } @@ -2883,14 +2877,7 @@ sub tr_gen_from { push(@code, make_op($var, 'set_var', $var{$var})); } } - if (is_instr($code[$#code], 'set_var')) { - my $ref = pop @code; - my $comment = $ref->[2]; - my $var = $ref->[1][1]; - push(@code, make_op($comment, 'set_var_next_arg', $var)); - } else { - push(@code, make_op($ignored_var, 'next_arg')); - } + push(@code, make_op($ignored_var, 'next_arg')); } # Remove redundant 'next_arg' instructions before the end @@ -2903,39 +2890,6 @@ sub tr_gen_from { # push(@code, make_op($may_fail ? '' : 'always reached', 'commit')); - # - # Peephole optimization: combine instructions. - # - for (my $i = 0; $i < @code; $i++) { - if (is_instr($code[$i], 'is_type')) { - my(undef, $is_type_ref, $type_comment) = @{$code[$i]}; - if (is_instr($code[$i+1], 'set_var_next_arg')) { - my(undef, $next_ref, $next_comment) = @{$code[$i+1]}; - my $comment = "$type_comment $next_comment"; - my $op = make_op($comment, 'is_type_set_var_next_arg', - $is_type_ref->[1], $next_ref->[1]); - splice @code, $i, 2, ($op); - } elsif (is_instr($code[$i+1], 'next_arg')) { - my $op = make_op($type_comment, 'is_type_next_arg', $is_type_ref->[1]); - splice @code, $i, 2, ($op); - } - } elsif (is_instr($code[$i], 'is_type_eq')) { - my(undef, $is_type_ref, $type_comment) = @{$code[$i]}; - if (is_instr($code[$i+1], 'set_var_next_arg')) { - my(undef, $next_ref, $next_comment) = @{$code[$i+1]}; - my $comment = "$type_comment $next_comment"; - my $op = make_op($comment, 'is_type_eq_set_var_next_arg', - $is_type_ref->[1], $is_type_ref->[2], - $next_ref->[1]); - splice @code, $i, 2, ($op); - } elsif (is_instr($code[$i+1], 'next_arg')) { - my $op = make_op($type_comment, 'is_type_eq_next_arg', - $is_type_ref->[1], $is_type_ref->[2]); - splice @code, $i, 2, ($op); - } - } - } - $te_max_vars = $var_num if $te_max_vars < $var_num; [\%var, \%var_type, \@instrs, \@code]; @@ -2984,7 +2938,7 @@ sub tr_gen_to { pop(@code); # Get rid of 'commit' instruction my $index = next_tr_index(\@call_table, \%call_table, $name, @args); - my $op = make_op("$name()", 'call_end', $index); + my $op = make_op("$name()", 'call', $index); my @slots = grep(/^\d+/, map { $var{$_} } @ops); op_slot_usage($op, @slots); push(@code, $op); @@ -3013,21 +2967,22 @@ sub tr_gen_to { } elsif ($var ne '') { error($where, "variable '$var' unbound") unless defined $var{$var}; - my $op = make_op($var, 'store_var_next_arg', $var{$var}); + my $op = make_op($var, 'store_var', $var{$var}); op_slot_usage($op, $var{$var}); - push(@code, $op); + my $next_arg = make_op('', 'next_arg'); + push @code, $op, $next_arg; } elsif ($type ne '') { my $val = $type_val || 0; my $comment = "$type=$val"; - my $op = make_op($comment, 'store_val_next_arg', "TAG_$type", $val); - push @code, $op; + my $store_val = make_op($comment, 'store_val', "TAG_$type", $val); + my $next_arg = make_op('', 'next_arg'); + push @code, $store_val, $next_arg; } } pop(@code) if is_instr($code[$#code], 'next_arg'); } - push(@code, make_op('', 'end')) - unless is_instr($code[$#code], 'call_end'); + push(@code, make_op('', 'end')); tr_maybe_keep(\@code); tr_maybe_rename(\@code); @@ -3162,7 +3117,8 @@ sub group_tr { sub tr_maybe_keep { my($ref) = @_; - my @last_instr; + my $ap = 1; + my @last_instr = ('unknown','ignored'); my $pos; my $reused_instr; @@ -3171,21 +3127,21 @@ sub tr_maybe_keep { my($size, $instr_ref, $comment) = @$instr; my($op, @args) = @$instr_ref; if ($op eq 'next_instr') { - @last_instr = ($args[0]); - } elsif ($op eq 'set_var_next_arg') { - push @last_instr, $args[0]; - } elsif ($op eq 'is_type_set_var_next_arg') { - push @last_instr, $args[1]; - } elsif ($op eq 'is_type_eq_set_var_next_arg') { - push @last_instr, $args[2]; + @last_instr = ($args[0],'ignored'); + $ap = 1; } elsif ($op eq 'next_arg') { - push @last_instr, 'ignored'; + $ap++; + $last_instr[$ap] = 'ignored' + unless defined $pos; + } elsif ($op eq 'set_var') { + $last_instr[$ap] = $args[0]; } elsif ($op eq 'new_instr') { unless (defined $pos) { # 'new_instr' immediately after 'commit'. $reused_instr = $args[0]; - return unless shift(@last_instr) == $reused_instr; + return unless $last_instr[0] == $reused_instr; $pos = $i - 1; + $ap = 1; } else { # Second 'new_instr' after 'commit'. The instructions # from $pos up to and including $i - 1 rebuilds the @@ -3196,8 +3152,8 @@ sub tr_maybe_keep { splice @$ref, $pos, $i-$pos, ($reuse); return; } - } elsif ($op eq 'store_var_next_arg') { - return unless @last_instr and shift(@last_instr) eq $args[0]; + } elsif ($op eq 'store_var') { + return unless $last_instr[$ap] eq $args[0]; } elsif (defined $pos) { return; } @@ -3235,26 +3191,7 @@ sub tr_maybe_rename { 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 'is_type_set_var_next_arg') { - if ($num_args == $a and $args[1] == $a) { - $num_args++; - } - $a++; - } elsif ($op eq 'is_type_eq_set_var_next_arg') { - if ($num_args == $a and $args[2] == $a) { - $num_args++; - } - $a++; - } elsif ($op eq 'next_arg') { - $a++; - } elsif ($op eq 'is_type_next_arg') { - $a++; - } elsif ($op eq 'is_type_eq_next_arg') { + if ($op eq 'next_arg') { $a++; } elsif ($op eq 'commit') { $a = 0; @@ -3272,9 +3209,7 @@ sub tr_maybe_rename { return; } } elsif ($s eq 'right') { - if ($op eq 'store_var_next_arg' && $args[0] == $a) { - $a++; - } elsif ($op eq 'end' && $a <= $num_args) { + if ($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); @@ -3303,19 +3238,10 @@ sub tr_remove_unused { for my $instr (@$ref) { my($size, $instr_ref, $comment) = @$instr; my($op, @args) = @$instr_ref; - if ($op eq 'set_var_next_arg') { + if ($op eq 'set_var') { my $var = $args[0]; next if $used{$var}; - $instr = make_op("$comment (ignored)", 'next_arg'); - } elsif ($op eq 'is_type_set_var_next_arg') { - my($type,$var) = @args; - next if $used{$var}; - $instr = make_op("$comment (ignored)", 'is_type_next_arg', $type); - } elsif ($op eq 'is_type_eq_set_var_next_arg') { - my($type,$val,$var) = @args; - next if $used{$var}; - $instr = make_op("$comment (ignored)", 'is_type_eq_next_arg', - $type, $val); + $instr = make_op("(ignoring unused variable $comment)", 'nop'); } } -- 2.35.3
Locations
Projects
Search
Status Monitor
Help
OpenBuildService.org
Documentation
API Documentation
Code of Conduct
Contact
Support
@OBShq
Terms
openSUSE Build Service is sponsored by
The Open Build Service is an
openSUSE project
.
Sign Up
Log In
Places
Places
All Projects
Status Monitor