diff options
Diffstat (limited to 'lib/compiler/src')
| -rw-r--r-- | lib/compiler/src/beam_validator.erl | 4 | ||||
| -rw-r--r-- | lib/compiler/src/compile.erl | 6 | ||||
| -rw-r--r-- | lib/compiler/src/sys_core_fold.erl | 78 | ||||
| -rw-r--r-- | lib/compiler/src/v3_core.erl | 22 |
4 files changed, 98 insertions, 12 deletions
diff --git a/lib/compiler/src/beam_validator.erl b/lib/compiler/src/beam_validator.erl index 682f7adbc2..2486d486ed 100644 --- a/lib/compiler/src/beam_validator.erl +++ b/lib/compiler/src/beam_validator.erl @@ -882,7 +882,7 @@ valfun_4(_, _) -> verify_put_map(Fail, Src, Dst, Live, List, Vst0) -> verify_live(Live, Vst0), verify_y_init(Vst0), - [assert_term(Term, Vst0) || Term <- List], + foreach(fun (Term) -> assert_term(Term, Vst0) end, List), assert_term(Src, Vst0), Vst1 = heap_alloc(0, Vst0), Vst2 = branch_state(Fail, Vst1), @@ -909,7 +909,7 @@ validate_bs_skip_utf(Fail, Ctx, Live, Vst0) -> branch_state(Fail, Vst). %% -%% Special state handling for setelement/3 and the set_tuple_element/3 instruction. +%% Special state handling for setelement/3 and set_tuple_element/3 instructions. %% A possibility for garbage collection must not occur between setelement/3 and %% set_tuple_element/3. %% diff --git a/lib/compiler/src/compile.erl b/lib/compiler/src/compile.erl index 5588f1fbe5..e79fe41f9b 100644 --- a/lib/compiler/src/compile.erl +++ b/lib/compiler/src/compile.erl @@ -626,7 +626,8 @@ core_passes() -> {iff,dcorefold,{listing,"corefold"}}, {core_inline_module,fun test_core_inliner/1,fun core_inline_module/1}, {iff,dinline,{listing,"inline"}}, - {core_fold_after_inlining,fun test_core_inliner/1,fun core_fold_module_after_inlining/1}, + {core_fold_after_inlining,fun test_any_inliner/1, + fun core_fold_module_after_inlining/1}, ?pass(core_transforms)]}, {iff,dcopt,{listing,"copt"}}, {iff,'to_core',{done,"core"}}]} @@ -1172,6 +1173,9 @@ test_core_inliner(#compile{options=Opts}) -> end, Opts) end. +test_any_inliner(St) -> + test_old_inliner(St) orelse test_core_inliner(St). + core_old_inliner(#compile{code=Code0,options=Opts}=St) -> {ok,Code} = sys_core_inline:module(Code0, Opts), {ok,St#compile{code=Code}}. diff --git a/lib/compiler/src/sys_core_fold.erl b/lib/compiler/src/sys_core_fold.erl index 500d431afe..e2b9213891 100644 --- a/lib/compiler/src/sys_core_fold.erl +++ b/lib/compiler/src/sys_core_fold.erl @@ -353,7 +353,12 @@ expr(#c_case{}=Case0, Ctxt, Sub) -> Case = Case1#c_case{arg=Arg2,clauses=Cs2}, warn_no_clause_match(Case1, Case), Expr = eval_case(Case, Sub), - bsm_an(Expr); + case move_case_into_arg(Case, Sub) of + impossible -> + bsm_an(Expr); + Other -> + expr(Other, Ctxt, sub_new_preserve_types(Sub)) + end; Other -> expr(Other, Ctxt, Sub) end; @@ -2606,6 +2611,77 @@ opt_simple_let_2(Let, Vs0, Arg0, Body, value, Sub) -> value, Sub) end. +move_case_into_arg(#c_case{arg=#c_let{vars=OuterVars0,arg=OuterArg, + body=InnerArg0}=Outer, + clauses=InnerClauses}=Inner, Sub) -> + %% + %% case let <OuterVars> = <OuterArg> in <InnerArg> of + %% <InnerClauses> + %% end + %% + %% ==> + %% + %% let <OuterVars> = <OuterArg> + %% in case <InnerArg> of <InnerClauses> end + %% + ScopeSub0 = sub_subst_scope(Sub#sub{t=[]}), + {OuterVars,ScopeSub} = pattern_list(OuterVars0, ScopeSub0), + InnerArg = body(InnerArg0, ScopeSub), + Outer#c_let{vars=OuterVars,arg=OuterArg, + body=Inner#c_case{arg=InnerArg,clauses=InnerClauses}}; +move_case_into_arg(#c_case{arg=#c_case{arg=OuterArg, + clauses=[OuterCa0,OuterCb]}=Outer, + clauses=InnerClauses}=Inner0, Sub) -> + case is_failing_clause(OuterCb) of + true -> + #c_clause{pats=OuterPats0,guard=OuterGuard0, + body=InnerArg0} = OuterCa0, + %% + %% case case <OuterArg> of + %% <OuterPats> when <OuterGuard> -> <InnerArg> + %% <OuterCb> + %% ... + %% end of + %% <InnerClauses> + %% end + %% + %% ==> + %% + %% case <OuterArg> of + %% <OuterPats> when <OuterGuard> -> + %% case <InnerArg> of <InnerClauses> end + %% <OuterCb> + %% end + %% + ScopeSub0 = sub_subst_scope(Sub#sub{t=[]}), + {OuterPats,ScopeSub} = pattern_list(OuterPats0, ScopeSub0), + OuterGuard = guard(OuterGuard0, ScopeSub), + InnerArg = body(InnerArg0, ScopeSub), + Inner = Inner0#c_case{arg=InnerArg,clauses=InnerClauses}, + OuterCa = OuterCa0#c_clause{pats=OuterPats,guard=OuterGuard, + body=Inner}, + Outer#c_case{arg=OuterArg, + clauses=[OuterCa,OuterCb]}; + false -> + impossible + end; +move_case_into_arg(#c_case{arg=#c_seq{arg=OuterArg,body=InnerArg}=Outer, + clauses=InnerClauses}=Inner, _Sub) -> + %% + %% case do <OuterArg> <InnerArg> of + %% <InnerClauses> + %% end + %% + %% ==> + %% + %% do <OuterArg> + %% case <InnerArg> of <InerClauses> end + %% + Outer#c_seq{arg=OuterArg, + body=Inner#c_case{arg=InnerArg,clauses=InnerClauses}}; +move_case_into_arg(_, _) -> + impossible. + %% In guards only, rewrite a case in a let argument like %% %% let <Var> = case <> of diff --git a/lib/compiler/src/v3_core.erl b/lib/compiler/src/v3_core.erl index 291443f824..ec5deb6905 100644 --- a/lib/compiler/src/v3_core.erl +++ b/lib/compiler/src/v3_core.erl @@ -900,6 +900,7 @@ lc_tq(Line, E, [{generate,Lg,P,G}|Qs0], Mc, St0) -> {Head,St2} = new_var(St1), {Tname,St3} = new_var_name(St2), LA = lineno_anno(Line, St3), + CGAnno = #a{anno=[list_comprehension|LA]}, LAnno = #a{anno=LA}, Tail = #c_var{anno=LA,name=Tname}, {Arg,St4} = new_var(St3), @@ -937,7 +938,7 @@ lc_tq(Line, E, [{generate,Lg,P,G}|Qs0], Mc, St0) -> body=Lps ++ [Lc]}|Cs0] end, Fun = #ifun{anno=LAnno,id=[],vars=[Arg],clauses=Cs,fc=Fc}, - {#iletrec{anno=LAnno,defs=[{{Name,1},Fun}], + {#iletrec{anno=CGAnno,defs=[{{Name,1},Fun}], body=Gps ++ [#iapply{anno=LAnno, op=#c_var{anno=LA,name={Name,1}}, args=[Gc]}]}, @@ -947,6 +948,7 @@ lc_tq(Line, E, [{b_generate,Lg,P,G}|Qs0], Mc, St0) -> {Name,St1} = new_fun_name("blc", St0), LA = lineno_anno(Line, St1), LAnno = #a{anno=LA}, + CGAnno = #a{anno=[list_comprehension|LA]}, HeadBinPattern = pattern(P, St1), #c_binary{segments=Ps0} = HeadBinPattern, {Ps,Tail,St2} = append_tail_segment(Ps0, St1), @@ -975,7 +977,7 @@ lc_tq(Line, E, [{b_generate,Lg,P,G}|Qs0], Mc, St0) -> pats=[#c_binary{anno=LA,segments=TailSegList}],guard=[], body=[Mc]}], Fun = #ifun{anno=LAnno,id=[],vars=[Arg],clauses=Cs,fc=Fc}, - {#iletrec{anno=LAnno,defs=[{{Name,1},Fun}], + {#iletrec{anno=CGAnno,defs=[{{Name,1},Fun}], body=Gps ++ [#iapply{anno=LAnno, op=#c_var{anno=LA,name={Name,1}}, args=[Gc]}]}, @@ -984,12 +986,13 @@ lc_tq(Line, E, [Fil0|Qs0], Mc, St0) -> %% Special case sequences guard tests. LA = lineno_anno(element(2, Fil0), St0), LAnno = #a{anno=LA}, + CGAnno = #a{anno=[list_comprehension|LA]}, case is_guard_test(Fil0) of true -> {Gs0,Qs1} = splitwith(fun is_guard_test/1, Qs0), {Lc,Lps,St1} = lc_tq(Line, E, Qs1, Mc, St0), {Gs,St2} = lc_guard_tests([Fil0|Gs0], St1), %These are always flat! - {#icase{anno=LAnno, + {#icase{anno=CGAnno, args=[], clauses=[#iclause{anno=LAnno,pats=[], guard=Gs,body=Lps ++ [Lc]}], @@ -1003,7 +1006,7 @@ lc_tq(Line, E, [Fil0|Qs0], Mc, St0) -> c_tuple([#c_literal{val=case_clause},Fpat])), %% Do a novars little optimisation here. {Filc,Fps,St3} = novars(Fil0, St2), - {#icase{anno=LAnno, + {#icase{anno=CGAnno, args=[Filc], clauses=[#iclause{anno=LAnno, pats=[#c_literal{anno=LA,val=true}], @@ -1047,6 +1050,7 @@ bc_tq1(Line, E, [{generate,Lg,P,G}|Qs0], AccExpr, St0) -> LA = lineno_anno(Line, St1), {[Head,Tail,AccVar],St2} = new_vars(LA, 3, St1), LAnno = #a{anno=LA}, + CGAnno = #a{anno=[list_comprehension|LA]}, {Arg,St3} = new_var(St2), NewMore = {call,Lg,{atom,Lg,Name},[{var,Lg,Tail#c_var.name}, {var,Lg,AccVar#c_var.name}]}, @@ -1080,7 +1084,7 @@ bc_tq1(Line, E, [{generate,Lg,P,G}|Qs0], AccExpr, St0) -> body=Body}|Cs0] end, Fun = #ifun{anno=LAnno,id=[],vars=[Arg,AccVar],clauses=Cs,fc=Fc}, - {#iletrec{anno=LAnno,defs=[{{Name,2},Fun}], + {#iletrec{anno=CGAnno,defs=[{{Name,2},Fun}], body=Gps ++ [#iapply{anno=LAnno, op=#c_var{anno=LA,name={Name,2}}, args=[Gc,AccExpr]}]}, @@ -1091,6 +1095,7 @@ bc_tq1(Line, E, [{b_generate,Lg,P,G}|Qs0], AccExpr, St0) -> LA = lineno_anno(Line, St1), {AccVar,St2} = new_var(LA, St1), LAnno = #a{anno=LA}, + CGAnno = #a{anno=[list_comprehension|LA]}, HeadBinPattern = pattern(P, St2), #c_binary{segments=Ps0} = HeadBinPattern, {Ps,Tail,St3} = append_tail_segment(Ps0, St2), @@ -1119,7 +1124,7 @@ bc_tq1(Line, E, [{b_generate,Lg,P,G}|Qs0], AccExpr, St0) -> pats=[#c_binary{anno=LA,segments=TailSegList},AccVar], guard=[], body=[AccVar]}], - Fun = #ifun{anno=LAnno,id=[],vars=[Arg,AccVar],clauses=Cs,fc=Fc}, + Fun = #ifun{anno=CGAnno,id=[],vars=[Arg,AccVar],clauses=Cs,fc=Fc}, {#iletrec{anno=LAnno,defs=[{{Name,2},Fun}], body=Gps ++ [#iapply{anno=LAnno, op=#c_var{anno=LA,name={Name,2}}, @@ -1129,12 +1134,13 @@ bc_tq1(Line, E, [Fil0|Qs0], AccVar, St0) -> %% Special case sequences guard tests. LA = lineno_anno(element(2, Fil0), St0), LAnno = #a{anno=LA}, + CGAnno = #a{anno=[list_comprehension|LA]}, case is_guard_test(Fil0) of true -> {Gs0,Qs1} = splitwith(fun is_guard_test/1, Qs0), {Bc,Bps,St1} = bc_tq1(Line, E, Qs1, AccVar, St0), {Gs,St} = lc_guard_tests([Fil0|Gs0], St1), %These are always flat! - {#icase{anno=LAnno, + {#icase{anno=CGAnno, args=[], clauses=[#iclause{anno=LAnno, pats=[], @@ -1149,7 +1155,7 @@ bc_tq1(Line, E, [Fil0|Qs0], AccVar, St0) -> c_tuple([#c_literal{val=case_clause},Fpat])), %% Do a novars little optimisation here. {Filc,Fps,St} = novars(Fil0, St2), - {#icase{anno=LAnno, + {#icase{anno=CGAnno, args=[Filc], clauses=[#iclause{anno=LAnno, pats=[#c_literal{anno=LA,val=true}], |
