3333    pass to apply its own inlining policy decisions. 
3434""" 
3535struct  DelayedInliningSpec
36-     match:: MethodMatch 
36+     match:: Union{ MethodMatch, InferenceResult} 
3737    atypes:: Vector{Any} 
3838    stmttype:: Any 
3939end 
@@ -44,7 +44,11 @@ struct InliningTodo
4444    spec:: Union{ResolvedInliningSpec, DelayedInliningSpec} 
4545end 
4646
47- InliningTodo (mi:: MethodInstance , match:: MethodMatch , atypes:: Vector{Any} , @nospecialize (stmttype)) =  InliningTodo (mi, DelayedInliningSpec (match, atypes, stmttype))
47+ InliningTodo (mi:: MethodInstance , match:: MethodMatch ,
48+     atypes:: Vector{Any} , @nospecialize (stmttype)) =  InliningTodo (mi, DelayedInliningSpec (match, atypes, stmttype))
49+ 
50+ InliningTodo (result:: InferenceResult , atypes:: Vector{Any} , @nospecialize (stmttype)) = 
51+     InliningTodo (result. linfo, DelayedInliningSpec (result, atypes, stmttype))
4852
4953struct  ConstantCase
5054    val:: Any 
@@ -631,7 +635,10 @@ function rewrite_apply_exprargs!(ir::IRCode, todo::Vector{Pair{Int, Any}}, idx::
631635                new_stmt =  Expr (:call , argexprs[2 ], def, state... )
632636                state1 =  insert_node! (ir, idx, call. rt, new_stmt)
633637                new_sig =  with_atype (call_sig (ir, new_stmt):: Signature )
634-                 if  isa (call. info, MethodMatchInfo) ||  isa (call. info, UnionSplitInfo)
638+                 if  isa (call. info, ConstCallInfo)
639+                     handle_const_call! (ir, state1. id, new_stmt, call. info, new_sig,
640+                         call. rt, et, caches, false , todo)
641+                 elseif  isa (call. info, MethodMatchInfo) ||  isa (call. info, UnionSplitInfo)
635642                    info =  isa (call. info, MethodMatchInfo) ? 
636643                        MethodMatchInfo[call. info] :  call. info. matches
637644                    #  See if we can inline this call to `iterate`
@@ -676,9 +683,31 @@ function compileable_specialization(et::Union{EdgeTracker, Nothing}, match::Meth
676683    return  mi
677684end 
678685
686+ function  compileable_specialization (et:: Union{EdgeTracker, Nothing} , result:: InferenceResult )
687+     mi =  specialize_method (result. linfo. def, result. argtypes, result. linfo. sparam_vals, false , true )
688+     mi != =  nothing  &&  et != =  nothing  &&  push! (et, mi:: MethodInstance )
689+     return  mi
690+ end 
691+ 
679692function  resolve_todo (todo:: InliningTodo , et:: Union{EdgeTracker, Nothing} , caches:: InferenceCaches )
680693    spec =  todo. spec:: DelayedInliningSpec 
681-     isconst, src =  find_inferred (todo. mi, spec. atypes, caches, spec. stmttype)
694+ 
695+     # XXX : update_valid_age!(min_valid[1], max_valid[1], sv)
696+     isconst, src =  false , nothing 
697+     if  isa (spec. match, InferenceResult)
698+         let  inferred_src =  spec. match. src
699+             if  isa (inferred_src, CodeInfo)
700+                 isconst, src =  false , inferred_src
701+             elseif  isa (inferred_src, Const)
702+                 if  ! is_inlineable_constant (inferred_src. val)
703+                     return  compileable_specialization (et, spec. match)
704+                 end 
705+                 isconst, src =  true , quoted (inferred_src. val)
706+             end 
707+         end 
708+     else 
709+         isconst, src =  find_inferred (todo. mi, spec. atypes, caches, spec. stmttype)
710+     end 
682711
683712    if  isconst &&  et != =  nothing 
684713        push! (et, todo. mi)
@@ -717,6 +746,13 @@ function resolve_todo!(todo::Vector{Pair{Int, Any}}, et::Union{EdgeTracker, Noth
717746    todo
718747end 
719748
749+ function  validate_sparams (sparams:: SimpleVector )
750+     for  i =  1 : length (sparams)
751+         (isa (sparams[i], TypeVar) ||  isa (sparams[i], Core. TypeofVararg)) &&  return  false 
752+     end 
753+     return  true 
754+ end 
755+ 
720756function  analyze_method! (match:: MethodMatch , atypes:: Vector{Any} ,
721757                         et:: Union{EdgeTracker, Nothing} ,
722758                         caches:: Union{InferenceCaches, Nothing} ,
@@ -737,9 +773,8 @@ function analyze_method!(match::MethodMatch, atypes::Vector{Any},
737773
738774    #  Bail out if any static parameters are left as TypeVar
739775    ok =  true 
740-     for  i =  1 : length (match. sparams)
741-         (isa (match. sparams[i], TypeVar) ||  isa (match. sparams[i], Core. TypeofVararg)) &&  return  nothing 
742-     end 
776+     validate_sparams (match. sparams) ||  return  nothing 
777+ 
743778
744779    if  ! params. inlining
745780        return  compileable_specialization (et, match)
@@ -1146,6 +1181,28 @@ function analyze_single_call!(ir::IRCode, todo::Vector{Pair{Int, Any}}, idx::Int
11461181    return  nothing 
11471182end 
11481183
1184+ function  handle_const_call! (ir:: IRCode , idx:: Int , stmt:: Expr ,
1185+         info:: ConstCallInfo , sig:: Signature , @nospecialize (calltype),
1186+         et:: Union{EdgeTracker, Nothing} , caches:: Union{InferenceCaches, Nothing} ,
1187+         isinvoke:: Bool , todo:: Vector{Pair{Int, Any}} )
1188+     item =  InliningTodo (info. result, sig. atypes, calltype)
1189+     validate_sparams (item. mi. sparam_vals) ||  return 
1190+     mthd_sig =  item. mi. def. sig
1191+     mistypes =  item. mi. specTypes
1192+     caches != =  nothing  &&  (item =  resolve_todo (item, et, caches))
1193+     if  sig. atype <:  mthd_sig 
1194+         return  handle_single_case! (ir, stmt, idx, item, isinvoke, todo)
1195+     else 
1196+         item ===  nothing  &&  return 
1197+         #  Union split out the error case
1198+         item =  UnionSplit (false , sig. atype, Pair{Any, Any}[mistypes =>  item])
1199+         if  isinvoke
1200+             stmt. args =  rewrite_invoke_exprargs! (stmt. args)
1201+         end 
1202+         push! (todo, idx=> item)
1203+     end 
1204+ end 
1205+ 
11491206function  assemble_inline_todo! (ir:: IRCode , state:: InliningState )
11501207    #  todo = (inline_idx, (isva, isinvoke, na), method, spvals, inline_linetable, inline_ir, lie)
11511208    todo =  Pair{Int, Any}[]
@@ -1173,6 +1230,15 @@ function assemble_inline_todo!(ir::IRCode, state::InliningState)
11731230            end 
11741231        end 
11751232
1233+         #  If inference arrived at this result by using constant propagation,
1234+         #  it'll performed a specialized analysis for just this case. Use its
1235+         #  result.
1236+         if  isa (info, ConstCallInfo)
1237+             handle_const_call! (ir, idx, stmt, info, sig, calltype, state. et,
1238+                 state. caches, invoke_data != =  nothing , todo)
1239+             continue 
1240+         end 
1241+ 
11761242        #  Ok, now figure out what method to call
11771243        if  invoke_data != =  nothing 
11781244            inline_invoke! (ir, idx, sig, invoke_data, state, todo)
@@ -1387,35 +1453,6 @@ function ssa_substitute_op!(@nospecialize(val), arg_replacements::Vector{Any},
13871453end 
13881454
13891455function  find_inferred (mi:: MethodInstance , atypes:: Vector{Any} , caches:: InferenceCaches , @nospecialize (rettype))
1390-     if  caches. inf_cache != =  nothing 
1391-         #  see if the method has a InferenceResult in the current cache
1392-         #  or an existing inferred code info store in `.inferred`
1393-         haveconst =  false 
1394-         for  i in  1 : length (atypes)
1395-             if  has_nontrivial_const_info (atypes[i])
1396-                 #  have new information from argtypes that wasn't available from the signature
1397-                 haveconst =  true 
1398-                 break 
1399-             end 
1400-         end 
1401-         if  haveconst ||  improvable_via_constant_propagation (rettype)
1402-             inf_result =  cache_lookup (mi, atypes, caches. inf_cache) #  Union{Nothing, InferenceResult}
1403-         else 
1404-             inf_result =  nothing 
1405-         end 
1406-         # XXX : update_valid_age!(min_valid[1], max_valid[1], sv)
1407-         if  isa (inf_result, InferenceResult)
1408-             let  inferred_src =  inf_result. src
1409-                 if  isa (inferred_src, CodeInfo)
1410-                     return  svec (false , inferred_src)
1411-                 end 
1412-                 if  isa (inferred_src, Const) &&  is_inlineable_constant (inferred_src. val)
1413-                     return  svec (true , quoted (inferred_src. val),)
1414-                 end 
1415-             end 
1416-         end 
1417-     end 
1418- 
14191456    linfo =  get (caches. mi_cache, mi, nothing )
14201457    if  linfo isa  CodeInstance
14211458        if  invoke_api (linfo) ==  2 
0 commit comments