@@ -329,9 +329,14 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
329329 self . write_scalar ( offset_ptr, dest) ?;
330330 }
331331 sym:: ptr_guaranteed_eq | sym:: ptr_guaranteed_ne => {
332- // FIXME: return `true` for at least some comparisons where we can reliably
333- // determine the result of runtime (in)equality tests at compile-time.
334- self . write_scalar ( Scalar :: from_bool ( false ) , dest) ?;
332+ let a = self . read_immediate ( args[ 0 ] ) ?. to_scalar ( ) ?;
333+ let b = self . read_immediate ( args[ 1 ] ) ?. to_scalar ( ) ?;
334+ let cmp = if intrinsic_name == sym:: ptr_guaranteed_eq {
335+ self . guaranteed_eq ( a, b)
336+ } else {
337+ self . guaranteed_ne ( a, b)
338+ } ;
339+ self . write_scalar ( Scalar :: from_bool ( cmp) , dest) ?;
335340 }
336341 sym:: ptr_offset_from => {
337342 let a = self . read_immediate ( args[ 0 ] ) ?. to_scalar ( ) ?;
@@ -448,6 +453,37 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
448453 Ok ( true )
449454 }
450455
456+ fn guaranteed_eq ( & mut self , a : Scalar < M :: PointerTag > , b : Scalar < M :: PointerTag > ) -> bool {
457+ match ( a, b) {
458+ // Comparisons between integers are always known.
459+ ( Scalar :: Raw { .. } , Scalar :: Raw { .. } ) => a == b,
460+ // Equality with integers can never be known for sure.
461+ ( Scalar :: Raw { .. } , Scalar :: Ptr ( _) ) | ( Scalar :: Ptr ( _) , Scalar :: Raw { .. } ) => false ,
462+ // FIXME: return `true` for when both sides are the same pointer, *except* that
463+ // some things (like functions and vtables) do not have stable addresses
464+ // so we need to be careful around them.
465+ ( Scalar :: Ptr ( _) , Scalar :: Ptr ( _) ) => false ,
466+ }
467+ }
468+
469+ fn guaranteed_ne ( & mut self , a : Scalar < M :: PointerTag > , b : Scalar < M :: PointerTag > ) -> bool {
470+ match ( a, b) {
471+ // Comparisons between integers are always known.
472+ ( Scalar :: Raw { .. } , Scalar :: Raw { .. } ) => a != b,
473+ // Comparisons of abstract pointers with null pointers are known if the pointer
474+ // is in bounds, because if they are in bounds, the pointer can't be null.
475+ ( Scalar :: Raw { data : 0 , .. } , Scalar :: Ptr ( ptr) )
476+ | ( Scalar :: Ptr ( ptr) , Scalar :: Raw { data : 0 , .. } ) => !self . memory . ptr_may_be_null ( ptr) ,
477+ // Inequality with integers other than null can never be known for sure.
478+ ( Scalar :: Raw { .. } , Scalar :: Ptr ( _) ) | ( Scalar :: Ptr ( _) , Scalar :: Raw { .. } ) => false ,
479+ // FIXME: return `true` for at least some comparisons where we can reliably
480+ // determine the result of runtime inequality tests at compile-time.
481+ // Examples include comparison of addresses in static items, for these we can
482+ // give reliable results.
483+ ( Scalar :: Ptr ( _) , Scalar :: Ptr ( _) ) => false ,
484+ }
485+ }
486+
451487 pub fn exact_div (
452488 & mut self ,
453489 a : ImmTy < ' tcx , M :: PointerTag > ,
0 commit comments