2018-06-16 20:28:51 +08:00
|
|
|
// REQUIRES: amdgpu-registered-target
|
2019-06-22 00:03:06 +08:00
|
|
|
// 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
|
2009-11-21 01:27:56 +08:00
|
|
|
|
2010-02-05 01:06:52 +08:00
|
|
|
namespace {
|
|
|
|
|
2010-02-05 01:23:15 +08:00
|
|
|
static int ctorcalls;
|
|
|
|
static int dtorcalls;
|
2010-02-05 01:06:52 +08:00
|
|
|
|
|
|
|
struct A {
|
2010-02-05 01:23:15 +08:00
|
|
|
A() : i(0) { ctorcalls++; }
|
|
|
|
~A() { dtorcalls++; }
|
2009-11-21 01:27:56 +08:00
|
|
|
int i;
|
2010-02-05 01:26:01 +08:00
|
|
|
|
|
|
|
friend const A& operator<<(const A& a, int n) {
|
|
|
|
return a;
|
|
|
|
}
|
2009-11-21 01:27:56 +08:00
|
|
|
};
|
|
|
|
|
2010-02-05 01:06:52 +08:00
|
|
|
void g(int) { }
|
2010-02-05 01:26:01 +08:00
|
|
|
void g(const A&) { }
|
2009-11-21 01:27:56 +08:00
|
|
|
|
2010-02-05 01:06:52 +08:00
|
|
|
void f1(bool b) {
|
|
|
|
g(b ? A().i : 0);
|
|
|
|
g(b || A().i);
|
|
|
|
g(b && A().i);
|
2010-02-05 01:26:01 +08:00
|
|
|
g(b ? A() << 1 : A() << 2);
|
2010-02-05 01:06:52 +08:00
|
|
|
}
|
2009-11-21 01:27:56 +08:00
|
|
|
|
2010-02-05 01:06:52 +08:00
|
|
|
struct Checker {
|
|
|
|
Checker() {
|
|
|
|
f1(true);
|
|
|
|
f1(false);
|
|
|
|
}
|
|
|
|
};
|
2009-11-21 01:27:56 +08:00
|
|
|
|
2010-02-05 01:06:52 +08:00
|
|
|
Checker c;
|
|
|
|
|
|
|
|
}
|
2009-11-21 01:27:56 +08:00
|
|
|
|
2020-02-04 02:09:39 +08:00
|
|
|
// CHECK-OPT-LABEL: define i32 @_Z12getCtorCallsv()
|
2010-02-05 01:23:15 +08:00
|
|
|
int getCtorCalls() {
|
2019-06-22 00:03:06 +08:00
|
|
|
// 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]]
|
2010-02-05 01:23:15 +08:00
|
|
|
return ctorcalls;
|
|
|
|
}
|
|
|
|
|
2018-08-04 09:25:06 +08:00
|
|
|
// CHECK-OPT-LABEL: define i32 @_Z12getDtorCallsv()
|
2010-02-05 01:23:15 +08:00
|
|
|
int getDtorCalls() {
|
2019-06-22 00:03:06 +08:00
|
|
|
// 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]]
|
2010-02-05 01:23:15 +08:00
|
|
|
return dtorcalls;
|
|
|
|
}
|
|
|
|
|
2018-08-04 09:25:06 +08:00
|
|
|
// CHECK-OPT-LABEL: define zeroext i1 @_Z7successv()
|
2010-02-05 01:23:15 +08:00
|
|
|
bool success() {
|
2019-06-22 00:03:06 +08:00
|
|
|
// 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
|
2010-02-05 01:23:15 +08:00
|
|
|
return ctorcalls == dtorcalls;
|
2009-11-21 01:27:56 +08:00
|
|
|
}
|
2018-08-04 09:25:06 +08:00
|
|
|
|
|
|
|
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);
|
|
|
|
}
|