| // 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); |
| } |