Clang Project

clang_source_code/test/CodeGen/aggregate-assign-call.c
1// 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;
21  // 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
36  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;
51  // O1: %[[TMP1_ALLOCA:[^ ]+]] = alloca %struct.S
52  // O1: %[[TMP2_ALLOCA:[^ ]+]] = alloca %struct.S
53  // 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]]:
91  // O1-NEXT: ret void
92  return r;
93}
94