blob: 83983722db945eb33f872c039fdd3c9ba35d7aad [file] [log] [blame]
George Burgess IV4deb75d2018-03-10 23:06:31 +00001// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -O1 -S -emit-llvm -o - %s | FileCheck %s --check-prefix=O1
2// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -O0 -S -emit-llvm -o - %s | FileCheck %s --check-prefix=O0
3//
4// Ensure that we place appropriate lifetime markers around indirectly returned
5// temporaries, and that the lifetime.ends appear in a timely manner.
6//
7// -O1 is used so lifetime markers actually get emitted.
8
9struct S {
10 int ns[40];
11};
12
13struct S foo(void);
14
15// CHECK-LABEL: define dso_local void @bar
16struct S bar() {
17 // O0-NOT: @llvm.lifetime.start
18 // O0-NOT: @llvm.lifetime.end
19
20 struct S r;
George Burgess IV4deb75d2018-03-10 23:06:31 +000021 // O1: call void @llvm.lifetime.start.p0i8({{[^,]*}}, i8* nonnull %[[TMP1:[^)]+]])
22 // O1: call void @foo
23 r = foo();
24 // O1: call void @llvm.lifetime.end.p0i8({{[^,]*}}, i8* nonnull %[[TMP1]])
25
26 // O1: call void @llvm.lifetime.start.p0i8({{[^,]*}}, i8* nonnull %[[TMP2:[^)]+]])
27 // O1: call void @foo
28 r = foo();
29 // O1: call void @llvm.lifetime.end.p0i8({{[^,]*}}, i8* nonnull %[[TMP2]])
30
31 // O1: call void @llvm.lifetime.start.p0i8({{[^,]*}}, i8* nonnull %[[TMP3:[^)]+]])
32 // O1: call void @foo
33 r = foo();
34 // O1: call void @llvm.lifetime.end.p0i8({{[^,]*}}, i8* nonnull %[[TMP3]])
35
George Burgess IV4deb75d2018-03-10 23:06:31 +000036 return r;
37}
38
39struct S foo_int(int);
40
41// Be sure that we're placing the lifetime.end so that all paths go through it.
42// Since this function turns out to be large-ish, optnone to hopefully keep it
43// stable.
44// CHECK-LABEL: define dso_local void @baz
45__attribute__((optnone))
46struct S baz(int i, volatile int *j) {
47 // O0-NOT: @llvm.lifetime.start
48 // O0-NOT: @llvm.lifetime.end
49
50 struct S r;
George Burgess IV4deb75d2018-03-10 23:06:31 +000051 // O1: %[[TMP1_ALLOCA:[^ ]+]] = alloca %struct.S
52 // O1: %[[TMP2_ALLOCA:[^ ]+]] = alloca %struct.S
George Burgess IV4deb75d2018-03-10 23:06:31 +000053 // O1: br label %[[DO_BODY:.+]]
54
55 do {
56 // O1: [[DO_BODY]]:
57 // O1: %[[P:[^ ]+]] = bitcast %struct.S* %[[TMP1_ALLOCA]] to i8*
58 // O1: call void @llvm.lifetime.start.p0i8({{[^,]*}}, i8* %[[P]])
59 // O1: br i1 {{[^,]+}}, label %[[IF_THEN:[^,]+]], label %[[IF_END:[^,]+]]
60 //
61 // O1: [[IF_THEN]]:
62 // O1: %[[P:[^ ]+]] = bitcast %struct.S* %[[TMP1_ALLOCA]] to i8*
63 // O1: call void @llvm.lifetime.end.p0i8({{[^,]*}}, i8* %[[P]])
64 // O1: br label %[[DO_END:.*]]
65 //
66 // O1: [[IF_END]]:
67 // O1: call void @foo_int(%struct.S* sret %[[TMP1_ALLOCA]],
68 // O1: call void @llvm.memcpy
69 // O1: %[[P:[^ ]+]] = bitcast %struct.S* %[[TMP1_ALLOCA]] to i8*
70 // O1: call void @llvm.lifetime.end.p0i8({{[^,]*}}, i8* %[[P]])
71 // O1: %[[P:[^ ]+]] = bitcast %struct.S* %[[TMP2_ALLOCA]] to i8*
72 // O1: call void @llvm.lifetime.start.p0i8({{[^,]*}}, i8* %[[P]])
73 // O1: call void @foo_int(%struct.S* sret %[[TMP2_ALLOCA]],
74 // O1: call void @llvm.memcpy
75 // O1: %[[P:[^ ]+]] = bitcast %struct.S* %[[TMP2_ALLOCA]] to i8*
76 // O1: call void @llvm.lifetime.end.p0i8({{[^,]*}}, i8* %[[P]])
77 // O1: br label %[[DO_COND:.*]]
78 //
79 // O1: [[DO_COND]]:
80 // O1: br label %[[DO_BODY]]
81 r = foo_int(({
82 if (*j)
83 break;
84 i++;
85 }));
86
87 r = foo_int(i++);
88 } while (1);
89
90 // O1: [[DO_END]]:
Akira Hatanaka673af7a2018-03-29 17:56:24 +000091 // O1-NEXT: ret void
George Burgess IV4deb75d2018-03-10 23:06:31 +000092 return r;
93}