Age | Commit message (Collapse) | Author |
|
Introduce subtraction of types to allow some redundant tests to be
eliminated.
Consider this function:
foo(L) when is_list(L) ->
case L of
[_|_] -> non_empty;
[] -> empty
end.
After entering the body of the function, L is known to be either
a cons cell or nil (otherwise the is_list/1 guard would have failed).
If the L is not a cons cell, it must be nil. Therefore, the test
for nil in the second clause of the case can be eliminated.
Here is the SSA code with some additonal comments for the function
before the optimization:
function t:foo(_0) {
0:
@ssa_bool = bif:is_list _0
br @ssa_bool, label 4, label 3
4:
%% _0 is now a list (cons or nil).
@ssa_bool:8 = is_nonempty_list _0
br @ssa_bool:8, label 9, label 7
9:
ret literal non_empty
7:
%% _0 is not a cons (or we wouldn't be here).
%% Subtracting cons from the previously known type list
%% gives that _0 must be nil.
@ssa_bool:10 = bif:'=:=' _0, literal []
br @ssa_bool:10, label 11, label 6
11:
ret literal empty
6:
_6 = put_tuple literal case_clause, _0
%% t.erl:5
@ssa_ret:12 = call remote (literal erlang):(literal error)/1, _6
ret @ssa_ret:12
3:
_9 = put_list _0, literal []
%% t.erl:4
@ssa_ret:13 = call remote (literal erlang):(literal error)/2, literal function_clause, _9
ret @ssa_ret:13
}
Type subtraction gives us that _0 must be nil in block 7, allowing us to
remove the comparison of _0 with nil. The code for the function can be simplified
to:
function t:foo(_0) {
0:
@ssa_bool = bif:is_list _0
br @ssa_bool, label 4, label 3
4:
@ssa_bool:8 = is_nonempty_list _0
br @ssa_bool:8, label 9, label 11
9:
ret literal non_empty
11:
ret literal empty
3:
_9 = put_list _0, literal []
%% t.erl:4
@ssa_ret:13 = call remote (literal erlang):(literal error)/2, literal function_clause, _9
ret @ssa_ret:13
}
|
|
* maint:
Remove unsafe optimization for delaying creation of stackframe
Conflicts:
lib/compiler/src/v3_codegen.erl
|
|
b89044a800c4 introduced an optimization that tries to delay creation
of stack frames. It turns out that this optimization is not always
safe. (See the new test case for an example.)
Since the code generator is completely rewritten in the `master`
branch for the upcoming OTP 22 release, it does not make sense trying
to mend this optimization. It is better to remove it. Out of a sample
of about 1000 modules in OTP, about 50 of them are changed as a result
of removing this optimization.
The compiler in OTP 22 will do the same optimization in a cleaner,
safer, and more effective way.
https://bugs.erlang.org/browse/ERL-807
|
|
* bjorn/cuddle-with-tests:
Cover code in beam_ssa_opt
Cover code in beam_ssa_dead
Cover code in beam_trim
Eliminate warnings for unused variables
regressions_SUITE: Fix exports
map_SUITE: Test for mixed map creation
map_SUITE: Fix indentation
|
|
* maint:
Fix unsafe optimization of stack trace building
|
|
The `sys_core_fold` pass of the compiler would optimize
away the building of the stacktrace in code such as:
try
...
catch
C:R:Stk ->
erlang:raise(C, {R,Stk}, Stk)
end
That optimization is unsafe and would cause a crash in a later compiler
pass.
|
|
The following function:
is_two_tuple(Arg) ->
case is_tuple(Arg) of
false -> false;
true -> tuple_size(Arg) == 2
end.
would cause an internal consistency failure:
Internal consistency check failed - please report this bug.
Instruction: {bif,tuple_size,{f,0},[{x,0}],{z,0}}
Error: {invalid_store,{z,0},{integer,[]}}:
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
The previous optimizations caused some code in beam_jump to
become uncovered. Add tests to cover more code. Also remove
a clause in beam_jump:opt/3 that does not seem possible to
cover anymore (this is safe, because the clause was an
optimization).
|
|
Some lines in beam_peep were no longer covered when the sharing optimization
was added to beam_ssa_opt. Also remove some code from beam_peep that no
longer seems possible to cover.
|
|
Share code for semantically equivalent blocks referred to to by `br`
and `switch` instructions.
A similar optimization is done in `beam_jump`, but doing it here as
well is beneficial as it may enable other optimizations. Also, if
there are many semantically equivalent clauses, this optimization can
substanstially decrease compilation times.
|
|
* maint:
Fix internal consistency failure for is_function/2
Conflicts:
lib/compiler/src/beam_utils.erl
|
|
There could be an internal consistency failure when using is_function/2,
because an optimization did not take into account that is_function/2 can fail.
https://bugs.erlang.org/browse/ERL-778
|
|
|
|
This will help investigation of compiler bugs.
|
|
* maint:
Fix bug when beam_jump removes put_tuple instructions
Conflicts:
lib/compiler/src/beam_jump.erl
lib/compiler/test/beam_jump_SUITE.erl
|
|
beam_except: Generalize translation to func_info instructions
|
|
* bjorn/compiler/diffable:
scripts/diffable: Correct the number of modules being compiled
scripts/diffable: Use the diffable compiler option
Add a diffable option for the compiler
scripts/diffable: Refactor option parsing
|
|
`beam_jump` could remove a `put_tuple` instruction when the
tuple would not be used, but it would leave the following
`put` instructions. Make sure they are removed.
https://bugs.erlang.org/browse/ERL-759
|
|
The `beam_except` pass replaces some calls to `erlang:error/1` or
`erlang:error/2` with specialized instructions in order to reduce the
size of the BEAM code.
In functions that do binary matching, `beam_except` would fail to
translate the instructions that generate a `function_clause`
exception. Here is an example:
bsum(<<H:16,T/binary>>, Acc) ->
bsum(T, Acc+H);
bsum(<<>>, Acc) ->
Acc.
The BEAM code that generates the `function_clause` exception looks
like this:
{label,4}.
{test_heap,2,3}.
{put_list,{x,1},nil,{x,1}}.
%% The following two instructions prevents the translation.
{bs_set_position,{x,2},{x,0}}.
{bs_get_tail,{x,2},{x,0},3}.
{test_heap,2,2}.
{put_list,{x,0},{x,1},{x,1}}.
{move,{atom,function_clause},{x,0}}.
{line,...}.
{call_ext,2,{extfunc,erlang,error,2}}.
Make the translation of `function_clause` exceptions smarter, so
that the following code will be produced:
{label,4}.
{bs_set_position,{x,2},{x,0}}.
{bs_get_tail,{x,2},{x,0},3}.
{jump,{f,1}}. %Jump to `func_info` instruction.
(This issue was noticed when looking at the code generated by
https://github.com/tomas-abrahamsson/gpb.)
|
|
Add the `diffable` option to produce a more diff-friendly output in
a .S file. In a diffable .S file, label numbers starts from 1 in each
function and local function calls use function names instead of labels.
scripts/diffable produces diff-friendly files but only for a hard-coded
sub set of files in OTP. Having the option directly in the compiler
makes is easier to diff the BEAM code for arbitrary source modules.
|
|
The `beam_jump` pass could eliminate `move` instructions when it was
not safe to do so. See the new test case `unsafe_move_elimination/1`
for an example.
Reported-by: Michał Muskała
|
|
* maint:
beam_utils: Handle bs_start_match2 in anno_defs
|
|
into maint
* john/compiler/bs_match-anno-liveness-fix/OTP-15353/ERL-753:
beam_utils: Handle bs_start_match2 in anno_defs
|
|
|
|
* maint:
compiler: Forward +source flag to epp and fix bug in +deterministic
epp: Allow user to set source name independently of input file name
|
|
Fixes a crash during code generation of the following code:
call_atom() ->
fun({send = Send}) ->
Send()
end.
|
|
The source file path as given to `erlc` was included in an implicit
file attribute inserted by epp, even when the +source flag was
set to something else which was a bit surprising. It was also
included when +deterministic was specified, breaking the flag's
promise.
This commit forwards the +source flag to epp so it inserts the
right information, and if +deterministic is given it will be shaved
to just the base name of the file, guaranteeing the same result
regardless of how the input is reached.
|
|
Co-authored-by: John Högberg <[email protected]>
|
|
* maint:
Fix rare bug in binary matching (again)
Conflicts:
lib/compiler/src/beam_bsm.erl
lib/compiler/src/sys_core_bsm.erl
|
|
OTP 22 extends the binary instructions to support a Y register
destination. When giving an option to compile for an earlier
release, make sure that binary instructions don't use a Y register
destination, by rewriting the binary instructions to use an X
register destination and adding a `move` instruction to move
the value to the Y register.
|
|
Rewrite BSM optimizations in the new SSA-based intermediate format
|
|
|
|
This commit improves the bit-syntax match optimization pass,
leveraging the new SSA intermediate format to perform much more
aggressive optimizations. Some highlights:
* Watch contexts can be reused even after being passed to a
function or being used in a try block.
* Sub-binaries are no longer eagerly extracted, making it far
easier to keep "happy paths" free from binary creation.
* Trivial wrapper functions no longer disable context reuse.
|
|
2e40d8d1c51a attempted fix a bug in binary matching, but it only
fixed the bug for the minimized test case.
This commit removes the previous fix and fixes the bug in a more
effective way. See the comments in the new code in `sys_core_bsm`
for an explanation.
This commit restores the optimizations in string.erl and dets_v9.erl
that the previous fix disabled.
I have not found any code where this commit will disable optimizations
when they are actually safe. There are some changes to the code
in ssl_cipher.erl in that some bs_start_match2 instruction did not
reuse the binary register for the match context, but the delayed
sub binary optimizations was never applied to the code in the first
place.
https://bugs.erlang.org/browse/ERL-689
|
|
The following code broke because aliases weren't tracked for hd/1:
bug(Bool) ->
Bug = remote:call(),
if
Bool -> %% Branch of some kind.
_ = hd(Bug),
remote:call(),
hd(Bug)
end.
Related to 1f221b27f1336e747f7409692f260055dd3ddf79
|
|
|
|
|
|
Most of the optimizations in beam_dead have been superseded
by the optimizations in beam_ssa_dead.
The forward/1 pass of beam_dead has been moved to beam_jump.
The beam_split pass splits blocks that contain instructions with
non-zero labels. Because there are no optimizations left that optimize
instructions within blocks, beam_block never needs to put such
instructions into blocks in the first place. beam_split also moved
'move' instructions out block to help beam_dead. That is no longer
necessary since beam_dead no longer exists.
|
|
Add beam_ssa_dead to perform the main optimizations done
by beam_dead:
* Shortcut branches that jump to another block with a branch.
If it can be seen that the second branch will always branch
to a specific block, replace the target of the first branch.
* Combined nested sequences of '=:=' tests and switch
instructions operating on the same variable to a single switch.
Diffing the compiler output, it seems that beam_ssa_dead finds
many more opportunities for optimizations than beam_dead,
although it does not find all opportunities that beam_dead does.
In total, beam_ssa_dead is such improvement over beam_dead that
there is no reason to keep beam_dead as well as beam_ssa_dead.
Note that beam_ssa_dead does not attempt to optimize away
redundant bs_context_binary instructions, because that instruction
will be superseded by new instructions in the near future.
|
|
|
|
This optimization working on the SSA format will replace
the similar optimization in beam_dead. See the comment
for an explanation of what the new optimization does.
|
|
Add more instructions to the list of functions that can be safely
removed if their values are not used. This is necessary for
correctness when doing more aggressive optimizations. Without this
change, the 'succeeded' instruction could be optimized away leaving
just the instruction followed by an unconditional branch, which the
beam_ssa_codegen does not know how to handle. Here is an example:
_3 = bs_start_match _1
br label 13
By adding bs_start_match to the list, the bs_start_match instruction
will be removed too. (If the result of bs_start_match is actually
used, the succeeded instruction would not be removed.)
While we are it, rename the misnamed function is_pure/1 to
no_side_effect/1 and move it to beam_ssa. is_pure/1 is a bad name
because bif:get has no side effect, but is not pure.
|
|
|