Summary:
Current generation of lifetime intrinsics does not handle cases like:
```
{
char x;
l1:
bar(&x, 1);
}
goto l1;
```
We will get code like this:
```
%x = alloca i8, align 1
call void @llvm.lifetime.start(i64 1, i8* nonnull %x)
br label %l1
l1:
%call = call i32 @bar(i8* nonnull %x, i32 1)
call void @llvm.lifetime.end(i64 1, i8* nonnull %x)
br label %l1
```
So the second time bar was called for x which is marked as dead.
Lifetime markers here are misleading so it's better to remove them at all.
This type of bypasses are rare, e.g. code detects just 8 functions building
clang (2329 targets).
PR28267
Reviewers: eugenis
Subscribers: beanz, mgorny, cfe-commits
Differential Revision: https://reviews.llvm.org/D24693
llvm-svn: 285176
92 lines
1.6 KiB
C
92 lines
1.6 KiB
C
// RUN: %clang -S -emit-llvm -o - -O2 %s | FileCheck %s -check-prefixes=CHECK,O2
|
|
// RUN: %clang -S -emit-llvm -o - -O0 %s | FileCheck %s -check-prefixes=CHECK,O0
|
|
|
|
extern int bar(char *A, int n);
|
|
|
|
// CHECK-LABEL: @foo
|
|
// O0-NOT: @llvm.lifetime.start
|
|
int foo (int n) {
|
|
if (n) {
|
|
// O2: @llvm.lifetime.start
|
|
char A[100];
|
|
return bar(A, 1);
|
|
} else {
|
|
// O2: @llvm.lifetime.start
|
|
char A[100];
|
|
return bar(A, 2);
|
|
}
|
|
}
|
|
|
|
// CHECK-LABEL: @no_goto_bypass
|
|
void no_goto_bypass() {
|
|
// O2: @llvm.lifetime.start(i64 1
|
|
char x;
|
|
l1:
|
|
bar(&x, 1);
|
|
// O2: @llvm.lifetime.start(i64 5
|
|
// O2: @llvm.lifetime.end(i64 5
|
|
char y[5];
|
|
bar(y, 5);
|
|
goto l1;
|
|
// Infinite loop
|
|
// O2-NOT: @llvm.lifetime.end(i64 1
|
|
}
|
|
|
|
// CHECK-LABEL: @goto_bypass
|
|
void goto_bypass() {
|
|
{
|
|
// O2-NOT: @llvm.lifetime.start(i64 1
|
|
// O2-NOT: @llvm.lifetime.end(i64 1
|
|
char x;
|
|
l1:
|
|
bar(&x, 1);
|
|
}
|
|
goto l1;
|
|
}
|
|
|
|
// CHECK-LABEL: @no_switch_bypass
|
|
void no_switch_bypass(int n) {
|
|
switch (n) {
|
|
case 1: {
|
|
// O2: @llvm.lifetime.start(i64 1
|
|
// O2: @llvm.lifetime.end(i64 1
|
|
char x;
|
|
bar(&x, 1);
|
|
break;
|
|
}
|
|
case 2:
|
|
n = n;
|
|
// O2: @llvm.lifetime.start(i64 5
|
|
// O2: @llvm.lifetime.end(i64 5
|
|
char y[5];
|
|
bar(y, 5);
|
|
break;
|
|
}
|
|
}
|
|
|
|
// CHECK-LABEL: @switch_bypass
|
|
void switch_bypass(int n) {
|
|
switch (n) {
|
|
case 1:
|
|
n = n;
|
|
// O2-NOT: @llvm.lifetime.start(i64 1
|
|
// O2-NOT: @llvm.lifetime.end(i64 1
|
|
char x;
|
|
bar(&x, 1);
|
|
break;
|
|
case 2:
|
|
bar(&x, 1);
|
|
break;
|
|
}
|
|
}
|
|
|
|
// CHECK-LABEL: @indirect_jump
|
|
void indirect_jump(int n) {
|
|
char x;
|
|
// O2-NOT: @llvm.lifetime
|
|
void *T[] = {&&L};
|
|
goto *T[n];
|
|
L:
|
|
bar(&x, 1);
|
|
}
|