@@ -816,8 +816,8 @@ function effect_free(@nospecialize(e), src::CodeInfo, mod::Module, allow_volatil
816
816
return true
817
817
end
818
818
if head === :static_parameter
819
- # if we aren't certain about the type, it might be an UndefVarError at runtime
820
- return ( isa (e. typ, DataType) && isleaftype (e . typ)) || isa ( e. typ, Const )
819
+ # if we aren't certain enough about the type, it might be an UndefVarError at runtime
820
+ return isa (e. typ, Const) || issingletontype ( widenconst ( e. typ) )
821
821
end
822
822
if e. typ === Bottom
823
823
return false
@@ -830,17 +830,17 @@ function effect_free(@nospecialize(e), src::CodeInfo, mod::Module, allow_volatil
830
830
return false
831
831
elseif is_known_call (e, getfield, src, mod)
832
832
nargs = length (ea)
833
- (2 < nargs < 5 ) || return false
833
+ (3 < nargs < 4 ) || return false
834
834
et = exprtype (e, src, mod)
835
- if ! isa (et, Const) && ! (isType (et) && isleaftype (et))
835
+ # TODO : check ninitialized
836
+ if ! isa (et, Const) && ! isconstType (et)
836
837
# first argument must be immutable to ensure e is affect_free
837
838
a = ea[2 ]
838
- typ = widenconst (exprtype (a, src, mod))
839
- if isconstType (typ)
840
- if Const (:uid ) ⊑ exprtype (ea[3 ], src, mod)
841
- return false # DataType uid field can change
842
- end
843
- elseif typ != = SimpleVector && (! isa (typ, DataType) || typ. mutable || typ. abstract)
839
+ typ = unwrap_unionall (widenconst (exprtype (a, src, mod)))
840
+ if isType (typ)
841
+ # all fields of subtypes of Type are effect-free
842
+ # (including the non-inferrable uid field)
843
+ elseif ! isa (typ, DataType) || typ. abstract || (typ. mutable && length (typ. types) > 0 )
844
844
return false
845
845
end
846
846
end
@@ -863,7 +863,8 @@ function effect_free(@nospecialize(e), src::CodeInfo, mod::Module, allow_volatil
863
863
# `Expr(:new)` of unknown type could raise arbitrary TypeError.
864
864
typ, isexact = instanceof_tfunc (typ)
865
865
isexact || return false
866
- (isleaftype (typ) && ! iskindtype (typ)) || return false
866
+ isconcretetype (typ) || return false
867
+ ! iskindtype (typ) || return false
867
868
typ = typ:: DataType
868
869
if ! allow_volatile && typ. mutable
869
870
return false
@@ -1075,11 +1076,11 @@ function inlineable(@nospecialize(f), @nospecialize(ft), e::Expr, atypes::Vector
1075
1076
sv:: OptimizationState )
1076
1077
argexprs = e. args
1077
1078
1078
- if (f === typeassert || ft ⊑ typeof (typeassert)) && length (atypes)== 3
1079
+ if (f === typeassert || ft ⊑ typeof (typeassert)) && length (atypes) == 3
1079
1080
# typeassert(x::S, T) => x, when S<:T
1080
1081
a3 = atypes[3 ]
1081
- if (isType (a3) && isleaftype (a3) && atypes[2 ] ⊑ a3. parameters[1 ]) ||
1082
- (isa (a3,Const) && isa (a3. val,Type) && atypes[2 ] ⊑ a3. val)
1082
+ if (isType (a3) && ! has_free_typevars (a3) && atypes[2 ] ⊑ a3. parameters[1 ]) ||
1083
+ (isa (a3, Const) && isa (a3. val, Type) && atypes[2 ] ⊑ a3. val)
1083
1084
return (argexprs[2 ], ())
1084
1085
end
1085
1086
end
@@ -1108,7 +1109,9 @@ function inlineable(@nospecialize(f), @nospecialize(ft), e::Expr, atypes::Vector
1108
1109
if f === Core. invoke && length (atypes) >= 3
1109
1110
ft = widenconst (atypes[2 ])
1110
1111
invoke_tt = widenconst (atypes[3 ])
1111
- if ! isleaftype (ft) || ! isleaftype (invoke_tt) || ! isType (invoke_tt)
1112
+ if ! (isconcretetype (ft) || ft <: Type ) || ! isType (invoke_tt) ||
1113
+ has_free_typevars (invoke_tt) || has_free_typevars (ft) || (ft <: Builtin )
1114
+ # TODO : this is really aggressive at preventing inlining of closures. maybe drop `isconcretetype` requirement?
1112
1115
return NOT_FOUND
1113
1116
end
1114
1117
if ! (isa (invoke_tt. parameters[1 ], Type) &&
@@ -1271,12 +1274,10 @@ function inlineable(@nospecialize(f), @nospecialize(ft), e::Expr, atypes::Vector
1271
1274
haveconst = false
1272
1275
for i in 1 : length (atypes)
1273
1276
a = atypes[i]
1274
- if isa (a, Const) && ! isdefined (typeof (a. val), :instance )
1275
- if ! isleaftype (a. val) # alternately: !isa(a.val, DataType) || !isconstType(Type{a.val})
1276
- # have new information from argtypes that wasn't available from the signature
1277
- haveconst = true
1278
- break
1279
- end
1277
+ if isa (a, Const) && ! isdefined (typeof (a. val), :instance ) && ! (isa (a. val, Type) && issingletontype (a. val))
1278
+ # have new information from argtypes that wasn't available from the signature
1279
+ haveconst = true
1280
+ break
1280
1281
end
1281
1282
end
1282
1283
if haveconst
@@ -1538,8 +1539,9 @@ end
1538
1539
1539
1540
# saturating sum (inputs are nonnegative), prevents overflow with typemax(Int) below
1540
1541
plus_saturate (x, y) = max (x, y, x+ y)
1542
+
1541
1543
# known return type
1542
- isknowntype (T) = (T == Union{}) || isleaftype (T)
1544
+ isknowntype (@nospecialize T) = (T == Union{}) || isconcretetype (T)
1543
1545
1544
1546
function statement_cost (ex:: Expr , line:: Int , src:: CodeInfo , mod:: Module , params:: Params )
1545
1547
head = ex. head
@@ -1770,7 +1772,8 @@ function inline_call(e::Expr, sv::OptimizationState, stmts::Vector{Any}, boundsc
1770
1772
ft = Bool
1771
1773
else
1772
1774
f = nothing
1773
- if ! ( isleaftype (ft) || ft<: Type )
1775
+ if ! (isconcretetype (ft) || (widenconst (ft) <: Type )) || has_free_typevars (ft)
1776
+ # TODO : this is really aggressive at preventing inlining of closures. maybe drop `isconcretetype` requirement?
1774
1777
return e
1775
1778
end
1776
1779
end
@@ -1927,7 +1930,8 @@ function inline_call(e::Expr, sv::OptimizationState, stmts::Vector{Any}, boundsc
1927
1930
ft = Bool
1928
1931
else
1929
1932
f = nothing
1930
- if ! ( isleaftype (ft) || ft<: Type )
1933
+ if ! (isconcretetype (ft) || (widenconst (ft) <: Type )) || has_free_typevars (ft)
1934
+ # TODO : this is really aggressive at preventing inlining of closures. maybe drop `isconcretetype` requirement?
1931
1935
return e
1932
1936
end
1933
1937
end
@@ -2745,15 +2749,15 @@ end
2745
2749
2746
2750
function split_disjoint_assign! (ctx:: AllocOptContext , info, key)
2747
2751
key. second && return false
2748
- isleaftype ( ctx. sv. src. slottypes[key. first]) && return false
2752
+ isdispatchelem ( widenconst ( ctx. sv. src. slottypes[key. first])) && return false # no splitting can be necessary
2749
2753
alltypes = ObjectIdDict ()
2750
2754
ndefs = length (info. defs)
2751
2755
deftypes = Vector {Any} (uninitialized, ndefs)
2752
2756
for i in 1 : ndefs
2753
2757
def = info. defs[i]
2754
2758
defex = (def. assign:: Expr ). args[2 ]
2755
2759
rhstyp = widenconst (exprtype (defex, ctx. sv. src, ctx. sv. mod))
2756
- isleaftype (rhstyp) || return false
2760
+ isdispatchelem (rhstyp) || return false
2757
2761
alltypes[rhstyp] = nothing
2758
2762
deftypes[i] = rhstyp
2759
2763
end
@@ -2763,7 +2767,7 @@ function split_disjoint_assign!(ctx::AllocOptContext, info, key)
2763
2767
slot = usex. args[use. exidx]
2764
2768
if isa (slot, TypedSlot)
2765
2769
usetyp = widenconst (slot. typ)
2766
- if isleaftype (usetyp)
2770
+ if isdispatchelem (usetyp)
2767
2771
alltypes[usetyp] = nothing
2768
2772
continue
2769
2773
end
@@ -2818,7 +2822,7 @@ function split_disjoint_assign!(ctx::AllocOptContext, info, key)
2818
2822
slot = usex. args[use. exidx]
2819
2823
if isa (slot, TypedSlot)
2820
2824
usetyp = widenconst (slot. typ)
2821
- if isleaftype (usetyp)
2825
+ if isdispatchelem (usetyp)
2822
2826
usetyp = widenconst (slot. typ)
2823
2827
new_slot = alltypes[usetyp]
2824
2828
if ! isa (new_slot, SlotNumber)
@@ -2988,7 +2992,7 @@ function split_struct_alloc!(ctx::AllocOptContext, info, key)
2988
2992
elseif defex. head === :new
2989
2993
typ = widenconst (exprtype (defex, ctx. sv. src, ctx. sv. mod))
2990
2994
# typ <: Tuple shouldn't happen but just in case someone generated invalid AST
2991
- if ! isa (typ, DataType) || ! isleaftype (typ) || typ <: Tuple
2995
+ if ! isa (typ, DataType) || ! isdispatchelem (typ) || typ <: Tuple
2992
2996
return false
2993
2997
end
2994
2998
si = structinfo_new (ctx, defex, typ)
0 commit comments