diff options
Diffstat (limited to 'lib/compiler')
-rw-r--r-- | lib/compiler/src/beam_ssa.erl | 23 | ||||
-rw-r--r-- | lib/compiler/src/beam_ssa_codegen.erl | 21 | ||||
-rw-r--r-- | lib/compiler/src/beam_ssa_dead.erl | 10 | ||||
-rw-r--r-- | lib/compiler/src/beam_ssa_opt.erl | 44 | ||||
-rw-r--r-- | lib/compiler/src/beam_ssa_pp.erl | 6 | ||||
-rw-r--r-- | lib/compiler/src/beam_ssa_pre_codegen.erl | 129 | ||||
-rw-r--r-- | lib/compiler/src/beam_ssa_recv.erl | 31 | ||||
-rw-r--r-- | lib/compiler/src/beam_ssa_type.erl | 54 |
8 files changed, 150 insertions, 168 deletions
diff --git a/lib/compiler/src/beam_ssa.erl b/lib/compiler/src/beam_ssa.erl index fc13ba06de..9d10d4aec3 100644 --- a/lib/compiler/src/beam_ssa.erl +++ b/lib/compiler/src/beam_ssa.erl @@ -523,15 +523,15 @@ update_phi_labels([], _, _, Blocks) -> Blocks. used(#b_blk{is=Is,last=Last}) -> used_1([Last|Is], ordsets:new()); -used(#b_br{bool=#b_var{name=V}}) -> +used(#b_br{bool=#b_var{}=V}) -> [V]; -used(#b_ret{arg=#b_var{name=V}}) -> +used(#b_ret{arg=#b_var{}=V}) -> [V]; used(#b_set{op=phi,args=Args}) -> - ordsets:from_list([V || {#b_var{name=V},_} <- Args]); + ordsets:from_list([V || {#b_var{}=V,_} <- Args]); used(#b_set{args=Args}) -> ordsets:from_list(used_args(Args)); -used(#b_switch{arg=#b_var{name=V}}) -> +used(#b_switch{arg=#b_var{}=V}) -> [V]; used(_) -> []. @@ -560,17 +560,16 @@ def_used_1([#b_blk{is=Is,last=Last}|Bs], Preds, Def0, Used0) -> def_used_1([], _Preds, Def, Used) -> {ordsets:from_list(Def),gb_sets:to_list(Used)}. -def_used_is([#b_set{op=phi,dst=#b_var{name=Dst},args=Args}|Is], +def_used_is([#b_set{op=phi,dst=Dst,args=Args}|Is], Preds, Def0, Used0) -> Def = [Dst|Def0], %% We must be careful to only include variables that will %% be used when arriving from one of the predecessor blocks %% in Preds. - Used1 = [V || {#b_var{name=V},L} <- Args, - gb_sets:is_member(L, Preds)], + Used1 = [V || {#b_var{}=V,L} <- Args, gb_sets:is_member(L, Preds)], Used = gb_sets:union(gb_sets:from_list(Used1), Used0), def_used_is(Is, Preds, Def, Used); -def_used_is([#b_set{dst=#b_var{name=Dst}}=I|Is], Preds, Def0, Used0) -> +def_used_is([#b_set{dst=Dst}=I|Is], Preds, Def0, Used0) -> Def = [Dst|Def0], Used = gb_sets:union(gb_sets:from_list(used(I)), Used0), def_used_is(Is, Preds, Def, Used); @@ -583,7 +582,7 @@ def_1([#b_blk{is=Is}|Bs], Def0) -> def_1([], Def) -> ordsets:from_list(Def). -def_is([#b_set{dst=#b_var{name=Dst}}|Is], Def) -> +def_is([#b_set{dst=Dst}|Is], Def) -> def_is(Is, [Dst|Def]); def_is([], Def) -> Def. @@ -684,10 +683,10 @@ rpo_1([L|Ls], Blocks, Seen0, Acc0) -> rpo_1([], _, Seen, Acc) -> {Acc,Seen}. -rename_var(#b_var{name=Old}=V, Rename) -> +rename_var(#b_var{}=Old, Rename) -> case Rename of #{Old:=New} -> New; - #{} -> V + #{} -> Old end; rename_var(#b_remote{mod=Mod0,name=Name0}=Remote, Rename) -> Mod = rename_var(Mod0, Rename), @@ -758,7 +757,7 @@ update_phi_labels_is(Is, _, _) -> Is. rename_label(Old, Old, New) -> New; rename_label(Lbl, _Old, _New) -> Lbl. -used_args([#b_var{name=V}|As]) -> +used_args([#b_var{}=V|As]) -> [V|used_args(As)]; used_args([#b_remote{mod=Mod,name=Name}|As]) -> used_args([Mod,Name|As]); diff --git a/lib/compiler/src/beam_ssa_codegen.erl b/lib/compiler/src/beam_ssa_codegen.erl index 40c2d8c07a..5085c950b5 100644 --- a/lib/compiler/src/beam_ssa_codegen.erl +++ b/lib/compiler/src/beam_ssa_codegen.erl @@ -592,8 +592,7 @@ liveness_successors(Terminator) -> liveness_is([#cg_alloc{}=I0|Is], Regs, Live, Acc) -> I = I0#cg_alloc{live=num_live(Live, Regs)}, liveness_is(Is, Regs, Live, [I|Acc]); -liveness_is([#cg_set{dst=Dst0,args=Args}=I0|Is], Regs, Live0, Acc) -> - #b_var{name=Dst} = Dst0, +liveness_is([#cg_set{dst=Dst,args=Args}=I0|Is], Regs, Live0, Acc) -> Live1 = liveness_clobber(I0, Live0, Regs), I1 = liveness_yregs_anno(I0, Live1, Regs), Live2 = liveness_args(Args, Live1), @@ -610,7 +609,7 @@ liveness_terminator(#cg_switch{arg=Arg}, Live) -> liveness_terminator(#cg_ret{arg=Arg}, Live) -> liveness_terminator_1(Arg, Live). -liveness_terminator_1(#b_var{name=V}, Live) -> +liveness_terminator_1(#b_var{}=V, Live) -> ordsets:add_element(V, Live); liveness_terminator_1(#b_literal{}, Live) -> Live; @@ -618,7 +617,7 @@ liveness_terminator_1(Reg, Live) -> _ = verify_beam_register(Reg), ordsets:add_element(Reg, Live). -liveness_args([#b_var{name=V}|As], Live) -> +liveness_args([#b_var{}=V|As], Live) -> liveness_args(As, ordsets:add_element(V, Live)); liveness_args([#b_remote{mod=Mod,name=Name}|As], Live) -> liveness_args([Mod,Name|As], Live); @@ -641,7 +640,7 @@ liveness_anno(#cg_set{op=Op}=I, Live, Regs) -> I end. -liveness_yregs_anno(#cg_set{op=Op,dst=#b_var{name=Dst}}=I, Live0, Regs) -> +liveness_yregs_anno(#cg_set{op=Op,dst=Dst}=I, Live0, Regs) -> case need_live_anno(Op) of true -> Live = ordsets:del_element(Dst, Live0), @@ -728,13 +727,13 @@ def_get(L, DefMap) -> def_is([#cg_alloc{anno=Anno0}=I0|Is], Regs, Def, Acc) -> I = I0#cg_alloc{anno=Anno0#{def_yregs=>Def}}, def_is(Is, Regs, Def, [I|Acc]); -def_is([#cg_set{op=kill_try_tag,args=[#b_var{name=Tag}]}=I|Is], Regs, Def0, Acc) -> +def_is([#cg_set{op=kill_try_tag,args=[#b_var{}=Tag]}=I|Is], Regs, Def0, Acc) -> Def = ordsets:del_element(Tag, Def0), def_is(Is, Regs, Def, [I|Acc]); -def_is([#cg_set{op=catch_end,args=[#b_var{name=Tag}|_]}=I|Is], Regs, Def0, Acc) -> +def_is([#cg_set{op=catch_end,args=[#b_var{}=Tag|_]}=I|Is], Regs, Def0, Acc) -> Def = ordsets:del_element(Tag, Def0), def_is(Is, Regs, Def, [I|Acc]); -def_is([#cg_set{anno=Anno0,op=call,dst=#b_var{name=Dst}}=I0|Is], +def_is([#cg_set{anno=Anno0,op=call,dst=Dst}=I0|Is], Regs, Def0, Acc) -> #{live_yregs:=LiveYregVars} = Anno0, LiveRegs = gb_sets:from_list([maps:get(V, Regs) || V <- LiveYregVars]), @@ -749,7 +748,7 @@ def_is([#cg_set{anno=Anno0,op=call,dst=#b_var{name=Dst}}=I0|Is], Def1 = ordsets:subtract(Def0, Kill), Def = def_add_yreg(Dst, Def1, Regs), def_is(Is, Regs, Def, [I|Acc]); -def_is([#cg_set{anno=Anno0,op={bif,Bif},dst=#b_var{name=Dst},args=Args}=I0|Is], +def_is([#cg_set{anno=Anno0,op={bif,Bif},dst=Dst,args=Args}=I0|Is], Regs, Def0, Acc) -> Arity = length(Args), I = case is_gc_bif(Bif, Args) orelse not erl_bifs:is_safe(erlang, Bif, Arity) of @@ -760,7 +759,7 @@ def_is([#cg_set{anno=Anno0,op={bif,Bif},dst=#b_var{name=Dst},args=Args}=I0|Is], end, Def = def_add_yreg(Dst, Def0, Regs), def_is(Is, Regs, Def, [I|Acc]); -def_is([#cg_set{anno=Anno0,dst=#b_var{name=Dst}}=I0|Is], Regs, Def0, Acc) -> +def_is([#cg_set{anno=Anno0,dst=Dst}=I0|Is], Regs, Def0, Acc) -> I = case need_y_init(I0) of true -> I0#cg_set{anno=Anno0#{def_yregs=>Def0}}; @@ -1716,7 +1715,7 @@ get_register(V, Regs) -> beam_args(As, St) -> [beam_arg(A, St) || A <- As]. -beam_arg(#b_var{name=Name}, #cg{regs=Regs}) -> +beam_arg(#b_var{}=Name, #cg{regs=Regs}) -> maps:get(Name, Regs); beam_arg(#b_literal{val=Val}, _) -> if diff --git a/lib/compiler/src/beam_ssa_dead.erl b/lib/compiler/src/beam_ssa_dead.erl index 7cdb4315fe..c20652580d 100644 --- a/lib/compiler/src/beam_ssa_dead.erl +++ b/lib/compiler/src/beam_ssa_dead.erl @@ -180,7 +180,7 @@ shortcut_2(L, Bs0, UnsetVars0, St) -> %% We have a potentially suitable br. %% Now update the set of variables that will never %% be set if this block will be skipped. - UnsetVars1 = [V || #b_set{dst=#b_var{name=V}} <- Is], + UnsetVars1 = [V || #b_set{dst=V} <- Is], UnsetVars = ordsets:union(UnsetVars0, ordsets:from_list(UnsetVars1)), @@ -315,7 +315,7 @@ get_block(L, St) -> is_br_safe(UnsetVars, Br, #st{us=Us}=St) -> %% Check that none of the unset variables will be used. case Br of - #b_br{bool=#b_var{name=V},succ=Succ,fail=Fail} -> + #b_br{bool=#b_var{}=V,succ=Succ,fail=Fail} -> #{Succ:=Used0,Fail:=Used1} = Us, %% A two-way branch never branches to a phi node, so there @@ -922,7 +922,7 @@ used_vars([{L,#b_blk{is=Is}=Blk}|Bs], UsedVars0, Skip0) -> %% can be skipped (does not bind any variable used %% in successor). - Defined0 = [Def || #b_set{dst=#b_var{name=Def}} <- Is], + Defined0 = [Def || #b_set{dst=Def} <- Is], Defined = ordsets:from_list(Defined0), MaySkip = ordsets:is_disjoint(Defined, Used0), case MaySkip of @@ -957,7 +957,7 @@ used_vars_phis(Is, L, Live0, UsedVars0) -> UsedVars; [_|_] -> PhiArgs = append([Args || #b_set{args=Args} <- Phis]), - case [{P,V} || {#b_var{name=V},P} <- PhiArgs] of + case [{P,V} || {#b_var{}=V,P} <- PhiArgs] of [_|_]=PhiVars -> PhiLive0 = rel2fam(PhiVars), PhiLive = [{{L,P},ordsets:union(ordsets:from_list(Vs), Live0)} || @@ -975,7 +975,7 @@ used_vars_blk(#b_blk{is=Is,last=Last}, Used0) -> used_vars_is([#b_set{op=phi}|Is], Used) -> used_vars_is(Is, Used); -used_vars_is([#b_set{dst=#b_var{name=Dst}}=I|Is], Used0) -> +used_vars_is([#b_set{dst=Dst}=I|Is], Used0) -> Used1 = ordsets:union(Used0, beam_ssa:used(I)), Used = ordsets:del_element(Dst, Used1), used_vars_is(Is, Used); diff --git a/lib/compiler/src/beam_ssa_opt.erl b/lib/compiler/src/beam_ssa_opt.erl index 83ee918b25..89cfbd7a84 100644 --- a/lib/compiler/src/beam_ssa_opt.erl +++ b/lib/compiler/src/beam_ssa_opt.erl @@ -319,8 +319,7 @@ record_opt([{L,#b_blk{is=Is0,last=Last}=Blk0}|Bs], Blocks) -> [{L,Blk}|record_opt(Bs, Blocks)]; record_opt([], _Blocks) -> []. -record_opt_is([#b_set{op={bif,is_tuple},dst=#b_var{name=Bool}, - args=[Tuple]}=Set], +record_opt_is([#b_set{op={bif,is_tuple},dst=Bool,args=[Tuple]}=Set], Last, Blocks) -> case is_tagged_tuple(Tuple, Bool, Last, Blocks) of {yes,Size,Tag} -> @@ -333,8 +332,8 @@ record_opt_is([I|Is], Last, Blocks) -> [I|record_opt_is(Is, Last, Blocks)]; record_opt_is([], _Last, _Blocks) -> []. -is_tagged_tuple(#b_var{name=Tuple}, Bool, - #b_br{bool=#b_var{name=Bool},succ=Succ,fail=Fail}, +is_tagged_tuple(#b_var{}=Tuple, Bool, + #b_br{bool=Bool,succ=Succ,fail=Fail}, Blocks) -> SuccBlk = maps:get(Succ, Blocks), is_tagged_tuple_1(SuccBlk, Tuple, Fail, Blocks); @@ -342,15 +341,14 @@ is_tagged_tuple(_, _, _, _) -> no. is_tagged_tuple_1(#b_blk{is=Is,last=Last}, Tuple, Fail, Blocks) -> case Is of - [#b_set{op={bif,tuple_size},dst=#b_var{name=ArityVar}, - args=[#b_var{name=Tuple}]}, + [#b_set{op={bif,tuple_size},dst=ArityVar, + args=[#b_var{}=Tuple]}, #b_set{op={bif,'=:='}, - dst=#b_var{name=Bool}, - args=[#b_var{name=ArityVar}, - #b_literal{val=ArityVal}=Arity]}] + dst=Bool, + args=[ArityVar, #b_literal{val=ArityVal}=Arity]}] when is_integer(ArityVal) -> case Last of - #b_br{bool=#b_var{name=Bool},succ=Succ,fail=Fail} -> + #b_br{bool=Bool,succ=Succ,fail=Fail} -> SuccBlk = maps:get(Succ, Blocks), case is_tagged_tuple_2(SuccBlk, Tuple, Fail) of no -> @@ -366,22 +364,22 @@ is_tagged_tuple_1(#b_blk{is=Is,last=Last}, Tuple, Fail, Blocks) -> end. is_tagged_tuple_2(#b_blk{is=Is, - last=#b_br{bool=#b_var{name=Bool},fail=Fail}}, + last=#b_br{bool=#b_var{}=Bool,fail=Fail}}, Tuple, Fail) -> is_tagged_tuple_3(Is, Bool, Tuple); is_tagged_tuple_2(#b_blk{}, _, _) -> no. is_tagged_tuple_3([#b_set{op=get_tuple_element, - dst=#b_var{name=TagVar}, - args=[#b_var{name=Tuple},#b_literal{val=0}]}|Is], + dst=TagVar, + args=[#b_var{}=Tuple,#b_literal{val=0}]}|Is], Bool, Tuple) -> is_tagged_tuple_4(Is, Bool, TagVar); is_tagged_tuple_3([_|Is], Bool, Tuple) -> is_tagged_tuple_3(Is, Bool, Tuple); is_tagged_tuple_3([], _, _) -> no. -is_tagged_tuple_4([#b_set{op={bif,'=:='},dst=#b_var{name=Bool}, - args=[#b_var{name=TagVar}, +is_tagged_tuple_4([#b_set{op={bif,'=:='},dst=Bool, + args=[#b_var{}=TagVar, #b_literal{val=TagVal}=Tag]}], Bool, TagVar) when is_atom(TagVal) -> {yes,Tag}; @@ -817,7 +815,7 @@ live_opt_phis(Is, L, Live0, LiveMap0) -> LiveMap; [_|_] -> PhiArgs = append([Args || #b_set{args=Args} <- Phis]), - case [{P,V} || {#b_var{name=V},P} <- PhiArgs] of + case [{P,V} || {#b_var{}=V,P} <- PhiArgs] of [_|_]=PhiVars -> PhiLive0 = rel2fam(PhiVars), PhiLive = [{{L,P},gb_sets:union(gb_sets:from_list(Vs), Live0)} || @@ -834,16 +832,16 @@ live_opt_blk(#b_blk{is=Is0,last=Last}=Blk, Live0) -> {Is,Live} = live_opt_is(reverse(Is0), Live1, []), {Blk#b_blk{is=Is},Live}. -live_opt_is([#b_set{op=phi,dst=#b_var{name=Dst}}=I|Is], Live, Acc) -> +live_opt_is([#b_set{op=phi,dst=Dst}=I|Is], Live, Acc) -> case gb_sets:is_member(Dst, Live) of true -> live_opt_is(Is, Live, [I|Acc]); false -> live_opt_is(Is, Live, Acc) end; -live_opt_is([#b_set{op=succeeded,dst=#b_var{name=SuccDst}=SuccDstVar, - args=[#b_var{name=Dst}]}=SuccI, - #b_set{dst=#b_var{name=Dst}}=I|Is], Live0, Acc) -> +live_opt_is([#b_set{op=succeeded,dst=SuccDst=SuccDstVar, + args=[Dst]}=SuccI, + #b_set{dst=Dst}=I|Is], Live0, Acc) -> case gb_sets:is_member(Dst, Live0) of true -> case gb_sets:is_member(SuccDst, Live0) of @@ -870,7 +868,7 @@ live_opt_is([#b_set{op=succeeded,dst=#b_var{name=SuccDst}=SuccDstVar, end end end; -live_opt_is([#b_set{dst=#b_var{name=Dst}}=I|Is], Live0, Acc) -> +live_opt_is([#b_set{dst=Dst}=I|Is], Live0, Acc) -> case gb_sets:is_member(Dst, Live0) of true -> Live1 = gb_sets:union(Live0, gb_sets:from_ordset(beam_ssa:used(I))), @@ -1427,7 +1425,7 @@ def_blocks([{L,#b_blk{is=Is}}|Bs]) -> def_blocks_is(Is, L, def_blocks(Bs)); def_blocks([]) -> []. -def_blocks_is([#b_set{op=get_tuple_element,dst=#b_var{name=Dst}}|Is], L, Acc) -> +def_blocks_is([#b_set{op=get_tuple_element,dst=Dst}|Is], L, Acc) -> def_blocks_is(Is, L, [{Dst,L}|Acc]); def_blocks_is([_|Is], L, Acc) -> def_blocks_is(Is, L, Acc); @@ -1570,7 +1568,7 @@ remove_def(V, #b_blk{is=Is0}=Blk) -> {Def,Is} = remove_def_is(Is0, V, []), {Def,Blk#b_blk{is=Is}}. -remove_def_is([#b_set{dst=#b_var{name=Dst}}=Def|Is], Dst, Acc) -> +remove_def_is([#b_set{dst=Dst}=Def|Is], Dst, Acc) -> {Def,reverse(Acc, Is)}; remove_def_is([I|Is], Dst, Acc) -> remove_def_is(Is, Dst, [I|Acc]). diff --git a/lib/compiler/src/beam_ssa_pp.erl b/lib/compiler/src/beam_ssa_pp.erl index 9daa2c2523..34ac08b32e 100644 --- a/lib/compiler/src/beam_ssa_pp.erl +++ b/lib/compiler/src/beam_ssa_pp.erl @@ -158,7 +158,7 @@ format_op({Prefix,Name}) -> format_op(Name) -> io_lib:format("~p", [Name]). -format_register(#b_var{name=V}, #{registers:=Regs}) -> +format_register(#b_var{}=V, #{registers:=Regs}) -> {Tag,N} = maps:get(V, Regs), io_lib:format("~p~p", [Tag,N]); format_register(_, #{}) -> "". @@ -224,9 +224,9 @@ format_anno_1(Anno) -> [io_lib:format(" %% Anno: ~p\n", [Anno])] end. -format_live_interval(#b_var{name=V}=Dst, #{live_intervals:=Intervals}) -> +format_live_interval(#b_var{}=Dst, #{live_intervals:=Intervals}) -> case Intervals of - #{V:=Rs0} -> + #{Dst:=Rs0} -> Rs1 = [io_lib:format("~p..~p", [Start,End]) || {Start,End} <- Rs0], Rs = lists:join(" ", Rs1), diff --git a/lib/compiler/src/beam_ssa_pre_codegen.erl b/lib/compiler/src/beam_ssa_pre_codegen.erl index 7f67e315f5..bc5609cd76 100644 --- a/lib/compiler/src/beam_ssa_pre_codegen.erl +++ b/lib/compiler/src/beam_ssa_pre_codegen.erl @@ -578,19 +578,17 @@ sanitize([], Count, Blocks0, Values) -> sanitize_is([#b_set{op=get_map_element, args=[#b_literal{}=Map,Key]}=I0|Is], Count0, Values, _Changed, Acc) -> - {MapVarName,Count} = new_var_name('@ssa_map', Count0), - MapVar = #b_var{name=MapVarName}, + {MapVar,Count} = new_var('@ssa_map', Count0), I = I0#b_set{args=[MapVar,Key]}, Copy = #b_set{op=copy,dst=MapVar,args=[Map]}, sanitize_is(Is, Count, Values, true, [I,Copy|Acc]); -sanitize_is([#b_set{op=Op,dst=#b_var{name=Dst},args=Args0}=I0|Is0], +sanitize_is([#b_set{op=Op,dst=Dst,args=Args0}=I0|Is0], Count, Values, Changed, Acc) -> - Args = map(fun(#b_var{name=V}=Var) -> + Args = map(fun(Var) -> case Values of - #{V:=New} -> New; + #{Var:=New} -> New; #{} -> Var - end; - (Lit) -> Lit + end end, Args0), case sanitize_instr(Op, Args, I0) of {value,Value0} -> @@ -703,8 +701,7 @@ prune_phi(#b_set{args=Args0}=Phi, Reachable) -> fix_tuples(#st{ssa=Blocks0,cnt=Count0}=St) -> F = fun (#b_set{op=put_tuple,args=Args}=Put, C0) -> Arity = #b_literal{val=length(Args)}, - {VarName,C} = new_var_name('@ssa_ignore', C0), - Ignore = #b_var{name=VarName}, + {Ignore,C} = new_var('@ssa_ignore', C0), {[Put#b_set{op=put_tuple_arity,args=[Arity]}, #b_set{dst=Ignore,op=put_tuple_elements,args=Args}],C}; (I, C) -> {[I],C} @@ -867,12 +864,12 @@ need_frame(#b_blk{is=Is,last=#b_ret{arg=Ret}}) -> need_frame(#b_blk{is=Is}) -> need_frame_1(Is, body). -need_frame_1([#b_set{op=make_fun,dst=#b_var{name=Fun}}|Is], {return,_}=Context) -> +need_frame_1([#b_set{op=make_fun,dst=Fun}|Is], {return,_}=Context) -> %% Since make_fun clobbers X registers, a stack frame is needed if %% any of the following instructions use any other variable than %% the one holding the reference to the created fun. need_frame_1(Is, Context) orelse - case beam_ssa:used(#b_blk{is=Is,last=#b_ret{arg=#b_var{name=Fun}}}) of + case beam_ssa:used(#b_blk{is=Is,last=#b_ret{arg=Fun}}) of [Fun] -> false; [_|_] -> true end; @@ -987,12 +984,10 @@ recv_common(Defs, Exit, Blocks) -> %% in the exit block following the receive. recv_fix_common([Msg0|T], Exit, Rm, Blocks0, Count0) -> - {Msg1,Count1} = new_var_name('@recv', Count0), - Msg = #b_var{name=Msg1}, + {Msg,Count1} = new_var('@recv', Count0), Blocks1 = beam_ssa:rename_vars(#{Msg0=>Msg}, [Exit], Blocks0), N = length(Rm), - {MsgVars0,Count} = new_var_names(duplicate(N, '@recv'), Count1), - MsgVars = [#b_var{name=V} || V <- MsgVars0], + {MsgVars,Count} = new_vars(duplicate(N, '@recv'), Count1), PhiArgs = fix_exit_phi_args(MsgVars, Rm, Exit, Blocks1), Phi = #b_set{op=phi,dst=Msg,args=PhiArgs}, ExitBlk0 = maps:get(Exit, Blocks1), @@ -1007,7 +1002,7 @@ recv_fix_common_1([V|Vs], [Rm|Rms], Msg, Blocks0) -> Ren = #{Msg=>V}, Blocks1 = beam_ssa:rename_vars(Ren, [Rm], Blocks0), #b_blk{is=Is0} = Blk0 = maps:get(Rm, Blocks1), - Copy = #b_set{op=copy,dst=V,args=[#b_var{name=Msg}]}, + Copy = #b_set{op=copy,dst=V,args=[Msg]}, Is = insert_after_phis(Is0, [Copy]), Blk = Blk0#b_blk{is=Is}, Blocks = Blocks1#{Rm:=Blk}, @@ -1038,13 +1033,11 @@ fix_receive([L|Ls], Defs, Blocks0, Count0) -> {RmDefs,Used0} = beam_ssa:def_used([L], Blocks0), Def = ordsets:subtract(Defs, RmDefs), Used = ordsets:intersection(Def, Used0), - {NewVs,Count} = new_var_names(Used, Count0), - NewVars = [#b_var{name=V} || V <- NewVs], + {NewVars,Count} = new_vars([Base || #b_var{name=Base} <- Used], Count0), Ren = zip(Used, NewVars), Blocks1 = beam_ssa:rename_vars(Ren, [L], Blocks0), #b_blk{is=Is0} = Blk1 = maps:get(L, Blocks1), - CopyIs = [#b_set{op=copy,dst=New,args=[#b_var{name=Old}]} || - {Old,New} <- Ren], + CopyIs = [#b_set{op=copy,dst=New,args=[Old]} || {Old,New} <- Ren], Is = insert_after_phis(Is0, CopyIs), Blk = Blk1#b_blk{is=Is}, Blocks = maps:put(L, Blk, Blocks1), @@ -1134,7 +1127,7 @@ find_rm_act([]) -> find_yregs(#st{frames=[]}=St) -> St; find_yregs(#st{frames=[_|_]=Frames,args=Args,ssa=Blocks0}=St) -> - FrameDefs = find_defs(Frames, Blocks0, [V || #b_var{name=V} <- Args]), + FrameDefs = find_defs(Frames, Blocks0, [V || #b_var{}=V <- Args]), Blocks = find_yregs_1(FrameDefs, Blocks0), St#st{ssa=Blocks}. @@ -1189,7 +1182,7 @@ find_defs_1([L|Ls], Blocks, Frames, Seen0, Defs0, Acc0) -> find_defs_1([], _, _, Seen, _, Acc) -> {Acc,Seen}. -find_defs_is([#b_set{dst=#b_var{name=Dst}}|Is], Acc) -> +find_defs_is([#b_set{dst=Dst}|Is], Acc) -> find_defs_is(Is, [Dst|Acc]); find_defs_is([], Acc) -> Acc. @@ -1207,7 +1200,7 @@ find_update_succ([S|Ss], #dk{d=Defs0,k=Killed0}=DK0, D0) -> end; find_update_succ([], _, D) -> D. -find_yregs_is([#b_set{dst=#b_var{name=Dst}}=I|Is], #dk{d=Defs0,k=Killed0}=Ys, Yregs0) -> +find_yregs_is([#b_set{dst=Dst}=I|Is], #dk{d=Defs0,k=Killed0}=Ys, Yregs0) -> Used = beam_ssa:used(I), Yregs1 = ordsets:intersection(Used, Killed0), Yregs = ordsets:union(Yregs0, Yregs1), @@ -1301,7 +1294,7 @@ copy_retval_1([F|Fs], Blocks0, Count0) -> copy_retval_1([], Blocks, Count) -> {Blocks,Count}. -collect_yregs([#b_set{op=copy,dst=#b_var{name=Y},args=[#b_var{name=X}]}|Is], +collect_yregs([#b_set{op=copy,dst=Y,args=[#b_var{}=X]}|Is], Yregs0) -> true = gb_sets:is_member(X, Yregs0), %Assertion. Yregs = gb_sets:insert(Y, gb_sets:delete(X, Yregs0)), @@ -1342,13 +1335,12 @@ copy_retval_is([#b_set{}]=Is, false, _Yregs, Copy, Count, Acc) -> {reverse(Acc, acc_copy(Is, Copy)),Count}; copy_retval_is([#b_set{},#b_set{op=succeeded}]=Is, false, _Yregs, Copy, Count, Acc) -> {reverse(Acc, acc_copy(Is, Copy)),Count}; -copy_retval_is([#b_set{op=Op,dst=#b_var{name=RetVal}=Dst}=I0|Is], RC, Yregs, +copy_retval_is([#b_set{op=Op,dst=#b_var{name=RetName}=Dst}=I0|Is], RC, Yregs, Copy0, Count0, Acc0) when Op =:= call; Op =:= make_fun -> {I1,Count1,Acc} = place_retval_copy(I0, Yregs, Copy0, Count0, Acc0), - case gb_sets:is_member(RetVal, Yregs) of + case gb_sets:is_member(Dst, Yregs) of true -> - {NewVarName,Count} = new_var_name(RetVal, Count1), - NewVar = #b_var{name=NewVarName}, + {NewVar,Count} = new_var(RetName, Count1), Copy = #b_set{op=copy,dst=Dst,args=[NewVar]}, I = I1#b_set{dst=NewVar}, copy_retval_is(Is, RC, Yregs, Copy, Count, [I|Acc]); @@ -1398,16 +1390,15 @@ copy_retval_is([], RC, _, Copy, Count, Acc) -> place_retval_copy(I, _Yregs, none, Count, Acc) -> {I,Count,Acc}; place_retval_copy(#b_set{args=[F|Args0]}=I, Yregs, Copy, Count0, Acc0) -> - #b_set{dst=#b_var{name=Avoid}} = Copy, + #b_set{dst=Avoid} = Copy, {Args,Acc1,Count} = copy_func_args(Args0, Yregs, Avoid, Acc0, [], Count0), Acc = [Copy|Acc1], {I#b_set{args=[F|Args]},Count,Acc}. -copy_func_args([#b_var{name=V}=A|As], Yregs, Avoid, CopyAcc, Acc, Count0) -> - case gb_sets:is_member(V, Yregs) of - true when V =/= Avoid -> - {NewVarName,Count} = new_var_name(V, Count0), - NewVar = #b_var{name=NewVarName}, +copy_func_args([#b_var{name=AName}=A|As], Yregs, Avoid, CopyAcc, Acc, Count0) -> + case gb_sets:is_member(A, Yregs) of + true when A =/= Avoid -> + {NewVar,Count} = new_var(AName, Count0), Copy = #b_set{op=copy,dst=NewVar,args=[A]}, copy_func_args(As, Yregs, Avoid, [Copy|CopyAcc], [NewVar|Acc], Count); _ -> @@ -1461,9 +1452,9 @@ opt_get_list_1([L|Ls], Res, Blocks0) -> end; opt_get_list_1([], _, Blocks) -> Blocks. -opt_get_list_is([#b_set{op=get_hd,dst=#b_var{name=Hd}, +opt_get_list_is([#b_set{op=get_hd,dst=Hd, args=[Cons]}=GetHd, - #b_set{op=get_tl,dst=#b_var{name=Tl}, + #b_set{op=get_tl,dst=Tl, args=[Cons]}=GetTl|Is], Res, Acc, Changed) -> %% Note that when this pass is run, only Y registers have @@ -1527,7 +1518,7 @@ number_is_2([], N, Acc) -> %%% live_intervals(#st{args=Args,ssa=Blocks}=St) -> - Vars0 = [{V,{0,1}} || #b_var{name=V} <- Args], + Vars0 = [{V,{0,1}} || #b_var{}=V <- Args], F = fun(L, _, A) -> live_interval_blk(L, Blocks, A) end, LiveMap0 = #{}, Acc0 = {[],[],LiveMap0}, @@ -1583,18 +1574,18 @@ make_block_ranges([{V,[{use,_}|_]=Uses}|Vs], First, Acc) -> make_block_ranges(Vs, First, [{V,{First,Last}}|Acc]); make_block_ranges([], _, Acc) -> Acc. -live_interval_blk_1([#b_set{op=phi,dst=#b_var{name=Dst}}|Is], +live_interval_blk_1([#b_set{op=phi,dst=Dst}|Is], FirstNumber, Aliases, Acc0) -> Acc = [{Dst,{def,FirstNumber}}|Acc0], live_interval_blk_1(Is, FirstNumber, Aliases, Acc); live_interval_blk_1([#b_set{op=bs_start_match}=I|Is], FirstNumber, Aliases0, Acc0) -> N = beam_ssa:get_anno(n, I), - #b_set{dst=#b_var{name=Dst}} = I, + #b_set{dst=Dst} = I, Acc1 = [{Dst,{def,N}}|Acc0], Aliases = case beam_ssa:get_anno(reuse_for_context, I) of true -> - #b_set{args=[#b_var{name=Src}]} = I, + #b_set{args=[Src]} = I, [{Dst,Src}|Aliases0]; false -> Aliases0 @@ -1604,7 +1595,7 @@ live_interval_blk_1([#b_set{op=bs_start_match}=I|Is], FirstNumber, live_interval_blk_1([I|Is], FirstNumber, Aliases, Acc0) -> N = beam_ssa:get_anno(n, I), Acc1 = case I of - #b_set{dst=#b_var{name=Dst}} -> + #b_set{dst=Dst} -> [{Dst,{def,N}}|Acc0]; _ -> Acc0 @@ -1640,9 +1631,9 @@ get_live(L, LiveMap) -> #{} -> [] end. -update_live_phis([#b_set{op=phi,dst=#b_var{name=Killed},args=Args}|Is], +update_live_phis([#b_set{op=phi,dst=Killed,args=Args}|Is], Pred, Live0) -> - Used = [V || {#b_var{name=V},L} <- Args, L =:= Pred], + Used = [V || {#b_var{}=V,L} <- Args, L =:= Pred], Live1 = ordsets:union(ordsets:from_list(Used), Live0), Live = ordsets:del_element(Killed, Live1), update_live_phis(Is, Pred, Live); @@ -1710,10 +1701,10 @@ get_active(L, ActMap) -> #{} -> #{} end. -reserve_try_tags_is([#b_set{op=new_try_tag,dst=#b_var{name=V}}|Is], Active) -> +reserve_try_tags_is([#b_set{op=new_try_tag,dst=V}|Is], Active) -> N = map_size(Active), reserve_try_tags_is(Is, Active#{V=>N}); -reserve_try_tags_is([#b_set{op=kill_try_tag,args=[#b_var{name=Tag}]}|Is], Active) -> +reserve_try_tags_is([#b_set{op=kill_try_tag,args=[Tag]}|Is], Active) -> reserve_try_tags_is(Is, maps:remove(Tag, Active)); reserve_try_tags_is([_|Is], Active) -> reserve_try_tags_is(Is, Active); @@ -1733,17 +1724,15 @@ update_act_map([], _, ActMap) -> ActMap. rename_vars([], _, Blocks, Count) -> {[],Blocks,Count}; rename_vars(Vs, L, Blocks0, Count0) -> - {NewVs,Count} = new_var_names(Vs, Count0), - NewVars = [#b_var{name=V} || V <- NewVs], + {NewVars,Count} = new_vars([Base || #b_var{name=Base} <- Vs], Count0), Ren = zip(Vs, NewVars), Blocks1 = beam_ssa:rename_vars(Ren, [L], Blocks0), #b_blk{is=Is0} = Blk0 = maps:get(L, Blocks1), - CopyIs = [#b_set{op=copy,dst=New,args=[#b_var{name=Old}]} || - {Old,New} <- Ren], + CopyIs = [#b_set{op=copy,dst=New,args=[Old]} || {Old,New} <- Ren], Is = insert_after_phis(Is0, CopyIs), Blk = Blk0#b_blk{is=Is}, Blocks = maps:put(L, Blk, Blocks1), - {NewVs,Blocks,Count}. + {NewVars,Blocks,Count}. insert_after_phis([#b_set{op=phi}=I|Is], InsertIs) -> [I|insert_after_phis(Is, InsertIs)]; @@ -1850,7 +1839,7 @@ reserve_regs(#st{args=Args,ssa=Blocks,intervals=Intervals,res=Res0}=St) -> Res = maps:from_list(Res3), St#st{res=reserve_xregs(Blocks, Res)}. -reserve_arg_regs([#b_var{name=Arg}|Is], N, Acc) -> +reserve_arg_regs([#b_var{}=Arg|Is], N, Acc) -> reserve_arg_regs(Is, N+1, [{Arg,{x,N}}|Acc]); reserve_arg_regs([], _, Acc) -> Acc. @@ -1875,7 +1864,7 @@ reserve_zreg([#b_set{op={bif,tuple_size},dst=Dst}, reserve_zreg([#b_set{op={bif,tuple_size},dst=Dst}], #b_switch{}, ShortLived, A) -> reserve_zreg_1(Dst, ShortLived, A); -reserve_zreg([#b_set{op=Op,dst=#b_var{name=Dst}}|Is], Last, ShortLived, A0) -> +reserve_zreg([#b_set{op=Op,dst=Dst}|Is], Last, ShortLived, A0) -> IsZReg = case Op of context_to_binary -> true; bs_match_string -> true; @@ -1901,7 +1890,7 @@ reserve_zreg([], #b_br{bool=Bool}, ShortLived, A) -> reserve_zreg_1(Bool, ShortLived, A); reserve_zreg([], _, _, A) -> A. -reserve_zreg_1(#b_var{name=V}, ShortLived, A) -> +reserve_zreg_1(#b_var{}=V, ShortLived, A) -> case cerl_sets:is_element(V, ShortLived) of true -> [{V,z}|A]; false -> A @@ -1914,7 +1903,7 @@ reserve_fregs(Blocks, Res) -> end, beam_ssa:fold_rpo(F, [0], Res, Blocks). -reserve_freg([#b_set{op={float,Op},dst=#b_var{name=V}}|Is], Res) -> +reserve_freg([#b_set{op={float,Op},dst=V}|Is], Res) -> case Op of get -> reserve_freg(Is, Res); @@ -1945,7 +1934,7 @@ reserve_xregs(Blocks, Res) -> end, beam_ssa:fold_po(F, Res, Blocks). -reserve_xregs_is([#b_set{op=Op,dst=#b_var{name=Dst},args=Args}=I|Is], Res0, Xs0, Used0) -> +reserve_xregs_is([#b_set{op=Op,dst=Dst,args=Args}=I|Is], Res0, Xs0, Used0) -> Xs1 = case is_gc_safe(I) of true -> Xs0; @@ -1980,9 +1969,9 @@ reserve_terminator(L, #b_br{bool=#b_literal{val=true},succ=Succ}, Blocks, Res) - reserve_terminator(_, Last, _, _) -> {#{},beam_ssa:used(Last)}. -res_xregs_from_phi([#b_set{op=phi,dst=#b_var{name=Dst},args=Args}|Is], +res_xregs_from_phi([#b_set{op=phi,dst=Dst,args=Args}|Is], Pred, Res, Acc) -> - case [V || {#b_var{name=V},L} <- Args, L =:= Pred] of + case [V || {#b_var{}=V,L} <- Args, L =:= Pred] of [] -> res_xregs_from_phi(Is, Pred, Res, Acc); [V] -> @@ -1998,8 +1987,8 @@ res_xregs_from_phi(_, _, _, Acc) -> Acc. reserve_call_args(Args) -> reserve_call_args(Args, 0, #{}). -reserve_call_args([#b_var{name=Name}|As], X, Xs) -> - reserve_call_args(As, X+1, Xs#{Name=>{x,X}}); +reserve_call_args([#b_var{}=Var|As], X, Xs) -> + reserve_call_args(As, X+1, Xs#{Var=>{x,X}}); reserve_call_args([#b_literal{}|As], X, Xs) -> reserve_call_args(As, X+1, Xs); reserve_call_args([], _, Xs) -> Xs. @@ -2078,9 +2067,9 @@ remove_unsuitable_aliases(#st{aliases=[_|_]=Aliases0,ssa=Blocks}=St) -> remove_unsuitable_aliases(#st{aliases=[]}=St) -> St. rem_unsuitable([#b_blk{is=Is}|Bs]) -> - Vs = [{V,Dst} || - #b_set{op=bs_start_match,dst=#b_var{name=Dst}, - args=[#b_var{name=V}]} <- Is], + Vs = [{Var,Dst} || + #b_set{op=bs_start_match,dst=Dst, + args=[#b_var{}=Var]} <- Is], Vs ++ rem_unsuitable(Bs); rem_unsuitable([]) -> []. @@ -2432,14 +2421,14 @@ is_yreg({x,_}) -> false; is_yreg({z,_}) -> false; is_yreg({fr,_}) -> false. -new_var_names([V0|Vs0], Count0) -> - {V,Count1} = new_var_name(V0, Count0), - {Vs,Count} = new_var_names(Vs0, Count1), +new_vars([Base|Vs0], Count0) -> + {V,Count1} = new_var(Base, Count0), + {Vs,Count} = new_vars(Vs0, Count1), {[V|Vs],Count}; -new_var_names([], Count) -> {[],Count}. +new_vars([], Count) -> {[],Count}. -new_var_name({Base,Int}, Count) -> +new_var({Base,Int}, Count) -> true = is_integer(Int), %Assertion. - {{Base,Count},Count+1}; -new_var_name(Base, Count) -> - {{Base,Count},Count+1}. + {#b_var{name={Base,Count}},Count+1}; +new_var(Base, Count) -> + {#b_var{name={Base,Count}},Count+1}. diff --git a/lib/compiler/src/beam_ssa_recv.erl b/lib/compiler/src/beam_ssa_recv.erl index 82fe006487..6e49b128da 100644 --- a/lib/compiler/src/beam_ssa_recv.erl +++ b/lib/compiler/src/beam_ssa_recv.erl @@ -138,7 +138,7 @@ recv_opt_is([I|Is], RecvLbl, Blocks, Acc) -> recv_opt_is(Is, RecvLbl, Blocks, [I|Acc]); recv_opt_is([], _, _, _) -> no. -makes_ref(#b_set{dst=#b_var{name=Dst},args=[Func0|_]}, Blocks) -> +makes_ref(#b_set{dst=Dst,args=[Func0|_]}, Blocks) -> Func = case Func0 of #b_remote{mod=#b_literal{val=erlang}, name=#b_literal{val=Name},arity=A0} -> @@ -158,15 +158,15 @@ makes_ref(#b_set{dst=#b_var{name=Dst},args=[Func0|_]}, Blocks) -> end. ref_in_tuple(Tuple, Blocks) -> - F = fun(#b_set{op=get_tuple_element,dst=#b_var{name=Ref}, - args=[#b_var{name=Tup},#b_literal{val=1}]}, no) + F = fun(#b_set{op=get_tuple_element,dst=Ref, + args=[#b_var{}=Tup,#b_literal{val=1}]}, no) when Tup =:= Tuple -> {yes,Ref}; (_, A) -> A end, beam_ssa:fold_instrs_rpo(F, [0], no, Blocks). opt_ref_used(RecvLbl, Ref, Blocks) -> - Vs = #{{var,Ref}=>ref,ref=>Ref,ref_matched=>false}, + Vs = #{Ref=>ref,ref=>Ref,ref_matched=>false}, case opt_ref_used_1(RecvLbl, Vs, Blocks) of used -> true; not_used -> false; @@ -182,10 +182,10 @@ opt_ref_used_1(L, Vs0, Blocks) -> Result end. -opt_ref_used_is([#b_set{op=peek_message,dst=#b_var{name=M}}|Is], Vs0) -> - Vs = Vs0#{{var,M}=>message}, +opt_ref_used_is([#b_set{op=peek_message,dst=Msg}|Is], Vs0) -> + Vs = Vs0#{Msg=>message}, opt_ref_used_is(Is, Vs); -opt_ref_used_is([#b_set{op={bif,Bif},args=Args,dst=#b_var{name=B}}=I|Is], +opt_ref_used_is([#b_set{op={bif,Bif},args=Args,dst=Dst}=I|Is], Vs0) -> S = case Bif of '=:=' -> true; @@ -199,7 +199,7 @@ opt_ref_used_is([#b_set{op={bif,Bif},args=Args,dst=#b_var{name=B}}=I|Is], Bool when is_boolean(Bool) -> case is_ref_msg_comparison(Args, Vs0) of true -> - Vs = Vs0#{B=>{is_ref,Bool}}, + Vs = Vs0#{Dst=>{is_ref,Bool}}, opt_ref_used_is(Is, Vs); false -> opt_ref_used_is(Is, Vs0) @@ -225,7 +225,7 @@ opt_ref_used_is([], Vs) -> Vs. opt_ref_used_last(#b_blk{last=Last}=Blk, Vs, Blocks) -> case Last of - #b_br{bool=#b_var{name=Bool},succ=Succ,fail=Fail} -> + #b_br{bool=#b_var{}=Bool,succ=Succ,fail=Fail} -> case Vs of #{Bool:={is_ref,Matched}} -> ref_used_in([{Succ,Vs#{ref_matched:=Matched}}, @@ -252,17 +252,16 @@ ref_used_in([{L,Vs0}|Ls], Blocks) -> end; ref_used_in([], _) -> done. -update_vars(#b_set{args=Args,dst=#b_var{name=B}}, Vs) -> - Vars = [V || #b_var{name=V} <- Args], - All = all(fun(V) -> - Var = {var,V}, +update_vars(#b_set{args=Args,dst=Dst}, Vs) -> + Vars = [V || #b_var{}=V <- Args], + All = all(fun(Var) -> case Vs of #{Var:=message} -> true; #{} -> false end end, Vars), case All of - true -> Vs#{{var,B}=>message}; + true -> Vs#{Dst=>message}; false -> Vs end. @@ -270,9 +269,7 @@ update_vars(#b_set{args=Args,dst=#b_var{name=B}}, Vs) -> %% Return 'true' if Args denotes a comparison between the %% reference and message or part of the message. -is_ref_msg_comparison([#b_var{name=A1},#b_var{name=A2}], Vs) -> - V1 = {var,A1}, - V2 = {var,A2}, +is_ref_msg_comparison([#b_var{}=V1,#b_var{}=V2], Vs) -> case Vs of #{V1:=ref,V2:=message} -> true; #{V1:=message,V2:=ref} -> true; diff --git a/lib/compiler/src/beam_ssa_type.erl b/lib/compiler/src/beam_ssa_type.erl index 058e40106c..5ccc9c371b 100644 --- a/lib/compiler/src/beam_ssa_type.erl +++ b/lib/compiler/src/beam_ssa_type.erl @@ -56,12 +56,12 @@ Block :: beam_ssa:b_blk(). opt(Linear, Args) -> - Ts = maps:from_list([{V,any} || #b_var{name=V} <- Args]), + Ts = maps:from_list([{V,any} || #b_var{}=V <- Args]), FakeCall = #b_set{op=call,args=[#b_remote{mod=#b_literal{val=unknown}, name=#b_literal{val=unknown}, arity=0}]}, - Defs = maps:from_list([{V,FakeCall#b_set{dst=Var}} || - #b_var{name=V}=Var <- Args]), + Defs = maps:from_list([{Var,FakeCall#b_set{dst=Var}} || + #b_var{}=Var <- Args]), D = #d{ds=Defs,ls=#{0=>Ts},sub=#{}}, opt_1(Linear, D). @@ -117,7 +117,7 @@ simplify_terminator(#b_switch{arg=Arg}=Sw, Sub, Ts) -> simplify_terminator(#b_ret{arg=Arg}=Ret, Sub, Ts) -> Ret#b_ret{arg=simplify_arg(Arg, Sub, Ts)}. -opt_is([#b_set{op=phi,dst=#b_var{name=Dst},args=Args0}=I0|Is], +opt_is([#b_set{op=phi,dst=Dst,args=Args0}=I0|Is], Ts0, Ds0, Ls, Sub0, Acc) -> %% Simplify the phi node by removing all predecessor blocks that no %% longer exists or no longer branches to this block. @@ -136,7 +136,7 @@ opt_is([#b_set{op=phi,dst=#b_var{name=Dst},args=Args0}=I0|Is], Ds = Ds0#{Dst=>I}, opt_is(Is, Ts, Ds, Ls, Sub0, [I|Acc]) end; -opt_is([#b_set{args=Args0,dst=#b_var{name=Dst}}=I0|Is], +opt_is([#b_set{args=Args0,dst=Dst}=I0|Is], Ts0, Ds0, Ls, Sub0, Acc) -> Args = simplify_args(Args0, Sub0, Ts0), I1 = beam_ssa:normalize(I0#b_set{args=Args}), @@ -361,9 +361,9 @@ simplify_arg(#b_remote{mod=Mod,name=Name}=Rem, Sub, Ts) -> name=simplify_arg(Name, Sub, Ts)}; simplify_arg(Arg, _Sub, _Ts) -> Arg. -sub_arg(#b_var{name=V}=Old, Sub) -> +sub_arg(#b_var{}=Old, Sub) -> case Sub of - #{V:=New} -> New; + #{Old:=New} -> New; #{} -> Old end. @@ -387,7 +387,7 @@ anno_float_arg(_) -> convert. opt_terminator(#b_br{bool=#b_literal{}}=Br, _Ts, _Ds) -> beam_ssa:normalize(Br); -opt_terminator(#b_br{bool=#b_var{name=V}}=Br, Ts, Ds) -> +opt_terminator(#b_br{bool=#b_var{}=V}=Br, Ts, Ds) -> #{V:=Set} = Ds, case Set of #b_set{op={bif,'=:='},args=[Bool,#b_literal{val=true}]} -> @@ -429,7 +429,7 @@ update_successors(#b_br{bool=#b_var{}=Bool,succ=Succ,fail=Fail}, Ts, D0) -> D = update_successor_bool(Bool, false, Fail, Ts, D0), SuccTs = infer_types(Bool, Ts, D0), update_successor_bool(Bool, true, Succ, SuccTs, D); -update_successors(#b_switch{arg=#b_var{name=V},fail=Fail,list=List}, Ts, D0) -> +update_successors(#b_switch{arg=#b_var{}=V,fail=Fail,list=List}, Ts, D0) -> D = update_successor(Fail, Ts, D0), foldl(fun({Val,S}, A) -> T = get_type(Val, Ts), @@ -437,10 +437,10 @@ update_successors(#b_switch{arg=#b_var{name=V},fail=Fail,list=List}, Ts, D0) -> end, D, List); update_successors(#b_ret{}, _Ts, D) -> D. -update_successor_bool(#b_var{name=V}=Var, BoolValue, S, Ts, D) -> +update_successor_bool(#b_var{}=Var, BoolValue, S, Ts, D) -> case t_is_boolean(get_type(Var, Ts)) of true -> - update_successor(S, Ts#{V:=t_atom(BoolValue)}, D); + update_successor(S, Ts#{Var:=t_atom(BoolValue)}, D); false -> %% The `br` terminator is preceeded by an instruction that %% does not produce a boolean value, such a `new_try_tag`. @@ -456,7 +456,7 @@ update_successor(S, Ts0, #d{ls=Ls}=D) -> D#d{ls=Ls#{S=>Ts0}} end. -update_types(#b_set{op=Op,dst=#b_var{name=Dst},args=Args}, Ts, Ds) -> +update_types(#b_set{op=Op,dst=Dst,args=Args}, Ts, Ds) -> T = type(Op, Args, Ts, Ds), Ts#{Dst=>T}. @@ -531,7 +531,7 @@ type(put_tuple, Args, _Ts, _Ds) -> _ -> #t_tuple{exact=true,size=length(Args)} end; -type(succeeded, [#b_var{name=Src}], Ts, Ds) -> +type(succeeded, [#b_var{}=Src], Ts, Ds) -> case maps:get(Src, Ds) of #b_set{op={bif,Bif},args=BifArgs} -> Types = get_types(BifArgs, Ts), @@ -750,7 +750,7 @@ simplify_switch_bool(#b_switch{arg=B,list=List0}=Sw, Ts, Ds) -> Sw end. -simplify_not(#b_br{bool=#b_var{name=V},succ=Succ,fail=Fail}=Br0, Ts, Ds) -> +simplify_not(#b_br{bool=#b_var{}=V,succ=Succ,fail=Fail}=Br0, Ts, Ds) -> case Ds of #{V:=#b_set{op={bif,'not'},args=[Bool]}} -> case t_is_boolean(get_type(Bool, Ts)) of @@ -768,7 +768,7 @@ get_types(Values, Ts) -> [get_type(Val, Ts) || Val <- Values]. -spec get_type(beam_ssa:value(), type_db()) -> type(). -get_type(#b_var{name=V}, Ts) -> +get_type(#b_var{}=V, Ts) -> #{V:=T} = Ts, T; get_type(#b_literal{val=Val}, _Ts) -> @@ -794,40 +794,40 @@ get_type(#b_literal{val=Val}, _Ts) -> any end. -infer_types(#b_var{name=V}, Ts, #d{ds=Ds}) -> +infer_types(#b_var{}=V, Ts, #d{ds=Ds}) -> #{V:=#b_set{op=Op,args=Args}} = Ds, Types = infer_type(Op, Args, Ds), meet_types(Types, Ts). -infer_type({bif,element}, [#b_literal{val=Pos},#b_var{name=Tuple}], _Ds) -> +infer_type({bif,element}, [#b_literal{val=Pos},#b_var{}=Tuple], _Ds) -> if is_integer(Pos), 1 =< Pos -> [{Tuple,#t_tuple{size=Pos}}]; true -> [] end; -infer_type({bif,'=:='}, [#b_var{name=Src},#b_literal{}=Lit], Ds) -> +infer_type({bif,'=:='}, [#b_var{}=Src,#b_literal{}=Lit], Ds) -> Def = maps:get(Src, Ds), Type = get_type(Lit, #{}), [{Src,Type}|infer_tuple_size(Def, Lit) ++ infer_first_element(Def, Lit)]; -infer_type({bif,Bif}, [#b_var{name=Src}]=Args, _Ds) -> +infer_type({bif,Bif}, [#b_var{}=Src]=Args, _Ds) -> case inferred_bif_type(Bif, Args) of any -> []; T -> [{Src,T}] end; -infer_type({bif,is_map_key}, [_,#b_var{name=Src}], _Ds) -> +infer_type({bif,is_map_key}, [_,#b_var{}=Src], _Ds) -> [{Src,map}]; -infer_type({bif,map_get}, [_,#b_var{name=Src}], _Ds) -> +infer_type({bif,map_get}, [_,#b_var{}=Src], _Ds) -> [{Src,map}]; -infer_type(bs_start_match, [#b_var{name=Bin}], _Ds) -> +infer_type(bs_start_match, [#b_var{}=Bin], _Ds) -> [{Bin,{binary,1}}]; -infer_type(is_nonempty_list, [#b_var{name=Src}], _Ds) -> +infer_type(is_nonempty_list, [#b_var{}=Src], _Ds) -> [{Src,cons}]; -infer_type(is_tagged_tuple, [#b_var{name=Src},#b_literal{val=Size}, +infer_type(is_tagged_tuple, [#b_var{}=Src,#b_literal{val=Size}, #b_literal{val=Tag}], _Ds) -> [{Src,#t_tuple{exact=true,size=Size,elements=[Tag]}}]; -infer_type(succeeded, [#b_var{name=Src}], Ds) -> +infer_type(succeeded, [#b_var{}=Src], Ds) -> #b_set{op=Op,args=Args} = maps:get(Src, Ds), infer_type(Op, Args, Ds); infer_type(_Op, _Args, _Ds) -> @@ -903,13 +903,13 @@ inferred_bif_type(tl, [_]) -> cons; inferred_bif_type(tuple_size, [_]) -> #t_tuple{}; inferred_bif_type(_, _) -> any. -infer_tuple_size(#b_set{op={bif,tuple_size},args=[#b_var{name=Tuple}]}, +infer_tuple_size(#b_set{op={bif,tuple_size},args=[#b_var{}=Tuple]}, #b_literal{val=Size}) when is_integer(Size) -> [{Tuple,#t_tuple{exact=true,size=Size}}]; infer_tuple_size(_, _) -> []. infer_first_element(#b_set{op=get_tuple_element, - args=[#b_var{name=Tuple},#b_literal{val=0}]}, + args=[#b_var{}=Tuple,#b_literal{val=0}]}, #b_literal{val=First}) -> [{Tuple,#t_tuple{size=1,elements=[First]}}]; infer_first_element(_, _) -> []. |