aboutsummaryrefslogtreecommitdiffstats
path: root/lib/compiler/src
diff options
context:
space:
mode:
authorBjörn Gustavsson <[email protected]>2014-02-12 14:52:44 +0100
committerBjörn Gustavsson <[email protected]>2014-02-12 14:52:44 +0100
commit152f1a4ba2f4e2f0dfbcde2efe5b5fd5edbdb986 (patch)
treebbd2547b06badbf7537ca966707f1367fb7d0b3f /lib/compiler/src
parentce1e2d3e865c42b01c8088ee07470a6f25be55cb (diff)
parentc89ada7517420ce9065840ea857a0009418ce2af (diff)
downloadotp-152f1a4ba2f4e2f0dfbcde2efe5b5fd5edbdb986.tar.gz
otp-152f1a4ba2f4e2f0dfbcde2efe5b5fd5edbdb986.tar.bz2
otp-152f1a4ba2f4e2f0dfbcde2efe5b5fd5edbdb986.zip
Merge branch 'bjorn/compiler/optimizations/OTP-11584'
* bjorn/compiler/optimizations/OTP-11584: Teach sys_core_fold:eval_case/2 to cope with handwritten Core Erlang sys_core_fold: Remove a redundant word in a comment
Diffstat (limited to 'lib/compiler/src')
-rw-r--r--lib/compiler/src/sys_core_fold.erl24
1 files changed, 17 insertions, 7 deletions
diff --git a/lib/compiler/src/sys_core_fold.erl b/lib/compiler/src/sys_core_fold.erl
index e302e2324d..500d431afe 100644
--- a/lib/compiler/src/sys_core_fold.erl
+++ b/lib/compiler/src/sys_core_fold.erl
@@ -1940,7 +1940,9 @@ opt_bool_case_guard(Arg, [#c_clause{pats=[#c_literal{val=false}]}=Fc,Tc]) ->
%% last clause is guaranteed to match so if there is only one clause
%% with a pattern containing only variables then rewrite to a let.
-eval_case(#c_case{arg=E,clauses=[#c_clause{pats=Ps0,body=B}]}, Sub) ->
+eval_case(#c_case{arg=E,clauses=[#c_clause{pats=Ps0,
+ guard=#c_literal{val=true},
+ body=B}]}=Case, Sub) ->
Es = case cerl:is_c_values(E) of
true -> cerl:values_es(E);
false -> [E]
@@ -1955,7 +1957,7 @@ eval_case(#c_case{arg=E,clauses=[#c_clause{pats=Ps0,body=B}]}, Sub) ->
%%
%% let <X,Y> = <SomeSideEffect(),SomeSideEffect()> in ...
%%
- %% because SomeSideEffect() would be called evaluated twice.
+ %% because SomeSideEffect() would be evaluated twice.
%%
%% Instead we must evaluate the case expression in an outer let
%% like this:
@@ -1964,11 +1966,19 @@ eval_case(#c_case{arg=E,clauses=[#c_clause{pats=Ps0,body=B}]}, Sub) ->
%% let <X,Y> = <NewVar,NewVar> in ...
%%
Vs = make_vars([], length(Es)),
- {true,Bs} = cerl_clauses:match_list(Ps0, Vs),
- {Ps,As} = unzip(Bs),
- InnerLet = cerl:c_let(Ps, core_lib:make_values(As), B),
- Let = cerl:c_let(Vs, E, InnerLet),
- expr(Let, sub_new(Sub));
+ case cerl_clauses:match_list(Ps0, Vs) of
+ {false,_} ->
+ %% This can only happen if the Core Erlang code is
+ %% handwritten or generated by another code generator
+ %% than v3_core. Assuming that the Core Erlang program
+ %% is correct, the clause will always match at run-time.
+ Case;
+ {true,Bs} ->
+ {Ps,As} = unzip(Bs),
+ InnerLet = cerl:c_let(Ps, core_lib:make_values(As), B),
+ Let = cerl:c_let(Vs, E, InnerLet),
+ expr(Let, sub_new(Sub))
+ end;
eval_case(Case, _) -> Case.
%% case_opt(CaseArg, [Clause]) -> {CaseArg,[Clause]}.