1%%
2%% %CopyrightBegin%
3%%
4%% Copyright Ericsson AB 1999-2018. All Rights Reserved.
5%%
6%% Licensed under the Apache License, Version 2.0 (the "License");
7%% you may not use this file except in compliance with the License.
8%% You may obtain a copy of the License at
9%%
10%%     http://www.apache.org/licenses/LICENSE-2.0
11%%
12%% Unless required by applicable law or agreed to in writing, software
13%% distributed under the License is distributed on an "AS IS" BASIS,
14%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15%% See the License for the specific language governing permissions and
16%% limitations under the License.
17%%
18%% %CopyrightEnd%
19%%
20%% Purpose: Type-based optimisations. See the comment for verified_type/1
21%% the very end of this file for a description of the types in the
22%% type database.
23
24-module(beam_type).
25
26-export([module/2]).
27
28-import(lists, [foldl/3,member/2,reverse/1,reverse/2,sort/1]).
29
30-define(UNICODE_INT, {integer,{0,16#10FFFF}}).
31
32-spec module(beam_utils:module_code(), [compile:option()]) ->
33                    {'ok',beam_utils:module_code()}.
34
35module({Mod,Exp,Attr,Fs0,Lc}, _Opts) ->
36    Fs = [function(F) || F <- Fs0],
37    {ok,{Mod,Exp,Attr,Fs,Lc}}.
38
39function({function,Name,Arity,CLabel,Asm0}) ->
40    try
41	Asm1 = beam_utils:live_opt(Asm0),
42	Asm2 = opt(Asm1, [], tdb_new()),
43	Asm3 = beam_utils:live_opt(Asm2),
44	Asm = beam_utils:delete_annos(Asm3),
45	{function,Name,Arity,CLabel,Asm}
46    catch
47        Class:Error:Stack ->
48	    io:fwrite("Function: ~w/~w\n", [Name,Arity]),
49	    erlang:raise(Class, Error, Stack)
50    end.
51
52%% opt([Instruction], Accumulator, TypeDb) -> {[Instruction'],TypeDb'}
53%%  Keep track of type information; try to simplify.
54
55opt([{block,Body1}|Is], [{block,Body0}|Acc], Ts0) ->
56    {Body2,Ts} = simplify(Body1, Ts0),
57    Body = merge_blocks(Body0, Body2),
58    opt(Is, [{block,Body}|Acc], Ts);
59opt([{block,Body0}|Is], Acc, Ts0) ->
60    {Body,Ts} = simplify(Body0, Ts0),
61    opt(Is, [{block,Body}|Acc], Ts);
62opt([I0|Is], Acc, Ts0) ->
63    case simplify_basic([I0], Ts0) of
64	{[],Ts} -> opt(Is, Acc, Ts);
65	{[I],Ts} -> opt(Is, [I|Acc], Ts)
66    end;
67opt([], Acc, _) -> reverse(Acc).
68
69%% simplify(Instruction, TypeDb) -> NewInstruction
70%%  Simplify an instruction using type information (this is
71%%  technically a "strength reduction").
72
73simplify(Is0, TypeDb0) ->
74    {Is,_} = BasicRes = simplify_basic(Is0, TypeDb0),
75    case simplify_float(Is, TypeDb0) of
76	not_possible -> BasicRes;
77	{_,_}=Res -> Res
78    end.
79
80%% simplify_basic([Instruction], TypeDatabase) -> {[Instruction],TypeDatabase'}
81%%  Basic simplification, mostly tuples, no floating point optimizations.
82
83simplify_basic(Is, Ts) ->
84    simplify_basic(Is, Ts, []).
85
86simplify_basic([I0|Is], Ts0, Acc) ->
87    case simplify_instr(I0, Ts0) of
88        [] ->
89            simplify_basic(Is, Ts0, Acc);
90        [I] ->
91            Ts = update(I, Ts0),
92            simplify_basic(Is, Ts, [I|Acc])
93    end;
94simplify_basic([], Ts, Acc) ->
95    {reverse(Acc),Ts}.
96
97%% simplify_instr(Instruction, Ts) -> [Instruction].
98
99%%  Simplify a simple instruction using type information. Return an
100%%  empty list if the instruction should be removed, or a list with
101%%  the original or modified instruction.
102
103simplify_instr({set,[D],[{integer,Index},Reg],{bif,element,_}}=I, Ts) ->
104    case max_tuple_size(Reg, Ts) of
105        Sz when 0 < Index, Index =< Sz ->
106            [{set,[D],[Reg],{get_tuple_element,Index-1}}];
107        _ -> [I]
108    end;
109simplify_instr({test,Test,Fail,[R]}=I, Ts) ->
110    case tdb_find(R, Ts) of
111        any ->
112            [I];
113        Type ->
114            case will_succeed(Test, Type) of
115                yes -> [];
116                no -> [{jump,Fail}];
117                maybe -> [I]
118            end
119    end;
120simplify_instr({set,[D],[TupleReg],{get_tuple_element,0}}=I, Ts) ->
121    case tdb_find(TupleReg, Ts) of
122        {tuple,_,_,[Contents]} ->
123            [{set,[D],[Contents],move}];
124        _ ->
125            [I]
126    end;
127simplify_instr({test,test_arity,_,[R,Arity]}=I, Ts) ->
128    case tdb_find(R, Ts) of
129        {tuple,exact_size,Arity,_} -> [];
130        _ -> [I]
131    end;
132simplify_instr({test,is_eq_exact,Fail,[R,{atom,A}=Atom]}=I, Ts) ->
133    case tdb_find(R, Ts) of
134        {atom,_}=Atom -> [];
135        boolean when is_boolean(A) -> [I];
136        any -> [I];
137        _ -> [{jump,Fail}]
138    end;
139simplify_instr({test,is_record,_,[R,{atom,_}=Tag,{integer,Arity}]}=I, Ts) ->
140    case tdb_find(R, Ts) of
141        {tuple,exact_size,Arity,[Tag]} -> [];
142        _ -> [I]
143    end;
144simplify_instr({select,select_val,Reg,_,_}=I, Ts) ->
145    [case tdb_find(Reg, Ts) of
146         {integer,Range} ->
147             simplify_select_val_int(I, Range);
148         boolean ->
149             simplify_select_val_bool(I);
150         _ ->
151             I
152     end];
153simplify_instr({test,bs_test_unit,_,[Src,Unit]}=I, Ts) ->
154    case tdb_find(Src, Ts) of
155        {binary,U} when U rem Unit =:= 0 -> [];
156        _ -> [I]
157    end;
158simplify_instr(I, _) -> [I].
159
160simplify_select_val_int({select,select_val,R,_,L0}=I, {Min,Max}) ->
161    Vs = sort([V || {integer,V} <- L0]),
162    case eq_ranges(Vs, Min, Max) of
163	false -> I;
164	true -> simplify_select_val_1(L0, {integer,Max}, R, [])
165    end.
166
167simplify_select_val_bool({select,select_val,R,_,L}=I) ->
168    Vs = sort([V || {atom,V} <- L]),
169    case Vs of
170	[false,true] ->
171	    simplify_select_val_1(L, {atom,false}, R, []);
172	_ ->
173	    I
174    end.
175
176simplify_select_val_1([Val,F|T], Val, R, Acc) ->
177    L = reverse(Acc, T),
178    {select,select_val,R,F,L};
179simplify_select_val_1([V,F|T], Val, R, Acc) ->
180    simplify_select_val_1(T, Val, R, [F,V|Acc]).
181
182eq_ranges([H], H, H) -> true;
183eq_ranges([H|T], H, Max) -> eq_ranges(T, H+1, Max);
184eq_ranges(_, _, _) -> false.
185
186%% will_succeed(TestOperation, Type) -> yes|no|maybe.
187%%  Test whether TestOperation applied to an argument of type Type
188%%  will succeed.  Return yes, no, or maybe.
189%%
190%%  Type is a type as described in the comment for verified_type/1 at
191%%  the very end of this file, but it will *never* be 'any'.
192
193will_succeed(is_atom, Type) ->
194    case Type of
195        {atom,_} -> yes;
196        boolean -> yes;
197        _ -> no
198    end;
199will_succeed(is_binary, Type) ->
200    case Type of
201        {binary,U} when U rem 8 =:= 0 -> yes;
202        {binary,_} -> maybe;
203        _ -> no
204    end;
205will_succeed(is_bitstr, Type) ->
206    case Type of
207        {binary,_} -> yes;
208        _ -> no
209    end;
210will_succeed(is_integer, Type) ->
211    case Type of
212        integer -> yes;
213        {integer,_} -> yes;
214        _ -> no
215    end;
216will_succeed(is_map, Type) ->
217    case Type of
218        map -> yes;
219        _ -> no
220    end;
221will_succeed(is_nonempty_list, Type) ->
222    case Type of
223        nonempty_list -> yes;
224        _ -> no
225    end;
226will_succeed(is_tuple, Type) ->
227    case Type of
228        {tuple,_,_,_} -> yes;
229        _ -> no
230    end;
231will_succeed(_, _) -> maybe.
232
233%% simplify_float([Instruction], TypeDatabase) ->
234%%                 {[Instruction],TypeDatabase'} | not_possible
235%%  Simplify floating point operations in blocks.
236%%
237simplify_float(Is0, Ts0) ->
238    {Is1,Ts} = simplify_float_1(Is0, Ts0, [], []),
239    Is2 = opt_fmoves(Is1, []),
240    Is3 = flt_need_heap(Is2),
241    try
242	{flt_liveness(Is3),Ts}
243    catch
244	throw:not_possible -> not_possible
245    end.
246
247simplify_float_1([{set,[],[],fclearerror}|Is], Ts, Rs, Acc) ->
248    simplify_float_1(Is, Ts, Rs, clearerror(Acc));
249simplify_float_1([{set,[],[],fcheckerror}|Is], Ts, Rs, Acc) ->
250    simplify_float_1(Is, Ts, Rs, checkerror(Acc));
251simplify_float_1([{set,[{fr,_}],_,_}=I|Is], Ts, Rs, Acc) ->
252    simplify_float_1(Is, Ts, Rs, [I|Acc]);
253simplify_float_1([{set,[D0],[A0],{alloc,_,{gc_bif,'-',{f,0}}}}=I|Is]=Is0,
254		 Ts0, Rs0, Acc0) ->
255    case tdb_find(A0, Ts0) of
256	float ->
257	    A = coerce_to_float(A0),
258	    {Rs1,Acc1} = load_reg(A, Ts0, Rs0, Acc0),
259	    {D,Rs} = find_dest(D0, Rs1),
260	    Areg = fetch_reg(A, Rs),
261	    Acc = [{set,[D],[Areg],{bif,fnegate,{f,0}}}|clearerror(Acc1)],
262	    Ts = tdb_store(D0, float, Ts0),
263	    simplify_float_1(Is, Ts, Rs, Acc);
264	_Other ->
265	    Ts = update(I, Ts0),
266	    {Rs,Acc} = flush(Rs0, Is0, Acc0),
267	    simplify_float_1(Is, Ts, Rs, [I|checkerror(Acc)])
268    end;
269simplify_float_1([{set,[D0],[A0,B0],{alloc,_,{gc_bif,Op0,{f,0}}}}=I|Is]=Is0,
270		 Ts0, Rs0, Acc0) ->
271    case float_op(Op0, A0, B0, Ts0) of
272	no ->
273	    Ts = update(I, Ts0),
274	    {Rs,Acc} = flush(Rs0, Is0, Acc0),
275	    simplify_float_1(Is, Ts, Rs, [I|checkerror(Acc)]);
276	{yes,Op} ->
277	    A = coerce_to_float(A0),
278	    B = coerce_to_float(B0),
279	    {Rs1,Acc1} = load_reg(A, Ts0, Rs0, Acc0),
280	    {Rs2,Acc2} = load_reg(B, Ts0, Rs1, Acc1),
281	    {D,Rs} = find_dest(D0, Rs2),
282	    Areg = fetch_reg(A, Rs),
283	    Breg = fetch_reg(B, Rs),
284	    Acc = [{set,[D],[Areg,Breg],{bif,Op,{f,0}}}|clearerror(Acc2)],
285	    Ts = tdb_store(D0, float, Ts0),
286	    simplify_float_1(Is, Ts, Rs, Acc)
287    end;
288simplify_float_1([{set,_,_,{try_catch,_,_}}=I|Is]=Is0, _Ts, Rs0, Acc0) ->
289    Acc = flush_all(Rs0, Is0, Acc0),
290    simplify_float_1(Is, tdb_new(), Rs0, [I|Acc]);
291simplify_float_1([{set,_,_,{line,_}}=I|Is], Ts, Rs, Acc) ->
292    simplify_float_1(Is, Ts, Rs, [I|Acc]);
293simplify_float_1([I|Is], Ts0, [], Acc) ->
294    Ts = update(I, Ts0),
295    simplify_float_1(Is, Ts, [], [I|Acc]);
296simplify_float_1([I|Is]=Is0, Ts0, Rs0, Acc0) ->
297    Ts = update(I, Ts0),
298    {Rs,Acc} = flush(Rs0, Is0, Acc0),
299    simplify_float_1(Is, Ts, Rs, [I|checkerror(Acc)]);
300simplify_float_1([], Ts, [], Acc) ->
301    Is = reverse(Acc),
302    {Is,Ts}.
303
304coerce_to_float({integer,I}=Int) ->
305    try float(I) of
306	F ->
307	    {float,F}
308    catch _:_ ->
309	    %% Let the overflow happen at run-time.
310	    Int
311    end;
312coerce_to_float(Other) -> Other.
313
314opt_fmoves([{set,[{x,_}=R],[{fr,_}]=Src,fmove}=I1,
315	    {set,[_]=Dst,[{x,_}=R],move}=I2|Is], Acc) ->
316    case beam_utils:is_killed_block(R, Is) of
317	false -> opt_fmoves(Is, [I2,I1|Acc]);
318	true -> opt_fmoves(Is, [{set,Dst,Src,fmove}|Acc])
319    end;
320opt_fmoves([I|Is], Acc) ->
321    opt_fmoves(Is, [I|Acc]);
322opt_fmoves([], Acc) -> reverse(Acc).
323
324clearerror(Is) ->
325    clearerror(Is, Is).
326
327clearerror([{set,[],[],fclearerror}|_], OrigIs) -> OrigIs;
328clearerror([{set,[],[],fcheckerror}|_], OrigIs) -> [{set,[],[],fclearerror}|OrigIs];
329clearerror([_|Is], OrigIs) -> clearerror(Is, OrigIs);
330clearerror([], OrigIs) -> [{set,[],[],fclearerror}|OrigIs].
331
332%% merge_blocks(Block1, Block2) -> Block.
333%%  Combine two blocks and eliminate any move instructions that assign
334%%  to registers that are killed later in the block.
335%%
336merge_blocks(B1, [{'%anno',_}|B2]) ->
337    merge_blocks_1(B1++[{set,[],[],stop_here}|B2]).
338
339merge_blocks_1([{set,[],_,stop_here}|Is]) -> Is;
340merge_blocks_1([{set,[D],_,move}=I|Is]) ->
341    case beam_utils:is_killed_block(D, Is) of
342	true -> merge_blocks_1(Is);
343	false -> [I|merge_blocks_1(Is)]
344    end;
345merge_blocks_1([I|Is]) -> [I|merge_blocks_1(Is)].
346
347%% flt_need_heap([Instruction]) -> [Instruction]
348%%  Insert need heap allocation instructions in the instruction stream
349%%  to properly account for both inserted floating point operations and
350%%  normal term build operations (such as put_list/3).
351%%
352%%  Ignore old heap allocation instructions (except if they allocate a stack
353%%  frame too), as they may be in the wrong place (because gc_bif instructions
354%%  could have been converted to floating point operations).
355
356flt_need_heap(Is) ->
357    flt_need_heap_1(reverse(Is), 0, 0, []).
358
359flt_need_heap_1([{set,[],[],{alloc,_,Alloc}}|Is], H, Fl, Acc) ->
360    case Alloc of
361	{_,nostack,_,_} ->
362	    %% Remove any existing test_heap/2 instruction.
363	    flt_need_heap_1(Is, H, Fl, Acc);
364	{Z,Stk,_,Inits} when is_integer(Stk) ->
365	    %% Keep any allocate*/2 instruction and recalculate heap need.
366	    I = {set,[],[],{alloc,regs,{Z,Stk,build_alloc(H, Fl),Inits}}},
367	    flt_need_heap_1(Is, 0, 0, [I|Acc])
368    end;
369flt_need_heap_1([I|Is], H0, Fl0, Acc) ->
370    {Ns,H1,Fl1} = flt_need_heap_2(I, H0, Fl0),
371    flt_need_heap_1(Is, H1, Fl1, [I|Ns]++Acc);
372flt_need_heap_1([], H, Fl, Acc) ->
373    flt_alloc(H, Fl) ++ Acc.
374
375%% First come all instructions that build. We pass through, while we
376%% add to the need for heap words and floats on the heap.
377flt_need_heap_2({set,[_],[{fr,_}],fmove}, H, Fl) ->
378    {[],H,Fl+1};
379flt_need_heap_2({set,_,_,put_list}, H, Fl) ->
380    {[],H+2,Fl};
381flt_need_heap_2({set,_,_,{put_tuple,_}}, H, Fl) ->
382    {[],H+1,Fl};
383flt_need_heap_2({set,_,_,put}, H, Fl) ->
384    {[],H+1,Fl};
385%% The following instructions cause the insertion of an allocation
386%% instruction if needed.
387flt_need_heap_2({set,_,_,{alloc,_,_}}, H, Fl) ->
388    {flt_alloc(H, Fl),0,0};
389flt_need_heap_2({set,_,_,{set_tuple_element,_}}, H, Fl) ->
390    {flt_alloc(H, Fl),0,0};
391flt_need_heap_2({'%anno',_}, H, Fl) ->
392    {flt_alloc(H, Fl),0,0};
393%% All other instructions are "neutral". We just pass them.
394flt_need_heap_2(_, H, Fl) ->
395    {[],H,Fl}.
396
397flt_alloc(0, 0) ->
398    [];
399flt_alloc(H, 0) ->
400    [{set,[],[],{alloc,regs,{nozero,nostack,H,[]}}}];
401flt_alloc(H, F) ->
402    [{set,[],[],{alloc,regs,{nozero,nostack,
403			     build_alloc(H, F),[]}}}].
404
405build_alloc(Words, 0) -> Words;
406build_alloc(Words, Floats) -> {alloc,[{words,Words},{floats,Floats}]}.
407
408
409%% flt_liveness([Instruction]) -> [Instruction]
410%%  (Re)calculate the number of live registers for each heap allocation
411%%  function. We base liveness of the number of register map at the
412%%  beginning of the instruction sequence.
413%%
414%%  A 'not_possible' term will be thrown if the set of live registers
415%%  is not continous at an allocation function (e.g. if {x,0} and {x,2}
416%%  are live, but not {x,1}).
417
418flt_liveness([{'%anno',{used,Regs}}=LiveInstr|Is]) ->
419    flt_liveness_1(Is, Regs, [LiveInstr]).
420
421flt_liveness_1([{set,Ds,Ss,{alloc,Live0,Alloc}}|Is], Regs0, Acc) ->
422    Live = min(Live0, live_regs(Regs0)),
423    I = {set,Ds,Ss,{alloc,Live,Alloc}},
424    Regs1 = init_regs(Live),
425    Regs = x_live(Ds, Regs1),
426    flt_liveness_1(Is, Regs, [I|Acc]);
427flt_liveness_1([{set,Ds,_,_}=I|Is], Regs0, Acc) ->
428    Regs = x_live(Ds, Regs0),
429    flt_liveness_1(Is, Regs, [I|Acc]);
430flt_liveness_1([{'%anno',_}], _Regs, Acc) ->
431    reverse(Acc).
432
433init_regs(Live) ->
434    (1 bsl Live) - 1.
435
436live_regs(Regs) ->
437    live_regs_1(Regs, 0).
438
439live_regs_1(0, N) -> N;
440live_regs_1(R, N) ->
441    case R band 1 of
442	0 -> throw(not_possible);
443	1 -> live_regs_1(R bsr 1, N+1)
444    end.
445
446x_live([{x,N}|Rs], Regs) -> x_live(Rs, Regs bor (1 bsl N));
447x_live([_|Rs], Regs) -> x_live(Rs, Regs);
448x_live([], Regs) -> Regs.
449
450%% update(Instruction, TypeDb) -> NewTypeDb
451%%  Update the type database to account for executing an instruction.
452%%
453%%  First the cases for instructions inside basic blocks.
454update({'%anno',_}, Ts) ->
455    Ts;
456update({set,[D],[S],move}, Ts) ->
457    tdb_copy(S, D, Ts);
458update({set,[D],[Index,Reg],{bif,element,_}}, Ts0) ->
459    MinSize = case Index of
460                  {integer,I} -> I;
461                  _ -> 0
462              end,
463    Ts = tdb_meet(Reg, {tuple,min_size,MinSize,[]}, Ts0),
464    tdb_store(D, any, Ts);
465update({set,[D],[_Key,Map],{bif,map_get,_}}, Ts0) ->
466    Ts = tdb_meet(Map, map, Ts0),
467    tdb_store(D, any, Ts);
468update({set,[D],Args,{bif,N,_}}, Ts) ->
469    Ar = length(Args),
470    BoolOp = erl_internal:new_type_test(N, Ar) orelse
471	erl_internal:comp_op(N, Ar) orelse
472	erl_internal:bool_op(N, Ar),
473    Type = case BoolOp of
474               true -> boolean;
475               false -> unary_op_type(N)
476           end,
477    tdb_store(D, Type, Ts);
478update({set,[D],[S],{get_tuple_element,0}}, Ts0) ->
479    if
480        D =:= S ->
481            tdb_store(D, any, Ts0);
482        true ->
483            Ts = tdb_store(D, {tuple_element,S,0}, Ts0),
484            tdb_store(S, {tuple,min_size,1,[]}, Ts)
485    end;
486update({set,[D],[S],{alloc,_,{gc_bif,float,{f,0}}}}, Ts0) ->
487    %% Make sure we reject non-numeric literal argument.
488    case possibly_numeric(S) of
489        true ->  tdb_store(D, float, Ts0);
490        false -> Ts0
491    end;
492update({set,[D],[S1,S2],{alloc,_,{gc_bif,'band',{f,0}}}}, Ts) ->
493    Type = band_type(S1, S2, Ts),
494    tdb_store(D, Type, Ts);
495update({set,[D],[S1,S2],{alloc,_,{gc_bif,'/',{f,0}}}}, Ts) ->
496    %% Make sure we reject non-numeric literals.
497    case possibly_numeric(S1) andalso possibly_numeric(S2) of
498        true -> tdb_store(D, float, Ts);
499        false -> Ts
500    end;
501update({set,[D],[S1,S2],{alloc,_,{gc_bif,Op,{f,0}}}}, Ts0) ->
502    case op_type(Op) of
503	integer ->
504	    tdb_store(D, integer, Ts0);
505        {float,_} ->
506            case {tdb_find(S1, Ts0),tdb_find(S2, Ts0)} of
507                {float,_} -> tdb_store(D, float, Ts0);
508                {_,float} -> tdb_store(D, float, Ts0);
509                {_,_} -> tdb_store(D, any, Ts0)
510            end;
511        Type ->
512            tdb_store(D, Type, Ts0)
513    end;
514update({set,[D],[_],{alloc,_,{gc_bif,Op,{f,0}}}}, Ts) ->
515    tdb_store(D, unary_op_type(Op), Ts);
516update({set,[],_Src,_Op}, Ts) ->
517    Ts;
518update({set,[D],_Src,_Op}, Ts) ->
519    tdb_store(D, any, Ts);
520update({kill,D}, Ts) ->
521    tdb_store(D, any, Ts);
522
523%% Instructions outside of blocks.
524update({test,test_arity,_Fail,[Src,Arity]}, Ts) ->
525    tdb_meet(Src, {tuple,exact_size,Arity,[]}, Ts);
526update({get_map_elements,_,Src,{list,Elems0}}, Ts0) ->
527    Ts1 = tdb_meet(Src, map, Ts0),
528    {_Ss,Ds} = beam_utils:split_even(Elems0),
529    foldl(fun(Dst, A) -> tdb_store(Dst, any, A) end, Ts1, Ds);
530update({test,is_eq_exact,_,[Reg,{atom,_}=Atom]}, Ts0) ->
531    Ts = case tdb_find_source_tuple(Reg, Ts0) of
532             {source_tuple,TupleReg} ->
533                 tdb_meet(TupleReg, {tuple,min_size,1,[Atom]}, Ts0);
534             none ->
535                 Ts0
536         end,
537    tdb_meet(Reg, Atom, Ts);
538update({test,is_record,_Fail,[Src,Tag,{integer,Arity}]}, Ts) ->
539    tdb_meet(Src, {tuple,exact_size,Arity,[Tag]}, Ts);
540
541%% Binaries and binary matching.
542
543update({test,bs_get_integer2,_,_,Args,Dst}, Ts) ->
544    tdb_store(Dst, get_bs_integer_type(Args), Ts);
545update({test,bs_get_utf8,_,_,_,Dst}, Ts) ->
546    tdb_store(Dst, ?UNICODE_INT, Ts);
547update({test,bs_get_utf16,_,_,_,Dst}, Ts) ->
548    tdb_store(Dst, ?UNICODE_INT, Ts);
549update({test,bs_get_utf32,_,_,_,Dst}, Ts) ->
550    tdb_store(Dst, ?UNICODE_INT, Ts);
551update({bs_init,_,{bs_init2,_,_},_,_,Dst}, Ts) ->
552    tdb_store(Dst, {binary,8}, Ts);
553update({bs_init,_,_,_,_,Dst}, Ts) ->
554    tdb_store(Dst, {binary,1}, Ts);
555update({bs_put,_,_,_}, Ts) ->
556    Ts;
557update({bs_save2,_,_}, Ts) ->
558    Ts;
559update({bs_restore2,_,_}, Ts) ->
560    Ts;
561update({bs_context_to_binary,Dst}, Ts) ->
562    tdb_store(Dst, any, Ts);
563update({test,bs_start_match2,_,_,[Src,_],Dst}, Ts0) ->
564    Ts = tdb_meet(Src, {binary,1}, Ts0),
565    tdb_copy(Src, Dst, Ts);
566update({test,bs_get_binary2,_,_,[_,_,Unit,_],Dst}, Ts) ->
567    true = is_integer(Unit),                    %Assertion.
568    tdb_store(Dst, {binary,Unit}, Ts);
569update({test,bs_get_float2,_,_,_,Dst}, Ts) ->
570    tdb_store(Dst, float, Ts);
571update({test,bs_test_unit,_,[Src,Unit]}, Ts) ->
572    tdb_meet(Src, {binary,Unit}, Ts);
573
574%% Other test instructions
575update({test,Test,_Fail,[Src]}, Ts) ->
576    Type = case Test of
577               is_binary -> {binary,8};
578               is_bitstr -> {binary,1};
579               is_boolean -> boolean;
580               is_float -> float;
581               is_integer -> integer;
582               is_map -> map;
583               is_nonempty_list -> nonempty_list;
584               _ -> any
585           end,
586    tdb_meet(Src, Type, Ts);
587update({test,_Test,_Fail,_Other}, Ts) ->
588    Ts;
589
590%% Calls
591
592update({call_ext,Ar,{extfunc,math,Math,Ar}}, Ts) ->
593    case is_math_bif(Math, Ar) of
594	true -> tdb_store({x,0}, float, Ts);
595	false -> tdb_kill_xregs(Ts)
596    end;
597update({call_ext,3,{extfunc,erlang,setelement,3}}, Ts0) ->
598    Ts = tdb_kill_xregs(Ts0),
599    case tdb_find({x,1}, Ts0) of
600	{tuple,SzKind,Sz,_}=T0 ->
601	    T = case tdb_find({x,0}, Ts0) of
602		    {integer,{I,I}} when I > 1 ->
603			%% First element is not changed. The result
604			%% will have the same type.
605			T0;
606		    _ ->
607			%% Position is 1 or unknown. May change the
608			%% first element of the tuple.
609			{tuple,SzKind,Sz,[]}
610		end,
611            tdb_store({x,0}, T, Ts);
612	_ ->
613	    Ts
614    end;
615update({call,_Arity,_Func}, Ts) -> tdb_kill_xregs(Ts);
616update({call_ext,_Arity,_Func}, Ts) -> tdb_kill_xregs(Ts);
617update({make_fun2,_,_,_,_}, Ts) -> tdb_kill_xregs(Ts);
618update({call_fun, _}, Ts) -> tdb_kill_xregs(Ts);
619update({apply, _}, Ts) -> tdb_kill_xregs(Ts);
620
621update({line,_}, Ts) -> Ts;
622update({'%',_}, Ts) -> Ts;
623
624%% The instruction is unknown.  Kill all information.
625update(_I, _Ts) -> tdb_new().
626
627band_type({integer,Int}, Other, Ts) ->
628    band_type_1(Int, Other, Ts);
629band_type(Other, {integer,Int}, Ts) ->
630    band_type_1(Int, Other, Ts);
631band_type(_, _, _) -> integer.
632
633band_type_1(Int, OtherSrc, Ts) ->
634    Type = band_type_2(Int, 0),
635    OtherType = tdb_find(OtherSrc, Ts),
636    meet(Type, OtherType).
637
638band_type_2(N, Bits) when Bits < 64 ->
639    case 1 bsl Bits of
640	P when P =:= N + 1 ->
641	    {integer,{0,N}};
642	P when P > N + 1 ->
643	    integer;
644	_ ->
645	    band_type_2(N, Bits+1)
646    end;
647band_type_2(_, _) ->
648    %% Negative or large positive number. Give up.
649    integer.
650
651get_bs_integer_type([_,{integer,N},U,{field_flags,Fl}])
652  when N*U < 64 ->
653    NumBits = N*U,
654    case member(unsigned, Fl) of
655	true ->
656	    {integer,{0,(1 bsl NumBits)-1}};
657	false ->
658	    %% Signed integer. Don't bother.
659	    integer
660    end;
661get_bs_integer_type(_) ->
662    %% Avoid creating ranges with a huge upper limit.
663    integer.
664
665is_math_bif(cos, 1) -> true;
666is_math_bif(cosh, 1) -> true;
667is_math_bif(sin, 1) -> true;
668is_math_bif(sinh, 1) -> true;
669is_math_bif(tan, 1) -> true;
670is_math_bif(tanh, 1) -> true;
671is_math_bif(acos, 1) -> true;
672is_math_bif(acosh, 1) -> true;
673is_math_bif(asin, 1) -> true;
674is_math_bif(asinh, 1) -> true;
675is_math_bif(atan, 1) -> true;
676is_math_bif(atanh, 1) -> true;
677is_math_bif(erf, 1) -> true;
678is_math_bif(erfc, 1) -> true;
679is_math_bif(exp, 1) -> true;
680is_math_bif(log, 1) -> true;
681is_math_bif(log2, 1) -> true;
682is_math_bif(log10, 1) -> true;
683is_math_bif(sqrt, 1) -> true;
684is_math_bif(atan2, 2) -> true;
685is_math_bif(pow, 2) -> true;
686is_math_bif(ceil, 1) -> true;
687is_math_bif(floor, 1) -> true;
688is_math_bif(fmod, 2) -> true;
689is_math_bif(pi, 0) -> true;
690is_math_bif(_, _) -> false.
691
692%% Reject non-numeric literals.
693possibly_numeric({x,_}) -> true;
694possibly_numeric({y,_}) -> true;
695possibly_numeric({integer,_}) -> true;
696possibly_numeric({float,_}) -> true;
697possibly_numeric(_) -> false.
698
699max_tuple_size(Reg, Ts) ->
700    case tdb_find(Reg, Ts) of
701	{tuple,_,Sz,_} -> Sz;
702	_Other -> 0
703    end.
704
705float_op('/', A, B, _) ->
706    case possibly_numeric(A) andalso possibly_numeric(B) of
707	true -> {yes,fdiv};
708	false -> no
709    end;
710float_op(Op, {float,_}, B, _) ->
711    case possibly_numeric(B) of
712	true -> arith_op(Op);
713	false -> no
714    end;
715float_op(Op, A, {float,_}, _) ->
716    case possibly_numeric(A) of
717	true -> arith_op(Op);
718	false -> no
719    end;
720float_op(Op, A, B, Ts) ->
721    case {tdb_find(A, Ts),tdb_find(B, Ts)} of
722	{float,_} -> arith_op(Op);
723	{_,float} -> arith_op(Op);
724	{_,_} -> no
725    end.
726
727find_dest(V, Rs0) ->
728    case find_reg(V, Rs0) of
729	{ok,FR} ->
730	    {FR,mark(V, Rs0, dirty)};
731	error ->
732	    Rs = put_reg(V, Rs0, dirty),
733	    {ok,FR} = find_reg(V, Rs),
734	    {FR,Rs}
735    end.
736
737load_reg({float,_}=F, _, Rs0, Is0) ->
738    Rs = put_reg(F, Rs0, clean),
739    {ok,FR} = find_reg(F, Rs),
740    Is = [{set,[FR],[F],fmove}|Is0],
741    {Rs,Is};
742load_reg(V, Ts, Rs0, Is0) ->
743    case find_reg(V, Rs0) of
744	{ok,_FR} -> {Rs0,Is0};
745	error ->
746	    Rs = put_reg(V, Rs0, clean),
747	    {ok,FR} = find_reg(V, Rs),
748	    Op = case tdb_find(V, Ts) of
749		     float -> fmove;
750		     _ -> fconv
751		 end,
752	    Is = [{set,[FR],[V],Op}|Is0],
753	    {Rs,Is}
754    end.
755
756arith_op(Op) ->
757    case op_type(Op) of
758	{float,Instr} -> {yes,Instr};
759	_ -> no
760    end.
761
762op_type('+') -> {float,fadd};
763op_type('-') -> {float,fsub};
764op_type('*') -> {float,fmul};
765%% '/' and 'band' are specially handled.
766op_type('bor') -> integer;
767op_type('bxor') -> integer;
768op_type('bsl') -> integer;
769op_type('bsr') -> integer;
770op_type('div') -> integer;
771op_type(_) -> any.
772
773unary_op_type(bit_size) -> integer;
774unary_op_type(byte_size) -> integer;
775unary_op_type(length) -> integer;
776unary_op_type(map_size) -> integer;
777unary_op_type(size) -> integer;
778unary_op_type(tuple_size) -> integer;
779unary_op_type(_) -> any.
780
781flush(Rs, [{set,[_],[_,_,_],{bif,is_record,_}}|_]=Is0, Acc0) ->
782    Acc = flush_all(Rs, Is0, Acc0),
783    {[],Acc};
784flush(Rs, [{set,[_],[],{put_tuple,_}}|_]=Is0, Acc0) ->
785    Acc = flush_all(Rs, Is0, Acc0),
786    {[],Acc};
787flush(Rs0, [{set,Ds,Ss,_Op}|_], Acc0) ->
788    Save = cerl_sets:from_list(Ss),
789    Acc = save_regs(Rs0, Save, Acc0),
790    Rs1 = foldl(fun(S, A) -> mark(S, A, clean) end, Rs0, Ss),
791    Kill = cerl_sets:from_list(Ds),
792    Rs = kill_regs(Rs1, Kill),
793    {Rs,Acc};
794flush(Rs0, Is, Acc0) ->
795    Acc = flush_all(Rs0, Is, Acc0),
796    {[],Acc}.
797
798flush_all([{_,{float,_},_}|Rs], Is, Acc) ->
799    flush_all(Rs, Is, Acc);
800flush_all([{I,V,dirty}|Rs], Is, Acc0) ->
801    Acc = checkerror(Acc0),
802    case beam_utils:is_killed_block(V, Is) of
803	true  -> flush_all(Rs, Is, Acc);
804	false -> flush_all(Rs, Is, [{set,[V],[{fr,I}],fmove}|Acc])
805    end;
806flush_all([{_,_,clean}|Rs], Is, Acc) -> flush_all(Rs, Is, Acc);
807flush_all([free|Rs], Is, Acc) -> flush_all(Rs, Is, Acc);
808flush_all([], _, Acc) -> Acc.
809
810save_regs(Rs, Save, Acc) ->
811    foldl(fun(R, A) -> save_reg(R, Save, A) end, Acc, Rs).
812
813save_reg({I,V,dirty}, Save, Acc) ->
814    case cerl_sets:is_element(V, Save) of
815	true -> [{set,[V],[{fr,I}],fmove}|checkerror(Acc)];
816	false -> Acc
817    end;
818save_reg(_, _, Acc) -> Acc.
819
820kill_regs(Rs, Kill) ->
821    [kill_reg(R, Kill) || R <- Rs].
822
823kill_reg({_,V,_}=R, Kill) ->
824    case cerl_sets:is_element(V, Kill) of
825	true -> free;
826	false -> R
827    end;
828kill_reg(R, _) -> R.
829
830mark(V, [{I,V,_}|Rs], Mark) -> [{I,V,Mark}|Rs];
831mark(V, [R|Rs], Mark) -> [R|mark(V, Rs, Mark)];
832mark(_, [], _) -> [].
833
834fetch_reg(V, [{I,V,_}|_]) -> {fr,I};
835fetch_reg(V, [_|SRs]) -> fetch_reg(V, SRs).
836
837find_reg(V, [{I,V,_}|_]) -> {ok,{fr,I}};
838find_reg(V, [_|SRs]) -> find_reg(V, SRs);
839find_reg(_, []) -> error.
840
841put_reg(V, Rs, Dirty) -> put_reg_1(V, Rs, Dirty, 0).
842
843put_reg_1(V, [free|Rs], Dirty, I) -> [{I,V,Dirty}|Rs];
844put_reg_1(V, [R|Rs], Dirty, I) -> [R|put_reg_1(V, Rs, Dirty, I+1)];
845put_reg_1(V, [], Dirty, I) -> [{I,V,Dirty}].
846
847checkerror(Is) ->
848    checkerror_1(Is, Is).
849
850checkerror_1([{set,[],[],fcheckerror}|_], OrigIs) -> OrigIs;
851checkerror_1([{set,_,_,{bif,fadd,_}}|_], OrigIs) -> checkerror_2(OrigIs);
852checkerror_1([{set,_,_,{bif,fsub,_}}|_], OrigIs) -> checkerror_2(OrigIs);
853checkerror_1([{set,_,_,{bif,fmul,_}}|_], OrigIs) -> checkerror_2(OrigIs);
854checkerror_1([{set,_,_,{bif,fdiv,_}}|_], OrigIs) -> checkerror_2(OrigIs);
855checkerror_1([{set,_,_,{bif,fnegate,_}}|_], OrigIs) -> checkerror_2(OrigIs);
856checkerror_1([_|Is], OrigIs) -> checkerror_1(Is, OrigIs);
857checkerror_1([], OrigIs) -> OrigIs.
858
859checkerror_2(OrigIs) -> [{set,[],[],fcheckerror}|OrigIs].
860
861
862%%% Routines for maintaining a type database.  The type database
863%%% associates type information with registers.
864%%%
865%%% See the comment for verified_type/1 at the end of module for
866%%% a description of the possible types.
867
868%% tdb_new() -> EmptyDataBase
869%%  Creates a new, empty type database.
870
871tdb_new() -> [].
872
873%% tdb_find(Register, Db) -> Type
874%%  Returns type information or the atom error if there is no type
875%%  information available for Register.
876%%
877%%  See the comment for verified_type/1 at the end of module for
878%%  a description of the possible types.
879
880tdb_find(Reg, Ts) ->
881    case tdb_find_raw(Reg, Ts) of
882        {tuple_element,_,_} -> any;
883        Type -> Type
884    end.
885
886%% tdb_find_source_tuple(Register, Ts) -> {source_tuple,Register} | 'none'.
887%%  Find the tuple whose first element was fetched to the register Register.
888
889tdb_find_source_tuple(Reg, Ts) ->
890    case tdb_find_raw(Reg, Ts) of
891        {tuple_element,Src,0} ->
892            {source_tuple,Src};
893        _ ->
894            none
895    end.
896
897%% tdb_copy(Source, Dest, Db) -> Db'
898%%  Update the type information for Dest to have the same type
899%%  as the Source.
900
901tdb_copy({Tag,_}=S, D, Ts) when Tag =:= x; Tag =:= y ->
902    case tdb_find_raw(S, Ts) of
903        any -> orddict:erase(D, Ts);
904        Type -> orddict:store(D, Type, Ts)
905    end;
906tdb_copy(Literal, D, Ts) ->
907    Type = case Literal of
908	       {atom,_} -> Literal;
909	       {float,_} -> float;
910	       {integer,Int} -> {integer,{Int,Int}};
911	       {literal,[_|_]} -> nonempty_list;
912	       {literal,#{}} -> map;
913	       {literal,Tuple} when tuple_size(Tuple) >= 1 ->
914		   Lit = tag_literal(element(1, Tuple)),
915		   {tuple,exact_size,tuple_size(Tuple),[Lit]};
916	       _ -> any
917	   end,
918    tdb_store(D, verified_type(Type), Ts).
919
920%% tdb_store(Register, Type, Ts0) -> Ts.
921%%  Store a new type for register Register. Return the update type
922%%  database. Use this function when a new value is assigned to
923%%  a register.
924%%
925%%  See the comment for verified_type/1 at the end of module for
926%%  a description of the possible types.
927
928tdb_store(Reg, any, Ts) ->
929    erase(Reg, Ts);
930tdb_store(Reg, Type, Ts) ->
931    store(Reg, verified_type(Type), Ts).
932
933store(Key, New, [{K,_}|_]=Dict) when Key < K ->
934    [{Key,New}|Dict];
935store(Key, New, [{K,Val}=E|Dict]) when Key > K ->
936    case Val of
937        {tuple_element,Key,_} -> store(Key, New, Dict);
938        _ -> [E|store(Key, New, Dict)]
939    end;
940store(Key, New, [{_K,Old}|Dict]) ->		%Key == K
941    case Old of
942        {tuple,_,_,_} ->
943            [{Key,New}|erase_tuple_element(Key, Dict)];
944        _ ->
945            [{Key,New}|Dict]
946    end;
947store(Key, New, []) -> [{Key,New}].
948
949erase(Key, [{K,_}=E|Dict]) when Key < K ->
950    [E|Dict];
951erase(Key, [{K,Val}=E|Dict]) when Key > K ->
952    case Val of
953        {tuple_element,Key,_} -> erase(Key, Dict);
954        _ -> [E|erase(Key, Dict)]
955    end;
956erase(Key, [{_K,Val}|Dict]) ->                 %Key == K
957    case Val of
958        {tuple,_,_,_} -> erase_tuple_element(Key, Dict);
959        _ -> Dict
960    end;
961erase(_, []) -> [].
962
963erase_tuple_element(Key, [{_,{tuple_element,Key,_}}|Dict]) ->
964    erase_tuple_element(Key, Dict);
965erase_tuple_element(Key, [E|Dict]) ->
966    [E|erase_tuple_element(Key, Dict)];
967erase_tuple_element(_Key, []) -> [].
968
969%% tdb_meet(Register, Type, Ts0) -> Ts.
970%%  Update information of a register that is used as the source for an
971%%  instruction. The type Type will be combined using the meet operation
972%%  with the previous type information for the register, resulting in
973%%  narrower (more specific) type.
974%%
975%%  For example, if the previous type is {tuple,min_size,2,[]} and the
976%%  the new type is {tuple,exact_size,5,[]}, the meet of the types will
977%%  be {tuple,exact_size,5,[]}.
978%%
979%%  See the comment for verified_type/1 at the end of module for
980%%  a description of the possible types.
981
982tdb_meet(Reg, NewType, Ts) ->
983    Update = fun(Type0) -> meet(Type0, NewType) end,
984    orddict:update(Reg, Update, NewType, Ts).
985
986%%%
987%%% Here follows internal helper functions for accessing and
988%%% updating the type database.
989%%%
990
991tdb_find_raw({x,_}=K, Ts) -> tdb_find_raw_1(K, Ts);
992tdb_find_raw({y,_}=K, Ts) -> tdb_find_raw_1(K, Ts);
993tdb_find_raw(_, _) -> any.
994
995tdb_find_raw_1(K, Ts) ->
996    case orddict:find(K, Ts) of
997	{ok,Val} -> Val;
998	error -> any
999    end.
1000
1001tag_literal(A) when is_atom(A) -> {atom,A};
1002tag_literal(F) when is_float(F) -> {float,F};
1003tag_literal(I) when is_integer(I) -> {integer,I};
1004tag_literal([]) -> nil;
1005tag_literal(Lit) -> {literal,Lit}.
1006
1007%% tdb_kill_xregs(Db) -> NewDb
1008%%  Kill all information about x registers. Also kill all tuple_element
1009%%  dependencies from y registers to x registers.
1010
1011tdb_kill_xregs([{{x,_},_Type}|Db]) -> tdb_kill_xregs(Db);
1012tdb_kill_xregs([{{y,_},{tuple_element,{x,_},_}}|Db]) -> tdb_kill_xregs(Db);
1013tdb_kill_xregs([Any|Db]) -> [Any|tdb_kill_xregs(Db)];
1014tdb_kill_xregs([]) -> [].
1015
1016%% meet(Type1, Type2) -> Type
1017%%  Returns the "meet" of Type1 and Type2. The meet is a narrower
1018%%  type than Type1 and Type2. For example:
1019%%
1020%%     meet(integer, {integer,{0,3}}) -> {integer,{0,3}}
1021%%
1022%%  The meet for two different types result in 'none', which is
1023%%  the bottom element for our type lattice:
1024%%
1025%%     meet(integer, map) -> none
1026
1027meet(T, T) ->
1028    T;
1029meet({integer,_}=T, integer) ->
1030    T;
1031meet(integer, {integer,_}=T) ->
1032    T;
1033meet({integer,{Min1,Max1}}, {integer,{Min2,Max2}}) ->
1034    {integer,{max(Min1, Min2),min(Max1, Max2)}};
1035meet({tuple,min_size,Sz1,Same}, {tuple,min_size,Sz2,Same}=Max) when Sz1 < Sz2 ->
1036    Max;
1037meet({tuple,min_size,Sz1,Same}=Max, {tuple,min_size,Sz2,Same}) when Sz1 > Sz2 ->
1038    Max;
1039meet({tuple,exact_size,_,Same}=Exact, {tuple,_,_,Same}) ->
1040    Exact;
1041meet({tuple,_,_,Same},{tuple,exact_size,_,Same}=Exact) ->
1042    Exact;
1043meet({tuple,SzKind1,Sz1,[]}, {tuple,_SzKind2,_Sz2,First}=Tuple2) ->
1044    meet({tuple,SzKind1,Sz1,First}, Tuple2);
1045meet({tuple,_SzKind1,_Sz1,First}=Tuple1, {tuple,SzKind2,Sz2,_}) ->
1046    meet(Tuple1, {tuple,SzKind2,Sz2,First});
1047meet({binary,U1}, {binary,U2}) ->
1048    {binary,max(U1, U2)};
1049meet(T1, T2) ->
1050    case is_any(T1) of
1051        true ->
1052            verified_type(T2);
1053        false ->
1054            case is_any(T2) of
1055                true ->
1056                    verified_type(T1);
1057                false ->
1058                    none                        %The bottom element.
1059            end
1060    end.
1061
1062is_any(any) -> true;
1063is_any({tuple_element,_,_}) -> true;
1064is_any(_) -> false.
1065
1066%% verified_type(Type) -> Type
1067%%  Returns the passed in type if it is one of the defined types.
1068%%  Crashes if there is anything wrong with the type.
1069%%
1070%%  Here are all possible types:
1071%%
1072%%  any                  Any Erlang term (top element for the type lattice).
1073%%
1074%%  {atom,Atom}          The specific atom Atom.
1075%%  {binary,Unit}        Binary/bitstring aligned to unit Unit.
1076%%  boolean              'true' | 'false'
1077%%  float                Floating point number.
1078%%  integer              Integer.
1079%%  {integer,{Min,Max}}  Integer in the inclusive range Min through Max.
1080%%  map                  Map.
1081%%  nonempty_list        Nonempty list.
1082%%  {tuple,_,_,_}        Tuple (see below).
1083%%
1084%%  none                 No type (bottom element for the type lattice).
1085%%
1086%%  {tuple,min_size,Size,First} means that the corresponding register
1087%%  contains a tuple with *at least* Size elements (conversely,
1088%%  {tuple,exact_size,Size,First} means that it contains a tuple with
1089%%  *exactly* Size elements). An tuple with unknown size is
1090%%  represented as {tuple,min_size,0,[]}. First is either [] (meaning
1091%%  that the tuple's first element is unknown) or [FirstElement] (the
1092%%  contents of the first element).
1093%%
1094%%  There is also a pseudo-type called {tuple_element,_,_}:
1095%%
1096%%    {tuple_element,SrcTuple,ElementNumber}
1097%%
1098%%  that does not provide any information about the type of the
1099%%  register itself, but provides a link back to the source tuple that
1100%%  the register got its value from.
1101%%
1102%%  Note that {tuple_element,_,_} will *never* be returned by tdb_find/2.
1103%%  Use tdb_find_source_tuple/2 to locate the source tuple for a register.
1104
1105verified_type(any=T) -> T;
1106verified_type({atom,_}=T) -> T;
1107verified_type({binary,U}=T) when is_integer(U) -> T;
1108verified_type(boolean=T) -> T;
1109verified_type(integer=T) -> T;
1110verified_type({integer,{Min,Max}}=T)
1111  when is_integer(Min), is_integer(Max) -> T;
1112verified_type(map=T) -> T;
1113verified_type(nonempty_list=T) -> T;
1114verified_type({tuple,_,Sz,[]}=T) when is_integer(Sz) -> T;
1115verified_type({tuple,_,Sz,[_]}=T) when is_integer(Sz) -> T;
1116verified_type({tuple_element,_,_}=T) -> T;
1117verified_type(float=T) -> T;
1118verified_type(none=T) -> T.
1119