llvm / llvm/llvm-project

Behavior of lifetime intrinsics depends on code that is never executed

Open
#169,361 1 comment 0 reactions 0 assignees View on GitHub
llvm:optimizations
Dominant language
LLVM
Stars
40.5k
Forks
18.7k
PR merge metrics
PR metrics pending

Description

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](https://alive2.llvm.org/ce/z/xB9o52) 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.

```llvm
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
```

Contributor guide

Open the contributing guide

Research direction

The issue does not name an implementation file, entry point, or test. Begin with the LLVM IR lifetime.start/lifetime.end and llvm.assume example and reproduce it in the linked Alive2 case; a concrete completion criterion is not specified.

Written by the indexing model from the issue text.

Assessment

Domain
compilers
Issue type
Bug
Difficulty
5/5
Estimated time
Over a week
Activity status
Stale
Clarity
Needs clarification
Newbie friendliness
20/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.