60
60
-record(range, {range :: range_rep(),
61
61
other :: boolean()}).
62
-type range() :: #range{}.
63
-record(ann, {range :: #range{},
64
-record(ann, {range :: range(),
64
65
type :: erl_types:erl_type(),
65
66
count :: integer()}).
67
-type ann() :: #ann{}.
67
-type range_anno() :: {range_anno, #ann{}, fun((#ann{}) -> string())}.
68
-type args_fun() :: fun((mfa(),cfg()) -> [#range{}]).
69
-type call_fun() :: fun((mfa(),[#range{}]) -> #range{}).
70
-type final_fun() :: fun((mfa(),[#range{}]) -> ok).
69
-type range_anno() :: {'range_anno', ann(), fun((ann()) -> string())}.
70
-type args_fun() :: fun((mfa(), cfg()) -> [range()]).
71
-type call_fun() :: fun((mfa(), [range()]) -> range()).
72
-type final_fun() :: fun((mfa(), [range()]) -> 'ok').
71
73
-type data() :: {mfa(), args_fun(), call_fun(), final_fun()}.
72
74
-type label() :: non_neg_integer().
73
75
-type info() :: gb_tree().
75
77
-type variable() :: #icode_variable{}.
76
78
-type annotated_variable() :: #icode_variable{}.
77
79
-type argument() :: #icode_const{} | variable().
78
-type three_range_fun() :: fun((#range{},#range{},#range{}) -> #range{}).
80
-type three_range_fun() :: fun((range(),range(),range()) -> range()).
79
81
-type instr_split_info() :: {icode_instr(), [{label(),info()}]}.
80
-type last_instr_return() :: {instr_split_info(), #range{}}.
82
-type last_instr_return() :: {instr_split_info(), range()}.
82
84
-record(state, {info_map = gb_trees:empty() :: info(),
83
85
counter = dict:new() :: dict(),
85
87
liveness = gb_trees:empty() :: gb_tree(),
87
89
lookup_fun :: call_fun(),
88
90
result_action :: final_fun()}).
108
110
-spec concurrent_cfg(cfg(), mfa(), pid()) -> cfg().
110
112
concurrent_cfg(Cfg, MFA, CompServer) ->
111
CompServer ! {ready, {MFA,self()}},
112
{ArgsFun,CallFun,FinalFun} = do_analysis(Cfg, MFA),
113
CompServer ! {ready, {MFA, self()}},
114
{ArgsFun, CallFun, FinalFun} = do_analysis(Cfg, MFA),
113
115
Ans = do_rewrite(Cfg, MFA, ArgsFun, CallFun, FinalFun),
114
116
CompServer ! {done_rewrite, MFA},
266
268
%% io:format("Uses: ~p~nRanges: ~p~n", [Uses, PresentRanges]),
267
269
JoinFun = fun(Var, Range) -> update_info(Var, Range, WidenFun) end,
268
270
NewUses = lists:zipwith(JoinFun, Uses, PresentRanges),
269
hipe_icode:subst_uses(lists:zip(Uses, NewUses),I).
271
hipe_icode:subst_uses(lists:zip(Uses, NewUses), I).
271
-spec join_info(#ann{}, #range{}, three_range_fun()) -> #ann{}.
273
-spec join_info(ann(), range(), three_range_fun()) -> ann().
273
275
join_info(Ann = #ann{range = R1, type = Type, count = ?WIDEN}, R2, Fun) ->
274
276
Ann#ann{range = Fun(R1, R2, range_from_simple_type(Type))};
278
280
NewR -> Ann#ann{range = NewR, count = C+1}
281
-spec join_three(#range{}, #range{}, #range{}) -> #range{}.
283
-spec join_three(range(), range(), range()) -> range().
283
285
join_three(R1, R2, R3) ->
284
286
inf(sup(R1, R2), R3).
286
-spec update_info(variable(), #range{}) -> annotated_variable().
288
-spec update_info(variable(), range()) -> annotated_variable().
288
290
update_info(Var, Range) ->
289
291
update_info(Var, Range, fun update_three/3).
291
-spec update_info(variable(), #range{}, three_range_fun()) -> annotated_variable().
293
-spec update_info(variable(), range(), three_range_fun()) -> annotated_variable().
293
295
update_info(Arg, R, Fun) ->
294
296
case hipe_icode:is_annotated_variable(Arg) of
314
316
NewR -> Ann#ann{range = NewR, count = C+1}
317
-spec type_to_ann(erl_types:erl_type()) -> #ann{}.
319
-spec type_to_ann(erl_types:erl_type()) -> ann().
319
321
type_to_ann(Type) ->
320
#ann{range = range_from_simple_type(Type), type = t_limit(Type,1), count=1}.
322
#ann{range = range_from_simple_type(Type), type = t_limit(Type,1), count = 1}.
322
-spec make_range_anno(#ann{}) -> range_anno().
324
-spec make_range_anno(ann()) -> range_anno().
324
326
make_range_anno(Ann) ->
325
327
{range_anno, Ann, fun pp_ann/1}.
327
-spec update_three(#range{}, #range{}, #range{}) -> #range{}.
329
-spec update_three(range(), range(), range()) -> range().
329
331
update_three(_R1, R2, R3) ->
332
-spec safe_widen(#range{}, #range{}, #range{}) -> #range{}.
334
-spec safe_widen(range(), range(), range()) -> range().
334
336
safe_widen(#range{range=Old}, #range{range=New}, T = #range{range=Wide}) ->
336
case {Old,New,Wide} of
337
{{Min,Max1},{Min,Max2},{_,Max}} ->
338
case inf_geq(OMax = next_up_limit(inf_max([Max1,Max2])),Max) of
338
case {Old, New, Wide} of
339
{{Min,Max1}, {Min,Max2}, {_,Max}} ->
340
case inf_geq(OMax = next_up_limit(inf_max([Max1, Max2])), Max) of
339
341
true -> {Min,Max};
340
342
false -> {Min,OMax}
342
{{Min1,Max},{Min2,Max},{Min,_}} ->
343
case inf_geq(Min, OMin = next_down_limit(inf_min([Min1,Min2]))) of
344
{{Min1,Max}, {Min2,Max}, {Min,_}} ->
345
case inf_geq(Min, OMin = next_down_limit(inf_min([Min1, Min2]))) of
344
346
true -> {Min,Max};
345
347
false -> {OMin,Max}
347
{{Min1,Max1},{Min2,Max2},{Min,Max}} ->
349
{{Min1,Max1}, {Min2,Max2}, {Min,Max}} ->
349
case inf_geq(OMax = next_up_limit(inf_max([Max1,Max2])),Max) of
351
case inf_geq(OMax = next_up_limit(inf_max([Max1, Max2])), Max) of
354
case inf_geq(Min, OMin = next_down_limit(inf_min([Min1,Min2]))) of
356
case inf_geq(Min, OMin = next_down_limit(inf_min([Min1, Min2]))) of
362
T#range{range=ResRange}.
364
T#range{range = ResRange}.
364
-spec widen(#range{}, #range{}, #range{}) -> #range{}.
366
-spec widen(range(), range(), range()) -> range().
366
368
widen(#range{range=Old}, #range{range=New}, T = #range{range=Wide}) ->
368
case {Old,New,Wide} of
369
{{Min,_},{Min,Max2},{_,Max}} ->
370
case inf_geq(OMax = next_up_limit(Max2),Max) of
370
case {Old, New, Wide} of
371
{{Min,_}, {Min,Max2}, {_,Max}} ->
372
case inf_geq(OMax = next_up_limit(Max2), Max) of
371
373
true -> {Min,Max};
372
374
false -> {Min,OMax}
374
{{_,Max},{Min2,Max},{Min,_}} ->
376
{{_,Max}, {Min2,Max}, {Min,_}} ->
375
377
case inf_geq(Min, OMin = next_down_limit(Min2)) of
376
378
true -> {Min,Max};
377
379
false -> {OMin,Max}
379
{_,{Min2,Max2},{Min,Max}} ->
381
{_, {Min2,Max2}, {Min,Max}} ->
381
case inf_geq(OMax = next_up_limit(Max2),Max) of
383
case inf_geq(OMax = next_up_limit(Max2), Max) of
497
-spec update_infos(argument(), info(), [{#range{},label()}]) -> [{label(),info()}].
499
-spec update_infos(argument(), info(), [{range(),label()}]) -> [{label(),info()}].
499
501
update_infos(Arg, Info, [{Range, Label}|Rest]) ->
500
[{Label,enter_define({Arg,Range},Info)} | update_infos(Arg,Info,Rest)];
502
[{Label,enter_define({Arg,Range},Info)} | update_infos(Arg, Info, Rest)];
501
503
update_infos(_, _, []) -> [].
503
-spec get_range_label_list([{argument(),label()}], #range{}, [{#range{},label()}]) ->
504
{#range{},[{#range{},label()}]}.
505
-spec get_range_label_list([{argument(),label()}], range(), [{range(),label()}]) ->
506
{range(),[{range(),label()}]}.
506
508
get_range_label_list([{Val,Label}|Cases], SRange, Acc) ->
507
509
VRange = get_range_from_arg(Val),
597
599
analyse_if(If, Info, Rewrite) ->
598
600
case hipe_icode:if_args(If) of
600
602
analyse_sane_if(If, Info, Args, get_range_from_args(Args), Rewrite);
602
604
TrueLabel = hipe_icode:if_true_label(If),
603
605
FalseLabel = hipe_icode:if_false_label(If),
604
{If, [{TrueLabel,Info},{FalseLabel,Info}]}
606
{If, [{TrueLabel, Info}, {FalseLabel, Info}]}
607
609
-spec analyse_sane_if(#icode_if{}, info(), [argument(),...],
608
[#range{},...], boolean()) ->
610
[range(),...], boolean()) ->
609
611
{#icode_goto{} | #icode_if{}, [{label(), info()}]}.
611
613
analyse_sane_if(If, Info, [Arg1, Arg2], [Range1, Range2], Rewrite) ->
614
616
{TrueRange2, TrueRange1, FalseRange2, FalseRange1} =
615
617
range_inequality_propagation(Range2, Range1);
617
{TempTrueRange1, TempTrueRange2, FalseRange1, FalseRange2}=
618
range_equality_propagation(Range1, Range2),
619
TrueRange1 = set_other(TempTrueRange1,other(Range1)),
620
TrueRange2 = set_other(TempTrueRange2,other(Range2));
622
{TrueRange1, TrueRange2, FalseRange1, FalseRange2} =
619
{TrueRange1, TrueRange2, FalseRange1, FalseRange2} =
623
620
range_inequality_propagation(Range1, Range2);
625
622
{FalseRange1, FalseRange2, TrueRange1, TrueRange2} =
626
623
range_inequality_propagation(Range1, Range2);
628
{FalseRange2, FalseRange1, TrueRange2, TrueRange1} =
625
{FalseRange2, FalseRange1, TrueRange2, TrueRange1} =
629
626
range_inequality_propagation(Range2, Range1);
631
{TrueRange1, TrueRange2, FalseRange1, FalseRange2}=
628
{TrueRange1, TrueRange2, FalseRange1, FalseRange2} =
632
629
range_equality_propagation(Range1, Range2);
634
631
{FalseRange1, FalseRange2, TrueRange1, TrueRange2} =
635
632
range_equality_propagation(Range1, Range2);
634
{TempTrueRange1, TempTrueRange2, FalseRange1, FalseRange2} =
635
range_equality_propagation(Range1, Range2),
636
TrueRange1 = set_other(TempTrueRange1, other(Range1)),
637
TrueRange2 = set_other(TempTrueRange2, other(Range2));
637
{TempFalseRange1, TempFalseRange2, TrueRange1, TrueRange2}=
639
{TempFalseRange1, TempFalseRange2, TrueRange1, TrueRange2} =
638
640
range_equality_propagation(Range1, Range2),
639
FalseRange1 = set_other(TempFalseRange1,other(Range1)),
640
FalseRange2 = set_other(TempFalseRange2,other(Range2))
641
FalseRange1 = set_other(TempFalseRange1, other(Range1)),
642
FalseRange2 = set_other(TempFalseRange2, other(Range2))
642
TrueLabel = hipe_icode:if_true_label(If),
643
FalseLabel = hipe_icode:if_false_label(If),
645
enter_defines([{Arg1,TrueRange1}, {Arg2,TrueRange2}],Info),
647
enter_defines([{Arg1,FalseRange1}, {Arg2,FalseRange2}],Info),
649
case lists:any(fun range__is_none/1,[TrueRange1,TrueRange2]) of
651
false -> [{TrueLabel,TrueInfo}]
654
case lists:any(fun range__is_none/1, [FalseRange1,FalseRange2]) of
656
false -> [{FalseLabel,FalseInfo}]
658
UpdateInfo = True++False,
644
%% io:format("TR1 = ~w\nTR2 = ~w\n", [TrueRange1, TrueRange2]),
646
case lists:all(fun range__is_none/1, [TrueRange1, TrueRange2]) of
649
TrueLabel = hipe_icode:if_true_label(If),
650
TrueArgRanges = [{Arg1, TrueRange1}, {Arg2, TrueRange2}],
651
TrueInfo = enter_defines(TrueArgRanges, Info),
652
[{TrueLabel, TrueInfo}]
654
%% io:format("FR1 = ~w\nFR2 = ~w\n", [FalseRange1, FalseRange2]),
656
case lists:all(fun range__is_none/1, [FalseRange1, FalseRange2]) of
659
FalseLabel = hipe_icode:if_false_label(If),
660
FalseArgRanges = [{Arg1, FalseRange1}, {Arg2, FalseRange2}],
661
FalseInfo = enter_defines(FalseArgRanges, Info),
662
[{FalseLabel, FalseInfo}]
664
UpdateInfo = True ++ False,
661
%%io:format("~w~n~w~n", [{Arg1,FalseRange1},{Arg2,FalseRange2}]),
662
%%io:format("Any none: ~w~n", [lists:any(fun range__is_none/1,[FalseRange1,FalseRange2])]),
663
667
case UpdateInfo of
664
[] -> %%This is weird
668
[] -> %% This is weird
667
671
hipe_icode:mk_goto(Label);
781
785
TrueRange = inf(any_range(), OldVarRange),
782
786
FalseRange = inf(none_range(), OldVarRange);
784
TrueRange = inf(none_range(),OldVarRange),
788
TrueRange = inf(none_range(), OldVarRange),
785
789
FalseRange = OldVarRange
787
791
TrueLabel = hipe_icode:type_true_label(Type),
788
792
FalseLabel = hipe_icode:type_false_label(Type),
790
enter_define({Arg,TrueRange},Info),
792
enter_define({Arg,FalseRange},Info),
793
TrueInfo = enter_define({Arg, TrueRange}, Info),
794
FalseInfo = enter_define({Arg, FalseRange}, Info),
794
796
case range__is_none(TrueRange) of
796
false -> [{TrueLabel,TrueInfo}]
798
false -> [{TrueLabel, TrueInfo}]
799
801
case range__is_none(FalseRange) of
801
false -> [{FalseLabel,FalseInfo}]
803
false -> [{FalseLabel, FalseInfo}]
803
UpdateInfo = True++False,
805
UpdateInfo = True ++ False,
806
808
case UpdateInfo of
899
901
range_init(empty, Other) ->
900
902
#range{range = empty, other = Other}.
902
-spec range(#range{}) -> range_rep().
904
-spec range(range()) -> range_rep().
904
906
range(#range{range = R}) -> R.
906
-spec other(#range{}) -> boolean().
908
-spec other(range()) -> boolean().
908
910
other(#range{other = O}) -> O.
910
-spec set_other(#range{}, boolean()) -> #range{}.
912
-spec set_other(range(), boolean()) -> range().
912
914
set_other(R, O) -> R#range{other = O}.
914
-spec range__min(#range{}) -> 'empty' | 'neg_inf' | integer().
916
range__min(#range{range=empty}) -> empty;
917
range__min(#range{range={Min,_}}) -> Min.
919
-spec range__max(#range{}) -> 'empty' | 'pos_inf' | integer().
921
range__max(#range{range=empty}) -> empty;
922
range__max(#range{range={_,Max}}) -> Max.
924
-spec range__is_none(#range{}) -> boolean().
926
range__is_none(#range{range=empty, other=false}) -> true;
916
-spec range__min(range()) -> 'empty' | 'neg_inf' | integer().
918
range__min(#range{range = empty}) -> empty;
919
range__min(#range{range = {Min,_}}) -> Min.
921
-spec range__max(range()) -> 'empty' | 'pos_inf' | integer().
923
range__max(#range{range = empty}) -> empty;
924
range__max(#range{range = {_,Max}}) -> Max.
926
-spec range__is_none(range()) -> boolean().
928
range__is_none(#range{range = empty, other = false}) -> true;
927
929
range__is_none(#range{}) -> false.
929
-spec range__is_empty(#range{}) -> boolean().
931
range__is_empty(#range{range=empty}) -> true;
932
range__is_empty(#range{range={_,_}}) -> false.
934
-spec remove_point_types(#range{}, [#range{}]) -> #range{}.
931
-spec range__is_empty(range()) -> boolean().
933
range__is_empty(#range{range = empty}) -> true;
934
range__is_empty(#range{range = {_,_}}) -> false.
936
-spec remove_point_types(range(), [range()]) -> range().
936
938
remove_point_types(Range, Ranges) ->
937
939
Sorted = lists:sort(Ranges),
939
941
Range1 = lists:foldl(FoldFun, Range, Sorted),
940
942
lists:foldl(FoldFun, Range1, lists:reverse(Sorted)).
942
-spec range__remove_constant(#range{}, #range{}) -> #range{}.
944
-spec range__remove_constant(range(), range()) -> range().
944
range__remove_constant(R = #range{range={C,C}}, #range{range={C,C}}) ->
945
R#range{range=empty};
946
range__remove_constant(R = #range{range={C,H}}, #range{range={C,C}}) ->
947
R#range{range={C+1,H}};
948
range__remove_constant(R = #range{range={L,C}}, #range{range={C,C}}) ->
949
R#range{range={L,C-1}};
950
range__remove_constant(R = #range{}, #range{range={C,C}}) ->
946
range__remove_constant(#range{range = {C, C}} = R, #range{range = {C, C}}) ->
947
R#range{range = empty};
948
range__remove_constant(#range{range = {C, H}} = R, #range{range = {C, C}}) ->
949
R#range{range = {C+1, H}};
950
range__remove_constant(#range{range = {L, C}} = R, #range{range = {C, C}}) ->
951
R#range{range = {L, C-1}};
952
range__remove_constant(#range{} = R, #range{range = {C,C}}) ->
952
range__remove_constant(R = #range{}, _) ->
954
range__remove_constant(#range{} = R, _) ->
955
-spec any_type() -> #range{}.
957
-spec any_type() -> range().
958
#range{range=any_r(), other=true}.
960
#range{range = any_r(), other = true}.
960
-spec any_range() -> #range{}.
962
-spec any_range() -> range().
963
#range{range=any_r(), other=false}.
965
#range{range = any_r(), other = false}.
965
-spec none_range() -> #range{}.
967
-spec none_range() -> range().
968
#range{range=empty, other=true}.
970
#range{range = empty, other = true}.
970
-spec none_type() -> #range{}.
972
-spec none_type() -> range().
973
975
#range{range = empty, other = false}.
1106
1108
{hipe_bs_primop, {bs_get_integer, Size, Flags}} ->
1107
1109
{Min, Max} = analyse_bs_get_integer(Size, Flags, length(Args) =:= 1),
1108
[#range{range={Min, Max}, other=false}, any_type()];
1110
[#range{range = {Min, Max}, other = false}, any_type()];
1109
1111
{hipe_bs_primop, _} = Primop ->
1110
1112
Type = hipe_icode_primops:type(Primop),
1111
1113
range_from_type(Type)
1114
-type bin_operation() :: fun((#range{},#range{}) -> #range{}).
1115
-type unary_operation() :: fun((#range{}) -> #range{}).
1116
-type bin_operation() :: fun((range(), range()) -> range()).
1117
-type unary_operation() :: fun((range()) -> range()).
1117
1119
-spec basic_type(fun_name()) -> 'not_int' | 'not_analysed'
1118
| {bin, bin_operation()}
1119
| {unary, unary_operation()}
1120
| {fcall, mfa()} | {hipe_bs_primop, _}.
1120
| {'bin', bin_operation()}
1121
| {'unary', unary_operation()}
1122
| {'fcall', mfa()} | {'hipe_bs_primop', _}.
1122
1124
%% Arithmetic operations
1123
1125
basic_type('+') -> {bin, fun(R1, R2) -> range_add(R1, R2) end};
1915
1917
Change = lists:zipwith(EqFun, ResRanges, OldRanges),
1916
1918
{lists:all(fun (X) -> X end, Change), ResRanges}.
1918
-spec new__info/1 :: ([#range{}]) -> [#ann{}].
1920
-spec new__info([range()]) -> [ann()].
1919
1921
new__info(NewRanges) ->
1920
1922
[#ann{range=Range,count=1,type=t_any()} || Range <- NewRanges].
1922
-spec return__info/1 :: ([#ann{}]) -> [#range{}].
1924
-spec return__info([ann()]) -> [range()].
1923
1925
return__info(Ranges) ->
1924
1926
[Range || #ann{range=Range} <- Ranges].
1926
-spec return_none/0 :: () -> [#range{},...].
1928
-spec return_none() -> [range(),...].
1927
1929
return_none() ->
1930
-spec return_none_args/2 :: (#cfg{}, mfa()) -> [#range{}].
1932
-spec return_none_args(cfg(), mfa()) -> [range()].
1931
1933
return_none_args(Cfg, {_M,_F,A}) ->
1933
1935
case hipe_icode_cfg:is_closure(Cfg) of