585585add_tfunc (nfields, 1 , 1 , nfields_tfunc, 1 )
586586add_tfunc (Core. _expr, 1 , INT_INF, @nospecs ((𝕃:: AbstractLattice , args... )-> Expr), 100 )
587587add_tfunc (svec, 0 , INT_INF, @nospecs ((𝕃:: AbstractLattice , args... )-> SimpleVector), 20 )
588+
589+ @nospecs function _svec_len_tfunc (𝕃:: AbstractLattice , s)
590+ if isa (s, Const) && isa (s. val, SimpleVector)
591+ return Const (length (s. val))
592+ end
593+ return Int
594+ end
595+ add_tfunc (Core. _svec_len, 1 , 1 , _svec_len_tfunc, 1 )
596+
588597@nospecs function _svec_ref_tfunc (𝕃:: AbstractLattice , s, i)
589598 if isa (s, Const) && isa (i, Const)
590599 s, i = s. val, i. val
@@ -1986,15 +1995,8 @@ function tuple_tfunc(𝕃::AbstractLattice, argtypes::Vector{Any})
19861995 # UnionAll context is missing around this.
19871996 pop! (argtypes)
19881997 end
1989- all_are_const = true
1990- for i in 1 : length (argtypes)
1991- if ! isa (argtypes[i], Const)
1992- all_are_const = false
1993- break
1994- end
1995- end
1996- if all_are_const
1997- return Const (ntuple (i:: Int -> argtypes[i]. val, length (argtypes)))
1998+ if is_all_const_arg (argtypes, 1 ) # repeated from builtin_tfunction for the benefit of callers that use this tfunc directly
1999+ return Const (tuple (collect_const_args (argtypes, 1 )... ))
19982000 end
19992001 params = Vector {Any} (undef, length (argtypes))
20002002 anyinfo = false
@@ -2359,14 +2361,17 @@ function _builtin_nothrow(𝕃::AbstractLattice, @nospecialize(f::Builtin), argt
23592361 elseif f === Core. compilerbarrier
23602362 na == 2 || return false
23612363 return compilerbarrier_nothrow (argtypes[1 ], nothing )
2364+ elseif f === Core. _svec_len
2365+ na == 1 || return false
2366+ return _svec_len_tfunc (𝕃, argtypes[1 ]) isa Const
23622367 elseif f === Core. _svec_ref
23632368 na == 2 || return false
23642369 return _svec_ref_tfunc (𝕃, argtypes[1 ], argtypes[2 ]) isa Const
23652370 end
23662371 return false
23672372end
23682373
2369- # known to be always effect-free (in particular nothrow)
2374+ # known to be always effect-free (in particular also nothrow)
23702375const _PURE_BUILTINS = Any[
23712376 tuple,
23722377 svec,
@@ -2395,6 +2400,8 @@ const _CONSISTENT_BUILTINS = Any[
23952400 donotdelete,
23962401 memoryrefnew,
23972402 memoryrefoffset,
2403+ Core. _svec_len,
2404+ Core. _svec_ref,
23982405]
23992406
24002407# known to be effect-free (but not necessarily nothrow)
@@ -2419,6 +2426,7 @@ const _EFFECT_FREE_BUILTINS = [
24192426 Core. throw_methoderror,
24202427 getglobal,
24212428 compilerbarrier,
2429+ Core. _svec_len,
24222430 Core. _svec_ref,
24232431]
24242432
@@ -2453,6 +2461,7 @@ const _ARGMEM_BUILTINS = Any[
24532461 replacefield!,
24542462 setfield!,
24552463 swapfield!,
2464+ Core. _svec_len,
24562465 Core. _svec_ref,
24572466]
24582467
@@ -2637,7 +2646,7 @@ function builtin_effects(𝕃::AbstractLattice, @nospecialize(f::Builtin), argty
26372646 else
26382647 if contains_is (_CONSISTENT_BUILTINS, f)
26392648 consistent = ALWAYS_TRUE
2640- elseif f === memoryrefget || f === memoryrefset! || f === memoryref_isassigned || f === Core. _svec_ref
2649+ elseif f === memoryrefget || f === memoryrefset! || f === memoryref_isassigned || f === Core. _svec_len || f === Core . _svec_ref
26412650 consistent = CONSISTENT_IF_INACCESSIBLEMEMONLY
26422651 elseif f === Core. _typevar || f === Core. memorynew
26432652 consistent = CONSISTENT_IF_NOTRETURNED
@@ -2746,11 +2755,12 @@ end
27462755function builtin_tfunction (interp:: AbstractInterpreter , @nospecialize (f), argtypes:: Vector{Any} ,
27472756 sv:: Union{AbsIntState, Nothing} )
27482757 𝕃ᵢ = typeinf_lattice (interp)
2749- if isa (f, IntrinsicFunction)
2750- if is_pure_intrinsic_infer (f) && all (@nospecialize (a) -> isa (a, Const), argtypes)
2751- argvals = anymap (@nospecialize (a) -> (a:: Const ). val, argtypes)
2758+ # Early constant evaluation for foldable builtins with all const args
2759+ if isa (f, IntrinsicFunction) ? is_pure_intrinsic_infer (f) : (f in _PURE_BUILTINS || (f in _CONSISTENT_BUILTINS && f in _EFFECT_FREE_BUILTINS))
2760+ if is_all_const_arg (argtypes, 1 )
2761+ argvals = collect_const_args (argtypes, 1 )
27522762 try
2753- # unroll a few cases which have specialized codegen
2763+ # unroll a few common cases for better codegen
27542764 if length (argvals) == 1
27552765 return Const (f (argvals[1 ]))
27562766 elseif length (argvals) == 2
@@ -2764,6 +2774,8 @@ function builtin_tfunction(interp::AbstractInterpreter, @nospecialize(f), argtyp
27642774 return Bottom
27652775 end
27662776 end
2777+ end
2778+ if isa (f, IntrinsicFunction)
27672779 iidx = Int (reinterpret (Int32, f)) + 1
27682780 if iidx < 0 || iidx > length (T_IFUNC)
27692781 # unknown intrinsic
@@ -2790,6 +2802,7 @@ function builtin_tfunction(interp::AbstractInterpreter, @nospecialize(f), argtyp
27902802 end
27912803 tf = T_FFUNC_VAL[fidx]
27922804 end
2805+
27932806 if hasvarargtype (argtypes)
27942807 if length (argtypes) - 1 > tf[2 ]
27952808 # definitely too many arguments
0 commit comments