@@ -466,29 +466,51 @@ add_tfunc(Core._typevar, 3, 3, typevar_tfunc, 100)
466466add_tfunc (applicable, 1 , INT_INF, (@nospecialize (f), args... )-> Bool, 100 )
467467add_tfunc (Core. Intrinsics. arraylen, 1 , 1 , @nospecialize (x)-> Int, 4 )
468468add_tfunc (arraysize, 2 , 2 , (@nospecialize (a), @nospecialize (d))-> Int, 4 )
469+
469470function pointer_eltype (@nospecialize (ptr))
470471 a = widenconst (ptr)
471- if a <: Ptr
472- if isa (a, DataType) && isa (a. parameters[1 ], Type)
473- return a. parameters[1 ]
474- elseif isa (a, UnionAll) && ! has_free_typevars (a)
475- unw = unwrap_unionall (a)
476- if isa (unw, DataType)
477- return rewrap_unionall (unw. parameters[1 ], a)
478- end
472+ if ! has_free_typevars (a)
473+ unw = unwrap_unionall (a)
474+ if isa (unw, DataType) && unw. name === Ptr. body. name
475+ T = unw. parameters[1 ]
476+ T isa Type && return rewrap_unionall (T, a)
479477 end
480478 end
481479 return Any
482480end
481+ function atomic_pointermodify_tfunc (ptr, op, v, order)
482+ @nospecialize
483+ a = widenconst (ptr)
484+ if ! has_free_typevars (a)
485+ unw = unwrap_unionall (a)
486+ if isa (unw, DataType) && unw. name === Ptr. body. name
487+ T = unw. parameters[1 ]
488+ # note: we could sometimes refine this to a PartialStruct if we analyzed `op(T, T)::T`
489+ T isa Type && return rewrap_unionall (Pair{T, T}, a)
490+ end
491+ end
492+ return Pair
493+ end
494+ function atomic_pointerreplace_tfunc (ptr, x, v, success_order, failure_order)
495+ @nospecialize
496+ a = widenconst (ptr)
497+ if ! has_free_typevars (a)
498+ unw = unwrap_unionall (a)
499+ if isa (unw, DataType) && unw. name === Ptr. body. name
500+ T = unw. parameters[1 ]
501+ T isa Type && return rewrap_unionall (Pair{T, Bool}, a)
502+ end
503+ end
504+ return Pair{T,Bool} where T
505+ end
483506add_tfunc (pointerref, 3 , 3 , (a, i, align) -> (@nospecialize ; pointer_eltype (a)), 4 )
484507add_tfunc (pointerset, 4 , 4 , (a, v, i, align) -> (@nospecialize ; a), 5 )
485-
486508add_tfunc (atomic_fence, 1 , 1 , (order) -> (@nospecialize ; Nothing), 4 )
487509add_tfunc (atomic_pointerref, 2 , 2 , (a, order) -> (@nospecialize ; pointer_eltype (a)), 4 )
488510add_tfunc (atomic_pointerset, 3 , 3 , (a, v, order) -> (@nospecialize ; a), 5 )
489511add_tfunc (atomic_pointerswap, 3 , 3 , (a, v, order) -> (@nospecialize ; pointer_eltype (a)), 5 )
490- add_tfunc (atomic_pointermodify, 4 , 4 , (a, op, v, order) -> ( @nospecialize ; T = pointer_eltype (a); Tuple{T, T}) , 5 )
491- add_tfunc (atomic_pointerreplace, 5 , 5 , (a, x, v, success_order, failure_order) -> ( @nospecialize ; Tuple{ pointer_eltype (a), Bool}) , 5 )
512+ add_tfunc (atomic_pointermodify, 4 , 4 , atomic_pointermodify_tfunc , 5 )
513+ add_tfunc (atomic_pointerreplace, 5 , 5 , atomic_pointerreplace_tfunc , 5 )
492514
493515# more accurate typeof_tfunc for vararg tuples abstract only in length
494516function typeof_concrete_vararg (t:: DataType )
@@ -911,11 +933,23 @@ setfield!_tfunc(o, f, v) = (@nospecialize; v)
911933
912934swapfield!_tfunc (o, f, v, order) = (@nospecialize ; getfield_tfunc (o, f))
913935swapfield!_tfunc (o, f, v) = (@nospecialize ; getfield_tfunc (o, f))
914- modifyfield!_tfunc (o, f, op, v, order) = (@nospecialize ; T = getfield_tfunc (o, f); T === Bottom ? T : Tuple{T, T})
915- modifyfield!_tfunc (o, f, op, v) = (@nospecialize ; T = getfield_tfunc (o, f); T === Bottom ? T : Tuple{T, T}) # TODO : also model op(o.f, v) call
936+ modifyfield!_tfunc (o, f, op, v, order) = (@nospecialize ; modifyfield!_tfunc (o, f, op, v))
937+ function modifyfield!_tfunc (o, f, op, v)
938+ @nospecialize
939+ T = _fieldtype_tfunc (o, isconcretetype (o), f)
940+ T === Bottom && return Bottom
941+ # note: we could sometimes refine this to a PartialStruct if we analyzed `op(o.f, v)::T`
942+ return instanceof_tfunc (apply_type_tfunc (Const (Pair), T, T))[1 ]
943+ end
916944replacefield!_tfunc (o, f, x, v, success_order, failure_order) = (@nospecialize ; replacefield!_tfunc (o, f, x, v))
917945replacefield!_tfunc (o, f, x, v, success_order) = (@nospecialize ; replacefield!_tfunc (o, f, x, v))
918- replacefield!_tfunc (o, f, x, v) = (@nospecialize ; T = getfield_tfunc (o, f); T === Bottom ? T : Tuple{widenconst (T), Bool})
946+ function replacefield!_tfunc (o, f, x, v)
947+ @nospecialize
948+ T = _fieldtype_tfunc (o, isconcretetype (o), f)
949+ T === Bottom && return Bottom
950+ return instanceof_tfunc (apply_type_tfunc (Const (Pair), T, Const (Bool)))[1 ]
951+ end
952+
919953# we could use tuple_tfunc instead of widenconst, but `o` is mutable, so that is unlikely to be beneficial
920954
921955add_tfunc (getfield, 2 , 4 , getfield_tfunc, 1 )
0 commit comments