35
35
-include("../flow/hipe_bb.hrl").
36
36
-include("hipe_icode_type.hrl").
38
-type(range_rep() :: {'neg_inf' | integer(), 'pos_inf' | integer()} | 'empty').
39
-type(fun_name() :: atom() | tuple()).
40
-type(inf_integer() :: 'neg_inf' | 'pos_inf' | integer()).
38
-type range_rep() :: {'neg_inf' | integer(), 'pos_inf' | integer()} | 'empty'.
39
-type fun_name() :: atom() | tuple().
40
-type inf_integer() :: 'neg_inf' | 'pos_inf' | integer().
42
42
-record(range, {range :: range_rep(),
45
-record(ann, {range :: #range{},
45
-record(ann, {range :: #range{},
47
47
count :: integer()}).
49
-type(range_anno() :: {range_anno, #ann{}, fun((#ann{}) -> string())}).
50
-type(args_fun() :: fun((mfa(),cfg()) -> [#range{}])).
51
-type(call_fun() :: fun((mfa(),[#range{}]) -> #range{})).
52
-type(final_fun() :: fun((mfa(),[#range{}]) -> ok)).
53
-type(data() :: {mfa(), args_fun(), call_fun(), final_fun()}).
54
-type(label() :: integer()).
55
-type(info() :: gb_tree()).
56
-type(work_list() :: {[label()],[label()],set()}).
57
-type(variable() :: #icode_variable{}).
58
-type(annotated_variable() :: #icode_variable{}).
59
-type(argument() :: #icode_const{} | variable()).
60
-type(three_range_fun() :: fun((#range{},#range{},#range{}) -> #range{})).
61
-type(instr_split_info() :: {icode_instr(),[{label(),info()}]}).
62
-type(last_instr_return() :: {instr_split_info(), #range{}}).
49
-type range_anno() :: {range_anno, #ann{}, fun((#ann{}) -> string())}.
50
-type args_fun() :: fun((mfa(),cfg()) -> [#range{}]).
51
-type call_fun() :: fun((mfa(),[#range{}]) -> #range{}).
52
-type final_fun() :: fun((mfa(),[#range{}]) -> ok).
53
-type data() :: {mfa(), args_fun(), call_fun(), final_fun()}.
54
-type label() :: integer().
55
-type info() :: gb_tree().
56
-type work_list() :: {[label()],[label()],set()}.
57
-type variable() :: #icode_variable{}.
58
-type annotated_variable() :: #icode_variable{}.
59
-type argument() :: #icode_const{} | variable().
60
-type three_range_fun() :: fun((#range{},#range{},#range{}) -> #range{}).
61
-type instr_split_info() :: {icode_instr(),[{label(),info()}]}.
62
-type last_instr_return() :: {instr_split_info(), #range{}}.
64
64
-record(state, {info_map :: gb_tree(),
65
65
counter=dict:new() :: dict(),
78
78
%%---------------------------------------------------------------------
80
-spec(cfg/4 :: (cfg(), mfa(), comp_options(), #comp_servers{}) -> cfg()).
80
-spec cfg(cfg(), mfa(), comp_options(), #comp_servers{}) -> cfg().
82
82
cfg(Cfg, MFA, Options, Servers) ->
83
83
case proplists:get_bool(concurrent_comp, Options) of
108
107
{NewArgsFun, NewCallFun, NewFinalFun}
111
-spec(do_rewrite/5 ::
112
(cfg(), mfa(), args_fun(), call_fun(), final_fun()) -> cfg()).
110
-spec do_rewrite(cfg(), mfa(), args_fun(), call_fun(), final_fun()) -> cfg().
114
112
do_rewrite(Cfg, MFA, ArgsFun, CallFun, FinalFun) ->
115
113
common_rewrite(Cfg, {MFA, ArgsFun, CallFun, FinalFun}).
117
-spec(ordinary_cfg/2 :: (cfg(), mfa()) -> cfg()).
115
-spec ordinary_cfg(cfg(), mfa()) -> cfg().
119
117
ordinary_cfg(Cfg, MFA) ->
120
118
Data = make_data(Cfg,MFA),
121
119
common_rewrite(Cfg, Data).
123
-spec(common_rewrite/2 :: (cfg(), data()) -> cfg()).
121
-spec common_rewrite(cfg(), data()) -> cfg().
125
123
common_rewrite(Cfg, Data) ->
126
124
State = safe_analyse(Cfg, Data),
162
160
(state__result_action(NewState))(MFA, [state__ret_type(NewState)]),
165
-spec(rewrite_blocks/1 :: (#state{}) -> #state{}).
163
-spec rewrite_blocks(#state{}) -> #state{}.
167
165
rewrite_blocks(State) ->
168
166
CFG = state__cfg(State),
169
167
Start = hipe_icode_cfg:start_label(CFG),
170
168
rewrite_blocks([Start], State, [Start]).
172
-spec(rewrite_blocks/3 :: ([label()], #state{}, [label()]) -> #state{}).
170
-spec rewrite_blocks([label()], #state{}, [label()]) -> #state{}.
174
172
rewrite_blocks([Next|Rest], State, Visited) ->
175
173
Info = state__info_in(State, Next),
199
197
analyse_blocks(NewState, NewWork2)
202
-spec(analyse_block/4 ::
203
(label(), info(), #state{}, bool()) -> {#state{}, [label()]}).
200
-spec analyse_block(label(), info(), #state{}, bool()) -> {#state{}, [label()]}.
205
202
analyse_block(Label, Info, State, Rewrite) ->
206
203
BB = state__bb(State, Label),
211
208
State2 = state__ret_type_update(State1, RetType),
212
209
state__update_info(State2, InfoList, Rewrite).
214
-spec(analyse_BB/5 ::
215
([icode_instr()], info(), [icode_instr()], bool(), call_fun()) ->
216
{[icode_instr()], [info()], #range{}}).
211
-spec analyse_BB([icode_instr()], info(), [icode_instr()], bool(), call_fun()) ->
212
{[icode_instr()], [info()], #range{}}.
218
214
analyse_BB([Last], Info, Code, Rewrite, LookupFun) ->
219
215
%% io:format("I: ~w~n",[Last]),
223
219
{NewInfo,NewI} = analyse_insn(Insn, Info, LookupFun),
224
220
analyse_BB(InsnList, NewInfo, [NewI|Code], Rewrite, LookupFun).
226
-spec(analyse_insn/3 ::
227
(icode_instr(), info(), call_fun()) -> {info(), icode_instr()}).
222
-spec analyse_insn(icode_instr(), info(), call_fun()) -> {info(), icode_instr()}.
229
224
analyse_insn(I, Info, LookupFun) ->
230
225
%% io:format("~w Info: ~p~n",[I,Info]),
240
235
{enter_vals(FinalI, Info), FinalI}.
242
-spec(handle_args/2 :: (icode_instr(), info()) -> icode_instr()).
237
-spec handle_args(icode_instr(), info()) -> icode_instr().
244
239
handle_args(I, Info) ->
245
240
WidenFun = fun update_three/3,
246
241
handle_args(I, Info, WidenFun).
248
-spec(handle_args/3 ::
249
(icode_instr(), info(), three_range_fun()) -> icode_instr()).
243
-spec handle_args(icode_instr(), info(), three_range_fun()) -> icode_instr().
251
245
handle_args(I, Info, WidenFun) ->
252
246
Uses = hipe_icode:uses(I),
256
250
NewUses = lists:zipwith(JoinFun, Uses, PresentRanges),
257
251
hipe_icode:subst_uses(lists:zip(Uses, NewUses),I).
259
-spec(join_info/3 :: (#ann{}, #range{}, three_range_fun()) -> #ann{}).
253
-spec join_info(#ann{}, #range{}, three_range_fun()) -> #ann{}.
261
255
join_info(Ann = #ann{range=R1,type=Type,count=?WIDEN}, R2, Fun) ->
262
256
Ann#ann{range = Fun(R1, R2, range_from_simple_type(Type))};
266
260
NewR -> Ann#ann{range=NewR, count=C+1}
269
-spec(join_three/3 :: (#range{}, #range{}, #range{}) -> #range{}).
263
-spec join_three(#range{}, #range{}, #range{}) -> #range{}.
271
265
join_three(R1, R2, R3) ->
272
266
inf(sup(R1, R2), R3).
274
-spec(update_info/2 :: (variable(), #range{}) -> annotated_variable()).
268
-spec update_info(variable(), #range{}) -> annotated_variable().
276
270
update_info(Var, Range) ->
277
271
update_info(Var, Range, fun update_three/3).
279
-spec(update_info/3 ::
280
(variable(), #range{}, three_range_fun()) -> annotated_variable()).
273
-spec update_info(variable(), #range{}, three_range_fun()) -> annotated_variable().
282
275
update_info(Arg, R, Fun) ->
283
276
case hipe_icode:is_annotated_variable(Arg) of
303
296
NewR -> Ann#ann{range=NewR, count=C+1}
306
-spec(type_to_ann/1 :: (any()) -> #ann{}).
299
-spec type_to_ann(any()) -> #ann{}.
308
301
type_to_ann(Type) ->
309
302
#ann{range = range_from_simple_type(Type), type = t_limit(Type,1), count=1}.
311
-spec(make_range_anno/1 :: (#ann{}) -> range_anno()).
304
-spec make_range_anno(#ann{}) -> range_anno().
313
306
make_range_anno(Ann) ->
314
307
{range_anno, Ann, fun pp_ann/1}.
316
-spec(update_three/3 :: (#range{}, #range{}, #range{}) -> #range{}).
309
-spec update_three(#range{}, #range{}, #range{}) -> #range{}.
318
311
update_three(_R1, R2, R3) ->
321
-spec(safe_widen/3 :: (#range{},#range{},#range{}) -> #range{}).
314
-spec safe_widen(#range{}, #range{}, #range{}) -> #range{}.
323
316
safe_widen(#range{range=Old}, #range{range=New}, T = #range{range=Wide}) ->
426
418
NewDst = update_info(Dst, DstRange, fun widen/3),
427
419
hipe_icode:subst_defines([{Dst, NewDst}], Phi).
429
-spec(analyse_last_insn/4 ::
430
(icode_instr(), info(), bool(), call_fun()) -> last_instr_return()).
421
-spec analyse_last_insn(icode_instr(), info(), bool(), call_fun()) ->
432
424
analyse_last_insn(I, Info, Rewrite, LookupFun) ->
433
425
%% io:format("~w Info: ~p~n",[I,Info]),
448
440
#icode_begin_try{} -> {analyse_begin_try(NewI, Info), none_type()}
451
-spec(analyse_return/2 :: (icode_instr(),info()) -> last_instr_return()).
443
-spec analyse_return(icode_instr(),info()) -> last_instr_return().
453
445
analyse_return(Insn, _Info) ->
454
446
[RetRange] = get_range_from_args(hipe_icode:return_vars(Insn)),
455
447
{{Insn,[]}, RetRange}.
457
-spec(analyse_enter/3 ::
458
(icode_instr(), info(), call_fun()) -> last_instr_return()).
449
-spec analyse_enter(icode_instr(), info(), call_fun()) -> last_instr_return().
460
451
analyse_enter(Insn, _Info, LookupFun) ->
461
452
Args = hipe_icode:args(Insn),
464
455
[RetRange] = analyse_call_or_enter_fun(Fun, Args, CallType, LookupFun),
465
456
{{Insn,[]}, RetRange}.
467
-spec(analyse_switch_val/3 ::
468
(#icode_switch_val{},info(),bool()) -> instr_split_info()).
458
-spec analyse_switch_val(#icode_switch_val{},info(),bool()) -> instr_split_info().
470
460
analyse_switch_val(Switch, Info, Rewrite) ->
471
461
Var = hipe_icode:switch_val_term(Switch),
489
-spec(update_infos/3 ::
490
(argument(), info(), [{#range{},label()}]) -> [{label(),info()}]).
479
-spec update_infos(argument(), info(), [{#range{},label()}]) -> [{label(),info()}].
492
481
update_infos(Arg, Info, [{Range, Label}|Rest]) ->
493
482
[{Label,enter_define({Arg,Range},Info)} | update_infos(Arg,Info,Rest)];
494
483
update_infos(_, _, []) -> [].
496
-spec(get_range_label_list/3 ::
497
([{argument(),label()}], #range{},[{#range{},label()}]) ->
498
{#range{},[{#range{},label()}]}).
485
-spec get_range_label_list([{argument(),label()}], #range{}, [{#range{},label()}]) ->
486
{#range{},[{#range{},label()}]}.
500
488
get_range_label_list([{Val,Label}|Cases], SRange, Acc) ->
501
489
VRange = get_range_from_arg(Val),
510
498
{PointTypes, _} = lists:unzip(Acc),
511
499
{remove_point_types(SRange, PointTypes), Acc}.
513
-spec(update_switch/3 ::
514
(#icode_switch_val{}, [{#range{},label()}], bool()) ->
515
#icode_switch_val{}).
501
-spec update_switch(#icode_switch_val{}, [{#range{},label()}], bool()) ->
517
504
update_switch(Switch, LabelRangeList, KeepFail) ->
529
-spec(label_range_list_to_cases/2 ::
530
([{#range{},label()}], [{#icode_const{},label()}]) ->
531
'no_update' | [{#icode_const{},label()}]).
516
-spec label_range_list_to_cases([{#range{},label()}], [{#icode_const{},label()}]) ->
517
'no_update' | [{#icode_const{},label()}].
533
519
label_range_list_to_cases([{#range{range={C,C},other=false},Label}|Rest],
534
520
Acc) when is_integer(C) ->
538
524
label_range_list_to_cases([], Acc) ->
539
525
lists:reverse(Acc).
541
-spec(analyse_switch_tuple_arity/2 ::
542
(#icode_switch_tuple_arity{},info()) ->
543
{#icode_switch_tuple_arity{},[{label(),info()}]}).
527
-spec analyse_switch_tuple_arity(#icode_switch_tuple_arity{}, info()) ->
528
{#icode_switch_tuple_arity{},[{label(),info()}]}.
545
530
analyse_switch_tuple_arity(Switch, Info) ->
546
531
Var = hipe_icode:switch_tuple_arity_term(Switch),
551
536
Labels = [Fail|Case_labels],
552
537
{Switch, [{Label,NewInfo} || Label <- Labels]}.
554
-spec(analyse_goto/2 ::
555
(#icode_goto{},info()) -> {#icode_goto{}, [{label(),info()},...]}).
539
-spec analyse_goto(#icode_goto{},info()) -> {#icode_goto{}, [{label(),info()},...]}.
557
541
analyse_goto(Insn, Info) ->
558
542
GotoLabel = hipe_icode:goto_label(Insn),
559
543
{Insn, [{GotoLabel,Info}]}.
561
-spec(analyse_fail/2 ::
562
(#icode_fail{}, info()) -> {#icode_fail{}, [{label(),info()}]}).
545
-spec analyse_fail(#icode_fail{}, info()) -> {#icode_fail{}, [{label(),info()}]}.
564
547
analyse_fail(Fail, Info) ->
565
548
case hipe_icode:fail_label(Fail) of
567
550
Label -> {Fail, [{Label,Info}]}
570
-spec(analyse_begin_try/2 ::
571
(#icode_begin_try{}, info()) ->
572
{#icode_begin_try{}, [{label(),info()},...]}).
553
-spec analyse_begin_try(#icode_begin_try{}, info()) ->
554
{#icode_begin_try{}, [{label(),info()},...]}.
574
556
analyse_begin_try(Insn, Info) ->
575
557
Label = hipe_icode:begin_try_label(Insn),
576
558
Successor = hipe_icode:begin_try_successor(Insn),
577
559
{Insn, [{Label,Info},{Successor,Info}]}.
579
-spec(analyse_last_call/3 ::
580
(#icode_call{}, info(), call_fun()) ->
581
{#icode_call{}, [{label(),info()},...]}).
561
-spec analyse_last_call(#icode_call{}, info(), call_fun()) ->
562
{#icode_call{}, [{label(),info()},...]}.
583
564
analyse_last_call(Call, Info, LookupFun) ->
584
565
%% hipe_icode_pp:pp_block([Insn]),
592
573
{NewI, [{Continuation,NewInfo}, {Fail,Info}]}
595
-spec(analyse_if/3 ::
596
(#icode_if{}, info(), bool()) ->
597
{#icode_goto{} | #icode_if{}, [{label(),info()}]}).
576
-spec analyse_if(#icode_if{}, info(), bool()) ->
577
{#icode_goto{} | #icode_if{}, [{label(),info()}]}.
599
579
analyse_if(If, Info, Rewrite) ->
600
580
case hipe_icode:if_args(If) of
606
586
{If, [{TrueLabel,Info},{FalseLabel,Info}]}
609
-spec(analyse_sane_if/5 ::
610
(#icode_if{},info(),[argument(),...],[#range{},...],bool()) ->
611
{#icode_goto{} | #icode_if{},[{label(),info()}]}).
589
-spec analyse_sane_if(#icode_if{}, info(), [argument(),...],
590
[#range{},...], bool()) ->
591
{#icode_goto{} | #icode_if{}, [{label(), info()}]}.
613
593
analyse_sane_if(If, Info, [Arg1, Arg2], [Range1, Range2], Rewrite) ->
614
594
case normalize_name(hipe_icode:if_op(If)) of
691
-spec(range_equality_propagation/2 ::
692
(#range{}, #range{}) -> {#range{}, #range{}, #range{}, #range{}}).
671
-spec range_equality_propagation(#range{}, #range{}) ->
672
{#range{}, #range{}, #range{}, #range{}}.
694
674
range_equality_propagation(Range_1, Range_2) ->
695
675
True_range = inf(Range_1, Range_2),
713
693
{True_range, True_range, False_range_1, False_range_2}.
715
-spec(range_inequality_propagation/2 ::
716
(#range{}, #range{}) -> {#range{}, #range{}, #range{}, #range{}}).
695
-spec range_inequality_propagation(#range{}, #range{}) ->
696
{#range{}, #range{}, #range{}, #range{}}.
718
698
%% Range1 < Range2
719
699
range_inequality_propagation(Range1, Range2) ->
769
749
range_init(R1_false_range, R1_other),
770
750
range_init(R2_false_range, R2_other)}.
772
-spec(analyse_type/3 ::
773
(#icode_type{}, info(), bool()) ->
774
{#icode_goto{} | #icode_type{}, [{label(),info()}]}).
752
-spec analyse_type(#icode_type{}, info(), bool()) ->
753
{#icode_goto{} | #icode_type{}, [{label(),info()}]}.
776
755
analyse_type(Type, Info, Rewrite) ->
777
756
TypeTest = hipe_icode:type_test(Type),
858
837
t_to_string(Type).
860
-spec(pp_range/1 :: (range_rep()) -> string()).
839
-spec pp_range(range_rep()) -> string().
862
841
pp_range(empty) ->
864
843
pp_range({Min, Max}) ->
865
844
val_to_string(Min) ++ ".." ++ val_to_string(Max).
867
-spec(val_to_string/1 :: ('pos_inf' | 'neg_inf' | integer()) -> string()).
846
-spec val_to_string('pos_inf' | 'neg_inf' | integer()) -> string().
869
848
val_to_string(pos_inf) -> "inf";
870
849
val_to_string(neg_inf) -> "-inf";
871
850
val_to_string(X) when is_integer(X) -> integer_to_list(X).
873
-spec(range_from_type/1 :: (_) -> [#range{}]).
852
-spec range_from_type(_) -> [#range{}].
875
854
range_from_type(Type) ->
876
855
case t_components(Type) of
907
886
range_init(empty, Other) ->
908
887
#range{range=empty, other=Other}.
910
-spec(range/1 :: (#range{}) -> range_rep()).
889
-spec range(#range{}) -> range_rep().
912
891
range(#range{range=R}) -> R.
914
-spec(other/1 :: (#range{}) -> bool()).
893
-spec other(#range{}) -> bool().
916
895
other(#range{other=O}) -> O.
918
-spec(set_other/2 :: (#range{}, bool()) -> #range{}).
897
-spec set_other(#range{}, bool()) -> #range{}.
920
899
set_other(R, O) -> R#range{other=O}.
922
-spec(range__min/1 :: (#range{}) -> 'empty' | 'neg_inf' | integer()).
901
-spec range__min(#range{}) -> 'empty' | 'neg_inf' | integer().
924
903
range__min(#range{range=empty}) -> empty;
925
904
range__min(#range{range={Min,_}}) -> Min.
927
-spec(range__max/1 :: (#range{}) -> 'empty' | 'pos_inf' | integer()).
906
-spec range__max(#range{}) -> 'empty' | 'pos_inf' | integer().
929
908
range__max(#range{range=empty}) -> empty;
930
909
range__max(#range{range={_,Max}}) -> Max.
932
-spec(range__is_none/1 :: (#range{}) -> bool()).
911
-spec range__is_none(#range{}) -> bool().
934
913
range__is_none(#range{range=empty, other=false}) -> true;
935
914
range__is_none(#range{}) -> false.
937
-spec(range__is_empty/1 :: (#range{}) -> bool()).
916
-spec range__is_empty(#range{}) -> bool().
939
918
range__is_empty(#range{range=empty}) -> true;
940
919
range__is_empty(#range{range={_,_}}) -> false.
942
-spec(remove_point_types/2 :: (#range{}, [#range{}]) -> #range{}).
921
-spec remove_point_types(#range{}, [#range{}]) -> #range{}.
944
923
remove_point_types(Range, Ranges) ->
945
924
Sorted = lists:sort(Ranges),
947
926
Range1 = lists:foldl(FoldFun, Range, Sorted),
948
927
lists:foldl(FoldFun, Range1, lists:reverse(Sorted)).
950
-spec(range__remove_constant/2 :: (#range{},#range{}) -> #range{}).
929
-spec range__remove_constant(#range{}, #range{}) -> #range{}.
952
931
range__remove_constant(R = #range{range={C,C}}, #range{range={C,C}}) ->
953
932
R#range{range=empty};
960
939
range__remove_constant(R = #range{}, _) ->
963
-spec(any_type/0 :: () -> #range{}).
942
-spec any_type() -> #range{}.
966
945
#range{range=any_r(), other=true}.
968
-spec(any_range/0 :: () -> #range{}).
947
-spec any_range() -> #range{}.
971
950
#range{range=any_r(), other=false}.
973
-spec(none_range/0 :: () -> #range{}).
952
-spec none_range() -> #range{}.
976
955
#range{range=empty, other=true}.
978
-spec(none_type/0 :: () -> #range{}).
957
-spec none_type() -> #range{}.
981
960
#range{range=empty, other=false}.
983
-spec(any_r/0 :: () -> {'neg_inf','pos_inf'}).
962
-spec any_r() -> {'neg_inf','pos_inf'}.
985
964
any_r() -> {neg_inf,pos_inf}.
987
-spec(get_range_from_args/1 :: ([argument()]) -> [#range{}]).
966
-spec get_range_from_args([argument()]) -> [#range{}].
989
968
get_range_from_args(Args) ->
990
969
[get_range_from_arg(Arg) || Arg <- Args].
992
-spec(get_range_from_arg/1 :: (argument()) -> #range{}).
971
-spec get_range_from_arg(argument()) -> #range{}.
994
973
get_range_from_arg(Arg) ->
995
974
case hipe_icode:is_const(Arg) of
1020
999
%% inf([R1,R2|Rest]) ->
1021
1000
%% inf([inf(R1,R2)|Rest]).
1023
-spec(inf/2 :: (#range{}, #range{}) -> #range{}).
1002
-spec inf(#range{}, #range{}) -> #range{}.
1025
1004
inf(#range{range=R1, other=O1}, #range{range=R2, other=O2}) ->
1026
1005
#range{range=range_inf(R1,R2), other=other_inf(O1,O2)}.
1028
-spec(range_inf/2 :: (range_rep(), range_rep()) -> range_rep()).
1007
-spec range_inf(range_rep(), range_rep()) -> range_rep().
1030
1009
range_inf(empty, _) -> empty;
1031
1010
range_inf(_, empty) -> empty;
1042
-spec(other_inf/2 :: (bool(), bool()) -> bool()).
1021
-spec other_inf(bool(), bool()) -> bool().
1044
1023
other_inf(O1, O2) -> O1 and O2.
1046
-spec(sup/1 :: ([#range{},...]) -> #range{}).
1025
-spec sup([#range{},...]) -> #range{}.
1050
1029
sup([R1,R2|Rest]) ->
1051
1030
sup([sup(R1, R2)|Rest]).
1053
-spec(sup/2 :: (#range{}, #range{}) -> #range{}).
1032
-spec sup(#range{}, #range{}) -> #range{}.
1055
1034
sup(#range{range=R1,other=O1}, #range{range=R2,other=O2}) ->
1056
1035
#range{range=range_sup(R1,R2), other=other_sup(O1,O2)}.
1058
-spec(range_sup/2 :: (range_rep(), range_rep()) -> range_rep()).
1037
-spec range_sup(range_rep(), range_rep()) -> range_rep().
1060
1039
range_sup(empty, R) -> R;
1061
1040
range_sup(R, empty) -> R;
1064
1043
NewMax = inf_max([Max1,Max2]),
1065
1044
{NewMin,NewMax}.
1067
-spec(other_sup/2 :: (bool(), bool()) -> bool()).
1046
-spec other_sup(bool(), bool()) -> bool().
1069
1048
other_sup(O1, O2) -> O1 or O2.
1071
1050
%%== Call Support =============================================================
1073
-spec(analyse_call_or_enter_fun/4 ::
1074
(fun_name(), [argument()], icode_call_type(), call_fun()) -> [#range{}]).
1052
-spec analyse_call_or_enter_fun(fun_name(), [argument()],
1053
icode_call_type(), call_fun()) -> [#range{}].
1076
1055
analyse_call_or_enter_fun(Fun, Args, CallType, LookupFun) ->
1077
1056
%%io:format("Fun: ~p~n Args: ~p~n CT: ~p~n LF: ~p~n", [Fun, Args, CallType, LookupFun]),
1118
1097
range_from_type(Type)
1121
-type(bin_operation() :: fun((#range{},#range{}) -> #range{})).
1122
-type(unary_operation() :: fun((#range{}) -> #range{})).
1100
-type bin_operation() :: fun((#range{},#range{}) -> #range{}).
1101
-type unary_operation() :: fun((#range{}) -> #range{}).
1124
-spec(basic_type/1 ::
1125
(fun_name()) -> 'not_int' | 'not_analysed' | {bin, bin_operation()} |
1126
{unary, unary_operation()} | {fcall, mfa()} |
1127
{hipe_bs_primop, _}).
1103
-spec basic_type(fun_name()) -> 'not_int' | 'not_analysed'
1104
| {bin, bin_operation()}
1105
| {unary, unary_operation()}
1106
| {fcall, mfa()} | {hipe_bs_primop, _}.
1129
1108
%% Arithmetic operations
1130
1109
basic_type('+') -> {bin, fun(R1, R2) -> range_add(R1, R2) end};
1199
1178
basic_type(#unsafe_element{}) -> not_analysed;
1200
1179
basic_type(#unsafe_update_element{}) -> not_analysed.
1202
-spec(analyse_bs_get_integer/3 ::
1203
(integer(), integer(), bool()) -> range_rep()).
1181
-spec analyse_bs_get_integer(integer(), integer(), bool()) -> range_rep().
1205
1183
analyse_bs_get_integer(Size, Flags, true) ->
1206
1184
Signed = Flags band 4,
1230
1208
Other = other(Range1) orelse other(Range2),
1231
1209
range_init({NewMin, NewMax}, Other).
1233
-spec(range_sub/2 :: (#range{}, #range{}) -> #range{}).
1211
-spec range_sub(#range{}, #range{}) -> #range{}.
1235
1213
range_sub(Range1, Range2) ->
1236
1214
Min_sub = inf_min([inf_inv(range__max(Range2)),
1282
1260
Other = other(Range1) orelse other(Range2),
1283
1261
range_init(Range, Other).
1285
-spec(extreme_divisors/1 :: (#range{}) -> range_rep()).
1263
-spec extreme_divisors(#range{}) -> range_rep().
1287
1265
extreme_divisors(#range{range={0,0}}) -> {0,0};
1288
1266
extreme_divisors(#range{range={0,Max}}) -> {1,Max};
1314
1292
inf_div(Max1, Min2), inf_div(Max1, Max2)],
1315
1293
range_init({inf_min(Min_max_list), inf_max(Min_max_list)}, false).
1317
-spec(range_rem/2 :: (#range{}, #range{}) -> #range{}).
1295
-spec range_rem(#range{}, #range{}) -> #range{}.
1319
1297
range_rem(Range1, Range2) ->
1320
1298
%% Range1 desides the sign of the answer.
1368
1346
range_init({Min, Max}, false).
1370
-spec(range_bnot/1 :: (#range{}) -> #range{}).
1348
-spec range_bnot(#range{}) -> #range{}.
1372
1350
range_bnot(Range) ->
1373
1351
Minus_one = range_init({-1,-1}, false),
1374
1352
range_add(range_mult(Range, Minus_one), Minus_one).
1376
-spec(width/1 :: (range_rep() | integer()) -> 'pos_inf' | non_neg_integer()).
1354
-spec width(range_rep() | integer()) -> 'pos_inf' | non_neg_integer().
1378
1356
width({Min, Max}) -> inf_max([width(Min), width(Max)]);
1379
1357
width(pos_inf) -> pos_inf;
1559
-spec(inf_abs/1 :: (inf_integer()) -> 'pos_inf' | integer()).
1536
-spec inf_abs(inf_integer()) -> 'pos_inf' | integer().
1561
1538
inf_abs(pos_inf) -> pos_inf;
1562
1539
inf_abs(neg_inf) -> pos_inf;
1563
1540
inf_abs(Number) when is_integer(Number), (Number < 0) -> - Number;
1564
1541
inf_abs(Number) when is_integer(Number) -> Number.
1566
-spec(inf_add/2 :: (inf_integer(), inf_integer()) -> inf_integer()).
1543
-spec inf_add(inf_integer(), inf_integer()) -> inf_integer().
1568
1545
inf_add(pos_inf, _Number) -> pos_inf;
1569
1546
inf_add(neg_inf, _Number) -> neg_inf;
1572
1549
inf_add(Number1, Number2) when is_integer(Number1), is_integer(Number2) ->
1573
1550
Number1 + Number2.
1575
-spec(inf_inv/1 :: (inf_integer()) -> inf_integer()).
1552
-spec inf_inv(inf_integer()) -> inf_integer().
1577
1554
inf_inv(pos_inf) -> neg_inf;
1578
1555
inf_inv(neg_inf) -> pos_inf;
1579
1556
inf_inv(Number) -> -Number.
1581
-spec(inf_geq/2 :: (inf_integer(), inf_integer()) -> bool()).
1558
-spec inf_geq(inf_integer(), inf_integer()) -> bool().
1583
1560
inf_geq(pos_inf, _) -> true;
1584
1561
inf_geq(_, pos_inf) -> false;
1586
1563
inf_geq(neg_inf, _) -> false;
1587
1564
inf_geq(A, B) -> A >= B.
1589
-spec(inf_greater_zero/1 :: (inf_integer()) -> bool()).
1566
-spec inf_greater_zero(inf_integer()) -> bool().
1591
1568
inf_greater_zero(pos_inf) -> true;
1592
1569
inf_greater_zero(neg_inf) -> false;
1593
1570
inf_greater_zero(Number) when is_integer(Number), Number >= 0 -> true;
1594
1571
inf_greater_zero(Number) when is_integer(Number), Number < 0 -> false.
1596
-spec(inf_div/2 :: (inf_integer(), inf_integer()) -> inf_integer()).
1573
-spec inf_div(inf_integer(), inf_integer()) -> inf_integer().
1598
1575
inf_div(Number, 0) ->
1599
1576
Greater = inf_greater_zero(Number),
1638
1615
inf_mult(Number, neg_inf) -> inf_mult(neg_inf, Number);
1639
1616
inf_mult(Number1, Number2) -> Number1 * Number2.
1641
-spec(inf_bsl/2 :: (inf_integer(), _) -> inf_integer()).
1618
-spec inf_bsl(inf_integer(), _) -> inf_integer().
1643
1620
inf_bsl(pos_inf, _) -> pos_inf;
1644
1621
inf_bsl(neg_inf, _) -> neg_inf;
1680
1657
lookup_fun=CallFun, result_action=FinalFun}
1683
-spec(state__cfg/1 :: (#state{}) -> cfg()).
1660
-spec state__cfg(#state{}) -> cfg().
1685
1662
state__cfg(#state{cfg=Cfg}) ->
1688
-spec(state__bb/2 :: (#state{}, label()) -> bb()).
1665
-spec state__bb(#state{}, label()) -> bb().
1690
1667
state__bb(#state{cfg=Cfg}, Label) ->
1691
1668
BB = hipe_icode_cfg:bb(Cfg, Label),
1692
1669
true = hipe_bb:is_bb(BB), % Just an assert
1695
-spec(state__bb_add/3 :: (#state{}, label(), bb()) -> #state{}).
1672
-spec state__bb_add(#state{}, label(), bb()) -> #state{}.
1697
1674
state__bb_add(S=#state{cfg=Cfg}, Label, BB) ->
1698
1675
NewCfg = hipe_icode_cfg:bb_add(Cfg, Label, BB),
1923
1900
Change = lists:zipwith(EqFun, ResRanges, OldRanges),
1924
1901
{lists:all(fun (X) -> X end, Change), ResRanges}.
1926
-spec(new__info/1 :: ([#range{}]) -> [#ann{}]).
1903
-spec new__info/1 :: ([#range{}]) -> [#ann{}].
1927
1904
new__info(NewRanges) ->
1928
1905
[#ann{range=Range,count=1,type=t_any()} || Range <- NewRanges].
1930
-spec(return__info/1 :: ([#ann{}]) -> [#range{}]).
1907
-spec return__info/1 :: ([#ann{}]) -> [#range{}].
1931
1908
return__info(Ranges) ->
1932
1909
[Range || #ann{range=Range} <- Ranges].
1934
-spec(return_none/0 :: () -> [#range{}]).
1911
-spec return_none/0 :: () -> [#range{}].
1935
1912
return_none() ->
1938
-spec(return_none_args/2 :: (#cfg{}, mfa()) -> [#range{}]).
1915
-spec return_none_args/2 :: (#cfg{}, mfa()) -> [#range{}].
1939
1916
return_none_args(Cfg, {_M,_F,A}) ->
1941
1918
case hipe_icode_cfg:is_closure(Cfg) of