@@ -1664,7 +1664,9 @@ and OpHasEffect g m op =
16641664 | TOp.ExnFieldGet ( ecref, n) -> isExnFieldMutable ecref n
16651665 | TOp.RefAddrGet _ -> false
16661666 | TOp.AnonRecdGet _ -> true // conservative
1667- | TOp.ValFieldGet rfref -> rfref.RecdField.IsMutable || ( TryFindTyconRefBoolAttribute g range0 g.attrib_ AllowNullLiteralAttribute rfref.TyconRef = Some true )
1667+ | TOp.ValFieldGet rfref ->
1668+ rfref.RecdField.IsMutable
1669+ || ( TryFindTyconRefBoolAttribute g range0 g.attrib_ AllowNullLiteralAttribute rfref.TyconRef = Some true )
16681670 | TOp.ValFieldGetAddr ( rfref, _ readonly) -> rfref.RecdField.IsMutable
16691671 | TOp.UnionCaseFieldGetAddr _ -> false // union case fields are immutable
16701672 | TOp.LValueOp ( LAddrOf _, _) -> false // addresses of values are always constants
@@ -3167,7 +3169,7 @@ and CanDevirtualizeApplication cenv v vref ty args =
31673169 && not ( isUnitTy g ty)
31683170 && isAppTy g ty
31693171 // Exclusion: Some unions have null as representations
3170- && not ( IsUnionTypeWithNullAsTrueValue g ( fst( StripToNominalTyconRef cenv ty)) .Deref)
3172+ && not ( IsUnionTypeWithNullAsTrueValue g ( fst( StripToNominalTyconRef cenv ty)) .Deref)
31713173 // If we de-virtualize an operation on structs then we have to take the address of the object argument
31723174 // Hence we have to actually have the object argument available to us,
31733175 && ( not ( isStructTy g ty) || not ( isNil args))
@@ -3189,9 +3191,13 @@ and TakeAddressOfStructArgumentIfNeeded cenv (vref: ValRef) ty args m =
31893191 else
31903192 id, args
31913193
3192- and DevirtualizeApplication cenv env ( vref : ValRef ) ty tyargs args m =
3194+ and DevirtualizeApplication cenv env ( vref : ValRef ) ty tyargs args m nullHandlerOpt =
31933195 let g = cenv.g
3194- let wrap , args = TakeAddressOfStructArgumentIfNeeded cenv vref ty args m
3196+ let wrap , args =
3197+ match nullHandlerOpt with
3198+ | Some nullHandler when g.checkNullness && TypeNullIsExtraValueNew g vref.Range ty ->
3199+ nullHandler g m, args
3200+ | _ -> TakeAddressOfStructArgumentIfNeeded cenv vref ty args m
31953201 let transformedExpr = wrap ( MakeApplicationAndBetaReduce g ( exprForValRef m vref, vref.Type, ( if isNil tyargs then [] else [ tyargs]), args, m))
31963202 OptimizeExpr cenv env transformedExpr
31973203
@@ -3212,8 +3218,10 @@ and TryDevirtualizeApplication cenv env (f, tyargs, args, m) =
32123218 | Expr.Val ( v, _, _), [ ty], _ when CanDevirtualizeApplication cenv v g.generic_ comparison_ inner_ vref ty args ->
32133219
32143220 let tcref , tyargs = StripToNominalTyconRef cenv ty
3215- match tcref.GeneratedCompareToValues with
3216- | Some (_, vref) -> Some ( DevirtualizeApplication cenv env vref ty tyargs args m)
3221+ match tcref.GeneratedCompareToValues, args with
3222+ | Some (_, vref), [ x; y] ->
3223+ let nullHandler g m = AugmentTypeDefinitions.mkBindNullComparison g m x y
3224+ Some ( DevirtualizeApplication cenv env vref ty tyargs args m ( Some nullHandler))
32173225 | _ -> None
32183226
32193227 | Expr.Val ( v, _, _), [ ty], _ when CanDevirtualizeApplication cenv v g.generic_ comparison_ withc_ inner_ vref ty args ->
@@ -3225,7 +3233,8 @@ and TryDevirtualizeApplication cenv env (f, tyargs, args, m) =
32253233 // arg list, and create a tuple of y & comp
32263234 // push the comparer to the end and box the argument
32273235 let args2 = [ x; mkRefTupledNoTypes g m [ mkCoerceExpr( y, g.obj_ ty_ ambivalent, m, ty) ; comp]]
3228- Some ( DevirtualizeApplication cenv env vref ty tyargs args2 m)
3236+ let nullHandler g m = AugmentTypeDefinitions.mkBindNullComparison g m x y
3237+ Some ( DevirtualizeApplication cenv env vref ty tyargs args2 m ( Some nullHandler))
32293238 | _ -> None
32303239
32313240 // Optimize/analyze calls to LanguagePrimitives.HashCompare.GenericEqualityIntrinsic when type is known
@@ -3235,8 +3244,10 @@ and TryDevirtualizeApplication cenv env (f, tyargs, args, m) =
32353244 | Expr.Val ( v, _, _), [ ty], _ when CanDevirtualizeApplication cenv v g.generic_ equality_ er_ inner_ vref ty args ->
32363245
32373246 let tcref , tyargs = StripToNominalTyconRef cenv ty
3238- match tcref.GeneratedHashAndEqualsValues with
3239- | Some (_, vref) -> Some ( DevirtualizeApplication cenv env vref ty tyargs args m)
3247+ match tcref.GeneratedHashAndEqualsValues, args with
3248+ | Some (_, vref),[ x; y] ->
3249+ let nullHandler g m = AugmentTypeDefinitions.mkBindThisNullEquals g m x y
3250+ Some ( DevirtualizeApplication cenv env vref ty tyargs args m ( Some nullHandler))
32403251 | _ -> None
32413252
32423253 // Optimize/analyze calls to LanguagePrimitives.HashCompare.GenericEqualityWithComparerIntrinsic
@@ -3246,11 +3257,13 @@ and TryDevirtualizeApplication cenv env (f, tyargs, args, m) =
32463257 | Some (_, _, _, Some withcEqualsExactVal), [ comp; x; y] ->
32473258 // push the comparer to the end
32483259 let args2 = [ x; mkRefTupledNoTypes g m [ y; comp]]
3249- Some ( DevirtualizeApplication cenv env withcEqualsExactVal ty tyargs args2 m)
3260+ let nullHandler g m = AugmentTypeDefinitions.mkBindThisNullEquals g m x y
3261+ Some ( DevirtualizeApplication cenv env withcEqualsExactVal ty tyargs args2 m ( Some nullHandler))
32503262 | Some (_, _, withcEqualsVal, _ ), [ comp; x; y] ->
32513263 // push the comparer to the end and box the argument
32523264 let args2 = [ x; mkRefTupledNoTypes g m [ mkCoerceExpr( y, g.obj_ ty_ ambivalent, m, ty) ; comp]]
3253- Some ( DevirtualizeApplication cenv env withcEqualsVal ty tyargs args2 m)
3265+ let nullHandler g m = AugmentTypeDefinitions.mkBindThisNullEquals g m x y
3266+ Some ( DevirtualizeApplication cenv env withcEqualsVal ty tyargs args2 m ( Some nullHandler))
32543267 | _ -> None
32553268
32563269 // Optimize/analyze calls to LanguagePrimitives.HashCompare.GenericEqualityIntrinsic
@@ -3259,20 +3272,23 @@ and TryDevirtualizeApplication cenv env (f, tyargs, args, m) =
32593272 match tcref.GeneratedHashAndEqualsWithComparerValues, args with
32603273 | Some (_, _, _, Some withcEqualsExactVal), [ x; y] ->
32613274 let args2 = [ x; mkRefTupledNoTypes g m [ y; ( mkCallGetGenericPEREqualityComparer g m)]]
3262- Some ( DevirtualizeApplication cenv env withcEqualsExactVal ty tyargs args2 m)
3275+ let nullHandler g m = AugmentTypeDefinitions.mkBindThisNullEquals g m x y
3276+ Some ( DevirtualizeApplication cenv env withcEqualsExactVal ty tyargs args2 m ( Some nullHandler))
32633277 | Some (_, _, withcEqualsVal, _), [ x; y] ->
32643278 let equalsExactOpt =
32653279 tcref.MembersOfFSharpTyconByName.TryFind( " Equals" )
32663280 |> Option.map ( List.where ( fun x -> x.IsCompilerGenerated))
32673281 |> Option.bind List.tryExactlyOne
32683282
3283+ let nullHandler g m = AugmentTypeDefinitions.mkBindThisNullEquals g m x y
3284+
32693285 match equalsExactOpt with
32703286 | Some equalsExact ->
32713287 let args2 = [ x; mkRefTupledNoTypes g m [ y; ( mkCallGetGenericPEREqualityComparer g m)]]
3272- Some ( DevirtualizeApplication cenv env equalsExact ty tyargs args2 m)
3288+ Some ( DevirtualizeApplication cenv env equalsExact ty tyargs args2 m ( Some nullHandler ) )
32733289 | None ->
32743290 let args2 = [ x; mkRefTupledNoTypes g m [ mkCoerceExpr( y, g.obj_ ty_ ambivalent, m, ty); ( mkCallGetGenericPEREqualityComparer g m)]]
3275- Some ( DevirtualizeApplication cenv env withcEqualsVal ty tyargs args2 m)
3291+ Some ( DevirtualizeApplication cenv env withcEqualsVal ty tyargs args2 m ( Some nullHandler ) )
32763292 | _ -> None
32773293
32783294 // Optimize/analyze calls to LanguagePrimitives.HashCompare.GenericHashIntrinsic
@@ -3281,7 +3297,8 @@ and TryDevirtualizeApplication cenv env (f, tyargs, args, m) =
32813297 match tcref.GeneratedHashAndEqualsWithComparerValues, args with
32823298 | Some (_, withcGetHashCodeVal, _, _), [ x] ->
32833299 let args2 = [ x; mkCallGetGenericEREqualityComparer g m]
3284- Some ( DevirtualizeApplication cenv env withcGetHashCodeVal ty tyargs args2 m)
3300+ let nullHandler g m = AugmentTypeDefinitions.mkBindNullHash g m x
3301+ Some ( DevirtualizeApplication cenv env withcGetHashCodeVal ty tyargs args2 m ( Some nullHandler))
32853302 | _ -> None
32863303
32873304 // Optimize/analyze calls to LanguagePrimitives.HashCompare.GenericHashWithComparerIntrinsic
@@ -3290,7 +3307,8 @@ and TryDevirtualizeApplication cenv env (f, tyargs, args, m) =
32903307 match tcref.GeneratedHashAndEqualsWithComparerValues, args with
32913308 | Some (_, withcGetHashCodeVal, _, _), [ comp; x] ->
32923309 let args2 = [ x; comp]
3293- Some ( DevirtualizeApplication cenv env withcGetHashCodeVal ty tyargs args2 m)
3310+ let nullHandler g m = AugmentTypeDefinitions.mkBindNullHash g m x
3311+ Some ( DevirtualizeApplication cenv env withcGetHashCodeVal ty tyargs args2 m ( Some nullHandler))
32943312 | _ -> None
32953313
32963314 // Optimize/analyze calls to LanguagePrimitives.HashCompare.GenericComparisonWithComparerIntrinsic for tuple types
@@ -3304,7 +3322,7 @@ and TryDevirtualizeApplication cenv env (f, tyargs, args, m) =
33043322 | 5 -> Some g.generic_ compare_ withc_ tuple5_ vref
33053323 | _ -> None
33063324 match vref with
3307- | Some vref -> Some ( DevirtualizeApplication cenv env vref ty tyargs ( mkCallGetGenericComparer g m :: args) m)
3325+ | Some vref -> Some ( DevirtualizeApplication cenv env vref ty tyargs ( mkCallGetGenericComparer g m :: args) m None )
33083326 | None -> None
33093327
33103328 // Optimize/analyze calls to LanguagePrimitives.HashCompare.GenericHashWithComparerIntrinsic for tuple types
@@ -3318,7 +3336,7 @@ and TryDevirtualizeApplication cenv env (f, tyargs, args, m) =
33183336 | 5 -> Some g.generic_ hash_ withc_ tuple5_ vref
33193337 | _ -> None
33203338 match vref with
3321- | Some vref -> Some ( DevirtualizeApplication cenv env vref ty tyargs ( mkCallGetGenericEREqualityComparer g m :: args) m)
3339+ | Some vref -> Some ( DevirtualizeApplication cenv env vref ty tyargs ( mkCallGetGenericEREqualityComparer g m :: args) m None )
33223340 | None -> None
33233341
33243342 // Optimize/analyze calls to LanguagePrimitives.HashCompare.GenericEqualityIntrinsic for tuple types
@@ -3334,7 +3352,7 @@ and TryDevirtualizeApplication cenv env (f, tyargs, args, m) =
33343352 | 5 -> Some g.generic_ equals_ withc_ tuple5_ vref
33353353 | _ -> None
33363354 match vref with
3337- | Some vref -> Some ( DevirtualizeApplication cenv env vref ty tyargs ( mkCallGetGenericPEREqualityComparer g m :: args) m)
3355+ | Some vref -> Some ( DevirtualizeApplication cenv env vref ty tyargs ( mkCallGetGenericPEREqualityComparer g m :: args) m None )
33383356 | None -> None
33393357
33403358 // Optimize/analyze calls to LanguagePrimitives.HashCompare.GenericComparisonWithComparerIntrinsic for tuple types
@@ -3348,7 +3366,7 @@ and TryDevirtualizeApplication cenv env (f, tyargs, args, m) =
33483366 | 5 -> Some g.generic_ compare_ withc_ tuple5_ vref
33493367 | _ -> None
33503368 match vref with
3351- | Some vref -> Some ( DevirtualizeApplication cenv env vref ty tyargs args m)
3369+ | Some vref -> Some ( DevirtualizeApplication cenv env vref ty tyargs args m None )
33523370 | None -> None
33533371
33543372 // Optimize/analyze calls to LanguagePrimitives.HashCompare.GenericHashWithComparerIntrinsic for tuple types
@@ -3362,7 +3380,7 @@ and TryDevirtualizeApplication cenv env (f, tyargs, args, m) =
33623380 | 5 -> Some g.generic_ hash_ withc_ tuple5_ vref
33633381 | _ -> None
33643382 match vref with
3365- | Some vref -> Some ( DevirtualizeApplication cenv env vref ty tyargs args m)
3383+ | Some vref -> Some ( DevirtualizeApplication cenv env vref ty tyargs args m None )
33663384 | None -> None
33673385
33683386 // Optimize/analyze calls to LanguagePrimitives.HashCompare.GenericEqualityWithComparerIntrinsic for tuple types
@@ -3376,7 +3394,7 @@ and TryDevirtualizeApplication cenv env (f, tyargs, args, m) =
33763394 | 5 -> Some g.generic_ equals_ withc_ tuple5_ vref
33773395 | _ -> None
33783396 match vref with
3379- | Some vref -> Some ( DevirtualizeApplication cenv env vref ty tyargs args m)
3397+ | Some vref -> Some ( DevirtualizeApplication cenv env vref ty tyargs args m None )
33803398 | None -> None
33813399
33823400 // Calls to LanguagePrimitives.IntrinsicFunctions.UnboxGeneric can be optimized to calls to UnboxFast when we know that the
@@ -3385,15 +3403,15 @@ and TryDevirtualizeApplication cenv env (f, tyargs, args, m) =
33853403 | Expr.Val ( v, _, _), [ ty], _ when valRefEq g v g.unbox_ vref &&
33863404 canUseUnboxFast g m ty ->
33873405
3388- Some( DevirtualizeApplication cenv env g.unbox_ fast_ vref ty tyargs args m)
3406+ Some( DevirtualizeApplication cenv env g.unbox_ fast_ vref ty tyargs args m None )
33893407
33903408 // Calls to LanguagePrimitives.IntrinsicFunctions.TypeTestGeneric can be optimized to calls to TypeTestFast when we know that the
33913409 // target type isn't 'NullNotTrueValue', i.e. that the target type is not an F# union, record etc.
33923410 // Note TypeTestFast is just the .NET IL 'isinst' instruction followed by a non-null comparison
33933411 | Expr.Val ( v, _, _), [ ty], _ when valRefEq g v g.istype_ vref &&
33943412 canUseTypeTestFast g ty ->
33953413
3396- Some( DevirtualizeApplication cenv env g.istype_ fast_ vref ty tyargs args m)
3414+ Some( DevirtualizeApplication cenv env g.istype_ fast_ vref ty tyargs args m None )
33973415
33983416 // Don't fiddle with 'methodhandleof' calls - just remake the application
33993417 | Expr.Val ( vref, _, _), _, _ when valRefEq g vref g.methodhandleof_ vref ->
0 commit comments