Skip to content

Miscompilation: Equal pointers compare as inequal #60696

Closed as not planned
Closed as not planned
@JakobDegen

Description

@JakobDegen

Upstream issue: rust-lang/rust#107975 .

Godbolt.

define void @_ZN7example3foo17h7be158369849a4c6E(ptr noalias nocapture noundef sret({ i64, i64, i8, [7 x i8] }) dereferenceable(24) %0) unnamed_addr #0 {
start:
  %1 = alloca i8, align 1
  %2 = alloca i8, align 1
  %v1 = alloca [16 x i8], align 1
  %v = alloca [16 x i8], align 1
  call void @llvm.lifetime.start.p0(i64 16, ptr %v)
  call void @llvm.lifetime.start.p0(i64 1, ptr %2)
  store i8 4, ptr %2, align 1
  call void asm sideeffect "", "r,~{memory}"(ptr %2)
  %_4 = load i8, ptr %2, align 1
  call void @llvm.lifetime.end.p0(i64 1, ptr %2)
  %3 = getelementptr inbounds [16 x i8], ptr %v, i64 0, i64 0
  call void @llvm.memset.p0.i64(ptr align 1 %3, i8 %_4, i64 16, i1 false)
  %_6 = getelementptr inbounds [16 x i8], ptr %v, i64 0, i64 0
  call void @llvm.lifetime.end.p0(i64 16, ptr %v)
  call void @llvm.lifetime.start.p0(i64 16, ptr %v1)
  call void @llvm.lifetime.start.p0(i64 1, ptr %1)
  store i8 4, ptr %1, align 1
  call void asm sideeffect "", "r,~{memory}"(ptr %1)
  %_9 = load i8, ptr %1, align 1
  call void @llvm.lifetime.end.p0(i64 1, ptr %1)
  %4 = getelementptr inbounds [16 x i8], ptr %v1, i64 0, i64 0
  call void @llvm.memset.p0.i64(ptr align 1 %4, i8 %_9, i64 16, i1 false)
  %_11 = getelementptr inbounds [16 x i8], ptr %v1, i64 0, i64 0
  call void @llvm.lifetime.end.p0(i64 16, ptr %v1)
  %_13 = ptrtoint ptr %_6 to i64
  %_15 = ptrtoint ptr %_11 to i64
  %_17 = icmp eq ptr %_6, %_11
  store i64 %_13, ptr %0, align 8
  %5 = getelementptr inbounds { i64, i64, i8, [7 x i8] }, ptr %0, i32 0, i32 1
  store i64 %_15, ptr %5, align 8
  %6 = getelementptr inbounds { i64, i64, i8, [7 x i8] }, ptr %0, i32 0, i32 2
  %7 = zext i1 %_17 to i8
  store i8 %7, ptr %6, align 8
  ret void
}

declare void @llvm.memset.p0.i64(ptr nocapture writeonly, i8, i64, i1 immarg) #1

declare void @llvm.lifetime.start.p0(i64 immarg, ptr nocapture) #2

declare void @llvm.lifetime.end.p0(i64 immarg, ptr nocapture) #2

This function creates two stack allocations with disjoint lifetimes and returns the pointers of those allocations cast to integers, as well as the result of comparing those pointers for equality. After optimization, the comparison is folded to false:

define void @_ZN7example3foo17h7be158369849a4c6E(ptr noalias nocapture noundef writeonly sret({ i64, i64, i8, [7 x i8] }) dereferenceable(24) %0) unnamed_addr {
  %1 = alloca i8, align 1
  %2 = alloca i8, align 1
  %v1 = alloca [16 x i8], align 1
  %v = alloca [16 x i8], align 1
  call void @llvm.lifetime.start.p0(i64 16, ptr nonnull %v)
  call void @llvm.lifetime.start.p0(i64 1, ptr nonnull %2)
  store i8 4, ptr %2, align 1
  call void asm sideeffect "", "r,~{memory}"(ptr nonnull %2) #1
  call void @llvm.lifetime.end.p0(i64 1, ptr nonnull %2)
  call void @llvm.lifetime.end.p0(i64 16, ptr nonnull %v)
  call void @llvm.lifetime.start.p0(i64 16, ptr nonnull %v1)
  call void @llvm.lifetime.start.p0(i64 1, ptr nonnull %1)
  store i8 4, ptr %1, align 1
  call void asm sideeffect "", "r,~{memory}"(ptr nonnull %1) #1
  call void @llvm.lifetime.end.p0(i64 1, ptr nonnull %1)
  call void @llvm.lifetime.end.p0(i64 16, ptr nonnull %v1)
  %_13 = ptrtoint ptr %v to i64
  %_15 = ptrtoint ptr %v1 to i64
  store i64 %_13, ptr %0, align 8
  %3 = getelementptr inbounds { i64, i64, i8, [7 x i8] }, ptr %0, i64 0, i32 1
  store i64 %_15, ptr %3, align 8
  %4 = getelementptr inbounds { i64, i64, i8, [7 x i8] }, ptr %0, i64 0, i32 2
  store i8 0, ptr %4, align 8
  ret void
}

declare void @llvm.lifetime.start.p0(i64 immarg, ptr nocapture) #0

declare void @llvm.lifetime.end.p0(i64 immarg, ptr nocapture) #0

attributes #0 = { mustprogress nocallback nofree nosync nounwind willreturn memory(argmem: readwrite) }
attributes #1 = { nounwind }

However, the addresses of these pointers may be equal. This reproduces as an end-to-end miscompilation in Rust.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions