585
585
add_tfunc (nfields, 1 , 1 , nfields_tfunc, 1 )
586
586
add_tfunc (Core. _expr, 1 , INT_INF, @nospecs ((𝕃:: AbstractLattice , args... )-> Expr), 100 )
587
587
add_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
+
588
597
@nospecs function _svec_ref_tfunc (𝕃:: AbstractLattice , s, i)
589
598
if isa (s, Const) && isa (i, Const)
590
599
s, i = s. val, i. val
@@ -1986,15 +1995,8 @@ function tuple_tfunc(𝕃::AbstractLattice, argtypes::Vector{Any})
1986
1995
# UnionAll context is missing around this.
1987
1996
pop! (argtypes)
1988
1997
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 )... ))
1998
2000
end
1999
2001
params = Vector {Any} (undef, length (argtypes))
2000
2002
anyinfo = false
@@ -2359,14 +2361,17 @@ function _builtin_nothrow(𝕃::AbstractLattice, @nospecialize(f::Builtin), argt
2359
2361
elseif f === Core. compilerbarrier
2360
2362
na == 2 || return false
2361
2363
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
2362
2367
elseif f === Core. _svec_ref
2363
2368
na == 2 || return false
2364
2369
return _svec_ref_tfunc (𝕃, argtypes[1 ], argtypes[2 ]) isa Const
2365
2370
end
2366
2371
return false
2367
2372
end
2368
2373
2369
- # known to be always effect-free (in particular nothrow)
2374
+ # known to be always effect-free (in particular also nothrow)
2370
2375
const _PURE_BUILTINS = Any[
2371
2376
tuple,
2372
2377
svec,
@@ -2395,6 +2400,8 @@ const _CONSISTENT_BUILTINS = Any[
2395
2400
donotdelete,
2396
2401
memoryrefnew,
2397
2402
memoryrefoffset,
2403
+ Core. _svec_len,
2404
+ Core. _svec_ref,
2398
2405
]
2399
2406
2400
2407
# known to be effect-free (but not necessarily nothrow)
@@ -2419,6 +2426,7 @@ const _EFFECT_FREE_BUILTINS = [
2419
2426
Core. throw_methoderror,
2420
2427
getglobal,
2421
2428
compilerbarrier,
2429
+ Core. _svec_len,
2422
2430
Core. _svec_ref,
2423
2431
]
2424
2432
@@ -2453,6 +2461,7 @@ const _ARGMEM_BUILTINS = Any[
2453
2461
replacefield!,
2454
2462
setfield!,
2455
2463
swapfield!,
2464
+ Core. _svec_len,
2456
2465
Core. _svec_ref,
2457
2466
]
2458
2467
@@ -2637,7 +2646,7 @@ function builtin_effects(𝕃::AbstractLattice, @nospecialize(f::Builtin), argty
2637
2646
else
2638
2647
if contains_is (_CONSISTENT_BUILTINS, f)
2639
2648
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
2641
2650
consistent = CONSISTENT_IF_INACCESSIBLEMEMONLY
2642
2651
elseif f === Core. _typevar || f === Core. memorynew
2643
2652
consistent = CONSISTENT_IF_NOTRETURNED
@@ -2746,11 +2755,12 @@ end
2746
2755
function builtin_tfunction (interp:: AbstractInterpreter , @nospecialize (f), argtypes:: Vector{Any} ,
2747
2756
sv:: Union{AbsIntState, Nothing} )
2748
2757
𝕃ᵢ = 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 )
2752
2762
try
2753
- # unroll a few cases which have specialized codegen
2763
+ # unroll a few common cases for better codegen
2754
2764
if length (argvals) == 1
2755
2765
return Const (f (argvals[1 ]))
2756
2766
elseif length (argvals) == 2
@@ -2764,6 +2774,8 @@ function builtin_tfunction(interp::AbstractInterpreter, @nospecialize(f), argtyp
2764
2774
return Bottom
2765
2775
end
2766
2776
end
2777
+ end
2778
+ if isa (f, IntrinsicFunction)
2767
2779
iidx = Int (reinterpret (Int32, f)) + 1
2768
2780
if iidx < 0 || iidx > length (T_IFUNC)
2769
2781
# unknown intrinsic
@@ -2790,6 +2802,7 @@ function builtin_tfunction(interp::AbstractInterpreter, @nospecialize(f), argtyp
2790
2802
end
2791
2803
tf = T_FFUNC_VAL[fidx]
2792
2804
end
2805
+
2793
2806
if hasvarargtype (argtypes)
2794
2807
if length (argtypes) - 1 > tf[2 ]
2795
2808
# definitely too many arguments
0 commit comments