From f39e0b6bbc5f5d9f6a55b87847bcad7707309883 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Gustavsson?= Date: Thu, 22 Apr 2010 13:37:18 +0200 Subject: compiler test: Test optimization of receive statements We don't attempt to run the generated code, but use beam_disasm and check for the presence or absence (as appropriate) of the recv_mark/1 and recv_set/1 instructions. --- lib/compiler/test/receive_SUITE.erl | 53 +++++++++++- .../test/receive_SUITE_data/ref_opt/no_1.erl | 99 ++++++++++++++++++++++ .../test/receive_SUITE_data/ref_opt/no_2.erl | 26 ++++++ .../test/receive_SUITE_data/ref_opt/no_3.erl | 14 +++ .../test/receive_SUITE_data/ref_opt/yes_1.erl | 12 +++ .../test/receive_SUITE_data/ref_opt/yes_2.erl | 13 +++ .../test/receive_SUITE_data/ref_opt/yes_3.erl | 16 ++++ .../test/receive_SUITE_data/ref_opt/yes_4.erl | 16 ++++ .../test/receive_SUITE_data/ref_opt/yes_5.erl | 46 ++++++++++ .../test/receive_SUITE_data/ref_opt/yes_6.erl | 15 ++++ .../test/receive_SUITE_data/ref_opt/yes_7.erl | 12 +++ .../test/receive_SUITE_data/ref_opt/yes_8.erl | 15 ++++ .../test/receive_SUITE_data/ref_opt/yes_9.erl | 13 +++ 13 files changed, 347 insertions(+), 3 deletions(-) create mode 100644 lib/compiler/test/receive_SUITE_data/ref_opt/no_1.erl create mode 100644 lib/compiler/test/receive_SUITE_data/ref_opt/no_2.erl create mode 100644 lib/compiler/test/receive_SUITE_data/ref_opt/no_3.erl create mode 100644 lib/compiler/test/receive_SUITE_data/ref_opt/yes_1.erl create mode 100644 lib/compiler/test/receive_SUITE_data/ref_opt/yes_2.erl create mode 100644 lib/compiler/test/receive_SUITE_data/ref_opt/yes_3.erl create mode 100644 lib/compiler/test/receive_SUITE_data/ref_opt/yes_4.erl create mode 100644 lib/compiler/test/receive_SUITE_data/ref_opt/yes_5.erl create mode 100644 lib/compiler/test/receive_SUITE_data/ref_opt/yes_6.erl create mode 100644 lib/compiler/test/receive_SUITE_data/ref_opt/yes_7.erl create mode 100644 lib/compiler/test/receive_SUITE_data/ref_opt/yes_8.erl create mode 100644 lib/compiler/test/receive_SUITE_data/ref_opt/yes_9.erl diff --git a/lib/compiler/test/receive_SUITE.erl b/lib/compiler/test/receive_SUITE.erl index cb8833759a..3cfc22ddc9 100644 --- a/lib/compiler/test/receive_SUITE.erl +++ b/lib/compiler/test/receive_SUITE.erl @@ -21,7 +21,7 @@ -module(receive_SUITE). -export([all/1,init_per_testcase/2,fin_per_testcase/2, - recv/1,coverage/1,otp_7980/1]). + recv/1,coverage/1,otp_7980/1,ref_opt/1]). -include("test_server.hrl"). @@ -36,7 +36,7 @@ fin_per_testcase(_Case, Config) -> all(suite) -> test_lib:recompile(?MODULE), - [recv,coverage,otp_7980]. + [recv,coverage,otp_7980,ref_opt]. -record(state, {ena = true}). @@ -157,5 +157,52 @@ otp_7980_add_clients(Count) -> end, N - 1 end, Count, [1,2,3]). - + +ref_opt(Config) when is_list(Config) -> + case ?MODULE of + receive_SUITE -> ref_opt_1(Config); + _ -> {skip,"Enough to run this case once."} + end. + +ref_opt_1(Config) -> + ?line DataDir = ?config(data_dir, Config), + ?line PrivDir = ?config(priv_dir, Config), + ?line Sources = filelib:wildcard(filename:join([DataDir,"ref_opt","*.erl"])), + ?line test_lib:p_run(fun(Src) -> + do_ref_opt(Src, PrivDir) + end, Sources), + ok. + +do_ref_opt(Source, PrivDir) -> + try + {ok,Mod} = c:c(Source, [{outdir,PrivDir}]), + ok = Mod:Mod(), + Base = filename:rootname(filename:basename(Source), ".erl"), + BeamFile = filename:join(PrivDir, Base), + {beam_file,Mod,_,_,_,Code} = beam_disasm:file(BeamFile), + case Base of + "no_"++_ -> + [] = collect_recv_opt_instrs(Code); + "yes_"++_ -> + [{recv_mark,{f,L}},{recv_set,{f,L}}] = + collect_recv_opt_instrs(Code) + end, + ok + catch Class:Error -> + io:format("~s: ~p ~p\n~p\n", + [Source,Class,Error,erlang:get_stacktrace()]), + error + end. + +collect_recv_opt_instrs(Code) -> + L = [ [I || I <- Is, + begin + case I of + {recv_mark,{f,_}} -> true; + {recv_set,{f,_}} -> true; + _ -> false + end + end] || {function,_,_,_,Is} <- Code], + lists:append(L). + id(I) -> I. diff --git a/lib/compiler/test/receive_SUITE_data/ref_opt/no_1.erl b/lib/compiler/test/receive_SUITE_data/ref_opt/no_1.erl new file mode 100644 index 0000000000..bc63dac437 --- /dev/null +++ b/lib/compiler/test/receive_SUITE_data/ref_opt/no_1.erl @@ -0,0 +1,99 @@ +-module(no_1). +-compile(export_all). + +?MODULE() -> + ok. + +f1(X) -> + Ref = make_ref(), + receive + _ when [X] =:= Ref -> + ok + end. + +f2(X, Y) -> + _Ref = make_ref(), + receive + _ when X =:= Y -> + ok + end. + +f3(X) -> + Ref = make_ref(), + receive + _ when X =:= Ref -> + ok + end. + +f4(X) -> + Ref = make_ref(), + receive + {X,_} when not X =:= Ref -> + ok + end. + +f5(X) -> + Ref = make_ref(), + receive + {Y,_} when X =:= Y; Y =:= Ref -> + ok + end. + +f6(X) -> + Ref = make_ref(), + receive + {Y,_} when Y =:= Ref; Ref =:= X -> + ok + end. + +f7(X) -> + Ref = make_ref(), + receive + {Y,_} when Y =:= Ref; not (X =:= Ref) -> + ok + end. + +f8(X) -> + Ref = make_ref(), + receive + {Y,_} when not (X =:= Ref); Y =:= Ref -> + ok + end. + +f9(X) -> + Ref = make_ref(), + receive + {Y,_} when (not (X =:= Ref)) or (Y =:= Ref) -> + ok + end. + +f10(X, Y) -> + Ref = make_ref(), + receive + {Z,_} when not (X =:= Y andalso Z =:= Ref) -> + ok + end. + +f11(X, Y) -> + Ref = make_ref(), + receive + {Z,_} when not ((X =:= Y) and (Z =:= Ref)) -> + ok + end. + +f12(X, Y) -> + Ref = make_ref(), + receive + {Z,_} when not ((Z =:= Ref) and (X =:= Y)) -> + ok + end. + +f13() -> + Ref = make_ref(), + RefCopy = id(Ref), + receive + _ when hd([RefCopy]) =:= Ref -> + ok + end. + +id(I) -> I. diff --git a/lib/compiler/test/receive_SUITE_data/ref_opt/no_2.erl b/lib/compiler/test/receive_SUITE_data/ref_opt/no_2.erl new file mode 100644 index 0000000000..bc8d30c2ac --- /dev/null +++ b/lib/compiler/test/receive_SUITE_data/ref_opt/no_2.erl @@ -0,0 +1,26 @@ +-module(no_2). +-compile(export_all). + +?MODULE() -> + ok. + +f1() -> + Ref = make_ref(), + receive + {'DOWN',Ref} -> + ok; + {'DOWN',_} -> + ok + end. + +f2(Pid, Msg) -> + Ref = erlang:monitor(process, Pid), + Pid ! Msg, + receive + {ok,Ref,Reply} -> + {ok,Reply}; + {error,Ref,Reply} -> + {error,Reply}; + {error,A,B} -> + {error,A,B} + end. diff --git a/lib/compiler/test/receive_SUITE_data/ref_opt/no_3.erl b/lib/compiler/test/receive_SUITE_data/ref_opt/no_3.erl new file mode 100644 index 0000000000..44cf8d7f71 --- /dev/null +++ b/lib/compiler/test/receive_SUITE_data/ref_opt/no_3.erl @@ -0,0 +1,14 @@ +-module(no_3). +-compile(export_all). + +?MODULE() -> + ok. + +f(X) -> + Ref = case X of + false -> ref; + true -> make_ref() + end, + receive + Ref -> ok + end. diff --git a/lib/compiler/test/receive_SUITE_data/ref_opt/yes_1.erl b/lib/compiler/test/receive_SUITE_data/ref_opt/yes_1.erl new file mode 100644 index 0000000000..e2ebe234c1 --- /dev/null +++ b/lib/compiler/test/receive_SUITE_data/ref_opt/yes_1.erl @@ -0,0 +1,12 @@ +-module(yes_1). +-compile(export_all). + +?MODULE() -> + ok. + +f() -> + Ref = make_ref(), + receive + {Ref,Reply} -> + Reply + end. diff --git a/lib/compiler/test/receive_SUITE_data/ref_opt/yes_2.erl b/lib/compiler/test/receive_SUITE_data/ref_opt/yes_2.erl new file mode 100644 index 0000000000..6077cdcab9 --- /dev/null +++ b/lib/compiler/test/receive_SUITE_data/ref_opt/yes_2.erl @@ -0,0 +1,13 @@ +-module(yes_2). +-compile(export_all). + +?MODULE() -> + ok. + +f(Pid, Msg) -> + Ref = make_ref(), + Pid ! Msg, + receive + {Ref,Reply} -> + Reply + end. diff --git a/lib/compiler/test/receive_SUITE_data/ref_opt/yes_3.erl b/lib/compiler/test/receive_SUITE_data/ref_opt/yes_3.erl new file mode 100644 index 0000000000..28efc542ae --- /dev/null +++ b/lib/compiler/test/receive_SUITE_data/ref_opt/yes_3.erl @@ -0,0 +1,16 @@ +-module(yes_3). +-compile(export_all). + +?MODULE() -> + ok. + +f(Pid, Msg) -> + Ref = make_ref(), + do_send(Pid, Msg), + receive + {Ref,Reply} -> + Reply + end. + +do_send(Pid, Msg) -> + Pid ! Msg. diff --git a/lib/compiler/test/receive_SUITE_data/ref_opt/yes_4.erl b/lib/compiler/test/receive_SUITE_data/ref_opt/yes_4.erl new file mode 100644 index 0000000000..d1ba4832c7 --- /dev/null +++ b/lib/compiler/test/receive_SUITE_data/ref_opt/yes_4.erl @@ -0,0 +1,16 @@ +-module(yes_4). +-compile(export_all). + +?MODULE() -> + ok. + +f(Pid, Msg) -> + Ref = make_ref(), + catch do_send(Pid, Msg), + receive + {Ref,Reply} -> + Reply + end. + +do_send(Pid, Msg) -> + Pid ! Msg. diff --git a/lib/compiler/test/receive_SUITE_data/ref_opt/yes_5.erl b/lib/compiler/test/receive_SUITE_data/ref_opt/yes_5.erl new file mode 100644 index 0000000000..3f02fba6a6 --- /dev/null +++ b/lib/compiler/test/receive_SUITE_data/ref_opt/yes_5.erl @@ -0,0 +1,46 @@ +-module(yes_5). +-compile(export_all). + +?MODULE() -> + ok. + +do_call(Process, Label, Request, Timeout) -> + Node = case Process of + {_S, N} when is_atom(N) -> + N; + _ when is_pid(Process) -> + node(Process) + end, + try erlang:monitor(process, Process) of + Mref -> + catch erlang:send(Process, {Label, {self(), Mref}, Request}, + [noconnect]), + receive + {Mref, Reply} -> + erlang:demonitor(Mref, [flush]), + {ok, Reply}; + {'DOWN', Mref, _, _, noconnection} -> + exit({nodedown, Node}); + {'DOWN', Mref, _, _, Reason} -> + exit(Reason) + after Timeout -> + erlang:demonitor(Mref), + receive + {'DOWN', Mref, _, _, _} -> true + after 0 -> true + end, + exit(timeout) + end + catch + error:_ -> + monitor_node(Node, true), + receive + {nodedown, Node} -> + monitor_node(Node, false), + exit({nodedown, Node}) + after 0 -> + Tag = make_ref(), + Process ! {Label, {self(), Tag}, Request}, + ?MODULE:wait_resp(Node, Tag, Timeout) + end + end. diff --git a/lib/compiler/test/receive_SUITE_data/ref_opt/yes_6.erl b/lib/compiler/test/receive_SUITE_data/ref_opt/yes_6.erl new file mode 100644 index 0000000000..c54b636aa6 --- /dev/null +++ b/lib/compiler/test/receive_SUITE_data/ref_opt/yes_6.erl @@ -0,0 +1,15 @@ +-module(yes_6). +-compile(export_all). + +?MODULE() -> + ok. + +f(Pid, Msg) -> + Ref = erlang:monitor(process, Pid), + Pid ! Msg, + receive + {ok,Ref,Reply} -> + {ok,Reply}; + {error,Ref,Reply} -> + {error,Reply} + end. diff --git a/lib/compiler/test/receive_SUITE_data/ref_opt/yes_7.erl b/lib/compiler/test/receive_SUITE_data/ref_opt/yes_7.erl new file mode 100644 index 0000000000..849eab1746 --- /dev/null +++ b/lib/compiler/test/receive_SUITE_data/ref_opt/yes_7.erl @@ -0,0 +1,12 @@ +-module(yes_7). +-compile(export_all). + +?MODULE() -> + ok. + +f(X, Y) -> + Ref = make_ref(), + receive + {Z,_} when X =:= Y, Ref =:= Z -> + ok + end. diff --git a/lib/compiler/test/receive_SUITE_data/ref_opt/yes_8.erl b/lib/compiler/test/receive_SUITE_data/ref_opt/yes_8.erl new file mode 100644 index 0000000000..a47fe8cfbf --- /dev/null +++ b/lib/compiler/test/receive_SUITE_data/ref_opt/yes_8.erl @@ -0,0 +1,15 @@ +-module(yes_8). +-compile(export_all). + +?MODULE() -> + ok. + +%% Cover use of floating point registers. + +f(Pid, X) when is_float(X) -> + Ref = make_ref(), + Pid ! {X+3}, + receive + Ref -> + ok + end. diff --git a/lib/compiler/test/receive_SUITE_data/ref_opt/yes_9.erl b/lib/compiler/test/receive_SUITE_data/ref_opt/yes_9.erl new file mode 100644 index 0000000000..97fce5e734 --- /dev/null +++ b/lib/compiler/test/receive_SUITE_data/ref_opt/yes_9.erl @@ -0,0 +1,13 @@ +-module(yes_9). +-compile(export_all). + +?MODULE() -> + ok. + +f(Fun) -> + Ref = make_ref(), + Fun(), + receive + {Ref,Reply} -> + Reply + end. -- cgit v1.2.3