1 // Test target codegen - host bc file has to be created first. 2 // RUN: %clang_cc1 -verify -fopenmp -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=nvptx64-nvidia-cuda -emit-llvm-bc %s -o %t-ppc-host.bc 3 // RUN: %clang_cc1 -verify -fopenmp -x c++ -triple nvptx64-unknown-unknown -fopenmp-targets=nvptx64-nvidia-cuda -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -o - | FileCheck %s --check-prefix CHECK --check-prefix CHECK-64 4 // RUN: %clang_cc1 -verify -fopenmp -x c++ -triple i386-unknown-unknown -fopenmp-targets=nvptx-nvidia-cuda -emit-llvm-bc %s -o %t-x86-host.bc 5 // RUN: %clang_cc1 -verify -fopenmp -x c++ -triple nvptx-unknown-unknown -fopenmp-targets=nvptx-nvidia-cuda -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-x86-host.bc -o - | FileCheck %s --check-prefix CHECK --check-prefix CHECK-32 6 // RUN: %clang_cc1 -verify -fopenmp -fexceptions -fcxx-exceptions -x c++ -triple nvptx-unknown-unknown -fopenmp-targets=nvptx-nvidia-cuda -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-x86-host.bc -o - | FileCheck %s --check-prefix CHECK --check-prefix CHECK-32 7 // expected-no-diagnostics 8 #ifndef HEADER 9 #define HEADER 10 11 template<typename tx, typename ty> 12 struct TT{ 13 tx X; 14 ty Y; 15 }; 16 17 int foo(int n) { 18 int a = 0; 19 short aa = 0; 20 float b[10]; 21 float bn[n]; 22 double c[5][10]; 23 double cn[5][n]; 24 TT<long long, char> d; 25 26 // CHECK-LABEL: define {{.*}}void {{@__omp_offloading_.+foo.+l90}}_worker() 27 // CHECK-DAG: [[OMP_EXEC_STATUS:%.+]] = alloca i8, 28 // CHECK-DAG: [[OMP_WORK_FN:%.+]] = alloca i8*, 29 // CHECK: store i8* null, i8** [[OMP_WORK_FN]], 30 // CHECK: store i8 0, i8* [[OMP_EXEC_STATUS]], 31 // CHECK: br label {{%?}}[[AWAIT_WORK:.+]] 32 // 33 // CHECK: [[AWAIT_WORK]] 34 // CHECK: call void @llvm.nvvm.barrier0() 35 // CHECK: [[WORK:%.+]] = load i8*, i8** [[OMP_WORK_FN]], 36 // CHECK: [[SHOULD_EXIT:%.+]] = icmp eq i8* [[WORK]], null 37 // CHECK: br i1 [[SHOULD_EXIT]], label {{%?}}[[EXIT:.+]], label {{%?}}[[SEL_WORKERS:.+]] 38 // 39 // CHECK: [[SEL_WORKERS]] 40 // CHECK: [[ST:%.+]] = load i8, i8* [[OMP_EXEC_STATUS]], 41 // CHECK: [[IS_ACTIVE:%.+]] = icmp ne i8 [[ST]], 0 42 // CHECK: br i1 [[IS_ACTIVE]], label {{%?}}[[EXEC_PARALLEL:.+]], label {{%?}}[[BAR_PARALLEL:.+]] 43 // 44 // CHECK: [[EXEC_PARALLEL]] 45 // CHECK: br label {{%?}}[[TERM_PARALLEL:.+]] 46 // 47 // CHECK: [[TERM_PARALLEL]] 48 // CHECK: br label {{%?}}[[BAR_PARALLEL]] 49 // 50 // CHECK: [[BAR_PARALLEL]] 51 // CHECK: call void @llvm.nvvm.barrier0() 52 // CHECK: br label {{%?}}[[AWAIT_WORK]] 53 // 54 // CHECK: [[EXIT]] 55 // CHECK: ret void 56 57 // CHECK: define {{.*}}void [[T1:@__omp_offloading_.+foo.+l90]]() 58 // CHECK-DAG: [[TID:%.+]] = call i32 @llvm.nvvm.read.ptx.sreg.tid.x() 59 // CHECK-DAG: [[NTH:%.+]] = call i32 @llvm.nvvm.read.ptx.sreg.ntid.x() 60 // CHECK-DAG: [[WS:%.+]] = call i32 @llvm.nvvm.read.ptx.sreg.warpsize() 61 // CHECK-DAG: [[TH_LIMIT:%.+]] = sub i32 [[NTH]], [[WS]] 62 // CHECK: [[IS_WORKER:%.+]] = icmp ult i32 [[TID]], [[TH_LIMIT]] 63 // CHECK: br i1 [[IS_WORKER]], label {{%?}}[[WORKER:.+]], label {{%?}}[[CHECK_MASTER:.+]] 64 // 65 // CHECK: [[WORKER]] 66 // CHECK: {{call|invoke}} void [[T1]]_worker() 67 // CHECK: br label {{%?}}[[EXIT:.+]] 68 // 69 // CHECK: [[CHECK_MASTER]] 70 // CHECK-DAG: [[CMTID:%.+]] = call i32 @llvm.nvvm.read.ptx.sreg.tid.x() 71 // CHECK-DAG: [[CMNTH:%.+]] = call i32 @llvm.nvvm.read.ptx.sreg.ntid.x() 72 // CHECK-DAG: [[CMWS:%.+]] = call i32 @llvm.nvvm.read.ptx.sreg.warpsize() 73 // CHECK: [[IS_MASTER:%.+]] = icmp eq i32 [[CMTID]], 74 // CHECK: br i1 [[IS_MASTER]], label {{%?}}[[MASTER:.+]], label {{%?}}[[EXIT]] 75 // 76 // CHECK: [[MASTER]] 77 // CHECK-DAG: [[MNTH:%.+]] = call i32 @llvm.nvvm.read.ptx.sreg.ntid.x() 78 // CHECK-DAG: [[MWS:%.+]] = call i32 @llvm.nvvm.read.ptx.sreg.warpsize() 79 // CHECK: [[MTMP1:%.+]] = sub i32 [[MNTH]], [[MWS]] 80 // CHECK: call void @__kmpc_kernel_init(i32 [[MTMP1]] 81 // CHECK: br label {{%?}}[[TERMINATE:.+]] 82 // 83 // CHECK: [[TERMINATE]] 84 // CHECK: call void @__kmpc_kernel_deinit() 85 // CHECK: call void @llvm.nvvm.barrier0() 86 // CHECK: br label {{%?}}[[EXIT]] 87 // 88 // CHECK: [[EXIT]] 89 // CHECK: ret void 90 #pragma omp target 91 { 92 } 93 94 // CHECK-NOT: define {{.*}}void [[T2:@__omp_offloading_.+foo.+]]_worker() 95 #pragma omp target if(0) 96 { 97 } 98 99 // CHECK-LABEL: define {{.*}}void {{@__omp_offloading_.+foo.+l167}}_worker() 100 // CHECK-DAG: [[OMP_EXEC_STATUS:%.+]] = alloca i8, 101 // CHECK-DAG: [[OMP_WORK_FN:%.+]] = alloca i8*, 102 // CHECK: store i8* null, i8** [[OMP_WORK_FN]], 103 // CHECK: store i8 0, i8* [[OMP_EXEC_STATUS]], 104 // CHECK: br label {{%?}}[[AWAIT_WORK:.+]] 105 // 106 // CHECK: [[AWAIT_WORK]] 107 // CHECK: call void @llvm.nvvm.barrier0() 108 // CHECK: [[WORK:%.+]] = load i8*, i8** [[OMP_WORK_FN]], 109 // CHECK: [[SHOULD_EXIT:%.+]] = icmp eq i8* [[WORK]], null 110 // CHECK: br i1 [[SHOULD_EXIT]], label {{%?}}[[EXIT:.+]], label {{%?}}[[SEL_WORKERS:.+]] 111 // 112 // CHECK: [[SEL_WORKERS]] 113 // CHECK: [[ST:%.+]] = load i8, i8* [[OMP_EXEC_STATUS]], 114 // CHECK: [[IS_ACTIVE:%.+]] = icmp ne i8 [[ST]], 0 115 // CHECK: br i1 [[IS_ACTIVE]], label {{%?}}[[EXEC_PARALLEL:.+]], label {{%?}}[[BAR_PARALLEL:.+]] 116 // 117 // CHECK: [[EXEC_PARALLEL]] 118 // CHECK: br label {{%?}}[[TERM_PARALLEL:.+]] 119 // 120 // CHECK: [[TERM_PARALLEL]] 121 // CHECK: br label {{%?}}[[BAR_PARALLEL]] 122 // 123 // CHECK: [[BAR_PARALLEL]] 124 // CHECK: call void @llvm.nvvm.barrier0() 125 // CHECK: br label {{%?}}[[AWAIT_WORK]] 126 // 127 // CHECK: [[EXIT]] 128 // CHECK: ret void 129 130 // CHECK: define {{.*}}void [[T2:@__omp_offloading_.+foo.+l167]](i[[SZ:32|64]] [[ARG1:%[a-zA-Z_]+]]) 131 // CHECK: [[AA_ADDR:%.+]] = alloca i[[SZ]], 132 // CHECK: store i[[SZ]] [[ARG1]], i[[SZ]]* [[AA_ADDR]], 133 // CHECK: [[AA_CADDR:%.+]] = bitcast i[[SZ]]* [[AA_ADDR]] to i16* 134 // CHECK-DAG: [[TID:%.+]] = call i32 @llvm.nvvm.read.ptx.sreg.tid.x() 135 // CHECK-DAG: [[NTH:%.+]] = call i32 @llvm.nvvm.read.ptx.sreg.ntid.x() 136 // CHECK-DAG: [[WS:%.+]] = call i32 @llvm.nvvm.read.ptx.sreg.warpsize() 137 // CHECK-DAG: [[TH_LIMIT:%.+]] = sub i32 [[NTH]], [[WS]] 138 // CHECK: [[IS_WORKER:%.+]] = icmp ult i32 [[TID]], [[TH_LIMIT]] 139 // CHECK: br i1 [[IS_WORKER]], label {{%?}}[[WORKER:.+]], label {{%?}}[[CHECK_MASTER:.+]] 140 // 141 // CHECK: [[WORKER]] 142 // CHECK: {{call|invoke}} void [[T2]]_worker() 143 // CHECK: br label {{%?}}[[EXIT:.+]] 144 // 145 // CHECK: [[CHECK_MASTER]] 146 // CHECK-DAG: [[CMTID:%.+]] = call i32 @llvm.nvvm.read.ptx.sreg.tid.x() 147 // CHECK-DAG: [[CMNTH:%.+]] = call i32 @llvm.nvvm.read.ptx.sreg.ntid.x() 148 // CHECK-DAG: [[CMWS:%.+]] = call i32 @llvm.nvvm.read.ptx.sreg.warpsize() 149 // CHECK: [[IS_MASTER:%.+]] = icmp eq i32 [[CMTID]], 150 // CHECK: br i1 [[IS_MASTER]], label {{%?}}[[MASTER:.+]], label {{%?}}[[EXIT]] 151 // 152 // CHECK: [[MASTER]] 153 // CHECK-DAG: [[MNTH:%.+]] = call i32 @llvm.nvvm.read.ptx.sreg.ntid.x() 154 // CHECK-DAG: [[MWS:%.+]] = call i32 @llvm.nvvm.read.ptx.sreg.warpsize() 155 // CHECK: [[MTMP1:%.+]] = sub i32 [[MNTH]], [[MWS]] 156 // CHECK: call void @__kmpc_kernel_init(i32 [[MTMP1]] 157 // CHECK: load i16, i16* [[AA_CADDR]], 158 // CHECK: br label {{%?}}[[TERMINATE:.+]] 159 // 160 // CHECK: [[TERMINATE]] 161 // CHECK: call void @__kmpc_kernel_deinit() 162 // CHECK: call void @llvm.nvvm.barrier0() 163 // CHECK: br label {{%?}}[[EXIT]] 164 // 165 // CHECK: [[EXIT]] 166 // CHECK: ret void 167 #pragma omp target if(1) 168 { 169 aa += 1; 170 } 171 172 // CHECK-LABEL: define {{.*}}void {{@__omp_offloading_.+foo.+l276}}_worker() 173 // CHECK-DAG: [[OMP_EXEC_STATUS:%.+]] = alloca i8, 174 // CHECK-DAG: [[OMP_WORK_FN:%.+]] = alloca i8*, 175 // CHECK: store i8* null, i8** [[OMP_WORK_FN]], 176 // CHECK: store i8 0, i8* [[OMP_EXEC_STATUS]], 177 // CHECK: br label {{%?}}[[AWAIT_WORK:.+]] 178 // 179 // CHECK: [[AWAIT_WORK]] 180 // CHECK: call void @llvm.nvvm.barrier0() 181 // CHECK: [[WORK:%.+]] = load i8*, i8** [[OMP_WORK_FN]], 182 // CHECK: [[SHOULD_EXIT:%.+]] = icmp eq i8* [[WORK]], null 183 // CHECK: br i1 [[SHOULD_EXIT]], label {{%?}}[[EXIT:.+]], label {{%?}}[[SEL_WORKERS:.+]] 184 // 185 // CHECK: [[SEL_WORKERS]] 186 // CHECK: [[ST:%.+]] = load i8, i8* [[OMP_EXEC_STATUS]], 187 // CHECK: [[IS_ACTIVE:%.+]] = icmp ne i8 [[ST]], 0 188 // CHECK: br i1 [[IS_ACTIVE]], label {{%?}}[[EXEC_PARALLEL:.+]], label {{%?}}[[BAR_PARALLEL:.+]] 189 // 190 // CHECK: [[EXEC_PARALLEL]] 191 // CHECK: br label {{%?}}[[TERM_PARALLEL:.+]] 192 // 193 // CHECK: [[TERM_PARALLEL]] 194 // CHECK: br label {{%?}}[[BAR_PARALLEL]] 195 // 196 // CHECK: [[BAR_PARALLEL]] 197 // CHECK: call void @llvm.nvvm.barrier0() 198 // CHECK: br label {{%?}}[[AWAIT_WORK]] 199 // 200 // CHECK: [[EXIT]] 201 // CHECK: ret void 202 203 // CHECK: define {{.*}}void [[T3:@__omp_offloading_.+foo.+l276]](i[[SZ]] 204 // Create local storage for each capture. 205 // CHECK: [[LOCAL_A:%.+]] = alloca i[[SZ]] 206 // CHECK: [[LOCAL_B:%.+]] = alloca [10 x float]* 207 // CHECK: [[LOCAL_VLA1:%.+]] = alloca i[[SZ]] 208 // CHECK: [[LOCAL_BN:%.+]] = alloca float* 209 // CHECK: [[LOCAL_C:%.+]] = alloca [5 x [10 x double]]* 210 // CHECK: [[LOCAL_VLA2:%.+]] = alloca i[[SZ]] 211 // CHECK: [[LOCAL_VLA3:%.+]] = alloca i[[SZ]] 212 // CHECK: [[LOCAL_CN:%.+]] = alloca double* 213 // CHECK: [[LOCAL_D:%.+]] = alloca [[TT:%.+]]* 214 // CHECK-DAG: store i[[SZ]] [[ARG_A:%.+]], i[[SZ]]* [[LOCAL_A]] 215 // CHECK-DAG: store [10 x float]* [[ARG_B:%.+]], [10 x float]** [[LOCAL_B]] 216 // CHECK-DAG: store i[[SZ]] [[ARG_VLA1:%.+]], i[[SZ]]* [[LOCAL_VLA1]] 217 // CHECK-DAG: store float* [[ARG_BN:%.+]], float** [[LOCAL_BN]] 218 // CHECK-DAG: store [5 x [10 x double]]* [[ARG_C:%.+]], [5 x [10 x double]]** [[LOCAL_C]] 219 // CHECK-DAG: store i[[SZ]] [[ARG_VLA2:%.+]], i[[SZ]]* [[LOCAL_VLA2]] 220 // CHECK-DAG: store i[[SZ]] [[ARG_VLA3:%.+]], i[[SZ]]* [[LOCAL_VLA3]] 221 // CHECK-DAG: store double* [[ARG_CN:%.+]], double** [[LOCAL_CN]] 222 // CHECK-DAG: store [[TT]]* [[ARG_D:%.+]], [[TT]]** [[LOCAL_D]] 223 // 224 // CHECK-64-DAG: [[REF_A:%.+]] = bitcast i64* [[LOCAL_A]] to i32* 225 // CHECK-DAG: [[REF_B:%.+]] = load [10 x float]*, [10 x float]** [[LOCAL_B]], 226 // CHECK-DAG: [[VAL_VLA1:%.+]] = load i[[SZ]], i[[SZ]]* [[LOCAL_VLA1]], 227 // CHECK-DAG: [[REF_BN:%.+]] = load float*, float** [[LOCAL_BN]], 228 // CHECK-DAG: [[REF_C:%.+]] = load [5 x [10 x double]]*, [5 x [10 x double]]** [[LOCAL_C]], 229 // CHECK-DAG: [[VAL_VLA2:%.+]] = load i[[SZ]], i[[SZ]]* [[LOCAL_VLA2]], 230 // CHECK-DAG: [[VAL_VLA3:%.+]] = load i[[SZ]], i[[SZ]]* [[LOCAL_VLA3]], 231 // CHECK-DAG: [[REF_CN:%.+]] = load double*, double** [[LOCAL_CN]], 232 // CHECK-DAG: [[REF_D:%.+]] = load [[TT]]*, [[TT]]** [[LOCAL_D]], 233 // 234 // CHECK-DAG: [[TID:%.+]] = call i32 @llvm.nvvm.read.ptx.sreg.tid.x() 235 // CHECK-DAG: [[NTH:%.+]] = call i32 @llvm.nvvm.read.ptx.sreg.ntid.x() 236 // CHECK-DAG: [[WS:%.+]] = call i32 @llvm.nvvm.read.ptx.sreg.warpsize() 237 // CHECK-DAG: [[TH_LIMIT:%.+]] = sub i32 [[NTH]], [[WS]] 238 // CHECK: [[IS_WORKER:%.+]] = icmp ult i32 [[TID]], [[TH_LIMIT]] 239 // CHECK: br i1 [[IS_WORKER]], label {{%?}}[[WORKER:.+]], label {{%?}}[[CHECK_MASTER:.+]] 240 // 241 // CHECK: [[WORKER]] 242 // CHECK: {{call|invoke}} void [[T3]]_worker() 243 // CHECK: br label {{%?}}[[EXIT:.+]] 244 // 245 // CHECK: [[CHECK_MASTER]] 246 // CHECK-DAG: [[CMTID:%.+]] = call i32 @llvm.nvvm.read.ptx.sreg.tid.x() 247 // CHECK-DAG: [[CMNTH:%.+]] = call i32 @llvm.nvvm.read.ptx.sreg.ntid.x() 248 // CHECK-DAG: [[CMWS:%.+]] = call i32 @llvm.nvvm.read.ptx.sreg.warpsize() 249 // CHECK: [[IS_MASTER:%.+]] = icmp eq i32 [[CMTID]], 250 // CHECK: br i1 [[IS_MASTER]], label {{%?}}[[MASTER:.+]], label {{%?}}[[EXIT]] 251 // 252 // CHECK: [[MASTER]] 253 // CHECK-DAG: [[MNTH:%.+]] = call i32 @llvm.nvvm.read.ptx.sreg.ntid.x() 254 // CHECK-DAG: [[MWS:%.+]] = call i32 @llvm.nvvm.read.ptx.sreg.warpsize() 255 // CHECK: [[MTMP1:%.+]] = sub i32 [[MNTH]], [[MWS]] 256 // CHECK: call void @__kmpc_kernel_init(i32 [[MTMP1]] 257 // 258 // Use captures. 259 // CHECK-64-DAG: load i32, i32* [[REF_A]] 260 // CHECK-32-DAG: load i32, i32* [[LOCAL_A]] 261 // CHECK-DAG: getelementptr inbounds [10 x float], [10 x float]* [[REF_B]], i[[SZ]] 0, i[[SZ]] 2 262 // CHECK-DAG: getelementptr inbounds float, float* [[REF_BN]], i[[SZ]] 3 263 // CHECK-DAG: getelementptr inbounds [5 x [10 x double]], [5 x [10 x double]]* [[REF_C]], i[[SZ]] 0, i[[SZ]] 1 264 // CHECK-DAG: getelementptr inbounds double, double* [[REF_CN]], i[[SZ]] %{{.+}} 265 // CHECK-DAG: getelementptr inbounds [[TT]], [[TT]]* [[REF_D]], i32 0, i32 0 266 // 267 // CHECK: br label {{%?}}[[TERMINATE:.+]] 268 // 269 // CHECK: [[TERMINATE]] 270 // CHECK: call void @__kmpc_kernel_deinit() 271 // CHECK: call void @llvm.nvvm.barrier0() 272 // CHECK: br label {{%?}}[[EXIT]] 273 // 274 // CHECK: [[EXIT]] 275 // CHECK: ret void 276 #pragma omp target if(n>20) 277 { 278 a += 1; 279 b[2] += 1.0; 280 bn[3] += 1.0; 281 c[1][2] += 1.0; 282 cn[1][3] += 1.0; 283 d.X += 1; 284 d.Y += 1; 285 } 286 287 return a; 288 } 289 290 template<typename tx> 291 tx ftemplate(int n) { 292 tx a = 0; 293 short aa = 0; 294 tx b[10]; 295 296 #pragma omp target if(n>40) 297 { 298 a += 1; 299 aa += 1; 300 b[2] += 1; 301 } 302 303 return a; 304 } 305 306 static 307 int fstatic(int n) { 308 int a = 0; 309 short aa = 0; 310 char aaa = 0; 311 int b[10]; 312 313 #pragma omp target if(n>50) 314 { 315 a += 1; 316 aa += 1; 317 aaa += 1; 318 b[2] += 1; 319 } 320 321 return a; 322 } 323 324 struct S1 { 325 double a; 326 327 int r1(int n){ 328 int b = n+1; 329 short int c[2][n]; 330 331 #pragma omp target if(n>60) 332 { 333 this->a = (double)b + 1.5; 334 c[1][1] = ++a; 335 } 336 337 return c[1][1] + (int)b; 338 } 339 }; 340 341 int bar(int n){ 342 int a = 0; 343 344 a += foo(n); 345 346 S1 S; 347 a += S.r1(n); 348 349 a += fstatic(n); 350 351 a += ftemplate<int>(n); 352 353 return a; 354 } 355 356 // CHECK-LABEL: define {{.*}}void {{@__omp_offloading_.+static.+313}}_worker() 357 // CHECK-DAG: [[OMP_EXEC_STATUS:%.+]] = alloca i8, 358 // CHECK-DAG: [[OMP_WORK_FN:%.+]] = alloca i8*, 359 // CHECK: store i8* null, i8** [[OMP_WORK_FN]], 360 // CHECK: store i8 0, i8* [[OMP_EXEC_STATUS]], 361 // CHECK: br label {{%?}}[[AWAIT_WORK:.+]] 362 // 363 // CHECK: [[AWAIT_WORK]] 364 // CHECK: call void @llvm.nvvm.barrier0() 365 // CHECK: [[WORK:%.+]] = load i8*, i8** [[OMP_WORK_FN]], 366 // CHECK: [[SHOULD_EXIT:%.+]] = icmp eq i8* [[WORK]], null 367 // CHECK: br i1 [[SHOULD_EXIT]], label {{%?}}[[EXIT:.+]], label {{%?}}[[SEL_WORKERS:.+]] 368 // 369 // CHECK: [[SEL_WORKERS]] 370 // CHECK: [[ST:%.+]] = load i8, i8* [[OMP_EXEC_STATUS]], 371 // CHECK: [[IS_ACTIVE:%.+]] = icmp ne i8 [[ST]], 0 372 // CHECK: br i1 [[IS_ACTIVE]], label {{%?}}[[EXEC_PARALLEL:.+]], label {{%?}}[[BAR_PARALLEL:.+]] 373 // 374 // CHECK: [[EXEC_PARALLEL]] 375 // CHECK: br label {{%?}}[[TERM_PARALLEL:.+]] 376 // 377 // CHECK: [[TERM_PARALLEL]] 378 // CHECK: br label {{%?}}[[BAR_PARALLEL]] 379 // 380 // CHECK: [[BAR_PARALLEL]] 381 // CHECK: call void @llvm.nvvm.barrier0() 382 // CHECK: br label {{%?}}[[AWAIT_WORK]] 383 // 384 // CHECK: [[EXIT]] 385 // CHECK: ret void 386 387 // CHECK: define {{.*}}void [[T4:@__omp_offloading_.+static.+l313]](i[[SZ]] 388 // Create local storage for each capture. 389 // CHECK: [[LOCAL_A:%.+]] = alloca i[[SZ]] 390 // CHECK: [[LOCAL_AA:%.+]] = alloca i[[SZ]] 391 // CHECK: [[LOCAL_AAA:%.+]] = alloca i[[SZ]] 392 // CHECK: [[LOCAL_B:%.+]] = alloca [10 x i32]* 393 // CHECK-DAG: store i[[SZ]] [[ARG_A:%.+]], i[[SZ]]* [[LOCAL_A]] 394 // CHECK-DAG: store i[[SZ]] [[ARG_AA:%.+]], i[[SZ]]* [[LOCAL_AA]] 395 // CHECK-DAG: store i[[SZ]] [[ARG_AAA:%.+]], i[[SZ]]* [[LOCAL_AAA]] 396 // CHECK-DAG: store [10 x i32]* [[ARG_B:%.+]], [10 x i32]** [[LOCAL_B]] 397 // Store captures in the context. 398 // CHECK-64-DAG: [[REF_A:%.+]] = bitcast i[[SZ]]* [[LOCAL_A]] to i32* 399 // CHECK-DAG: [[REF_AA:%.+]] = bitcast i[[SZ]]* [[LOCAL_AA]] to i16* 400 // CHECK-DAG: [[REF_AAA:%.+]] = bitcast i[[SZ]]* [[LOCAL_AAA]] to i8* 401 // CHECK-DAG: [[REF_B:%.+]] = load [10 x i32]*, [10 x i32]** [[LOCAL_B]], 402 // 403 // CHECK-DAG: [[TID:%.+]] = call i32 @llvm.nvvm.read.ptx.sreg.tid.x() 404 // CHECK-DAG: [[NTH:%.+]] = call i32 @llvm.nvvm.read.ptx.sreg.ntid.x() 405 // CHECK-DAG: [[WS:%.+]] = call i32 @llvm.nvvm.read.ptx.sreg.warpsize() 406 // CHECK-DAG: [[TH_LIMIT:%.+]] = sub i32 [[NTH]], [[WS]] 407 // CHECK: [[IS_WORKER:%.+]] = icmp ult i32 [[TID]], [[TH_LIMIT]] 408 // CHECK: br i1 [[IS_WORKER]], label {{%?}}[[WORKER:.+]], label {{%?}}[[CHECK_MASTER:.+]] 409 // 410 // CHECK: [[WORKER]] 411 // CHECK: {{call|invoke}} void [[T4]]_worker() 412 // CHECK: br label {{%?}}[[EXIT:.+]] 413 // 414 // CHECK: [[CHECK_MASTER]] 415 // CHECK-DAG: [[CMTID:%.+]] = call i32 @llvm.nvvm.read.ptx.sreg.tid.x() 416 // CHECK-DAG: [[CMNTH:%.+]] = call i32 @llvm.nvvm.read.ptx.sreg.ntid.x() 417 // CHECK-DAG: [[CMWS:%.+]] = call i32 @llvm.nvvm.read.ptx.sreg.warpsize() 418 // CHECK: [[IS_MASTER:%.+]] = icmp eq i32 [[CMTID]], 419 // CHECK: br i1 [[IS_MASTER]], label {{%?}}[[MASTER:.+]], label {{%?}}[[EXIT]] 420 // 421 // CHECK: [[MASTER]] 422 // CHECK-DAG: [[MNTH:%.+]] = call i32 @llvm.nvvm.read.ptx.sreg.ntid.x() 423 // CHECK-DAG: [[MWS:%.+]] = call i32 @llvm.nvvm.read.ptx.sreg.warpsize() 424 // CHECK: [[MTMP1:%.+]] = sub i32 [[MNTH]], [[MWS]] 425 // CHECK: call void @__kmpc_kernel_init(i32 [[MTMP1]] 426 // CHECK-64-DAG: load i32, i32* [[REF_A]] 427 // CHECK-32-DAG: load i32, i32* [[LOCAL_A]] 428 // CHECK-DAG: load i16, i16* [[REF_AA]] 429 // CHECK-DAG: getelementptr inbounds [10 x i32], [10 x i32]* [[REF_B]], i[[SZ]] 0, i[[SZ]] 2 430 // CHECK: br label {{%?}}[[TERMINATE:.+]] 431 // 432 // CHECK: [[TERMINATE]] 433 // CHECK: call void @__kmpc_kernel_deinit() 434 // CHECK: call void @llvm.nvvm.barrier0() 435 // CHECK: br label {{%?}}[[EXIT]] 436 // 437 // CHECK: [[EXIT]] 438 // CHECK: ret void 439 440 441 442 // CHECK-LABEL: define {{.*}}void {{@__omp_offloading_.+S1.+l331}}_worker() 443 // CHECK-DAG: [[OMP_EXEC_STATUS:%.+]] = alloca i8, 444 // CHECK-DAG: [[OMP_WORK_FN:%.+]] = alloca i8*, 445 // CHECK: store i8* null, i8** [[OMP_WORK_FN]], 446 // CHECK: store i8 0, i8* [[OMP_EXEC_STATUS]], 447 // CHECK: br label {{%?}}[[AWAIT_WORK:.+]] 448 // 449 // CHECK: [[AWAIT_WORK]] 450 // CHECK: call void @llvm.nvvm.barrier0() 451 // CHECK: [[WORK:%.+]] = load i8*, i8** [[OMP_WORK_FN]], 452 // CHECK: [[SHOULD_EXIT:%.+]] = icmp eq i8* [[WORK]], null 453 // CHECK: br i1 [[SHOULD_EXIT]], label {{%?}}[[EXIT:.+]], label {{%?}}[[SEL_WORKERS:.+]] 454 // 455 // CHECK: [[SEL_WORKERS]] 456 // CHECK: [[ST:%.+]] = load i8, i8* [[OMP_EXEC_STATUS]], 457 // CHECK: [[IS_ACTIVE:%.+]] = icmp ne i8 [[ST]], 0 458 // CHECK: br i1 [[IS_ACTIVE]], label {{%?}}[[EXEC_PARALLEL:.+]], label {{%?}}[[BAR_PARALLEL:.+]] 459 // 460 // CHECK: [[EXEC_PARALLEL]] 461 // CHECK: br label {{%?}}[[TERM_PARALLEL:.+]] 462 // 463 // CHECK: [[TERM_PARALLEL]] 464 // CHECK: br label {{%?}}[[BAR_PARALLEL]] 465 // 466 // CHECK: [[BAR_PARALLEL]] 467 // CHECK: call void @llvm.nvvm.barrier0() 468 // CHECK: br label {{%?}}[[AWAIT_WORK]] 469 // 470 // CHECK: [[EXIT]] 471 // CHECK: ret void 472 473 // CHECK: define {{.*}}void [[T5:@__omp_offloading_.+S1.+l331]]( 474 // Create local storage for each capture. 475 // CHECK: [[LOCAL_THIS:%.+]] = alloca [[S1:%struct.*]]* 476 // CHECK: [[LOCAL_B:%.+]] = alloca i[[SZ]] 477 // CHECK: [[LOCAL_VLA1:%.+]] = alloca i[[SZ]] 478 // CHECK: [[LOCAL_VLA2:%.+]] = alloca i[[SZ]] 479 // CHECK: [[LOCAL_C:%.+]] = alloca i16* 480 // CHECK-DAG: store [[S1]]* [[ARG_THIS:%.+]], [[S1]]** [[LOCAL_THIS]] 481 // CHECK-DAG: store i[[SZ]] [[ARG_B:%.+]], i[[SZ]]* [[LOCAL_B]] 482 // CHECK-DAG: store i[[SZ]] [[ARG_VLA1:%.+]], i[[SZ]]* [[LOCAL_VLA1]] 483 // CHECK-DAG: store i[[SZ]] [[ARG_VLA2:%.+]], i[[SZ]]* [[LOCAL_VLA2]] 484 // CHECK-DAG: store i16* [[ARG_C:%.+]], i16** [[LOCAL_C]] 485 // Store captures in the context. 486 // CHECK-DAG: [[REF_THIS:%.+]] = load [[S1]]*, [[S1]]** [[LOCAL_THIS]], 487 // CHECK-64-DAG:[[REF_B:%.+]] = bitcast i[[SZ]]* [[LOCAL_B]] to i32* 488 // CHECK-DAG: [[VAL_VLA1:%.+]] = load i[[SZ]], i[[SZ]]* [[LOCAL_VLA1]], 489 // CHECK-DAG: [[VAL_VLA2:%.+]] = load i[[SZ]], i[[SZ]]* [[LOCAL_VLA2]], 490 // CHECK-DAG: [[REF_C:%.+]] = load i16*, i16** [[LOCAL_C]], 491 // 492 // CHECK-DAG: [[TID:%.+]] = call i32 @llvm.nvvm.read.ptx.sreg.tid.x() 493 // CHECK-DAG: [[NTH:%.+]] = call i32 @llvm.nvvm.read.ptx.sreg.ntid.x() 494 // CHECK-DAG: [[WS:%.+]] = call i32 @llvm.nvvm.read.ptx.sreg.warpsize() 495 // CHECK-DAG: [[TH_LIMIT:%.+]] = sub i32 [[NTH]], [[WS]] 496 // CHECK: [[IS_WORKER:%.+]] = icmp ult i32 [[TID]], [[TH_LIMIT]] 497 // CHECK: br i1 [[IS_WORKER]], label {{%?}}[[WORKER:.+]], label {{%?}}[[CHECK_MASTER:.+]] 498 // 499 // CHECK: [[WORKER]] 500 // CHECK: {{call|invoke}} void [[T5]]_worker() 501 // CHECK: br label {{%?}}[[EXIT:.+]] 502 // 503 // CHECK: [[CHECK_MASTER]] 504 // CHECK-DAG: [[CMTID:%.+]] = call i32 @llvm.nvvm.read.ptx.sreg.tid.x() 505 // CHECK-DAG: [[CMNTH:%.+]] = call i32 @llvm.nvvm.read.ptx.sreg.ntid.x() 506 // CHECK-DAG: [[CMWS:%.+]] = call i32 @llvm.nvvm.read.ptx.sreg.warpsize() 507 // CHECK: [[IS_MASTER:%.+]] = icmp eq i32 [[CMTID]], 508 // CHECK: br i1 [[IS_MASTER]], label {{%?}}[[MASTER:.+]], label {{%?}}[[EXIT]] 509 // 510 // CHECK: [[MASTER]] 511 // CHECK-DAG: [[MNTH:%.+]] = call i32 @llvm.nvvm.read.ptx.sreg.ntid.x() 512 // CHECK-DAG: [[MWS:%.+]] = call i32 @llvm.nvvm.read.ptx.sreg.warpsize() 513 // CHECK: [[MTMP1:%.+]] = sub i32 [[MNTH]], [[MWS]] 514 // CHECK: call void @__kmpc_kernel_init(i32 [[MTMP1]] 515 // Use captures. 516 // CHECK-DAG: getelementptr inbounds [[S1]], [[S1]]* [[REF_THIS]], i32 0, i32 0 517 // CHECK-64-DAG:load i32, i32* [[REF_B]] 518 // CHECK-32-DAG:load i32, i32* [[LOCAL_B]] 519 // CHECK-DAG: getelementptr inbounds i16, i16* [[REF_C]], i[[SZ]] %{{.+}} 520 // CHECK: br label {{%?}}[[TERMINATE:.+]] 521 // 522 // CHECK: [[TERMINATE]] 523 // CHECK: call void @__kmpc_kernel_deinit() 524 // CHECK: call void @llvm.nvvm.barrier0() 525 // CHECK: br label {{%?}}[[EXIT]] 526 // 527 // CHECK: [[EXIT]] 528 // CHECK: ret void 529 530 531 532 // CHECK-LABEL: define {{.*}}void {{@__omp_offloading_.+template.+l296}}_worker() 533 // CHECK-DAG: [[OMP_EXEC_STATUS:%.+]] = alloca i8, 534 // CHECK-DAG: [[OMP_WORK_FN:%.+]] = alloca i8*, 535 // CHECK: store i8* null, i8** [[OMP_WORK_FN]], 536 // CHECK: store i8 0, i8* [[OMP_EXEC_STATUS]], 537 // CHECK: br label {{%?}}[[AWAIT_WORK:.+]] 538 // 539 // CHECK: [[AWAIT_WORK]] 540 // CHECK: call void @llvm.nvvm.barrier0() 541 // CHECK: [[WORK:%.+]] = load i8*, i8** [[OMP_WORK_FN]], 542 // CHECK: [[SHOULD_EXIT:%.+]] = icmp eq i8* [[WORK]], null 543 // CHECK: br i1 [[SHOULD_EXIT]], label {{%?}}[[EXIT:.+]], label {{%?}}[[SEL_WORKERS:.+]] 544 // 545 // CHECK: [[SEL_WORKERS]] 546 // CHECK: [[ST:%.+]] = load i8, i8* [[OMP_EXEC_STATUS]], 547 // CHECK: [[IS_ACTIVE:%.+]] = icmp ne i8 [[ST]], 0 548 // CHECK: br i1 [[IS_ACTIVE]], label {{%?}}[[EXEC_PARALLEL:.+]], label {{%?}}[[BAR_PARALLEL:.+]] 549 // 550 // CHECK: [[EXEC_PARALLEL]] 551 // CHECK: br label {{%?}}[[TERM_PARALLEL:.+]] 552 // 553 // CHECK: [[TERM_PARALLEL]] 554 // CHECK: br label {{%?}}[[BAR_PARALLEL]] 555 // 556 // CHECK: [[BAR_PARALLEL]] 557 // CHECK: call void @llvm.nvvm.barrier0() 558 // CHECK: br label {{%?}}[[AWAIT_WORK]] 559 // 560 // CHECK: [[EXIT]] 561 // CHECK: ret void 562 563 // CHECK: define {{.*}}void [[T6:@__omp_offloading_.+template.+l296]](i[[SZ]] 564 // Create local storage for each capture. 565 // CHECK: [[LOCAL_A:%.+]] = alloca i[[SZ]] 566 // CHECK: [[LOCAL_AA:%.+]] = alloca i[[SZ]] 567 // CHECK: [[LOCAL_B:%.+]] = alloca [10 x i32]* 568 // CHECK-DAG: store i[[SZ]] [[ARG_A:%.+]], i[[SZ]]* [[LOCAL_A]] 569 // CHECK-DAG: store i[[SZ]] [[ARG_AA:%.+]], i[[SZ]]* [[LOCAL_AA]] 570 // CHECK-DAG: store [10 x i32]* [[ARG_B:%.+]], [10 x i32]** [[LOCAL_B]] 571 // Store captures in the context. 572 // CHECK-64-DAG:[[REF_A:%.+]] = bitcast i[[SZ]]* [[LOCAL_A]] to i32* 573 // CHECK-DAG: [[REF_AA:%.+]] = bitcast i[[SZ]]* [[LOCAL_AA]] to i16* 574 // CHECK-DAG: [[REF_B:%.+]] = load [10 x i32]*, [10 x i32]** [[LOCAL_B]], 575 // 576 // CHECK-DAG: [[TID:%.+]] = call i32 @llvm.nvvm.read.ptx.sreg.tid.x() 577 // CHECK-DAG: [[NTH:%.+]] = call i32 @llvm.nvvm.read.ptx.sreg.ntid.x() 578 // CHECK-DAG: [[WS:%.+]] = call i32 @llvm.nvvm.read.ptx.sreg.warpsize() 579 // CHECK-DAG: [[TH_LIMIT:%.+]] = sub i32 [[NTH]], [[WS]] 580 // CHECK: [[IS_WORKER:%.+]] = icmp ult i32 [[TID]], [[TH_LIMIT]] 581 // CHECK: br i1 [[IS_WORKER]], label {{%?}}[[WORKER:.+]], label {{%?}}[[CHECK_MASTER:.+]] 582 // 583 // CHECK: [[WORKER]] 584 // CHECK: {{call|invoke}} void [[T6]]_worker() 585 // CHECK: br label {{%?}}[[EXIT:.+]] 586 // 587 // CHECK: [[CHECK_MASTER]] 588 // CHECK-DAG: [[CMTID:%.+]] = call i32 @llvm.nvvm.read.ptx.sreg.tid.x() 589 // CHECK-DAG: [[CMNTH:%.+]] = call i32 @llvm.nvvm.read.ptx.sreg.ntid.x() 590 // CHECK-DAG: [[CMWS:%.+]] = call i32 @llvm.nvvm.read.ptx.sreg.warpsize() 591 // CHECK: [[IS_MASTER:%.+]] = icmp eq i32 [[CMTID]], 592 // CHECK: br i1 [[IS_MASTER]], label {{%?}}[[MASTER:.+]], label {{%?}}[[EXIT]] 593 // 594 // CHECK: [[MASTER]] 595 // CHECK-DAG: [[MNTH:%.+]] = call i32 @llvm.nvvm.read.ptx.sreg.ntid.x() 596 // CHECK-DAG: [[MWS:%.+]] = call i32 @llvm.nvvm.read.ptx.sreg.warpsize() 597 // CHECK: [[MTMP1:%.+]] = sub i32 [[MNTH]], [[MWS]] 598 // CHECK: call void @__kmpc_kernel_init(i32 [[MTMP1]] 599 // 600 // CHECK-64-DAG: load i32, i32* [[REF_A]] 601 // CHECK-32-DAG: load i32, i32* [[LOCAL_A]] 602 // CHECK-DAG: load i16, i16* [[REF_AA]] 603 // CHECK-DAG: getelementptr inbounds [10 x i32], [10 x i32]* [[REF_B]], i[[SZ]] 0, i[[SZ]] 2 604 // 605 // CHECK: br label {{%?}}[[TERMINATE:.+]] 606 // 607 // CHECK: [[TERMINATE]] 608 // CHECK: call void @__kmpc_kernel_deinit() 609 // CHECK: call void @llvm.nvvm.barrier0() 610 // CHECK: br label {{%?}}[[EXIT]] 611 // 612 // CHECK: [[EXIT]] 613 // CHECK: ret void 614 #endif 615