1 // REQUIRES: amdgpu-registered-target 2 // 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 3 // 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 4 // 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 5 // 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 6 // 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 7 // RUN: %clang_cc1 -emit-llvm %s -o - -triple=amdgcn-amd-amdhsa -O2 -fexperimental-new-pass-manager | FileCheck %s --check-prefixes=CHECK,CHECK-OPT,AMDGCN-NEWPM-OPT 8 9 namespace { 10 11 static int ctorcalls; 12 static int dtorcalls; 13 14 struct A { 15 A() : i(0) { ctorcalls++; } 16 ~A() { dtorcalls++; } 17 int i; 18 19 friend const A& operator<<(const A& a, int n) { 20 return a; 21 } 22 }; 23 24 void g(int) { } 25 void g(const A&) { } 26 27 void f1(bool b) { 28 g(b ? A().i : 0); 29 g(b || A().i); 30 g(b && A().i); 31 g(b ? A() << 1 : A() << 2); 32 } 33 34 struct Checker { 35 Checker() { 36 f1(true); 37 f1(false); 38 } 39 }; 40 41 Checker c; 42 43 } 44 45 // CHECK-OPT-LABEL: define i32 @_Z12getCtorCallsv() 46 int getCtorCalls() { 47 // CHECK-LEGACY-OPT: ret i32 5 48 // X64-NEWPM-OPT: ret i32 5 49 // AMDGCN-NEWPM-OPT: [[RET:%.*]] = load i32, i32* addrspacecast (i32 addrspace(1)* @_ZN12_GLOBAL__N_19ctorcallsE to i32*), align 4 50 // AMDGCN-NEWPM-OPT: ret i32 [[RET]] 51 return ctorcalls; 52 } 53 54 // CHECK-OPT-LABEL: define i32 @_Z12getDtorCallsv() 55 int getDtorCalls() { 56 // CHECK-LEGACY-OPT: ret i32 5 57 // X64-NEWPM-OPT: ret i32 5 58 // AMDGCN-NEWPM-OPT: [[RET:%.*]] = load i32, i32* addrspacecast (i32 addrspace(1)* @_ZN12_GLOBAL__N_19dtorcallsE to i32*), align 4 59 // AMDGCN-NEWPM-OPT: ret i32 [[RET]] 60 return dtorcalls; 61 } 62 63 // CHECK-OPT-LABEL: define zeroext i1 @_Z7successv() 64 bool success() { 65 // CHECK-LEGACY-OPT: ret i1 true 66 // X64-NEWPM-OPT: ret i1 true 67 // AMDGCN-NEWPM-OPT: [[CTORS:%.*]] = load i32, i32* addrspacecast (i32 addrspace(1)* @_ZN12_GLOBAL__N_19ctorcallsE to i32*), align 4, !tbaa !2 68 // AMDGCN-NEWPM-OPT: [[DTORS:%.*]] = load i32, i32* addrspacecast (i32 addrspace(1)* @_ZN12_GLOBAL__N_19dtorcallsE to i32*), align 4, !tbaa !2 69 // AMDGCN-NEWPM-OPT: %cmp = icmp eq i32 [[CTORS]], [[DTORS]] 70 // AMDGCN-NEWPM-OPT: ret i1 %cmp 71 return ctorcalls == dtorcalls; 72 } 73 74 struct X { ~X(); int f(); }; 75 int g(int, int, int); 76 // CHECK-LABEL: @_Z16lifetime_nontriv 77 int lifetime_nontriv(bool cond) { 78 // CHECK-NOOPT: store i1 false, 79 // CHECK-NOOPT: store i1 false, 80 // CHECK-NOOPT: store i1 false, 81 // CHECK-NOOPT: store i1 false, 82 // CHECK-NOOPT: store i1 false, 83 // CHECK-NOOPT: store i1 false, 84 // CHECK-NOOPT: br i1 85 // 86 // CHECK-NOOPT: call void @llvm.lifetime.start 87 // CHECK-NOOPT: store i1 true, 88 // CHECK-NOOPT: store i1 true, 89 // CHECK-NOOPT: call i32 @_ZN1X1fEv( 90 // CHECK-NOOPT: call void @llvm.lifetime.start 91 // CHECK-NOOPT: store i1 true, 92 // CHECK-NOOPT: store i1 true, 93 // CHECK-NOOPT: call i32 @_ZN1X1fEv( 94 // CHECK-NOOPT: call void @llvm.lifetime.start 95 // CHECK-NOOPT: store i1 true, 96 // CHECK-NOOPT: store i1 true, 97 // CHECK-NOOPT: call i32 @_ZN1X1fEv( 98 // CHECK-NOOPT: call i32 @_Z1giii( 99 // CHECK-NOOPT: br label 100 // 101 // CHECK-NOOPT: call i32 @_Z1giii(i32 1, i32 2, i32 3) 102 // CHECK-NOOPT: br label 103 // 104 // CHECK-NOOPT: load i1, 105 // CHECK-NOOPT: br i1 106 // CHECK-NOOPT: call void @_ZN1XD1Ev( 107 // CHECK-NOOPT: br label 108 // 109 // CHECK-NOOPT: load i1, 110 // CHECK-NOOPT: br i1 111 // CHECK-NOOPT: call void @llvm.lifetime.end 112 // CHECK-NOOPT: br label 113 // 114 // CHECK-NOOPT: load i1, 115 // CHECK-NOOPT: br i1 116 // CHECK-NOOPT: call void @_ZN1XD1Ev( 117 // CHECK-NOOPT: br label 118 // 119 // CHECK-NOOPT: load i1, 120 // CHECK-NOOPT: br i1 121 // CHECK-NOOPT: call void @llvm.lifetime.end 122 // CHECK-NOOPT: br label 123 // 124 // CHECK-NOOPT: load i1, 125 // CHECK-NOOPT: br i1 126 // CHECK-NOOPT: call void @_ZN1XD1Ev( 127 // CHECK-NOOPT: br label 128 // 129 // CHECK-NOOPT: load i1, 130 // CHECK-NOOPT: br i1 131 // CHECK-NOOPT: call void @llvm.lifetime.end 132 // CHECK-NOOPT: br label 133 // 134 // CHECK-NOOPT: ret 135 136 // CHECK-OPT: br i1 137 // 138 // CHECK-OPT: call void @llvm.lifetime.start 139 // CHECK-OPT: call i32 @_ZN1X1fEv( 140 // CHECK-OPT: call void @llvm.lifetime.start 141 // CHECK-OPT: call i32 @_ZN1X1fEv( 142 // CHECK-OPT: call void @llvm.lifetime.start 143 // CHECK-OPT: call i32 @_ZN1X1fEv( 144 // CHECK-OPT: call i32 @_Z1giii( 145 // CHECK-OPT: call void @_ZN1XD1Ev( 146 // CHECK-OPT: call void @llvm.lifetime.end 147 // CHECK-OPT: call void @_ZN1XD1Ev( 148 // CHECK-OPT: call void @llvm.lifetime.end 149 // CHECK-OPT: call void @_ZN1XD1Ev( 150 // CHECK-OPT: call void @llvm.lifetime.end 151 // CHECK-OPT: br label 152 return cond ? g(X().f(), X().f(), X().f()) : g(1, 2, 3); 153 } 154 155 struct Y { int f(); }; 156 int g(int, int, int); 157 // CHECK-LABEL: @_Z13lifetime_triv 158 int lifetime_triv(bool cond) { 159 // CHECK-NOOPT: call void @llvm.lifetime.start 160 // CHECK-NOOPT: call void @llvm.lifetime.start 161 // CHECK-NOOPT: call void @llvm.lifetime.start 162 // CHECK-NOOPT: br i1 163 // 164 // CHECK-NOOPT: call i32 @_ZN1Y1fEv( 165 // CHECK-NOOPT: call i32 @_ZN1Y1fEv( 166 // CHECK-NOOPT: call i32 @_ZN1Y1fEv( 167 // CHECK-NOOPT: call i32 @_Z1giii( 168 // CHECK-NOOPT: br label 169 // 170 // CHECK-NOOPT: call i32 @_Z1giii(i32 1, i32 2, i32 3) 171 // CHECK-NOOPT: br label 172 // 173 // CHECK-NOOPT: call void @llvm.lifetime.end 174 // CHECK-NOOPT-NOT: br 175 // CHECK-NOOPT: call void @llvm.lifetime.end 176 // CHECK-NOOPT-NOT: br 177 // CHECK-NOOPT: call void @llvm.lifetime.end 178 // 179 // CHECK-NOOPT: ret 180 181 // FIXME: LLVM isn't smart enough to remove the lifetime markers from the 182 // g(1, 2, 3) path here. 183 184 // CHECK-OPT: call void @llvm.lifetime.start 185 // CHECK-OPT: call void @llvm.lifetime.start 186 // CHECK-OPT: call void @llvm.lifetime.start 187 // CHECK-OPT: br i1 188 // 189 // CHECK-OPT: call i32 @_ZN1Y1fEv( 190 // CHECK-OPT: call i32 @_ZN1Y1fEv( 191 // CHECK-OPT: call i32 @_ZN1Y1fEv( 192 // CHECK-OPT: call i32 @_Z1giii( 193 // CHECK-OPT: br label 194 // 195 // CHECK-OPT: call void @llvm.lifetime.end 196 // CHECK-OPT: call void @llvm.lifetime.end 197 // CHECK-OPT: call void @llvm.lifetime.end 198 return cond ? g(Y().f(), Y().f(), Y().f()) : g(1, 2, 3); 199 } 200 201 struct Z { ~Z() {} int f(); }; 202 int g(int, int, int); 203 // CHECK-LABEL: @_Z22lifetime_nontriv_empty 204 int lifetime_nontriv_empty(bool cond) { 205 // CHECK-OPT: br i1 206 // 207 // CHECK-OPT: call void @llvm.lifetime.start 208 // CHECK-OPT: call i32 @_ZN1Z1fEv( 209 // CHECK-OPT: call void @llvm.lifetime.start 210 // CHECK-OPT: call i32 @_ZN1Z1fEv( 211 // CHECK-OPT: call void @llvm.lifetime.start 212 // CHECK-OPT: call i32 @_ZN1Z1fEv( 213 // CHECK-OPT: call i32 @_Z1giii( 214 // CHECK-OPT: call void @llvm.lifetime.end 215 // CHECK-OPT: call void @llvm.lifetime.end 216 // CHECK-OPT: call void @llvm.lifetime.end 217 // CHECK-OPT: br label 218 return cond ? g(Z().f(), Z().f(), Z().f()) : g(1, 2, 3); 219 } 220