Skip to content

Behavior of lifetime intrinsics depends on code that is never executed #169361

@tmiasko

Description

@tmiasko

Behavior of lifetime intrinsics depends on instructions that are yet to be executed or are never executed, with calamitous consequences.

Consider allocations a and b. Their lifetimes are disjoint, except for a single code path where they do overlap. This code path is executed only when allocations have been observed to have the same address -- an impossibility. On the one hand this code path must be dead, on the other hand removing it might change the behavior because lifetimes are no longer overlapping.

An Alive2 example demonstrating surprising consequences. In the example, it is invalid to replace %1 with 1 despite preceding assumption call void @llvm.assume(i1 %1). The nature of this specific failure might be an implementation detail of Alive2, but I hope conveys the overall sense of the issue.

define void @src() {
  %a = alloca ptr
  %b = alloca ptr
  call void @llvm.lifetime.start.p0(ptr %a)
  call void @llvm.lifetime.end.p0(ptr %a)
  call void @llvm.lifetime.start.p0(ptr %b)
  call void @llvm.lifetime.end.p0(ptr %b)
  %1 = icmp ne ptr %a, %b
  call void @llvm.assume(i1 %1)
  br i1 %1, label %bb2, label %bb1
bb1:
  call void @llvm.lifetime.start.p0(ptr %a)
  call void @llvm.lifetime.start.p0(ptr %b)
  call void @llvm.lifetime.end.p0(ptr %b)
  call void @llvm.lifetime.end.p0(ptr %a)
  br label %bb2
bb2:
  ret void
}

define void @tgt() {
  %a = alloca ptr
  %b = alloca ptr
  call void @llvm.lifetime.start.p0(ptr %a)
  call void @llvm.lifetime.end.p0(ptr %a)
  call void @llvm.lifetime.start.p0(ptr %b)
  call void @llvm.lifetime.end.p0(ptr %b)
  %1 = icmp ne ptr %a, %b
  call void @llvm.assume(i1 %1)
  br i1 1, label %bb2, label %bb1
bb1:
  call void @llvm.lifetime.start.p0(ptr %a)
  call void @llvm.lifetime.start.p0(ptr %b)
  call void @llvm.lifetime.end.p0(ptr %b)
  call void @llvm.lifetime.end.p0(ptr %a)
  br label %bb2
bb2:
  ret void
}
Transformation doesn't verify!

ERROR: Source is more defined than target

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