aboutsummaryrefslogtreecommitdiffstats
path: root/erts/emulator/utils/beam_makeops
AgeCommit message (Collapse)Author
2016-04-18Merge branch 'bjorn/erts/beam_load'Björn Gustavsson
* bjorn/erts/beam_load: Optimize get_tuple_element instructions that target Y registers Mend beam_SUITE:packed_registers/1 Correct unpacking of 3 operands on 32-bit archictectures Eliminate misleading #ifdef ARCH_64 in beam_opcodes.h beam_debug: Correct masking when unpacking packed operands
2016-04-14Correct unpacking of 3 operands on 32-bit archictecturesBjörn Gustavsson
0a4750f91c83 optimized unpacking by removing a mask operation when unpacking three packed operands. Unfortunately, that optimization is only safe on 64-bit architectures. Here is what happens on 32-bit architectures. The operands to be packed are 10-bit register numbers that have been turned into byte offsets: aaaaaaaaaa00 bbbbbbbbbb00 cccccccccc00 They can be packed into a single word like this: 30 20 10 0 | | | | aa aaaaaaaabb bbbbbbbbcc cccccccc00 If we call the packed word P, the original operands can be extracted like this: C = P band 2#111111111100 B = (P bsr 10) band 2#111111111100 A = (P bsr 20) band 2#111111111100 The bug was that A was extracted without the masking: A = P bsr 20 That would give A the value: aaaaaaaaaaaabb That would only be safe if the two most significant bits in B were zeroes.
2016-04-14Eliminate misleading #ifdef ARCH_64 in beam_opcodes.hBjörn Gustavsson
There is a '#ifdef ARCH_64' beam_opcodes.h, which might make you think that files generated by beam_makeops will work for both 32-bit and 64-bit architectures. They will not. beam_makeops will generate different code depending on its -wordsize option.
2016-04-13Merge branch 'henrik/update-copyrightyear'Henrik Nord
* henrik/update-copyrightyear: update copyright-year
2016-04-07Remove unused variables after code generationBjörn Gustavsson
The removal of instructions on the left side of a transformation is done while generating the code for the left side. Postpone removal of unused variables to a later, separate passes to allow more variables to be eliminated after the optimizations passes introduced in the previous commits.
2016-04-07Avoid rebuilding unchanged instructionsBjörn Gustavsson
In transformations such as: move S X0=x==0 | line Loc | call_ext Ar Func => \ line Loc | move S X0 | call_ext Ar Func we can avoid rebuilding the last instruction in the sequence by introducing a 'keep' instruction. Currently, there are only 13 transformations that are hit by this optimization, but most of them are frequently used.
2016-04-07Introduce a 'rename' instructionBjörn Gustavsson
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.
2016-04-07Simplify window management for the transformation engineBjörn Gustavsson
Generic instructions have a min_window field. Its purpose is to avoid calling transform_engine() when there are too few instructions in the current "transformation window" for a transformation to succeed. Currently it does not do much good since the window size will be decremented by one before being used. The reason for the subtraction is probably that in some circumstances in the past, the loader could read past the end of the BEAM module while attempting to fetch instructions to increase the window size. Therefore, it would not be safe to just remove the subtraction by one. The simplest and safest solution seems to always ensure that there are always at least TWO instructions when calling transform_engine(). That will be safe, as long as a BEAM module is always finished with an int_code_end/0 that is not involved in any transformation.
2016-04-07Eliminate allocation of variables in transform_engine()Björn Gustavsson
When an instruction with a variable number operands (such as select_val) is seen of the left side of a transformation, the 'next_arg' instruction will allocate a buffer to fit all variables and all operands will be copied into the buffer. Very often, the 'commit' instruction will never be reached because of a test or predicate failing or because of a short window; in that case, the variable buffer will be deallocated. Note that originally there were only few instructions with a variable number of operands, but now common operations such as tuple building also have a variable number of operands. To avoid those frequent allocations and deallocations, modify the 'next_arg' instruction to only save a pointer to the first of the "rest" arguments. Also move the deallocation of the instructions on the left side from the 'commit' instruction to the 'end' instruction to ensure that 'store_rest_args' will still work.
2016-03-15update copyright-yearHenrik Nord
2015-07-06Improve unpacking performance on x86_64Björn Gustavsson
When unpacking operands on 64-bit CPUs, use a smarter mask to help the compiler optimize the code. It turns out that on x86_64, if we use the mask 0xFFFFUL (selecting the 16 least significant bits), the compiler can combine a move and a mask operation into the single insruction 'movzwl', which will eliminate one instruction.
2015-07-06Eliminate prefetch for conditional instructionsBjörn Gustavsson
Not pre-fetching in conditional instructions (instructions that use -fail_action) seems to improve performance slightly. The reason for that is that conditional instructions may jump to the failure label, wasting the pre-fetched instruction. Another reason is that that many conditional instructions do a function call, and the register pressure is therefore high. Avoiding the pre-fetch may reduce the register pressure and pontentially result in more efficient code.
2015-07-03Teach beam_makeops to pack operands for move3 and move_windowBjörn Gustavsson
It is currently only possible to pack up to 4 operands. However, the move_window4 instrucion has 5 operands and move_window5 and move3 instrucations have 6 operands. Teach beam_makeops to pack instructions with 5 or 6 operands. Also rewrite the move_window instructions in beam_emu.c to macros to allow their operands to get packed.
2015-07-03beam_makeops: Eliminate unnecessary masking when packing 3 operandsBjörn Gustavsson
When packing 3 operands into one word, there would be an unnecessary mask operation when extracting the last operand.
2015-07-03Make the 'r' operand type optionalBjörn Gustavsson
The 'r' type is now mandatory. That means in order to handle both of the following instructions: move x(0) y(7) move x(1) y(7) we would need to define two specific operations in ops.tab: move r y move x y We want to make 'r' operands optional. That is, if we have only this specific instruction: move x y it will match both of the following instructions: move x(0) y(7) move x(1) y(7) Make 'r' optional allows us to save code space when we don't want to make handling of x(0) a special case, but we can still use 'r' to optimize commonly used instructions.
2015-07-03Allow X and Y registers to be overloaded with any literalBjörn Gustavsson
Consider the try_case_end instruction: try_case_end s The 's' operand type means that the operand can either be a literal of one of the types atom, integer, or empty list, or a register. That worked well before R12. In R12 additional types of literals where introduced. Because of way the overloading was done, an 's' operand cannot handle the new types of literals. Therefore, code such as the following is necessary in ops.tab to avoid giving an 's' operand a literal: try_case_end Literal=q => move Literal x | try_case_end x While this work, it is error-prone in that it is easy to forget to add that kind of rule. It would also be complicated in case we wanted to introduce a new kind of addition operator such as: i_plus jssd Since there are two 's' operands, two scratch registers and two 'move' instructions would be needed. Therefore, we'll need to find a smarter way to find tag register operands. We will overload the pid and port tags for X and Y register, respectively. That works because pids and port are immediate values (fit in one word), and there are no literals for pids and ports.
2015-07-03Change the meaning of 'x' in a transformationBjörn Gustavsson
The purpose of this series of commits is to improve code generation for the Clang compiler. As a first step we want to change the meaning of 'x' in a transformation such as: operation Literal=q => move Literal x | operation x Currently, a plain 'x' means reg[0] or x(0), which is the first element in the X register array. That element is distinct from r(0) which is a variable in process_main(). Therefore, since r(0) and x(0) are currently distinct it is fine to use x(0) as a scratch register. However, in the next commit we will eliminate the separate variable for storing the contents of X register zero (thus, x(0) and r(0) will point to the same location in the X register array). Therefore, we must use another scratch register in transformation. Redefine a plain 'x' in a transformation to mean x(1023). Also define SCRATCH_X_REG so that we can refer to the register by name from C code.
2015-07-03beam_makeops: Eliminate crash because of unsafe packingBjörn Gustavsson
Consider an hypothetical instruction: do_something x x c The loader would crash if we tried to load an instance of the instruction with the last operand referencing a literal: {do_something,{x,0},{x,1},{literal,{a,b,c}}} Teach beam_makeops to turn off packing for such unsafe instructions.
2015-06-24erts: Remove HALFWORD_HEAP definitionBjörn-Egil Dahlberg
2015-06-18Change license text to APLv2Bruce Yinhe
2014-01-28BEAM loader: Support preservation of extra operand in transformsBjörn Gustavsson
It was not possible to preserve extra arguments in transformations. The following (hypothetical) example will now work: some_op Lit=c SizeArg Rest=* => move Lit x | some_op x SizeArg Rest
2012-10-22beam_makeops: Turn on warnings and eliminate existing warningsBjörn Gustavsson
2012-10-15beam_makeops: Eliminate a deprecation warningBjörn Gustavsson
Perl 5.16.1 (and perhaps other versions) issues the following warning: defined(@array) is deprecated at utils/beam_makeops line 1714. (Maybe you should just omit the defined()?) for the following line: $prev_last = pop(@{$gen_transform{$key}}) if defined @{$gen_transform{$key}}; # LINE 1714 The documentation for "defined" says that its use on hashes and arrays is deprecated and that it may stop working in a future release. Simply removing "defined" (as suggested by the warning message) will not work, as there will be an error when trying to use an undefined value as an array reference: Can't use an undefined value as an ARRAY reference at utils/beam_makeops line 1714. What we must do is to check whether $gen_transform{$key} is defined before trying to use it as an array reference. Noticed-by: Tuncer Ayaz
2012-03-30Update copyright yearsBjörn-Egil Dahlberg
2012-03-22beam_makeops: Add a simple preprocessorBjörn Gustavsson
2011-10-11Print transformtions sorted on the name of the first instructionBjörn Gustavsson
2011-10-11Share code for call of predicate and transformation functionsBjörn Gustavsson
2011-10-11Introduce 'try_me_else_fail'Björn Gustavsson
2011-10-11Combine 'store_var' with 'next_arg'Björn Gustavsson
'store_var' is always followed by 'next_arg'.
2011-10-11Merge 'next_instr' and 'is_op' into 'next_instr'Björn Gustavsson
'next_instr' is always followed by 'is_op'.
2011-10-11Merge 'new_instr' and 'store_op' into 'new_instr'Björn Gustavsson
Since the 'new_instr' instruction always occurs before the 'store_op' instruction, we can merge the instructions into one. Also, there is no need to include the arity of the BEAM instruction as an operand, since the arity can be looked up based on the opcode.
2011-10-11Combine a 'call' instruction with the following 'end' instructionBjörn Gustavsson
A 'call' instruction in the loader transformation language is always followed by an 'end' instruction, so we can replace the 'call' instruction with a 'call_end' instruction.
2011-10-11Get rid of redundant 'try_me_else' and 'fail' instructionsBjörn Gustavsson
If the left part of a transformation will always match, omit the the 'try_me_else' and 'fail' instructions. As part of this optimization, make it an error to have a transformation that can never be reached because of a previous transformation that will always match. (Remove one transformation from ops.tab that was found to be unreachable.)
2011-10-11Add some more information in instruction commentsBjörn Gustavsson
2011-10-11In transformations, don't store variables that are never usedBjörn Gustavsson
This optimization will save some space (in the loader tables) and some loading time.
2011-10-11Remove redundant 'next_arg' before 'next_instr'Björn Gustavsson
Fix the incorrect code that attempted to remove a single 'next_arg' instructions before 'next_instr'.
2011-10-11Generalize and rename is_set_var_instr() to is_instr()Björn Gustavsson
It is more useful to have a helper function that can test for any instruction.
2011-09-29Update copyright yearsBjörn-Egil Dahlberg
2011-08-03beam_load.c: Add overflow check of tag valuesBjörn Gustavsson
The handling of large values for other tags than TAG_i (integer) is buggy. Any tag value equal to or greater than 2^40 (5 bytes) will abort loading. Tag values fitting in 5 bytes will be truncated to 4 bytes values. Those bugs cause real problems because the bs_init2/6 and bs_init_bits/6 instructions unfortunately use TAG_u to encode literal sizes (using TAG_i would have been a better choice, but it is too late to change that now). Any binary size that cannot fit in an Uint should cause a system_limit exception at run-time, but instead the buggy handling will either cause an emulator crash (for values in the range 2^32 to 2^40-1) or abort loading. In this commit, implement overflow checking of tag values as a preparation for fixing the binary construction instructions. If any tag value cannot fit in an Uint (except for TAG_i), change the tag to the special TAG_o overflow tag.
2011-08-03beam_makeops: Add some sanity checksBjörn Gustavsson
We want to make sure that a tag/type name is not defined more than once and that we don't define too many primitive tags. Primitive tags must be named with lowercase letters (or they will be confused with variable names in transformations in the ops.tab file).
2011-01-17beam_makeops: Support jumping to common code from an instruction macroBjörn Gustavsson
2011-01-17Support packing of the 'I' type in a 64-bit emulatorBjörn Gustavsson
In many (not all) cases, the value for the 'I' type will fit into 32 bits.
2011-01-17beam_makeops: Refactor packing code to facilitate extensionsBjörn Gustavsson
We don't want the packable types listed in two places.
2011-01-17BEAM loader: Pack more instructions using a new 'Q' typeBjörn Gustavsson
Introduce a new 'Q' type, similar to 'P' except that it can be packed.
2011-01-17If the wordsize is 64 bits, pack up to 4 operands into a wordBjörn Gustavsson
In the 32-bit BEAM emulator, it is only possible to pack 3 register operands into one word. Therefore, the move2 instruction (that has 4 operands) needs two words for its operands. Take advantage of the larger wordsize in the 64-bit emulator and pack up to 4 operands into a single word.
2011-01-17Pass the external word size to the beam_makeops scriptBjörn Gustavsson
Giving the beam_makeops script access to the external word size (=the size of instruction words) will allow it to pack more operands into a word for the 64 bits emulator.
2011-01-17BEAM loader: Combine is_type/1 and is_eq/1 instructionsBjörn Gustavsson
In the transformation engine in the loader, an is_eq/1 instruction is currently always preceded by an is_type/1 instruction. Therefore, save a word and slight amount of time by combining those instructions into an is_type_eq/2 instruction.
2011-01-17BEAM loader: Omit type tests for instructions that don't need themBjörn Gustavsson
2011-01-17beam_makeops: Allow -pack and -nonext to be combinedBjörn Gustavsson
2011-01-17beam_makeops: Relax requirements for having specific instructionsBjörn Gustavsson