Open
Description
In the example below, allocation a
and allocation b
have overlapping
lifetimes in all executions, so it should be impossible to observe them having
the same address. InstCombine removes the overlapping lifetimes. Which
introduces a behavior that wasn't possible before.
Before InstCombine:
define { i1, i1 } @f() {
%a = alloca ptr
%b = alloca ptr
; Overlapping lifetimes (removed by instcombine)
call void @llvm.lifetime.start.p0(i64 8, ptr %a)
call void @llvm.lifetime.start.p0(i64 8, ptr %b)
call void @llvm.lifetime.end.p0(i64 8, ptr %a)
call void @llvm.lifetime.end.p0(i64 8, ptr %b)
; Disjoint lifetimes
call void @llvm.lifetime.start.p0(i64 8, ptr %a)
call void @g(ptr %a)
call void @llvm.lifetime.end.p0(i64 8, ptr %a)
call void @llvm.lifetime.start.p0(i64 8, ptr %b)
call void @g(ptr %b)
call void @llvm.lifetime.end.p0(i64 8, ptr %b)
; Obscured equality comparison. Avoids fold that incorrectly assumes that
; "Two distinct allocations will never be equal." See #45725 for details.
%1 = icmp ule ptr %a, %b
%2 = icmp uge ptr %a, %b
%3 = insertvalue { i1, i1 } poison, i1 %1, 0
%4 = insertvalue { i1, i1 } %3, i1 %2, 1
ret { i1, i1 } %4
}
declare void @g(ptr)
After InstCombine
define { i1, i1 } @f() {
%a = alloca ptr, align 8
%b = alloca ptr, align 8
call void @llvm.lifetime.start.p0(i64 8, ptr nonnull %a)
call void @g(ptr nonnull %a)
call void @llvm.lifetime.end.p0(i64 8, ptr nonnull %a)
call void @llvm.lifetime.start.p0(i64 8, ptr nonnull %b)
call void @g(ptr nonnull %b)
call void @llvm.lifetime.end.p0(i64 8, ptr nonnull %b)
%1 = icmp ule ptr %a, %b
%2 = icmp uge ptr %a, %b
%3 = insertvalue { i1, i1 } poison, i1 %1, 0
%4 = insertvalue { i1, i1 } %3, i1 %2, 1
ret { i1, i1 } %4
}