aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--lib/compiler/src/cerl_inline.erl39
-rw-r--r--lib/compiler/test/inline_SUITE.erl3
-rw-r--r--lib/compiler/test/inline_SUITE_data/fname.erl29
3 files changed, 61 insertions, 10 deletions
diff --git a/lib/compiler/src/cerl_inline.erl b/lib/compiler/src/cerl_inline.erl
index 2e7554c1ff..c6de63c69f 100644
--- a/lib/compiler/src/cerl_inline.erl
+++ b/lib/compiler/src/cerl_inline.erl
@@ -52,7 +52,7 @@
clause_pats/1, clause_vars/1, concrete/1, cons_hd/1,
cons_tl/1, data_arity/1, data_es/1, data_type/1,
fun_body/1, fun_vars/1, get_ann/1, int_val/1,
- is_c_atom/1, is_c_cons/1, is_c_fun/1, is_c_int/1,
+ is_c_atom/1, is_c_cons/1, is_c_fname/1, is_c_int/1,
is_c_list/1, is_c_seq/1, is_c_tuple/1, is_c_var/1,
is_data/1, is_literal/1, is_literal_term/1, let_arg/1,
let_body/1, let_vars/1, letrec_body/1, letrec_defs/1,
@@ -1578,7 +1578,7 @@ make_let_binding_1(R, E, S) ->
%% completely.
copy(R, Opnd, E, Ctxt, Env, S) ->
- case is_c_var(E) of
+ case is_c_var(E) andalso not is_c_fname(E) of
true ->
%% The operand reduces to another variable - get its
%% ref-structure and attempt to propagate further.
@@ -1628,12 +1628,12 @@ copy_var(R, Ctxt, Env, S) ->
end.
copy_1(R, Opnd, E, Ctxt, Env, S) ->
- %% Fun-expression (lambdas) are a bit special; they are copyable,
- %% but should preferably not be duplicated, so they should not be
- %% copy propagated except into application contexts, where they can
- %% be inlined.
- case is_c_fun(E) of
- true ->
+ case type(E) of
+ 'fun' ->
+ %% Fun-expression (lambdas) are a bit special; they are copyable,
+ %% but should preferably not be duplicated, so they should not be
+ %% copy propagated except into application contexts, where they can
+ %% be inlined.
case Ctxt of
#app{} ->
%% First test if the operand is "outer-pending"; if
@@ -1649,7 +1649,28 @@ copy_1(R, Opnd, E, Ctxt, Env, S) ->
_ ->
residualize_var(R, S)
end;
- false ->
+ var ->
+ %% Variables at this point only refer to local functions; they are
+ %% copyable but can't appear in guards, so they should not be
+ %% copy propagated except into application contexts, where they can
+ %% be inlined.
+ case Ctxt of
+ #app{} ->
+ %% First test if the operand is "outer-pending"; if
+ %% so, don't inline.
+ case st__test_outer_pending(Opnd#opnd.loc, S) of
+ false ->
+ R1 = env__get(var_name(E), Opnd#opnd.env),
+ copy_var(R1, Ctxt, Env, S);
+ true ->
+ %% Cyclic reference forced inlining to stop
+ %% (avoiding infinite unfolding).
+ residualize_var(R, S)
+ end;
+ _ ->
+ residualize_var(R, S)
+ end;
+ _ ->
%% We have no other cases to handle here
residualize_var(R, S)
end.
diff --git a/lib/compiler/test/inline_SUITE.erl b/lib/compiler/test/inline_SUITE.erl
index d9b92766e4..e5c2d4f73a 100644
--- a/lib/compiler/test/inline_SUITE.erl
+++ b/lib/compiler/test/inline_SUITE.erl
@@ -36,7 +36,7 @@ all() ->
groups() ->
[{p,test_lib:parallel(),
- [attribute,bsdecode,bsdes,barnes2,decode1,smith,
+ [attribute,bsdecode,bsdes,barnes2,decode1,smith,fname,
itracer,pseudoknot,comma_splitter,lists,really_inlined,otp_7223,
coverage]}].
@@ -84,6 +84,7 @@ attribute(Config) when is_list(Config) ->
?comp(itracer).
?comp(pseudoknot).
?comp(comma_splitter).
+?comp(fname).
try_inline(Mod, Config) ->
Node = ?config(testing_node, Config),
diff --git a/lib/compiler/test/inline_SUITE_data/fname.erl b/lib/compiler/test/inline_SUITE_data/fname.erl
new file mode 100644
index 0000000000..7ad4446bf3
--- /dev/null
+++ b/lib/compiler/test/inline_SUITE_data/fname.erl
@@ -0,0 +1,29 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2013. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+%% the License for the specific language governing rights and limitations
+%% under the License.
+%%
+%% %CopyrightEnd%
+%%
+-module(fname).
+-export([?MODULE/0]).
+
+?MODULE() ->
+ F = fun bar/1,
+ G = lists:last([(fun (X) when F =:= X -> X end)]),
+ F = G(F),
+ ok.
+
+bar(X) ->
+ X.