@@ -461,8 +461,10 @@ add_tfunc(Core._typevar, 3, 3, typevar_tfunc, 100)
461461add_tfunc (applicable, 1 , INT_INF, (@nospecialize (f), args... )-> Bool, 100 )
462462add_tfunc (Core. Intrinsics. arraylen, 1 , 1 , @nospecialize (x)-> Int, 4 )
463463
464+ const Arrayish = Union{Array,ImmutableArray}
465+
464466function arraysize_tfunc (@nospecialize (ary), @nospecialize (dim))
465- hasintersect (widenconst (ary), Array ) || return Bottom
467+ hasintersect (widenconst (ary), Arrayish ) || return Bottom
466468 hasintersect (widenconst (dim), Int) || return Bottom
467469 return Int
468470end
@@ -472,7 +474,7 @@ function arraysize_nothrow(argtypes::Vector{Any})
472474 length (argtypes) == 2 || return false
473475 ary = argtypes[1 ]
474476 dim = argtypes[2 ]
475- ary ⊑ Array || return false
477+ widenconst ( ary) <: Arrayish || return false
476478 if isa (dim, Const)
477479 dimval = dim. val
478480 return isa (dimval, Int) && dimval > 0
@@ -1535,27 +1537,27 @@ function tuple_tfunc(argtypes::Vector{Any})
15351537end
15361538
15371539arrayref_tfunc (@nospecialize (boundscheck), @nospecialize (ary), @nospecialize idxs... ) =
1538- _arrayref_tfunc (boundscheck, ary, idxs)
1539- function _arrayref_tfunc (@nospecialize (boundscheck ), @nospecialize (ary),
1540- @nospecialize idxs:: Tuple )
1540+ _arrayref_tfunc (Arrayish, boundscheck, ary, idxs)
1541+ function _arrayref_tfunc (@nospecialize (Arytype ),
1542+ @nospecialize (boundscheck), @nospecialize (ary), @nospecialize idxs:: Tuple )
15411543 isempty (idxs) && return Bottom
1542- array_builtin_common_errorcheck (boundscheck, ary, idxs) || return Bottom
1543- return array_elmtype (ary)
1544+ array_builtin_common_errorcheck (Arytype, boundscheck, ary, idxs) || return Bottom
1545+ return array_elmtype (Arytype, ary)
15441546end
15451547add_tfunc (arrayref, 3 , INT_INF, arrayref_tfunc, 20 )
15461548add_tfunc (const_arrayref, 3 , INT_INF, arrayref_tfunc, 20 )
15471549
15481550function arrayset_tfunc (@nospecialize (boundscheck), @nospecialize (ary), @nospecialize (item),
15491551 @nospecialize idxs... )
1550- hasintersect (widenconst (item), _arrayref_tfunc (boundscheck, ary, idxs)) || return Bottom
1552+ hasintersect (widenconst (item), _arrayref_tfunc (Array, boundscheck, ary, idxs)) || return Bottom
15511553 return ary
15521554end
15531555add_tfunc (arrayset, 4 , INT_INF, arrayset_tfunc, 20 )
15541556
1555- function array_builtin_common_errorcheck (@nospecialize (boundscheck), @nospecialize (ary ),
1556- @nospecialize idxs:: Tuple )
1557+ function array_builtin_common_errorcheck (@nospecialize (Arytype ),
1558+ @nospecialize (boundscheck), @nospecialize (ary), @nospecialize idxs:: Tuple )
15571559 hasintersect (widenconst (boundscheck), Bool) || return false
1558- hasintersect (widenconst (ary), Array ) || return false
1560+ hasintersect (widenconst (ary), Arytype ) || return false
15591561 for i = 1 : length (idxs)
15601562 idx = getfield (idxs, i)
15611563 idx = isvarargtype (idx) ? unwrapva (idx) : widenconst (idx)
@@ -1564,9 +1566,9 @@ function array_builtin_common_errorcheck(@nospecialize(boundscheck), @nospeciali
15641566 return true
15651567end
15661568
1567- function array_elmtype (@nospecialize ary)
1569+ function array_elmtype (@nospecialize (Arytype), @nospecialize ary)
15681570 a = widenconst (ary)
1569- if ! has_free_typevars (a) && a <: Array
1571+ if ! has_free_typevars (a) && a <: Arytype
15701572 a0 = a
15711573 if isa (a, UnionAll)
15721574 a = unwrap_unionall (a0)
@@ -1580,6 +1582,32 @@ function array_elmtype(@nospecialize ary)
15801582 return Any
15811583end
15821584
1585+ # the ImmutableArray operations might involve copies and so their computation costs can be high,
1586+ # nevertheless we assign smaller inlining costs to them here, since the escape analysis
1587+ # at this moment isn't able to propagate array escapes interprocedurally
1588+ # and it will fail to optimize most cases without inlining
1589+
1590+ arrayfreeze_tfunc (@nospecialize a) = immutable_array_tfunc (Array, ImmutableArray, a)
1591+ add_tfunc (Core. arrayfreeze, 1 , 1 , arrayfreeze_tfunc, 20 )
1592+
1593+ mutating_arrayfreeze_tfunc (@nospecialize a) = immutable_array_tfunc (Array, ImmutableArray, a)
1594+ add_tfunc (Core. mutating_arrayfreeze, 1 , 1 , mutating_arrayfreeze_tfunc, 10 )
1595+
1596+ arraythaw_tfunc (@nospecialize a) = immutable_array_tfunc (ImmutableArray, Array, a)
1597+ add_tfunc (Core. arraythaw, 1 , 1 , arraythaw_tfunc, 20 )
1598+
1599+ function immutable_array_tfunc (@nospecialize (at), @nospecialize (rt), @nospecialize (a))
1600+ a = widenconst (a)
1601+ hasintersect (a, at) || return Bottom
1602+ if a <: at
1603+ unw = unwrap_unionall (a)
1604+ if isa (unw, DataType)
1605+ return rewrap_unionall (rt{unw. parameters[1 ], unw. parameters[2 ]}, a)
1606+ end
1607+ end
1608+ return rt
1609+ end
1610+
15831611function _opaque_closure_tfunc (@nospecialize (arg), @nospecialize (isva),
15841612 @nospecialize (lb), @nospecialize (ub), @nospecialize (source), env:: Vector{Any} ,
15851613 linfo:: MethodInstance )
@@ -1613,11 +1641,12 @@ function array_type_undefable(@nospecialize(arytype))
16131641 end
16141642end
16151643
1616- function array_builtin_common_nothrow (argtypes:: Vector{Any} , first_idx_idx:: Int )
1644+ function array_builtin_common_nothrow (@nospecialize (Arytype),
1645+ argtypes:: Vector{Any} , first_idx_idx:: Int )
16171646 length (argtypes) >= 4 || return false
16181647 boundscheck = argtypes[1 ]
16191648 arytype = argtypes[2 ]
1620- array_builtin_common_typecheck (boundscheck, arytype, argtypes, first_idx_idx) || return false
1649+ array_builtin_common_typecheck (Arytype, boundscheck, arytype, argtypes, first_idx_idx) || return false
16211650 # If we could potentially throw undef ref errors, bail out now.
16221651 arytype = widenconst (arytype)
16231652 array_type_undefable (arytype) && return false
@@ -1632,12 +1661,12 @@ function array_builtin_common_nothrow(argtypes::Vector{Any}, first_idx_idx::Int)
16321661 return false
16331662end
16341663
1635- function array_builtin_common_typecheck (
1664+ function array_builtin_common_typecheck (@nospecialize (Arytype),
16361665 @nospecialize (boundscheck), @nospecialize (arytype),
16371666 argtypes:: Vector{Any} , first_idx_idx:: Int )
1638- (boundscheck ⊑ Bool && arytype ⊑ Array ) || return false
1667+ (widenconst ( boundscheck) <: Bool && widenconst ( arytype) <: Arytype ) || return false
16391668 for i = first_idx_idx: length (argtypes)
1640- argtypes[i] ⊑ Int || return false
1669+ widenconst ( argtypes[i]) <: Int || return false
16411670 end
16421671 return true
16431672end
@@ -1656,11 +1685,11 @@ end
16561685# Query whether the given builtin is guaranteed not to throw given the argtypes
16571686function _builtin_nothrow (@nospecialize (f), argtypes:: Array{Any,1} , @nospecialize (rt))
16581687 if f === arrayset
1659- array_builtin_common_nothrow (argtypes, 4 ) || return true
1688+ array_builtin_common_nothrow (Array, argtypes, 4 ) || return true
16601689 # Additionally check element type compatibility
16611690 return arrayset_typecheck (argtypes[2 ], argtypes[3 ])
16621691 elseif f === arrayref || f === const_arrayref
1663- return array_builtin_common_nothrow (argtypes, 3 )
1692+ return array_builtin_common_nothrow (Arrayish, argtypes, 3 )
16641693 elseif f === arraysize
16651694 return arraysize_nothrow (argtypes)
16661695 elseif f === Core. _expr
@@ -1818,8 +1847,7 @@ function builtin_tfunction(interp::AbstractInterpreter, @nospecialize(f), argtyp
18181847 end
18191848 end
18201849 return rt
1821- end
1822- if isa (f, IntrinsicFunction)
1850+ elseif isa (f, IntrinsicFunction)
18231851 if is_pure_intrinsic_infer (f) && _all (@nospecialize (a) -> isa (a, Const), argtypes)
18241852 argvals = anymap (@nospecialize (a) -> (a:: Const ). val, argtypes)
18251853 try
0 commit comments