1%% -*- erlang-indent-level: 2 -*- 2%% 3%% Licensed under the Apache License, Version 2.0 (the "License"); 4%% you may not use this file except in compliance with the License. 5%% You may obtain a copy of the License at 6%% 7%% http://www.apache.org/licenses/LICENSE-2.0 8%% 9%% Unless required by applicable law or agreed to in writing, software 10%% distributed under the License is distributed on an "AS IS" BASIS, 11%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12%% See the License for the specific language governing permissions and 13%% limitations under the License. 14%% 15%%%-------------------------------------------------------------------- 16%%% File : hipe_icode_type.erl 17%%% Author : Tobias Lindahl <Tobias.Lindahl@it.uu.se> 18%%% Description : Propagate type information. 19%%% 20%%% Created : 25 Feb 2003 by Tobias Lindahl <Tobias.Lindahl@it.uu.se> 21%%%-------------------------------------------------------------------- 22 23-module(hipe_icode_type). 24 25-export([cfg/4, unannotate_cfg/1, specialize/1]). 26 27%%===================================================================== 28%% Icode Coordinator Callbacks 29%%===================================================================== 30 31-export([replace_nones/1, 32 update__info/2, new__info/1, return__info/1, 33 return_none/0, return_none_args/2, return_any_args/2]). 34 35%%===================================================================== 36 37-include("../main/hipe.hrl"). 38-include("hipe_icode.hrl"). 39-include("hipe_icode_primops.hrl"). 40-include("hipe_icode_type.hrl"). 41-include("../flow/cfg.hrl"). 42 43-type args_fun() :: fun((mfa(), cfg()) -> [erl_types:erl_type()]). 44-type call_fun() :: fun((mfa(), [_]) -> erl_types:erl_type()). 45-type final_fun() :: fun((mfa(), [_]) -> 'ok'). 46-type data() :: {mfa(), args_fun(), call_fun(), final_fun()}. 47 48%-define(DO_HIPE_ICODE_TYPE_TEST, false). 49 50-ifdef(DO_HIPE_ICODE_TYPE_TEST). 51-export([test/0]). 52-endif. 53 54-define(MFA_debug, fun(_, _, _) -> ok end). 55 56%-define(debug, fun(X, Y) -> io:format("~s ~p~n", [X, Y]) end). 57-define(debug, fun(_, _) -> ok end). 58 59%-define(flow_debug, fun(X, Y) -> io:format("flow: ~s ~p~n", [X, Y]) end). 60-define(flow_debug, fun(_, _) -> ok end). 61 62%-define(widening_debug, fun(X, Y) -> io:format("wid: ~s ~p~n", [X, Y]) end). 63-define(widening_debug, fun(_, _) -> ok end). 64 65%-define(call_debug, fun(X, Y) -> io:format("call: ~s ~p~n", [X, Y]) end). 66-define(call_debug, fun(_, _) -> ok end). 67 68%-define(ineq_debug, fun(X, Y) -> io:format("ineq: ~s ~p~n", [X, Y]) end). 69-define(ineq_debug, fun(_, _) -> ok end). 70 71%-define(server_debug, fun(X, Y) -> io:format("~p server: ~s ~p~n", [self(), X, Y]) end). 72-define(server_debug, fun(_, _) -> ok end). 73 74-import(erl_types, [number_min/1, number_max/1, 75 t_any/0, t_atom/1, t_atom/0, t_atom_vals/1, 76 t_binary/0, t_bitstr/0, t_bitstr_base/1, t_bitstr_unit/1, 77 t_boolean/0, t_cons/0, 78 t_float/0, t_from_term/1, t_from_range/2, 79 t_fun/0, t_fun/1, t_fun/2, t_fun_args/1, t_fun_arity/1, 80 t_inf/2, t_inf_lists/2, t_integer/0, 81 t_integer/1, t_is_atom/1, t_is_any/1, 82 t_is_binary/1, t_is_bitstr/1, t_is_bitwidth/1, 83 t_is_boolean/1, t_is_fixnum/1, t_is_cons/1, t_is_map/1, 84 t_is_maybe_improper_list/1, t_is_equal/2, t_is_float/1, 85 t_is_fun/1, t_is_integer/1, t_is_non_neg_integer/1, 86 t_is_number/1, t_is_matchstate/1, 87 t_is_none/1, t_is_port/1, t_is_pid/1, 88 t_is_reference/1, t_is_subtype/2, t_is_tuple/1, 89 t_limit/2, t_matchstate_present/1, t_matchstate/0, 90 t_matchstate_slots/1, t_maybe_improper_list/0, t_map/0, 91 t_nil/0, t_none/0, t_number/0, t_number/1, t_number_vals/1, 92 t_pid/0, t_port/0, t_reference/0, t_subtract/2, t_sup/2, 93 t_to_tlist/1, t_tuple/0, t_tuple/1, t_tuple_sizes/1]). 94 95-record(state, {info_map = gb_trees:empty() :: gb_trees:tree(), 96 cfg :: cfg(), 97 liveness :: hipe_icode_ssa:liveness(), 98 arg_types :: [erl_types:erl_type()], 99 ret_type = [t_none()] :: [erl_types:erl_type()], 100 lookupfun :: call_fun(), 101 resultaction :: final_fun()}). 102-type state() :: #state{}. 103 104%%----------------------------------------------------------------------- 105%% The main exported function 106%%----------------------------------------------------------------------- 107 108-spec cfg(cfg(), mfa(), comp_options(), #comp_servers{}) -> cfg(). 109 110cfg(Cfg, MFA, Options, Servers) -> 111 case proplists:get_bool(concurrent_comp, Options) of 112 true -> 113 concurrent_cfg(Cfg, MFA, Servers#comp_servers.type); 114 false -> 115 ordinary_cfg(Cfg, MFA) 116 end. 117 118concurrent_cfg(Cfg, MFA, CompServer) -> 119 CompServer ! {ready, {MFA, self()}}, 120 {ArgsFun, CallFun, FinalFun} = do_analysis(Cfg, MFA), 121 Ans = do_rewrite(Cfg, MFA, ArgsFun, CallFun, FinalFun), 122 CompServer ! {done_rewrite, MFA}, 123 Ans. 124 125do_analysis(Cfg, MFA) -> 126 receive 127 {analyse, {ArgsFun,CallFun,FinalFun}} -> 128 analyse(Cfg, {MFA,ArgsFun,CallFun,FinalFun}), 129 do_analysis(Cfg, MFA); 130 {done, {_NewArgsFun,_NewCallFun,_NewFinalFun} = Done} -> 131 Done 132 end. 133 134do_rewrite(Cfg, MFA, ArgsFun, CallFun, FinalFun) -> 135 common_rewrite(Cfg, {MFA,ArgsFun,CallFun,FinalFun}). 136 137ordinary_cfg(Cfg, MFA) -> 138 Data = make_data(Cfg,MFA), 139 common_rewrite(Cfg, Data). 140 141common_rewrite(Cfg, Data) -> 142 State = safe_analyse(Cfg, Data), 143 NewState = simplify_controlflow(State), 144 NewCfg = state__cfg(annotate_cfg(NewState)), 145 hipe_icode_cfg:remove_unreachable_code(specialize(NewCfg)). 146 147make_data(Cfg, {_M,_F,A}=MFA) -> 148 NoArgs = 149 case hipe_icode_cfg:is_closure(Cfg) of 150 true -> hipe_icode_cfg:closure_arity(Cfg); 151 false -> A 152 end, 153 Args = lists:duplicate(NoArgs, t_any()), 154 ArgsFun = fun(_,_) -> Args end, 155 CallFun = fun(_,_) -> t_any() end, 156 FinalFun = fun(_,_) -> ok end, 157 {MFA,ArgsFun,CallFun,FinalFun}. 158 159%%debug_make_data(Cfg, {_M,_F,A}=MFA) -> 160%% NoArgs = 161%% case hipe_icode_cfg:is_closure(Cfg) of 162%% true -> hipe_icode_cfg:closure_arity(Cfg); 163%% false -> A 164%% end, 165%% Args = lists:duplicate(NoArgs, t_any()), 166%% ArgsFun = fun(MFA,_Cfg) -> io:format("Start:~p~n",[MFA]),Args end, 167%% CallFun = fun(MFA,Types) -> io:format("Call With:~p~nTo:~p~n",[Types,MFA]), t_any() end, 168%% FinalFun = fun(MFA,Type) -> io:format("ResType:~p~nFor:~p~n",[Type,MFA]),ok end, 169%% {MFA,ArgsFun,CallFun,FinalFun}. 170 171 172%%------------------------------------------------------------------- 173%% Global type analysis on the whole function. Demands that the code 174%% is in SSA form. When we encounter a phi node, the types of the 175%% arguments are joined. At the end of a block the information out is 176%% joined with the current information in for all _valid_ successors, 177%% that is, of all successors that actually can be reached. If the 178%% join produces new information in for the successor, this 179%% information is added to the worklist. 180%%------------------------------------------------------------------- 181 182-spec analyse(cfg(), data()) -> 'ok'. 183 184analyse(Cfg, Data) -> 185 try 186 #state{} = safe_analyse(Cfg, Data), 187 ok 188 catch throw:no_input -> ok % No need to do anything since we have no input 189 end. 190 191-spec safe_analyse(cfg(), data()) -> state(). 192 193safe_analyse(Cfg, {MFA,_,_,_}=Data) -> 194 State = new_state(Cfg, Data), 195 NewState = analyse_blocks(State,MFA), 196 (state__resultaction(NewState))(MFA,state__ret_type(NewState)), 197 NewState. 198 199analyse_blocks(State, MFA) -> 200 Work = init_work(State), 201 analyse_blocks(Work, State, MFA). 202 203analyse_blocks(Work, State, MFA) -> 204 case get_work(Work) of 205 fixpoint -> 206 State; 207 {Label, NewWork} -> 208 Info = state__info_in(State, Label), 209 {NewState, NewLabels} = 210 try analyse_block(Label, Info, State) 211 catch throw:none_type -> 212 %% io:format("received none type at label: ~p~n", [Label]), 213 {State,[]} 214 end, 215 NewWork2 = add_work(NewWork, NewLabels), 216 analyse_blocks(NewWork2, NewState, MFA) 217 end. 218 219analyse_block(Label, InfoIn, State) -> 220 BB = state__bb(State, Label), 221 Code = hipe_bb:butlast(BB), 222 Last = hipe_bb:last(BB), 223 InfoOut = analyse_insns(Code, InfoIn, state__lookupfun(State)), 224 NewState = state__info_out_update(State, Label, InfoOut), 225 case Last of 226 #icode_if{} -> 227 UpdateInfo = do_if(Last, InfoOut), 228 do_updates(NewState, UpdateInfo); 229 #icode_type{} -> 230 UpdateInfo = do_type(Last, InfoOut), 231 do_updates(NewState, UpdateInfo); 232 #icode_switch_tuple_arity{} -> 233 UpdateInfo = do_switch_tuple_arity(Last, InfoOut), 234 do_updates(NewState, UpdateInfo); 235 #icode_switch_val{} -> 236 UpdateInfo = do_switch_val(Last, InfoOut), 237 do_updates(NewState, UpdateInfo); 238 #icode_enter{} -> 239 NewState1 = do_enter(Last, InfoOut, NewState, state__lookupfun(NewState)), 240 do_updates(NewState1,[]); 241 #icode_call{} -> 242 {NewState1,UpdateInfo} = do_last_call(Last, InfoOut, NewState, Label), 243 do_updates(NewState1, UpdateInfo); 244 #icode_return{} -> 245 NewState1 = do_return(Last, InfoOut, NewState), 246 do_updates(NewState1,[]); 247 _ -> 248 UpdateInfo = [{X, InfoOut} || X <- state__succ(NewState, Label)], 249 do_updates(NewState, UpdateInfo) 250 end. 251 252analyse_insns([I|Insns], Info, LookupFun) -> 253 NewInfo = analyse_insn(I, Info, LookupFun), 254 analyse_insns(Insns, NewInfo, LookupFun); 255analyse_insns([], Info, _) -> 256 Info. 257 258analyse_insn(I, Info, LookupFun) -> 259 case I of 260 #icode_move{} -> 261 do_move(I, Info); 262 #icode_call{} -> 263 NewInfo = do_call(I, Info, LookupFun), 264 %% io:format("Analysing Call: ~w~n~w~n", [I, NewInfo]), 265 update_call_arguments(I, NewInfo); 266 #icode_phi{} -> 267 Type = t_limit(join_list(hipe_icode:args(I), Info), ?TYPE_DEPTH), 268 enter_defines(I, Type, Info); 269 #icode_begin_handler{} -> 270 enter_defines(I, t_any(), Info); 271 _ -> 272 %% Just an assert 273 case defines(I) of 274 [] -> Info; 275 _ -> exit({"Instruction with destination not analysed", I}) 276 end 277 end. 278 279do_move(I, Info) -> 280 %% Can't use uses/1 since we must keep constants. 281 [Src] = hipe_icode:args(I), 282 enter_defines(I, lookup(Src, Info), Info). 283 284do_basic_call(I, Info, LookupFun) -> 285 case hipe_icode:call_type(I) of 286 primop -> 287 Fun = hipe_icode:call_fun(I), 288 ArgTypes = lookup_list(hipe_icode:args(I), Info), 289 primop_type(Fun, ArgTypes); 290 remote -> 291 {M, F, A} = hipe_icode:call_fun(I), 292 ArgTypes = lookup_list(hipe_icode:args(I), Info), 293 None = t_none(), 294 case erl_bif_types:type(M, F, A, ArgTypes) of 295 None -> 296 NewArgTypes = add_funs_to_arg_types(ArgTypes), 297 erl_bif_types:type(M, F, A, NewArgTypes); 298 Other -> 299 Other 300 end; 301 local -> 302 MFA = hipe_icode:call_fun(I), 303 ArgTypes = lookup_list(hipe_icode:args(I), Info), 304 %% io:format("Call:~p~nTypes: ~p~n",[I,ArgTypes]), 305 LookupFun(MFA,ArgTypes) 306 end. 307 308do_call(I, Info, LookupFun) -> 309 RetType = do_basic_call(I, Info, LookupFun), 310 IsNone = t_is_none(RetType), 311 %% io:format("RetType ~p~nIsNone ~p~n~p~n",[RetType,IsNone,I]), 312 if IsNone -> throw(none_type); 313 true -> enter_defines(I, RetType, Info) 314 end. 315 316do_safe_call(I, Info, LookupFun) -> 317 RetType = do_basic_call(I, Info, LookupFun), 318 enter_defines(I, RetType, Info). 319 320do_last_call(Last, InfoOut, State, Label) -> 321 try 322 NewInfoOut = do_call(Last, InfoOut, state__lookupfun(State)), 323 NewState = state__info_out_update(State, Label, NewInfoOut), 324 ContInfo = update_call_arguments(Last, NewInfoOut), 325 Cont = hipe_icode:call_continuation(Last), 326 Fail = hipe_icode:call_fail_label(Last), 327 ?call_debug("Continfo, NewInfoOut", {ContInfo, NewInfoOut}), 328 UpdateInfo = 329 case Fail of 330 [] -> 331 [{Cont, ContInfo}]; 332 _ -> 333 case call_always_fails(Last, InfoOut) of 334 true -> 335 [{Fail, NewInfoOut}]; 336 false -> 337 Fun = hipe_icode:call_fun(Last), 338 case hipe_icode_primops:fails(Fun) of 339 true -> 340 [{Cont, ContInfo}, {Fail, NewInfoOut}]; 341 false -> 342 [{Cont, ContInfo}] 343 end 344 end 345 end, 346 {NewState,UpdateInfo} 347 catch throw:none_type -> 348 State2 = state__info_out_update(State, Label, InfoOut), 349 case hipe_icode:call_fail_label(Last) of 350 [] -> throw(none_type); 351 FailLbl -> 352 {State2,[{FailLbl, InfoOut}]} 353 end 354 end. 355 356call_always_fails(#icode_call{} = I, Info) -> 357 case hipe_icode:call_fun(I) of 358 %% These can actually be calls too. 359 {erlang, halt, 0} -> false; 360 {erlang, halt, 1} -> false; 361 {erlang, halt, 2} -> false; 362 {erlang, exit, 1} -> false; 363 {erlang, error, 1} -> false; 364 {erlang, error, 2} -> false; 365 {erlang, throw, 1} -> false; 366 {erlang, hibernate, 3} -> false; 367 Fun -> 368 case hipe_icode:call_type(I) of 369 primop -> 370 Args = safe_lookup_list(hipe_icode:call_args(I), Info), 371 ReturnType = primop_type(Fun, Args), 372 t_is_none(ReturnType); 373 _ -> false 374 end 375 end. 376 377do_enter(I, Info, State, LookupFun) -> 378 %% io:format("Enter:~p~n",[I]), 379 ArgTypes = lookup_list(hipe_icode:args(I), Info), 380 RetTypes = 381 case hipe_icode:enter_type(I) of 382 local -> 383 MFA = hipe_icode:enter_fun(I), 384 LookupFun(MFA,ArgTypes); 385 remote -> 386 {M, F, A} = hipe_icode:enter_fun(I), 387 None = t_none(), 388 case erl_bif_types:type(M, F, A, ArgTypes) of 389 None -> 390 NewArgTypes = add_funs_to_arg_types(ArgTypes), 391 erl_bif_types:type(M, F, A, NewArgTypes); 392 Other -> 393 Other 394 end; 395 primop -> 396 Fun = hipe_icode:enter_fun(I), 397 primop_type(Fun, ArgTypes) 398 end, 399 state__ret_type_update(State, RetTypes). 400 401do_return(I, Info, State) -> 402 RetTypes = lookup_list(hipe_icode:args(I), Info), 403 state__ret_type_update(State, RetTypes). 404 405do_if(I, Info) -> 406 %% XXX: Could probably do better than this. 407 TrueLab = hipe_icode:if_true_label(I), 408 FalseLab = hipe_icode:if_false_label(I), 409 case hipe_icode:if_args(I) of 410 [Arg1, Arg2] = Args -> 411 [Type1, Type2] = lookup_list(Args, Info), 412 case t_is_none(Type1) orelse t_is_none(Type2) of 413 true -> 414 [{TrueLab, Info}, {FalseLab, Info}]; 415 false -> 416 Inf = t_inf(Type1, Type2), 417 case hipe_icode:if_op(I) of 418 '=:='-> 419 case t_is_none(Inf) of 420 true -> 421 [{FalseLab, Info}]; 422 false -> 423 [{TrueLab, enter(Arg1, Inf, enter(Arg2, Inf, Info))}, 424 {FalseLab, Info}] 425 end; 426 '=/=' -> 427 case t_is_none(Inf) of 428 true -> 429 [{TrueLab, Info}]; 430 false -> 431 [{FalseLab, enter(Arg1, Inf, enter(Arg2, Inf, Info))}, 432 {TrueLab, Info}] 433 end; 434 '==' -> 435 [{TrueLab, Info}, {FalseLab, Info}]; 436 '/=' -> 437 [{TrueLab, Info}, {FalseLab, Info}]; 438 Op -> 439 integer_range_inequality_propagation(Op, Arg1, Arg2, 440 TrueLab, FalseLab, Info) 441 %%_ -> 442 %% [{TrueLab, Info}, {FalseLab, Info}] 443 end 444 end; 445 _ -> 446 %% Only care for binary if:s 447 [{TrueLab, Info}, {FalseLab, Info}] 448 end. 449 450integer_range_inequality_propagation(Op, A1, A2, TrueLab, FalseLab, Info) -> 451 Arg1 = lookup(A1, Info), 452 Arg2 = lookup(A2, Info), 453 ?ineq_debug("args", [Arg1,Arg2]), 454 IntArg1 = t_inf(Arg1, t_integer()), 455 IntArg2 = t_inf(Arg2, t_integer()), 456 NonIntArg1 = t_subtract(Arg1, t_integer()), 457 NonIntArg2 = t_subtract(Arg2, t_integer()), 458 ?ineq_debug("nonintargs", [NonIntArg1,NonIntArg2]), 459 case t_is_none(IntArg1) orelse t_is_none(IntArg2) of 460 true -> 461 ?ineq_debug("one is none", [IntArg1,IntArg2]), 462 [{TrueLab, Info}, {FalseLab, Info}]; 463 false -> 464 {TrueArg1, TrueArg2, FalseArg1, FalseArg2} = 465 case Op of 466 '>=' -> 467 {FA1, FA2, TA1, TA2} = int_range_lt_propagator(IntArg1, IntArg2), 468 {TA1, TA2, FA1, FA2}; 469 '>' -> 470 {TA2, TA1, FA2, FA1} = int_range_lt_propagator(IntArg2, IntArg1), 471 {TA1, TA2, FA1, FA2}; 472 '<' -> 473 int_range_lt_propagator(IntArg1, IntArg2); 474 '=<' -> 475 {FA2, FA1, TA2, TA1} = int_range_lt_propagator(IntArg2, IntArg1), 476 {TA1, TA2, FA1, FA2} 477 end, 478 ?ineq_debug("int res", [TrueArg1, TrueArg2, FalseArg1, FalseArg2]), 479 False = {FalseLab, enter(A1, t_sup(FalseArg1, NonIntArg1), 480 enter(A2, t_sup(FalseArg2, NonIntArg2), Info))}, 481 True = {TrueLab, enter(A1, t_sup(TrueArg1, NonIntArg1), 482 enter(A2, t_sup(TrueArg2, NonIntArg2), Info))}, 483 [True, False] 484 end. 485 486int_range_lt_propagator(IntArg1, IntArg2) -> 487 Min1 = number_min(IntArg1), 488 Max1 = number_max(IntArg1), 489 Min2 = number_min(IntArg2), 490 Max2 = number_max(IntArg2), 491 %% is this the same as erl_types:t_subtract?? no ... ?? 492 TrueMax1 = erl_types:min(Max1, erl_bif_types:infinity_add(Max2, -1)), 493 TrueMin2 = erl_types:max(erl_bif_types:infinity_add(Min1, 1), Min2), 494 FalseMin1 = erl_types:max(Min1, Min2), 495 FalseMax2 = erl_types:min(Max1, Max2), 496 {t_from_range(Min1, TrueMax1), 497 t_from_range(TrueMin2, Max2), 498 t_from_range(FalseMin1, Max1), 499 t_from_range(Min2, FalseMax2)}. 500 501do_type(I, Info) -> 502 case hipe_icode:args(I) of 503 [Var] -> do_type(I, Info, Var); 504 [Var1,Var2] -> do_type2(I, Info, Var1, Var2) 505 end. 506 507do_type2(I, Info, FunVar, ArityVar) -> % function2(Fun,Arity) 508 %% Just for sanity. 509 function2 = hipe_icode:type_test(I), 510 FunType = lookup(FunVar, Info), 511 ArityType = lookup(ArityVar, Info), 512 TrueLab = hipe_icode:type_true_label(I), 513 FalseLab = hipe_icode:type_false_label(I), 514 SuccType1 = t_inf(t_fun(), FunType), 515 case combine_test(test_type(function, FunType), 516 test_type(integer, ArityType)) of 517 true -> 518 case t_number_vals(ArityType) of 519 [Arity] -> 520 case t_fun_arity(SuccType1) of 521 unknown -> 522 SuccType = t_inf(t_fun(Arity,t_any()),FunType), 523 [{TrueLab, enter(FunVar, SuccType, Info)}, 524 {FalseLab, Info}]; 525 Arity when is_integer(Arity) -> 526 FalseType = t_subtract(FunType, t_fun(Arity, t_any())), 527 [{TrueLab, enter(FunVar, SuccType1, Info)}, 528 {FalseLab, enter(FunVar, FalseType, Info)}] 529 end; 530 _ -> 531 case t_fun_arity(SuccType1) of 532 unknown -> 533 [{TrueLab, enter(FunVar,SuccType1,Info)}, 534 {FalseLab, Info}]; 535 Arity when is_integer(Arity) -> 536 T = t_from_term(Arity), 537 NewInfo = enter(ArityVar, T, Info), 538 [{TrueLab, enter(FunVar, SuccType1, NewInfo)}, 539 {FalseLab, enter(ArityVar, t_subtract(T, ArityType), Info)}] 540 end 541 end; 542 false -> 543 [{FalseLab, Info}]; 544 maybe -> 545 GenTrueArity = t_inf(t_integer(), ArityType), 546 GenTrueFun = t_inf(t_fun(), FunType), 547 case {t_number_vals(GenTrueArity), t_fun_arity(GenTrueFun)} of 548 {unknown, unknown} -> 549 TrueInfo = enter_list([FunVar, ArityVar], 550 [GenTrueFun, GenTrueArity], Info), 551 [{TrueLab, TrueInfo}, {FalseLab, Info}]; 552 {unknown, Arity} when is_integer(Arity) -> 553 TrueInfo = enter_list([FunVar, ArityVar], 554 [GenTrueFun, t_integer(Arity)], Info), 555 [{TrueLab, TrueInfo}, {FalseLab, Info}]; 556 {[Val], unknown} when is_integer(Val) -> 557 TrueInfo = enter_list([FunVar, ArityVar], 558 [t_inf(GenTrueFun, t_fun(Val, t_any())), 559 GenTrueArity], Info), 560 [{TrueLab, TrueInfo}, {FalseLab, Info}]; 561 {Vals, unknown} when is_list(Vals) -> 562 %% The function type gets widened when we have more than one arity. 563 TrueInfo = enter_list([FunVar, ArityVar], 564 [GenTrueFun, GenTrueArity], Info), 565 [{TrueLab, TrueInfo}, {FalseLab, Info}]; 566 {Vals, Arity} when is_list(Vals), is_integer(Arity) -> 567 case lists:member(Arity, Vals) of 568 false -> 569 [{FalseLab, Info}]; 570 true -> 571 TrueInfo = enter_list([FunVar, ArityVar], 572 [GenTrueFun, t_integer(Arity)], Info), 573 [{TrueLab, TrueInfo}, {FalseLab, Info}] 574 end 575 end 576 end. 577 578combine_test(true, true) -> true; 579combine_test(false, _) -> false; 580combine_test(_, false) -> false; 581combine_test(_, _) -> maybe. 582 583do_type(I, Info, Var) -> 584 TrueLab = hipe_icode:type_true_label(I), 585 FalseLab = hipe_icode:type_false_label(I), 586 None = t_none(), 587 case lookup(Var, Info) of 588 None -> 589 [{TrueLab, Info}, {FalseLab, Info}]; 590 VarInfo -> 591 case hipe_icode:type_test(I) of 592 cons -> 593 test_cons_or_nil(t_cons(), Var, VarInfo, TrueLab, FalseLab, Info); 594 nil -> 595 test_cons_or_nil(t_nil(), Var, VarInfo, TrueLab, FalseLab, Info); 596 {atom, A} = Test -> 597 test_number_or_atom(fun(X) -> t_atom(X) end, 598 A, Var, VarInfo, Test, TrueLab, FalseLab, Info); 599 {integer, N} = Test -> 600 test_number_or_atom(fun(X) -> t_number(X) end, 601 N, Var, VarInfo, Test, TrueLab, FalseLab, Info); 602 {record, Atom, Size} -> 603 test_record(Atom, Size, Var, VarInfo, TrueLab, FalseLab, Info); 604 Other -> 605 case t_is_any(VarInfo) of 606 true -> 607 TrueType = t_inf(true_branch_info(Other), VarInfo), 608 TrueInfo = enter(Var, TrueType, Info), 609 [{TrueLab, TrueInfo}, {FalseLab, Info}]; 610 false -> 611 case test_type(Other, VarInfo) of 612 true -> 613 [{TrueLab, Info}]; 614 false -> 615 [{FalseLab, Info}]; 616 maybe -> 617 TrueType = t_inf(true_branch_info(Other), VarInfo), 618 TrueInfo = enter(Var, TrueType, Info), 619 FalseType = t_subtract(VarInfo, TrueType), 620 FalseInfo = enter(Var, FalseType, Info), 621 [{TrueLab, TrueInfo}, {FalseLab, FalseInfo}] 622 end 623 end 624 end 625 end. 626 627do_switch_tuple_arity(I, Info) -> 628 Var = hipe_icode:switch_tuple_arity_term(I), 629 VarType = lookup(Var, Info), 630 Cases = hipe_icode:switch_tuple_arity_cases(I), 631 FailLabel = hipe_icode:switch_tuple_arity_fail_label(I), 632 case legal_switch_tuple_arity_cases(Cases, VarType) of 633 [] -> 634 [{FailLabel, Info}]; 635 LegalCases -> 636 {Fail, UpdateInfo} = 637 switch_tuple_arity_update_info(LegalCases, Var, VarType, 638 FailLabel, VarType, Info, []), 639 case switch_tuple_arity_can_fail(LegalCases, VarType) of 640 true -> [Fail|UpdateInfo]; 641 false -> UpdateInfo 642 end 643 end. 644 645legal_switch_tuple_arity_cases(Cases, Type) -> 646 case t_is_tuple(Type) of 647 false -> 648 Inf = t_inf(t_tuple(), Type), 649 case t_is_tuple(Inf) of 650 true -> legal_switch_tuple_arity_cases_1(Cases, Inf); 651 false -> [] 652 end; 653 true -> 654 legal_switch_tuple_arity_cases_1(Cases, Type) 655 end. 656 657legal_switch_tuple_arity_cases_1(Cases, Type) -> 658 case t_tuple_sizes(Type) of 659 unknown -> 660 Cases; 661 TupleSizes -> 662 [Case || {Size, _Label} = Case <- Cases, 663 lists:member(hipe_icode:const_value(Size), TupleSizes)] 664 end. 665 666switch_tuple_arity_can_fail(LegalCases, ArgType) -> 667 case t_is_tuple(ArgType) of 668 false -> true; 669 true -> 670 case t_tuple_sizes(ArgType) of 671 unknown -> true; 672 Sizes1 -> 673 Sizes2 = [hipe_icode:const_value(X) || {X, _} <- LegalCases], 674 Set1 = sets:from_list(Sizes1), 675 Set2 = sets:from_list(Sizes2), 676 not sets:is_subset(Set1, Set2) 677 end 678 end. 679 680switch_tuple_arity_update_info([{Arity, Label}|Left], Var, TupleType, 681 FailLabel, FailType, Info, Acc) -> 682 Inf = t_inf(TupleType, t_tuple(hipe_icode:const_value(Arity))), 683 NewInfo = enter(Var, Inf, Info), 684 NewFailType = t_subtract(FailType, Inf), 685 switch_tuple_arity_update_info(Left, Var, TupleType, FailLabel, NewFailType, 686 Info, [{Label, NewInfo}|Acc]); 687switch_tuple_arity_update_info([], Var, _TupleType, 688 FailLabel, FailType, Info, Acc) -> 689 {{FailLabel, enter(Var, FailType, Info)}, Acc}. 690 691do_switch_val(I, Info) -> 692 Var = hipe_icode:switch_val_term(I), 693 VarType = lookup(Var, Info), 694 Cases = hipe_icode:switch_val_cases(I), 695 FailLabel = hipe_icode:switch_val_fail_label(I), 696 case legal_switch_val_cases(Cases, VarType) of 697 [] -> 698 [{FailLabel, Info}]; 699 LegalCases -> 700 switch_val_update_info(LegalCases, Var, VarType, 701 FailLabel, VarType, Info, []) 702 end. 703 704legal_switch_val_cases(Cases, Type) -> 705 legal_switch_val_cases(Cases, Type, []). 706 707legal_switch_val_cases([{Val, _Label} = VL|Left], Type, Acc) -> 708 ConstType = t_from_term(hipe_icode:const_value(Val)), 709 case t_is_subtype(ConstType, Type) of 710 true -> 711 legal_switch_val_cases(Left, Type, [VL|Acc]); 712 false -> 713 legal_switch_val_cases(Left, Type, Acc) 714 end; 715legal_switch_val_cases([], _Type, Acc) -> 716 lists:reverse(Acc). 717 718switch_val_update_info([{Const, Label}|Left], Arg, ArgType, 719 FailLabel, FailType, Info, Acc) -> 720 TrueType = t_from_term(hipe_icode:const_value(Const)), 721 NewInfo = enter(Arg, TrueType, Info), 722 NewFailType = t_subtract(FailType, TrueType), 723 switch_val_update_info(Left, Arg, ArgType, FailLabel, NewFailType, 724 Info, [{Label, NewInfo}|Acc]); 725switch_val_update_info([], Arg, _ArgType, FailLabel, FailType,Info, Acc) -> 726 [{FailLabel, enter(Arg, FailType, Info)}|Acc]. 727 728test_cons_or_nil(Type, Var, VarInfo, TrueLab, FalseLab, Info) -> 729 case t_is_any(VarInfo) of 730 true -> 731 [{TrueLab, enter(Var, Type, Info)}, 732 {FalseLab, Info}]; 733 false -> 734 TrueType = t_inf(VarInfo, Type), 735 FalseType = t_subtract(VarInfo, TrueType), 736 case t_is_none(FalseType) of 737 true -> 738 [{TrueLab, Info}]; 739 false -> 740 case t_is_none(TrueType) of 741 true -> 742 [{FalseLab, Info}]; 743 false -> 744 [{TrueLab, enter(Var, TrueType, Info)}, 745 {FalseLab, enter(Var, FalseType, Info)}] 746 end 747 end 748 end. 749 750test_number_or_atom(Fun, X, Var, VarInfo, TypeTest, 751 TrueLab, FalseLab, Info) -> 752 case t_is_any(VarInfo) of 753 true -> 754 [{TrueLab, enter(Var, Fun(X), Info)}, 755 {FalseLab, Info}]; 756 false -> 757 case test_type(TypeTest, VarInfo) of 758 false -> 759 [{FalseLab, Info}]; 760 true -> 761 [{TrueLab, Info}]; 762 maybe -> 763 FalseType = t_subtract(VarInfo, Fun(X)), 764 [{TrueLab, enter(Var, Fun(X), Info)}, 765 {FalseLab, enter(Var, FalseType, Info)}] 766 end 767 end. 768 769test_record(Atom, Size, Var, VarInfo, TrueLab, FalseLab, Info) -> 770 AnyList = lists:duplicate(Size - 1, t_any()), 771 RecordType = t_tuple([t_atom(Atom)|AnyList]), 772 Inf = t_inf(RecordType, VarInfo), 773 case t_is_none(Inf) of 774 true -> 775 [{FalseLab, Info}]; 776 false -> 777 Sub = t_subtract(VarInfo, Inf), 778 case t_is_none(Sub) of 779 true -> 780 [{TrueLab, enter(Var, Inf, Info)}]; 781 false -> 782 [{TrueLab, enter(Var, Inf, Info)}, 783 {FalseLab, enter(Var, Sub, Info)}] 784 end 785 end. 786 787test_type(Test, Type) -> 788 %% io:format("Test is: ~w\n", [Test]), 789 %% io:format("Type is: ~s\n", [format_type(Type)]), 790 Ans = 791 case t_is_any(Type) of 792 true -> maybe; 793 false -> 794 TrueTest = true_branch_info(Test), 795 Inf = t_inf(TrueTest, Type), 796 %% io:format("TrueTest is: ~s\n", [format_type(TrueTest)]), 797 %% io:format("Inf is: ~s\n", [format_type(Inf)]), 798 case t_is_equal(Type, Inf) of 799 true -> 800 not t_is_none(Type); 801 false -> 802 case t_is_equal(TrueTest, Inf) of 803 true -> 804 case test_type0(Test, Type) of 805 false -> 806 maybe; 807 true -> 808 true; 809 maybe -> 810 maybe 811 end; 812 false -> 813 case test_type0(Test, Inf) of 814 true -> 815 maybe; 816 false -> 817 false; 818 maybe -> 819 maybe 820 end 821 end 822 end 823 end, 824 %% io:format("Result is: ~s\n\n", [Ans]), 825 Ans. 826 827test_type0(integer, T) -> 828 t_is_integer(T); 829test_type0({integer, N}, T) -> 830 case t_is_integer(T) of 831 true -> 832 case t_number_vals(T) of 833 unknown -> maybe; 834 [N] -> true; 835 List when is_list(List) -> 836 case lists:member(N, List) of 837 true -> maybe; 838 false -> false 839 end 840 end; 841 false -> false 842 end; 843test_type0(float, T) -> 844 t_is_float(T); 845test_type0(number, T) -> 846 t_is_number(T); 847test_type0(atom, T) -> 848 t_is_atom(T); 849test_type0({atom, A}, T) -> 850 case t_is_atom(T) of 851 true -> 852 case t_atom_vals(T) of 853 unknown -> maybe; 854 [A] -> true; 855 List when is_list(List) -> 856 case lists:member(A, List) of 857 true -> maybe; 858 false -> false 859 end 860 end; 861 false -> false 862 end; 863test_type0(tuple, T) -> 864 t_is_tuple(T); 865test_type0({tuple, N}, T) -> 866 case t_is_tuple(T) of 867 true -> 868 case t_tuple_sizes(T) of 869 unknown -> maybe; 870 [X] when is_integer(X) -> X =:= N; 871 List when is_list(List) -> 872 case lists:member(N, List) of 873 true -> maybe; 874 false -> false 875 end 876 end; 877 false -> false 878 end; 879test_type0(pid, T) -> 880 t_is_pid(T); 881test_type0(port, T) -> 882 t_is_port(T); 883test_type0(binary, T) -> 884 t_is_binary(T); 885test_type0(bitstr, T) -> 886 t_is_bitstr(T); 887test_type0(reference, T) -> 888 t_is_reference(T); 889test_type0(function, T) -> 890 t_is_fun(T); 891test_type0(boolean, T) -> 892 t_is_boolean(T); 893test_type0(list, T) -> 894 t_is_maybe_improper_list(T); 895%% test_type0(cons, T) -> 896%% t_is_cons(T); 897%% test_type0(nil, T) -> 898%% t_is_nil(T). 899test_type0(map, T) -> 900 t_is_map(T). 901 902true_branch_info(integer) -> 903 t_integer(); 904true_branch_info({integer, N}) -> 905 t_integer(N); 906true_branch_info(float) -> 907 t_float(); 908true_branch_info(number) -> 909 t_number(); 910true_branch_info(atom) -> 911 t_atom(); 912true_branch_info({atom, A}) -> 913 t_atom(A); 914true_branch_info(list) -> 915 t_maybe_improper_list(); 916true_branch_info(tuple) -> 917 t_tuple(); 918true_branch_info({tuple, N}) -> 919 t_tuple(N); 920true_branch_info(pid) -> 921 t_pid(); 922true_branch_info(port) -> 923 t_port(); 924true_branch_info(binary) -> 925 t_binary(); 926true_branch_info(bitstr) -> 927 t_bitstr(); 928true_branch_info(reference) -> 929 t_reference(); 930true_branch_info(function) -> 931 t_fun(); 932%% true_branch_info(cons) -> 933%% t_cons(); 934%% true_branch_info(nil) -> 935%% t_nil(); 936true_branch_info(boolean) -> 937 t_boolean(); 938true_branch_info(map) -> 939 t_map(); 940true_branch_info(T) -> 941 exit({?MODULE, unknown_typetest, T}). 942 943 944%% _________________________________________________________________ 945%% 946%% Remove the redundant type tests. If a test is removed, the trace 947%% that isn't taken is explicitly removed from the CFG to simplify 948%% the handling of Phi nodes. If a Phi node is left and at least one 949%% branch into it has disappeared, the SSA propagation pass cannot 950%% handle it. 951%% 952%% If the CFG has changed at the end of this pass, the analysis is 953%% done again since we might be able to find more information because 954%% of the simplification of the CFG. 955%% 956 957simplify_controlflow(State) -> 958 Cfg = state__cfg(State), 959 simplify_controlflow(hipe_icode_cfg:reverse_postorder(Cfg), State). 960 961simplify_controlflow([Label|Left], State) -> 962 Info = state__info_out(State, Label), 963 NewState = 964 case state__bb(State, Label) of 965 not_found -> State; 966 BB -> 967 I = hipe_bb:last(BB), 968 case I of 969 #icode_if{} -> 970 rewrite_if(State,I,BB,Info,Label); 971 #icode_type{} -> 972 rewrite_type(State,I,BB,Info,Label); 973 #icode_switch_tuple_arity{} -> 974 rewrite_switch_tuple_arity(State,I,BB,Info,Label); 975 #icode_switch_val{} -> 976 rewrite_switch_val(State,I,BB,Info,Label); 977 #icode_call{} -> 978 rewrite_call(State,I,BB,Info,Label); 979 _ -> 980 State 981 end 982 end, 983 simplify_controlflow(Left, NewState); 984simplify_controlflow([], State) -> 985 State. 986 987rewrite_if(State, I, BB, Info, Label) -> 988 case do_if(I, Info) of 989 [{Lab, _}] -> 990 mk_goto(State, BB, Label, Lab); 991 [_,_] -> 992 State 993 end. 994 995rewrite_type(State, I, BB, Info, Label) -> 996 FalseLab = hipe_icode:type_false_label(I), 997 case hipe_icode:type_true_label(I) of 998 FalseLab -> 999 %% true label = false label, this can occur! 1000 mk_goto(State, BB, Label, FalseLab); 1001 TrueLab -> 1002 case do_type(I, Info) of 1003 [{TrueLab, _}] -> 1004 mk_goto(State, BB, Label, TrueLab); 1005 [{FalseLab, _}] -> 1006 mk_goto(State, BB, Label, FalseLab); 1007 [_,_] -> %% Maybe 1008 State 1009 end 1010 end. 1011 1012rewrite_switch_tuple_arity(State, I, BB, Info, Label) -> 1013 Cases = hipe_icode:switch_tuple_arity_cases(I), 1014 Var = hipe_icode:switch_tuple_arity_term(I), 1015 Type = safe_lookup(Var, Info), 1016 case legal_switch_tuple_arity_cases(Cases, Type) of 1017 [] -> 1018 Fail = hipe_icode:switch_tuple_arity_fail_label(I), 1019 mk_goto(State, BB, Label, Fail); 1020 Cases -> 1021 %% Nothing changed. 1022 case switch_tuple_arity_can_fail(Cases, Type) of 1023 true -> State; 1024 false -> 1025 NewCases = butlast(Cases), 1026 {_Arity, NewFail} = lists:last(Cases), 1027 TmpI = 1028 hipe_icode:switch_tuple_arity_fail_label_update(I, NewFail), 1029 NewI = 1030 hipe_icode:switch_tuple_arity_cases_update(TmpI, NewCases), 1031 NewBB = hipe_bb:code_update(BB, hipe_bb:butlast(BB) ++ [NewI]), 1032 state__bb_add(State, Label, NewBB) 1033 end; 1034 LegalCases -> 1035 NewI = 1036 case switch_tuple_arity_can_fail(LegalCases, Type) of 1037 true -> 1038 hipe_icode:switch_tuple_arity_cases_update(I, LegalCases); 1039 false -> 1040 NewCases = butlast(LegalCases), 1041 {_Arity, NewFail} = lists:last(LegalCases), 1042 TmpI = 1043 hipe_icode:switch_tuple_arity_cases_update(I, NewCases), 1044 hipe_icode:switch_tuple_arity_fail_label_update(TmpI, NewFail) 1045 end, 1046 NewBB = hipe_bb:code_update(BB, hipe_bb:butlast(BB) ++ [NewI]), 1047 state__bb_add(State, Label, NewBB) 1048 end. 1049 1050rewrite_switch_val(State, I, BB, Info, Label) -> 1051 Cases = hipe_icode:switch_val_cases(I), 1052 Var = hipe_icode:switch_val_term(I), 1053 VarType = safe_lookup(Var, Info), 1054 case legal_switch_val_cases(Cases, VarType) of 1055 [] -> 1056 Fail = hipe_icode:switch_val_fail_label(I), 1057 mk_goto(State, BB, Label, Fail); 1058 Cases -> 1059 State; 1060 %% TODO: Find out whether switch_val can fail 1061 %% just as switch_tuple_arity 1062 LegalCases -> 1063 NewI = hipe_icode:switch_val_cases_update(I, LegalCases), 1064 NewBB = hipe_bb:code_update(BB, hipe_bb:butlast(BB) ++ [NewI]), 1065 state__bb_add(State, Label, NewBB) 1066 end. 1067 1068rewrite_call(State,I,BB,Info,Label) -> 1069 case call_always_fails(I, Info) of 1070 false -> 1071 Fun = hipe_icode:call_fun(I), 1072 case hipe_icode_primops:fails(Fun) of 1073 false -> 1074 case hipe_icode:call_fail_label(I) of 1075 [] -> State; 1076 _ -> unset_fail(State, BB, Label, I) 1077 end; 1078 true -> State 1079 end; 1080 true -> 1081 case hipe_icode:call_in_guard(I) of 1082 false -> State; 1083 true -> 1084 FailLabel = hipe_icode:call_fail_label(I), 1085 mk_goto(State, BB, Label, FailLabel) 1086 end 1087 end. 1088 1089mk_goto(State, BB, Label, Succ) -> 1090 NewI = hipe_icode:mk_goto(Succ), 1091 NewBB = hipe_bb:code_update(BB, hipe_bb:butlast(BB) ++ [NewI]), 1092 state__bb_add(State, Label, NewBB). 1093 1094unset_fail(State, BB, Label, I) -> 1095 %%io:format("Setting a guard that cannot fail\n", []), 1096 NewI = hipe_icode:call_set_fail_label(I, []), 1097 NewBB = hipe_bb:code_update(BB, hipe_bb:butlast(BB) ++ [NewI]), 1098 state__bb_add(State, Label, NewBB). 1099 1100%% _________________________________________________________________ 1101%% 1102%% Make transformations (specialisations) based on the type knowledge. 1103%% 1104%% Annotate the variables with the local information. Since we have 1105%% the code in SSA form and the type information can only depend on 1106%% assignments or branches (type tests), we can use the information 1107%% out of the block to annotate all variables in it. 1108%% 1109 1110-spec specialize(cfg()) -> cfg(). 1111 1112specialize(Cfg) -> 1113 Labels = hipe_icode_cfg:reverse_postorder(Cfg), 1114 transform_bbs(Labels, Cfg). 1115 1116transform_bbs([Label|Left], Cfg) -> 1117 BB = hipe_icode_cfg:bb(Cfg, Label), 1118 Code = hipe_bb:code(BB), 1119 NewCode = make_transformations(Code), 1120 NewBB = hipe_bb:code_update(BB, NewCode), 1121 NewCfg = hipe_icode_cfg:bb_add(Cfg, Label, NewBB), 1122 transform_bbs(Left, NewCfg); 1123transform_bbs([], Cfg) -> 1124 Cfg. 1125 1126make_transformations(Is) -> 1127 lists:flatten([transform_insn(I) || I <- Is]). 1128 1129transform_insn(I) -> 1130 case I of 1131 #icode_call{} -> 1132 handle_call_and_enter(I); 1133 #icode_enter{} -> 1134 handle_call_and_enter(I); 1135 #icode_if{} -> 1136 CurrentIfOp = hipe_icode:if_op(I), 1137 UsesFixnums = all_fixnums([get_type(A) || A <- hipe_icode:args(I)]), 1138 AnyImmediate = any_immediate([get_type(A) || A <- hipe_icode:args(I)]), 1139 ExactComp = is_exact_comp(CurrentIfOp), 1140 if UsesFixnums -> 1141 hipe_icode:if_op_update(I, fixnum_ifop(CurrentIfOp)); 1142 AnyImmediate andalso ExactComp -> 1143 hipe_icode:if_op_update(I, fixnum_ifop(CurrentIfOp)); 1144 true -> 1145 I 1146 end; 1147 _ -> 1148 I 1149 end. 1150 1151handle_call_and_enter(I) -> 1152 case call_or_enter_fun(I) of 1153 #element{} -> 1154 transform_insn(update_call_or_enter(I, {erlang, element, 2})); 1155 {erlang, element, 2} -> 1156 NewI1 = transform_element2(I), 1157 case is_record(I, icode_call) andalso hipe_icode:call_in_guard(I) of 1158 true -> 1159 case hipe_icode:call_fun(NewI1) of 1160 #unsafe_element{} -> NewI1; 1161 _ -> I 1162 end; 1163 false -> 1164 NewI1 1165 end; 1166 {erlang, hd, 1} -> transform_hd_or_tl(I, unsafe_hd); 1167 {erlang, tl, 1} -> transform_hd_or_tl(I, unsafe_tl); 1168 {hipe_bs_primop, BsOP} -> 1169 NewBsOp = 1170 bit_opts(BsOP, get_type_list(hipe_icode:args(I))), 1171 update_call_or_enter(I, {hipe_bs_primop, NewBsOp}); 1172 conv_to_float -> 1173 [Src] = hipe_icode:args(I), 1174 case t_is_float(get_type(Src)) of 1175 true -> 1176 update_call_or_enter(I, unsafe_untag_float); 1177 false -> 1178 I 1179 end; 1180 FunName -> 1181 case is_arith_function(FunName) of 1182 true -> 1183 case strength_reduce(I, FunName) of 1184 NewIs when is_list(NewIs) -> 1185 [pos_transform_arith(NewI) || NewI <- NewIs]; 1186 NewI -> 1187 pos_transform_arith(NewI) 1188 end; 1189 false -> 1190 I 1191 end 1192 end. 1193 1194pos_transform_arith(I) -> 1195 case hipe_icode:is_enter(I) orelse hipe_icode:is_call(I) of 1196 true -> 1197 FunName = call_or_enter_fun(I), 1198 transform_arith(I, FunName); 1199 false -> 1200 I 1201 end. 1202 1203is_arith_function(Name) -> 1204 case Name of 1205 'band' -> true; 1206 'bor' -> true; 1207 'bxor' -> true; 1208 'bnot' -> true; 1209 'bsl' -> true; 1210 'bsr' -> true; 1211 '+' -> true; 1212 '-' -> true; 1213 '*' -> true; 1214 'div' -> true; 1215 'rem' -> true; 1216 _ -> false 1217 end. 1218 1219%%--------------------------------------------------------------------- 1220%% Perform a limited form of strength reduction for multiplication and 1221%% division of an integer with constants which are multiples of 2. 1222%%--------------------------------------------------------------------- 1223 1224strength_reduce(I, Op) -> 1225 case Op of 1226 '*' -> 1227 [Arg1, Arg2] = mult_args_const_second(I), 1228 ArgT1 = get_type(Arg1), 1229 case t_is_integer(ArgT1) of 1230 true -> 1231 case hipe_icode:is_const(Arg2) of 1232 true -> 1233 case hipe_icode:const_value(Arg2) of 1234 0 -> case call_dstlist(I) of 1235 [] -> remove_useless_arithmetic_instruction(I); 1236 [Dst] -> create_strength_reduce_move(I, Dst, Arg2) 1237 end; 1238 1 -> case call_dstlist(I) of 1239 [] -> remove_useless_arithmetic_instruction(I); 1240 [Dst] -> create_strength_reduce_move(I, Dst, Arg1) 1241 end; 1242 2 -> strength_reduce_imult(I, Arg1, 1); 1243 4 -> strength_reduce_imult(I, Arg1, 2); 1244 8 -> strength_reduce_imult(I, Arg1, 3); 1245 16 -> strength_reduce_imult(I, Arg1, 4); 1246 32 -> strength_reduce_imult(I, Arg1, 5); 1247 64 -> strength_reduce_imult(I, Arg1, 6); 1248 128 -> strength_reduce_imult(I, Arg1, 7); 1249 256 -> strength_reduce_imult(I, Arg1, 8); 1250 ___ -> I 1251 end; 1252 false -> I 1253 end; 1254 false -> I 1255 end; 1256 'div' -> 1257 [Arg1, Arg2] = hipe_icode:args(I), 1258 ArgT1 = get_type(Arg1), 1259 case t_is_non_neg_integer(ArgT1) of 1260 true -> %% the optimization is NOT valid for negative integers 1261 case hipe_icode:is_const(Arg2) of 1262 true -> 1263 case hipe_icode:const_value(Arg2) of 1264 0 -> io:fwrite("Integer division by 0 detected!\n"), I; 1265 1 -> case call_dstlist(I) of 1266 [] -> remove_useless_arithmetic_instruction(I); 1267 [Dst] -> create_strength_reduce_move(I, Dst, Arg1) 1268 end; 1269 2 -> strength_reduce_div(I, Arg1, 1); 1270 4 -> strength_reduce_div(I, Arg1, 2); 1271 8 -> strength_reduce_div(I, Arg1, 3); 1272 16 -> strength_reduce_div(I, Arg1, 4); 1273 32 -> strength_reduce_div(I, Arg1, 5); 1274 64 -> strength_reduce_div(I, Arg1, 6); 1275 128 -> strength_reduce_div(I, Arg1, 7); 1276 256 -> strength_reduce_div(I, Arg1, 8); 1277 ___ -> I 1278 end; 1279 false -> I 1280 end; 1281 false -> I 1282 end; 1283 'rem' -> 1284 [Arg1, Arg2] = hipe_icode:args(I), 1285 ArgT1 = get_type(Arg1), 1286 case t_is_non_neg_integer(ArgT1) of 1287 true -> %% the optimization is NOT valid for negative integers 1288 case hipe_icode:is_const(Arg2) of 1289 true -> 1290 case hipe_icode:const_value(Arg2) of 1291 0 -> io:fwrite("Remainder with 0 detected!\n"), I; 1292 1 -> case call_dstlist(I) of 1293 [] -> remove_useless_arithmetic_instruction(I); 1294 [Dst] -> create_strength_reduce_move( 1295 I, Dst, hipe_icode:mk_const(0)) 1296 end; 1297 2 -> strength_reduce_rem(I, Arg1, 1); 1298 4 -> strength_reduce_rem(I, Arg1, 3); 1299 8 -> strength_reduce_rem(I, Arg1, 7); 1300 16 -> strength_reduce_rem(I, Arg1, 15); 1301 32 -> strength_reduce_rem(I, Arg1, 31); 1302 64 -> strength_reduce_rem(I, Arg1, 63); 1303 128 -> strength_reduce_rem(I, Arg1, 127); 1304 256 -> strength_reduce_rem(I, Arg1, 255); 1305 ___ -> I 1306 end; 1307 false -> I 1308 end; 1309 false -> I 1310 end; 1311 _ -> I 1312 end. 1313 1314remove_useless_arithmetic_instruction(_) -> 1315 []. 1316 1317create_strength_reduce_move(I, Dst, Val) -> 1318 case hipe_icode:call_continuation(I) of 1319 [] -> 1320 hipe_icode:mk_move(Dst, Val); 1321 Lbl -> 1322 [hipe_icode:mk_move(Dst, Val), 1323 hipe_icode:mk_goto(Lbl)] 1324 end. 1325 1326%% Puts the args of a multiplication in a form where the constant 1327%% (if present) is always the second argument. 1328mult_args_const_second(I) -> 1329 [Arg1, Arg2] = Args = hipe_icode:args(I), 1330 case hipe_icode:is_const(Arg1) of 1331 true -> [Arg2, Arg1]; 1332 false -> Args 1333 end. 1334 1335%% In all three functions below: 1336%% - Arg1 is a variable of integer type 1337%% - N is a small positive integer that will be used in a bit shift operation 1338strength_reduce_imult(I, Arg1, N) -> 1339 case t_number_vals(get_type(Arg1)) of 1340 [X] when is_integer(X) -> 1341 %% io:format("Multiplication with constant arguments:\n ~w\n", [I]), 1342 case call_dstlist(I) of 1343 [] -> remove_useless_arithmetic_instruction(I); 1344 [D] -> create_strength_reduce_move(I, D, hipe_icode:mk_const(X bsl N)) 1345 end; 1346 _ -> 1347 update_call_or_enter(I, 'bsl', [Arg1, hipe_icode:mk_const(N)]) 1348 end. 1349 1350strength_reduce_div(I, Arg1, N) -> 1351 case t_number_vals(get_type(Arg1)) of 1352 [X] when is_integer(X) -> 1353 %% io:format("Division with constant arguments:\n ~w\n", [I]), 1354 case call_dstlist(I) of 1355 [] -> remove_useless_arithmetic_instruction(I); 1356 [D] -> create_strength_reduce_move(I, D, hipe_icode:mk_const(X bsr N)) 1357 end; 1358 _ -> 1359 update_call_or_enter(I, 'bsr', [Arg1, hipe_icode:mk_const(N)]) 1360 end. 1361 1362strength_reduce_rem(I, Arg1, N) -> 1363 case t_number_vals(get_type(Arg1)) of 1364 [X] when is_integer(X) -> 1365 %% io:format("Remainder with constant arguments:\n ~w\n", [I]), 1366 case call_dstlist(I) of 1367 [] -> remove_useless_arithmetic_instruction(I); 1368 [D] -> create_strength_reduce_move(I, D, hipe_icode:mk_const(X band N)) 1369 end; 1370 _ -> 1371 update_call_or_enter(I, 'band', [Arg1, hipe_icode:mk_const(N)]) 1372 end. 1373 1374%%--------------------------------------------------------------------- 1375 1376call_or_enter_fun(I) -> 1377 case hipe_icode:is_call(I) of 1378 true -> hipe_icode:call_fun(I); 1379 false -> hipe_icode:enter_fun(I) 1380 end. 1381 1382update_call_or_enter(I, NewFun) -> 1383 case hipe_icode:is_call(I) of 1384 true -> 1385 case hipe_icode_primops:fails(NewFun) of 1386 false -> 1387 NewI = hipe_icode:call_fun_update(I, NewFun), 1388 hipe_icode:call_set_fail_label(NewI, []); 1389 true -> 1390 hipe_icode:call_fun_update(I, NewFun) 1391 end; 1392 false -> hipe_icode:enter_fun_update(I, NewFun) 1393 end. 1394 1395update_call_or_enter(I, NewFun, NewArgs) -> 1396 case hipe_icode:is_call(I) of 1397 true -> 1398 I1 = hipe_icode:call_args_update(I, NewArgs), 1399 hipe_icode:call_fun_update(I1, NewFun); 1400 false -> 1401 I1 = hipe_icode:enter_args_update(I, NewArgs), 1402 hipe_icode:enter_fun_update(I1, NewFun) 1403 end. 1404 1405transform_element2(I) -> 1406 [Index, Tuple] = hipe_icode:args(I), 1407 IndexType = get_type(Index), 1408 TupleType = get_type(Tuple), 1409 ?debug("Tuple", TupleType), 1410 NewIndex = 1411 case test_type(integer, IndexType) of 1412 true -> 1413 case {number_min(IndexType), number_max(IndexType)} of 1414 {Lb0, Ub0} when is_integer(Lb0), is_integer(Ub0) -> 1415 {number, Lb0, Ub0}; 1416 {_, _} -> unknown 1417 end; 1418 _ -> unknown 1419 end, 1420 MinSize = 1421 case test_type(tuple, TupleType) of 1422 true -> 1423 ?debug("is tuple", TupleType), 1424 case t_tuple_sizes(TupleType) of 1425 unknown -> unknown; 1426 Sizes -> {tuple, lists:min(Sizes)} 1427 end; 1428 _ -> unknown 1429 end, 1430 case {NewIndex, MinSize} of 1431 {{number, Lb, Ub}, {tuple, A}} when is_integer(A) -> 1432 case 0 < Lb andalso Ub =< A of 1433 true -> 1434 case {Lb, Ub} of 1435 {Idx, Idx} -> 1436 [_, Tuple] = hipe_icode:args(I), 1437 update_call_or_enter(I, #unsafe_element{index = Idx}, [Tuple]); 1438 {_, _} -> 1439 NewFun = {element, [MinSize, valid]}, 1440 update_call_or_enter(I, NewFun) 1441 end; 1442 false -> 1443 case lists:all(fun(X) -> hipe_tagscheme:is_fixnum(X) end, [Lb, Ub]) of 1444 true -> 1445 NewFun = {element, [MinSize, fixnums]}, 1446 update_call_or_enter(I, NewFun); 1447 false -> 1448 NewFun = {element, [MinSize, unknown]}, 1449 update_call_or_enter(I, NewFun) 1450 end 1451 end; 1452 _ when (NewIndex =:= unknown) orelse (MinSize =:= unknown) -> 1453 case t_is_fixnum(IndexType) of 1454 true -> 1455 NewFun = {element, [MinSize, fixnums]}, 1456 update_call_or_enter(I, NewFun); 1457 false -> 1458 NewFun = {element, [MinSize, NewIndex]}, 1459 update_call_or_enter(I, NewFun) 1460 end 1461 end. 1462 1463transform_hd_or_tl(I, Primop) -> 1464 [Arg] = hipe_icode:args(I), 1465 case t_is_cons(get_type(Arg)) of 1466 true -> update_call_or_enter(I, Primop); 1467 false -> I 1468 end. 1469 1470transform_arith(I, Op) -> 1471 ArgTypes = get_type_list(hipe_icode:args(I)), 1472 %% io:format("Op = ~w, Args = ~w\n", [Op, ArgTypes]), 1473 DstTypes = 1474 case hipe_icode:is_call(I) of 1475 true -> get_type_list(call_dstlist(I)); 1476 false -> [erl_bif_types:type(erlang, Op, length(ArgTypes), ArgTypes)] 1477 end, 1478 case valid_unsafe_args(ArgTypes, Op) of 1479 true -> 1480 case all_is_fixnum(DstTypes) of 1481 true -> 1482 update_call_or_enter(I, arithop_to_extra_unsafe(Op)); 1483 false -> 1484 update_call_or_enter(I, arithop_to_unsafe(Op)) 1485 end; 1486 false -> 1487 I 1488 end. 1489 1490all_is_fixnum(Types) -> 1491 lists:all(fun erl_types:t_is_fixnum/1, Types). 1492 1493valid_unsafe_args(Args, Op) -> 1494 if Op =:= 'bnot' -> 1495 [Arg] = Args, 1496 t_is_fixnum(Arg); 1497 true -> 1498 [LeftArg, RightArg] = Args, 1499 case Op of 1500 'bsl' -> t_is_fixnum(LeftArg) and t_is_bitwidth(RightArg); 1501 'bsr' -> t_is_fixnum(LeftArg) and t_is_bitwidth(RightArg); 1502 _ -> t_is_fixnum(LeftArg) and t_is_fixnum(RightArg) 1503 end 1504 end. 1505 1506arithop_to_extra_unsafe(Op) -> 1507 case Op of 1508 '+' -> extra_unsafe_add; 1509 '-' -> extra_unsafe_sub; 1510 '*' -> '*'; %% XXX: Revise? 1511 'div' -> 'div'; %% XXX: Revise? 1512 'rem' -> 'rem'; %% XXX: Revise? 1513 'band' -> unsafe_band; 1514 'bor' -> unsafe_bor; 1515 'bxor' -> unsafe_bxor; 1516 'bnot' -> unsafe_bnot; 1517 'bsl' -> unsafe_bsl; 1518 'bsr' -> unsafe_bsr 1519 end. 1520 1521arithop_to_unsafe(Op) -> 1522 case Op of 1523 '+' -> unsafe_add; 1524 '-' -> unsafe_sub; 1525 _ -> Op 1526 end. 1527 1528fixnum_ifop(Op) -> 1529 case Op of 1530 '=:=' -> 'fixnum_eq'; 1531 '=/=' -> 'fixnum_neq'; 1532 '==' -> 'fixnum_eq'; 1533 '/=' -> 'fixnum_neq'; 1534 '>' -> 'fixnum_gt'; 1535 '<' -> 'fixnum_lt'; 1536 '>=' -> 'fixnum_ge'; 1537 '=<' -> 'fixnum_le'; 1538 Op -> Op 1539 end. 1540 1541bit_opts({Name, Size, Flags} = I, [MSType]) when Name =:= bs_get_integer; 1542 Name =:= bs_get_float; 1543 Name =:= bs_get_binary -> 1544 Bits = t_matchstate_present(MSType), 1545 case t_is_bitstr(Bits) of 1546 true -> 1547 Base = t_bitstr_base(Bits), 1548 if Base >= Size -> 1549 {Name, Size, Flags bor 16}; 1550 true -> I 1551 end; 1552 false -> I 1553 end; 1554bit_opts({bs_get_binary_all, Size, Flags} = I, [MSType]) -> 1555 Bits = t_matchstate_present(MSType), 1556 case t_is_bitstr(Bits) of 1557 true -> 1558 Base = t_bitstr_base(Bits), 1559 Unit = t_bitstr_unit(Bits), 1560 if (Base rem Size) =:= 0 andalso (Unit rem Size) =:= 0 -> 1561 {bs_get_binary_all, Size, Flags bor 16}; 1562 true -> I 1563 end; 1564 false -> I 1565 end; 1566bit_opts({bs_test_unit, Size} = I, [MSType]) -> 1567 Bits = t_matchstate_present(MSType), 1568 case t_is_bitstr(Bits) of 1569 true -> 1570 Base = t_bitstr_base(Bits), 1571 Unit = t_bitstr_unit(Bits), 1572 if (Base rem Size) =:= 0 andalso (Unit rem Size) =:= 0 -> 1573 {bs_test_unit, 1}; 1574 true -> I 1575 end; 1576 false -> I 1577 end; 1578bit_opts({bs_put_integer, Size, Flags, ConstInfo} = I, [Src|_]) -> 1579 case t_is_fixnum(Src) of 1580 true -> 1581 {unsafe_bs_put_integer, Size, Flags, ConstInfo}; 1582 false -> I 1583 end; 1584bit_opts({bs_start_match, Max} = I, [Src]) -> 1585 case t_is_bitstr(Src) of 1586 true -> {{bs_start_match, bitstr}, Max}; 1587 false -> 1588 MSorNone = t_inf(t_matchstate(), Src), 1589 case t_is_matchstate(MSorNone) of 1590 true -> 1591 Slots = t_matchstate_slots(MSorNone), 1592 case t_is_any(Slots) orelse (length(t_to_tlist(Slots)) =< Max) of 1593 true -> I; 1594 false -> {{bs_start_match, ok_matchstate}, Max} 1595 end; 1596 false -> I 1597 end 1598 end; 1599bit_opts(I, _) -> I. 1600 1601is_exact_comp(Op) -> 1602 case Op of 1603 '=:=' -> true; 1604 '=/=' -> true; 1605 _Op -> false 1606 end. 1607 1608all_fixnums([Type|Types]) -> 1609 t_is_fixnum(Type) andalso all_fixnums(Types); 1610all_fixnums([]) -> 1611 true. 1612 1613any_immediate([Type|Types]) -> 1614 t_is_fixnum(Type) orelse t_is_atom(Type) orelse any_immediate(Types); 1615any_immediate([]) -> false. 1616 1617get_standard_primop(unsafe_bsl) -> 'bsl'; 1618get_standard_primop(unsafe_bsr) -> 'bsr'; 1619get_standard_primop(unsafe_add) -> '+'; 1620get_standard_primop(extra_unsafe_add) -> '+'; 1621get_standard_primop(unsafe_bnot) -> 'bnot'; 1622get_standard_primop(unsafe_bxor) -> 'bxor'; 1623get_standard_primop(unsafe_band) -> 'band'; 1624get_standard_primop(unsafe_bor) -> 'bor'; 1625get_standard_primop(unsafe_sub) -> '-'; 1626get_standard_primop(extra_unsafe_sub) -> '-'; 1627get_standard_primop(Op) -> Op. 1628 1629primop_type(Op, Args) -> 1630 case Op of 1631 #mkfun{mfa = MFA} -> 1632 t_inf(t_fun(), find_signature_mfa(MFA)); 1633 _ -> 1634 None = t_none(), 1635 Primop = get_standard_primop(Op), 1636 RetType = hipe_icode_primops:type(Primop, Args), 1637 case RetType of 1638 None -> 1639 hipe_icode_primops:type(Primop, add_funs_to_arg_types(Args)); 1640 Other -> 1641 Other 1642 end 1643 end. 1644 1645%%------------------------------------------------------------------ 1646%% Various help functions. 1647%%------------------------------------------------------------------ 1648 1649add_arg_types(Args, Types) -> 1650 add_arg_types(Args, Types, gb_trees:empty()). 1651 1652add_arg_types([Arg|Args], [Type|Types], Acc) -> 1653 Type1 = 1654 case t_is_none(Type) of 1655 true -> t_any(); 1656 false -> Type 1657 end, 1658 add_arg_types(Args,Types, enter(Arg, Type1, Acc)); 1659add_arg_types(_, [], Acc) -> 1660 Acc. 1661 1662get_type_list(ArgList) -> 1663 [get_type(Arg) || Arg <- ArgList]. 1664 1665get_type(Arg) -> 1666 case hipe_icode:is_annotated_variable(Arg) of 1667 true -> 1668 None = t_none(), 1669 case hipe_icode:variable_annotation(Arg) of 1670 {type_anno, None, _} -> t_any(); 1671 {type_anno, Type, _} -> Type 1672 end; 1673 false -> 1674 case hipe_icode:is_const(Arg) of 1675 true -> const_type(Arg); 1676 false -> t_any() 1677 end 1678 end. 1679 1680%% Lookup treats anything that is neither in the map or a constant as 1681%% t_none(). Use this during type propagation! 1682 1683lookup(Var, Tree) -> 1684 case gb_trees:lookup(Var, Tree) of 1685 none -> 1686 case hipe_icode:is_const(Var) of 1687 true -> const_type(Var); 1688 false -> t_none() 1689 end; 1690 {value, Type} -> 1691 Type 1692 end. 1693 1694lookup_list(List, Info) -> 1695 lookup_list0(List, Info, []). 1696 1697lookup_list0([H|T], Info, Acc) -> 1698 lookup_list0(T, Info, [lookup(H, Info)|Acc]); 1699lookup_list0([], _, Acc) -> 1700 lists:reverse(Acc). 1701 1702%% safe_lookup treats anything that is neither in the map nor a 1703%% constant as t_any(). Use this during transformations. 1704 1705safe_lookup(Var, Tree) -> 1706 case gb_trees:lookup(Var, Tree) of 1707 none -> 1708 case hipe_icode:is_const(Var) of 1709 true -> const_type(Var); 1710 false -> 1711 %% io:format("Expression has undefined type\n",[]), 1712 t_any() 1713 end; 1714 {value, Type} -> 1715 Type 1716 end. 1717 1718safe_lookup_list(List, Info) -> 1719 safe_lookup_list0(List, Info, []). 1720 1721safe_lookup_list0([H|T], Info, Acc) -> 1722 safe_lookup_list0(T, Info, [safe_lookup(H, Info)|Acc]); 1723safe_lookup_list0([], _, Acc) -> 1724 lists:reverse(Acc). 1725 1726enter_list([Var|VarLeft], [Type|TypeLeft], Info) -> 1727 NewInfo = enter(Var, Type, Info), 1728 enter_list(VarLeft, TypeLeft, NewInfo); 1729enter_list([], [], Info) -> 1730 Info. 1731 1732enter([Key], Value, Tree) -> 1733 enter(Key, Value, Tree); 1734enter(Key, Value, Tree) -> 1735 case is_var_or_reg(Key) of 1736 true -> 1737 case t_is_none(Value) of 1738 true -> 1739 gb_trees:delete_any(Key, Tree); 1740 false -> 1741 gb_trees:enter(Key, Value, Tree) 1742 end; 1743 false -> 1744 Tree 1745 end. 1746 1747join_list(List, Info) -> 1748 join_list(List, Info, t_none()). 1749 1750join_list([H|T], Info, Acc) -> 1751 Type = t_sup(lookup(H, Info), Acc), 1752 join_list(T, Info, Type); 1753join_list([], _, Acc) -> 1754 Acc. 1755 1756join_info_in([], _OldInfo, _NewInfo) -> 1757 %% No variables are live in. The information must be at a fixpoint. 1758 fixpoint; 1759join_info_in(Vars, OldInfo, NewInfo) -> 1760 NewInfo2 = join_info_in(Vars, Vars, OldInfo, NewInfo, gb_trees:empty()), 1761 case info_is_equal(NewInfo2, OldInfo) of 1762 true -> fixpoint; 1763 false -> NewInfo2 1764 end. 1765 1766%% NOTE: Variables can be bound to other variables. Joining these is 1767%% only possible if the binding is the same from both traces and this 1768%% variable is still live. 1769 1770join_info_in([Var|Left], LiveIn, Info1, Info2, Acc) -> 1771 Type1 = gb_trees:lookup(Var, Info1), 1772 Type2 = gb_trees:lookup(Var, Info2), 1773 case {Type1, Type2} of 1774 {none, none} -> 1775 join_info_in(Left, LiveIn, Info1, Info2, Acc); 1776 {none, {value, Val}} -> 1777 NewTree = gb_trees:insert(Var, Val, Acc), 1778 join_info_in(Left, LiveIn, Info1, Info2, NewTree); 1779 {{value, Val}, none} -> 1780 NewTree = gb_trees:insert(Var, Val, Acc), 1781 join_info_in(Left, LiveIn, Info1, Info2, NewTree); 1782 {{value, Val1}, {value, Val2}} -> 1783 NewTree = gb_trees:insert(Var, t_sup(Val1, Val2), Acc), 1784 join_info_in(Left, LiveIn, Info1, Info2, NewTree) 1785 end; 1786join_info_in([], _LiveIn, _Info1, _Info2, Acc) -> 1787 Acc. 1788 1789info_is_equal(Info1, Info2) -> 1790 compare(gb_trees:to_list(Info1), gb_trees:to_list(Info2)). 1791 1792compare([{Var, Type1}|Left1], [{Var, Type2}|Left2]) -> 1793 t_is_equal(Type1, Type2) andalso compare(Left1, Left2); 1794compare([], []) -> 1795 true; 1796compare(_, _) -> 1797 false. 1798 1799const_type(Const) -> 1800 t_from_term(hipe_icode:const_value(Const)). 1801 1802do_updates(State, List) -> 1803 do_updates(State, List, []). 1804 1805do_updates(State, [{Label, Info}|Tail], Worklist) -> 1806 case state__info_in_update(State, Label, Info) of 1807 fixpoint -> 1808 %% io:format("Info in for ~w is: fixpoint\n", [Label]), 1809 do_updates(State, Tail, Worklist); 1810 NewState -> 1811 %% io:format("Info in for ~w is:\n", [Label]), 1812 %% [io:format("~w: ~p\n", [X, format_type(Y)]) 1813 %% || {X, Y} <- gb_trees:to_list(state__info_in(NewState, Label))], 1814 do_updates(NewState, Tail, [Label|Worklist]) 1815 end; 1816do_updates(State, [], Worklist) -> 1817 {State, Worklist}. 1818 1819enter_defines(I, Type, Info) -> 1820 case defines(I) of 1821 [] -> Info; 1822 [Def] -> 1823 enter(Def, Type, Info); 1824 Defs -> 1825 Pairs = case t_is_any(Type) of 1826 true -> 1827 [{Def, t_any()} || Def <- Defs]; 1828 false -> 1829 case t_is_none(Type) of 1830 true -> 1831 [{Def, t_none()} || Def <- Defs]; 1832 false -> 1833 lists:zip(Defs, t_to_tlist(Type)) 1834 end 1835 end, 1836 lists:foldl(fun({X, T}, Inf) -> enter(X, T, Inf) end, Info, Pairs) 1837 end. 1838 1839defines(I) -> 1840 keep_vars_and_regs(hipe_icode:defines(I)). 1841 1842call_dstlist(I) -> 1843 hipe_icode:call_dstlist(I). 1844 1845uses(I) -> 1846 keep_vars_and_regs(hipe_icode:uses(I)). 1847 1848keep_vars_and_regs(Vars) -> 1849 [V || V <- Vars, is_var_or_reg(V)]. 1850 1851butlast([_]) -> 1852 []; 1853butlast([H|T]) -> 1854 [H|butlast(T)]. 1855 1856-spec any_is_none([erl_types:erl_type()]) -> boolean(). 1857 1858any_is_none(Types) -> 1859 lists:any(fun (T) -> t_is_none(T) end, Types). 1860 1861is_var_or_reg(X) -> 1862 hipe_icode:is_var(X) orelse hipe_icode:is_reg(X). 1863 1864%% _________________________________________________________________ 1865%% 1866%% Handling the state 1867%% 1868 1869new_state(Cfg, {MFA, GetCallFun, GetResFun, FinalAction}) -> 1870 Start = hipe_icode_cfg:start_label(Cfg), 1871 Params = hipe_icode_cfg:params(Cfg), 1872 ParamTypes = GetCallFun(MFA, Cfg), 1873 case any_is_none(ParamTypes) of 1874 true -> 1875 FinalAction(MFA, [t_none()]), 1876 throw(no_input); 1877 false -> 1878 Info = add_arg_types(Params, ParamTypes), 1879 InfoMap = gb_trees:insert({Start, in}, Info, gb_trees:empty()), 1880 Liveness = hipe_icode_ssa:ssa_liveness__analyze(Cfg), 1881 #state{info_map = InfoMap, cfg = Cfg, liveness = Liveness, 1882 arg_types = ParamTypes, lookupfun = GetResFun, 1883 resultaction = FinalAction} 1884 end. 1885 1886state__cfg(#state{cfg = Cfg}) -> 1887 Cfg. 1888 1889state__succ(#state{cfg = Cfg}, Label) -> 1890 hipe_icode_cfg:succ(Cfg, Label). 1891 1892state__bb(#state{cfg = Cfg}, Label) -> 1893 hipe_icode_cfg:bb(Cfg, Label). 1894 1895state__bb_add(S = #state{cfg = Cfg}, Label, BB) -> 1896 NewCfg = hipe_icode_cfg:bb_add(Cfg, Label, BB), 1897 S#state{cfg=NewCfg}. 1898 1899state__params_update(S = #state{cfg = Cfg}, NewParams) -> 1900 NewCfg = hipe_icode_cfg:params_update(Cfg, NewParams), 1901 S#state{cfg = NewCfg}. 1902 1903state__ret_type(#state{ret_type = RT}) -> RT. 1904 1905state__lookupfun(#state{lookupfun = LF}) -> LF. 1906 1907state__resultaction(#state{resultaction = RA}) -> RA. 1908 1909state__info_in(S, Label) -> 1910 state__info(S, {Label, in}). 1911 1912state__info_out(S, Label) -> 1913 state__info(S, {Label, out}). 1914 1915state__info(#state{info_map = IM}, Label) -> 1916 case gb_trees:lookup(Label, IM) of 1917 {value, Info} -> Info; 1918 none -> gb_trees:empty() 1919 end. 1920 1921state__ret_type_update(#state{ret_type = RT} = State, NewType) when 1922 is_list(NewType) -> 1923 TotType = lists:zipwith(fun erl_types:t_sup/2, RT, NewType), 1924 State#state{ret_type = TotType}; 1925state__ret_type_update(#state{ret_type = RT} = State, NewType) -> 1926 state__ret_type_update(State, [NewType || _ <- RT]). 1927 1928state__info_in_update(S=#state{info_map=IM, liveness=Liveness}, Label, Info) -> 1929 LiveIn = hipe_icode_ssa:ssa_liveness__livein(Liveness, Label), 1930 LabelIn = {Label, in}, 1931 case gb_trees:lookup(LabelIn, IM) of 1932 none -> 1933 OldInfo = gb_trees:empty(), 1934 case join_info_in(LiveIn, OldInfo, Info) of 1935 fixpoint -> 1936 %% If the BB has not been handled we ignore the fixpoint. 1937 S#state{info_map = gb_trees:enter(LabelIn, OldInfo, IM)}; 1938 NewInfo -> 1939 S#state{info_map = gb_trees:enter(LabelIn, NewInfo, IM)} 1940 end; 1941 {value, OldInfo} -> 1942 case join_info_in(LiveIn, OldInfo, Info) of 1943 fixpoint -> 1944 fixpoint; 1945 NewInfo -> 1946 S#state{info_map = gb_trees:enter(LabelIn, NewInfo, IM)} 1947 end 1948 end. 1949 1950state__info_out_update(#state{info_map = IM} = State, Label, Info) -> 1951 State#state{info_map = gb_trees:enter({Label, out}, Info, IM)}. 1952 1953%% _________________________________________________________________ 1954%% 1955%% The worklist. 1956%% 1957 1958init_work(State) -> 1959 %% Labels = hipe_icode_cfg:reverse_postorder(state__cfg(State)), 1960 Labels = [hipe_icode_cfg:start_label(state__cfg(State))], 1961 {Labels, [], gb_sets:from_list(Labels)}. 1962 1963get_work({[Label|Left], List, Set}) -> 1964 NewWork = {Left, List, gb_sets:delete(Label, Set)}, 1965 {Label, NewWork}; 1966get_work({[], [], _Set}) -> 1967 fixpoint; 1968get_work({[], List, Set}) -> 1969 get_work({lists:reverse(List), [], Set}). 1970 1971add_work(Work = {List1, List2, Set}, [Label|Left]) -> 1972 case gb_sets:is_member(Label, Set) of 1973 true -> 1974 add_work(Work, Left); 1975 false -> 1976 %% io:format("Adding work: ~w\n", [Label]), 1977 add_work({List1, [Label|List2], gb_sets:insert(Label, Set)}, Left) 1978 end; 1979add_work(Work, []) -> 1980 Work. 1981 1982%% _________________________________________________________________ 1983%% 1984%% Annotator 1985%% 1986 1987annotate_cfg(State) -> 1988 Cfg = state__cfg(State), 1989 NewState = annotate_params(hipe_icode_cfg:params(Cfg), State, 1990 hipe_icode_cfg:start_label(Cfg)), 1991 Labels = hipe_icode_cfg:reverse_postorder(Cfg), 1992 annotate_bbs(Labels, NewState). 1993 1994annotate_params(Params, State, Start) -> 1995 Info = state__info_in(State, Start), 1996 AnnoFun = fun hipe_icode:annotate_variable/2, 1997 NewParams = 1998 lists:zipwith(AnnoFun, Params, [make_annotation(P,Info) || P <- Params]), 1999 state__params_update(State,NewParams). 2000 2001annotate_bbs([Label|Left], State) -> 2002 BB = state__bb(State, Label), 2003 Code = hipe_bb:code(BB), 2004 Info = state__info_in(State, Label), 2005 NewCode = annotate_instr_list(Code, Info, state__lookupfun(State), []), 2006 NewBB = hipe_bb:code_update(BB, NewCode), 2007 NewState = state__bb_add(State, Label, NewBB), 2008 annotate_bbs(Left, NewState); 2009annotate_bbs([], State) -> 2010 State. 2011 2012annotate_instr_list([I], Info, LookupFun, Acc) -> 2013 NewInfo = 2014 case I of 2015 #icode_call{} -> 2016 do_safe_call(I, Info, LookupFun); 2017 _ -> 2018 analyse_insn(I, Info, LookupFun) 2019 end, 2020 NewI = annotate_instr(I, NewInfo, Info), 2021 lists:reverse([NewI|Acc]); 2022annotate_instr_list([I|Left], Info, LookupFun, Acc) -> 2023 NewInfo = 2024 case I of 2025 #icode_call{} -> 2026 do_safe_call(I, Info, LookupFun); 2027 _ -> 2028 analyse_insn(I, Info, LookupFun) 2029 end, 2030 NewI = annotate_instr(I, NewInfo, Info), 2031 annotate_instr_list(Left, NewInfo, LookupFun, [NewI|Acc]). 2032 2033annotate_instr(I, DefInfo, UseInfo) -> 2034 Def = defines(I), 2035 Use = uses(I), 2036 Fun = fun hipe_icode:annotate_variable/2, 2037 DefSubst = [{X, Fun(X, make_annotation(X, DefInfo))} || X <- Def], 2038 UseSubst = [{X, Fun(X, make_annotation(X, UseInfo))} || X <- Use], 2039 case DefSubst ++ UseSubst of 2040 [] -> 2041 I; 2042 Subst -> 2043 hipe_icode:subst(Subst, I) 2044 end. 2045 2046make_annotation(X, Info) -> 2047 {type_anno, safe_lookup(X, Info), fun erl_types:t_to_string/1}. 2048 2049-spec unannotate_cfg(cfg()) -> cfg(). 2050 2051unannotate_cfg(Cfg) -> 2052 NewCfg = unannotate_params(Cfg), 2053 Labels = hipe_icode_cfg:labels(NewCfg), 2054 unannotate_bbs(Labels, NewCfg). 2055 2056unannotate_params(Cfg) -> 2057 Params = hipe_icode_cfg:params(Cfg), 2058 NewParams = [hipe_icode:unannotate_variable(X) 2059 || X <- Params, hipe_icode:is_variable(X)], 2060 hipe_icode_cfg:params_update(Cfg, NewParams). 2061 2062unannotate_bbs([Label|Left], Cfg) -> 2063 BB = hipe_icode_cfg:bb(Cfg, Label), 2064 Code = hipe_bb:code(BB), 2065 NewCode = unannotate_instr_list(Code, []), 2066 NewBB = hipe_bb:code_update(BB, NewCode), 2067 NewCfg = hipe_icode_cfg:bb_add(Cfg, Label, NewBB), 2068 unannotate_bbs(Left, NewCfg); 2069unannotate_bbs([], Cfg) -> 2070 Cfg. 2071 2072unannotate_instr_list([I|Left], Acc) -> 2073 NewI = unannotate_instr(I), 2074 unannotate_instr_list(Left, [NewI|Acc]); 2075unannotate_instr_list([], Acc) -> 2076 lists:reverse(Acc). 2077 2078unannotate_instr(I) -> 2079 DefUses = hipe_icode:defines(I) ++ hipe_icode:uses(I), 2080 Subst = [{X, hipe_icode:unannotate_variable(X)} || X <- DefUses, 2081 hipe_icode:is_variable(X)], 2082 if Subst =:= [] -> I; 2083 true -> hipe_icode:subst(Subst, I) 2084 end. 2085 2086%% _________________________________________________________________ 2087%% 2088%% Find the types of the arguments to a call 2089%% 2090 2091update_call_arguments(I, Info) -> 2092 Args = hipe_icode:call_args(I), 2093 ArgTypes = lookup_list(Args, Info), 2094 Signature = find_signature(hipe_icode:call_fun(I), length(Args)), 2095 case t_fun_args(Signature) of 2096 unknown -> 2097 Info; 2098 PltArgTypes -> 2099 NewArgTypes = t_inf_lists(ArgTypes, PltArgTypes), 2100 enter_list(Args, NewArgTypes, Info) 2101 end. 2102 2103%% _________________________________________________________________ 2104%% 2105%% PLT info 2106%% 2107 2108find_signature(MFA = {_, _, _}, _) -> find_signature_mfa(MFA); 2109find_signature(Primop, Arity) -> find_signature_primop(Primop, Arity). 2110 2111find_signature_mfa(MFA) -> 2112 case get_mfa_arg_types(MFA) of 2113 any -> 2114 t_fun(get_mfa_type(MFA)); 2115 BifArgs -> 2116 t_fun(BifArgs, get_mfa_type(MFA)) 2117 end. 2118 2119find_signature_primop(Primop, Arity) -> 2120 case get_primop_arg_types(Primop) of 2121 any -> 2122 t_fun(Arity, get_primop_type(Primop)); 2123 ArgTypes -> 2124 t_fun(ArgTypes, get_primop_type(Primop)) 2125 end. 2126 2127get_primop_arg_types(Primop) -> 2128 case hipe_icode_primops:arg_types(Primop) of 2129 unknown -> any; 2130 ArgTypes -> add_tuple_to_args(ArgTypes) 2131 end. 2132 2133get_mfa_arg_types({M, F, A}) -> 2134 case erl_bif_types:arg_types(M, F, A) of 2135 unknown -> 2136 any; 2137 BifArgs -> 2138 add_tuple_to_args(BifArgs) 2139 end. 2140 2141get_mfa_type({M, F, A}) -> 2142 erl_bif_types:type(M, F, A). 2143 2144get_primop_type(Primop) -> 2145 hipe_icode_primops:type(get_standard_primop(Primop)). 2146 2147add_tuple_to_args(Types) -> 2148 [add_tuple_to_type(T) || T <- Types]. 2149 2150add_tuple_to_type(T) -> 2151 None = t_none(), 2152 case t_inf(t_fun(), T) of 2153 None -> T; 2154 _Other -> t_sup(T, t_tuple([t_atom(),t_atom()])) 2155 end. 2156 2157add_funs_to_arg_types(Types) -> 2158 [add_fun_to_arg_type(T) || T <- Types]. 2159 2160add_fun_to_arg_type(T) -> 2161 None = t_none(), 2162 case t_inf(t_tuple([t_atom(),t_atom()]), T) of 2163 None -> T; 2164 _Other -> t_sup(T, t_fun()) 2165 end. 2166 2167%%===================================================================== 2168%% Icode Coordinator Callbacks 2169%%===================================================================== 2170 2171-spec replace_nones([erl_types:erl_type()] | erl_types:erl_type()) -> 2172 [erl_types:erl_type()]. 2173 2174replace_nones(Types) when is_list(Types) -> 2175 [replace_none(T) || T <- Types]; 2176replace_nones(Type) -> 2177 [replace_none(Type)]. 2178 2179-spec replace_none(erl_types:erl_type()) -> erl_types:erl_type(). 2180 2181replace_none(Type) -> 2182 case erl_types:t_is_none(Type) of 2183 true -> 2184 erl_types:t_any(); 2185 false -> 2186 Type 2187 end. 2188 2189-spec update__info([erl_types:erl_type()], [erl_types:erl_type()]) -> 2190 {boolean(), [erl_types:erl_type()]}. 2191 2192update__info(NewTypes, OldTypes) -> 2193 SupFun = 2194 fun(T1, T2) -> erl_types:t_limit(erl_types:t_sup(T1,T2), ?TYPE_DEPTH) end, 2195 EqFun = fun erl_types:t_is_equal/2, 2196 ResTypes = lists:zipwith(SupFun, NewTypes, OldTypes), 2197 Change = lists:zipwith(EqFun, ResTypes, OldTypes), 2198 {lists:all(fun(X) -> X end, Change), ResTypes}. 2199 2200-spec new__info([erl_types:erl_type()]) -> [erl_types:erl_type()]. 2201 2202new__info(NewTypes) -> 2203 [erl_types:t_limit(T, ?TYPE_DEPTH) || T <- NewTypes]. 2204 2205-spec return__info(erl_types:erl_type()) -> erl_types:erl_type(). 2206 2207return__info(Types) -> 2208 Types. 2209 2210-spec return_none() -> [erl_types:erl_type(),...]. 2211 2212return_none() -> 2213 [erl_types:t_none()]. 2214 2215-spec return_none_args(cfg(), mfa()) -> [erl_types:erl_type()]. 2216 2217return_none_args(Cfg, {_M,_F,A}) -> 2218 NoArgs = 2219 case hipe_icode_cfg:is_closure(Cfg) of 2220 true -> hipe_icode_cfg:closure_arity(Cfg) - 1; 2221 false -> A 2222 end, 2223 lists:duplicate(NoArgs, erl_types:t_none()). 2224 2225-spec return_any_args(cfg(), mfa()) -> [erl_types:erl_type()]. 2226 2227return_any_args(Cfg, {_M,_F,A}) -> 2228 NoArgs = 2229 case hipe_icode_cfg:is_closure(Cfg) of 2230 true -> hipe_icode_cfg:closure_arity(Cfg); 2231 false -> A 2232 end, 2233 lists:duplicate(NoArgs, erl_types:t_any()). 2234 2235%%===================================================================== 2236%% Testing function below 2237%%===================================================================== 2238 2239-ifdef(DO_HIPE_ICODE_TYPE_TEST). 2240 2241test() -> 2242 Range1 = t_from_range(1, pos_inf), 2243 Range2 = t_from_range(0, 5), 2244 Var1 = hipe_icode:mk_var(1), 2245 Var2 = hipe_icode:mk_var(2), 2246 2247 Info = enter(Var1, Range1, enter(Var2, Range2, gb_trees:empty())), 2248 io:format("A1 ~p~n", [Info]), 2249 A = integer_range_inequality_propagation('<', Var1, Var2, 1, 2, Info), 2250 B = integer_range_inequality_propagation('>=', Var1, Var2, 1, 2, Info), 2251 C = integer_range_inequality_propagation('=<', Var1, Var2, 1, 2, Info), 2252 D = integer_range_inequality_propagation('>', Var1, Var2, 1, 2, Info), 2253 2254 io:format("< ~p~n", [A]), 2255 io:format(">= ~p~n", [B]), 2256 io:format("<= ~p~n", [C]), 2257 io:format("> ~p~n", [D]). 2258 2259-endif. 2260