aboutsummaryrefslogtreecommitdiffstats
path: root/lib/compiler
AgeCommit message (Collapse)Author
2019-05-27Merge pull request #2248 from bjorng/bjorn/compiler/move-core-opts-to-ssaBjörn Gustavsson
Move type-based optimizations from Core Erlang passes to SSA passes
2019-05-27Merge branch 'maint'Björn Gustavsson
* maint: Fix unsafe negative type inference
2019-05-27Merge branch 'bjorn/compiler/fix-unsafe-type-inference/OTP-15838' into maintBjörn Gustavsson
* bjorn/compiler/fix-unsafe-type-inference/OTP-15838: Fix unsafe negative type inference
2019-05-24Fix unsafe negative type inferenceBjörn Gustavsson
The type optimizer pass (`beam_ssa_type`) could make unsafe negative inferences. That is, incorrectly infer that a variable could *not* have a particular type. This bug was found when adding another optimization. It is not clear how write a failing test case without that added optimization.
2019-05-23Simplify sys_core_fold by removing obsoleted optimizationsBjörn Gustavsson
Simplify sys_core_fold by removing optimizations by removing the optimizations that have been obsoleted by the preceding commits.
2019-05-23Optimize is_function/{1,2} callsBjörn Gustavsson
Remove is_function/1,2 tests if that are known to never fail.
2019-05-23Optimize expression comparing a boolean to 'false'Björn Gustavsson
2019-05-23Implement '==' optimization in beam_ssa_typeBjörn Gustavsson
`=:=` is faster than `==`, so when they would return the same result, we want to replace `==` with `=:=`. There is currently such an optimization in sys_core_fold, but the optimimization will be more effective if done in beam_ssa_type because beam_ssa_type has better type information.
2019-05-23Merge branch 'maint'Björn Gustavsson
* maint: Eliminate compiler crash when compiling complex receive statements
2019-05-23Merge branch 'bjorn/compiler/fix-receive-patch/ERL-950/OTP-15832' into maintBjörn Gustavsson
* bjorn/compiler/fix-receive-patch/ERL-950/OTP-15832: Eliminate compiler crash when compiling complex receive statements
2019-05-22Merge branch 'maint'Björn Gustavsson
* maint: Fix non-terminating compilation Fix compiler crash when funs were matched
2019-05-22Merge branch 'bjorn/compiler/fix-freeze/ERL-948/OTP-15828' into maintBjörn Gustavsson
* bjorn/compiler/fix-freeze/ERL-948/OTP-15828: Fix non-terminating compilation
2019-05-22Merge pull request #2243 from bjorng/bjorn/compiler/fix-redundant-testsBjörn Gustavsson
Improve optimization of redundant tests
2019-05-22Merge pull request #2242 from bjorng/bjorn/add-swap-instructionBjörn Gustavsson
Make the swap instruction known to the compiler
2019-05-22Make the swap instruction known to the compilerBjörn Gustavsson
BEAM has had a `swap` instruction for several releases, but it was not known to the compiler. The loader would translate a sequence of three `move` instructions to the `swap` instructions, but only when it was possible to determine that it would be safe. By making `swap` known to the compiler, it can be applied in more situations since it is easier for the compiler than for the loader to ensure that the usage is safe, and the loader shenanigans can be eliminated.
2019-05-21Eliminate compiler crash when compiling complex receive statementsBjörn Gustavsson
Certain complex receive statements would result in an internal compiler failure. That would happen when the compiler would fail to find the common exit block following a receive. See the added test case for an example. https://bugs.erlang.org/browse/ERL-950
2019-05-20Improve optimization of redundant testsBjörn Gustavsson
The `beam_ssa_dead` pass is supposed to eliminate tests that are determined to be redundant based on the outcome of a previous test. For example, in the following example that repeats a guard test, the second clause can never be executed: foo(A) when A >= 42 -> one; foo(A) when A >= 42 -> two; foo(_) -> three. `beam_ssa_dead` should have eliminated the second clause, but didn't: {test,is_ge,{f,5},[{x,0},{integer,42}]}. {move,{atom,one},{x,0}}. return. {label,5}. {test,is_ge,{f,6},[{x,0},{integer,42}]}. {move,{atom,two},{x,0}}. return. {label,6}. {move,{atom,three},{x,0}}. return. Correct the optimization of four different combinations of relational operations that were too conservate. To ensure the correctness of the optimization, also add an exahaustive test of all combinations of relational operations with one variable and one literal. (Also remove the weak and now redundant coverage tests in `beam_ssa_SUITE`.) With this correction, the following code will be generated for the example: {test,is_ge,{f,5},[{x,0},{integer,42}]}. {move,{atom,one},{x,0}}. return. {label,5}. {move,{atom,three},{x,0}}. return. Thanks to Dániel Szoboszlay (@dszoboszlay), whose talk at Code BEAM STO 2019 made me aware of this missed opportunity for optimization.
2019-05-20Fix non-terminating compilationBjörn Gustavsson
The compiler would not terminate while compiling the following code: foo(<<N:32>>, Tuple, NewValue) -> _ = element(N, Tuple), setelement(N, Tuple, NewValue). The type analysis pass would attempt to construct a huge list when attempting analyse the type of `Tuple` after the call to `setelement/3`. https://bugs.erlang.org/browse/ERL-948
2019-05-14Eliminate the beam_except passBjörn Gustavsson
The beam_except pass rewrites certain calls `erlang:error/{1,2}` to use specialized instructions for common exceptions such as `{badmatch,Term}`. Move this optimization to `beam_ssa_pre_codegen` and `beam_ssa_codegen`. The main reason for this change is that optimization passes operating on SSA code are easier to maintain than optimization passes working on BEAM code.
2019-05-14Fix compiler crash when funs were matchedBjörn Gustavsson
Code such as the following would crash the compiler in OTP 22: [some_atom = fun some_function/1] The reason is that the fun would be copied (used both in the match operation and as a value in the list), and the copy of the fun would create two wrapper functions with the same name for calling some_function/1. In OTP 21, the duplicate functions happened not to cause any harm (one of the wrappers functions would be unused and ultimately be removed by beam_clean). In OTP 22, the new beam_ssa_type pass would be confused by the multiple definitions of the wrapper function.
2019-05-10Prepare releaseErlang/OTP
2019-04-30Merge branch 'john/compiler/fix-missing-match-reposition/ERL-923'John Högberg
* john/compiler/fix-missing-match-reposition/ERL-923: compiler: Propagate match context position on fail path
2019-04-29compiler: Propagate match context position on fail pathJohn Högberg
2019-04-23beam_validator: Don't infer types for dead valuesJohn Högberg
2019-04-15Optimize encoding of simple literalsBjörn Gustavsson
`beam_asm` would encode `{literal,[]}`, `{literal,erlang}`, and `{literal,42}` in a less efficient way than the equivalent values `nil`, `{atom,erlang}`, and `{integer,42}`. That would increase the size of BEAM files and could increase the loaded code size. It would probably not harm performance, because `literal` was only used this way in code that generates `badmatch` and `case_clause` exceptions.
2019-04-10compiler: Add missing header dependenciesJohn Högberg
2019-04-08Merge pull request #2200 from ↵Björn Gustavsson
bjorng/bjorn/deprecation-warnings/ERL-904/OTP-15749 Add compiler option for suppressing warnings about removed functions/modules
2019-04-05Add options for suppressing warnings about removed functionsBjörn Gustavsson
An appliction outside of OTP may want to reuse then name of a module that was previously included in OTP. Therefore, there should be a way to suppress warnings for removed functions.
2019-04-04cerl_clauses: Fix broken linkBjörn Gustavsson
2019-04-04erts: Fix more internal docs xmllintLukas Larsson
2019-04-04compiler: Add internal docs sectionLukas Larsson
2019-03-28compile: Add some types to core_parse.hrlHans Bolinder
The core_parse.hrl can be used in applications with the +warn_untyped_record compiler flag.
2019-03-28compiler: Fix documentation of cerl:c_binary/1Hans Bolinder
2019-03-28Merge branch 'bjorn/compiler/cuddle-with-tests'Björn Gustavsson
* bjorn/compiler/cuddle-with-tests: Verify the highest opcode for the r21 test suites Add test_lib:highest_opcode/1 sys_core_fold: Simplify case_expand_var/2 beam_validator: Remove uncovered lines in lists_mod_return_type/3 Cover return type determination of lists functions
2019-03-26compiler: Fully disable no_return optimizations in try blocksJohn Högberg
Validation could fail when a function that never returned was used in a try block (see attached test case). It's possible to solve this without disabling the optimization as the generated code is sound, but I'm not comfortable making such a large change this close to the OTP 22 release.
2019-03-25Verify the highest opcode for the r21 test suitesBjörn Gustavsson
2019-03-25Add test_lib:highest_opcode/1Björn Gustavsson
2019-03-25sys_core_fold: Simplify case_expand_var/2Björn Gustavsson
5239eb0c62a9 stopped storing patterns that a variable has matched. The only tuples that are stored in the type database are tuples that have been previously constructed. Therefore, the code in sys_core_fold:case_expand_var/2 and friends that converts a tuple pattern to a tuple construction can be simplified to used the stored tuple directly.
2019-03-25beam_validator: Remove uncovered lines in lists_mod_return_type/3Björn Gustavsson
Don't bother infering the return types for lists function that beam_ssa_type does not handle.
2019-03-25Cover return type determination of lists functionsBjörn Gustavsson
2019-03-21Merge branch 'bjorn/hipe-compilation/OTP-15596'Björn Gustavsson
* bjorn/hipe-compilation/OTP-15596: HiPE: Don't fail the compilation for unimplemented instructions
2019-03-21lib/compiler/scripts/smoke: Compile some cloudi packagesBjörn Gustavsson
2019-03-20HiPE: Don't fail the compilation for unimplemented instructionsBjörn Gustavsson
2019-03-19Merge branch 'john/compiler/fix-eq-type-infererence-in-validator/ERL-886'John Högberg
* john/compiler/fix-eq-type-infererence-in-validator/ERL-886: beam_validator: Infer types on both sides of '=:='
2019-03-18lib/compiler/scripts/smoke: Force a local hexBjörn Gustavsson
The script would hang if no local hex had been installed previously.
2019-03-18beam_validator: Infer types on both sides of '=:='John Högberg
2019-03-13Merge pull request #2177 from bjorng/bjorn/erts/tail-recursive-bifsBjörn Gustavsson
Optimize tail-recursive calls of BIFs OTP-15674
2019-03-12Merge branch 'maint'Henrik Nord
* maint: Updated OTP version Prepare release
2019-03-11Prepare releaseErlang/OTP
2019-03-09Optimize tail-recursive calls of BIFsBjörn Gustavsson
BEAM currently does not call BIFs at the end of a function in a tail-recursive way. That is, when calling a BIF at the end of a function, the BIF is first called, and then the stack frame is deallocated, and then control is transferred to the caller. If there is no stack frame when a BIF is called in the tail position, the loader will emit a sequence of three instructions: first an instruction that allocates a stack frame and saves the continuation pointer (`allocate`), then an instruction that calls the BIF (`call_bif`), and lastly an instruction that deallocates the stack frame and returns to the caller (`deallocate_return`). The old compiler would essentially allocate a stack frame for each clause in a function, so it would not be that common that a BIF was called in the tail position when there was no stack frame, so the three-instruction sequence was deemed acceptable. The new compiler only allocates stack frames when truly needed, so the three-instruction BIF call sequence has become much more common. This commit introduces a new `call_bif_only` instruction so that only one instruction will be needed when calling a BIF in the tail position when there is no stack frame. This instruction is also used when there is a stack frame to make it possible to deallocate the stack frame **before** calling the BIF, which may make a subsequent garbage collection at the end of the BIF call cheaper (copying less garbage). The one downside of this change is that the function that called the BIF will not be included in the stack backtrace (similar to how a tail-recursive call to an Erlang function will not be included in the backtrace). That was the quick summary of the commit. Here comes a detailed look at how BIF calls are translated by the loader. The first example is a function that calls `setelement/3` in the tail position: update_no_stackframe(X) -> setelement(5, X, new_value). Here is the BEAM code: {function, update_no_stackframe, 1, 12}. {label,11}. {line,[...]}. {func_info,{atom,t},{atom,update_no_stackframe},1}. {label,12}. {move,{x,0},{x,1}}. {move,{atom,new_value},{x,2}}. {move,{integer,5},{x,0}}. {line,[...]}. {call_ext_only,3,{extfunc,erlang,setelement,3}}. Because there is no stack frame, the `call_ext_only` instruction will be used to call `setelement/3`: {call_ext_only,3,{extfunc,erlang,setelement,3}}. The loader will transform this instruction to a three-instruction sequence: 0000000020BD8130: allocate_tt 0 3 0000000020BD8138: call_bif_e erlang:setelement/3 0000000020BD8148: deallocate_return_Q 0 Using the `call_bif_only` instruction introduced in this commit, only one instruction is needed: 000000005DC377F0: call_bif_only_e erlang:setelement/3 `call_bif_only` calls the BIF and returns to the caller. Now let's look at a function that already has a stack frame when `setelement/3` is called: update_with_stackframe(X) -> foobar(X), setelement(5, X, new_value). Here is the BEAM code: {function, update_with_stackframe, 1, 14}. {label,13}. {line,[...]}. {func_info,{atom,t},{atom,update_with_stackframe},1}. {label,14}. {allocate,1,1}. {move,{x,0},{y,0}}. {line,[...]}. {call,1,{f,16}}. {move,{y,0},{x,1}}. {move,{atom,new_value},{x,2}}. {move,{integer,5},{x,0}}. {line,[...]}. {call_ext_last,3,{extfunc,erlang,setelement,3},1}. Since there is a stack frame, the `call_ext_last` instruction will be used to deallocate the stack frame and call the function: {call_ext_last,3,{extfunc,erlang,setelement,3},1}. Before this commit, the loader would translate this instruction to: 0000000020BD81B8: call_bif_e erlang:setelement/3 0000000020BD81C8: deallocate_return_Q 1 That is, the BIF is called before deallocating the stack frame and returning to the calling function. After this commit, the loader will translate the `call_ext_last` like this: 000000005DC37868: deallocate_Q 1 000000005DC37870: call_bif_only_e erlang:setelement/3 There are still two instructions, but now the stack frame will be deallocated before calling the BIF, which could make the potential garbage collection after the BIF call slightly more efficient (copying less garbage). We could have introduced a `call_bif_last` instruction, but the code for calling a BIF is relatively large and there does not seem be a practical way to share the code between `call_bif` and `call_bif_only` (since the difference is at the end, after the BIF call). Therefore, we did not want to clone the BIF calling code yet another time to make a `call_bif_last` instruction.