aboutsummaryrefslogtreecommitdiffstats
path: root/lib/compiler/src/v3_kernel.erl
AgeCommit message (Collapse)Author
2016-12-02Merge branch 'egil/compiler/opt-maps-pattern-matching/OTP-14072'Björn-Egil Dahlberg
* egil/compiler/opt-maps-pattern-matching/OTP-14072: compiler: Add regression tests compiler: Optimize maps pattern matching compiler: Allow for unaligned match argument in value groups
2016-12-01compiler: Optimize maps pattern matchingBjörn-Egil Dahlberg
2016-11-18v3_kernel: Generate optimized code for guardsBjörn Gustavsson
The compiler produces poor code for complex guard expressions with andalso/orelse. Here is an example from the filename module: -define(IS_DRIVELETTER(Letter),(((Letter >= $A) andalso (Letter =< $Z)) orelse ((Letter >= $a) andalso (Letter =< $z)))). skip_prefix(Name, false) -> Name; skip_prefix([L, DrvSep|Name], DrvSep) when ?IS_DRIVELETTER(L) -> Name; skip_prefix(Name, _) -> Name. beam_bool fails to simplify the code for the guard, leaving several 'bif' instructions: {function, skip_prefix, 2, 49}. {label,48}. {line,[{location,"filename.erl",187}]}. {func_info,{atom,filename},{atom,skip_prefix},2}. {label,49}. {test,is_ne_exact,{f,52},[{x,1},{atom,false}]}. {test,is_nonempty_list,{f,52},[{x,0}]}. {get_list,{x,0},{x,2},{x,3}}. {test,is_nonempty_list,{f,52},[{x,3}]}. {get_list,{x,3},{x,4},{x,5}}. {bif,'=:=',{f,52},[{x,1},{x,4}],{x,6}}. {test,is_ge,{f,50},[{x,2},{integer,65}]}. {bif,'=<',{f,52},[{x,2},{integer,90}],{x,7}}. {test,is_eq_exact,{f,51},[{x,7},{atom,false}]}. {test,is_ge,{f,50},[{x,2},{integer,97}]}. {bif,'=<',{f,52},[{x,2},{integer,122}],{x,7}}. {jump,{f,51}}. {label,50}. {move,{atom,false},{x,7}}. {label,51}. {bif,'=:=',{f,52},[{x,7},{atom,true}],{x,7}}. {test,is_eq_exact,{f,52},[{x,6},{atom,true}]}. {test,is_eq_exact,{f,52},[{x,7},{atom,true}]}. {move,{x,5},{x,0}}. return. {label,52}. return. We can add optimizations of guard tests to v3_kernel to achive a better result: {function, skip_prefix, 2, 49}. {label,48}. {line,[{location,"filename.erl",187}]}. {func_info,{atom,filename},{atom,skip_prefix},2}. {label,49}. {test,is_ne_exact,{f,51},[{x,1},{atom,false}]}. {test,is_nonempty_list,{f,51},[{x,0}]}. {get_list,{x,0},{x,2},{x,3}}. {test,is_nonempty_list,{f,51},[{x,3}]}. {get_list,{x,3},{x,4},{x,5}}. {test,is_eq_exact,{f,51},[{x,1},{x,4}]}. {test,is_ge,{f,51},[{x,2},{integer,65}]}. {test,is_lt,{f,50},[{integer,90},{x,2}]}. {test,is_ge,{f,51},[{x,2},{integer,97}]}. {test,is_ge,{f,51},[{integer,122},{x,2}]}. {label,50}. {move,{x,5},{x,0}}. return. {label,51}. return. Looking at the STDLIB application, there were 112 lines of BIF calls in guards that beam_bool failed to convert to test instructions. This commit eliminates all those BIF calls. Here is how I counted the instructions: $ PATH=$ERL_TOP/bin:$PATH erlc -I ../include -I ../../kernel/include -S *.erl $ grep "bif,'[=<>]" *.S | grep -v f,0 dets.S: {bif,'=:=',{f,547},[{x,4},{atom,read_write}],{x,4}}. dets.S: {bif,'=:=',{f,547},[{x,5},{atom,saved}],{x,5}}. dets.S: {bif,'=:=',{f,589},[{x,5},{atom,read}],{x,5}}. . . . $ grep "bif,'[=<>]" *.S | grep -v f,0 | wc 112 224 6765 $
2016-09-29compiler: Allow for unaligned match argument in value groupsBjörn-Egil Dahlberg
At this stage in match compilation we are allowed to change the alignment of arguments and constructors as long as they are the same aligned in the same group.
2016-09-29Merge branch 'josevalim/compiler/at-var/PR-1081/OTP-13924'Björn Gustavsson
* josevalim/compiler/at-var/PR-1081/OTP-13924: Use @ in variable names generated by core and kernel
2016-09-26Use @ in variable names generated by core and kernelJosé Valim
The previous variable names can be generated by projects like LFE and Elixir, leading to possible conflicts. Our first to choice to solve such conflicts was to use $ but that's not a valid variable name in core. Therefore we picked @ which is currently supported and still reduces the chance of conflicts.
2016-09-21Simplify handling of internal BIFsBjörn Gustavsson
Do a simpler translation of internal BIFs. While we are it, also remove the dummy values of Index and Uniq from the make_fun internal operation.
2016-09-21v3_life: Eliminate special handling of guardsBjörn Gustavsson
Remove the special handling #k_try{} in guards in v3_life. If we introduce a new #k_protected{} record in v3_kernel, v3_life no longer needs to know whether it is processing guards or bodies.
2016-05-25Merge branch 'kostis/compiler/v3_kernel/eta-conversion'Björn Gustavsson
* kostis/compiler/v3_kernel/eta-conversion: v3_kernel: Fix typo in comment
2016-05-23v3_kernel: Fix typo in commentKostis Sagonas
2016-05-09compiler: Let module_info(attributes) skip more attributesHans Bolinder
'callback' and 'optional_callbacks' are no longer wild attributes.
2016-04-14v3_kernel: Construct literal lists properlyBjörn Gustavsson
Use cerl:make_list/1 instead of a home-made make_list/1 to ensure that literal lists are constructed as literals. In a future release, we would like to forbid in the loader construction of literal lists using instructions like: put_list {atom,a} [] Dst The proper way is: move {literal,[a]} {x,0} Also update the comment about "put_list Const [] Dst" in ops.tab.
2016-02-17compiler: Update the compiler to handle typed record fieldsBjörn Gustavsson
2015-11-11v3_kernel: Speed up compilation of modules with many funsBjörn Gustavsson
Using a map to store the number of free variables for funs instead of an orddict will speed up the v3_kernel pass for modules with a huge number of funs (such as NBAP-PDU-Contents in the asn1 test suite).
2015-06-18Change license text to APLv2Bruce Yinhe
2015-05-21compiler: Use cerl_sets instead of sets in v3_kernelBjörn-Egil Dahlberg
2015-04-22v3_kernel: Optimize subst_vsub/3Björn Gustavsson
Profiling shows that subst_vsub/3 dominates the running time. It is therefore worthwhile optimizing it.
2015-03-09v3_core: Add is_map tests before map instructionsBjörn Gustavsson
If we have a sequence of put_map_* instructions operating on the same map, it will be more efficient if we can have one is_map/2 instruction before put_map_* instructions, so that each put_map_* does not need to test whether the argument is a map.
2015-02-12Eliminate use of core_lib:literal_value/1Björn Gustavsson
Essentially, core_lib:literal_value/1 became useless when literals were introduced in R12. Since we always create #c_literal{} records whenever possible, literal_value/1 would *only* succeed when it was passed a #c_literal{} argument.
2015-01-29Move grouping of map constructions from v3_core to v3_kernelBjörn Gustavsson
When translating a function with map construction: f(A) -> B = b, C = c, #{A=>1,B=>2,C=>3}. v3_core would break apart the map construction into three parts because of the way the map instructions in BEAM work -- variable keys need to be in their own instruction. In the example, constant propagation will turn two of the keys to literal keys. But the initial breaking apart will not be undone, so there will still be three map constructions: 'f'/1 = fun (_cor0) -> let <_cor3> = ~{::<_cor0,1>}~ in let <_cor4> = ~{::<'b',2>|_cor3}~ in ~{::<'c',3>|_cor4}~ It would be possible to complicate the sys_core_fold pass to regroup map operations so that we would get: 'f'/1 = fun (_cor0) -> let <_cor3> = ~{::<_cor0,1>}~ in ~{::<'b',2>,::<'c',3>|_cor3}~ A simpler way that allows to simplify the translation is to skip the grouping in v3_core and translate the function to: 'f'/1 = fun (_cor0) -> ~{::<_cor0,1>,::<'b',2>,::<'c',3>}~ We will then let v3_kernel do the grouping while translating from Core Erlang to Kernel Erlang.
2014-08-22compiler: Use variables in Map kernel passBjörn-Egil Dahlberg
2014-03-25compiler: Variable keys are not allowed in MapsBjörn-Egil Dahlberg
No need to check for variables in Map keys.
2014-03-17compiler: Change #c_map{var} to #c_map{arg}Björn-Egil Dahlberg
Not only variables are allowed as arguments, the name should reflect that. Change cerl Map argument interface * cerl:map_arg/1 is more suitable then cerl:map_val/1 in this case.
2014-03-17compiler: Validate Map srcBjörn-Egil Dahlberg
Reject all expressions that are known to fail. Emit 'badarg' for those expressions. Ex. []#{ a => 1} Is not a valid map update expression.
2014-03-04Properly order Kernel code for maps with mixed pairsAnthony Ramine
The Kernel instructions were not properly ordered when compiling maps with complex values mixed in assoc and exact pairs. Reported-by: Ulf Norell
2014-02-13compiler: Change map instructions for fetching valuesBjörn-Egil Dahlberg
* Combine multiple get values with one instruction * Combine multiple check keys with one instruction
2014-02-10Merge branch 'egil/compiler/maps-fix-codegen'Björn-Egil Dahlberg
* egil/compiler/maps-fix-codegen: compiler: Fix codegen multiple updates for Maps erts,compiler: Correct and amend tests for Maps
2014-02-07compiler: Fix codegen multiple updates for MapsBjörn-Egil Dahlberg
This fixes an error on multiple updates optimization for map pairs. The error was introduced with moving to term order in Maps. This also fixes an error where register life time was lost for values and could result in erroneuos values being emitted in for map pairs. Simplified v3_codegen by moving multiple update optimizations to v3_kernel.
2014-02-07Merge branch 'hsv/using_lists_droplast'Henrik Nord
* hsv/using_lists_droplast: lib/mnesia/test/ - Replace reverse(tl(reverse(L))) with lists:droplast/1 lib/ssh - Replace reverse(tl(reverse(L))) with lists:droplast/1 lib/wx - Replace reverse(tl(reverse(L))) with lists:droplast/1 Use lists:droplast/1 in orber/orber_interceptors.erl Import and use lists:droplast/1 in v3_core/v3_kernel OTP-11678 OTP-11677
2014-01-29compiler: Squash #c_map_pair_*{} to #c_map_pair{}Björn-Egil Dahlberg
Simplify compiler internals and parsing of core format.
2014-01-29compiler: Squash #k_map_pair_*{} to #k_map_pair{}Björn-Egil Dahlberg
Simplify compiler internals for kernel passes.
2014-01-28compiler: Rename map pattern to proper nameBjörn-Egil Dahlberg
2014-01-28Pass the map pair operators through to the v3_codegen passBjörn Gustavsson
2014-01-28compiler: Implement support for exact Op in MapsBjörn-Egil Dahlberg
The syntax is handled upto v3_kernel where it is reduced to previous behaviour for construction and updates. Meaning, the ':=' operator is handled exactly as '=>' operator.
2014-01-28compiler: Fix multiple same keysBjörn-Egil Dahlberg
2014-01-28compiler: Handle literals, not just atoms, as keys in mapsBjörn-Egil Dahlberg
2014-01-28Implement support for maps in the compilerBjörn Gustavsson
To make it possible to build the entire OTP system, also define dummys for the instructions in ops.tab.
2014-01-24Import and use lists:droplast/1 in v3_core/v3_kernelHans Svensson
Also imported lists:last/1, and removed the local definition.
2013-09-12Remove ^L characters hidden randomly in the code. Not those used in text ↵Pierre Fenoll
files as delimiters. While working on a tool that processes Erlang code and testing it against this repo, I found out about those little sneaky 0xff. I thought it may be of help to other people build such tools to remove non-conforming-to-standard characters.
2013-09-05compiler: Conform returned errors to the documented formatBjörn Gustavsson
ErrorInfo is documented to be: {ErrorLine,Module,ErrorDescriptor} but for some errors with line numbers it would look like: {Module,ErrorDescriptor} Ensure that all ErrorInfo tuples have three elements. Use 'none' instead of a line number: {none,Module,ErrorDescriptor} There already are errors that return 'none' when no line number is available, but that convention was not documented. Mention it in the documentation. Also make sure that the compiler will not print 'none' as a line number in error messages (if the 'report_errors' option is given) as that looks stupid. That is, when attempting to compile a non-existing module, the error message should be: non-existing.erl: no such file or directory and not: non-existing.erl:none: no such file or directory
2013-01-25Update copyright yearsBjörn-Egil Dahlberg
2013-01-23Revert "Merge branch 'nox/rm-reverse-eta-conversion/OTP-10682'"Fredrik Gustafsson
This reverts commit 750ecdea08fa5fa7e32b7f3019eed96c1699427e, reversing changes made to 2cfa0466c3b3c7bd5e3621aff0f3e2ca30addb68.
2012-12-03Remove the reverse eta-conversion from v3_kernelAnthony Ramine
Local function references should be handled directly as a make_fun internal BIF call instead of creating an extra lambda function every time they are used.
2012-10-09v3_kernel: Fix match code for matched out segment size in multiple clausesBjörn Gustavsson
When matched variable is used as a size field in multiple clauses, as in: foo(<<L:8,A:L>>) -> A; foo(<<L:8,A:L,B:8>>) -> {A,B}. the match tree would branch out before the segment that used the matched-out variable (in this example, the tree would branch out before the matching of A:L). That happens because the pattern matching compilator did not take variable substitutions into account when grouping clauses that match the same value. That is, the generated code would work similarly to this code: foo(<<L:8,T/binary>>) -> case T of <<A:L>> -> A; _ -> case T of <<A:L,B:8>> -> %% A matched out again! {A,B} end end. We would like the matching to work more like: foo(<<L,A:L,T/binary>>) -> case T of <<>> -> A; <<B:8>> -> {A,B} end. Fix the problem by taking the substitutions into account when grouping clauses that match out the same value.
2012-10-09Improve binary matching of literalsBjörn Gustavsson
The bs_match_string instruction is used to speed up matching of binary literals. For example, given this source code: foo1(<<1,2,3>>) -> ok. The matching part of the code will look like: {test,bs_start_match2,{f,1},1,[{x,0},0],{x,0}}. {test,bs_match_string,{f,3},[{x,0},24,{string,[1,2,3]}]}. {test,bs_test_tail2,{f,3},[{x,0},0]}. Nice. However, if we do a simple change to the source code: foo2(<<1,2,3>>) -> ok; foo2(<<>>) -> error. the resulting matching code will look like (sligthly simplified): {test,bs_start_match2,{f,4},1,[{x,0},0],{x,0}}. {test,bs_get_integer2,{f,7},1,[{x,0},{integer,8},1,Flags],{x,1}}. {test,is_eq_exact,{f,8},[{x,1},{integer,1}]}. {test,bs_match_string,{f,6},[{x,0},16,{string,[2,3]}]}. {test,bs_test_tail2,{f,6},[{x,0},0]}. {move,{atom,ok},{x,0}}. return. {label,6}. {bs_restore2,{x,0},{atom,start}}. {label,7}. {test,bs_test_tail2,{f,8},[{x,0},0]}. That is, matching of the first byte is not combined into the bs_match_string instruction that follows. Fix this problem by allowing a bs_match_string instruction to be used if all clauses will match either the same integer literal or the empty binary.
2012-08-22compiler: Warn if the size of a binary segment is invalidBjörn Gustavsson
The compiler would silently accept and Dialyzer would crash on code like: <<X:(2.5)>> It is never acceptable for Dialyzer to crash. The compiler should at least generate a warning for such code. It is tempting to let the compiler generate an error, but that would mean that code like: Sz = 42.0, <<X:Sz>>. would be possible to compile with optimizations disabled, but not with optimizations enabled. Dialyzer crashes because it calls cerl:bitstr_bitsize/1, which crashes if the type of size for the segment is invalid. The easiest way to avoid that crash is to extend the sanity checks in v3_core to also include the size field of binary segments. That will cause the compiler to issue a warning and to replace the bad binary construction with a call to erlang:error/1. (It also means that Dialyzer will not issue a warning for bad size fields.)
2012-03-30Update copyright yearsBjörn-Egil Dahlberg
2012-03-14v3_core: Don't put negative line numbers in annotationsBjörn Gustavsson
In Core Erlang and later passes, compiler-generated code can be indicated in two different ways: by negative line numbers and by a 'compiler_generated' annotation. Simplify the code and improve coverage by turning negative line numbers positive and adding a 'compiler_generated' annotation in the v3_core pass. That means that Core Erlang and latter passes do not have deal with negative line numbers.
2012-03-14v3_kernel: Dig out the line number only when generating a warningBjörn Gustavsson
2012-03-14v3_kernel: Clean up handling of guardsBjörn Gustavsson
Handling of guards become a mess when andalso/orelse in guards were introduced. Clean it up by using common code for most constructs, regardless of where they occur, and when needed use is_in_guard/1 to handle guard constructs differently.