aboutsummaryrefslogtreecommitdiffstats
path: root/lib/compiler/src/beam_flatten.erl
diff options
context:
space:
mode:
authorBjörn Gustavsson <[email protected]>2018-01-25 10:09:59 +0100
committerBjörn Gustavsson <[email protected]>2018-01-26 15:57:57 +0100
commitfbcff5a137e37edd80aca9c5fe18ce6880648169 (patch)
treefb846d82599a3e52230f1b028b59f63cb0dd09ec /lib/compiler/src/beam_flatten.erl
parent5b58d9e2d3262160b7f10d8b6798f89f0618c5f6 (diff)
downloadotp-fbcff5a137e37edd80aca9c5fe18ce6880648169.tar.gz
otp-fbcff5a137e37edd80aca9c5fe18ce6880648169.tar.bz2
otp-fbcff5a137e37edd80aca9c5fe18ce6880648169.zip
Eliminate get_list/3 internally in the compiler
Instructions that produce more than one result complicate optimizations. get_list/3 is one of two instructions that produce multiple results (get_map_elements/3 is the other). Introduce the get_hd/2 and get_tl/2 instructions that return the head and tail of a cons cell, respectively, and use it internally in all optimization passes. For efficiency, we still want to use get_list/3 if both head and tail are used, so we will translate matching pairs of get_hd and get_tl back to get_list instructions.
Diffstat (limited to 'lib/compiler/src/beam_flatten.erl')
-rw-r--r--lib/compiler/src/beam_flatten.erl6
1 files changed, 5 insertions, 1 deletions
diff --git a/lib/compiler/src/beam_flatten.erl b/lib/compiler/src/beam_flatten.erl
index a4d45a4ca6..4045ab6dc5 100644
--- a/lib/compiler/src/beam_flatten.erl
+++ b/lib/compiler/src/beam_flatten.erl
@@ -50,6 +50,9 @@ norm_block([{set,[],[],{alloc,R,Alloc}}|Is], Acc0) ->
Acc ->
norm_block(Is, Acc)
end;
+norm_block([{set,[D1],[S],get_hd},{set,[D2],[S],get_tl}|Is], Acc) ->
+ I = {get_list,S,D1,D2},
+ norm_block(Is, [I|Acc]);
norm_block([I|Is], Acc) -> norm_block(Is, [norm(I)|Acc]);
norm_block([], Acc) -> Acc.
@@ -64,7 +67,8 @@ norm({set,[D],[],{put_tuple,A}}) -> {put_tuple,A,D};
norm({set,[],[S],put}) -> {put,S};
norm({set,[D],[S],{get_tuple_element,I}}) -> {get_tuple_element,S,I,D};
norm({set,[],[S,D],{set_tuple_element,I}}) -> {set_tuple_element,S,D,I};
-norm({set,[D1,D2],[S],get_list}) -> {get_list,S,D1,D2};
+norm({set,[D],[S],get_hd}) -> {get_hd,S,D};
+norm({set,[D],[S],get_tl}) -> {get_tl,S,D};
norm({set,[D],[S|Puts],{alloc,R,{put_map,Op,F}}}) ->
{put_map,F,Op,S,D,R,{list,Puts}};
norm({set,[],[],remove_message}) -> remove_message;