@@ -1994,7 +1994,6 @@ add_tfunc(Core.memoryrefmodify!, 5, 5, memoryrefmodify!_tfunc, 20)
19941994add_tfunc (Core. memoryrefreplace!, 6 , 6 , memoryrefreplace!_tfunc, 20 )
19951995add_tfunc (Core. memoryrefsetonce!, 5 , 5 , memoryrefsetonce!_tfunc, 20 )
19961996
1997-
19981997@nospecs function memoryref_isassigned_tfunc (𝕃:: AbstractLattice , mem, order, boundscheck)
19991998 return _memoryref_isassigned_tfunc (𝕃, mem, order, boundscheck)
20001999end
@@ -2176,9 +2175,12 @@ end
21762175 return boundscheck ⊑ Bool && memtype ⊑ GenericMemoryRef && order ⊑ Symbol
21772176end
21782177
2179- # Query whether the given builtin is guaranteed not to throw given the argtypes
2180- @nospecs function _builtin_nothrow (𝕃:: AbstractLattice , f, argtypes:: Vector{Any} , rt)
2178+ # Query whether the given builtin is guaranteed not to throw given the `argtypes`.
2179+ # `argtypes` can be assumed not to contain varargs.
2180+ function _builtin_nothrow (𝕃:: AbstractLattice , @nospecialize (f:: Builtin ), argtypes:: Vector{Any} ,
2181+ @nospecialize (rt))
21812182 ⊑ = partialorder (𝕃)
2183+ na = length (argtypes)
21822184 if f === memoryref
21832185 return memoryref_builtin_common_nothrow (argtypes)
21842186 elseif f === memoryrefoffset
@@ -2194,13 +2196,7 @@ end
21942196 elseif f === Core. _expr
21952197 length (argtypes) >= 1 || return false
21962198 return argtypes[1 ] ⊑ Symbol
2197- end
2198-
2199- # These builtins are not-vararg, so if we have varars, here, we can't guarantee
2200- # the correct number of arguments.
2201- na = length (argtypes)
2202- (na ≠ 0 && isvarargtype (argtypes[end ])) && return false
2203- if f === Core. _typevar
2199+ elseif f === Core. _typevar
22042200 na == 3 || return false
22052201 return typevar_nothrow (𝕃, argtypes[1 ], argtypes[2 ], argtypes[3 ])
22062202 elseif f === invoke
@@ -2225,8 +2221,6 @@ end
22252221 elseif f === (< :)
22262222 na == 2 || return false
22272223 return subtype_nothrow (𝕃, argtypes[1 ], argtypes[2 ])
2228- elseif f === UnionAll
2229- return na == 2 && (argtypes[1 ] ⊑ TypeVar && argtypes[2 ] ⊑ Type)
22302224 elseif f === isdefined
22312225 return isdefined_nothrow (𝕃, argtypes)
22322226 elseif f === Core. sizeof
@@ -2334,7 +2328,7 @@ const _INACCESSIBLEMEM_BUILTINS = Any[
23342328 typeof,
23352329 compilerbarrier,
23362330 Core. _typevar,
2337- donotdelete
2331+ donotdelete,
23382332]
23392333
23402334const _ARGMEM_BUILTINS = Any[
@@ -2505,8 +2499,7 @@ function builtin_effects(𝕃::AbstractLattice, @nospecialize(f::Builtin), argty
25052499 return Effects (EFFECTS_TOTAL;
25062500 consistent = ALWAYS_FALSE,
25072501 notaskstate = false ,
2508- nothrow
2509- )
2502+ nothrow)
25102503 else
25112504 if contains_is (_CONSISTENT_BUILTINS, f)
25122505 consistent = ALWAYS_TRUE
@@ -2526,7 +2519,7 @@ function builtin_effects(𝕃::AbstractLattice, @nospecialize(f::Builtin), argty
25262519 else
25272520 effect_free = ALWAYS_FALSE
25282521 end
2529- nothrow = ( isempty (argtypes) || ! isvarargtype (argtypes[ end ])) && builtin_nothrow (𝕃, f, argtypes, rt)
2522+ nothrow = builtin_nothrow (𝕃, f, argtypes, rt)
25302523 if contains_is (_INACCESSIBLEMEM_BUILTINS, f)
25312524 inaccessiblememonly = ALWAYS_TRUE
25322525 elseif contains_is (_ARGMEM_BUILTINS, f)
@@ -2543,7 +2536,6 @@ function builtin_effects(𝕃::AbstractLattice, @nospecialize(f::Builtin), argty
25432536 end
25442537end
25452538
2546-
25472539function memoryop_noub (@nospecialize (f), argtypes:: Vector{Any} )
25482540 nargs = length (argtypes)
25492541 nargs == 0 && return true # must throw and noub
@@ -2600,14 +2592,22 @@ function current_scope_tfunc(interp::AbstractInterpreter, sv::InferenceState)
26002592end
26012593current_scope_tfunc (interp:: AbstractInterpreter , sv) = Any
26022594
2595+ hasvarargtype (argtypes:: Vector{Any} ) = ! isempty (argtypes) && isvarargtype (argtypes[end ])
2596+
26032597"""
26042598 builtin_nothrow(𝕃::AbstractLattice, f::Builtin, argtypes::Vector{Any}, rt) -> Bool
26052599
26062600Compute throw-ness of a builtin function call. `argtypes` should not include `f` itself.
26072601"""
26082602function builtin_nothrow (𝕃:: AbstractLattice , @nospecialize (f), argtypes:: Vector{Any} , @nospecialize (rt))
26092603 rt === Bottom && return false
2610- contains_is (_PURE_BUILTINS, f) && return true
2604+ if f === tuple || f === svec
2605+ return true
2606+ elseif hasvarargtype (argtypes)
2607+ return false
2608+ elseif contains_is (_PURE_BUILTINS, f)
2609+ return true
2610+ end
26112611 return _builtin_nothrow (𝕃, f, argtypes, rt)
26122612end
26132613
@@ -2632,7 +2632,7 @@ function builtin_tfunction(interp::AbstractInterpreter, @nospecialize(f), argtyp
26322632 return Bottom
26332633 end
26342634 end
2635- iidx = Int (reinterpret (Int32, f:: IntrinsicFunction )) + 1
2635+ iidx = Int (reinterpret (Int32, f)) + 1
26362636 if iidx < 0 || iidx > length (T_IFUNC)
26372637 # unknown intrinsic
26382638 return Any
@@ -2656,8 +2656,7 @@ function builtin_tfunction(interp::AbstractInterpreter, @nospecialize(f), argtyp
26562656 end
26572657 tf = T_FFUNC_VAL[fidx]
26582658 end
2659- tf = tf:: Tuple{Int, Int, Any}
2660- if ! isempty (argtypes) && isvarargtype (argtypes[end ])
2659+ if hasvarargtype (argtypes)
26612660 if length (argtypes) - 1 > tf[2 ]
26622661 # definitely too many arguments
26632662 return Bottom
@@ -2687,8 +2686,6 @@ _iszero(@nospecialize x) = x === Intrinsics.xor_int(x, x)
26872686_isneg1 (@nospecialize x) = _iszero (Intrinsics. not_int (x))
26882687_istypemin (@nospecialize x) = ! _iszero (x) && Intrinsics. neg_int (x) === x
26892688
2690-
2691-
26922689function builtin_exct (𝕃:: AbstractLattice , @nospecialize (f:: Builtin ), argtypes:: Vector{Any} , @nospecialize (rt))
26932690 if isa (f, IntrinsicFunction)
26942691 return intrinsic_exct (𝕃, f, argtypes)
@@ -2698,7 +2695,6 @@ end
26982695
26992696function div_nothrow (f:: IntrinsicFunction , @nospecialize (arg1), @nospecialize (arg2))
27002697 isa (arg2, Const) || return false
2701-
27022698 den_val = arg2. val
27032699 _iszero (den_val) && return false
27042700 f != = Intrinsics. checked_sdiv_int && return true
@@ -2713,18 +2709,17 @@ function known_is_valid_intrinsic_elptr(𝕃::AbstractLattice, @nospecialize(ptr
27132709end
27142710
27152711function intrinsic_exct (𝕃:: AbstractLattice , f:: IntrinsicFunction , argtypes:: Vector{Any} )
2716- if ! isempty (argtypes) && isvarargtype (argtypes[ end ] )
2712+ if hasvarargtype (argtypes)
27172713 return Any
27182714 end
27192715
27202716 # First check that we have the correct number of arguments
2721- iidx = Int (reinterpret (Int32, f:: IntrinsicFunction )) + 1
2717+ iidx = Int (reinterpret (Int32, f)) + 1
27222718 if iidx < 1 || iidx > length (T_IFUNC)
27232719 # invalid intrinsic (system will crash)
27242720 return Any
27252721 end
27262722 tf = T_IFUNC[iidx]
2727- tf = tf:: Tuple{Int, Int, Any}
27282723 if ! (tf[1 ] <= length (argtypes) <= tf[2 ])
27292724 # wrong # of args
27302725 return ArgumentError
@@ -2736,7 +2731,8 @@ function intrinsic_exct(𝕃::AbstractLattice, f::IntrinsicFunction, argtypes::V
27362731 # that it won't
27372732 f === Intrinsics. llvmcall && return Any
27382733
2739- if f === Intrinsics. checked_udiv_int || f === Intrinsics. checked_urem_int || f === Intrinsics. checked_srem_int || f === Intrinsics. checked_sdiv_int
2734+ if (f === Intrinsics. checked_udiv_int || f === Intrinsics. checked_urem_int ||
2735+ f === Intrinsics. checked_srem_int || f === Intrinsics. checked_sdiv_int)
27402736 # Nothrow as long as the second argument is guaranteed not to be zero
27412737 arg1 = argtypes[1 ]
27422738 arg2 = argtypes[2 ]
@@ -2788,8 +2784,8 @@ function intrinsic_exct(𝕃::AbstractLattice, f::IntrinsicFunction, argtypes::V
27882784 end
27892785
27902786 if f in (Intrinsics. sext_int, Intrinsics. zext_int, Intrinsics. trunc_int,
2791- Intrinsics. fptoui, Intrinsics. fptosi, Intrinsics. uitofp,
2792- Intrinsics. sitofp, Intrinsics. fptrunc, Intrinsics. fpext)
2787+ Intrinsics. fptoui, Intrinsics. fptosi, Intrinsics. uitofp,
2788+ Intrinsics. sitofp, Intrinsics. fptrunc, Intrinsics. fpext)
27932789 # If !isconcrete, `ty` may be Union{} at runtime even if we have
27942790 # isprimitivetype(ty).
27952791 ty, isexact, isconcrete = instanceof_tfunc (argtypes[1 ], true )
@@ -2851,14 +2847,13 @@ function intrinsic_effects(f::IntrinsicFunction, argtypes::Vector{Any})
28512847 # llvmcall can do arbitrary things
28522848 return Effects ()
28532849 end
2854-
28552850 if contains_is (_INCONSISTENT_INTRINSICS, f)
28562851 consistent = ALWAYS_FALSE
28572852 else
28582853 consistent = ALWAYS_TRUE
28592854 end
28602855 effect_free = ! (f === Intrinsics. pointerset) ? ALWAYS_TRUE : ALWAYS_FALSE
2861- nothrow = ( isempty (argtypes) || ! isvarargtype (argtypes[ end ])) && intrinsic_nothrow (f, argtypes)
2856+ nothrow = intrinsic_nothrow (f, argtypes)
28622857 inaccessiblememonly = ALWAYS_TRUE
28632858 return Effects (EFFECTS_TOTAL; consistent, effect_free, nothrow, inaccessiblememonly)
28642859end
@@ -3103,7 +3098,6 @@ add_tfunc(Core.modifyglobal!, 4, 5, modifyglobal!_tfunc, 3)
31033098add_tfunc (Core. replaceglobal!, 4 , 6 , replaceglobal!_tfunc, 3 )
31043099add_tfunc (Core. setglobalonce!, 3 , 5 , setglobalonce!_tfunc, 3 )
31053100
3106-
31073101@nospecs function setglobal!_nothrow (M, s, newty, o)
31083102 global_order_nothrow (o, #= loading=# false , #= storing=# true ) || return false
31093103 return setglobal!_nothrow (M, s, newty)
0 commit comments