@@ -827,8 +827,8 @@ function effect_free(@nospecialize(e), src::CodeInfo, mod::Module, allow_volatil
827827 return true
828828 end
829829 if head === :static_parameter
830- # if we aren't certain about the type, it might be an UndefVarError at runtime
831- return ( isa (e. typ, DataType) && isleaftype (e . typ)) || isa ( e. typ, Const )
830+ # if we aren't certain enough about the type, it might be an UndefVarError at runtime
831+ return isa (e. typ, Const) || issingletontype ( widenconst ( e. typ) )
832832 end
833833 if e. typ === Bottom
834834 return false
@@ -841,17 +841,17 @@ function effect_free(@nospecialize(e), src::CodeInfo, mod::Module, allow_volatil
841841 return false
842842 elseif is_known_call (e, getfield, src, mod)
843843 nargs = length (ea)
844- (2 < nargs < 5 ) || return false
844+ (3 < nargs < 4 ) || return false
845845 et = exprtype (e, src, mod)
846- if ! isa (et, Const) && ! (isType (et) && isleaftype (et))
846+ # TODO : check ninitialized
847+ if ! isa (et, Const) && ! isconstType (et)
847848 # first argument must be immutable to ensure e is affect_free
848849 a = ea[2 ]
849- typ = widenconst (exprtype (a, src, mod))
850- if isconstType (typ)
851- if Const (:uid ) ⊑ exprtype (ea[3 ], src, mod)
852- return false # DataType uid field can change
853- end
854- elseif typ != = SimpleVector && (! isa (typ, DataType) || typ. mutable || typ. abstract)
850+ typ = unwrap_unionall (widenconst (exprtype (a, src, mod)))
851+ if isType (typ)
852+ # all fields of subtypes of Type are effect-free
853+ # (including the non-inferrable uid field)
854+ elseif ! isa (typ, DataType) || typ. abstract || (typ. mutable && length (typ. types) > 0 )
855855 return false
856856 end
857857 end
@@ -874,7 +874,8 @@ function effect_free(@nospecialize(e), src::CodeInfo, mod::Module, allow_volatil
874874 # `Expr(:new)` of unknown type could raise arbitrary TypeError.
875875 typ, isexact = instanceof_tfunc (typ)
876876 isexact || return false
877- (isleaftype (typ) && ! iskindtype (typ)) || return false
877+ isconcretetype (typ) || return false
878+ ! iskindtype (typ) || return false
878879 typ = typ:: DataType
879880 if ! allow_volatile && typ. mutable
880881 return false
@@ -1086,11 +1087,11 @@ function inlineable(@nospecialize(f), @nospecialize(ft), e::Expr, atypes::Vector
10861087 sv:: OptimizationState )
10871088 argexprs = e. args
10881089
1089- if (f === typeassert || ft ⊑ typeof (typeassert)) && length (atypes)== 3
1090+ if (f === typeassert || ft ⊑ typeof (typeassert)) && length (atypes) == 3
10901091 # typeassert(x::S, T) => x, when S<:T
10911092 a3 = atypes[3 ]
1092- if (isType (a3) && isleaftype (a3) && atypes[2 ] ⊑ a3. parameters[1 ]) ||
1093- (isa (a3,Const) && isa (a3. val,Type) && atypes[2 ] ⊑ a3. val)
1093+ if (isType (a3) && ! has_free_typevars (a3) && atypes[2 ] ⊑ a3. parameters[1 ]) ||
1094+ (isa (a3, Const) && isa (a3. val, Type) && atypes[2 ] ⊑ a3. val)
10941095 return (argexprs[2 ], ())
10951096 end
10961097 end
@@ -1119,7 +1120,9 @@ function inlineable(@nospecialize(f), @nospecialize(ft), e::Expr, atypes::Vector
11191120 if f === Core. invoke && length (atypes) >= 3
11201121 ft = widenconst (atypes[2 ])
11211122 invoke_tt = widenconst (atypes[3 ])
1122- if ! isleaftype (ft) || ! isleaftype (invoke_tt) || ! isType (invoke_tt)
1123+ if ! (isconcretetype (ft) || ft <: Type ) || ! isType (invoke_tt) ||
1124+ has_free_typevars (invoke_tt) || has_free_typevars (ft) || (ft <: Builtin )
1125+ # TODO : this is really aggressive at preventing inlining of closures. maybe drop `isconcretetype` requirement?
11231126 return NOT_FOUND
11241127 end
11251128 if ! (isa (invoke_tt. parameters[1 ], Type) &&
@@ -1282,12 +1285,10 @@ function inlineable(@nospecialize(f), @nospecialize(ft), e::Expr, atypes::Vector
12821285 haveconst = false
12831286 for i in 1 : length (atypes)
12841287 a = atypes[i]
1285- if isa (a, Const) && ! isdefined (typeof (a. val), :instance )
1286- if ! isleaftype (a. val) # alternately: !isa(a.val, DataType) || !isconstType(Type{a.val})
1287- # have new information from argtypes that wasn't available from the signature
1288- haveconst = true
1289- break
1290- end
1288+ if isa (a, Const) && ! isdefined (typeof (a. val), :instance ) && ! (isa (a. val, Type) && issingletontype (a. val))
1289+ # have new information from argtypes that wasn't available from the signature
1290+ haveconst = true
1291+ break
12911292 end
12921293 end
12931294 if haveconst
@@ -1549,8 +1550,9 @@ end
15491550
15501551# saturating sum (inputs are nonnegative), prevents overflow with typemax(Int) below
15511552plus_saturate (x, y) = max (x, y, x+ y)
1553+
15521554# known return type
1553- isknowntype (T) = (T == Union{}) || isleaftype (T)
1555+ isknowntype (@nospecialize T) = (T == Union{}) || isconcretetype (T)
15541556
15551557function statement_cost (ex:: Expr , line:: Int , src:: CodeInfo , mod:: Module , params:: Params )
15561558 head = ex. head
@@ -1781,7 +1783,8 @@ function inline_call(e::Expr, sv::OptimizationState, stmts::Vector{Any}, boundsc
17811783 ft = Bool
17821784 else
17831785 f = nothing
1784- if ! ( isleaftype (ft) || ft<: Type )
1786+ if ! (isconcretetype (ft) || (widenconst (ft) <: Type )) || has_free_typevars (ft)
1787+ # TODO : this is really aggressive at preventing inlining of closures. maybe drop `isconcretetype` requirement?
17851788 return e
17861789 end
17871790 end
@@ -1938,7 +1941,8 @@ function inline_call(e::Expr, sv::OptimizationState, stmts::Vector{Any}, boundsc
19381941 ft = Bool
19391942 else
19401943 f = nothing
1941- if ! ( isleaftype (ft) || ft<: Type )
1944+ if ! (isconcretetype (ft) || (widenconst (ft) <: Type )) || has_free_typevars (ft)
1945+ # TODO : this is really aggressive at preventing inlining of closures. maybe drop `isconcretetype` requirement?
19421946 return e
19431947 end
19441948 end
@@ -2754,15 +2758,15 @@ end
27542758
27552759function split_disjoint_assign! (ctx:: AllocOptContext , info, key)
27562760 key. second && return false
2757- isleaftype ( ctx. sv. src. slottypes[key. first]) && return false
2761+ isdispatchelem ( widenconst ( ctx. sv. src. slottypes[key. first])) && return false # no splitting can be necessary
27582762 alltypes = IdDict ()
27592763 ndefs = length (info. defs)
27602764 deftypes = Vector {Any} (uninitialized, ndefs)
27612765 for i in 1 : ndefs
27622766 def = info. defs[i]
27632767 defex = (def. assign:: Expr ). args[2 ]
27642768 rhstyp = widenconst (exprtype (defex, ctx. sv. src, ctx. sv. mod))
2765- isleaftype (rhstyp) || return false
2769+ isdispatchelem (rhstyp) || return false
27662770 alltypes[rhstyp] = nothing
27672771 deftypes[i] = rhstyp
27682772 end
@@ -2772,7 +2776,7 @@ function split_disjoint_assign!(ctx::AllocOptContext, info, key)
27722776 slot = usex. args[use. exidx]
27732777 if isa (slot, TypedSlot)
27742778 usetyp = widenconst (slot. typ)
2775- if isleaftype (usetyp)
2779+ if isdispatchelem (usetyp)
27762780 alltypes[usetyp] = nothing
27772781 continue
27782782 end
@@ -2827,7 +2831,7 @@ function split_disjoint_assign!(ctx::AllocOptContext, info, key)
28272831 slot = usex. args[use. exidx]
28282832 if isa (slot, TypedSlot)
28292833 usetyp = widenconst (slot. typ)
2830- if isleaftype (usetyp)
2834+ if isdispatchelem (usetyp)
28312835 usetyp = widenconst (slot. typ)
28322836 new_slot = alltypes[usetyp]
28332837 if ! isa (new_slot, SlotNumber)
@@ -2997,7 +3001,7 @@ function split_struct_alloc!(ctx::AllocOptContext, info, key)
29973001 elseif defex. head === :new
29983002 typ = widenconst (exprtype (defex, ctx. sv. src, ctx. sv. mod))
29993003 # typ <: Tuple shouldn't happen but just in case someone generated invalid AST
3000- if ! isa (typ, DataType) || ! isleaftype (typ) || typ <: Tuple
3004+ if ! isa (typ, DataType) || ! isdispatchelem (typ) || typ <: Tuple
30013005 return false
30023006 end
30033007 si = structinfo_new (ctx, defex, typ)
0 commit comments