580580add_tfunc (nfields, 1 , 1 , nfields_tfunc, 1 )
581581add_tfunc (Core. _expr, 1 , INT_INF, @nospecs ((𝕃:: AbstractLattice , args... )-> Expr), 100 )
582582add_tfunc (svec, 0 , INT_INF, @nospecs ((𝕃:: AbstractLattice , args... )-> SimpleVector), 20 )
583+ 
584+ @nospecs  function  _svec_len_tfunc (𝕃:: AbstractLattice , s)
585+     if  isa (s, Const) &&  isa (s. val, SimpleVector)
586+         return  Const (length (s. val))
587+     end 
588+     return  Int
589+ end 
590+ add_tfunc (Core. _svec_len, 1 , 1 , _svec_len_tfunc, 1 )
591+ 
583592@nospecs  function  _svec_ref_tfunc (𝕃:: AbstractLattice , s, i)
584593    if  isa (s, Const) &&  isa (i, Const)
585594        s, i =  s. val, i. val
@@ -1960,15 +1969,8 @@ function tuple_tfunc(𝕃::AbstractLattice, argtypes::Vector{Any})
19601969        #  UnionAll context is missing around this.
19611970        pop! (argtypes)
19621971    end 
1963-     all_are_const =  true 
1964-     for  i in  1 : length (argtypes)
1965-         if  ! isa (argtypes[i], Const)
1966-             all_are_const =  false 
1967-             break 
1968-         end 
1969-     end 
1970-     if  all_are_const
1971-         return  Const (ntuple (i:: Int -> argtypes[i]. val, length (argtypes)))
1972+     if  is_all_const_arg (argtypes, 1 ) #  repeated from builtin_tfunction for the benefit of callers that use this tfunc directly
1973+         return  Const (tuple (collect_const_args (argtypes, 1 )... ))
19721974    end 
19731975    params =  Vector {Any} (undef, length (argtypes))
19741976    anyinfo =  false 
@@ -2334,14 +2336,17 @@ function _builtin_nothrow(𝕃::AbstractLattice, @nospecialize(f::Builtin), argt
23342336    elseif  f ===  Core. compilerbarrier
23352337        na ==  2  ||  return  false 
23362338        return  compilerbarrier_nothrow (argtypes[1 ], nothing )
2339+     elseif  f ===  Core. _svec_len
2340+         na ==  1  ||  return  false 
2341+         return  _svec_len_tfunc (𝕃, argtypes[1 ]) isa  Const
23372342    elseif  f ===  Core. _svec_ref
23382343        na ==  2  ||  return  false 
23392344        return  _svec_ref_tfunc (𝕃, argtypes[1 ], argtypes[2 ]) isa  Const
23402345    end 
23412346    return  false 
23422347end 
23432348
2344- #  known to be always effect-free (in particular nothrow)
2349+ #  known to be always effect-free (in particular also  nothrow)
23452350const  _PURE_BUILTINS =  Any[
23462351    tuple,
23472352    svec,
@@ -2370,6 +2375,8 @@ const _CONSISTENT_BUILTINS = Any[
23702375    donotdelete,
23712376    memoryrefnew,
23722377    memoryrefoffset,
2378+     Core. _svec_len,
2379+     Core. _svec_ref,
23732380]
23742381
23752382#  known to be effect-free (but not necessarily nothrow)
@@ -2394,6 +2401,7 @@ const _EFFECT_FREE_BUILTINS = [
23942401    Core. throw_methoderror,
23952402    getglobal,
23962403    compilerbarrier,
2404+     Core. _svec_len,
23972405    Core. _svec_ref,
23982406]
23992407
@@ -2428,6 +2436,7 @@ const _ARGMEM_BUILTINS = Any[
24282436    replacefield!,
24292437    setfield!,
24302438    swapfield!,
2439+     Core. _svec_len,
24312440    Core. _svec_ref,
24322441]
24332442
@@ -2571,6 +2580,7 @@ const _EFFECTS_KNOWN_BUILTINS = Any[
25712580    #  Core._primitivetype,
25722581    #  Core._setsuper!,
25732582    #  Core._structtype,
2583+     Core. _svec_len,
25742584    Core. _svec_ref,
25752585    #  Core._typebody!,
25762586    Core. _typevar,
@@ -2675,7 +2685,7 @@ function builtin_effects(𝕃::AbstractLattice, @nospecialize(f::Builtin), argty
26752685    else 
26762686        if  contains_is (_CONSISTENT_BUILTINS, f)
26772687            consistent =  ALWAYS_TRUE
2678-         elseif  f ===  memoryrefget ||  f ===  memoryrefset! ||  f ===  memoryref_isassigned ||  f ===  Core. _svec_ref
2688+         elseif  f ===  memoryrefget ||  f ===  memoryrefset! ||  f ===  memoryref_isassigned ||  f ===  Core. _svec_len  ||  f  ===  Core . _svec_ref
26792689            consistent =  CONSISTENT_IF_INACCESSIBLEMEMONLY
26802690        elseif  f ===  Core. _typevar ||  f ===  Core. memorynew
26812691            consistent =  CONSISTENT_IF_NOTRETURNED
@@ -2784,11 +2794,12 @@ end
27842794function  builtin_tfunction (interp:: AbstractInterpreter , @nospecialize (f), argtypes:: Vector{Any} ,
27852795                           sv:: Union{AbsIntState, Nothing} )
27862796    𝕃ᵢ =  typeinf_lattice (interp)
2787-     if  isa (f, IntrinsicFunction)
2788-         if  is_pure_intrinsic_infer (f) &&  all (@nospecialize (a) ->  isa (a, Const), argtypes)
2789-             argvals =  anymap (@nospecialize (a) ->  (a:: Const ). val, argtypes)
2797+     #  Early constant evaluation for foldable builtins with all const args
2798+     if  isa (f, IntrinsicFunction) ?  is_pure_intrinsic_infer (f) :  (f in  _PURE_BUILTINS ||  (f in  _CONSISTENT_BUILTINS &&  f in  _EFFECT_FREE_BUILTINS))
2799+         if  is_all_const_arg (argtypes, 1 )
2800+             argvals =  collect_const_args (argtypes, 1 )
27902801            try 
2791-                 #  unroll a few cases which have specialized  codegen
2802+                 #  unroll a few common  cases for better  codegen
27922803                if  length (argvals) ==  1 
27932804                    return  Const (f (argvals[1 ]))
27942805                elseif  length (argvals) ==  2 
@@ -2802,6 +2813,8 @@ function builtin_tfunction(interp::AbstractInterpreter, @nospecialize(f), argtyp
28022813                return  Bottom
28032814            end 
28042815        end 
2816+     end 
2817+     if  isa (f, IntrinsicFunction)
28052818        iidx =  Int (reinterpret (Int32, f)) +  1 
28062819        if  iidx <  0  ||  iidx >  length (T_IFUNC)
28072820            #  unknown intrinsic
@@ -2828,6 +2841,7 @@ function builtin_tfunction(interp::AbstractInterpreter, @nospecialize(f), argtyp
28282841        end 
28292842        tf =  T_FFUNC_VAL[fidx]
28302843    end 
2844+ 
28312845    if  hasvarargtype (argtypes)
28322846        if  length (argtypes) -  1  >  tf[2 ]
28332847            #  definitely too many arguments
0 commit comments