Skip to content

Commit f5caa63

Browse files
committed
beam_ssa_opt: Get rid of the opt_ranges subpass
The `opt_ranges` subpass is no longer needed after the improvements made to the signatures pass in the previous commit.
1 parent 5059a24 commit f5caa63

3 files changed

Lines changed: 3 additions & 174 deletions

File tree

lib/compiler/src/beam_call_types.erl

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -492,9 +492,7 @@ types(erlang, 'bnot', [_]) ->
492492
%% between the ranges calculated by the type pass and by
493493
%% beam_validator.
494494
%%
495-
%% Therefore, don't attempt to calculate a range now. Save the
496-
%% range calculation for the opt_ranges pass (arith_type/2), which
497-
%% is only run once.
495+
%% Therefore, don't attempt to calculate a range now.
498496
sub_unsafe(#t_integer{}, [#t_integer{}]);
499497

500498
%% Fixed-type arithmetic

lib/compiler/src/beam_ssa_opt.erl

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -321,8 +321,7 @@ late_epilogue_passes(Opts) ->
321321
?PASS(ssa_opt_get_tuple_element),
322322
?PASS(ssa_opt_tail_literals),
323323
?PASS(ssa_opt_trim_unreachable),
324-
?PASS(ssa_opt_unfold_literals),
325-
?PASS(ssa_opt_ranges)],
324+
?PASS(ssa_opt_unfold_literals)],
326325
passes_1(Ps, Opts).
327326

328327
passes_1(Ps, Opts0) ->
@@ -461,9 +460,6 @@ ssa_opt_merge_blocks({#opt_st{ssa=Blocks0}=St, FuncDb}) ->
461460
Blocks = beam_ssa:merge_blocks(RPO, Blocks0),
462461
{St#opt_st{ssa=Blocks}, FuncDb}.
463462

464-
ssa_opt_ranges({#opt_st{ssa=Blocks}=St, FuncDb}) ->
465-
{St#opt_st{ssa=beam_ssa_type:opt_ranges(Blocks)}, FuncDb}.
466-
467463
%%%
468464
%%% Merges updates that cannot fail, for example two consecutive updates of the
469465
%%% same record.

lib/compiler/src/beam_ssa_type.erl

Lines changed: 1 addition & 166 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@
3030

3131
-module(beam_ssa_type).
3232
-moduledoc false.
33-
-export([opt_start/2, opt_continue/4, opt_finish/3, opt_ranges/1]).
33+
-export([opt_start/2, opt_continue/4, opt_finish/3]).
3434

3535
-include("beam_ssa_opt.hrl").
3636
-include("beam_types.hrl").
@@ -678,12 +678,6 @@ benefits_from_type_anno(is_tagged_tuple, _Args) ->
678678
true;
679679
benefits_from_type_anno(call, [#b_var{} | _]) ->
680680
true;
681-
benefits_from_type_anno({float,convert}, _Args) ->
682-
%% Note: The {float,convert} instruction does not exist when
683-
%% the main type optimizer pass is run. It is created and
684-
%% annotated by ssa_opt_float1 in beam_ssa_opt, and can also
685-
%% be annotated by opt_ranges/1.
686-
true;
687681
benefits_from_type_anno(get_map_element, _Args) ->
688682
true;
689683
benefits_from_type_anno(has_map_field, _Args) ->
@@ -821,165 +815,6 @@ opt_finish_1([Arg | Args], [TypeMap | TypeMaps], Acc0) ->
821815
opt_finish_1([], [], Acc) ->
822816
Acc.
823817

824-
%%%
825-
%%% This sub pass is run once after the main type sub pass
826-
%%% to annotate more instructions with integer ranges.
827-
%%%
828-
%%% The main type sub pass annotates certain instructions with
829-
%%% their types to help the JIT generate better code.
830-
%%%
831-
%%% Example:
832-
%%%
833-
%%% foo(N0) ->
834-
%%% N1 = N0 band 3,
835-
%%% N = N1 + 1, % N1 is in 0..3
836-
%%% element(N,
837-
%%% {zero,one,two,three}).
838-
%%%
839-
%%% The main type pass is able to figure out the range for `N1` but
840-
%%% not for `N`. The reason is that the type pass iterates until it
841-
%%% reaches a fixpoint. To guarantee that it will converge, ranges for
842-
%%% results must only be calculated for operations that retain or
843-
%%% shrink the ranges of their arguments.
844-
%%%
845-
%%% Therefore, to ensure convergence, the main type pass can only
846-
%%% safely calculate ranges for results of operations such as `and`,
847-
%%% `bsr`, and `rem`, but not for operations such as `+`, '-', '*',
848-
%%% and `bsl`.
849-
%%%
850-
%%% This sub pass will start from the types found in the annotations
851-
%%% and propagate them forward through arithmetic instructions within
852-
%%% the same function.
853-
%%%
854-
%%% For the example, this sub pass adds a new annotation for `N`:
855-
%%%
856-
%%% foo(N0) ->
857-
%%% N1 = N0 band 3,
858-
%%% N = N1 + 1, % N1 is in 0..3
859-
%%% element(N, % N is in 1..4
860-
%%% {zero,one,two,three}).
861-
%%%
862-
%%% With a known range and known tuple size, the JIT is able to remove
863-
%%% all range checks for the `element/2` instruction.
864-
%%%
865-
866-
-spec opt_ranges(Blocks0) -> Blocks when
867-
Blocks0 :: beam_ssa:block_map(),
868-
Blocks :: beam_ssa:block_map().
869-
870-
opt_ranges(Blocks) ->
871-
RPO = beam_ssa:rpo(Blocks),
872-
Tss = #{0 => #{}, ?EXCEPTION_BLOCK => #{}},
873-
ranges(RPO, Tss, Blocks).
874-
875-
ranges([L|Ls], Tss0, Blocks0) ->
876-
#b_blk{is=Is0} = Blk0 = map_get(L, Blocks0),
877-
Ts0 = map_get(L, Tss0),
878-
{Is,Ts} = ranges_is(Is0, Ts0, []),
879-
Blk = Blk0#b_blk{is=Is},
880-
Blocks = Blocks0#{L := Blk},
881-
Tss = ranges_successors(beam_ssa:successors(Blk), Ts, Tss0),
882-
ranges(Ls, Tss, Blocks);
883-
ranges([], _Tss, Blocks) -> Blocks.
884-
885-
ranges_is([#b_set{op=Op,args=Args}=I0|Is], Ts0, Acc) ->
886-
case benefits_from_type_anno(Op, Args) of
887-
false ->
888-
ranges_is(Is, Ts0, [I0|Acc]);
889-
true ->
890-
I = update_anno_types(I0, Ts0),
891-
Ts = ranges_propagate_types(I, Ts0),
892-
ranges_is(Is, Ts, [I|Acc])
893-
end;
894-
ranges_is([], Ts, Acc) ->
895-
{reverse(Acc),Ts}.
896-
897-
ranges_successors([?EXCEPTION_BLOCK|Ls], Ts, Tss) ->
898-
ranges_successors(Ls, Ts, Tss);
899-
ranges_successors([L|Ls], Ts0, Tss0) ->
900-
case Tss0 of
901-
#{L := Ts1} ->
902-
Ts = join_types(Ts0, Ts1),
903-
Tss = Tss0#{L := Ts},
904-
ranges_successors(Ls, Ts0, Tss);
905-
#{} ->
906-
Tss = Tss0#{L => Ts0},
907-
ranges_successors(Ls, Ts0, Tss)
908-
end;
909-
ranges_successors([], _, Tss) -> Tss.
910-
911-
ranges_propagate_types(#b_set{anno=Anno,op={bif,_}=Op,args=Args,dst=Dst}, Ts) ->
912-
case Anno of
913-
#{arg_types := ArgTypes0} ->
914-
ArgTypes = ranges_get_arg_types(Args, 0, ArgTypes0),
915-
case beam_call_types:arith_type(Op, ArgTypes) of
916-
any -> Ts;
917-
T -> Ts#{Dst => T}
918-
end;
919-
#{} ->
920-
Ts
921-
end;
922-
ranges_propagate_types(_, Ts) -> Ts.
923-
924-
ranges_get_arg_types([#b_var{}|As], Index, ArgTypes) ->
925-
case ArgTypes of
926-
#{Index := Type} ->
927-
[Type|ranges_get_arg_types(As, Index + 1, ArgTypes)];
928-
#{} ->
929-
[any|ranges_get_arg_types(As, Index + 1, ArgTypes)]
930-
end;
931-
ranges_get_arg_types([#b_literal{val=Value}|As], Index, ArgTypes) ->
932-
Type = beam_types:make_type_from_value(Value),
933-
[Type|ranges_get_arg_types(As, Index + 1, ArgTypes)];
934-
ranges_get_arg_types([], _, _) -> [].
935-
936-
update_anno_types(#b_set{anno=Anno,args=Args}=I, Ts) ->
937-
ArgTypes1 = case Anno of
938-
#{arg_types := ArgTypes0} -> ArgTypes0;
939-
#{} -> #{}
940-
end,
941-
ArgTypes = update_anno_types_1(Args, Ts, 0, ArgTypes1),
942-
case Anno of
943-
#{arg_types := ArgTypes} ->
944-
I;
945-
#{} when map_size(ArgTypes) =/= 0 ->
946-
I#b_set{anno=Anno#{arg_types => ArgTypes}};
947-
#{} ->
948-
I
949-
end.
950-
951-
update_anno_types_1([#b_var{}=V|As], Ts, Index, ArgTypes) ->
952-
T0 = case ArgTypes of
953-
#{Index := T00} -> T00;
954-
#{} -> any
955-
end,
956-
T1 = case Ts of
957-
#{V := T11} -> T11;
958-
#{} -> any
959-
end,
960-
case beam_types:meet(T0, T1) of
961-
any ->
962-
update_anno_types_1(As, Ts, Index + 1, ArgTypes);
963-
none ->
964-
%% This instruction will never be reached. This happens when
965-
%% compiling code such as the following:
966-
%%
967-
%% f(X) when is_integer(X), 0 =< X, X < 64 ->
968-
%% (X = bnot X) + 1.
969-
%%
970-
%% The main type optimization sub pass will not find out
971-
%% that `(X = bnot X)` will never succeed and that the `+`
972-
%% operator is never executed, but this sub pass will.
973-
%% This happens very rarely; therefore, don't bother removing
974-
%% the unreachable instruction.
975-
update_anno_types_1(As, Ts, Index + 1, ArgTypes);
976-
T ->
977-
update_anno_types_1(As, Ts, Index + 1, ArgTypes#{Index => T})
978-
end;
979-
update_anno_types_1([_|As], Ts, Index, ArgTypes) ->
980-
update_anno_types_1(As, Ts, Index + 1, ArgTypes);
981-
update_anno_types_1([], _, _, ArgTypes) -> ArgTypes.
982-
983818
%%%
984819
%%% Optimization helpers
985820
%%%

0 commit comments

Comments
 (0)