84 lines · c
1// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -O1 -emit-llvm -o - %s | FileCheck %s --check-prefixes=O12// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -O0 -emit-llvm -o - %s | FileCheck %s --check-prefix=O03//4// Ensure that we place appropriate lifetime markers around indirectly returned5// temporaries, and that the lifetime.ends appear in a timely manner.6//7// -O1 is used so lifetime markers actually get emitted and optnone is added8// to avoid elimination of lifetime markers by optimizations.9 10struct S {11 int ns[40];12};13 14struct S foo(void);15 16// CHECK-LABEL: define dso_local void @bar17__attribute__((optnone))18struct S bar(void) {19 // O0-NOT: @llvm.lifetime.start20 // O0-NOT: @llvm.lifetime.end21 22 struct S r;23 // O1: %[[TMP1_ALLOCA:[^ ]+]] = alloca %struct.S24 // O1: %[[TMP2_ALLOCA:[^ ]+]] = alloca %struct.S25 // O1: %[[TMP3_ALLOCA:[^ ]+]] = alloca %struct.S26 27 // O1: call void @llvm.lifetime.start.p0(ptr %[[TMP1_ALLOCA]])28 // O1: call void @foo29 r = foo();30 // O1: memcpy31 // O1: call void @llvm.lifetime.end.p0(ptr %[[TMP1_ALLOCA]])32 33 // O1: call void @llvm.lifetime.start.p0(ptr %[[TMP2_ALLOCA]])34 // O1: call void @foo35 r = foo();36 // O1: memcpy37 // O1: call void @llvm.lifetime.end.p0(ptr %[[TMP2_ALLOCA]])38 39 // O1: call void @llvm.lifetime.start.p0(ptr %[[TMP3_ALLOCA]])40 // O1: call void @foo41 r = foo();42 // O1: memcpy43 // O1: call void @llvm.lifetime.end.p0(ptr %[[TMP3_ALLOCA]])44 45 return r;46}47 48struct S foo_int(int);49 50// Be sure that we're placing the lifetime.end so that all paths go through it.51// CHECK-LABEL: define dso_local void @baz52__attribute__((optnone))53struct S baz(int i, volatile int *j) {54 // O0-NOT: @llvm.lifetime.start55 // O0-NOT: @llvm.lifetime.end56 57 struct S r;58 // O1: %[[TMP1_ALLOCA:[^ ]+]] = alloca %struct.S59 // O1: %[[TMP2_ALLOCA:[^ ]+]] = alloca %struct.S60 61 do {62 // O1: call void @llvm.lifetime.start.p0(ptr %[[TMP1_ALLOCA]])63 //64 // O1: call void @llvm.lifetime.end.p0(ptr %[[TMP1_ALLOCA]])65 //66 // O1: call void @foo_int(ptr dead_on_unwind writable sret(%struct.S) align 4 %[[TMP1_ALLOCA]],67 // O1: call void @llvm.memcpy68 // O1: call void @llvm.lifetime.end.p0(ptr %[[TMP1_ALLOCA]])69 // O1: call void @llvm.lifetime.start.p0(ptr %[[TMP2_ALLOCA]])70 // O1: call void @foo_int(ptr dead_on_unwind writable sret(%struct.S) align 4 %[[TMP2_ALLOCA]],71 // O1: call void @llvm.memcpy72 // O1: call void @llvm.lifetime.end.p0(ptr %[[TMP2_ALLOCA]])73 r = foo_int(({74 if (*j)75 break;76 i++;77 }));78 79 r = foo_int(i++);80 } while (1);81 82 return r;83}84