-
Notifications
You must be signed in to change notification settings - Fork 15.3k
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 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