220 lines
		
	
	
		
			7.1 KiB
		
	
	
	
		
			C++
		
	
	
	
			
		
		
	
	
			220 lines
		
	
	
		
			7.1 KiB
		
	
	
	
		
			C++
		
	
	
	
// 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);
 | 
						|
}
 |