From 51c7e590e470cb2aa8d09ac8f56a659e272d88b4 Mon Sep 17 00:00:00 2001 From: Anthony Ramine Date: Mon, 18 Nov 2013 11:49:58 +0100 Subject: Properly let floating-point instructions through in the BEAM compiler The compiler shouldn't crash when fed an already-optimised BEAM assembly file. --- lib/compiler/src/beam_block.erl | 4 ++++ lib/compiler/src/beam_type.erl | 6 ++++++ 2 files changed, 10 insertions(+) diff --git a/lib/compiler/src/beam_block.erl b/lib/compiler/src/beam_block.erl index cf5244e1ce..ea984a6afb 100644 --- a/lib/compiler/src/beam_block.erl +++ b/lib/compiler/src/beam_block.erl @@ -144,6 +144,10 @@ collect({set_tuple_element,S,D,I}) -> {set,[],[S,D],{set_tuple_element,I}}; collect({get_list,S,D1,D2}) -> {set,[D1,D2],[S],get_list}; collect(remove_message) -> {set,[],[],remove_message}; collect({'catch',R,L}) -> {set,[R],[],{'catch',L}}; +collect(fclearerror) -> {set,[],[],fclearerror}; +collect({fcheckerror,{f,0}}) -> {set,[],[],fcheckerror}; +collect({fmove,S,D}) -> {set,[D],[S],fmove}; +collect({fconv,S,D}) -> {set,[D],[S],fconv}; collect(_) -> error. %% embed_lines([Instruction]) -> [Instruction] diff --git a/lib/compiler/src/beam_type.erl b/lib/compiler/src/beam_type.erl index 3ec57a67da..58c0f765ae 100644 --- a/lib/compiler/src/beam_type.erl +++ b/lib/compiler/src/beam_type.erl @@ -142,6 +142,12 @@ simplify_float(Is0, Ts0) -> throw:not_possible -> not_possible end. +simplify_float_1([{set,[],[],fclearerror}|Is], Ts, Rs, Acc) -> + simplify_float_1(Is, Ts, Rs, clearerror(Acc)); +simplify_float_1([{set,[],[],fcheckerror}|Is], Ts, Rs, Acc) -> + simplify_float_1(Is, Ts, Rs, checkerror(Acc)); +simplify_float_1([{set,[{fr,_}],_,_}=I|Is], Ts, Rs, Acc) -> + simplify_float_1(Is, Ts, Rs, [I|Acc]); simplify_float_1([{set,[D0],[A0],{alloc,_,{gc_bif,'-',{f,0}}}}=I|Is]=Is0, Ts0, Rs0, Acc0) -> case tdb_find(A0, Ts0) of -- cgit v1.2.3 From 4df9a5ab0da9fed4ff67f99fdb191b56780bec0b Mon Sep 17 00:00:00 2001 From: Anthony Ramine Date: Tue, 19 Nov 2013 18:15:10 +0100 Subject: Properly collect allocate_zero instructions in beam_block If an allocate_zero instruction is fed to beam_block and the beam_type pass is not used afterwards (e.g. with erlc +no_topt), the 'no_opt' atom will be rejected by beam_flatten. --- lib/compiler/src/beam_block.erl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/compiler/src/beam_block.erl b/lib/compiler/src/beam_block.erl index ea984a6afb..5d96b51bff 100644 --- a/lib/compiler/src/beam_block.erl +++ b/lib/compiler/src/beam_block.erl @@ -124,7 +124,7 @@ collect_block(Is) -> collect_block(Is, []). collect_block([{allocate_zero,Ns,R},{test_heap,Nh,R}|Is], Acc) -> - collect_block(Is, [{set,[],[],{alloc,R,{no_opt,Ns,Nh,[]}}}|Acc]); + collect_block(Is, [{set,[],[],{alloc,R,{zero,Ns,Nh,[]}}}|Acc]); collect_block([I|Is]=Is0, Acc) -> case collect(I) of error -> {reverse(Acc),Is0}; -- cgit v1.2.3 From 7bd678640d855ee9053d6d78434a98d977ad0f1f Mon Sep 17 00:00:00 2001 From: Anthony Ramine Date: Tue, 19 Nov 2013 18:17:53 +0100 Subject: Collect all optimised allocate instructions in beam_block Any init instruction following an allocate is put in the Inits list of the corresponding alloc tuple. --- lib/compiler/src/beam_block.erl | 9 +++++++++ lib/compiler/src/beam_flatten.erl | 1 + 2 files changed, 10 insertions(+) diff --git a/lib/compiler/src/beam_block.erl b/lib/compiler/src/beam_block.erl index 5d96b51bff..402fbe2e2e 100644 --- a/lib/compiler/src/beam_block.erl +++ b/lib/compiler/src/beam_block.erl @@ -123,6 +123,11 @@ is_last_bool([], _) -> false. collect_block(Is) -> collect_block(Is, []). +collect_block([{allocate,N,R}|Is0], Acc) -> + {Inits,Is} = lists:splitwith(fun ({init,{y,_}}) -> true; + (_) -> false + end, Is0), + collect_block(Is, [{set,[],[],{alloc,R,{nozero,N,0,Inits}}}|Acc]); collect_block([{allocate_zero,Ns,R},{test_heap,Nh,R}|Is], Acc) -> collect_block(Is, [{set,[],[],{alloc,R,{zero,Ns,Nh,[]}}}|Acc]); collect_block([I|Is]=Is0, Acc) -> @@ -131,7 +136,11 @@ collect_block([I|Is]=Is0, Acc) -> Instr -> collect_block(Is, [Instr|Acc]) end. +collect({allocate,N,R}) -> {set,[],[],{alloc,R,{nozero,N,0,[]}}}; collect({allocate_zero,N,R}) -> {set,[],[],{alloc,R,{zero,N,0,[]}}}; +collect({allocate_heap,Ns,Nh,R}) -> {set,[],[],{alloc,R,{nozero,Ns,Nh,[]}}}; +collect({allocate_heap_zero,Ns,Nh,R}) -> {set,[],[],{alloc,R,{zero,Ns,Nh,[]}}}; +collect({init,D}) -> {set,[D],[],init}; collect({test_heap,N,R}) -> {set,[],[],{alloc,R,{nozero,nostack,N,[]}}}; collect({bif,N,F,As,D}) -> {set,[D],As,{bif,N,F}}; collect({gc_bif,N,F,R,As,D}) -> {set,[D],As,{alloc,R,{gc_bif,N,F}}}; diff --git a/lib/compiler/src/beam_flatten.erl b/lib/compiler/src/beam_flatten.erl index 25428c0c10..5603a677e8 100644 --- a/lib/compiler/src/beam_flatten.erl +++ b/lib/compiler/src/beam_flatten.erl @@ -51,6 +51,7 @@ norm_block([], Acc) -> Acc. norm({set,[D],As,{bif,N,F}}) -> {bif,N,F,As,D}; norm({set,[D],As,{alloc,R,{gc_bif,N,F}}}) -> {gc_bif,N,F,R,As,D}; +norm({set,[D],[],init}) -> {init,D}; norm({set,[D],[S],move}) -> {move,S,D}; norm({set,[D],[S],fmove}) -> {fmove,S,D}; norm({set,[D],[S],fconv}) -> {fconv,S,D}; -- cgit v1.2.3 From 27885492f26bc19479ea7f86b15434f4882d67fe Mon Sep 17 00:00:00 2001 From: Anthony Ramine Date: Tue, 19 Nov 2013 18:19:48 +0100 Subject: Add missing recv_set, recv_mark and '%' to BEAM live annotation --- lib/compiler/src/beam_utils.erl | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/lib/compiler/src/beam_utils.erl b/lib/compiler/src/beam_utils.erl index e9911fefd9..36f3200d11 100644 --- a/lib/compiler/src/beam_utils.erl +++ b/lib/compiler/src/beam_utils.erl @@ -759,6 +759,12 @@ live_opt([{allocate,_,Live}=I|Is], _, D, Acc) -> live_opt(Is, live_call(Live), D, [I|Acc]); live_opt([{allocate_heap,_,_,Live}=I|Is], _, D, Acc) -> live_opt(Is, live_call(Live), D, [I|Acc]); +live_opt([{'%',_}=I|Is], Regs, D, Acc) -> + live_opt(Is, Regs, D, [I|Acc]); +live_opt([{recv_set,_}=I|Is], Regs, D, Acc) -> + live_opt(Is, Regs, D, [I|Acc]); +live_opt([{recv_mark,_}=I|Is], Regs, D, Acc) -> + live_opt(Is, Regs, D, [I|Acc]); live_opt([], _, _, Acc) -> Acc. -- cgit v1.2.3 From 8a0b31772fe73503a989df3212546f2098308fa7 Mon Sep 17 00:00:00 2001 From: Anthony Ramine Date: Tue, 19 Nov 2013 18:22:44 +0100 Subject: Keep exit blocks in order when moving them in beam_jump This makes applying the pass a second time a no-op. --- lib/compiler/src/beam_jump.erl | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/lib/compiler/src/beam_jump.erl b/lib/compiler/src/beam_jump.erl index b29a3565e4..d57fb80ac2 100644 --- a/lib/compiler/src/beam_jump.erl +++ b/lib/compiler/src/beam_jump.erl @@ -202,19 +202,19 @@ is_label(_) -> false. move(Is) -> move_1(Is, [], []). -move_1([I|Is], End0, Acc0) -> +move_1([I|Is], Ends, Acc0) -> case is_exit_instruction(I) of false -> - move_1(Is, End0, [I|Acc0]); + move_1(Is, Ends, [I|Acc0]); true -> - case extract_seq(Acc0, [I|End0]) of + case extract_seq(Acc0, [I]) of no -> - move_1(Is, End0, [I|Acc0]); + move_1(Is, Ends, [I|Acc0]); {yes,End,Acc} -> - move_1(Is, End, Acc) + move_1(Is, [End|Ends], Acc) end end; -move_1([], End, Acc) -> reverse(Acc, End). +move_1([], Ends, Acc) -> reverse(Acc, lists:append(reverse(Ends))). extract_seq([{line,_}=Line|Is], Acc) -> extract_seq(Is, [Line|Acc]); -- cgit v1.2.3 From 20c38f0156b711032274cdea5a5049fc7ce8e81f Mon Sep 17 00:00:00 2001 From: Anthony Ramine Date: Tue, 19 Nov 2013 19:25:37 +0100 Subject: Test compilation of BEAM assembly with optimisations on --- lib/compiler/test/compilation_SUITE.erl | 10 ++++++++++ lib/compiler/test/compile_SUITE.erl | 2 +- 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/lib/compiler/test/compilation_SUITE.erl b/lib/compiler/test/compilation_SUITE.erl index d517029b1b..93b2fb4ea5 100644 --- a/lib/compiler/test/compilation_SUITE.erl +++ b/lib/compiler/test/compilation_SUITE.erl @@ -278,6 +278,16 @@ try_it(StartNode, Module, Conf) -> ?line ok = rpc:call(Node, ?MODULE, load_and_call, [Out, Module]), ?line test_server:timetrap_cancel(LastDog), + AsmDog = test_server:timetrap(test_server:minutes(10)), + io:format("Compiling (from assembly): ~s\n", [Src]), + {ok,_} = compile:file(Src, [to_asm,{outdir,Out},report|OtherOpts]), + Asm = filename:join(Out, lists:concat([Module, ".S"])), + CompRc3 = compile:file(Asm, [from_asm,{outdir,Out},report|OtherOpts]), + io:format("Result: ~p\n",[CompRc3]), + {ok,_} = CompRc3, + ok = rpc:call(Node, ?MODULE, load_and_call, [Out, Module]), + test_server:timetrap_cancel(AsmDog), + case StartNode of false -> ok; true -> ?line test_server:stop_node(Node) diff --git a/lib/compiler/test/compile_SUITE.erl b/lib/compiler/test/compile_SUITE.erl index 66ce6c00ab..1dc1ddb653 100644 --- a/lib/compiler/test/compile_SUITE.erl +++ b/lib/compiler/test/compile_SUITE.erl @@ -794,7 +794,7 @@ do_asm(Beam, Outdir) -> {ok,Fd} = file:open(AsmFile, [write,{encoding,utf8}]), beam_listing:module(Fd, Asm), ok = file:close(Fd), - case compile:file(AsmFile, [from_asm,no_postopt,binary,report]) of + case compile:file(AsmFile, [from_asm,binary,report]) of {ok,M,_} -> ok = file:delete(AsmFile); Other -> -- cgit v1.2.3