diff options
author | Björn Gustavsson <[email protected]> | 2017-10-04 20:44:47 +0200 |
---|---|---|
committer | Björn Gustavsson <[email protected]> | 2017-10-09 11:28:40 +0200 |
commit | c2e746117b24235b8f2c508ef8f90e35ad422bf2 (patch) | |
tree | b9ae6f61acdf136018fdeb4667bbd9e0281668c1 | |
parent | a71ffb9c1b9de6ccc7b8d2278361474b373802c3 (diff) | |
download | otp-c2e746117b24235b8f2c508ef8f90e35ad422bf2.tar.gz otp-c2e746117b24235b8f2c508ef8f90e35ad422bf2.tar.bz2 otp-c2e746117b24235b8f2c508ef8f90e35ad422bf2.zip |
Pack operands for combined instructions into the instruction word
The operands for the first part of a combined instruction (the entry
point following the OpCase() label) can safely be packed into the
instruction word.
This commit will make each of the following instructions one word
shorter:
bs_context_to_binary_x
i_band_xcjtd
i_bs_get_binary_all_reuse_xft
i_bs_get_integer_imm_xWtftx
i_bs_get_integer_small_imm_xWftx
i_bs_init_bits_fail_xjtx
i_bs_init_bits_fail_yjtx
i_bs_init_bits_fail_heap_sIjtx
i_bs_init_bits_heap_WItx
i_bs_init_fail_xjtx
i_bs_init_fail_yjtx
i_bs_init_fail_heap_sIjtx
i_bs_init_heap_WItx
i_bs_start_match2_xfttx
i_bs_start_match2_yfttx
i_element_xjsd
i_element_yjsd
i_fast_element_xjId
i_fast_element_yjId
i_increment_xWtd
i_increment_yWtd
i_jump_on_val_xfIW
i_jump_on_val_yfIW
i_jump_on_val_zero_xfI
i_jump_on_val_zero_yfI
i_minus_xxjtd
i_plus_xxjtd
i_plus_xyjtd
i_put_tuple_xI
i_put_tuple_yI
i_rem_xxjtd
i_select_tuple_arity_xfI
i_select_tuple_arity_yfI
i_select_tuple_arity2_xfAA
i_select_tuple_arity2_yfAA
i_select_val2_xfcc
i_select_val2_yfcc
i_select_val_bins_xfI
i_select_val_bins_yfI
i_select_val_lins_xfI
i_select_val_lins_yfI
-rwxr-xr-x | erts/emulator/utils/beam_makeops | 41 |
1 files changed, 32 insertions, 9 deletions
diff --git a/erts/emulator/utils/beam_makeops b/erts/emulator/utils/beam_makeops index 50dd534828..d7791d23fa 100755 --- a/erts/emulator/utils/beam_makeops +++ b/erts/emulator/utils/beam_makeops @@ -1129,9 +1129,28 @@ sub combine_instruction_group { # Variables. my %offsets; my @instrs; - my %num_references; + my %num_references; # Number of references from other sub instructions. my $group_size = 999; + # + # Calculate the number of references from other sub instructions. + # This number is useful in several ways: + # + # * If this number is 0, it is only used as the entry point for a + # function, implying that it does not need a label and that operands + # can be packed into the instruction word. + # + # * We'll use this number in the sort key, as a tie breaker for sub instructions + # at the same instruction offset. + # + foreach my $ref_instr (@in_instrs) { + my(undef,undef,$first_sub,@other_subs) = @$ref_instr; + $num_references{$first_sub} += 0; # Make sure it is defined. + foreach my $sub (@other_subs) { + $num_references{$sub}++; + } + } + # Do basic error checking. Associate operands of instructions # with the correct micro instructions. Calculate offsets for micro # instructions. @@ -1157,12 +1176,13 @@ sub combine_instruction_group { foreach (0..$#c_args) { push @first, shift @rest; } - my $size = cg_combined_size(name => $s, args => \@first); + my $size = cg_combined_size(name => $s, + first => $num_references{$s} == 0, + args => \@first); $offsets{$s} = $offset unless defined $offsets{$s} and $offsets{$s} < $offset; $offset += $size - 1; my $label = micro_label($s); - $num_references{$label} = 0; push @new_subs, [$opcase,$label,$s,$size-1,@first]; $opcase = ''; } @@ -1181,9 +1201,8 @@ sub combine_instruction_group { my($opcase,$label,$s,$size,@args) = @{$subs[$i]}; my $next = ''; (undef,$next) = @{$subs[$i+1]} if $i < $#subs; - $num_references{$next}++ if $next; my $instr_info = "$opcase:$label:$next:$s:$size:@args"; - push @all_instrs, [$label,$offsets{$s},$instr_info]; + push @all_instrs, [$label,$s,$offsets{$s},$instr_info]; } } @@ -1191,8 +1210,8 @@ sub combine_instruction_group { my %label_to_offset; my %order_to_offset; foreach my $instr (@all_instrs) { - my($label,$offset,$instr_info) = @$instr; - my $sort_key = sprintf("%02d.%02d", $offset, $num_references{$label}); + my($label,$s,$offset,$instr_info) = @$instr; + my $sort_key = sprintf("%02d.%02d", $offset, $num_references{$s}); push @{$order_to_instrs{$sort_key}}, $instr_info; $label_to_offset{$label} = $offset; $order_to_offset{$sort_key} = $offset; @@ -1231,7 +1250,7 @@ sub combine_instruction_group { $gcode .= "OpCase($opcase):\n"; push @opcase_labels, $opcase; } - if ($num_references{$label}) { + if ($num_references{$s}) { $gcode .= "$label:\n"; } @@ -1249,6 +1268,7 @@ sub combine_instruction_group { my($gen_code,$down,$up) = cg_combined_code(name => $s, + first => $num_references{$s} == 0, extra_comments => $flags, offset => $offset, comp_size => $group_size-$offset, @@ -1314,6 +1334,8 @@ sub cg_basic { sub cg_combined_size { my %params = (@_, pack_options => \@basic_pack_options); + $params{pack_options} = \@extended_pack_options + if $params{first}; my($size) = code_gen(%params); $size; } @@ -1324,7 +1346,8 @@ sub cg_combined_size { sub cg_combined_code { my %params = (@_, pack_options => \@basic_pack_options); - + $params{pack_options} = \@extended_pack_options + if $params{first}; my($size,$code,$pack_spec) = code_gen(%params); if ($pack_spec eq '') { ($code,'',''); |