|  | // REQUIRES: amdgpu-registered-target | 
|  | // RUN: %clang_cc1 -emit-llvm %s -o - -triple=x86_64-apple-darwin9 -O2 -fno-experimental-new-pass-manager -disable-llvm-passes | FileCheck %s --check-prefixes=CHECK,CHECK-NOOPT | 
|  | // RUN: %clang_cc1 -emit-llvm %s -o - -triple=x86_64-apple-darwin9 -O2 -fno-experimental-new-pass-manager | FileCheck %s --check-prefixes=CHECK,CHECK-OPT,CHECK-LEGACY-OPT | 
|  | // RUN: %clang_cc1 -emit-llvm %s -o - -triple=amdgcn-amd-amdhsa -O2 -fno-experimental-new-pass-manager | FileCheck %s --check-prefixes=CHECK,CHECK-OPT,CHECK-LEGACY-OPT | 
|  | // RUN: %clang_cc1 -emit-llvm %s -o - -triple=x86_64-apple-darwin9 -O2 -fexperimental-new-pass-manager -disable-llvm-passes | FileCheck %s --check-prefixes=CHECK,CHECK-NOOPT | 
|  | // RUN: %clang_cc1 -emit-llvm %s -o - -triple=x86_64-apple-darwin9 -O2 -fexperimental-new-pass-manager | FileCheck %s --check-prefixes=CHECK,CHECK-OPT,X64-NEWPM-OPT | 
|  | // RUN: %clang_cc1 -emit-llvm %s -o - -triple=amdgcn-amd-amdhsa -O2 -fexperimental-new-pass-manager | FileCheck %s --check-prefixes=CHECK,CHECK-OPT,CHECK-OPT-NEWPM,AMDGCN-NEWPM-OPT | 
|  |  | 
|  | namespace { | 
|  |  | 
|  | static int ctorcalls; | 
|  | static int dtorcalls; | 
|  |  | 
|  | struct A { | 
|  | A() : i(0) { ctorcalls++; } | 
|  | ~A() { dtorcalls++; } | 
|  | int i; | 
|  |  | 
|  | friend const A& operator<<(const A& a, int n) { | 
|  | return a; | 
|  | } | 
|  | }; | 
|  |  | 
|  | void g(int) { } | 
|  | void g(const A&) { } | 
|  |  | 
|  | void f1(bool b) { | 
|  | g(b ? A().i : 0); | 
|  | g(b || A().i); | 
|  | g(b && A().i); | 
|  | g(b ? A() << 1 : A() << 2); | 
|  | } | 
|  |  | 
|  | struct Checker { | 
|  | Checker() { | 
|  | f1(true); | 
|  | f1(false); | 
|  | } | 
|  | }; | 
|  |  | 
|  | Checker c; | 
|  |  | 
|  | } | 
|  |  | 
|  | // CHECK-OPT-LABEL: define i32 @_Z12getCtorCallsv() | 
|  | int getCtorCalls() { | 
|  | // CHECK-LEGACY-OPT: ret i32 5 | 
|  | // X64-NEWPM-OPT: ret i32 5 | 
|  | // AMDGCN-NEWPM-OPT: [[RET:%.*]] = load i32, i32* addrspacecast (i32 addrspace(1)* @_ZN12_GLOBAL__N_19ctorcallsE to i32*), align 4 | 
|  | // AMDGCN-NEWPM-OPT: ret i32 [[RET]] | 
|  | return ctorcalls; | 
|  | } | 
|  |  | 
|  | // CHECK-OPT-LABEL: define i32 @_Z12getDtorCallsv() | 
|  | int getDtorCalls() { | 
|  | // CHECK-LEGACY-OPT: ret i32 5 | 
|  | // X64-NEWPM-OPT: ret i32 5 | 
|  | // AMDGCN-NEWPM-OPT: [[RET:%.*]] = load i32, i32* addrspacecast (i32 addrspace(1)* @_ZN12_GLOBAL__N_19dtorcallsE to i32*), align 4 | 
|  | // AMDGCN-NEWPM-OPT: ret i32 [[RET]] | 
|  | return dtorcalls; | 
|  | } | 
|  |  | 
|  | // CHECK-OPT-LABEL: define zeroext i1 @_Z7successv() | 
|  | bool success() { | 
|  | // CHECK-LEGACY-OPT: ret i1 true | 
|  | // X64-NEWPM-OPT: ret i1 true | 
|  | // AMDGCN-NEWPM-OPT: [[CTORS:%.*]] = load i32, i32* addrspacecast (i32 addrspace(1)* @_ZN12_GLOBAL__N_19ctorcallsE to i32*), align 4, !tbaa !2 | 
|  | // AMDGCN-NEWPM-OPT: [[DTORS:%.*]] = load i32, i32* addrspacecast (i32 addrspace(1)* @_ZN12_GLOBAL__N_19dtorcallsE to i32*), align 4, !tbaa !2 | 
|  | // AMDGCN-NEWPM-OPT: %cmp = icmp eq i32 [[CTORS]], [[DTORS]] | 
|  | // AMDGCN-NEWPM-OPT: ret i1 %cmp | 
|  | return ctorcalls == dtorcalls; | 
|  | } | 
|  |  | 
|  | struct X { ~X(); int f(); }; | 
|  | int g(int, int, int); | 
|  | // CHECK-LABEL: @_Z16lifetime_nontriv | 
|  | int lifetime_nontriv(bool cond) { | 
|  | // CHECK-NOOPT: store i1 false, | 
|  | // CHECK-NOOPT: store i1 false, | 
|  | // CHECK-NOOPT: store i1 false, | 
|  | // CHECK-NOOPT: store i1 false, | 
|  | // CHECK-NOOPT: store i1 false, | 
|  | // CHECK-NOOPT: store i1 false, | 
|  | // CHECK-NOOPT: br i1 | 
|  | // | 
|  | // CHECK-NOOPT: call void @llvm.lifetime.start | 
|  | // CHECK-NOOPT: store i1 true, | 
|  | // CHECK-NOOPT: store i1 true, | 
|  | // CHECK-NOOPT: call i32 @_ZN1X1fEv( | 
|  | // CHECK-NOOPT: call void @llvm.lifetime.start | 
|  | // CHECK-NOOPT: store i1 true, | 
|  | // CHECK-NOOPT: store i1 true, | 
|  | // CHECK-NOOPT: call i32 @_ZN1X1fEv( | 
|  | // CHECK-NOOPT: call void @llvm.lifetime.start | 
|  | // CHECK-NOOPT: store i1 true, | 
|  | // CHECK-NOOPT: store i1 true, | 
|  | // CHECK-NOOPT: call i32 @_ZN1X1fEv( | 
|  | // CHECK-NOOPT: call i32 @_Z1giii( | 
|  | // CHECK-NOOPT: br label | 
|  | // | 
|  | // CHECK-NOOPT: call i32 @_Z1giii(i32 1, i32 2, i32 3) | 
|  | // CHECK-NOOPT: br label | 
|  | // | 
|  | // CHECK-NOOPT: load i1, | 
|  | // CHECK-NOOPT: br i1 | 
|  | // CHECK-NOOPT: call void @_ZN1XD1Ev( | 
|  | // CHECK-NOOPT: br label | 
|  | // | 
|  | // CHECK-NOOPT: load i1, | 
|  | // CHECK-NOOPT: br i1 | 
|  | // CHECK-NOOPT: call void @llvm.lifetime.end | 
|  | // CHECK-NOOPT: br label | 
|  | // | 
|  | // CHECK-NOOPT: load i1, | 
|  | // CHECK-NOOPT: br i1 | 
|  | // CHECK-NOOPT: call void @_ZN1XD1Ev( | 
|  | // CHECK-NOOPT: br label | 
|  | // | 
|  | // CHECK-NOOPT: load i1, | 
|  | // CHECK-NOOPT: br i1 | 
|  | // CHECK-NOOPT: call void @llvm.lifetime.end | 
|  | // CHECK-NOOPT: br label | 
|  | // | 
|  | // CHECK-NOOPT: load i1, | 
|  | // CHECK-NOOPT: br i1 | 
|  | // CHECK-NOOPT: call void @_ZN1XD1Ev( | 
|  | // CHECK-NOOPT: br label | 
|  | // | 
|  | // CHECK-NOOPT: load i1, | 
|  | // CHECK-NOOPT: br i1 | 
|  | // CHECK-NOOPT: call void @llvm.lifetime.end | 
|  | // CHECK-NOOPT: br label | 
|  | // | 
|  | // CHECK-NOOPT: ret | 
|  |  | 
|  | // CHECK-OPT: br i1 | 
|  | // | 
|  | // CHECK-OPT: call void @llvm.lifetime.start | 
|  | // CHECK-OPT: call i32 @_ZN1X1fEv( | 
|  | // CHECK-OPT: call void @llvm.lifetime.start | 
|  | // CHECK-OPT: call i32 @_ZN1X1fEv( | 
|  | // CHECK-OPT: call void @llvm.lifetime.start | 
|  | // CHECK-OPT: call i32 @_ZN1X1fEv( | 
|  | // CHECK-OPT: call i32 @_Z1giii( | 
|  | // CHECK-OPT: call void @_ZN1XD1Ev( | 
|  | // CHECK-OPT: call void @llvm.lifetime.end | 
|  | // CHECK-OPT: call void @_ZN1XD1Ev( | 
|  | // CHECK-OPT: call void @llvm.lifetime.end | 
|  | // CHECK-OPT: call void @_ZN1XD1Ev( | 
|  | // CHECK-OPT: call void @llvm.lifetime.end | 
|  | // CHECK-OPT: br label | 
|  | return cond ? g(X().f(), X().f(), X().f()) : g(1, 2, 3); | 
|  | } | 
|  |  | 
|  | struct Y { int f(); }; | 
|  | int g(int, int, int); | 
|  | // CHECK-LABEL: @_Z13lifetime_triv | 
|  | int lifetime_triv(bool cond) { | 
|  | // CHECK-NOOPT: call void @llvm.lifetime.start | 
|  | // CHECK-NOOPT: call void @llvm.lifetime.start | 
|  | // CHECK-NOOPT: call void @llvm.lifetime.start | 
|  | // CHECK-NOOPT: br i1 | 
|  | // | 
|  | // CHECK-NOOPT: call i32 @_ZN1Y1fEv( | 
|  | // CHECK-NOOPT: call i32 @_ZN1Y1fEv( | 
|  | // CHECK-NOOPT: call i32 @_ZN1Y1fEv( | 
|  | // CHECK-NOOPT: call i32 @_Z1giii( | 
|  | // CHECK-NOOPT: br label | 
|  | // | 
|  | // CHECK-NOOPT: call i32 @_Z1giii(i32 1, i32 2, i32 3) | 
|  | // CHECK-NOOPT: br label | 
|  | // | 
|  | // CHECK-NOOPT: call void @llvm.lifetime.end | 
|  | // CHECK-NOOPT-NOT: br | 
|  | // CHECK-NOOPT: call void @llvm.lifetime.end | 
|  | // CHECK-NOOPT-NOT: br | 
|  | // CHECK-NOOPT: call void @llvm.lifetime.end | 
|  | // | 
|  | // CHECK-NOOPT: ret | 
|  |  | 
|  | // FIXME: LLVM isn't smart enough to remove the lifetime markers from the | 
|  | // g(1, 2, 3) path here. | 
|  |  | 
|  | // CHECK-OPT: call void @llvm.lifetime.start | 
|  | // CHECK-OPT: call void @llvm.lifetime.start | 
|  | // CHECK-OPT: call void @llvm.lifetime.start | 
|  | // CHECK-OPT: br i1 | 
|  | // | 
|  | // CHECK-OPT: call i32 @_ZN1Y1fEv( | 
|  | // CHECK-OPT: call i32 @_ZN1Y1fEv( | 
|  | // CHECK-OPT: call i32 @_ZN1Y1fEv( | 
|  | // CHECK-OPT: call i32 @_Z1giii( | 
|  | // CHECK-OPT: br label | 
|  | // | 
|  | // CHECK-OPT: call void @llvm.lifetime.end | 
|  | // CHECK-OPT: call void @llvm.lifetime.end | 
|  | // CHECK-OPT: call void @llvm.lifetime.end | 
|  | return cond ? g(Y().f(), Y().f(), Y().f()) : g(1, 2, 3); | 
|  | } | 
|  |  | 
|  | struct Z { ~Z() {} int f(); }; | 
|  | int g(int, int, int); | 
|  | // CHECK-LABEL: @_Z22lifetime_nontriv_empty | 
|  | int lifetime_nontriv_empty(bool cond) { | 
|  | // CHECK-OPT: br i1 | 
|  | // | 
|  | // CHECK-OPT: call void @llvm.lifetime.start | 
|  | // CHECK-OPT: call i32 @_ZN1Z1fEv( | 
|  | // CHECK-OPT: call void @llvm.lifetime.start | 
|  | // CHECK-OPT: call i32 @_ZN1Z1fEv( | 
|  | // CHECK-OPT: call void @llvm.lifetime.start | 
|  | // CHECK-OPT: call i32 @_ZN1Z1fEv( | 
|  | // CHECK-OPT: call i32 @_Z1giii( | 
|  | // CHECK-OPT: call void @llvm.lifetime.end | 
|  | // CHECK-OPT: call void @llvm.lifetime.end | 
|  | // CHECK-OPT: call void @llvm.lifetime.end | 
|  | // CHECK-OPT: br label | 
|  | return cond ? g(Z().f(), Z().f(), Z().f()) : g(1, 2, 3); | 
|  | } |