From c758fa81e1c48c56ff20ef2a95e6424c1e69033a Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Bj=C3=B6rn=20Gustavsson?= <bjorn@erlang.org>
Date: Tue, 12 May 2015 06:34:54 +0200
Subject: sys_core_fold: Eliminate warnings for unused terms

The optimization introduced in 0a0d39d351fc would cause spurious
warnings of the type: "a term is constructed, but never used".

To avoid the warning, we must mark not only tuples and lists as
compiler_generated, but also each element. We must also propagate
compiler_generated annotations in lets. For example, if we have:

  let <X -| ['compiler_generated']> = 42 in X + 1

we must propagate the compiler_generated annotation to the literal
when do constant propagation:

  42 -| ['compiler_generated'] + 1
---
 lib/compiler/src/sys_core_fold.erl   | 27 ++++++++++++++++++++-------
 lib/compiler/test/warnings_SUITE.erl |  8 ++++++++
 2 files changed, 28 insertions(+), 7 deletions(-)

(limited to 'lib')

diff --git a/lib/compiler/src/sys_core_fold.erl b/lib/compiler/src/sys_core_fold.erl
index 6f8279f65e..4068d60ec4 100644
--- a/lib/compiler/src/sys_core_fold.erl
+++ b/lib/compiler/src/sys_core_fold.erl
@@ -1130,11 +1130,23 @@ let_substs_1(Vs, #c_values{es=As}, Sub) ->
 let_substs_1([V], A, Sub) -> let_subst_list([V], [A], Sub);
 let_substs_1(Vs, A, _) -> {Vs,A,[]}.
 
-let_subst_list([V|Vs0], [A|As0], Sub) ->
+let_subst_list([V|Vs0], [A0|As0], Sub) ->
     {Vs1,As1,Ss} = let_subst_list(Vs0, As0, Sub),
-    case is_subst(A) of
-	true -> {Vs1,As1,sub_subst_var(V, A, Sub) ++ Ss};
-	false -> {[V|Vs1],[A|As1],Ss}
+    case is_subst(A0) of
+	true ->
+	    A = case is_compiler_generated(V) andalso
+		    not is_compiler_generated(A0) of
+		    true ->
+			%% Propagate the 'compiler_generated' annotation
+			%% along with the value.
+			Ann = [compiler_generated|cerl:get_ann(A0)],
+			cerl:set_ann(A0, Ann);
+		    false ->
+			A0
+		end,
+	    {Vs1,As1,sub_subst_var(V, A, Sub) ++ Ss};
+	false ->
+	    {[V|Vs1],[A0|As1],Ss}
     end;
 let_subst_list([], [], _) -> {[],[],[]}.
 
@@ -1899,8 +1911,8 @@ case_data_pat_alias(P, BindTo0, TypeSig, Bs0) ->
 	    %% Here we will need to actually build the data and bind
 	    %% it to the variable.
 	    {Type,Arity} = TypeSig,
-	    Vars = make_vars([], Arity),
 	    Ann = [compiler_generated],
+	    Vars = make_vars(Ann, Arity),
 	    Data = cerl:ann_make_data(Ann, Type, Vars),
 	    Bs = [{BindTo0,P},{P,Data}|Bs0],
 	    {Vars,Bs};
@@ -2392,8 +2404,9 @@ delay_build_1(Core0, TypeSig) ->
     try delay_build_expr(Core0, TypeSig) of
 	Core ->
 	    {Type,Arity} = TypeSig,
-	    Vars = make_vars([], Arity),
-	    Data = cerl:ann_make_data([compiler_generated], Type, Vars),
+	    Ann = [compiler_generated],
+	    Vars = make_vars(Ann, Arity),
+	    Data = cerl:ann_make_data(Ann, Type, Vars),
 	    {yes,Vars,Core,Data}
     catch
 	throw:impossible ->
diff --git a/lib/compiler/test/warnings_SUITE.erl b/lib/compiler/test/warnings_SUITE.erl
index f6ba75577d..471ded219f 100644
--- a/lib/compiler/test/warnings_SUITE.erl
+++ b/lib/compiler/test/warnings_SUITE.erl
@@ -739,6 +739,14 @@ no_warnings(Config) when is_list(Config) ->
                 case R0 of
 	          {r,V1,_V2,V3} -> {r,V1,\"def\",V3}
                 end.
+
+              d(In0, Bool) ->
+                {In1,Int} = case id(Bool) of
+                              false -> {In0,0}
+                            end,
+                [In1,Int].
+
+              id(I) -> I.
            ">>,
            [],
            []}],
-- 
cgit v1.2.3


From 3d012b584a57e0ba8f76f00f475428a35e081885 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Bj=C3=B6rn=20Gustavsson?= <bjorn@erlang.org>
Date: Fri, 22 May 2015 11:54:06 +0200
Subject: sys_core_fold: Eliminate warnings for unused terms in effect context

The optimization introduced in 0a0d39d351fc could cause spurious
warnings of the type: "a term is constructed, but never used".
That would happen for constructs in effect context.

To avoid those warnings, we will need to apply warning suppression
also in effect context.
---
 lib/compiler/src/sys_core_fold.erl   | 25 +++++++++++++++----------
 lib/compiler/test/warnings_SUITE.erl | 16 +++++++++++++++-
 2 files changed, 30 insertions(+), 11 deletions(-)

(limited to 'lib')

diff --git a/lib/compiler/src/sys_core_fold.erl b/lib/compiler/src/sys_core_fold.erl
index 4068d60ec4..37006cd8ce 100644
--- a/lib/compiler/src/sys_core_fold.erl
+++ b/lib/compiler/src/sys_core_fold.erl
@@ -2493,7 +2493,7 @@ opt_simple_let_2(Let0, Vs0, Arg0, Body, PrevBody, Ctxt, Sub) ->
 		    Arg1;
 		false ->
 		    %% let <Var> = Arg in <OtherVar>  ==>  seq Arg OtherVar
-		    Arg = maybe_suppress_warnings(Arg1, Vs0, PrevBody, Ctxt),
+		    Arg = maybe_suppress_warnings(Arg1, Vs0, PrevBody),
 		    expr(#c_seq{arg=Arg,body=Body}, Ctxt,
 			 sub_new_preserve_types(Sub))
 	    end;
@@ -2501,7 +2501,7 @@ opt_simple_let_2(Let0, Vs0, Arg0, Body, PrevBody, Ctxt, Sub) ->
 	    %% No variables left.
 	    Body;
 	{Vs,Arg1,#c_literal{}} ->
-	    Arg = maybe_suppress_warnings(Arg1, Vs, PrevBody, Ctxt),
+	    Arg = maybe_suppress_warnings(Arg1, Vs, PrevBody),
 	    E = case Ctxt of
 		    effect ->
 			%% Throw away the literal body.
@@ -2520,7 +2520,7 @@ opt_simple_let_2(Let0, Vs0, Arg0, Body, PrevBody, Ctxt, Sub) ->
 	    %%        seq Arg BodyWithoutVar
 	    case is_any_var_used(Vs, Body) of
 		false ->
-		    Arg = maybe_suppress_warnings(Arg1, Vs, PrevBody, Ctxt),
+		    Arg = maybe_suppress_warnings(Arg1, Vs, PrevBody),
 		    expr(#c_seq{arg=Arg,body=Body}, Ctxt,
 			 sub_new_preserve_types(Sub));
 		true ->
@@ -2530,7 +2530,7 @@ opt_simple_let_2(Let0, Vs0, Arg0, Body, PrevBody, Ctxt, Sub) ->
 	    end
     end.
 
-%% maybe_suppress_warnings(Arg, [#c_var{}], PreviousBody, Context) -> Arg'
+%% maybe_suppress_warnings(Arg, [#c_var{}], PreviousBody) -> Arg'
 %%  Try to suppress false warnings when a variable is not used.
 %%  For instance, we don't expect a warning for useless building in:
 %%
@@ -2541,10 +2541,7 @@ opt_simple_let_2(Let0, Vs0, Arg0, Body, PrevBody, Ctxt, Sub) ->
 %%  referenced in the original unoptimized code. If they were, we will
 %%  consider the warning false and suppress it.
 
-maybe_suppress_warnings(Arg, _, _, effect) ->
-    %% Don't suppress any warnings in effect context.
-    Arg;
-maybe_suppress_warnings(Arg, Vs, PrevBody, value) ->
+maybe_suppress_warnings(Arg, Vs, PrevBody) ->
     case should_suppress_warning(Arg) of
 	true ->
 	    Arg;				%Already suppressed.
@@ -2568,8 +2565,16 @@ suppress_warning([H|T]) ->
 		true ->
 		    suppress_warning(cerl:data_es(H) ++ T);
 		false ->
-		    Arg = cerl:set_ann(H, [compiler_generated]),
-		    cerl:c_seq(Arg, suppress_warning(T))
+		    %% Some other thing, such as a function call.
+		    %% This cannot be the compiler's fault, so the
+		    %% warning should not be suppressed. We must
+		    %% be careful not to destroy tail-recursion.
+		    case T of
+			[] ->
+			    H;
+			[_|_] ->
+			    cerl:c_seq(H, suppress_warning(T))
+		    end
 	    end
     end;
 suppress_warning([]) -> void().
diff --git a/lib/compiler/test/warnings_SUITE.erl b/lib/compiler/test/warnings_SUITE.erl
index 471ded219f..ca6946e3cd 100644
--- a/lib/compiler/test/warnings_SUITE.erl
+++ b/lib/compiler/test/warnings_SUITE.erl
@@ -281,6 +281,7 @@ bad_arith(Config) when is_list(Config) ->
 	     {3,sys_core_fold,{eval_failure,badarith}},
 	     {9,sys_core_fold,nomatch_guard},
 	     {9,sys_core_fold,{eval_failure,badarith}},
+	     {9,sys_core_fold,{no_effect,{erlang,is_integer,1}}},
 	     {10,sys_core_fold,nomatch_guard},
 	     {10,sys_core_fold,{eval_failure,badarith}},
 	     {15,sys_core_fold,{eval_failure,badarith}}
@@ -369,7 +370,7 @@ files(Config) when is_list(Config) ->
 
 %% Test warnings for term construction and BIF calls in effect context.
 effect(Config) when is_list(Config) ->
-    Ts = [{lc,
+    Ts = [{effect,
 	   <<"
              t(X) ->
                case X of
@@ -475,6 +476,19 @@ effect(Config) when is_list(Config) ->
              m9(Bs) ->
                 [{B,ok} = {B,foo:bar(B)} || B <- Bs],
                 ok.
+
+             m10(ConfigTableSize) ->
+               case ConfigTableSize of
+                 apa ->
+                   CurrentConfig = {id(camel_phase3),id(sms)},
+                   case CurrentConfig of
+                     {apa, bepa} -> ok;
+		     _ -> ok
+	           end
+               end,
+               ok.
+
+             id(I) -> I.
              ">>,
 	   [],
 	   {warnings,[{5,sys_core_fold,{no_effect,{erlang,is_integer,1}}},
-- 
cgit v1.2.3