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